xref: /onnv-gate/usr/src/uts/common/fs/udfs/udf_vnops.c (revision 12196:515936598736)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53898Srsb  * Common Development and Distribution License (the "License").
63898Srsb  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
2110440SRoger.Faulkner@Sun.COM 
220Sstevel@tonic-gate /*
23*12196SMilan.Cermak@Sun.COM  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/t_lock.h>
280Sstevel@tonic-gate #include <sys/param.h>
290Sstevel@tonic-gate #include <sys/time.h>
300Sstevel@tonic-gate #include <sys/systm.h>
310Sstevel@tonic-gate #include <sys/sysmacros.h>
320Sstevel@tonic-gate #include <sys/resource.h>
330Sstevel@tonic-gate #include <sys/signal.h>
340Sstevel@tonic-gate #include <sys/cred.h>
350Sstevel@tonic-gate #include <sys/user.h>
360Sstevel@tonic-gate #include <sys/buf.h>
370Sstevel@tonic-gate #include <sys/vfs.h>
383898Srsb #include <sys/vfs_opreg.h>
390Sstevel@tonic-gate #include <sys/stat.h>
400Sstevel@tonic-gate #include <sys/vnode.h>
410Sstevel@tonic-gate #include <sys/mode.h>
420Sstevel@tonic-gate #include <sys/proc.h>
430Sstevel@tonic-gate #include <sys/disp.h>
440Sstevel@tonic-gate #include <sys/file.h>
450Sstevel@tonic-gate #include <sys/fcntl.h>
460Sstevel@tonic-gate #include <sys/flock.h>
470Sstevel@tonic-gate #include <sys/kmem.h>
480Sstevel@tonic-gate #include <sys/uio.h>
490Sstevel@tonic-gate #include <sys/dnlc.h>
500Sstevel@tonic-gate #include <sys/conf.h>
510Sstevel@tonic-gate #include <sys/errno.h>
520Sstevel@tonic-gate #include <sys/mman.h>
530Sstevel@tonic-gate #include <sys/fbuf.h>
540Sstevel@tonic-gate #include <sys/pathname.h>
550Sstevel@tonic-gate #include <sys/debug.h>
560Sstevel@tonic-gate #include <sys/vmsystm.h>
570Sstevel@tonic-gate #include <sys/cmn_err.h>
580Sstevel@tonic-gate #include <sys/dirent.h>
590Sstevel@tonic-gate #include <sys/errno.h>
600Sstevel@tonic-gate #include <sys/modctl.h>
610Sstevel@tonic-gate #include <sys/statvfs.h>
620Sstevel@tonic-gate #include <sys/mount.h>
630Sstevel@tonic-gate #include <sys/sunddi.h>
640Sstevel@tonic-gate #include <sys/bootconf.h>
650Sstevel@tonic-gate #include <sys/policy.h>
660Sstevel@tonic-gate 
670Sstevel@tonic-gate #include <vm/hat.h>
680Sstevel@tonic-gate #include <vm/page.h>
690Sstevel@tonic-gate #include <vm/pvn.h>
700Sstevel@tonic-gate #include <vm/as.h>
710Sstevel@tonic-gate #include <vm/seg.h>
720Sstevel@tonic-gate #include <vm/seg_map.h>
730Sstevel@tonic-gate #include <vm/seg_kmem.h>
740Sstevel@tonic-gate #include <vm/seg_vn.h>
750Sstevel@tonic-gate #include <vm/rm.h>
760Sstevel@tonic-gate #include <vm/page.h>
770Sstevel@tonic-gate #include <sys/swap.h>
780Sstevel@tonic-gate 
790Sstevel@tonic-gate #include <fs/fs_subr.h>
800Sstevel@tonic-gate 
810Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
820Sstevel@tonic-gate #include <sys/fs/udf_inode.h>
830Sstevel@tonic-gate 
840Sstevel@tonic-gate static int32_t udf_open(struct vnode **,
855331Samw 	int32_t, struct cred *, caller_context_t *);
860Sstevel@tonic-gate static int32_t udf_close(struct vnode *,
875331Samw 	int32_t, int32_t, offset_t, struct cred *, caller_context_t *);
880Sstevel@tonic-gate static int32_t udf_read(struct vnode *,
895331Samw 	struct uio *, int32_t, struct cred *, caller_context_t *);
900Sstevel@tonic-gate static int32_t udf_write(struct vnode *,
915331Samw 	struct uio *, int32_t, struct cred *, caller_context_t *);
920Sstevel@tonic-gate static int32_t udf_ioctl(struct vnode *,
935331Samw 	int32_t, intptr_t, int32_t, struct cred *, int32_t *,
945331Samw 	caller_context_t *);
950Sstevel@tonic-gate static int32_t udf_getattr(struct vnode *,
965331Samw 	struct vattr *, int32_t, struct cred *, caller_context_t *);
970Sstevel@tonic-gate static int32_t udf_setattr(struct vnode *,
980Sstevel@tonic-gate 	struct vattr *, int32_t, struct cred *, caller_context_t *);
990Sstevel@tonic-gate static int32_t udf_access(struct vnode *,
1005331Samw 	int32_t, int32_t, struct cred *, caller_context_t *);
1010Sstevel@tonic-gate static int32_t udf_lookup(struct vnode *,
1020Sstevel@tonic-gate 	char *, struct vnode **, struct pathname *,
1035331Samw 	int32_t, struct vnode *, struct cred *,
1045331Samw 	caller_context_t *, int *, pathname_t *);
1050Sstevel@tonic-gate static int32_t udf_create(struct vnode *,
1060Sstevel@tonic-gate 	char *, struct vattr *, enum vcexcl,
1075331Samw 	int32_t, struct vnode **, struct cred *, int32_t,
1085331Samw 	caller_context_t *, vsecattr_t *);
1090Sstevel@tonic-gate static int32_t udf_remove(struct vnode *,
1105331Samw 	char *, struct cred *, caller_context_t *, int);
1110Sstevel@tonic-gate static int32_t udf_link(struct vnode *,
1125331Samw 	struct vnode *, char *, struct cred *, caller_context_t *, int);
1130Sstevel@tonic-gate static int32_t udf_rename(struct vnode *,
1145331Samw 	char *, struct vnode *, char *, struct cred *, caller_context_t *, int);
1150Sstevel@tonic-gate static int32_t udf_mkdir(struct vnode *,
1165331Samw 	char *, struct vattr *, struct vnode **, struct cred *,
1175331Samw 	caller_context_t *, int, vsecattr_t *);
1180Sstevel@tonic-gate static int32_t udf_rmdir(struct vnode *,
1195331Samw 	char *, struct vnode *, struct cred *, caller_context_t *, int);
1200Sstevel@tonic-gate static int32_t udf_readdir(struct vnode *,
1215331Samw 	struct uio *, struct cred *, int32_t *, caller_context_t *, int);
1220Sstevel@tonic-gate static int32_t udf_symlink(struct vnode *,
1235331Samw 	char *, struct vattr *, char *, struct cred *, caller_context_t *, int);
1240Sstevel@tonic-gate static int32_t udf_readlink(struct vnode *,
1255331Samw 	struct uio *, struct cred *, caller_context_t *);
1260Sstevel@tonic-gate static int32_t udf_fsync(struct vnode *,
1275331Samw 	int32_t, struct cred *, caller_context_t *);
1280Sstevel@tonic-gate static void udf_inactive(struct vnode *,
1295331Samw 	struct cred *, caller_context_t *);
1305331Samw static int32_t udf_fid(struct vnode *, struct fid *, caller_context_t *);
1310Sstevel@tonic-gate static int udf_rwlock(struct vnode *, int32_t, caller_context_t *);
1320Sstevel@tonic-gate static void udf_rwunlock(struct vnode *, int32_t, caller_context_t *);
1335331Samw static int32_t udf_seek(struct vnode *, offset_t, offset_t *,
1345331Samw 	caller_context_t *);
1350Sstevel@tonic-gate static int32_t udf_frlock(struct vnode *, int32_t,
1365331Samw 	struct flock64 *, int32_t, offset_t, struct flk_callback *, cred_t *,
1375331Samw 	caller_context_t *);
1380Sstevel@tonic-gate static int32_t udf_space(struct vnode *, int32_t,
1390Sstevel@tonic-gate 	struct flock64 *, int32_t, offset_t, cred_t *, caller_context_t *);
1400Sstevel@tonic-gate static int32_t udf_getpage(struct vnode *, offset_t,
1410Sstevel@tonic-gate 	size_t, uint32_t *, struct page **, size_t,
1425331Samw 	struct seg *, caddr_t, enum seg_rw, struct cred *, caller_context_t *);
1430Sstevel@tonic-gate static int32_t udf_putpage(struct vnode *, offset_t,
1445331Samw 	size_t, int32_t, struct cred *, caller_context_t *);
1450Sstevel@tonic-gate static int32_t udf_map(struct vnode *, offset_t, struct as *,
1465331Samw 	caddr_t *, size_t, uint8_t, uint8_t, uint32_t, struct cred *,
1475331Samw 	caller_context_t *);
1480Sstevel@tonic-gate static int32_t udf_addmap(struct vnode *, offset_t, struct as *,
1495331Samw 	caddr_t, size_t, uint8_t, uint8_t, uint32_t, struct cred *,
1505331Samw 	caller_context_t *);
1510Sstevel@tonic-gate static int32_t udf_delmap(struct vnode *, offset_t, struct as *,
1525331Samw 	caddr_t, size_t, uint32_t, uint32_t, uint32_t, struct cred *,
1535331Samw 	caller_context_t *);
1540Sstevel@tonic-gate static int32_t udf_l_pathconf(struct vnode *, int32_t,
1555331Samw 	ulong_t *, struct cred *, caller_context_t *);
1560Sstevel@tonic-gate static int32_t udf_pageio(struct vnode *, struct page *,
1575331Samw 	u_offset_t, size_t, int32_t, struct cred *, caller_context_t *);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate int32_t ud_getpage_miss(struct vnode *, u_offset_t,
1600Sstevel@tonic-gate 	size_t, struct seg *, caddr_t, page_t *pl[],
1610Sstevel@tonic-gate 	size_t, enum seg_rw, int32_t);
1620Sstevel@tonic-gate void ud_getpage_ra(struct vnode *, u_offset_t, struct seg *, caddr_t);
1630Sstevel@tonic-gate int32_t ud_putpages(struct vnode *, offset_t, size_t, int32_t, struct cred *);
1640Sstevel@tonic-gate int32_t ud_page_fill(struct ud_inode *, page_t *,
1650Sstevel@tonic-gate 	u_offset_t, uint32_t, u_offset_t *);
1660Sstevel@tonic-gate int32_t ud_iodone(struct buf *);
1670Sstevel@tonic-gate int32_t ud_rdip(struct ud_inode *, struct uio *, int32_t, cred_t *);
1680Sstevel@tonic-gate int32_t ud_wrip(struct ud_inode *, struct uio *, int32_t, cred_t *);
1690Sstevel@tonic-gate int32_t ud_multi_strat(struct ud_inode *, page_t *, struct buf *, u_offset_t);
1700Sstevel@tonic-gate int32_t ud_slave_done(struct buf *);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  * Structures to control multiple IO operations to get or put pages
1740Sstevel@tonic-gate  * that are backed by discontiguous blocks. The master struct is
1750Sstevel@tonic-gate  * a dummy that holds the original bp from pageio_setup. The
1760Sstevel@tonic-gate  * slave struct holds the working bp's to do the actual IO. Once
1770Sstevel@tonic-gate  * all the slave IOs complete. The master is processed as if a single
1780Sstevel@tonic-gate  * IO op has completed.
1790Sstevel@tonic-gate  */
1800Sstevel@tonic-gate uint32_t master_index = 0;
1810Sstevel@tonic-gate typedef struct mio_master {
1820Sstevel@tonic-gate 	kmutex_t	mm_mutex;	/* protect the fields below */
1830Sstevel@tonic-gate 	int32_t		mm_size;
1840Sstevel@tonic-gate 	buf_t		*mm_bp;		/* original bp */
1850Sstevel@tonic-gate 	int32_t		mm_resid;	/* bytes remaining to transfer */
1860Sstevel@tonic-gate 	int32_t		mm_error;	/* accumulated error from slaves */
1870Sstevel@tonic-gate 	int32_t		mm_index;	/* XXX debugging */
1880Sstevel@tonic-gate } mio_master_t;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate typedef struct mio_slave {
1910Sstevel@tonic-gate 	buf_t		ms_buf;		/* working buffer for this IO chunk */
1920Sstevel@tonic-gate 	mio_master_t	*ms_ptr;	/* pointer to master */
1930Sstevel@tonic-gate } mio_slave_t;
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate struct vnodeops *udf_vnodeops;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate const fs_operation_def_t udf_vnodeops_template[] = {
1983898Srsb 	VOPNAME_OPEN,		{ .vop_open = udf_open },
1993898Srsb 	VOPNAME_CLOSE,		{ .vop_close = udf_close },
2003898Srsb 	VOPNAME_READ,		{ .vop_read = udf_read },
2013898Srsb 	VOPNAME_WRITE,		{ .vop_write = udf_write },
2023898Srsb 	VOPNAME_IOCTL,		{ .vop_ioctl = udf_ioctl },
2033898Srsb 	VOPNAME_GETATTR,	{ .vop_getattr = udf_getattr },
2043898Srsb 	VOPNAME_SETATTR,	{ .vop_setattr = udf_setattr },
2053898Srsb 	VOPNAME_ACCESS,		{ .vop_access = udf_access },
2063898Srsb 	VOPNAME_LOOKUP,		{ .vop_lookup = udf_lookup },
2073898Srsb 	VOPNAME_CREATE,		{ .vop_create = udf_create },
2083898Srsb 	VOPNAME_REMOVE,		{ .vop_remove = udf_remove },
2093898Srsb 	VOPNAME_LINK,		{ .vop_link = udf_link },
2103898Srsb 	VOPNAME_RENAME,		{ .vop_rename = udf_rename },
2113898Srsb 	VOPNAME_MKDIR,		{ .vop_mkdir = udf_mkdir },
2123898Srsb 	VOPNAME_RMDIR,		{ .vop_rmdir = udf_rmdir },
2133898Srsb 	VOPNAME_READDIR,	{ .vop_readdir = udf_readdir },
2143898Srsb 	VOPNAME_SYMLINK,	{ .vop_symlink = udf_symlink },
2153898Srsb 	VOPNAME_READLINK,	{ .vop_readlink = udf_readlink },
2163898Srsb 	VOPNAME_FSYNC,		{ .vop_fsync = udf_fsync },
2173898Srsb 	VOPNAME_INACTIVE,	{ .vop_inactive = udf_inactive },
2183898Srsb 	VOPNAME_FID,		{ .vop_fid = udf_fid },
2193898Srsb 	VOPNAME_RWLOCK,		{ .vop_rwlock = udf_rwlock },
2203898Srsb 	VOPNAME_RWUNLOCK,	{ .vop_rwunlock = udf_rwunlock },
2213898Srsb 	VOPNAME_SEEK,		{ .vop_seek = udf_seek },
2223898Srsb 	VOPNAME_FRLOCK,		{ .vop_frlock = udf_frlock },
2233898Srsb 	VOPNAME_SPACE,		{ .vop_space = udf_space },
2243898Srsb 	VOPNAME_GETPAGE,	{ .vop_getpage = udf_getpage },
2253898Srsb 	VOPNAME_PUTPAGE,	{ .vop_putpage = udf_putpage },
2263898Srsb 	VOPNAME_MAP,		{ .vop_map = udf_map },
2273898Srsb 	VOPNAME_ADDMAP,		{ .vop_addmap = udf_addmap },
2283898Srsb 	VOPNAME_DELMAP,		{ .vop_delmap = udf_delmap },
2293898Srsb 	VOPNAME_PATHCONF,	{ .vop_pathconf = udf_l_pathconf },
2303898Srsb 	VOPNAME_PAGEIO,		{ .vop_pageio = udf_pageio },
2313898Srsb 	VOPNAME_VNEVENT,	{ .vop_vnevent = fs_vnevent_support },
2323898Srsb 	NULL,			NULL
2330Sstevel@tonic-gate };
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate /* ARGSUSED */
2360Sstevel@tonic-gate static int32_t
udf_open(struct vnode ** vpp,int32_t flag,struct cred * cr,caller_context_t * ct)2375331Samw udf_open(
2385331Samw 	struct vnode **vpp,
2395331Samw 	int32_t flag,
2405331Samw 	struct cred *cr,
2415331Samw 	caller_context_t *ct)
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate 	ud_printf("udf_open\n");
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	return (0);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate /* ARGSUSED */
2490Sstevel@tonic-gate static int32_t
udf_close(struct vnode * vp,int32_t flag,int32_t count,offset_t offset,struct cred * cr,caller_context_t * ct)2505331Samw udf_close(
2515331Samw 	struct vnode *vp,
2525331Samw 	int32_t flag,
2535331Samw 	int32_t count,
2545331Samw 	offset_t offset,
2555331Samw 	struct cred *cr,
2565331Samw 	caller_context_t *ct)
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	ud_printf("udf_close\n");
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	ITIMES(ip);
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
2650Sstevel@tonic-gate 	cleanshares(vp, ttoproc(curthread)->p_pid);
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	/*
2680Sstevel@tonic-gate 	 * Push partially filled cluster at last close.
2690Sstevel@tonic-gate 	 * ``last close'' is approximated because the dnlc
2700Sstevel@tonic-gate 	 * may have a hold on the vnode.
2710Sstevel@tonic-gate 	 */
2720Sstevel@tonic-gate 	if (vp->v_count <= 2 && vp->v_type != VBAD) {
2730Sstevel@tonic-gate 		struct ud_inode *ip = VTOI(vp);
2740Sstevel@tonic-gate 		if (ip->i_delaylen) {
2750Sstevel@tonic-gate 			(void) ud_putpages(vp, ip->i_delayoff, ip->i_delaylen,
2768059SDonghai.Qiao@Sun.COM 			    B_ASYNC | B_FREE, cr);
2770Sstevel@tonic-gate 			ip->i_delaylen = 0;
2780Sstevel@tonic-gate 		}
2790Sstevel@tonic-gate 	}
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	return (0);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2845331Samw /* ARGSUSED */
2850Sstevel@tonic-gate static int32_t
udf_read(struct vnode * vp,struct uio * uiop,int32_t ioflag,struct cred * cr,caller_context_t * ct)2865331Samw udf_read(
2875331Samw 	struct vnode *vp,
2885331Samw 	struct uio *uiop,
2895331Samw 	int32_t ioflag,
2905331Samw 	struct cred *cr,
2915331Samw 	caller_context_t *ct)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
2940Sstevel@tonic-gate 	int32_t error;
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	ud_printf("udf_read\n");
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate #ifdef	__lock_lint
2990Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_READER);
3000Sstevel@tonic-gate #endif
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	ASSERT(RW_READ_HELD(&ip->i_rwlock));
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	if (MANDLOCK(vp, ip->i_char)) {
3050Sstevel@tonic-gate 		/*
3060Sstevel@tonic-gate 		 * udf_getattr ends up being called by chklock
3070Sstevel@tonic-gate 		 */
3080Sstevel@tonic-gate 		error = chklock(vp, FREAD, uiop->uio_loffset,
3098059SDonghai.Qiao@Sun.COM 		    uiop->uio_resid, uiop->uio_fmode, ct);
3100Sstevel@tonic-gate 		if (error) {
3110Sstevel@tonic-gate 			goto end;
3120Sstevel@tonic-gate 		}
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_READER);
3160Sstevel@tonic-gate 	error = ud_rdip(ip, uiop, ioflag, cr);
3170Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate end:
3200Sstevel@tonic-gate #ifdef	__lock_lint
3210Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
3220Sstevel@tonic-gate #endif
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	return (error);
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate int32_t ud_WRITES = 1;
3290Sstevel@tonic-gate int32_t ud_HW = 96 * 1024;
3300Sstevel@tonic-gate int32_t ud_LW = 64 * 1024;
3310Sstevel@tonic-gate int32_t ud_throttles = 0;
3320Sstevel@tonic-gate 
3335331Samw /* ARGSUSED */
3340Sstevel@tonic-gate static int32_t
udf_write(struct vnode * vp,struct uio * uiop,int32_t ioflag,struct cred * cr,caller_context_t * ct)3355331Samw udf_write(
3365331Samw 	struct vnode *vp,
3375331Samw 	struct uio *uiop,
3385331Samw 	int32_t ioflag,
3395331Samw 	struct cred *cr,
3405331Samw 	caller_context_t *ct)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
3430Sstevel@tonic-gate 	int32_t error = 0;
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	ud_printf("udf_write\n");
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate #ifdef	__lock_lint
3480Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_WRITER);
3490Sstevel@tonic-gate #endif
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	ASSERT(RW_WRITE_HELD(&ip->i_rwlock));
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	if (MANDLOCK(vp, ip->i_char)) {
3540Sstevel@tonic-gate 		/*
3550Sstevel@tonic-gate 		 * ud_getattr ends up being called by chklock
3560Sstevel@tonic-gate 		 */
3570Sstevel@tonic-gate 		error = chklock(vp, FWRITE, uiop->uio_loffset,
3588059SDonghai.Qiao@Sun.COM 		    uiop->uio_resid, uiop->uio_fmode, ct);
3590Sstevel@tonic-gate 		if (error) {
3600Sstevel@tonic-gate 			goto end;
3610Sstevel@tonic-gate 		}
3620Sstevel@tonic-gate 	}
3630Sstevel@tonic-gate 	/*
3640Sstevel@tonic-gate 	 * Throttle writes.
3650Sstevel@tonic-gate 	 */
3660Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
3670Sstevel@tonic-gate 	if (ud_WRITES && (ip->i_writes > ud_HW)) {
3680Sstevel@tonic-gate 		while (ip->i_writes > ud_HW) {
3690Sstevel@tonic-gate 			ud_throttles++;
3700Sstevel@tonic-gate 			cv_wait(&ip->i_wrcv, &ip->i_tlock);
3710Sstevel@tonic-gate 		}
3720Sstevel@tonic-gate 	}
3730Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	/*
3760Sstevel@tonic-gate 	 * Write to the file
3770Sstevel@tonic-gate 	 */
3780Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_WRITER);
3790Sstevel@tonic-gate 	if ((ioflag & FAPPEND) != 0 && (ip->i_type == VREG)) {
3800Sstevel@tonic-gate 		/*
3810Sstevel@tonic-gate 		 * In append mode start at end of file.
3820Sstevel@tonic-gate 		 */
3830Sstevel@tonic-gate 		uiop->uio_loffset = ip->i_size;
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 	error = ud_wrip(ip, uiop, ioflag, cr);
3860Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate end:
3890Sstevel@tonic-gate #ifdef	__lock_lint
3900Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
3910Sstevel@tonic-gate #endif
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	return (error);
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate /* ARGSUSED */
3970Sstevel@tonic-gate static int32_t
udf_ioctl(struct vnode * vp,int32_t cmd,intptr_t arg,int32_t flag,struct cred * cr,int32_t * rvalp,caller_context_t * ct)3985331Samw udf_ioctl(
3995331Samw 	struct vnode *vp,
4005331Samw 	int32_t cmd,
4015331Samw 	intptr_t arg,
4025331Samw 	int32_t flag,
4035331Samw 	struct cred *cr,
4045331Samw 	int32_t *rvalp,
4055331Samw 	caller_context_t *ct)
4060Sstevel@tonic-gate {
4070Sstevel@tonic-gate 	return (ENOTTY);
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate /* ARGSUSED */
4110Sstevel@tonic-gate static int32_t
udf_getattr(struct vnode * vp,struct vattr * vap,int32_t flags,struct cred * cr,caller_context_t * ct)4125331Samw udf_getattr(
4135331Samw 	struct vnode *vp,
4145331Samw 	struct vattr *vap,
4155331Samw 	int32_t flags,
4165331Samw 	struct cred *cr,
4175331Samw 	caller_context_t *ct)
4180Sstevel@tonic-gate {
4190Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	ud_printf("udf_getattr\n");
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	if (vap->va_mask == AT_SIZE) {
4240Sstevel@tonic-gate 		/*
4250Sstevel@tonic-gate 		 * for performance, if only the size is requested don't bother
4260Sstevel@tonic-gate 		 * with anything else.
4270Sstevel@tonic-gate 		 */
4280Sstevel@tonic-gate 		vap->va_size = ip->i_size;
4290Sstevel@tonic-gate 		return (0);
4300Sstevel@tonic-gate 	}
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_READER);
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	vap->va_type = vp->v_type;
4350Sstevel@tonic-gate 	vap->va_mode = UD2VA_PERM(ip->i_perm) | ip->i_char;
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	vap->va_uid = ip->i_uid;
4380Sstevel@tonic-gate 	vap->va_gid = ip->i_gid;
4390Sstevel@tonic-gate 	vap->va_fsid = ip->i_dev;
4400Sstevel@tonic-gate 	vap->va_nodeid = ip->i_icb_lbano;
4410Sstevel@tonic-gate 	vap->va_nlink = ip->i_nlink;
4420Sstevel@tonic-gate 	vap->va_size = ip->i_size;
4430Sstevel@tonic-gate 	vap->va_seq = ip->i_seq;
4440Sstevel@tonic-gate 	if (vp->v_type == VCHR || vp->v_type == VBLK) {
4450Sstevel@tonic-gate 		vap->va_rdev = ip->i_rdev;
4460Sstevel@tonic-gate 	} else {
4470Sstevel@tonic-gate 		vap->va_rdev = 0;
4480Sstevel@tonic-gate 	}
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
4510Sstevel@tonic-gate 	ITIMES_NOLOCK(ip);	/* mark correct time in inode */
4520Sstevel@tonic-gate 	vap->va_atime.tv_sec = (time_t)ip->i_atime.tv_sec;
4530Sstevel@tonic-gate 	vap->va_atime.tv_nsec = ip->i_atime.tv_nsec;
4540Sstevel@tonic-gate 	vap->va_mtime.tv_sec = (time_t)ip->i_mtime.tv_sec;
4550Sstevel@tonic-gate 	vap->va_mtime.tv_nsec = ip->i_mtime.tv_nsec;
4560Sstevel@tonic-gate 	vap->va_ctime.tv_sec = (time_t)ip->i_ctime.tv_sec;
4570Sstevel@tonic-gate 	vap->va_ctime.tv_nsec = ip->i_ctime.tv_nsec;
4580Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	switch (ip->i_type) {
4610Sstevel@tonic-gate 		case VBLK:
4620Sstevel@tonic-gate 			vap->va_blksize = MAXBSIZE;
4630Sstevel@tonic-gate 			break;
4640Sstevel@tonic-gate 		case VCHR:
4650Sstevel@tonic-gate 			vap->va_blksize = MAXBSIZE;
4660Sstevel@tonic-gate 			break;
4670Sstevel@tonic-gate 		default:
4680Sstevel@tonic-gate 			vap->va_blksize = ip->i_udf->udf_lbsize;
4690Sstevel@tonic-gate 			break;
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 	vap->va_nblocks = ip->i_lbr << ip->i_udf->udf_l2d_shift;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	return (0);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate static int
ud_iaccess_vmode(void * ip,int mode,struct cred * cr)4790Sstevel@tonic-gate ud_iaccess_vmode(void *ip, int mode, struct cred *cr)
4800Sstevel@tonic-gate {
481*12196SMilan.Cermak@Sun.COM 	return (ud_iaccess(ip, UD_UPERM2DPERM(mode), cr, 0));
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate /*ARGSUSED4*/
4850Sstevel@tonic-gate static int32_t
udf_setattr(struct vnode * vp,struct vattr * vap,int32_t flags,struct cred * cr,caller_context_t * ct)4860Sstevel@tonic-gate udf_setattr(
4870Sstevel@tonic-gate 	struct vnode *vp,
4880Sstevel@tonic-gate 	struct vattr *vap,
4890Sstevel@tonic-gate 	int32_t flags,
4900Sstevel@tonic-gate 	struct cred *cr,
4910Sstevel@tonic-gate 	caller_context_t *ct)
4920Sstevel@tonic-gate {
4930Sstevel@tonic-gate 	int32_t error = 0;
4940Sstevel@tonic-gate 	uint32_t mask = vap->va_mask;
4950Sstevel@tonic-gate 	struct ud_inode *ip;
4960Sstevel@tonic-gate 	timestruc_t now;
4970Sstevel@tonic-gate 	struct vattr ovap;
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	ud_printf("udf_setattr\n");
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	ip = VTOI(vp);
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	/*
5040Sstevel@tonic-gate 	 * not updates allowed to 4096 files
5050Sstevel@tonic-gate 	 */
5060Sstevel@tonic-gate 	if (ip->i_astrat == STRAT_TYPE4096) {
5070Sstevel@tonic-gate 		return (EINVAL);
5080Sstevel@tonic-gate 	}
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	/*
5110Sstevel@tonic-gate 	 * Cannot set these attributes
5120Sstevel@tonic-gate 	 */
5130Sstevel@tonic-gate 	if (mask & AT_NOSET) {
5140Sstevel@tonic-gate 		return (EINVAL);
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_WRITER);
5180Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_WRITER);
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	ovap.va_uid = ip->i_uid;
5210Sstevel@tonic-gate 	ovap.va_mode = UD2VA_PERM(ip->i_perm) | ip->i_char;
5220Sstevel@tonic-gate 	error = secpolicy_vnode_setattr(cr, vp, vap, &ovap, flags,
5238059SDonghai.Qiao@Sun.COM 	    ud_iaccess_vmode, ip);
5240Sstevel@tonic-gate 	if (error)
5250Sstevel@tonic-gate 		goto update_inode;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	mask = vap->va_mask;
5280Sstevel@tonic-gate 	/*
5290Sstevel@tonic-gate 	 * Change file access modes.
5300Sstevel@tonic-gate 	 */
5310Sstevel@tonic-gate 	if (mask & AT_MODE) {
5320Sstevel@tonic-gate 		ip->i_perm = VA2UD_PERM(vap->va_mode);
5330Sstevel@tonic-gate 		ip->i_char = vap->va_mode & (VSUID | VSGID | VSVTX);
5340Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
5350Sstevel@tonic-gate 		ip->i_flag |= ICHG;
5360Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 	if (mask & (AT_UID|AT_GID)) {
5390Sstevel@tonic-gate 		if (mask & AT_UID) {
5400Sstevel@tonic-gate 			ip->i_uid = vap->va_uid;
5410Sstevel@tonic-gate 		}
5420Sstevel@tonic-gate 		if (mask & AT_GID) {
5430Sstevel@tonic-gate 			ip->i_gid = vap->va_gid;
5440Sstevel@tonic-gate 		}
5450Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
5460Sstevel@tonic-gate 		ip->i_flag |= ICHG;
5470Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
5480Sstevel@tonic-gate 	}
5490Sstevel@tonic-gate 	/*
5500Sstevel@tonic-gate 	 * Truncate file.  Must have write permission and not be a directory.
5510Sstevel@tonic-gate 	 */
5520Sstevel@tonic-gate 	if (mask & AT_SIZE) {
5530Sstevel@tonic-gate 		if (vp->v_type == VDIR) {
5540Sstevel@tonic-gate 			error = EISDIR;
5550Sstevel@tonic-gate 			goto update_inode;
5560Sstevel@tonic-gate 		}
557*12196SMilan.Cermak@Sun.COM 		if (error = ud_iaccess(ip, IWRITE, cr, 0)) {
5580Sstevel@tonic-gate 			goto update_inode;
5590Sstevel@tonic-gate 		}
5600Sstevel@tonic-gate 		if (vap->va_size > MAXOFFSET_T) {
5610Sstevel@tonic-gate 			error = EFBIG;
5620Sstevel@tonic-gate 			goto update_inode;
5630Sstevel@tonic-gate 		}
5640Sstevel@tonic-gate 		if (error = ud_itrunc(ip, vap->va_size, 0, cr)) {
5650Sstevel@tonic-gate 			goto update_inode;
5660Sstevel@tonic-gate 		}
5670Sstevel@tonic-gate 	}
5680Sstevel@tonic-gate 	/*
5690Sstevel@tonic-gate 	 * Change file access or modified times.
5700Sstevel@tonic-gate 	 */
5710Sstevel@tonic-gate 	if (mask & (AT_ATIME|AT_MTIME)) {
5720Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
5730Sstevel@tonic-gate 		if (mask & AT_ATIME) {
5740Sstevel@tonic-gate 			ip->i_atime.tv_sec = vap->va_atime.tv_sec;
5750Sstevel@tonic-gate 			ip->i_atime.tv_nsec = vap->va_atime.tv_nsec;
5760Sstevel@tonic-gate 			ip->i_flag &= ~IACC;
5770Sstevel@tonic-gate 		}
5780Sstevel@tonic-gate 		if (mask & AT_MTIME) {
5790Sstevel@tonic-gate 			ip->i_mtime.tv_sec = vap->va_mtime.tv_sec;
5800Sstevel@tonic-gate 			ip->i_mtime.tv_nsec = vap->va_mtime.tv_nsec;
5810Sstevel@tonic-gate 			gethrestime(&now);
5820Sstevel@tonic-gate 			ip->i_ctime.tv_sec = now.tv_sec;
5830Sstevel@tonic-gate 			ip->i_ctime.tv_nsec = now.tv_nsec;
5840Sstevel@tonic-gate 			ip->i_flag &= ~(IUPD|ICHG);
5850Sstevel@tonic-gate 			ip->i_flag |= IMODTIME;
5860Sstevel@tonic-gate 		}
5870Sstevel@tonic-gate 		ip->i_flag |= IMOD;
5880Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate update_inode:
5920Sstevel@tonic-gate 	if (curthread->t_flag & T_DONTPEND) {
5930Sstevel@tonic-gate 		ud_iupdat(ip, 1);
5940Sstevel@tonic-gate 	} else {
5950Sstevel@tonic-gate 		ITIMES_NOLOCK(ip);
5960Sstevel@tonic-gate 	}
5970Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
5980Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	return (error);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate /* ARGSUSED */
6040Sstevel@tonic-gate static int32_t
udf_access(struct vnode * vp,int32_t mode,int32_t flags,struct cred * cr,caller_context_t * ct)6055331Samw udf_access(
6065331Samw 	struct vnode *vp,
6075331Samw 	int32_t mode,
6085331Samw 	int32_t flags,
6095331Samw 	struct cred *cr,
6105331Samw 	caller_context_t *ct)
6110Sstevel@tonic-gate {
6120Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 	ud_printf("udf_access\n");
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	if (ip->i_udf == NULL) {
6170Sstevel@tonic-gate 		return (EIO);
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 
620*12196SMilan.Cermak@Sun.COM 	return (ud_iaccess(ip, UD_UPERM2DPERM(mode), cr, 1));
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate int32_t udfs_stickyhack = 1;
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate /* ARGSUSED */
6260Sstevel@tonic-gate static int32_t
udf_lookup(struct vnode * dvp,char * nm,struct vnode ** vpp,struct pathname * pnp,int32_t flags,struct vnode * rdir,struct cred * cr,caller_context_t * ct,int * direntflags,pathname_t * realpnp)6275331Samw udf_lookup(
6285331Samw 	struct vnode *dvp,
6295331Samw 	char *nm,
6305331Samw 	struct vnode **vpp,
6315331Samw 	struct pathname *pnp,
6325331Samw 	int32_t flags,
6335331Samw 	struct vnode *rdir,
6345331Samw 	struct cred *cr,
6355331Samw 	caller_context_t *ct,
6365331Samw 	int *direntflags,
6375331Samw 	pathname_t *realpnp)
6380Sstevel@tonic-gate {
6390Sstevel@tonic-gate 	int32_t error;
6400Sstevel@tonic-gate 	struct vnode *vp;
6410Sstevel@tonic-gate 	struct ud_inode *ip, *xip;
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 	ud_printf("udf_lookup\n");
6440Sstevel@tonic-gate 	/*
6450Sstevel@tonic-gate 	 * Null component name is a synonym for directory being searched.
6460Sstevel@tonic-gate 	 */
6470Sstevel@tonic-gate 	if (*nm == '\0') {
6480Sstevel@tonic-gate 		VN_HOLD(dvp);
6490Sstevel@tonic-gate 		*vpp = dvp;
6500Sstevel@tonic-gate 		error = 0;
6510Sstevel@tonic-gate 		goto out;
6520Sstevel@tonic-gate 	}
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 	/*
6550Sstevel@tonic-gate 	 * Fast path: Check the directory name lookup cache.
6560Sstevel@tonic-gate 	 */
6570Sstevel@tonic-gate 	ip = VTOI(dvp);
6580Sstevel@tonic-gate 	if (vp = dnlc_lookup(dvp, nm)) {
6590Sstevel@tonic-gate 		/*
6600Sstevel@tonic-gate 		 * Check accessibility of directory.
6610Sstevel@tonic-gate 		 */
662*12196SMilan.Cermak@Sun.COM 		if ((error = ud_iaccess(ip, IEXEC, cr, 1)) != 0) {
6630Sstevel@tonic-gate 			VN_RELE(vp);
6640Sstevel@tonic-gate 		}
6650Sstevel@tonic-gate 		xip = VTOI(vp);
6660Sstevel@tonic-gate 	} else {
6670Sstevel@tonic-gate 		error = ud_dirlook(ip, nm, &xip, cr, 1);
6680Sstevel@tonic-gate 		ITIMES(ip);
6690Sstevel@tonic-gate 	}
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	if (error == 0) {
6720Sstevel@tonic-gate 		ip = xip;
6730Sstevel@tonic-gate 		*vpp = ITOV(ip);
6740Sstevel@tonic-gate 		if ((ip->i_type != VDIR) &&
6758059SDonghai.Qiao@Sun.COM 		    (ip->i_char & ISVTX) &&
6768059SDonghai.Qiao@Sun.COM 		    ((ip->i_perm & IEXEC) == 0) &&
6778059SDonghai.Qiao@Sun.COM 		    udfs_stickyhack) {
6780Sstevel@tonic-gate 			mutex_enter(&(*vpp)->v_lock);
6790Sstevel@tonic-gate 			(*vpp)->v_flag |= VISSWAP;
6800Sstevel@tonic-gate 			mutex_exit(&(*vpp)->v_lock);
6810Sstevel@tonic-gate 		}
6820Sstevel@tonic-gate 		ITIMES(ip);
6830Sstevel@tonic-gate 		/*
6840Sstevel@tonic-gate 		 * If vnode is a device return special vnode instead.
6850Sstevel@tonic-gate 		 */
6860Sstevel@tonic-gate 		if (IS_DEVVP(*vpp)) {
6870Sstevel@tonic-gate 			struct vnode *newvp;
6880Sstevel@tonic-gate 			newvp = specvp(*vpp, (*vpp)->v_rdev,
6898059SDonghai.Qiao@Sun.COM 			    (*vpp)->v_type, cr);
6900Sstevel@tonic-gate 			VN_RELE(*vpp);
6910Sstevel@tonic-gate 			if (newvp == NULL) {
6920Sstevel@tonic-gate 				error = ENOSYS;
6930Sstevel@tonic-gate 			} else {
6940Sstevel@tonic-gate 				*vpp = newvp;
6950Sstevel@tonic-gate 			}
6960Sstevel@tonic-gate 		}
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate out:
6990Sstevel@tonic-gate 	return (error);
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate /* ARGSUSED */
7030Sstevel@tonic-gate static int32_t
udf_create(struct vnode * dvp,char * name,struct vattr * vap,enum vcexcl excl,int32_t mode,struct vnode ** vpp,struct cred * cr,int32_t flag,caller_context_t * ct,vsecattr_t * vsecp)7045331Samw udf_create(
7055331Samw 	struct vnode *dvp,
7065331Samw 	char *name,
7075331Samw 	struct vattr *vap,
7085331Samw 	enum vcexcl excl,
7095331Samw 	int32_t mode,
7105331Samw 	struct vnode **vpp,
7115331Samw 	struct cred *cr,
7125331Samw 	int32_t flag,
7135331Samw 	caller_context_t *ct,
7145331Samw 	vsecattr_t *vsecp)
7150Sstevel@tonic-gate {
7160Sstevel@tonic-gate 	int32_t error;
7170Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(dvp), *xip;
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 	ud_printf("udf_create\n");
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr) != 0)
7220Sstevel@tonic-gate 		vap->va_mode &= ~VSVTX;
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	if (*name == '\0') {
7250Sstevel@tonic-gate 		/*
7260Sstevel@tonic-gate 		 * Null component name refers to the directory itself.
7270Sstevel@tonic-gate 		 */
7280Sstevel@tonic-gate 		VN_HOLD(dvp);
7290Sstevel@tonic-gate 		ITIMES(ip);
7300Sstevel@tonic-gate 		error = EEXIST;
7310Sstevel@tonic-gate 	} else {
7320Sstevel@tonic-gate 		xip = NULL;
7330Sstevel@tonic-gate 		rw_enter(&ip->i_rwlock, RW_WRITER);
7340Sstevel@tonic-gate 		error = ud_direnter(ip, name, DE_CREATE,
7358059SDonghai.Qiao@Sun.COM 		    (struct ud_inode *)0, (struct ud_inode *)0,
7368059SDonghai.Qiao@Sun.COM 		    vap, &xip, cr, ct);
7370Sstevel@tonic-gate 		rw_exit(&ip->i_rwlock);
7380Sstevel@tonic-gate 		ITIMES(ip);
7390Sstevel@tonic-gate 		ip = xip;
7400Sstevel@tonic-gate 	}
7410Sstevel@tonic-gate #ifdef	__lock_lint
7420Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_WRITER);
7430Sstevel@tonic-gate #else
7440Sstevel@tonic-gate 	if (ip != NULL) {
7450Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_WRITER);
7460Sstevel@tonic-gate 	}
7470Sstevel@tonic-gate #endif
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 	/*
7500Sstevel@tonic-gate 	 * If the file already exists and this is a non-exclusive create,
7510Sstevel@tonic-gate 	 * check permissions and allow access for non-directories.
7520Sstevel@tonic-gate 	 * Read-only create of an existing directory is also allowed.
7530Sstevel@tonic-gate 	 * We fail an exclusive create of anything which already exists.
7540Sstevel@tonic-gate 	 */
7550Sstevel@tonic-gate 	if (error == EEXIST) {
7560Sstevel@tonic-gate 		if (excl == NONEXCL) {
7570Sstevel@tonic-gate 			if ((ip->i_type == VDIR) && (mode & VWRITE)) {
7580Sstevel@tonic-gate 				error = EISDIR;
7590Sstevel@tonic-gate 			} else if (mode) {
7600Sstevel@tonic-gate 				error = ud_iaccess(ip,
761*12196SMilan.Cermak@Sun.COM 				    UD_UPERM2DPERM(mode), cr, 0);
7620Sstevel@tonic-gate 			} else {
7630Sstevel@tonic-gate 				error = 0;
7640Sstevel@tonic-gate 			}
7650Sstevel@tonic-gate 		}
7660Sstevel@tonic-gate 		if (error) {
7670Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
7680Sstevel@tonic-gate 			VN_RELE(ITOV(ip));
7690Sstevel@tonic-gate 			goto out;
7700Sstevel@tonic-gate 		} else if ((ip->i_type == VREG) &&
7718059SDonghai.Qiao@Sun.COM 		    (vap->va_mask & AT_SIZE) && vap->va_size == 0) {
7720Sstevel@tonic-gate 			/*
7730Sstevel@tonic-gate 			 * Truncate regular files, if requested by caller.
7740Sstevel@tonic-gate 			 * Grab i_rwlock to make sure no one else is
7750Sstevel@tonic-gate 			 * currently writing to the file (we promised
7760Sstevel@tonic-gate 			 * bmap we would do this).
7770Sstevel@tonic-gate 			 * Must get the locks in the correct order.
7780Sstevel@tonic-gate 			 */
7790Sstevel@tonic-gate 			if (ip->i_size == 0) {
7800Sstevel@tonic-gate 				ip->i_flag |= ICHG | IUPD;
7810Sstevel@tonic-gate 			} else {
7820Sstevel@tonic-gate 				rw_exit(&ip->i_contents);
7830Sstevel@tonic-gate 				rw_enter(&ip->i_rwlock, RW_WRITER);
7840Sstevel@tonic-gate 				rw_enter(&ip->i_contents, RW_WRITER);
7850Sstevel@tonic-gate 				(void) ud_itrunc(ip, 0, 0, cr);
7860Sstevel@tonic-gate 				rw_exit(&ip->i_rwlock);
7870Sstevel@tonic-gate 			}
7885331Samw 			vnevent_create(ITOV(ip), ct);
7890Sstevel@tonic-gate 		}
7900Sstevel@tonic-gate 	}
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	if (error == 0) {
7930Sstevel@tonic-gate 		*vpp = ITOV(ip);
7940Sstevel@tonic-gate 		ITIMES(ip);
7950Sstevel@tonic-gate 	}
7960Sstevel@tonic-gate #ifdef	__lock_lint
7970Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
7980Sstevel@tonic-gate #else
7990Sstevel@tonic-gate 	if (ip != NULL) {
8000Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate #endif
8030Sstevel@tonic-gate 	if (error) {
8040Sstevel@tonic-gate 		goto out;
8050Sstevel@tonic-gate 	}
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	/*
8080Sstevel@tonic-gate 	 * If vnode is a device return special vnode instead.
8090Sstevel@tonic-gate 	 */
8100Sstevel@tonic-gate 	if (!error && IS_DEVVP(*vpp)) {
8110Sstevel@tonic-gate 		struct vnode *newvp;
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 		newvp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
8140Sstevel@tonic-gate 		VN_RELE(*vpp);
8150Sstevel@tonic-gate 		if (newvp == NULL) {
8160Sstevel@tonic-gate 			error = ENOSYS;
8170Sstevel@tonic-gate 			goto out;
8180Sstevel@tonic-gate 		}
8190Sstevel@tonic-gate 		*vpp = newvp;
8200Sstevel@tonic-gate 	}
8210Sstevel@tonic-gate out:
8220Sstevel@tonic-gate 	return (error);
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate 
8255331Samw /* ARGSUSED */
8260Sstevel@tonic-gate static int32_t
udf_remove(struct vnode * vp,char * nm,struct cred * cr,caller_context_t * ct,int flags)8275331Samw udf_remove(
8285331Samw 	struct vnode *vp,
8295331Samw 	char *nm,
8305331Samw 	struct cred *cr,
8315331Samw 	caller_context_t *ct,
8325331Samw 	int flags)
8330Sstevel@tonic-gate {
8340Sstevel@tonic-gate 	int32_t error;
8350Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 	ud_printf("udf_remove\n");
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_WRITER);
8400Sstevel@tonic-gate 	error = ud_dirremove(ip, nm,
8418059SDonghai.Qiao@Sun.COM 	    (struct ud_inode *)0, (struct vnode *)0, DR_REMOVE, cr, ct);
8420Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
8430Sstevel@tonic-gate 	ITIMES(ip);
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 	return (error);
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate 
8485331Samw /* ARGSUSED */
8490Sstevel@tonic-gate static int32_t
udf_link(struct vnode * tdvp,struct vnode * svp,char * tnm,struct cred * cr,caller_context_t * ct,int flags)8505331Samw udf_link(
8515331Samw 	struct vnode *tdvp,
8525331Samw 	struct vnode *svp,
8535331Samw 	char *tnm,
8545331Samw 	struct cred *cr,
8555331Samw 	caller_context_t *ct,
8565331Samw 	int flags)
8570Sstevel@tonic-gate {
8580Sstevel@tonic-gate 	int32_t error;
8590Sstevel@tonic-gate 	struct vnode *realvp;
8600Sstevel@tonic-gate 	struct ud_inode *sip;
8610Sstevel@tonic-gate 	struct ud_inode *tdp;
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 	ud_printf("udf_link\n");
8645331Samw 	if (VOP_REALVP(svp, &realvp, ct) == 0) {
8650Sstevel@tonic-gate 		svp = realvp;
8660Sstevel@tonic-gate 	}
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	/*
8690Sstevel@tonic-gate 	 * Do not allow links to directories
8700Sstevel@tonic-gate 	 */
8710Sstevel@tonic-gate 	if (svp->v_type == VDIR) {
8720Sstevel@tonic-gate 		return (EPERM);
8730Sstevel@tonic-gate 	}
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 	sip = VTOI(svp);
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	if (sip->i_uid != crgetuid(cr) && secpolicy_basic_link(cr) != 0)
8780Sstevel@tonic-gate 		return (EPERM);
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	tdp = VTOI(tdvp);
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	rw_enter(&tdp->i_rwlock, RW_WRITER);
8830Sstevel@tonic-gate 	error = ud_direnter(tdp, tnm, DE_LINK, (struct ud_inode *)0,
8848059SDonghai.Qiao@Sun.COM 	    sip, (struct vattr *)0, (struct ud_inode **)0, cr, ct);
8850Sstevel@tonic-gate 	rw_exit(&tdp->i_rwlock);
8860Sstevel@tonic-gate 	ITIMES(sip);
8870Sstevel@tonic-gate 	ITIMES(tdp);
8880Sstevel@tonic-gate 
8894863Spraks 	if (error == 0) {
8905331Samw 		vnevent_link(svp, ct);
8914863Spraks 	}
8924863Spraks 
8930Sstevel@tonic-gate 	return (error);
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate /* ARGSUSED */
8970Sstevel@tonic-gate static int32_t
udf_rename(struct vnode * sdvp,char * snm,struct vnode * tdvp,char * tnm,struct cred * cr,caller_context_t * ct,int flags)8985331Samw udf_rename(
8995331Samw 	struct vnode *sdvp,
9005331Samw 	char *snm,
9015331Samw 	struct vnode *tdvp,
9025331Samw 	char *tnm,
9035331Samw 	struct cred *cr,
9045331Samw 	caller_context_t *ct,
9055331Samw 	int flags)
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate 	int32_t error = 0;
9080Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
9090Sstevel@tonic-gate 	struct ud_inode *sip;		/* source inode */
9100Sstevel@tonic-gate 	struct ud_inode *sdp, *tdp;	/* source and target parent inode */
9110Sstevel@tonic-gate 	struct vnode *realvp;
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	ud_printf("udf_rename\n");
9140Sstevel@tonic-gate 
9155331Samw 	if (VOP_REALVP(tdvp, &realvp, ct) == 0) {
9160Sstevel@tonic-gate 		tdvp = realvp;
9170Sstevel@tonic-gate 	}
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 	sdp = VTOI(sdvp);
9200Sstevel@tonic-gate 	tdp = VTOI(tdvp);
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	udf_vfsp = sdp->i_udf;
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 	mutex_enter(&udf_vfsp->udf_rename_lck);
9250Sstevel@tonic-gate 	/*
9260Sstevel@tonic-gate 	 * Look up inode of file we're supposed to rename.
9270Sstevel@tonic-gate 	 */
9280Sstevel@tonic-gate 	if (error = ud_dirlook(sdp, snm, &sip, cr, 0)) {
9290Sstevel@tonic-gate 		mutex_exit(&udf_vfsp->udf_rename_lck);
9300Sstevel@tonic-gate 		return (error);
9310Sstevel@tonic-gate 	}
9320Sstevel@tonic-gate 	/*
9330Sstevel@tonic-gate 	 * be sure this is not a directory with another file system mounted
9340Sstevel@tonic-gate 	 * over it.  If it is just give up the locks, and return with
9350Sstevel@tonic-gate 	 * EBUSY
9360Sstevel@tonic-gate 	 */
9370Sstevel@tonic-gate 	if (vn_mountedvfs(ITOV(sip)) != NULL) {
9380Sstevel@tonic-gate 		error = EBUSY;
9390Sstevel@tonic-gate 		goto errout;
9400Sstevel@tonic-gate 	}
9410Sstevel@tonic-gate 	/*
9420Sstevel@tonic-gate 	 * Make sure we can delete the source entry.  This requires
9430Sstevel@tonic-gate 	 * write permission on the containing directory.  If that
9440Sstevel@tonic-gate 	 * directory is "sticky" it further requires (except for
9450Sstevel@tonic-gate 	 * privileged users) that the user own the directory or the
9460Sstevel@tonic-gate 	 * source entry, or else have permission to write the source
9470Sstevel@tonic-gate 	 * entry.
9480Sstevel@tonic-gate 	 */
9490Sstevel@tonic-gate 	rw_enter(&sdp->i_contents, RW_READER);
9500Sstevel@tonic-gate 	rw_enter(&sip->i_contents, RW_READER);
951*12196SMilan.Cermak@Sun.COM 	if ((error = ud_iaccess(sdp, IWRITE, cr, 0)) != 0 ||
9520Sstevel@tonic-gate 	    (error = ud_sticky_remove_access(sdp, sip, cr)) != 0) {
9530Sstevel@tonic-gate 		rw_exit(&sip->i_contents);
9540Sstevel@tonic-gate 		rw_exit(&sdp->i_contents);
9550Sstevel@tonic-gate 		ITIMES(sip);
9560Sstevel@tonic-gate 		goto errout;
9570Sstevel@tonic-gate 	}
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	/*
9600Sstevel@tonic-gate 	 * Check for renaming '.' or '..' or alias of '.'
9610Sstevel@tonic-gate 	 */
9620Sstevel@tonic-gate 	if ((strcmp(snm, ".") == 0) ||
9638059SDonghai.Qiao@Sun.COM 	    (strcmp(snm, "..") == 0) ||
9648059SDonghai.Qiao@Sun.COM 	    (sdp == sip)) {
9650Sstevel@tonic-gate 		error = EINVAL;
9660Sstevel@tonic-gate 		rw_exit(&sip->i_contents);
9670Sstevel@tonic-gate 		rw_exit(&sdp->i_contents);
9680Sstevel@tonic-gate 		goto errout;
9690Sstevel@tonic-gate 	}
9700Sstevel@tonic-gate 	rw_exit(&sip->i_contents);
9710Sstevel@tonic-gate 	rw_exit(&sdp->i_contents);
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 	/*
9750Sstevel@tonic-gate 	 * Link source to the target.
9760Sstevel@tonic-gate 	 */
9770Sstevel@tonic-gate 	rw_enter(&tdp->i_rwlock, RW_WRITER);
9780Sstevel@tonic-gate 	if (error = ud_direnter(tdp, tnm, DE_RENAME, sdp, sip,
9795331Samw 	    (struct vattr *)0, (struct ud_inode **)0, cr, ct)) {
9800Sstevel@tonic-gate 		/*
9810Sstevel@tonic-gate 		 * ESAME isn't really an error; it indicates that the
9820Sstevel@tonic-gate 		 * operation should not be done because the source and target
9830Sstevel@tonic-gate 		 * are the same file, but that no error should be reported.
9840Sstevel@tonic-gate 		 */
9850Sstevel@tonic-gate 		if (error == ESAME) {
9860Sstevel@tonic-gate 			error = 0;
9870Sstevel@tonic-gate 		}
9880Sstevel@tonic-gate 		rw_exit(&tdp->i_rwlock);
9890Sstevel@tonic-gate 		goto errout;
9900Sstevel@tonic-gate 	}
9915331Samw 	vnevent_rename_src(ITOV(sip), sdvp, snm, ct);
9920Sstevel@tonic-gate 	rw_exit(&tdp->i_rwlock);
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 	rw_enter(&sdp->i_rwlock, RW_WRITER);
9950Sstevel@tonic-gate 	/*
9960Sstevel@tonic-gate 	 * Unlink the source.
9970Sstevel@tonic-gate 	 * Remove the source entry.  ud_dirremove() checks that the entry
9980Sstevel@tonic-gate 	 * still reflects sip, and returns an error if it doesn't.
9990Sstevel@tonic-gate 	 * If the entry has changed just forget about it.  Release
10000Sstevel@tonic-gate 	 * the source inode.
10010Sstevel@tonic-gate 	 */
10020Sstevel@tonic-gate 	if ((error = ud_dirremove(sdp, snm, sip, (struct vnode *)0,
10035331Samw 	    DR_RENAME, cr, ct)) == ENOENT) {
10040Sstevel@tonic-gate 		error = 0;
10050Sstevel@tonic-gate 	}
10060Sstevel@tonic-gate 	rw_exit(&sdp->i_rwlock);
10070Sstevel@tonic-gate errout:
10080Sstevel@tonic-gate 	ITIMES(sdp);
10090Sstevel@tonic-gate 	ITIMES(tdp);
10100Sstevel@tonic-gate 	VN_RELE(ITOV(sip));
10110Sstevel@tonic-gate 	mutex_exit(&udf_vfsp->udf_rename_lck);
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate 	return (error);
10140Sstevel@tonic-gate }
10150Sstevel@tonic-gate 
10165331Samw /* ARGSUSED */
10170Sstevel@tonic-gate static int32_t
udf_mkdir(struct vnode * dvp,char * dirname,struct vattr * vap,struct vnode ** vpp,struct cred * cr,caller_context_t * ct,int flags,vsecattr_t * vsecp)10185331Samw udf_mkdir(
10195331Samw 	struct vnode *dvp,
10205331Samw 	char *dirname,
10215331Samw 	struct vattr *vap,
10225331Samw 	struct vnode **vpp,
10235331Samw 	struct cred *cr,
10245331Samw 	caller_context_t *ct,
10255331Samw 	int flags,
10265331Samw 	vsecattr_t *vsecp)
10270Sstevel@tonic-gate {
10280Sstevel@tonic-gate 	int32_t error;
10290Sstevel@tonic-gate 	struct ud_inode *ip;
10300Sstevel@tonic-gate 	struct ud_inode *xip;
10310Sstevel@tonic-gate 
10320Sstevel@tonic-gate 	ASSERT((vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE));
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	ud_printf("udf_mkdir\n");
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 	ip = VTOI(dvp);
10370Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_WRITER);
10380Sstevel@tonic-gate 	error = ud_direnter(ip, dirname, DE_MKDIR,
10398059SDonghai.Qiao@Sun.COM 	    (struct ud_inode *)0, (struct ud_inode *)0, vap, &xip, cr, ct);
10400Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
10410Sstevel@tonic-gate 	ITIMES(ip);
10420Sstevel@tonic-gate 	if (error == 0) {
10430Sstevel@tonic-gate 		ip = xip;
10440Sstevel@tonic-gate 		*vpp = ITOV(ip);
10450Sstevel@tonic-gate 		ITIMES(ip);
10460Sstevel@tonic-gate 	} else if (error == EEXIST) {
10470Sstevel@tonic-gate 		ITIMES(xip);
10480Sstevel@tonic-gate 		VN_RELE(ITOV(xip));
10490Sstevel@tonic-gate 	}
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 	return (error);
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate 
10545331Samw /* ARGSUSED */
10550Sstevel@tonic-gate static int32_t
udf_rmdir(struct vnode * vp,char * nm,struct vnode * cdir,struct cred * cr,caller_context_t * ct,int flags)10565331Samw udf_rmdir(
10575331Samw 	struct vnode *vp,
10585331Samw 	char *nm,
10595331Samw 	struct vnode *cdir,
10605331Samw 	struct cred *cr,
10615331Samw 	caller_context_t *ct,
10625331Samw 	int flags)
10630Sstevel@tonic-gate {
10640Sstevel@tonic-gate 	int32_t error;
10650Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	ud_printf("udf_rmdir\n");
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_WRITER);
10705331Samw 	error = ud_dirremove(ip, nm, (struct ud_inode *)0, cdir, DR_RMDIR,
10718059SDonghai.Qiao@Sun.COM 	    cr, ct);
10720Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
10730Sstevel@tonic-gate 	ITIMES(ip);
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	return (error);
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate /* ARGSUSED */
10790Sstevel@tonic-gate static int32_t
udf_readdir(struct vnode * vp,struct uio * uiop,struct cred * cr,int32_t * eofp,caller_context_t * ct,int flags)10805331Samw udf_readdir(
10815331Samw 	struct vnode *vp,
10825331Samw 	struct uio *uiop,
10835331Samw 	struct cred *cr,
10845331Samw 	int32_t *eofp,
10855331Samw 	caller_context_t *ct,
10865331Samw 	int flags)
10870Sstevel@tonic-gate {
10880Sstevel@tonic-gate 	struct ud_inode *ip;
10890Sstevel@tonic-gate 	struct dirent64 *nd;
10900Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
10910Sstevel@tonic-gate 	int32_t error = 0, len, outcount = 0;
10920Sstevel@tonic-gate 	uint32_t dirsiz, offset;
10930Sstevel@tonic-gate 	uint32_t bufsize, ndlen, dummy;
10940Sstevel@tonic-gate 	caddr_t outbuf;
10950Sstevel@tonic-gate 	caddr_t outb, end_outb;
10960Sstevel@tonic-gate 	struct iovec *iovp;
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate 	uint8_t *dname;
10990Sstevel@tonic-gate 	int32_t length;
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 	uint8_t *buf = NULL;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	struct fbuf *fbp = NULL;
11040Sstevel@tonic-gate 	struct file_id *fid;
11050Sstevel@tonic-gate 	uint8_t *name;
11060Sstevel@tonic-gate 
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 	ud_printf("udf_readdir\n");
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	ip = VTOI(vp);
11110Sstevel@tonic-gate 	udf_vfsp = ip->i_udf;
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate 	dirsiz = ip->i_size;
11140Sstevel@tonic-gate 	if ((uiop->uio_offset >= dirsiz) ||
11158059SDonghai.Qiao@Sun.COM 	    (ip->i_nlink <= 0)) {
11160Sstevel@tonic-gate 		if (eofp) {
11170Sstevel@tonic-gate 			*eofp = 1;
11180Sstevel@tonic-gate 		}
11190Sstevel@tonic-gate 		return (0);
11200Sstevel@tonic-gate 	}
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	offset = uiop->uio_offset;
11230Sstevel@tonic-gate 	iovp = uiop->uio_iov;
11240Sstevel@tonic-gate 	bufsize = iovp->iov_len;
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	outb = outbuf = (char *)kmem_alloc((uint32_t)bufsize, KM_SLEEP);
11270Sstevel@tonic-gate 	end_outb = outb + bufsize;
11280Sstevel@tonic-gate 	nd = (struct dirent64 *)outbuf;
11290Sstevel@tonic-gate 
11300Sstevel@tonic-gate 	dname = (uint8_t *)kmem_zalloc(1024, KM_SLEEP);
11310Sstevel@tonic-gate 	buf = (uint8_t *)kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP);
11320Sstevel@tonic-gate 
11330Sstevel@tonic-gate 	if (offset == 0) {
11340Sstevel@tonic-gate 		len = DIRENT64_RECLEN(1);
11350Sstevel@tonic-gate 		if (((caddr_t)nd + len) >= end_outb) {
11360Sstevel@tonic-gate 			error = EINVAL;
11370Sstevel@tonic-gate 			goto end;
11380Sstevel@tonic-gate 		}
11390Sstevel@tonic-gate 		nd->d_ino = ip->i_icb_lbano;
11400Sstevel@tonic-gate 		nd->d_reclen = (uint16_t)len;
11410Sstevel@tonic-gate 		nd->d_off = 0x10;
11420Sstevel@tonic-gate 		nd->d_name[0] = '.';
11430Sstevel@tonic-gate 		bzero(&nd->d_name[1], DIRENT64_NAMELEN(len) - 1);
11440Sstevel@tonic-gate 		nd = (struct dirent64 *)((char *)nd + nd->d_reclen);
11450Sstevel@tonic-gate 		outcount++;
11460Sstevel@tonic-gate 	} else if (offset == 0x10) {
11470Sstevel@tonic-gate 		offset = 0;
11480Sstevel@tonic-gate 	}
11490Sstevel@tonic-gate 
11500Sstevel@tonic-gate 	while (offset < dirsiz) {
11510Sstevel@tonic-gate 		error = ud_get_next_fid(ip, &fbp,
11528059SDonghai.Qiao@Sun.COM 		    offset, &fid, &name, buf);
11530Sstevel@tonic-gate 		if (error != 0) {
11540Sstevel@tonic-gate 			break;
11550Sstevel@tonic-gate 		}
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 		if ((fid->fid_flags & FID_DELETED) == 0) {
11580Sstevel@tonic-gate 			if (fid->fid_flags & FID_PARENT) {
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate 				len = DIRENT64_RECLEN(2);
11610Sstevel@tonic-gate 				if (((caddr_t)nd + len) >= end_outb) {
11620Sstevel@tonic-gate 					error = EINVAL;
11630Sstevel@tonic-gate 					break;
11640Sstevel@tonic-gate 				}
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 				nd->d_ino = ip->i_icb_lbano;
11670Sstevel@tonic-gate 				nd->d_reclen = (uint16_t)len;
11680Sstevel@tonic-gate 				nd->d_off = offset + FID_LEN(fid);
11690Sstevel@tonic-gate 				nd->d_name[0] = '.';
11700Sstevel@tonic-gate 				nd->d_name[1] = '.';
11710Sstevel@tonic-gate 				bzero(&nd->d_name[2],
11720Sstevel@tonic-gate 				    DIRENT64_NAMELEN(len) - 2);
11730Sstevel@tonic-gate 				nd = (struct dirent64 *)
11748059SDonghai.Qiao@Sun.COM 				    ((char *)nd + nd->d_reclen);
11750Sstevel@tonic-gate 			} else {
11760Sstevel@tonic-gate 				if ((error = ud_uncompress(fid->fid_idlen,
11778059SDonghai.Qiao@Sun.COM 				    &length, name, dname)) != 0) {
11780Sstevel@tonic-gate 					break;
11790Sstevel@tonic-gate 				}
11800Sstevel@tonic-gate 				if (length == 0) {
11810Sstevel@tonic-gate 					offset += FID_LEN(fid);
11820Sstevel@tonic-gate 					continue;
11830Sstevel@tonic-gate 				}
11840Sstevel@tonic-gate 				len = DIRENT64_RECLEN(length);
11850Sstevel@tonic-gate 				if (((caddr_t)nd + len) >= end_outb) {
11860Sstevel@tonic-gate 					if (!outcount) {
11870Sstevel@tonic-gate 						error = EINVAL;
11880Sstevel@tonic-gate 					}
11890Sstevel@tonic-gate 					break;
11900Sstevel@tonic-gate 				}
11910Sstevel@tonic-gate 				(void) strncpy(nd->d_name,
11920Sstevel@tonic-gate 				    (caddr_t)dname, length);
11930Sstevel@tonic-gate 				bzero(&nd->d_name[length],
11940Sstevel@tonic-gate 				    DIRENT64_NAMELEN(len) - length);
11950Sstevel@tonic-gate 				nd->d_ino = ud_xlate_to_daddr(udf_vfsp,
11968059SDonghai.Qiao@Sun.COM 				    SWAP_16(fid->fid_icb.lad_ext_prn),
11978059SDonghai.Qiao@Sun.COM 				    SWAP_32(fid->fid_icb.lad_ext_loc), 1,
11988059SDonghai.Qiao@Sun.COM 				    &dummy);
11990Sstevel@tonic-gate 				nd->d_reclen = (uint16_t)len;
12000Sstevel@tonic-gate 				nd->d_off = offset + FID_LEN(fid);
12010Sstevel@tonic-gate 				nd = (struct dirent64 *)
12028059SDonghai.Qiao@Sun.COM 				    ((char *)nd + nd->d_reclen);
12030Sstevel@tonic-gate 			}
12040Sstevel@tonic-gate 			outcount++;
12050Sstevel@tonic-gate 		}
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 		offset += FID_LEN(fid);
12080Sstevel@tonic-gate 	}
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate end:
12110Sstevel@tonic-gate 	if (fbp != NULL) {
12120Sstevel@tonic-gate 		fbrelse(fbp, S_OTHER);
12130Sstevel@tonic-gate 	}
12140Sstevel@tonic-gate 	ndlen = ((char *)nd - outbuf);
12150Sstevel@tonic-gate 	/*
12160Sstevel@tonic-gate 	 * In case of error do not call uiomove.
12170Sstevel@tonic-gate 	 * Return the error to the caller.
12180Sstevel@tonic-gate 	 */
12190Sstevel@tonic-gate 	if ((error == 0) && (ndlen != 0)) {
12200Sstevel@tonic-gate 		error = uiomove(outbuf, (long)ndlen, UIO_READ, uiop);
12210Sstevel@tonic-gate 		uiop->uio_offset = offset;
12220Sstevel@tonic-gate 	}
12230Sstevel@tonic-gate 	kmem_free((caddr_t)buf, udf_vfsp->udf_lbsize);
12240Sstevel@tonic-gate 	kmem_free((caddr_t)dname, 1024);
12250Sstevel@tonic-gate 	kmem_free(outbuf, (uint32_t)bufsize);
12260Sstevel@tonic-gate 	if (eofp && error == 0) {
12270Sstevel@tonic-gate 		*eofp = (uiop->uio_offset >= dirsiz);
12280Sstevel@tonic-gate 	}
12290Sstevel@tonic-gate 	return (error);
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate /* ARGSUSED */
12330Sstevel@tonic-gate static int32_t
udf_symlink(struct vnode * dvp,char * linkname,struct vattr * vap,char * target,struct cred * cr,caller_context_t * ct,int flags)12345331Samw udf_symlink(
12355331Samw 	struct vnode *dvp,
12365331Samw 	char *linkname,
12375331Samw 	struct vattr *vap,
12385331Samw 	char *target,
12395331Samw 	struct cred *cr,
12405331Samw 	caller_context_t *ct,
12415331Samw 	int flags)
12420Sstevel@tonic-gate {
12430Sstevel@tonic-gate 	int32_t error = 0, outlen;
12440Sstevel@tonic-gate 	uint32_t ioflag = 0;
12450Sstevel@tonic-gate 	struct ud_inode *ip, *dip = VTOI(dvp);
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate 	struct path_comp *pc;
12480Sstevel@tonic-gate 	int8_t *dname = NULL, *uname = NULL, *sp;
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 	ud_printf("udf_symlink\n");
12510Sstevel@tonic-gate 
12520Sstevel@tonic-gate 	ip = (struct ud_inode *)0;
12530Sstevel@tonic-gate 	vap->va_type = VLNK;
12540Sstevel@tonic-gate 	vap->va_rdev = 0;
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 	rw_enter(&dip->i_rwlock, RW_WRITER);
12570Sstevel@tonic-gate 	error = ud_direnter(dip, linkname, DE_CREATE,
12588059SDonghai.Qiao@Sun.COM 	    (struct ud_inode *)0, (struct ud_inode *)0, vap, &ip, cr, ct);
12590Sstevel@tonic-gate 	rw_exit(&dip->i_rwlock);
12600Sstevel@tonic-gate 	if (error == 0) {
12610Sstevel@tonic-gate 		dname = kmem_zalloc(1024, KM_SLEEP);
12620Sstevel@tonic-gate 		uname = kmem_zalloc(PAGESIZE, KM_SLEEP);
12630Sstevel@tonic-gate 
12640Sstevel@tonic-gate 		pc = (struct path_comp *)uname;
12650Sstevel@tonic-gate 		/*
12660Sstevel@tonic-gate 		 * If the first character in target is "/"
12670Sstevel@tonic-gate 		 * then skip it and create entry for it
12680Sstevel@tonic-gate 		 */
12690Sstevel@tonic-gate 		if (*target == '/') {
12700Sstevel@tonic-gate 			pc->pc_type = 2;
12710Sstevel@tonic-gate 			pc->pc_len = 0;
12720Sstevel@tonic-gate 			pc = (struct path_comp *)(((char *)pc) + 4);
12730Sstevel@tonic-gate 			while (*target == '/') {
12740Sstevel@tonic-gate 				target++;
12750Sstevel@tonic-gate 			}
12760Sstevel@tonic-gate 		}
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 		while (*target != NULL) {
12790Sstevel@tonic-gate 			sp = target;
12800Sstevel@tonic-gate 			while ((*target != '/') && (*target != '\0')) {
12810Sstevel@tonic-gate 				target ++;
12820Sstevel@tonic-gate 			}
12830Sstevel@tonic-gate 			/*
12840Sstevel@tonic-gate 			 * We got the next component of the
12850Sstevel@tonic-gate 			 * path name. Create path_comp of
12860Sstevel@tonic-gate 			 * appropriate type
12870Sstevel@tonic-gate 			 */
12880Sstevel@tonic-gate 			if (((target - sp) == 1) && (*sp == '.')) {
12890Sstevel@tonic-gate 				/*
12900Sstevel@tonic-gate 				 * Dot entry.
12910Sstevel@tonic-gate 				 */
12920Sstevel@tonic-gate 				pc->pc_type = 4;
12930Sstevel@tonic-gate 				pc = (struct path_comp *)(((char *)pc) + 4);
12940Sstevel@tonic-gate 			} else if (((target - sp) == 2) &&
12958059SDonghai.Qiao@Sun.COM 			    (*sp == '.') && ((*(sp + 1)) == '.')) {
12960Sstevel@tonic-gate 				/*
12970Sstevel@tonic-gate 				 * DotDot entry.
12980Sstevel@tonic-gate 				 */
12990Sstevel@tonic-gate 				pc->pc_type = 3;
13000Sstevel@tonic-gate 				pc = (struct path_comp *)(((char *)pc) + 4);
13010Sstevel@tonic-gate 			} else {
13020Sstevel@tonic-gate 				/*
13030Sstevel@tonic-gate 				 * convert the user given name
13040Sstevel@tonic-gate 				 * into appropriate form to be put
13050Sstevel@tonic-gate 				 * on the media
13060Sstevel@tonic-gate 				 */
13070Sstevel@tonic-gate 				outlen = 1024;	/* set to size of dname */
13080Sstevel@tonic-gate 				if (error = ud_compress(target - sp, &outlen,
13098059SDonghai.Qiao@Sun.COM 				    (uint8_t *)sp, (uint8_t *)dname)) {
13100Sstevel@tonic-gate 					break;
13110Sstevel@tonic-gate 				}
13120Sstevel@tonic-gate 				pc->pc_type = 5;
13130Sstevel@tonic-gate 				/* LINTED */
13140Sstevel@tonic-gate 				pc->pc_len = outlen;
13150Sstevel@tonic-gate 				dname[outlen] = '\0';
13160Sstevel@tonic-gate 				(void) strcpy((char *)pc->pc_id, dname);
13170Sstevel@tonic-gate 				pc = (struct path_comp *)
13188059SDonghai.Qiao@Sun.COM 				    (((char *)pc) + 4 + outlen);
13190Sstevel@tonic-gate 			}
13200Sstevel@tonic-gate 			while (*target == '/') {
13210Sstevel@tonic-gate 				target++;
13220Sstevel@tonic-gate 			}
13230Sstevel@tonic-gate 			if (*target == NULL) {
13240Sstevel@tonic-gate 				break;
13250Sstevel@tonic-gate 			}
13260Sstevel@tonic-gate 		}
13270Sstevel@tonic-gate 
13280Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_WRITER);
13290Sstevel@tonic-gate 		if (error == 0) {
13300Sstevel@tonic-gate 			ioflag = FWRITE;
13310Sstevel@tonic-gate 			if (curthread->t_flag & T_DONTPEND) {
13320Sstevel@tonic-gate 				ioflag |= FDSYNC;
13330Sstevel@tonic-gate 			}
13340Sstevel@tonic-gate 			error = ud_rdwri(UIO_WRITE, ioflag, ip,
13358059SDonghai.Qiao@Sun.COM 			    uname, ((int8_t *)pc) - uname,
13368059SDonghai.Qiao@Sun.COM 			    (offset_t)0, UIO_SYSSPACE, (int32_t *)0, cr);
13370Sstevel@tonic-gate 		}
13380Sstevel@tonic-gate 		if (error) {
13390Sstevel@tonic-gate 			ud_idrop(ip);
13400Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
13410Sstevel@tonic-gate 			rw_enter(&dip->i_rwlock, RW_WRITER);
13420Sstevel@tonic-gate 			(void) ud_dirremove(dip, linkname, (struct ud_inode *)0,
13438059SDonghai.Qiao@Sun.COM 			    (struct vnode *)0, DR_REMOVE, cr, ct);
13440Sstevel@tonic-gate 			rw_exit(&dip->i_rwlock);
13450Sstevel@tonic-gate 			goto update_inode;
13460Sstevel@tonic-gate 		}
13470Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
13480Sstevel@tonic-gate 	}
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate 	if ((error == 0) || (error == EEXIST)) {
13510Sstevel@tonic-gate 		VN_RELE(ITOV(ip));
13520Sstevel@tonic-gate 	}
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate update_inode:
13550Sstevel@tonic-gate 	ITIMES(VTOI(dvp));
13560Sstevel@tonic-gate 	if (uname != NULL) {
13570Sstevel@tonic-gate 		kmem_free(uname, PAGESIZE);
13580Sstevel@tonic-gate 	}
13590Sstevel@tonic-gate 	if (dname != NULL) {
13600Sstevel@tonic-gate 		kmem_free(dname, 1024);
13610Sstevel@tonic-gate 	}
13620Sstevel@tonic-gate 
13630Sstevel@tonic-gate 	return (error);
13640Sstevel@tonic-gate }
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate /* ARGSUSED */
13670Sstevel@tonic-gate static int32_t
udf_readlink(struct vnode * vp,struct uio * uiop,struct cred * cr,caller_context_t * ct)13685331Samw udf_readlink(
13695331Samw 	struct vnode *vp,
13705331Samw 	struct uio *uiop,
13715331Samw 	struct cred *cr,
13725331Samw 	caller_context_t *ct)
13730Sstevel@tonic-gate {
13740Sstevel@tonic-gate 	int32_t error = 0, off, id_len, size, len;
13750Sstevel@tonic-gate 	int8_t *dname = NULL, *uname = NULL;
13760Sstevel@tonic-gate 	struct ud_inode *ip;
13770Sstevel@tonic-gate 	struct fbuf *fbp = NULL;
13780Sstevel@tonic-gate 	struct path_comp *pc;
13790Sstevel@tonic-gate 
13800Sstevel@tonic-gate 	ud_printf("udf_readlink\n");
13810Sstevel@tonic-gate 
13820Sstevel@tonic-gate 	if (vp->v_type != VLNK) {
13830Sstevel@tonic-gate 		return (EINVAL);
13840Sstevel@tonic-gate 	}
13850Sstevel@tonic-gate 
13860Sstevel@tonic-gate 	ip = VTOI(vp);
13870Sstevel@tonic-gate 	size = ip->i_size;
13880Sstevel@tonic-gate 	if (size > PAGESIZE) {
13890Sstevel@tonic-gate 		return (EIO);
13900Sstevel@tonic-gate 	}
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate 	if (size == 0) {
13930Sstevel@tonic-gate 		return (0);
13940Sstevel@tonic-gate 	}
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	dname = kmem_zalloc(1024, KM_SLEEP);
13970Sstevel@tonic-gate 	uname = kmem_zalloc(PAGESIZE, KM_SLEEP);
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_READER);
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 	if ((error = fbread(vp, 0, size, S_READ, &fbp)) != 0) {
14020Sstevel@tonic-gate 		goto end;
14030Sstevel@tonic-gate 	}
14040Sstevel@tonic-gate 
14050Sstevel@tonic-gate 	off = 0;
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate 	while (off < size) {
14080Sstevel@tonic-gate 		pc = (struct path_comp *)(fbp->fb_addr + off);
14090Sstevel@tonic-gate 		switch (pc->pc_type) {
14100Sstevel@tonic-gate 			case 1 :
14110Sstevel@tonic-gate 				(void) strcpy(uname, ip->i_udf->udf_fsmnt);
14120Sstevel@tonic-gate 				(void) strcat(uname, "/");
14130Sstevel@tonic-gate 				break;
14140Sstevel@tonic-gate 			case 2 :
14150Sstevel@tonic-gate 				if (pc->pc_len != 0) {
14160Sstevel@tonic-gate 					goto end;
14170Sstevel@tonic-gate 				}
14180Sstevel@tonic-gate 				uname[0] = '/';
14190Sstevel@tonic-gate 				uname[1] = '\0';
14200Sstevel@tonic-gate 				break;
14210Sstevel@tonic-gate 			case 3 :
14220Sstevel@tonic-gate 				(void) strcat(uname, "../");
14230Sstevel@tonic-gate 				break;
14240Sstevel@tonic-gate 			case 4 :
14250Sstevel@tonic-gate 				(void) strcat(uname, "./");
14260Sstevel@tonic-gate 				break;
14270Sstevel@tonic-gate 			case 5 :
14280Sstevel@tonic-gate 				if ((error = ud_uncompress(pc->pc_len, &id_len,
14298059SDonghai.Qiao@Sun.COM 				    pc->pc_id, (uint8_t *)dname)) != 0) {
14300Sstevel@tonic-gate 					break;
14310Sstevel@tonic-gate 				}
14320Sstevel@tonic-gate 				dname[id_len] = '\0';
14330Sstevel@tonic-gate 				(void) strcat(uname, dname);
14340Sstevel@tonic-gate 				(void) strcat(uname, "/");
14350Sstevel@tonic-gate 				break;
14360Sstevel@tonic-gate 			default :
14370Sstevel@tonic-gate 				error = EINVAL;
14380Sstevel@tonic-gate 				goto end;
14390Sstevel@tonic-gate 		}
14400Sstevel@tonic-gate 		off += 4 + pc->pc_len;
14410Sstevel@tonic-gate 	}
14420Sstevel@tonic-gate 	len = strlen(uname) - 1;
14430Sstevel@tonic-gate 	if (uname[len] == '/') {
14440Sstevel@tonic-gate 		if (len == 0) {
14450Sstevel@tonic-gate 			/*
14460Sstevel@tonic-gate 			 * special case link to /
14470Sstevel@tonic-gate 			 */
14480Sstevel@tonic-gate 			len = 1;
14490Sstevel@tonic-gate 		} else {
14500Sstevel@tonic-gate 			uname[len] = '\0';
14510Sstevel@tonic-gate 		}
14520Sstevel@tonic-gate 	}
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 	error = uiomove(uname, len, UIO_READ, uiop);
14550Sstevel@tonic-gate 
14560Sstevel@tonic-gate 	ITIMES(ip);
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate end:
14590Sstevel@tonic-gate 	if (fbp != NULL) {
14600Sstevel@tonic-gate 		fbrelse(fbp, S_OTHER);
14610Sstevel@tonic-gate 	}
14620Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
14630Sstevel@tonic-gate 	if (uname != NULL) {
14640Sstevel@tonic-gate 		kmem_free(uname, PAGESIZE);
14650Sstevel@tonic-gate 	}
14660Sstevel@tonic-gate 	if (dname != NULL) {
14670Sstevel@tonic-gate 		kmem_free(dname, 1024);
14680Sstevel@tonic-gate 	}
14690Sstevel@tonic-gate 	return (error);
14700Sstevel@tonic-gate }
14710Sstevel@tonic-gate 
14720Sstevel@tonic-gate /* ARGSUSED */
14730Sstevel@tonic-gate static int32_t
udf_fsync(struct vnode * vp,int32_t syncflag,struct cred * cr,caller_context_t * ct)14745331Samw udf_fsync(
14755331Samw 	struct vnode *vp,
14765331Samw 	int32_t syncflag,
14775331Samw 	struct cred *cr,
14785331Samw 	caller_context_t *ct)
14790Sstevel@tonic-gate {
14800Sstevel@tonic-gate 	int32_t error = 0;
14810Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate 	ud_printf("udf_fsync\n");
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_WRITER);
14860Sstevel@tonic-gate 	if (!(IS_SWAPVP(vp))) {
14870Sstevel@tonic-gate 		error = ud_syncip(ip, 0, I_SYNC); /* Do synchronous writes */
14880Sstevel@tonic-gate 	}
14890Sstevel@tonic-gate 	if (error == 0) {
14900Sstevel@tonic-gate 		error = ud_sync_indir(ip);
14910Sstevel@tonic-gate 	}
14920Sstevel@tonic-gate 	ITIMES(ip);		/* XXX: is this necessary ??? */
14930Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 	return (error);
14960Sstevel@tonic-gate }
14970Sstevel@tonic-gate 
14980Sstevel@tonic-gate /* ARGSUSED */
14990Sstevel@tonic-gate static void
udf_inactive(struct vnode * vp,struct cred * cr,caller_context_t * ct)15005331Samw udf_inactive(struct vnode *vp, struct cred *cr, caller_context_t *ct)
15010Sstevel@tonic-gate {
15020Sstevel@tonic-gate 	ud_printf("udf_iinactive\n");
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate 	ud_iinactive(VTOI(vp), cr);
15050Sstevel@tonic-gate }
15060Sstevel@tonic-gate 
15075331Samw /* ARGSUSED */
15080Sstevel@tonic-gate static int32_t
udf_fid(struct vnode * vp,struct fid * fidp,caller_context_t * ct)15095331Samw udf_fid(struct vnode *vp, struct fid *fidp, caller_context_t *ct)
15100Sstevel@tonic-gate {
15110Sstevel@tonic-gate 	struct udf_fid *udfidp;
15120Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 	ud_printf("udf_fid\n");
15150Sstevel@tonic-gate 
15160Sstevel@tonic-gate 	if (fidp->fid_len < (sizeof (struct udf_fid) - sizeof (uint16_t))) {
15170Sstevel@tonic-gate 		fidp->fid_len = sizeof (struct udf_fid) - sizeof (uint16_t);
15180Sstevel@tonic-gate 		return (ENOSPC);
15190Sstevel@tonic-gate 	}
15200Sstevel@tonic-gate 
15210Sstevel@tonic-gate 	udfidp = (struct udf_fid *)fidp;
15220Sstevel@tonic-gate 	bzero((char *)udfidp, sizeof (struct udf_fid));
15230Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_READER);
15240Sstevel@tonic-gate 	udfidp->udfid_len = sizeof (struct udf_fid) - sizeof (uint16_t);
15250Sstevel@tonic-gate 	udfidp->udfid_uinq_lo = ip->i_uniqid & 0xffffffff;
15260Sstevel@tonic-gate 	udfidp->udfid_prn = ip->i_icb_prn;
15270Sstevel@tonic-gate 	udfidp->udfid_icb_lbn = ip->i_icb_block;
15280Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	return (0);
15310Sstevel@tonic-gate }
15320Sstevel@tonic-gate 
15330Sstevel@tonic-gate /* ARGSUSED2 */
15340Sstevel@tonic-gate static int
udf_rwlock(struct vnode * vp,int32_t write_lock,caller_context_t * ctp)15350Sstevel@tonic-gate udf_rwlock(struct vnode *vp, int32_t write_lock, caller_context_t *ctp)
15360Sstevel@tonic-gate {
15370Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
15380Sstevel@tonic-gate 
15390Sstevel@tonic-gate 	ud_printf("udf_rwlock\n");
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 	if (write_lock) {
15420Sstevel@tonic-gate 		rw_enter(&ip->i_rwlock, RW_WRITER);
15430Sstevel@tonic-gate 	} else {
15440Sstevel@tonic-gate 		rw_enter(&ip->i_rwlock, RW_READER);
15450Sstevel@tonic-gate 	}
15460Sstevel@tonic-gate #ifdef	__lock_lint
15470Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
15480Sstevel@tonic-gate #endif
15490Sstevel@tonic-gate 	return (write_lock);
15500Sstevel@tonic-gate }
15510Sstevel@tonic-gate 
15520Sstevel@tonic-gate /* ARGSUSED */
15530Sstevel@tonic-gate static void
udf_rwunlock(struct vnode * vp,int32_t write_lock,caller_context_t * ctp)15540Sstevel@tonic-gate udf_rwunlock(struct vnode *vp, int32_t write_lock, caller_context_t *ctp)
15550Sstevel@tonic-gate {
15560Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate 	ud_printf("udf_rwunlock\n");
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate #ifdef	__lock_lint
15610Sstevel@tonic-gate 	rw_enter(&ip->i_rwlock, RW_WRITER);
15620Sstevel@tonic-gate #endif
15630Sstevel@tonic-gate 
15640Sstevel@tonic-gate 	rw_exit(&ip->i_rwlock);
15650Sstevel@tonic-gate 
15660Sstevel@tonic-gate }
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate /* ARGSUSED */
15690Sstevel@tonic-gate static int32_t
udf_seek(struct vnode * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)15705331Samw udf_seek(struct vnode *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
15710Sstevel@tonic-gate {
15720Sstevel@tonic-gate 	return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0);
15730Sstevel@tonic-gate }
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate static int32_t
udf_frlock(struct vnode * vp,int32_t cmd,struct flock64 * bfp,int32_t flag,offset_t offset,struct flk_callback * flk_cbp,cred_t * cr,caller_context_t * ct)15765331Samw udf_frlock(
15775331Samw 	struct vnode *vp,
15785331Samw 	int32_t cmd,
15795331Samw 	struct flock64 *bfp,
15805331Samw 	int32_t flag,
15815331Samw 	offset_t offset,
15825331Samw 	struct flk_callback *flk_cbp,
15835331Samw 	cred_t *cr,
15845331Samw 	caller_context_t *ct)
15850Sstevel@tonic-gate {
15860Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
15870Sstevel@tonic-gate 
15880Sstevel@tonic-gate 	ud_printf("udf_frlock\n");
15890Sstevel@tonic-gate 
15900Sstevel@tonic-gate 	/*
15910Sstevel@tonic-gate 	 * If file is being mapped, disallow frlock.
15920Sstevel@tonic-gate 	 * XXX I am not holding tlock while checking i_mapcnt because the
15930Sstevel@tonic-gate 	 * current locking strategy drops all locks before calling fs_frlock.
15940Sstevel@tonic-gate 	 * So, mapcnt could change before we enter fs_frlock making is
15950Sstevel@tonic-gate 	 * meaningless to have held tlock in the first place.
15960Sstevel@tonic-gate 	 */
15970Sstevel@tonic-gate 	if ((ip->i_mapcnt > 0) &&
15988059SDonghai.Qiao@Sun.COM 	    (MANDLOCK(vp, ip->i_char))) {
15990Sstevel@tonic-gate 		return (EAGAIN);
16000Sstevel@tonic-gate 	}
16010Sstevel@tonic-gate 
16025331Samw 	return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
16030Sstevel@tonic-gate }
16040Sstevel@tonic-gate 
16050Sstevel@tonic-gate /*ARGSUSED6*/
16060Sstevel@tonic-gate static int32_t
udf_space(struct vnode * vp,int32_t cmd,struct flock64 * bfp,int32_t flag,offset_t offset,cred_t * cr,caller_context_t * ct)16070Sstevel@tonic-gate udf_space(
16080Sstevel@tonic-gate 	struct vnode *vp,
16090Sstevel@tonic-gate 	int32_t cmd,
16100Sstevel@tonic-gate 	struct flock64 *bfp,
16110Sstevel@tonic-gate 	int32_t flag,
16120Sstevel@tonic-gate 	offset_t offset,
16130Sstevel@tonic-gate 	cred_t *cr,
16140Sstevel@tonic-gate 	caller_context_t *ct)
16150Sstevel@tonic-gate {
16160Sstevel@tonic-gate 	int32_t error = 0;
16170Sstevel@tonic-gate 
16180Sstevel@tonic-gate 	ud_printf("udf_space\n");
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 	if (cmd != F_FREESP) {
16210Sstevel@tonic-gate 		error =  EINVAL;
16220Sstevel@tonic-gate 	} else if ((error = convoff(vp, bfp, 0, offset)) == 0) {
16230Sstevel@tonic-gate 		error = ud_freesp(vp, bfp, flag, cr);
16240Sstevel@tonic-gate 	}
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 	return (error);
16270Sstevel@tonic-gate }
16280Sstevel@tonic-gate 
16290Sstevel@tonic-gate /* ARGSUSED */
16300Sstevel@tonic-gate static int32_t
udf_getpage(struct vnode * vp,offset_t off,size_t len,uint32_t * protp,struct page ** plarr,size_t plsz,struct seg * seg,caddr_t addr,enum seg_rw rw,struct cred * cr,caller_context_t * ct)16315331Samw udf_getpage(
16325331Samw 	struct vnode *vp,
16335331Samw 	offset_t off,
16345331Samw 	size_t len,
16355331Samw 	uint32_t *protp,
16365331Samw 	struct page **plarr,
16375331Samw 	size_t plsz,
16385331Samw 	struct seg *seg,
16395331Samw 	caddr_t addr,
16405331Samw 	enum seg_rw rw,
16415331Samw 	struct cred *cr,
16425331Samw 	caller_context_t *ct)
16430Sstevel@tonic-gate {
16440Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
16450Sstevel@tonic-gate 	int32_t error, has_holes, beyond_eof, seqmode, dolock;
16460Sstevel@tonic-gate 	int32_t pgsize = PAGESIZE;
16470Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp = ip->i_udf;
16480Sstevel@tonic-gate 	page_t **pl;
16490Sstevel@tonic-gate 	u_offset_t pgoff, eoff, uoff;
16500Sstevel@tonic-gate 	krw_t rwtype;
16510Sstevel@tonic-gate 	caddr_t pgaddr;
16520Sstevel@tonic-gate 
16530Sstevel@tonic-gate 	ud_printf("udf_getpage\n");
16540Sstevel@tonic-gate 
16550Sstevel@tonic-gate 	uoff = (u_offset_t)off; /* type conversion */
16560Sstevel@tonic-gate 	if (protp) {
16570Sstevel@tonic-gate 		*protp = PROT_ALL;
16580Sstevel@tonic-gate 	}
16590Sstevel@tonic-gate 	if (vp->v_flag & VNOMAP) {
16600Sstevel@tonic-gate 		return (ENOSYS);
16610Sstevel@tonic-gate 	}
16620Sstevel@tonic-gate 	seqmode = ip->i_nextr == uoff && rw != S_CREATE;
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate 	rwtype = RW_READER;
16650Sstevel@tonic-gate 	dolock = (rw_owner(&ip->i_contents) != curthread);
16660Sstevel@tonic-gate retrylock:
16670Sstevel@tonic-gate #ifdef	__lock_lint
16680Sstevel@tonic-gate 	rw_enter(&ip->i_contents, rwtype);
16690Sstevel@tonic-gate #else
16700Sstevel@tonic-gate 	if (dolock) {
16710Sstevel@tonic-gate 		rw_enter(&ip->i_contents, rwtype);
16720Sstevel@tonic-gate 	}
16730Sstevel@tonic-gate #endif
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 	/*
16760Sstevel@tonic-gate 	 * We may be getting called as a side effect of a bmap using
16770Sstevel@tonic-gate 	 * fbread() when the blocks might be being allocated and the
16780Sstevel@tonic-gate 	 * size has not yet been up'ed.  In this case we want to be
16790Sstevel@tonic-gate 	 * able to return zero pages if we get back UDF_HOLE from
16800Sstevel@tonic-gate 	 * calling bmap for a non write case here.  We also might have
16810Sstevel@tonic-gate 	 * to read some frags from the disk into a page if we are
16820Sstevel@tonic-gate 	 * extending the number of frags for a given lbn in bmap().
16830Sstevel@tonic-gate 	 */
16840Sstevel@tonic-gate 	beyond_eof = uoff + len > ip->i_size + PAGEOFFSET;
16850Sstevel@tonic-gate 	if (beyond_eof && seg != segkmap) {
16860Sstevel@tonic-gate #ifdef	__lock_lint
16870Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
16880Sstevel@tonic-gate #else
16890Sstevel@tonic-gate 		if (dolock) {
16900Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
16910Sstevel@tonic-gate 		}
16920Sstevel@tonic-gate #endif
16930Sstevel@tonic-gate 		return (EFAULT);
16940Sstevel@tonic-gate 	}
16950Sstevel@tonic-gate 
16960Sstevel@tonic-gate 	/*
16970Sstevel@tonic-gate 	 * Must hold i_contents lock throughout the call to pvn_getpages
16980Sstevel@tonic-gate 	 * since locked pages are returned from each call to ud_getapage.
16990Sstevel@tonic-gate 	 * Must *not* return locked pages and then try for contents lock
17000Sstevel@tonic-gate 	 * due to lock ordering requirements (inode > page)
17010Sstevel@tonic-gate 	 */
17020Sstevel@tonic-gate 
17030Sstevel@tonic-gate 	has_holes = ud_bmap_has_holes(ip);
17040Sstevel@tonic-gate 
17050Sstevel@tonic-gate 	if ((rw == S_WRITE || rw == S_CREATE) && (has_holes || beyond_eof)) {
17060Sstevel@tonic-gate 		int32_t	blk_size, count;
17070Sstevel@tonic-gate 		u_offset_t offset;
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 		/*
17100Sstevel@tonic-gate 		 * We must acquire the RW_WRITER lock in order to
17110Sstevel@tonic-gate 		 * call bmap_write().
17120Sstevel@tonic-gate 		 */
17130Sstevel@tonic-gate 		if (dolock && rwtype == RW_READER) {
17140Sstevel@tonic-gate 			rwtype = RW_WRITER;
17150Sstevel@tonic-gate 
17160Sstevel@tonic-gate 			if (!rw_tryupgrade(&ip->i_contents)) {
17170Sstevel@tonic-gate 
17180Sstevel@tonic-gate 				rw_exit(&ip->i_contents);
17190Sstevel@tonic-gate 
17200Sstevel@tonic-gate 				goto retrylock;
17210Sstevel@tonic-gate 			}
17220Sstevel@tonic-gate 		}
17230Sstevel@tonic-gate 
17240Sstevel@tonic-gate 		/*
17250Sstevel@tonic-gate 		 * May be allocating disk blocks for holes here as
17260Sstevel@tonic-gate 		 * a result of mmap faults. write(2) does the bmap_write
17270Sstevel@tonic-gate 		 * in rdip/wrip, not here. We are not dealing with frags
17280Sstevel@tonic-gate 		 * in this case.
17290Sstevel@tonic-gate 		 */
17300Sstevel@tonic-gate 		offset = uoff;
17310Sstevel@tonic-gate 		while ((offset < uoff + len) &&
17328059SDonghai.Qiao@Sun.COM 		    (offset < ip->i_size)) {
17330Sstevel@tonic-gate 			/*
17340Sstevel@tonic-gate 			 * the variable "bnp" is to simplify the expression for
17350Sstevel@tonic-gate 			 * the compiler; * just passing in &bn to bmap_write
17360Sstevel@tonic-gate 			 * causes a compiler "loop"
17370Sstevel@tonic-gate 			 */
17380Sstevel@tonic-gate 
17390Sstevel@tonic-gate 			blk_size = udf_vfsp->udf_lbsize;
17400Sstevel@tonic-gate 			if ((offset + blk_size) > ip->i_size) {
17410Sstevel@tonic-gate 				count = ip->i_size - offset;
17420Sstevel@tonic-gate 			} else {
17430Sstevel@tonic-gate 				count = blk_size;
17440Sstevel@tonic-gate 			}
17450Sstevel@tonic-gate 			error = ud_bmap_write(ip, offset, count, 0, cr);
17460Sstevel@tonic-gate 			if (error) {
17470Sstevel@tonic-gate 				goto update_inode;
17480Sstevel@tonic-gate 			}
17490Sstevel@tonic-gate 			offset += count; /* XXX - make this contig */
17500Sstevel@tonic-gate 		}
17510Sstevel@tonic-gate 	}
17520Sstevel@tonic-gate 
17530Sstevel@tonic-gate 	/*
17540Sstevel@tonic-gate 	 * Can be a reader from now on.
17550Sstevel@tonic-gate 	 */
17560Sstevel@tonic-gate #ifdef	__lock_lint
17570Sstevel@tonic-gate 	if (rwtype == RW_WRITER) {
17580Sstevel@tonic-gate 		rw_downgrade(&ip->i_contents);
17590Sstevel@tonic-gate 	}
17600Sstevel@tonic-gate #else
17610Sstevel@tonic-gate 	if (dolock && rwtype == RW_WRITER) {
17620Sstevel@tonic-gate 		rw_downgrade(&ip->i_contents);
17630Sstevel@tonic-gate 	}
17640Sstevel@tonic-gate #endif
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate 	/*
17670Sstevel@tonic-gate 	 * We remove PROT_WRITE in cases when the file has UDF holes
17680Sstevel@tonic-gate 	 * because we don't  want to call bmap_read() to check each
17690Sstevel@tonic-gate 	 * page if it is backed with a disk block.
17700Sstevel@tonic-gate 	 */
17710Sstevel@tonic-gate 	if (protp && has_holes && rw != S_WRITE && rw != S_CREATE) {
17720Sstevel@tonic-gate 		*protp &= ~PROT_WRITE;
17730Sstevel@tonic-gate 	}
17740Sstevel@tonic-gate 
17750Sstevel@tonic-gate 	error = 0;
17760Sstevel@tonic-gate 
17770Sstevel@tonic-gate 	/*
17780Sstevel@tonic-gate 	 * The loop looks up pages in the range <off, off + len).
17790Sstevel@tonic-gate 	 * For each page, we first check if we should initiate an asynchronous
17800Sstevel@tonic-gate 	 * read ahead before we call page_lookup (we may sleep in page_lookup
17810Sstevel@tonic-gate 	 * for a previously initiated disk read).
17820Sstevel@tonic-gate 	 */
17830Sstevel@tonic-gate 	eoff = (uoff + len);
17840Sstevel@tonic-gate 	for (pgoff = uoff, pgaddr = addr, pl = plarr;
17858059SDonghai.Qiao@Sun.COM 	    pgoff < eoff; /* empty */) {
17860Sstevel@tonic-gate 		page_t	*pp;
17870Sstevel@tonic-gate 		u_offset_t	nextrio;
17880Sstevel@tonic-gate 		se_t	se;
17890Sstevel@tonic-gate 
17900Sstevel@tonic-gate 		se = ((rw == S_CREATE) ? SE_EXCL : SE_SHARED);
17910Sstevel@tonic-gate 
17920Sstevel@tonic-gate 		/*
17930Sstevel@tonic-gate 		 * Handle async getpage (faultahead)
17940Sstevel@tonic-gate 		 */
17950Sstevel@tonic-gate 		if (plarr == NULL) {
17960Sstevel@tonic-gate 			ip->i_nextrio = pgoff;
17970Sstevel@tonic-gate 			ud_getpage_ra(vp, pgoff, seg, pgaddr);
17980Sstevel@tonic-gate 			pgoff += pgsize;
17990Sstevel@tonic-gate 			pgaddr += pgsize;
18000Sstevel@tonic-gate 			continue;
18010Sstevel@tonic-gate 		}
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 		/*
18040Sstevel@tonic-gate 		 * Check if we should initiate read ahead of next cluster.
18050Sstevel@tonic-gate 		 * We call page_exists only when we need to confirm that
18060Sstevel@tonic-gate 		 * we have the current page before we initiate the read ahead.
18070Sstevel@tonic-gate 		 */
18080Sstevel@tonic-gate 		nextrio = ip->i_nextrio;
18090Sstevel@tonic-gate 		if (seqmode &&
18100Sstevel@tonic-gate 		    pgoff + RD_CLUSTSZ(ip) >= nextrio && pgoff <= nextrio &&
18110Sstevel@tonic-gate 		    nextrio < ip->i_size && page_exists(vp, pgoff))
18120Sstevel@tonic-gate 			ud_getpage_ra(vp, pgoff, seg, pgaddr);
18130Sstevel@tonic-gate 
18140Sstevel@tonic-gate 		if ((pp = page_lookup(vp, pgoff, se)) != NULL) {
18150Sstevel@tonic-gate 
18160Sstevel@tonic-gate 			/*
18170Sstevel@tonic-gate 			 * We found the page in the page cache.
18180Sstevel@tonic-gate 			 */
18190Sstevel@tonic-gate 			*pl++ = pp;
18200Sstevel@tonic-gate 			pgoff += pgsize;
18210Sstevel@tonic-gate 			pgaddr += pgsize;
18220Sstevel@tonic-gate 			len -= pgsize;
18230Sstevel@tonic-gate 			plsz -= pgsize;
18240Sstevel@tonic-gate 		} else  {
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate 			/*
18270Sstevel@tonic-gate 			 * We have to create the page, or read it from disk.
18280Sstevel@tonic-gate 			 */
18290Sstevel@tonic-gate 			if (error = ud_getpage_miss(vp, pgoff, len,
18308059SDonghai.Qiao@Sun.COM 			    seg, pgaddr, pl, plsz, rw, seqmode)) {
18310Sstevel@tonic-gate 				goto error_out;
18320Sstevel@tonic-gate 			}
18330Sstevel@tonic-gate 
18340Sstevel@tonic-gate 			while (*pl != NULL) {
18350Sstevel@tonic-gate 				pl++;
18360Sstevel@tonic-gate 				pgoff += pgsize;
18370Sstevel@tonic-gate 				pgaddr += pgsize;
18380Sstevel@tonic-gate 				len -= pgsize;
18390Sstevel@tonic-gate 				plsz -= pgsize;
18400Sstevel@tonic-gate 			}
18410Sstevel@tonic-gate 		}
18420Sstevel@tonic-gate 	}
18430Sstevel@tonic-gate 
18440Sstevel@tonic-gate 	/*
18450Sstevel@tonic-gate 	 * Return pages up to plsz if they are in the page cache.
18460Sstevel@tonic-gate 	 * We cannot return pages if there is a chance that they are
18470Sstevel@tonic-gate 	 * backed with a UDF hole and rw is S_WRITE or S_CREATE.
18480Sstevel@tonic-gate 	 */
18490Sstevel@tonic-gate 	if (plarr && !(has_holes && (rw == S_WRITE || rw == S_CREATE))) {
18500Sstevel@tonic-gate 
18510Sstevel@tonic-gate 		ASSERT((protp == NULL) ||
18528059SDonghai.Qiao@Sun.COM 		    !(has_holes && (*protp & PROT_WRITE)));
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 		eoff = pgoff + plsz;
18550Sstevel@tonic-gate 		while (pgoff < eoff) {
18560Sstevel@tonic-gate 			page_t		*pp;
18570Sstevel@tonic-gate 
18580Sstevel@tonic-gate 			if ((pp = page_lookup_nowait(vp, pgoff,
18590Sstevel@tonic-gate 			    SE_SHARED)) == NULL)
18600Sstevel@tonic-gate 				break;
18610Sstevel@tonic-gate 
18620Sstevel@tonic-gate 			*pl++ = pp;
18630Sstevel@tonic-gate 			pgoff += pgsize;
18640Sstevel@tonic-gate 			plsz -= pgsize;
18650Sstevel@tonic-gate 		}
18660Sstevel@tonic-gate 	}
18670Sstevel@tonic-gate 
18680Sstevel@tonic-gate 	if (plarr)
18690Sstevel@tonic-gate 		*pl = NULL;			/* Terminate page list */
18700Sstevel@tonic-gate 	ip->i_nextr = pgoff;
18710Sstevel@tonic-gate 
18720Sstevel@tonic-gate error_out:
18730Sstevel@tonic-gate 	if (error && plarr) {
18740Sstevel@tonic-gate 		/*
18750Sstevel@tonic-gate 		 * Release any pages we have locked.
18760Sstevel@tonic-gate 		 */
18770Sstevel@tonic-gate 		while (pl > &plarr[0])
18780Sstevel@tonic-gate 			page_unlock(*--pl);
18790Sstevel@tonic-gate 
18800Sstevel@tonic-gate 		plarr[0] = NULL;
18810Sstevel@tonic-gate 	}
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate update_inode:
18840Sstevel@tonic-gate #ifdef	__lock_lint
18850Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
18860Sstevel@tonic-gate #else
18870Sstevel@tonic-gate 	if (dolock) {
18880Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
18890Sstevel@tonic-gate 	}
18900Sstevel@tonic-gate #endif
18910Sstevel@tonic-gate 
18920Sstevel@tonic-gate 	/*
18930Sstevel@tonic-gate 	 * If the inode is not already marked for IACC (in rwip() for read)
18940Sstevel@tonic-gate 	 * and the inode is not marked for no access time update (in rwip()
18950Sstevel@tonic-gate 	 * for write) then update the inode access time and mod time now.
18960Sstevel@tonic-gate 	 */
18970Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
18980Sstevel@tonic-gate 	if ((ip->i_flag & (IACC | INOACC)) == 0) {
18990Sstevel@tonic-gate 		if ((rw != S_OTHER) && (ip->i_type != VDIR)) {
19000Sstevel@tonic-gate 			ip->i_flag |= IACC;
19010Sstevel@tonic-gate 		}
19020Sstevel@tonic-gate 		if (rw == S_WRITE) {
19030Sstevel@tonic-gate 			ip->i_flag |= IUPD;
19040Sstevel@tonic-gate 		}
19050Sstevel@tonic-gate 		ITIMES_NOLOCK(ip);
19060Sstevel@tonic-gate 	}
19070Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
19080Sstevel@tonic-gate 
19090Sstevel@tonic-gate 	return (error);
19100Sstevel@tonic-gate }
19110Sstevel@tonic-gate 
19120Sstevel@tonic-gate int32_t ud_delay = 1;
19130Sstevel@tonic-gate 
19140Sstevel@tonic-gate /* ARGSUSED */
19150Sstevel@tonic-gate static int32_t
udf_putpage(struct vnode * vp,offset_t off,size_t len,int32_t flags,struct cred * cr,caller_context_t * ct)19165331Samw udf_putpage(
19175331Samw 	struct vnode *vp,
19185331Samw 	offset_t off,
19195331Samw 	size_t len,
19205331Samw 	int32_t flags,
19215331Samw 	struct cred *cr,
19225331Samw 	caller_context_t *ct)
19230Sstevel@tonic-gate {
19240Sstevel@tonic-gate 	struct ud_inode *ip;
19250Sstevel@tonic-gate 	int32_t error = 0;
19260Sstevel@tonic-gate 
19270Sstevel@tonic-gate 	ud_printf("udf_putpage\n");
19280Sstevel@tonic-gate 
19290Sstevel@tonic-gate 	ip = VTOI(vp);
19300Sstevel@tonic-gate #ifdef	__lock_lint
19310Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_WRITER);
19320Sstevel@tonic-gate #endif
19330Sstevel@tonic-gate 
19340Sstevel@tonic-gate 	if (vp->v_count == 0) {
19350Sstevel@tonic-gate 		cmn_err(CE_WARN, "ud_putpage : bad v_count");
19360Sstevel@tonic-gate 		error = EINVAL;
19370Sstevel@tonic-gate 		goto out;
19380Sstevel@tonic-gate 	}
19390Sstevel@tonic-gate 
19400Sstevel@tonic-gate 	if (vp->v_flag & VNOMAP) {
19410Sstevel@tonic-gate 		error = ENOSYS;
19420Sstevel@tonic-gate 		goto out;
19430Sstevel@tonic-gate 	}
19440Sstevel@tonic-gate 
19450Sstevel@tonic-gate 	if (flags & B_ASYNC) {
19460Sstevel@tonic-gate 		if (ud_delay && len &&
19470Sstevel@tonic-gate 		    (flags & ~(B_ASYNC|B_DONTNEED|B_FREE)) == 0) {
19480Sstevel@tonic-gate 			mutex_enter(&ip->i_tlock);
19490Sstevel@tonic-gate 
19500Sstevel@tonic-gate 			/*
19510Sstevel@tonic-gate 			 * If nobody stalled, start a new cluster.
19520Sstevel@tonic-gate 			 */
19530Sstevel@tonic-gate 			if (ip->i_delaylen == 0) {
19540Sstevel@tonic-gate 				ip->i_delayoff = off;
19550Sstevel@tonic-gate 				ip->i_delaylen = len;
19560Sstevel@tonic-gate 				mutex_exit(&ip->i_tlock);
19570Sstevel@tonic-gate 				goto out;
19580Sstevel@tonic-gate 			}
19590Sstevel@tonic-gate 
19600Sstevel@tonic-gate 			/*
19610Sstevel@tonic-gate 			 * If we have a full cluster or they are not contig,
19620Sstevel@tonic-gate 			 * then push last cluster and start over.
19630Sstevel@tonic-gate 			 */
19640Sstevel@tonic-gate 			if (ip->i_delaylen >= WR_CLUSTSZ(ip) ||
19650Sstevel@tonic-gate 			    ip->i_delayoff + ip->i_delaylen != off) {
19660Sstevel@tonic-gate 				u_offset_t doff;
19670Sstevel@tonic-gate 				size_t dlen;
19680Sstevel@tonic-gate 
19690Sstevel@tonic-gate 				doff = ip->i_delayoff;
19700Sstevel@tonic-gate 				dlen = ip->i_delaylen;
19710Sstevel@tonic-gate 				ip->i_delayoff = off;
19720Sstevel@tonic-gate 				ip->i_delaylen = len;
19730Sstevel@tonic-gate 				mutex_exit(&ip->i_tlock);
19740Sstevel@tonic-gate 				error = ud_putpages(vp, doff, dlen, flags, cr);
19750Sstevel@tonic-gate 				/* LMXXX - flags are new val, not old */
19760Sstevel@tonic-gate 				goto out;
19770Sstevel@tonic-gate 			}
19780Sstevel@tonic-gate 
19790Sstevel@tonic-gate 			/*
19800Sstevel@tonic-gate 			 * There is something there, it's not full, and
19810Sstevel@tonic-gate 			 * it is contig.
19820Sstevel@tonic-gate 			 */
19830Sstevel@tonic-gate 			ip->i_delaylen += len;
19840Sstevel@tonic-gate 			mutex_exit(&ip->i_tlock);
19850Sstevel@tonic-gate 			goto out;
19860Sstevel@tonic-gate 		}
19870Sstevel@tonic-gate 
19880Sstevel@tonic-gate 		/*
19890Sstevel@tonic-gate 		 * Must have weird flags or we are not clustering.
19900Sstevel@tonic-gate 		 */
19910Sstevel@tonic-gate 	}
19920Sstevel@tonic-gate 
19930Sstevel@tonic-gate 	error = ud_putpages(vp, off, len, flags, cr);
19940Sstevel@tonic-gate 
19950Sstevel@tonic-gate out:
19960Sstevel@tonic-gate #ifdef	__lock_lint
19970Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
19980Sstevel@tonic-gate #endif
19990Sstevel@tonic-gate 	return (error);
20000Sstevel@tonic-gate }
20010Sstevel@tonic-gate 
20025331Samw /* ARGSUSED */
20030Sstevel@tonic-gate static int32_t
udf_map(struct vnode * vp,offset_t off,struct as * as,caddr_t * addrp,size_t len,uint8_t prot,uint8_t maxprot,uint32_t flags,struct cred * cr,caller_context_t * ct)20045331Samw udf_map(
20055331Samw 	struct vnode *vp,
20065331Samw 	offset_t off,
20075331Samw 	struct as *as,
20085331Samw 	caddr_t *addrp,
20095331Samw 	size_t len,
20105331Samw 	uint8_t prot,
20115331Samw 	uint8_t maxprot,
20125331Samw 	uint32_t flags,
20135331Samw 	struct cred *cr,
20145331Samw 	caller_context_t *ct)
20150Sstevel@tonic-gate {
20160Sstevel@tonic-gate 	struct segvn_crargs vn_a;
20170Sstevel@tonic-gate 	int32_t error = 0;
20180Sstevel@tonic-gate 
20190Sstevel@tonic-gate 	ud_printf("udf_map\n");
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate 	if (vp->v_flag & VNOMAP) {
20220Sstevel@tonic-gate 		error = ENOSYS;
20230Sstevel@tonic-gate 		goto end;
20240Sstevel@tonic-gate 	}
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate 	if ((off < (offset_t)0) ||
20278059SDonghai.Qiao@Sun.COM 	    ((off + len) < (offset_t)0)) {
20280Sstevel@tonic-gate 		error = EINVAL;
20290Sstevel@tonic-gate 		goto end;
20300Sstevel@tonic-gate 	}
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate 	if (vp->v_type != VREG) {
20330Sstevel@tonic-gate 		error = ENODEV;
20340Sstevel@tonic-gate 		goto end;
20350Sstevel@tonic-gate 	}
20360Sstevel@tonic-gate 
20370Sstevel@tonic-gate 	/*
20380Sstevel@tonic-gate 	 * If file is being locked, disallow mapping.
20390Sstevel@tonic-gate 	 */
20400Sstevel@tonic-gate 	if (vn_has_mandatory_locks(vp, VTOI(vp)->i_char)) {
20410Sstevel@tonic-gate 		error = EAGAIN;
20420Sstevel@tonic-gate 		goto end;
20430Sstevel@tonic-gate 	}
20440Sstevel@tonic-gate 
20450Sstevel@tonic-gate 	as_rangelock(as);
20466036Smec 	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
20476036Smec 	if (error != 0) {
20486036Smec 		as_rangeunlock(as);
20496036Smec 		goto end;
20500Sstevel@tonic-gate 	}
20510Sstevel@tonic-gate 
20520Sstevel@tonic-gate 	vn_a.vp = vp;
20530Sstevel@tonic-gate 	vn_a.offset = off;
20540Sstevel@tonic-gate 	vn_a.type = flags & MAP_TYPE;
20550Sstevel@tonic-gate 	vn_a.prot = prot;
20560Sstevel@tonic-gate 	vn_a.maxprot = maxprot;
20570Sstevel@tonic-gate 	vn_a.cred = cr;
20580Sstevel@tonic-gate 	vn_a.amp = NULL;
20590Sstevel@tonic-gate 	vn_a.flags = flags & ~MAP_TYPE;
20600Sstevel@tonic-gate 	vn_a.szc = 0;
20610Sstevel@tonic-gate 	vn_a.lgrp_mem_policy_flags = 0;
20620Sstevel@tonic-gate 
20630Sstevel@tonic-gate 	error = as_map(as, *addrp, len, segvn_create, (caddr_t)&vn_a);
20640Sstevel@tonic-gate 	as_rangeunlock(as);
20650Sstevel@tonic-gate 
20660Sstevel@tonic-gate end:
20670Sstevel@tonic-gate 	return (error);
20680Sstevel@tonic-gate }
20690Sstevel@tonic-gate 
20700Sstevel@tonic-gate /* ARGSUSED */
20710Sstevel@tonic-gate static int32_t
udf_addmap(struct vnode * vp,offset_t off,struct as * as,caddr_t addr,size_t len,uint8_t prot,uint8_t maxprot,uint32_t flags,struct cred * cr,caller_context_t * ct)20725331Samw udf_addmap(struct vnode *vp,
20735331Samw 	offset_t off,
20745331Samw 	struct as *as,
20755331Samw 	caddr_t addr,
20765331Samw 	size_t len,
20775331Samw 	uint8_t prot,
20785331Samw 	uint8_t maxprot,
20795331Samw 	uint32_t flags,
20805331Samw 	struct cred *cr,
20815331Samw 	caller_context_t *ct)
20820Sstevel@tonic-gate {
20830Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate 	ud_printf("udf_addmap\n");
20860Sstevel@tonic-gate 
20870Sstevel@tonic-gate 	if (vp->v_flag & VNOMAP) {
20880Sstevel@tonic-gate 		return (ENOSYS);
20890Sstevel@tonic-gate 	}
20900Sstevel@tonic-gate 
20910Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
20920Sstevel@tonic-gate 	ip->i_mapcnt += btopr(len);
20930Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
20940Sstevel@tonic-gate 
20950Sstevel@tonic-gate 	return (0);
20960Sstevel@tonic-gate }
20970Sstevel@tonic-gate 
20980Sstevel@tonic-gate /* ARGSUSED */
20990Sstevel@tonic-gate static int32_t
udf_delmap(struct vnode * vp,offset_t off,struct as * as,caddr_t addr,size_t len,uint32_t prot,uint32_t maxprot,uint32_t flags,struct cred * cr,caller_context_t * ct)21005331Samw udf_delmap(
21015331Samw 	struct vnode *vp, offset_t off,
21025331Samw 	struct as *as,
21035331Samw 	caddr_t addr,
21045331Samw 	size_t len,
21055331Samw 	uint32_t prot,
21065331Samw 	uint32_t maxprot,
21075331Samw 	uint32_t flags,
21085331Samw 	struct cred *cr,
21095331Samw 	caller_context_t *ct)
21100Sstevel@tonic-gate {
21110Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
21120Sstevel@tonic-gate 
21130Sstevel@tonic-gate 	ud_printf("udf_delmap\n");
21140Sstevel@tonic-gate 
21150Sstevel@tonic-gate 	if (vp->v_flag & VNOMAP) {
21160Sstevel@tonic-gate 		return (ENOSYS);
21170Sstevel@tonic-gate 	}
21180Sstevel@tonic-gate 
21190Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
21200Sstevel@tonic-gate 	ip->i_mapcnt -= btopr(len); 	/* Count released mappings */
21210Sstevel@tonic-gate 	ASSERT(ip->i_mapcnt >= 0);
21220Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
21230Sstevel@tonic-gate 
21240Sstevel@tonic-gate 	return (0);
21250Sstevel@tonic-gate }
21260Sstevel@tonic-gate 
21275331Samw /* ARGSUSED */
21280Sstevel@tonic-gate static int32_t
udf_l_pathconf(struct vnode * vp,int32_t cmd,ulong_t * valp,struct cred * cr,caller_context_t * ct)21295331Samw udf_l_pathconf(
21305331Samw 	struct vnode *vp,
21315331Samw 	int32_t cmd,
21325331Samw 	ulong_t *valp,
21335331Samw 	struct cred *cr,
21345331Samw 	caller_context_t *ct)
21350Sstevel@tonic-gate {
21360Sstevel@tonic-gate 	int32_t error = 0;
21370Sstevel@tonic-gate 
21380Sstevel@tonic-gate 	ud_printf("udf_l_pathconf\n");
21390Sstevel@tonic-gate 
21400Sstevel@tonic-gate 	if (cmd == _PC_FILESIZEBITS) {
21410Sstevel@tonic-gate 		/*
21420Sstevel@tonic-gate 		 * udf supports 64 bits as file size
21430Sstevel@tonic-gate 		 * but there are several other restrictions
21440Sstevel@tonic-gate 		 * it only supports 32-bit block numbers and
21450Sstevel@tonic-gate 		 * daddr32_t is only and int32_t so taking these
21460Sstevel@tonic-gate 		 * into account we can stay just as where ufs is
21470Sstevel@tonic-gate 		 */
21480Sstevel@tonic-gate 		*valp = 41;
214910440SRoger.Faulkner@Sun.COM 	} else if (cmd == _PC_TIMESTAMP_RESOLUTION) {
215010440SRoger.Faulkner@Sun.COM 		/* nanosecond timestamp resolution */
215110440SRoger.Faulkner@Sun.COM 		*valp = 1L;
21520Sstevel@tonic-gate 	} else {
21535331Samw 		error = fs_pathconf(vp, cmd, valp, cr, ct);
21540Sstevel@tonic-gate 	}
21550Sstevel@tonic-gate 
21560Sstevel@tonic-gate 	return (error);
21570Sstevel@tonic-gate }
21580Sstevel@tonic-gate 
21590Sstevel@tonic-gate uint32_t ud_pageio_reads = 0, ud_pageio_writes = 0;
21600Sstevel@tonic-gate #ifndef	__lint
21610Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("safe sharing", ud_pageio_reads))
21620Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("safe sharing", ud_pageio_writes))
21630Sstevel@tonic-gate #endif
21640Sstevel@tonic-gate /*
21650Sstevel@tonic-gate  * Assumption is that there will not be a pageio request
21660Sstevel@tonic-gate  * to a enbedded file
21670Sstevel@tonic-gate  */
21680Sstevel@tonic-gate /* ARGSUSED */
21690Sstevel@tonic-gate static int32_t
udf_pageio(struct vnode * vp,struct page * pp,u_offset_t io_off,size_t io_len,int32_t flags,struct cred * cr,caller_context_t * ct)21705331Samw udf_pageio(
21715331Samw 	struct vnode *vp,
21725331Samw 	struct page *pp,
21735331Samw 	u_offset_t io_off,
21745331Samw 	size_t io_len,
21755331Samw 	int32_t flags,
21765331Samw 	struct cred *cr,
21775331Samw 	caller_context_t *ct)
21780Sstevel@tonic-gate {
21790Sstevel@tonic-gate 	daddr_t bn;
21800Sstevel@tonic-gate 	struct buf *bp;
21810Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
21820Sstevel@tonic-gate 	int32_t dolock, error = 0, contig, multi_io;
21830Sstevel@tonic-gate 	size_t done_len = 0, cur_len = 0;
21840Sstevel@tonic-gate 	page_t *npp = NULL, *opp = NULL, *cpp = pp;
21850Sstevel@tonic-gate 
21860Sstevel@tonic-gate 	if (pp == NULL) {
21870Sstevel@tonic-gate 		return (EINVAL);
21880Sstevel@tonic-gate 	}
21890Sstevel@tonic-gate 
21900Sstevel@tonic-gate 	dolock = (rw_owner(&ip->i_contents) != curthread);
21910Sstevel@tonic-gate 
21920Sstevel@tonic-gate 	/*
21930Sstevel@tonic-gate 	 * We need a better check.  Ideally, we would use another
21940Sstevel@tonic-gate 	 * vnodeops so that hlocked and forcibly unmounted file
21950Sstevel@tonic-gate 	 * systems would return EIO where appropriate and w/o the
21960Sstevel@tonic-gate 	 * need for these checks.
21970Sstevel@tonic-gate 	 */
21980Sstevel@tonic-gate 	if (ip->i_udf == NULL) {
21990Sstevel@tonic-gate 		return (EIO);
22000Sstevel@tonic-gate 	}
22010Sstevel@tonic-gate 
22020Sstevel@tonic-gate #ifdef	__lock_lint
22030Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_READER);
22040Sstevel@tonic-gate #else
22050Sstevel@tonic-gate 	if (dolock) {
22060Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_READER);
22070Sstevel@tonic-gate 	}
22080Sstevel@tonic-gate #endif
22090Sstevel@tonic-gate 
22100Sstevel@tonic-gate 	/*
22110Sstevel@tonic-gate 	 * Break the io request into chunks, one for each contiguous
22120Sstevel@tonic-gate 	 * stretch of disk blocks in the target file.
22130Sstevel@tonic-gate 	 */
22140Sstevel@tonic-gate 	while (done_len < io_len) {
22150Sstevel@tonic-gate 		ASSERT(cpp);
22160Sstevel@tonic-gate 		bp = NULL;
22170Sstevel@tonic-gate 		contig = 0;
22180Sstevel@tonic-gate 		if (error = ud_bmap_read(ip, (u_offset_t)(io_off + done_len),
22198059SDonghai.Qiao@Sun.COM 		    &bn, &contig)) {
22200Sstevel@tonic-gate 			break;
22210Sstevel@tonic-gate 		}
22220Sstevel@tonic-gate 
22230Sstevel@tonic-gate 		if (bn == UDF_HOLE) {   /* No holey swapfiles */
22240Sstevel@tonic-gate 			cmn_err(CE_WARN, "SWAP file has HOLES");
22250Sstevel@tonic-gate 			error = EINVAL;
22260Sstevel@tonic-gate 			break;
22270Sstevel@tonic-gate 		}
22280Sstevel@tonic-gate 
22290Sstevel@tonic-gate 		cur_len = MIN(io_len - done_len, contig);
22300Sstevel@tonic-gate 
22310Sstevel@tonic-gate 		/*
22320Sstevel@tonic-gate 		 * Check if more than one I/O is
22330Sstevel@tonic-gate 		 * required to complete the given
22340Sstevel@tonic-gate 		 * I/O operation
22350Sstevel@tonic-gate 		 */
22360Sstevel@tonic-gate 		if (ip->i_udf->udf_lbsize < PAGESIZE) {
22370Sstevel@tonic-gate 			if (cur_len >= PAGESIZE) {
22380Sstevel@tonic-gate 				multi_io = 0;
22390Sstevel@tonic-gate 				cur_len &= PAGEMASK;
22400Sstevel@tonic-gate 			} else {
22410Sstevel@tonic-gate 				multi_io = 1;
22420Sstevel@tonic-gate 				cur_len = MIN(io_len - done_len, PAGESIZE);
22430Sstevel@tonic-gate 			}
22440Sstevel@tonic-gate 		}
22450Sstevel@tonic-gate 		page_list_break(&cpp, &npp, btop(cur_len));
22460Sstevel@tonic-gate 
22470Sstevel@tonic-gate 		bp = pageio_setup(cpp, cur_len, ip->i_devvp, flags);
22480Sstevel@tonic-gate 		ASSERT(bp != NULL);
22490Sstevel@tonic-gate 
22500Sstevel@tonic-gate 		bp->b_edev = ip->i_dev;
22510Sstevel@tonic-gate 		bp->b_dev = cmpdev(ip->i_dev);
22520Sstevel@tonic-gate 		bp->b_blkno = bn;
22530Sstevel@tonic-gate 		bp->b_un.b_addr = (caddr_t)0;
22540Sstevel@tonic-gate 		bp->b_file = vp;
22550Sstevel@tonic-gate 		bp->b_offset = (offset_t)(io_off + done_len);
22560Sstevel@tonic-gate 
22570Sstevel@tonic-gate /*
22580Sstevel@tonic-gate  *		ub.ub_pageios.value.ul++;
22590Sstevel@tonic-gate  */
22600Sstevel@tonic-gate 		if (multi_io == 0) {
22610Sstevel@tonic-gate 			(void) bdev_strategy(bp);
22620Sstevel@tonic-gate 		} else {
22630Sstevel@tonic-gate 			error = ud_multi_strat(ip, cpp, bp,
22648059SDonghai.Qiao@Sun.COM 			    (u_offset_t)(io_off + done_len));
22650Sstevel@tonic-gate 			if (error != 0) {
22660Sstevel@tonic-gate 				pageio_done(bp);
22670Sstevel@tonic-gate 				break;
22680Sstevel@tonic-gate 			}
22690Sstevel@tonic-gate 		}
22700Sstevel@tonic-gate 		if (flags & B_READ) {
22710Sstevel@tonic-gate 			ud_pageio_reads++;
22720Sstevel@tonic-gate 		} else {
22730Sstevel@tonic-gate 			ud_pageio_writes++;
22740Sstevel@tonic-gate 		}
22750Sstevel@tonic-gate 
22760Sstevel@tonic-gate 		/*
22770Sstevel@tonic-gate 		 * If the request is not B_ASYNC, wait for i/o to complete
22780Sstevel@tonic-gate 		 * and re-assemble the page list to return to the caller.
22790Sstevel@tonic-gate 		 * If it is B_ASYNC we leave the page list in pieces and
22800Sstevel@tonic-gate 		 * cleanup() will dispose of them.
22810Sstevel@tonic-gate 		 */
22820Sstevel@tonic-gate 		if ((flags & B_ASYNC) == 0) {
22830Sstevel@tonic-gate 			error = biowait(bp);
22840Sstevel@tonic-gate 			pageio_done(bp);
22850Sstevel@tonic-gate 			if (error) {
22860Sstevel@tonic-gate 				break;
22870Sstevel@tonic-gate 			}
22880Sstevel@tonic-gate 			page_list_concat(&opp, &cpp);
22890Sstevel@tonic-gate 		}
22900Sstevel@tonic-gate 		cpp = npp;
22910Sstevel@tonic-gate 		npp = NULL;
22920Sstevel@tonic-gate 		done_len += cur_len;
22930Sstevel@tonic-gate 	}
22940Sstevel@tonic-gate 
22950Sstevel@tonic-gate 	ASSERT(error || (cpp == NULL && npp == NULL && done_len == io_len));
22960Sstevel@tonic-gate 	if (error) {
22970Sstevel@tonic-gate 		if (flags & B_ASYNC) {
22980Sstevel@tonic-gate 			/* Cleanup unprocessed parts of list */
22990Sstevel@tonic-gate 			page_list_concat(&cpp, &npp);
23000Sstevel@tonic-gate 			if (flags & B_READ) {
23010Sstevel@tonic-gate 				pvn_read_done(cpp, B_ERROR);
23020Sstevel@tonic-gate 			} else {
23030Sstevel@tonic-gate 				pvn_write_done(cpp, B_ERROR);
23040Sstevel@tonic-gate 			}
23050Sstevel@tonic-gate 		} else {
23060Sstevel@tonic-gate 			/* Re-assemble list and let caller clean up */
23070Sstevel@tonic-gate 			page_list_concat(&opp, &cpp);
23080Sstevel@tonic-gate 			page_list_concat(&opp, &npp);
23090Sstevel@tonic-gate 		}
23100Sstevel@tonic-gate 	}
23110Sstevel@tonic-gate 
23120Sstevel@tonic-gate #ifdef	__lock_lint
23130Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
23140Sstevel@tonic-gate #else
23150Sstevel@tonic-gate 	if (dolock) {
23160Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
23170Sstevel@tonic-gate 	}
23180Sstevel@tonic-gate #endif
23190Sstevel@tonic-gate 	return (error);
23200Sstevel@tonic-gate }
23210Sstevel@tonic-gate 
23220Sstevel@tonic-gate 
23230Sstevel@tonic-gate 
23240Sstevel@tonic-gate 
23250Sstevel@tonic-gate /* -------------------- local functions --------------------------- */
23260Sstevel@tonic-gate 
23270Sstevel@tonic-gate 
23280Sstevel@tonic-gate 
23290Sstevel@tonic-gate int32_t
ud_rdwri(enum uio_rw rw,int32_t ioflag,struct ud_inode * ip,caddr_t base,int32_t len,offset_t offset,enum uio_seg seg,int32_t * aresid,struct cred * cr)23300Sstevel@tonic-gate ud_rdwri(enum uio_rw rw, int32_t ioflag,
23310Sstevel@tonic-gate 	struct ud_inode *ip, caddr_t base, int32_t len,
23320Sstevel@tonic-gate 	offset_t offset, enum uio_seg seg, int32_t *aresid, struct cred *cr)
23330Sstevel@tonic-gate {
23340Sstevel@tonic-gate 	int32_t error;
23350Sstevel@tonic-gate 	struct uio auio;
23360Sstevel@tonic-gate 	struct iovec aiov;
23370Sstevel@tonic-gate 
23380Sstevel@tonic-gate 	ud_printf("ud_rdwri\n");
23390Sstevel@tonic-gate 
23400Sstevel@tonic-gate 	bzero((caddr_t)&auio, sizeof (uio_t));
23410Sstevel@tonic-gate 	bzero((caddr_t)&aiov, sizeof (iovec_t));
23420Sstevel@tonic-gate 
23430Sstevel@tonic-gate 	aiov.iov_base = base;
23440Sstevel@tonic-gate 	aiov.iov_len = len;
23450Sstevel@tonic-gate 	auio.uio_iov = &aiov;
23460Sstevel@tonic-gate 	auio.uio_iovcnt = 1;
23470Sstevel@tonic-gate 	auio.uio_loffset = offset;
23480Sstevel@tonic-gate 	auio.uio_segflg = (int16_t)seg;
23490Sstevel@tonic-gate 	auio.uio_resid = len;
23500Sstevel@tonic-gate 
23510Sstevel@tonic-gate 	if (rw == UIO_WRITE) {
23520Sstevel@tonic-gate 		auio.uio_fmode = FWRITE;
23530Sstevel@tonic-gate 		auio.uio_extflg = UIO_COPY_DEFAULT;
23540Sstevel@tonic-gate 		auio.uio_llimit = curproc->p_fsz_ctl;
23550Sstevel@tonic-gate 		error = ud_wrip(ip, &auio, ioflag, cr);
23560Sstevel@tonic-gate 	} else {
23570Sstevel@tonic-gate 		auio.uio_fmode = FREAD;
23580Sstevel@tonic-gate 		auio.uio_extflg = UIO_COPY_CACHED;
23590Sstevel@tonic-gate 		auio.uio_llimit = MAXOFFSET_T;
23600Sstevel@tonic-gate 		error = ud_rdip(ip, &auio, ioflag, cr);
23610Sstevel@tonic-gate 	}
23620Sstevel@tonic-gate 
23630Sstevel@tonic-gate 	if (aresid) {
23640Sstevel@tonic-gate 		*aresid = auio.uio_resid;
23650Sstevel@tonic-gate 	} else if (auio.uio_resid) {
23660Sstevel@tonic-gate 		error = EIO;
23670Sstevel@tonic-gate 	}
23680Sstevel@tonic-gate 	return (error);
23690Sstevel@tonic-gate }
23700Sstevel@tonic-gate 
23710Sstevel@tonic-gate /*
23720Sstevel@tonic-gate  * Free behind hacks.  The pager is busted.
23730Sstevel@tonic-gate  * XXX - need to pass the information down to writedone() in a flag like B_SEQ
23740Sstevel@tonic-gate  * or B_FREE_IF_TIGHT_ON_MEMORY.
23750Sstevel@tonic-gate  */
23760Sstevel@tonic-gate int32_t ud_freebehind = 1;
23770Sstevel@tonic-gate int32_t ud_smallfile = 32 * 1024;
23780Sstevel@tonic-gate 
23790Sstevel@tonic-gate /* ARGSUSED */
23800Sstevel@tonic-gate int32_t
ud_getpage_miss(struct vnode * vp,u_offset_t off,size_t len,struct seg * seg,caddr_t addr,page_t * pl[],size_t plsz,enum seg_rw rw,int32_t seq)23810Sstevel@tonic-gate ud_getpage_miss(struct vnode *vp, u_offset_t off,
23820Sstevel@tonic-gate 	size_t len, struct seg *seg, caddr_t addr, page_t *pl[],
23830Sstevel@tonic-gate 	size_t plsz, enum seg_rw rw, int32_t seq)
23840Sstevel@tonic-gate {
23850Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
23860Sstevel@tonic-gate 	int32_t err = 0;
23870Sstevel@tonic-gate 	size_t io_len;
23880Sstevel@tonic-gate 	u_offset_t io_off;
23890Sstevel@tonic-gate 	u_offset_t pgoff;
23900Sstevel@tonic-gate 	page_t *pp;
23910Sstevel@tonic-gate 
23920Sstevel@tonic-gate 	pl[0] = NULL;
23930Sstevel@tonic-gate 
23940Sstevel@tonic-gate 	/*
23950Sstevel@tonic-gate 	 * Figure out whether the page can be created, or must be
23960Sstevel@tonic-gate 	 * read from the disk
23970Sstevel@tonic-gate 	 */
23980Sstevel@tonic-gate 	if (rw == S_CREATE) {
23990Sstevel@tonic-gate 		if ((pp = page_create_va(vp, off,
24008059SDonghai.Qiao@Sun.COM 		    PAGESIZE, PG_WAIT, seg, addr)) == NULL) {
24010Sstevel@tonic-gate 			cmn_err(CE_WARN, "ud_getpage_miss: page_create");
24020Sstevel@tonic-gate 			return (EINVAL);
24030Sstevel@tonic-gate 		}
24040Sstevel@tonic-gate 		io_len = PAGESIZE;
24050Sstevel@tonic-gate 	} else {
24060Sstevel@tonic-gate 		pp = pvn_read_kluster(vp, off, seg, addr, &io_off,
24078059SDonghai.Qiao@Sun.COM 		    &io_len, off, PAGESIZE, 0);
24080Sstevel@tonic-gate 
24090Sstevel@tonic-gate 		/*
24100Sstevel@tonic-gate 		 * Some other thread has entered the page.
24110Sstevel@tonic-gate 		 * ud_getpage will retry page_lookup.
24120Sstevel@tonic-gate 		 */
24130Sstevel@tonic-gate 		if (pp == NULL) {
24140Sstevel@tonic-gate 			return (0);
24150Sstevel@tonic-gate 		}
24160Sstevel@tonic-gate 
24170Sstevel@tonic-gate 		/*
24180Sstevel@tonic-gate 		 * Fill the page with as much data as we can from the file.
24190Sstevel@tonic-gate 		 */
24200Sstevel@tonic-gate 		err = ud_page_fill(ip, pp, off, B_READ, &pgoff);
24210Sstevel@tonic-gate 		if (err) {
24220Sstevel@tonic-gate 			pvn_read_done(pp, B_ERROR);
24230Sstevel@tonic-gate 			return (err);
24240Sstevel@tonic-gate 		}
24250Sstevel@tonic-gate 
24260Sstevel@tonic-gate 		/*
24270Sstevel@tonic-gate 		 * XXX ??? ufs has io_len instead of pgoff below
24280Sstevel@tonic-gate 		 */
24290Sstevel@tonic-gate 		ip->i_nextrio = off + ((pgoff + PAGESIZE - 1) & PAGEMASK);
24300Sstevel@tonic-gate 
24310Sstevel@tonic-gate 		/*
24320Sstevel@tonic-gate 		 * If the file access is sequential, initiate read ahead
24330Sstevel@tonic-gate 		 * of the next cluster.
24340Sstevel@tonic-gate 		 */
24350Sstevel@tonic-gate 		if (seq && ip->i_nextrio < ip->i_size) {
24360Sstevel@tonic-gate 			ud_getpage_ra(vp, off, seg, addr);
24370Sstevel@tonic-gate 		}
24380Sstevel@tonic-gate 	}
24390Sstevel@tonic-gate 
24400Sstevel@tonic-gate outmiss:
24410Sstevel@tonic-gate 	pvn_plist_init(pp, pl, plsz, (offset_t)off, io_len, rw);
24420Sstevel@tonic-gate 	return (err);
24430Sstevel@tonic-gate }
24440Sstevel@tonic-gate 
24450Sstevel@tonic-gate /* ARGSUSED */
24460Sstevel@tonic-gate void
ud_getpage_ra(struct vnode * vp,u_offset_t off,struct seg * seg,caddr_t addr)24470Sstevel@tonic-gate ud_getpage_ra(struct vnode *vp,
24480Sstevel@tonic-gate 	u_offset_t off, struct seg *seg, caddr_t addr)
24490Sstevel@tonic-gate {
24500Sstevel@tonic-gate 	page_t *pp;
24510Sstevel@tonic-gate 	size_t io_len;
24520Sstevel@tonic-gate 	struct ud_inode *ip = VTOI(vp);
24530Sstevel@tonic-gate 	u_offset_t io_off = ip->i_nextrio, pgoff;
24540Sstevel@tonic-gate 	caddr_t addr2 = addr + (io_off - off);
24550Sstevel@tonic-gate 	daddr_t bn;
24560Sstevel@tonic-gate 	int32_t contig = 0;
24570Sstevel@tonic-gate 
24580Sstevel@tonic-gate 	/*
24590Sstevel@tonic-gate 	 * Is this test needed?
24600Sstevel@tonic-gate 	 */
24610Sstevel@tonic-gate 
24620Sstevel@tonic-gate 	if (addr2 >= seg->s_base + seg->s_size) {
24630Sstevel@tonic-gate 		return;
24640Sstevel@tonic-gate 	}
24650Sstevel@tonic-gate 
24660Sstevel@tonic-gate 	contig = 0;
24670Sstevel@tonic-gate 	if (ud_bmap_read(ip, io_off, &bn, &contig) != 0 || bn == UDF_HOLE) {
24680Sstevel@tonic-gate 		return;
24690Sstevel@tonic-gate 	}
24700Sstevel@tonic-gate 
24710Sstevel@tonic-gate 	pp = pvn_read_kluster(vp, io_off, seg, addr2,
24728059SDonghai.Qiao@Sun.COM 	    &io_off, &io_len, io_off, PAGESIZE, 1);
24730Sstevel@tonic-gate 
24740Sstevel@tonic-gate 	/*
24750Sstevel@tonic-gate 	 * Some other thread has entered the page.
24760Sstevel@tonic-gate 	 * So no read head done here (ie we will have to and wait
24770Sstevel@tonic-gate 	 * for the read when needed).
24780Sstevel@tonic-gate 	 */
24790Sstevel@tonic-gate 
24800Sstevel@tonic-gate 	if (pp == NULL) {
24810Sstevel@tonic-gate 		return;
24820Sstevel@tonic-gate 	}
24830Sstevel@tonic-gate 
24840Sstevel@tonic-gate 	(void) ud_page_fill(ip, pp, io_off, (B_READ|B_ASYNC), &pgoff);
24850Sstevel@tonic-gate 	ip->i_nextrio =  io_off + ((pgoff + PAGESIZE - 1) & PAGEMASK);
24860Sstevel@tonic-gate }
24870Sstevel@tonic-gate 
24880Sstevel@tonic-gate int
ud_page_fill(struct ud_inode * ip,page_t * pp,u_offset_t off,uint32_t bflgs,u_offset_t * pg_off)24890Sstevel@tonic-gate ud_page_fill(struct ud_inode *ip, page_t *pp, u_offset_t off,
24900Sstevel@tonic-gate 	uint32_t bflgs, u_offset_t *pg_off)
24910Sstevel@tonic-gate {
24920Sstevel@tonic-gate 	daddr_t bn;
24930Sstevel@tonic-gate 	struct buf *bp;
24940Sstevel@tonic-gate 	caddr_t kaddr, caddr;
24950Sstevel@tonic-gate 	int32_t error = 0, contig = 0, multi_io = 0;
24960Sstevel@tonic-gate 	int32_t lbsize = ip->i_udf->udf_lbsize;
24970Sstevel@tonic-gate 	int32_t lbmask = ip->i_udf->udf_lbmask;
24980Sstevel@tonic-gate 	uint64_t isize;
24990Sstevel@tonic-gate 
25000Sstevel@tonic-gate 	isize = (ip->i_size + lbmask) & (~lbmask);
25010Sstevel@tonic-gate 	if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
25020Sstevel@tonic-gate 
25030Sstevel@tonic-gate 		/*
25040Sstevel@tonic-gate 		 * Embedded file read file_entry
25050Sstevel@tonic-gate 		 * from buffer cache and copy the required
25060Sstevel@tonic-gate 		 * portions
25070Sstevel@tonic-gate 		 */
25080Sstevel@tonic-gate 		bp = ud_bread(ip->i_dev,
25098059SDonghai.Qiao@Sun.COM 		    ip->i_icb_lbano << ip->i_udf->udf_l2d_shift, lbsize);
25100Sstevel@tonic-gate 		if ((bp->b_error == 0) &&
25118059SDonghai.Qiao@Sun.COM 		    (bp->b_resid == 0)) {
25120Sstevel@tonic-gate 
25130Sstevel@tonic-gate 			caddr = bp->b_un.b_addr + ip->i_data_off;
25140Sstevel@tonic-gate 
25150Sstevel@tonic-gate 			/*
25160Sstevel@tonic-gate 			 * mapin to kvm
25170Sstevel@tonic-gate 			 */
25180Sstevel@tonic-gate 			kaddr = (caddr_t)ppmapin(pp,
25198059SDonghai.Qiao@Sun.COM 			    PROT_READ | PROT_WRITE, (caddr_t)-1);
25200Sstevel@tonic-gate 			(void) kcopy(caddr, kaddr, ip->i_size);
25210Sstevel@tonic-gate 
25220Sstevel@tonic-gate 			/*
25230Sstevel@tonic-gate 			 * mapout of kvm
25240Sstevel@tonic-gate 			 */
25250Sstevel@tonic-gate 			ppmapout(kaddr);
25260Sstevel@tonic-gate 		}
25270Sstevel@tonic-gate 		brelse(bp);
25280Sstevel@tonic-gate 		contig = ip->i_size;
25290Sstevel@tonic-gate 	} else {
25300Sstevel@tonic-gate 
25310Sstevel@tonic-gate 		/*
25320Sstevel@tonic-gate 		 * Get the continuous size and block number
25330Sstevel@tonic-gate 		 * at offset "off"
25340Sstevel@tonic-gate 		 */
25350Sstevel@tonic-gate 		if (error = ud_bmap_read(ip, off, &bn, &contig))
25360Sstevel@tonic-gate 			goto out;
25370Sstevel@tonic-gate 		contig = MIN(contig, PAGESIZE);
25380Sstevel@tonic-gate 		contig = (contig + lbmask) & (~lbmask);
25390Sstevel@tonic-gate 
25400Sstevel@tonic-gate 		/*
25410Sstevel@tonic-gate 		 * Zero part of the page which we are not
25420Sstevel@tonic-gate 		 * going to read from the disk.
25430Sstevel@tonic-gate 		 */
25440Sstevel@tonic-gate 
25450Sstevel@tonic-gate 		if (bn == UDF_HOLE) {
25460Sstevel@tonic-gate 
25470Sstevel@tonic-gate 			/*
25480Sstevel@tonic-gate 			 * This is a HOLE. Just zero out
25490Sstevel@tonic-gate 			 * the page
25500Sstevel@tonic-gate 			 */
25510Sstevel@tonic-gate 			if (((off + contig) == isize) ||
25528059SDonghai.Qiao@Sun.COM 			    (contig == PAGESIZE)) {
25530Sstevel@tonic-gate 				pagezero(pp->p_prev, 0, PAGESIZE);
25540Sstevel@tonic-gate 				goto out;
25550Sstevel@tonic-gate 			}
25560Sstevel@tonic-gate 		}
25570Sstevel@tonic-gate 
25580Sstevel@tonic-gate 		if (contig < PAGESIZE) {
25590Sstevel@tonic-gate 			uint64_t count;
25600Sstevel@tonic-gate 
25610Sstevel@tonic-gate 			count = isize - off;
25620Sstevel@tonic-gate 			if (contig != count) {
25630Sstevel@tonic-gate 				multi_io = 1;
25640Sstevel@tonic-gate 				contig = (int32_t)(MIN(count, PAGESIZE));
25650Sstevel@tonic-gate 			} else {
25660Sstevel@tonic-gate 				pagezero(pp->p_prev, contig, PAGESIZE - contig);
25670Sstevel@tonic-gate 			}
25680Sstevel@tonic-gate 		}
25690Sstevel@tonic-gate 
25700Sstevel@tonic-gate 		/*
25710Sstevel@tonic-gate 		 * Get a bp and initialize it
25720Sstevel@tonic-gate 		 */
25730Sstevel@tonic-gate 		bp = pageio_setup(pp, contig, ip->i_devvp, bflgs);
25740Sstevel@tonic-gate 		ASSERT(bp != NULL);
25750Sstevel@tonic-gate 
25760Sstevel@tonic-gate 		bp->b_edev = ip->i_dev;
25770Sstevel@tonic-gate 		bp->b_dev = cmpdev(ip->i_dev);
25780Sstevel@tonic-gate 		bp->b_blkno = bn;
25790Sstevel@tonic-gate 		bp->b_un.b_addr = 0;
25800Sstevel@tonic-gate 		bp->b_file = ip->i_vnode;
25810Sstevel@tonic-gate 
25820Sstevel@tonic-gate 		/*
25830Sstevel@tonic-gate 		 * Start I/O
25840Sstevel@tonic-gate 		 */
25850Sstevel@tonic-gate 		if (multi_io == 0) {
25860Sstevel@tonic-gate 
25870Sstevel@tonic-gate 			/*
25880Sstevel@tonic-gate 			 * Single I/O is sufficient for this page
25890Sstevel@tonic-gate 			 */
25900Sstevel@tonic-gate 			(void) bdev_strategy(bp);
25910Sstevel@tonic-gate 		} else {
25920Sstevel@tonic-gate 
25930Sstevel@tonic-gate 			/*
25940Sstevel@tonic-gate 			 * We need to do the I/O in
25950Sstevel@tonic-gate 			 * piece's
25960Sstevel@tonic-gate 			 */
25970Sstevel@tonic-gate 			error = ud_multi_strat(ip, pp, bp, off);
25980Sstevel@tonic-gate 			if (error != 0) {
25990Sstevel@tonic-gate 				goto out;
26000Sstevel@tonic-gate 			}
26010Sstevel@tonic-gate 		}
26020Sstevel@tonic-gate 		if ((bflgs & B_ASYNC) == 0) {
26030Sstevel@tonic-gate 
26040Sstevel@tonic-gate 			/*
26050Sstevel@tonic-gate 			 * Wait for i/o to complete.
26060Sstevel@tonic-gate 			 */
26070Sstevel@tonic-gate 
26080Sstevel@tonic-gate 			error = biowait(bp);
26090Sstevel@tonic-gate 			pageio_done(bp);
26100Sstevel@tonic-gate 			if (error) {
26110Sstevel@tonic-gate 				goto out;
26120Sstevel@tonic-gate 			}
26130Sstevel@tonic-gate 		}
26140Sstevel@tonic-gate 	}
26150Sstevel@tonic-gate 	if ((off + contig) >= ip->i_size) {
26160Sstevel@tonic-gate 		contig = ip->i_size - off;
26170Sstevel@tonic-gate 	}
26180Sstevel@tonic-gate 
26190Sstevel@tonic-gate out:
26200Sstevel@tonic-gate 	*pg_off = contig;
26210Sstevel@tonic-gate 	return (error);
26220Sstevel@tonic-gate }
26230Sstevel@tonic-gate 
26240Sstevel@tonic-gate int32_t
ud_putpages(struct vnode * vp,offset_t off,size_t len,int32_t flags,struct cred * cr)26250Sstevel@tonic-gate ud_putpages(struct vnode *vp, offset_t off,
26260Sstevel@tonic-gate 	size_t len, int32_t flags, struct cred *cr)
26270Sstevel@tonic-gate {
26280Sstevel@tonic-gate 	struct ud_inode *ip;
26290Sstevel@tonic-gate 	page_t *pp;
26300Sstevel@tonic-gate 	u_offset_t io_off;
26310Sstevel@tonic-gate 	size_t io_len;
26320Sstevel@tonic-gate 	u_offset_t eoff;
26330Sstevel@tonic-gate 	int32_t err = 0;
26340Sstevel@tonic-gate 	int32_t dolock;
26350Sstevel@tonic-gate 
26360Sstevel@tonic-gate 	ud_printf("ud_putpages\n");
26370Sstevel@tonic-gate 
26380Sstevel@tonic-gate 	if (vp->v_count == 0) {
26390Sstevel@tonic-gate 		cmn_err(CE_WARN, "ud_putpages: bad v_count");
26400Sstevel@tonic-gate 		return (EINVAL);
26410Sstevel@tonic-gate 	}
26420Sstevel@tonic-gate 
26430Sstevel@tonic-gate 	ip = VTOI(vp);
26440Sstevel@tonic-gate 
26450Sstevel@tonic-gate 	/*
26460Sstevel@tonic-gate 	 * Acquire the readers/write inode lock before locking
26470Sstevel@tonic-gate 	 * any pages in this inode.
26480Sstevel@tonic-gate 	 * The inode lock is held during i/o.
26490Sstevel@tonic-gate 	 */
26500Sstevel@tonic-gate 	if (len == 0) {
26510Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
26520Sstevel@tonic-gate 		ip->i_delayoff = ip->i_delaylen = 0;
26530Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
26540Sstevel@tonic-gate 	}
26550Sstevel@tonic-gate #ifdef	__lock_lint
26560Sstevel@tonic-gate 	rw_enter(&ip->i_contents, RW_READER);
26570Sstevel@tonic-gate #else
26580Sstevel@tonic-gate 	dolock = (rw_owner(&ip->i_contents) != curthread);
26590Sstevel@tonic-gate 	if (dolock) {
26600Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_READER);
26610Sstevel@tonic-gate 	}
26620Sstevel@tonic-gate #endif
26630Sstevel@tonic-gate 
26640Sstevel@tonic-gate 	if (!vn_has_cached_data(vp)) {
26650Sstevel@tonic-gate #ifdef	__lock_lint
26660Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
26670Sstevel@tonic-gate #else
26680Sstevel@tonic-gate 		if (dolock) {
26690Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
26700Sstevel@tonic-gate 		}
26710Sstevel@tonic-gate #endif
26720Sstevel@tonic-gate 		return (0);
26730Sstevel@tonic-gate 	}
26740Sstevel@tonic-gate 
26750Sstevel@tonic-gate 	if (len == 0) {
26760Sstevel@tonic-gate 		/*
26770Sstevel@tonic-gate 		 * Search the entire vp list for pages >= off.
26780Sstevel@tonic-gate 		 */
26790Sstevel@tonic-gate 		err = pvn_vplist_dirty(vp, (u_offset_t)off, ud_putapage,
26808059SDonghai.Qiao@Sun.COM 		    flags, cr);
26810Sstevel@tonic-gate 	} else {
26820Sstevel@tonic-gate 		/*
26830Sstevel@tonic-gate 		 * Loop over all offsets in the range looking for
26840Sstevel@tonic-gate 		 * pages to deal with.
26850Sstevel@tonic-gate 		 */
26860Sstevel@tonic-gate 		if ((eoff = blkroundup(ip->i_udf, ip->i_size)) != 0) {
26870Sstevel@tonic-gate 			eoff = MIN(off + len, eoff);
26880Sstevel@tonic-gate 		} else {
26890Sstevel@tonic-gate 			eoff = off + len;
26900Sstevel@tonic-gate 		}
26910Sstevel@tonic-gate 
26920Sstevel@tonic-gate 		for (io_off = off; io_off < eoff; io_off += io_len) {
26930Sstevel@tonic-gate 			/*
26940Sstevel@tonic-gate 			 * If we are not invalidating, synchronously
26950Sstevel@tonic-gate 			 * freeing or writing pages, use the routine
26960Sstevel@tonic-gate 			 * page_lookup_nowait() to prevent reclaiming
26970Sstevel@tonic-gate 			 * them from the free list.
26980Sstevel@tonic-gate 			 */
26990Sstevel@tonic-gate 			if ((flags & B_INVAL) || ((flags & B_ASYNC) == 0)) {
27000Sstevel@tonic-gate 				pp = page_lookup(vp, io_off,
27018059SDonghai.Qiao@Sun.COM 				    (flags & (B_INVAL | B_FREE)) ?
27028059SDonghai.Qiao@Sun.COM 				    SE_EXCL : SE_SHARED);
27030Sstevel@tonic-gate 			} else {
27040Sstevel@tonic-gate 				pp = page_lookup_nowait(vp, io_off,
27058059SDonghai.Qiao@Sun.COM 				    (flags & B_FREE) ? SE_EXCL : SE_SHARED);
27060Sstevel@tonic-gate 			}
27070Sstevel@tonic-gate 
27080Sstevel@tonic-gate 			if (pp == NULL || pvn_getdirty(pp, flags) == 0) {
27090Sstevel@tonic-gate 				io_len = PAGESIZE;
27100Sstevel@tonic-gate 			} else {
27110Sstevel@tonic-gate 
27120Sstevel@tonic-gate 				err = ud_putapage(vp, pp,
27138059SDonghai.Qiao@Sun.COM 				    &io_off, &io_len, flags, cr);
27140Sstevel@tonic-gate 				if (err != 0) {
27150Sstevel@tonic-gate 					break;
27160Sstevel@tonic-gate 				}
27170Sstevel@tonic-gate 				/*
27180Sstevel@tonic-gate 				 * "io_off" and "io_len" are returned as
27190Sstevel@tonic-gate 				 * the range of pages we actually wrote.
27200Sstevel@tonic-gate 				 * This allows us to skip ahead more quickly
27210Sstevel@tonic-gate 				 * since several pages may've been dealt
27220Sstevel@tonic-gate 				 * with by this iteration of the loop.
27230Sstevel@tonic-gate 				 */
27240Sstevel@tonic-gate 			}
27250Sstevel@tonic-gate 		}
27260Sstevel@tonic-gate 	}
27270Sstevel@tonic-gate 	if (err == 0 && off == 0 && (len == 0 || len >= ip->i_size)) {
27280Sstevel@tonic-gate 		/*
27290Sstevel@tonic-gate 		 * We have just sync'ed back all the pages on
27300Sstevel@tonic-gate 		 * the inode, turn off the IMODTIME flag.
27310Sstevel@tonic-gate 		 */
27320Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
27330Sstevel@tonic-gate 		ip->i_flag &= ~IMODTIME;
27340Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
27350Sstevel@tonic-gate 	}
27360Sstevel@tonic-gate #ifdef	__lock_lint
27370Sstevel@tonic-gate 	rw_exit(&ip->i_contents);
27380Sstevel@tonic-gate #else
27390Sstevel@tonic-gate 	if (dolock) {
27400Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
27410Sstevel@tonic-gate 	}
27420Sstevel@tonic-gate #endif
27430Sstevel@tonic-gate 	return (err);
27440Sstevel@tonic-gate }
27450Sstevel@tonic-gate 
27460Sstevel@tonic-gate /* ARGSUSED */
27470Sstevel@tonic-gate int32_t
ud_putapage(struct vnode * vp,page_t * pp,u_offset_t * offp,size_t * lenp,int32_t flags,struct cred * cr)27480Sstevel@tonic-gate ud_putapage(struct vnode *vp,
27490Sstevel@tonic-gate 	page_t *pp, u_offset_t *offp,
27500Sstevel@tonic-gate 	size_t *lenp, int32_t flags, struct cred *cr)
27510Sstevel@tonic-gate {
27520Sstevel@tonic-gate 	daddr_t bn;
27530Sstevel@tonic-gate 	size_t io_len;
27540Sstevel@tonic-gate 	struct ud_inode *ip;
27550Sstevel@tonic-gate 	int32_t error = 0, contig, multi_io = 0;
27560Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
27570Sstevel@tonic-gate 	u_offset_t off, io_off;
27580Sstevel@tonic-gate 	caddr_t kaddr, caddr;
27590Sstevel@tonic-gate 	struct buf *bp = NULL;
27600Sstevel@tonic-gate 	int32_t lbmask;
27610Sstevel@tonic-gate 	uint64_t isize;
27620Sstevel@tonic-gate 	int32_t crc_len;
27630Sstevel@tonic-gate 	struct file_entry *fe;
27640Sstevel@tonic-gate 
27650Sstevel@tonic-gate 	ud_printf("ud_putapage\n");
27660Sstevel@tonic-gate 
27670Sstevel@tonic-gate 	ip = VTOI(vp);
27680Sstevel@tonic-gate 	ASSERT(ip);
27690Sstevel@tonic-gate 	ASSERT(RW_LOCK_HELD(&ip->i_contents));
27700Sstevel@tonic-gate 	lbmask = ip->i_udf->udf_lbmask;
27710Sstevel@tonic-gate 	isize = (ip->i_size + lbmask) & (~lbmask);
27720Sstevel@tonic-gate 
27730Sstevel@tonic-gate 	udf_vfsp = ip->i_udf;
27740Sstevel@tonic-gate 	ASSERT(udf_vfsp->udf_flags & UDF_FL_RW);
27750Sstevel@tonic-gate 
27760Sstevel@tonic-gate 	/*
27770Sstevel@tonic-gate 	 * If the modified time on the inode has not already been
27780Sstevel@tonic-gate 	 * set elsewhere (e.g. for write/setattr) we set the time now.
27790Sstevel@tonic-gate 	 * This gives us approximate modified times for mmap'ed files
27800Sstevel@tonic-gate 	 * which are modified via stores in the user address space.
27810Sstevel@tonic-gate 	 */
27820Sstevel@tonic-gate 	if (((ip->i_flag & IMODTIME) == 0) || (flags & B_FORCE)) {
27830Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
27840Sstevel@tonic-gate 		ip->i_flag |= IUPD;
27850Sstevel@tonic-gate 		ITIMES_NOLOCK(ip);
27860Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
27870Sstevel@tonic-gate 	}
27880Sstevel@tonic-gate 
27890Sstevel@tonic-gate 
27900Sstevel@tonic-gate 	/*
27910Sstevel@tonic-gate 	 * Align the request to a block boundry (for old file systems),
27920Sstevel@tonic-gate 	 * and go ask bmap() how contiguous things are for this file.
27930Sstevel@tonic-gate 	 */
27940Sstevel@tonic-gate 	off = pp->p_offset & ~(offset_t)lbmask;
27950Sstevel@tonic-gate 				/* block align it */
27960Sstevel@tonic-gate 
27970Sstevel@tonic-gate 
27980Sstevel@tonic-gate 	if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
27990Sstevel@tonic-gate 		ASSERT(ip->i_size <= ip->i_max_emb);
28000Sstevel@tonic-gate 
28010Sstevel@tonic-gate 		pp = pvn_write_kluster(vp, pp, &io_off,
28028059SDonghai.Qiao@Sun.COM 		    &io_len, off, PAGESIZE, flags);
28030Sstevel@tonic-gate 		if (io_len == 0) {
28040Sstevel@tonic-gate 			io_len = PAGESIZE;
28050Sstevel@tonic-gate 		}
28060Sstevel@tonic-gate 
28070Sstevel@tonic-gate 		bp = ud_bread(ip->i_dev,
28088059SDonghai.Qiao@Sun.COM 		    ip->i_icb_lbano << udf_vfsp->udf_l2d_shift,
28098059SDonghai.Qiao@Sun.COM 		    udf_vfsp->udf_lbsize);
28100Sstevel@tonic-gate 		fe = (struct file_entry *)bp->b_un.b_addr;
28110Sstevel@tonic-gate 		if ((bp->b_flags & B_ERROR) ||
28120Sstevel@tonic-gate 		    (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
28130Sstevel@tonic-gate 		    ip->i_icb_block,
28140Sstevel@tonic-gate 		    1, udf_vfsp->udf_lbsize) != 0)) {
28150Sstevel@tonic-gate 			if (pp != NULL)
28160Sstevel@tonic-gate 				pvn_write_done(pp, B_ERROR | B_WRITE | flags);
28170Sstevel@tonic-gate 			if (bp->b_flags & B_ERROR) {
28180Sstevel@tonic-gate 				error = EIO;
28190Sstevel@tonic-gate 			} else {
28200Sstevel@tonic-gate 				error = EINVAL;
28210Sstevel@tonic-gate 			}
28220Sstevel@tonic-gate 			brelse(bp);
28230Sstevel@tonic-gate 			return (error);
28240Sstevel@tonic-gate 		}
28250Sstevel@tonic-gate 		if ((bp->b_error == 0) &&
28268059SDonghai.Qiao@Sun.COM 		    (bp->b_resid == 0)) {
28270Sstevel@tonic-gate 
28280Sstevel@tonic-gate 			caddr = bp->b_un.b_addr + ip->i_data_off;
28290Sstevel@tonic-gate 			kaddr = (caddr_t)ppmapin(pp,
28308059SDonghai.Qiao@Sun.COM 			    PROT_READ | PROT_WRITE, (caddr_t)-1);
28310Sstevel@tonic-gate 			(void) kcopy(kaddr, caddr, ip->i_size);
28320Sstevel@tonic-gate 			ppmapout(kaddr);
28330Sstevel@tonic-gate 		}
28340Sstevel@tonic-gate 		crc_len = ((uint32_t)&((struct file_entry *)0)->fe_spec) +
28358059SDonghai.Qiao@Sun.COM 		    SWAP_32(fe->fe_len_ear);
28360Sstevel@tonic-gate 		crc_len += ip->i_size;
28370Sstevel@tonic-gate 		ud_make_tag(ip->i_udf, &fe->fe_tag,
28388059SDonghai.Qiao@Sun.COM 		    UD_FILE_ENTRY, ip->i_icb_block, crc_len);
28390Sstevel@tonic-gate 
28400Sstevel@tonic-gate 		bwrite(bp);
28410Sstevel@tonic-gate 
28420Sstevel@tonic-gate 		if (flags & B_ASYNC) {
28430Sstevel@tonic-gate 			pvn_write_done(pp, flags);
28440Sstevel@tonic-gate 		}
28450Sstevel@tonic-gate 		contig = ip->i_size;
28460Sstevel@tonic-gate 	} else {
28470Sstevel@tonic-gate 
28480Sstevel@tonic-gate 		if (error = ud_bmap_read(ip, off, &bn, &contig)) {
28490Sstevel@tonic-gate 			goto out;
28500Sstevel@tonic-gate 		}
28510Sstevel@tonic-gate 		contig = MIN(contig, PAGESIZE);
28520Sstevel@tonic-gate 		contig = (contig + lbmask) & (~lbmask);
28530Sstevel@tonic-gate 
28540Sstevel@tonic-gate 		if (contig < PAGESIZE) {
28550Sstevel@tonic-gate 			uint64_t count;
28560Sstevel@tonic-gate 
28570Sstevel@tonic-gate 			count = isize - off;
28580Sstevel@tonic-gate 			if (contig != count) {
28590Sstevel@tonic-gate 				multi_io = 1;
28600Sstevel@tonic-gate 				contig = (int32_t)(MIN(count, PAGESIZE));
28610Sstevel@tonic-gate 			}
28620Sstevel@tonic-gate 		}
28630Sstevel@tonic-gate 
28640Sstevel@tonic-gate 		if ((off + contig) > isize) {
28650Sstevel@tonic-gate 			contig = isize - off;
28660Sstevel@tonic-gate 		}
28670Sstevel@tonic-gate 
28680Sstevel@tonic-gate 		if (contig > PAGESIZE) {
28690Sstevel@tonic-gate 			if (contig & PAGEOFFSET) {
28700Sstevel@tonic-gate 				contig &= PAGEMASK;
28710Sstevel@tonic-gate 			}
28720Sstevel@tonic-gate 		}
28730Sstevel@tonic-gate 
28740Sstevel@tonic-gate 		pp = pvn_write_kluster(vp, pp, &io_off,
28758059SDonghai.Qiao@Sun.COM 		    &io_len, off, contig, flags);
28760Sstevel@tonic-gate 		if (io_len == 0) {
28770Sstevel@tonic-gate 			io_len = PAGESIZE;
28780Sstevel@tonic-gate 		}
28790Sstevel@tonic-gate 
28800Sstevel@tonic-gate 		bp = pageio_setup(pp, contig, ip->i_devvp, B_WRITE | flags);
28810Sstevel@tonic-gate 		ASSERT(bp != NULL);
28820Sstevel@tonic-gate 
28830Sstevel@tonic-gate 		bp->b_edev = ip->i_dev;
28840Sstevel@tonic-gate 		bp->b_dev = cmpdev(ip->i_dev);
28850Sstevel@tonic-gate 		bp->b_blkno = bn;
28860Sstevel@tonic-gate 		bp->b_un.b_addr = 0;
28870Sstevel@tonic-gate 		bp->b_file = vp;
28880Sstevel@tonic-gate 		bp->b_offset = (offset_t)off;
28890Sstevel@tonic-gate 
28900Sstevel@tonic-gate 
28910Sstevel@tonic-gate 		/*
28920Sstevel@tonic-gate 		 * write throttle
28930Sstevel@tonic-gate 		 */
28940Sstevel@tonic-gate 		ASSERT(bp->b_iodone == NULL);
28950Sstevel@tonic-gate 		bp->b_iodone = ud_iodone;
28960Sstevel@tonic-gate 		mutex_enter(&ip->i_tlock);
28970Sstevel@tonic-gate 		ip->i_writes += bp->b_bcount;
28980Sstevel@tonic-gate 		mutex_exit(&ip->i_tlock);
28990Sstevel@tonic-gate 
29000Sstevel@tonic-gate 		if (multi_io == 0) {
29010Sstevel@tonic-gate 
29020Sstevel@tonic-gate 			(void) bdev_strategy(bp);
29030Sstevel@tonic-gate 		} else {
29040Sstevel@tonic-gate 			error = ud_multi_strat(ip, pp, bp, off);
29050Sstevel@tonic-gate 			if (error != 0) {
29060Sstevel@tonic-gate 				goto out;
29070Sstevel@tonic-gate 			}
29080Sstevel@tonic-gate 		}
29090Sstevel@tonic-gate 
29100Sstevel@tonic-gate 		if ((flags & B_ASYNC) == 0) {
29110Sstevel@tonic-gate 			/*
29120Sstevel@tonic-gate 			 * Wait for i/o to complete.
29130Sstevel@tonic-gate 			 */
29140Sstevel@tonic-gate 			error = biowait(bp);
29150Sstevel@tonic-gate 			pageio_done(bp);
29160Sstevel@tonic-gate 		}
29170Sstevel@tonic-gate 	}
29180Sstevel@tonic-gate 
29190Sstevel@tonic-gate 	if ((flags & B_ASYNC) == 0) {
29200Sstevel@tonic-gate 		pvn_write_done(pp, ((error) ? B_ERROR : 0) | B_WRITE | flags);
29210Sstevel@tonic-gate 	}
29220Sstevel@tonic-gate 
29230Sstevel@tonic-gate 	pp = NULL;
29240Sstevel@tonic-gate 
29250Sstevel@tonic-gate out:
29260Sstevel@tonic-gate 	if (error != 0 && pp != NULL) {
29270Sstevel@tonic-gate 		pvn_write_done(pp, B_ERROR | B_WRITE | flags);
29280Sstevel@tonic-gate 	}
29290Sstevel@tonic-gate 
29300Sstevel@tonic-gate 	if (offp) {
29310Sstevel@tonic-gate 		*offp = io_off;
29320Sstevel@tonic-gate 	}
29330Sstevel@tonic-gate 	if (lenp) {
29340Sstevel@tonic-gate 		*lenp = io_len;
29350Sstevel@tonic-gate 	}
29360Sstevel@tonic-gate 
29370Sstevel@tonic-gate 	return (error);
29380Sstevel@tonic-gate }
29390Sstevel@tonic-gate 
29400Sstevel@tonic-gate 
29410Sstevel@tonic-gate int32_t
ud_iodone(struct buf * bp)29420Sstevel@tonic-gate ud_iodone(struct buf *bp)
29430Sstevel@tonic-gate {
29440Sstevel@tonic-gate 	struct ud_inode *ip;
29450Sstevel@tonic-gate 
29460Sstevel@tonic-gate 	ASSERT((bp->b_pages->p_vnode != NULL) && !(bp->b_flags & B_READ));
29470Sstevel@tonic-gate 
29480Sstevel@tonic-gate 	bp->b_iodone = NULL;
29490Sstevel@tonic-gate 
29500Sstevel@tonic-gate 	ip = VTOI(bp->b_pages->p_vnode);
29510Sstevel@tonic-gate 
29520Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
29530Sstevel@tonic-gate 	if (ip->i_writes >= ud_LW) {
29540Sstevel@tonic-gate 		if ((ip->i_writes -= bp->b_bcount) <= ud_LW) {
29550Sstevel@tonic-gate 			if (ud_WRITES) {
29560Sstevel@tonic-gate 				cv_broadcast(&ip->i_wrcv); /* wake all up */
29570Sstevel@tonic-gate 			}
29580Sstevel@tonic-gate 		}
29590Sstevel@tonic-gate 	} else {
29600Sstevel@tonic-gate 		ip->i_writes -= bp->b_bcount;
29610Sstevel@tonic-gate 	}
29620Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
29630Sstevel@tonic-gate 	iodone(bp);
29640Sstevel@tonic-gate 	return (0);
29650Sstevel@tonic-gate }
29660Sstevel@tonic-gate 
29670Sstevel@tonic-gate /* ARGSUSED3 */
29680Sstevel@tonic-gate int32_t
ud_rdip(struct ud_inode * ip,struct uio * uio,int32_t ioflag,cred_t * cr)29690Sstevel@tonic-gate ud_rdip(struct ud_inode *ip, struct uio *uio, int32_t ioflag, cred_t *cr)
29700Sstevel@tonic-gate {
29710Sstevel@tonic-gate 	struct vnode *vp;
29720Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
29730Sstevel@tonic-gate 	krw_t rwtype;
29740Sstevel@tonic-gate 	caddr_t base;
29750Sstevel@tonic-gate 	uint32_t flags;
29760Sstevel@tonic-gate 	int32_t error, n, on, mapon, dofree;
29770Sstevel@tonic-gate 	u_offset_t off;
29780Sstevel@tonic-gate 	long oresid = uio->uio_resid;
29790Sstevel@tonic-gate 
29800Sstevel@tonic-gate 	ASSERT(RW_LOCK_HELD(&ip->i_contents));
29810Sstevel@tonic-gate 	if ((ip->i_type != VREG) &&
29828059SDonghai.Qiao@Sun.COM 	    (ip->i_type != VDIR) &&
29838059SDonghai.Qiao@Sun.COM 	    (ip->i_type != VLNK)) {
29840Sstevel@tonic-gate 		return (EIO);
29850Sstevel@tonic-gate 	}
29860Sstevel@tonic-gate 
29870Sstevel@tonic-gate 	if (uio->uio_loffset > MAXOFFSET_T) {
29880Sstevel@tonic-gate 		return (0);
29890Sstevel@tonic-gate 	}
29900Sstevel@tonic-gate 
29910Sstevel@tonic-gate 	if ((uio->uio_loffset < (offset_t)0) ||
29928059SDonghai.Qiao@Sun.COM 	    ((uio->uio_loffset + uio->uio_resid) < 0)) {
29930Sstevel@tonic-gate 		return (EINVAL);
29940Sstevel@tonic-gate 	}
29950Sstevel@tonic-gate 	if (uio->uio_resid == 0) {
29960Sstevel@tonic-gate 		return (0);
29970Sstevel@tonic-gate 	}
29980Sstevel@tonic-gate 
29990Sstevel@tonic-gate 	vp = ITOV(ip);
30000Sstevel@tonic-gate 	udf_vfsp = ip->i_udf;
30010Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
30020Sstevel@tonic-gate 	ip->i_flag |= IACC;
30030Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
30040Sstevel@tonic-gate 
30050Sstevel@tonic-gate 	rwtype = (rw_write_held(&ip->i_contents)?RW_WRITER:RW_READER);
30060Sstevel@tonic-gate 
30070Sstevel@tonic-gate 	do {
30080Sstevel@tonic-gate 		offset_t diff;
30090Sstevel@tonic-gate 		u_offset_t uoff = uio->uio_loffset;
30100Sstevel@tonic-gate 		off = uoff & (offset_t)MAXBMASK;
30110Sstevel@tonic-gate 		mapon = (int)(uoff & (offset_t)MAXBOFFSET);
30120Sstevel@tonic-gate 		on = (int)blkoff(udf_vfsp, uoff);
30130Sstevel@tonic-gate 		n = (int)MIN(udf_vfsp->udf_lbsize - on, uio->uio_resid);
30140Sstevel@tonic-gate 
30150Sstevel@tonic-gate 		diff = ip->i_size - uoff;
30160Sstevel@tonic-gate 
30170Sstevel@tonic-gate 		if (diff <= (offset_t)0) {
30180Sstevel@tonic-gate 			error = 0;
30190Sstevel@tonic-gate 			goto out;
30200Sstevel@tonic-gate 		}
30210Sstevel@tonic-gate 		if (diff < (offset_t)n) {
30220Sstevel@tonic-gate 			n = (int)diff;
30230Sstevel@tonic-gate 		}
30240Sstevel@tonic-gate 		dofree = ud_freebehind &&
30258059SDonghai.Qiao@Sun.COM 		    ip->i_nextr == (off & PAGEMASK) &&
30268059SDonghai.Qiao@Sun.COM 		    off > ud_smallfile;
30270Sstevel@tonic-gate 
30280Sstevel@tonic-gate #ifndef	__lock_lint
30290Sstevel@tonic-gate 		if (rwtype == RW_READER) {
30300Sstevel@tonic-gate 			rw_exit(&ip->i_contents);
30310Sstevel@tonic-gate 		}
30320Sstevel@tonic-gate #endif
30330Sstevel@tonic-gate 
30340Sstevel@tonic-gate 		base = segmap_getmapflt(segkmap, vp, (off + mapon),
30358059SDonghai.Qiao@Sun.COM 		    (uint32_t)n, 1, S_READ);
30360Sstevel@tonic-gate 		error = uiomove(base + mapon, (long)n, UIO_READ, uio);
30370Sstevel@tonic-gate 
30380Sstevel@tonic-gate 		flags = 0;
30390Sstevel@tonic-gate 		if (!error) {
30400Sstevel@tonic-gate 			/*
30410Sstevel@tonic-gate 			 * If read a whole block, or read to eof,
30420Sstevel@tonic-gate 			 * won't need this buffer again soon.
30430Sstevel@tonic-gate 			 */
30440Sstevel@tonic-gate 			if (n + on == MAXBSIZE && ud_freebehind && dofree &&
30458059SDonghai.Qiao@Sun.COM 			    freemem < lotsfree + pages_before_pager) {
30460Sstevel@tonic-gate 				flags = SM_FREE | SM_DONTNEED |SM_ASYNC;
30470Sstevel@tonic-gate 			}
30480Sstevel@tonic-gate 			/*
30490Sstevel@tonic-gate 			 * In POSIX SYNC (FSYNC and FDSYNC) read mode,
30500Sstevel@tonic-gate 			 * we want to make sure that the page which has
30510Sstevel@tonic-gate 			 * been read, is written on disk if it is dirty.
30520Sstevel@tonic-gate 			 * And corresponding indirect blocks should also
30530Sstevel@tonic-gate 			 * be flushed out.
30540Sstevel@tonic-gate 			 */
30550Sstevel@tonic-gate 			if ((ioflag & FRSYNC) && (ioflag & (FSYNC|FDSYNC))) {
30560Sstevel@tonic-gate 				flags &= ~SM_ASYNC;
30570Sstevel@tonic-gate 				flags |= SM_WRITE;
30580Sstevel@tonic-gate 			}
30590Sstevel@tonic-gate 			error = segmap_release(segkmap, base, flags);
30600Sstevel@tonic-gate 		} else    {
30610Sstevel@tonic-gate 			(void) segmap_release(segkmap, base, flags);
30620Sstevel@tonic-gate 		}
30630Sstevel@tonic-gate 
30640Sstevel@tonic-gate #ifndef __lock_lint
30650Sstevel@tonic-gate 		if (rwtype == RW_READER) {
30660Sstevel@tonic-gate 			rw_enter(&ip->i_contents, rwtype);
30670Sstevel@tonic-gate 		}
30680Sstevel@tonic-gate #endif
30690Sstevel@tonic-gate 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
30700Sstevel@tonic-gate out:
30710Sstevel@tonic-gate 	/*
30720Sstevel@tonic-gate 	 * Inode is updated according to this table if FRSYNC is set.
30730Sstevel@tonic-gate 	 *
30740Sstevel@tonic-gate 	 *	FSYNC	FDSYNC(posix.4)
30750Sstevel@tonic-gate 	 *	--------------------------
30760Sstevel@tonic-gate 	 *	always	IATTCHG|IBDWRITE
30770Sstevel@tonic-gate 	 */
30780Sstevel@tonic-gate 	if (ioflag & FRSYNC) {
30790Sstevel@tonic-gate 		if ((ioflag & FSYNC) ||
30808059SDonghai.Qiao@Sun.COM 		    ((ioflag & FDSYNC) &&
30818059SDonghai.Qiao@Sun.COM 		    (ip->i_flag & (IATTCHG|IBDWRITE)))) {
30820Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
30830Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_WRITER);
30840Sstevel@tonic-gate 		ud_iupdat(ip, 1);
30850Sstevel@tonic-gate 		}
30860Sstevel@tonic-gate 	}
30870Sstevel@tonic-gate 	/*
30880Sstevel@tonic-gate 	 * If we've already done a partial read, terminate
30890Sstevel@tonic-gate 	 * the read but return no error.
30900Sstevel@tonic-gate 	 */
30910Sstevel@tonic-gate 	if (oresid != uio->uio_resid) {
30920Sstevel@tonic-gate 		error = 0;
30930Sstevel@tonic-gate 	}
30940Sstevel@tonic-gate 	ITIMES(ip);
30950Sstevel@tonic-gate 
30960Sstevel@tonic-gate 	return (error);
30970Sstevel@tonic-gate }
30980Sstevel@tonic-gate 
30990Sstevel@tonic-gate int32_t
ud_wrip(struct ud_inode * ip,struct uio * uio,int ioflag,struct cred * cr)31000Sstevel@tonic-gate ud_wrip(struct ud_inode *ip, struct uio *uio, int ioflag, struct cred *cr)
31010Sstevel@tonic-gate {
31020Sstevel@tonic-gate 	caddr_t base;
31030Sstevel@tonic-gate 	struct vnode *vp;
31040Sstevel@tonic-gate 	struct udf_vfs *udf_vfsp;
31050Sstevel@tonic-gate 	uint32_t flags;
31060Sstevel@tonic-gate 	int32_t error = 0, iupdat_flag, n, on, mapon, i_size_changed = 0;
31070Sstevel@tonic-gate 	int32_t pagecreate, newpage;
31080Sstevel@tonic-gate 	uint64_t old_i_size;
31090Sstevel@tonic-gate 	u_offset_t off;
31100Sstevel@tonic-gate 	long start_resid = uio->uio_resid, premove_resid;
31110Sstevel@tonic-gate 	rlim64_t limit = uio->uio_limit;
31120Sstevel@tonic-gate 
31130Sstevel@tonic-gate 
31140Sstevel@tonic-gate 	ASSERT(RW_WRITE_HELD(&ip->i_contents));
31150Sstevel@tonic-gate 	if ((ip->i_type != VREG) &&
31168059SDonghai.Qiao@Sun.COM 	    (ip->i_type != VDIR) &&
31178059SDonghai.Qiao@Sun.COM 	    (ip->i_type != VLNK)) {
31180Sstevel@tonic-gate 		return (EIO);
31190Sstevel@tonic-gate 	}
31200Sstevel@tonic-gate 
31210Sstevel@tonic-gate 	if (uio->uio_loffset >= MAXOFFSET_T) {
31220Sstevel@tonic-gate 		return (EFBIG);
31230Sstevel@tonic-gate 	}
31240Sstevel@tonic-gate 	/*
31250Sstevel@tonic-gate 	 * see udf_l_pathconf
31260Sstevel@tonic-gate 	 */
31270Sstevel@tonic-gate 	if (limit > (((uint64_t)1 << 40) - 1)) {
31280Sstevel@tonic-gate 		limit = ((uint64_t)1 << 40) - 1;
31290Sstevel@tonic-gate 	}
31300Sstevel@tonic-gate 	if (uio->uio_loffset >= limit) {
31310Sstevel@tonic-gate 		proc_t *p = ttoproc(curthread);
31320Sstevel@tonic-gate 
31330Sstevel@tonic-gate 		mutex_enter(&p->p_lock);
31340Sstevel@tonic-gate 		(void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE], p->p_rctls,
31350Sstevel@tonic-gate 		    p, RCA_UNSAFE_SIGINFO);
31360Sstevel@tonic-gate 		mutex_exit(&p->p_lock);
31370Sstevel@tonic-gate 		return (EFBIG);
31380Sstevel@tonic-gate 	}
31390Sstevel@tonic-gate 	if ((uio->uio_loffset < (offset_t)0) ||
31408059SDonghai.Qiao@Sun.COM 	    ((uio->uio_loffset + uio->uio_resid) < 0)) {
31410Sstevel@tonic-gate 		return (EINVAL);
31420Sstevel@tonic-gate 	}
31430Sstevel@tonic-gate 	if (uio->uio_resid == 0) {
31440Sstevel@tonic-gate 		return (0);
31450Sstevel@tonic-gate 	}
31460Sstevel@tonic-gate 
31470Sstevel@tonic-gate 	mutex_enter(&ip->i_tlock);
31480Sstevel@tonic-gate 	ip->i_flag |= INOACC;
31490Sstevel@tonic-gate 
31500Sstevel@tonic-gate 	if (ioflag & (FSYNC | FDSYNC)) {
31510Sstevel@tonic-gate 		ip->i_flag |= ISYNC;
31520Sstevel@tonic-gate 		iupdat_flag = 1;
31530Sstevel@tonic-gate 	}
31540Sstevel@tonic-gate 	mutex_exit(&ip->i_tlock);
31550Sstevel@tonic-gate 
31560Sstevel@tonic-gate 	udf_vfsp = ip->i_udf;
31570Sstevel@tonic-gate 	vp = ITOV(ip);
31580Sstevel@tonic-gate 
31590Sstevel@tonic-gate 	do {
31600Sstevel@tonic-gate 		u_offset_t uoff = uio->uio_loffset;
31610Sstevel@tonic-gate 		off = uoff & (offset_t)MAXBMASK;
31620Sstevel@tonic-gate 		mapon = (int)(uoff & (offset_t)MAXBOFFSET);
31630Sstevel@tonic-gate 		on = (int)blkoff(udf_vfsp, uoff);
31640Sstevel@tonic-gate 		n = (int)MIN(udf_vfsp->udf_lbsize - on, uio->uio_resid);
31650Sstevel@tonic-gate 
31660Sstevel@tonic-gate 		if (ip->i_type == VREG && uoff + n >= limit) {
31670Sstevel@tonic-gate 			if (uoff >= limit) {
31680Sstevel@tonic-gate 				error = EFBIG;
31690Sstevel@tonic-gate 				goto out;
31700Sstevel@tonic-gate 			}
31710Sstevel@tonic-gate 			n = (int)(limit - (rlim64_t)uoff);
31720Sstevel@tonic-gate 		}
31730Sstevel@tonic-gate 		if (uoff + n > ip->i_size) {
31740Sstevel@tonic-gate 			/*
31750Sstevel@tonic-gate 			 * We are extending the length of the file.
31760Sstevel@tonic-gate 			 * bmap is used so that we are sure that
31770Sstevel@tonic-gate 			 * if we need to allocate new blocks, that it
31780Sstevel@tonic-gate 			 * is done here before we up the file size.
31790Sstevel@tonic-gate 			 */
31800Sstevel@tonic-gate 			error = ud_bmap_write(ip, uoff,
31818059SDonghai.Qiao@Sun.COM 			    (int)(on + n), mapon == 0, cr);
31820Sstevel@tonic-gate 			if (error) {
31830Sstevel@tonic-gate 				break;
31840Sstevel@tonic-gate 			}
31850Sstevel@tonic-gate 			i_size_changed = 1;
31860Sstevel@tonic-gate 			old_i_size = ip->i_size;
31870Sstevel@tonic-gate 			ip->i_size = uoff + n;
31880Sstevel@tonic-gate 			/*
31890Sstevel@tonic-gate 			 * If we are writing from the beginning of
31900Sstevel@tonic-gate 			 * the mapping, we can just create the
31910Sstevel@tonic-gate 			 * pages without having to read them.
31920Sstevel@tonic-gate 			 */
31930Sstevel@tonic-gate 			pagecreate = (mapon == 0);
31940Sstevel@tonic-gate 		} else if (n == MAXBSIZE) {
31950Sstevel@tonic-gate 			/*
31960Sstevel@tonic-gate 			 * Going to do a whole mappings worth,
31970Sstevel@tonic-gate 			 * so we can just create the pages w/o
31980Sstevel@tonic-gate 			 * having to read them in.  But before
31990Sstevel@tonic-gate 			 * we do that, we need to make sure any
32000Sstevel@tonic-gate 			 * needed blocks are allocated first.
32010Sstevel@tonic-gate 			 */
32020Sstevel@tonic-gate 			error = ud_bmap_write(ip, uoff,
32038059SDonghai.Qiao@Sun.COM 			    (int)(on + n), 1, cr);
32040Sstevel@tonic-gate 			if (error) {
32050Sstevel@tonic-gate 				break;
32060Sstevel@tonic-gate 			}
32070Sstevel@tonic-gate 			pagecreate = 1;
32080Sstevel@tonic-gate 		} else {
32090Sstevel@tonic-gate 			pagecreate = 0;
32100Sstevel@tonic-gate 		}
32110Sstevel@tonic-gate 
32120Sstevel@tonic-gate 		rw_exit(&ip->i_contents);
32130Sstevel@tonic-gate 
32148059SDonghai.Qiao@Sun.COM 		/*
32158059SDonghai.Qiao@Sun.COM 		 * Touch the page and fault it in if it is not in
32168059SDonghai.Qiao@Sun.COM 		 * core before segmap_getmapflt can lock it. This
32178059SDonghai.Qiao@Sun.COM 		 * is to avoid the deadlock if the buffer is mapped
32188059SDonghai.Qiao@Sun.COM 		 * to the same file through mmap which we want to
32198059SDonghai.Qiao@Sun.COM 		 * write to.
32208059SDonghai.Qiao@Sun.COM 		 */
32218059SDonghai.Qiao@Sun.COM 		uio_prefaultpages((long)n, uio);
32228059SDonghai.Qiao@Sun.COM 
32230Sstevel@tonic-gate 		base = segmap_getmapflt(segkmap, vp, (off + mapon),
32248059SDonghai.Qiao@Sun.COM 		    (uint32_t)n, !pagecreate, S_WRITE);
32250Sstevel@tonic-gate 
32260Sstevel@tonic-gate 		/*
32270Sstevel@tonic-gate 		 * segmap_pagecreate() returns 1 if it calls
32280Sstevel@tonic-gate 		 * page_create_va() to allocate any pages.
32290Sstevel@tonic-gate 		 */
32300Sstevel@tonic-gate 		newpage = 0;
32310Sstevel@tonic-gate 		if (pagecreate) {
32320Sstevel@tonic-gate 			newpage = segmap_pagecreate(segkmap, base,
32338059SDonghai.Qiao@Sun.COM 			    (size_t)n, 0);
32340Sstevel@tonic-gate 		}
32350Sstevel@tonic-gate 
32360Sstevel@tonic-gate 		premove_resid = uio->uio_resid;
32370Sstevel@tonic-gate 		error = uiomove(base + mapon, (long)n, UIO_WRITE, uio);
32380Sstevel@tonic-gate 
32390Sstevel@tonic-gate 		if (pagecreate &&
32408059SDonghai.Qiao@Sun.COM 		    uio->uio_loffset < roundup(off + mapon + n, PAGESIZE)) {
32410Sstevel@tonic-gate 			/*
32420Sstevel@tonic-gate 			 * We created pages w/o initializing them completely,
32430Sstevel@tonic-gate 			 * thus we need to zero the part that wasn't set up.
32440Sstevel@tonic-gate 			 * This happens on most EOF write cases and if
32450Sstevel@tonic-gate 			 * we had some sort of error during the uiomove.
32460Sstevel@tonic-gate 			 */
32470Sstevel@tonic-gate 			int nzero, nmoved;
32480Sstevel@tonic-gate 
32490Sstevel@tonic-gate 			nmoved = (int)(uio->uio_loffset - (off + mapon));
32500Sstevel@tonic-gate 			ASSERT(nmoved >= 0 && nmoved <= n);
32510Sstevel@tonic-gate 			nzero = roundup(on + n, PAGESIZE) - nmoved;
32520Sstevel@tonic-gate 			ASSERT(nzero > 0 && mapon + nmoved + nzero <= MAXBSIZE);
32530Sstevel@tonic-gate 			(void) kzero(base + mapon + nmoved, (uint32_t)nzero);
32540Sstevel@tonic-gate 		}
32550Sstevel@tonic-gate 
32560Sstevel@tonic-gate 		/*
32570Sstevel@tonic-gate 		 * Unlock the pages allocated by page_create_va()
32580Sstevel@tonic-gate 		 * in segmap_pagecreate()
32590Sstevel@tonic-gate 		 */
32600Sstevel@tonic-gate 		if (newpage) {
32610Sstevel@tonic-gate 			segmap_pageunlock(segkmap, base, (size_t)n, S_WRITE);
32620Sstevel@tonic-gate 		}
32630Sstevel@tonic-gate 
32640Sstevel@tonic-gate 		if (error) {
32650Sstevel@tonic-gate 			/*
32660Sstevel@tonic-gate 			 * If we failed on a write, we may have already
32670Sstevel@tonic-gate 			 * allocated file blocks as well as pages.  It's
32680Sstevel@tonic-gate 			 * hard to undo the block allocation, but we must
32690Sstevel@tonic-gate 			 * be sure to invalidate any pages that may have
32700Sstevel@tonic-gate 			 * been allocated.
32710Sstevel@tonic-gate 			 */
32720Sstevel@tonic-gate 			(void) segmap_release(segkmap, base, SM_INVAL);
32730Sstevel@tonic-gate 		} else {
32740Sstevel@tonic-gate 			flags = 0;
32750Sstevel@tonic-gate 			/*
32760Sstevel@tonic-gate 			 * Force write back for synchronous write cases.
32770Sstevel@tonic-gate 			 */
32780Sstevel@tonic-gate 			if ((ioflag & (FSYNC|FDSYNC)) || ip->i_type == VDIR) {
32790Sstevel@tonic-gate 				/*
32800Sstevel@tonic-gate 				 * If the sticky bit is set but the
32810Sstevel@tonic-gate 				 * execute bit is not set, we do a
32820Sstevel@tonic-gate 				 * synchronous write back and free
32830Sstevel@tonic-gate 				 * the page when done.  We set up swap
32840Sstevel@tonic-gate 				 * files to be handled this way to
32850Sstevel@tonic-gate 				 * prevent servers from keeping around
32860Sstevel@tonic-gate 				 * the client's swap pages too long.
32870Sstevel@tonic-gate 				 * XXX - there ought to be a better way.
32880Sstevel@tonic-gate 				 */
32890Sstevel@tonic-gate 				if (IS_SWAPVP(vp)) {
32900Sstevel@tonic-gate 					flags = SM_WRITE | SM_FREE |
32918059SDonghai.Qiao@Sun.COM 					    SM_DONTNEED;
32920Sstevel@tonic-gate 					iupdat_flag = 0;
32930Sstevel@tonic-gate 				} else {
32940Sstevel@tonic-gate 					flags = SM_WRITE;
32950Sstevel@tonic-gate 				}
32960Sstevel@tonic-gate 			} else if (((mapon + n) == MAXBSIZE) ||
32978059SDonghai.Qiao@Sun.COM 			    IS_SWAPVP(vp)) {
32980Sstevel@tonic-gate 				/*
32990Sstevel@tonic-gate 				 * Have written a whole block.
33000Sstevel@tonic-gate 				 * Start an asynchronous write and
33010Sstevel@tonic-gate 				 * mark the buffer to indicate that
33020Sstevel@tonic-gate 				 * it won't be needed again soon.
33030Sstevel@tonic-gate 				 */
33040Sstevel@tonic-gate 				flags = SM_WRITE |SM_ASYNC | SM_DONTNEED;
33050Sstevel@tonic-gate 			}
33060Sstevel@tonic-gate 			error = segmap_release(segkmap, base, flags);
33070Sstevel@tonic-gate 
33080Sstevel@tonic-gate 			/*
33090Sstevel@tonic-gate 			 * If the operation failed and is synchronous,
33100Sstevel@tonic-gate 			 * then we need to unwind what uiomove() last
33110Sstevel@tonic-gate 			 * did so we can potentially return an error to
33120Sstevel@tonic-gate 			 * the caller.  If this write operation was
33130Sstevel@tonic-gate 			 * done in two pieces and the first succeeded,
33140Sstevel@tonic-gate 			 * then we won't return an error for the second
33150Sstevel@tonic-gate 			 * piece that failed.  However, we only want to
33160Sstevel@tonic-gate 			 * return a resid value that reflects what was
33170Sstevel@tonic-gate 			 * really done.
33180Sstevel@tonic-gate 			 *
33190Sstevel@tonic-gate 			 * Failures for non-synchronous operations can
33200Sstevel@tonic-gate 			 * be ignored since the page subsystem will
33210Sstevel@tonic-gate 			 * retry the operation until it succeeds or the
33220Sstevel@tonic-gate 			 * file system is unmounted.
33230Sstevel@tonic-gate 			 */
33240Sstevel@tonic-gate 			if (error) {
33250Sstevel@tonic-gate 				if ((ioflag & (FSYNC | FDSYNC)) ||
33268059SDonghai.Qiao@Sun.COM 				    ip->i_type == VDIR) {
33270Sstevel@tonic-gate 					uio->uio_resid = premove_resid;
33280Sstevel@tonic-gate 				} else {
33290Sstevel@tonic-gate 					error = 0;
33300Sstevel@tonic-gate 				}
33310Sstevel@tonic-gate 			}
33320Sstevel@tonic-gate 		}
33330Sstevel@tonic-gate 
33340Sstevel@tonic-gate 		/*
33350Sstevel@tonic-gate 		 * Re-acquire contents lock.
33360Sstevel@tonic-gate 		 */
33370Sstevel@tonic-gate 		rw_enter(&ip->i_contents, RW_WRITER);
33380Sstevel@tonic-gate 		/*
33390Sstevel@tonic-gate 		 * If the uiomove() failed or if a synchronous
33400Sstevel@tonic-gate 		 * page push failed, fix up i_size.
33410Sstevel@tonic-gate 		 */
33420Sstevel@tonic-gate 		if (error) {
33430Sstevel@tonic-gate 			if (i_size_changed) {
33440Sstevel@tonic-gate 				/*
33450Sstevel@tonic-gate 				 * The uiomove failed, and we
33460Sstevel@tonic-gate 				 * allocated blocks,so get rid
33470Sstevel@tonic-gate 				 * of them.
33480Sstevel@tonic-gate 				 */
33490Sstevel@tonic-gate 				(void) ud_itrunc(ip, old_i_size, 0, cr);
33500Sstevel@tonic-gate 			}
33510Sstevel@tonic-gate 		} else {
33520Sstevel@tonic-gate 			/*
33530Sstevel@tonic-gate 			 * XXX - Can this be out of the loop?
33540Sstevel@tonic-gate 			 */
33550Sstevel@tonic-gate 			ip->i_flag |= IUPD | ICHG;
33560Sstevel@tonic-gate 			if (i_size_changed) {
33570Sstevel@tonic-gate 				ip->i_flag |= IATTCHG;
33580Sstevel@tonic-gate 			}
33590Sstevel@tonic-gate 			if ((ip->i_perm & (IEXEC | (IEXEC >> 5) |
33608059SDonghai.Qiao@Sun.COM 			    (IEXEC >> 10))) != 0 &&
33610Sstevel@tonic-gate 			    (ip->i_char & (ISUID | ISGID)) != 0 &&
33620Sstevel@tonic-gate 			    secpolicy_vnode_setid_retain(cr,
33630Sstevel@tonic-gate 			    (ip->i_char & ISUID) != 0 && ip->i_uid == 0) != 0) {
33640Sstevel@tonic-gate 				/*
33650Sstevel@tonic-gate 				 * Clear Set-UID & Set-GID bits on
33660Sstevel@tonic-gate 				 * successful write if not privileged
33670Sstevel@tonic-gate 				 * and at least one of the execute bits
33680Sstevel@tonic-gate 				 * is set.  If we always clear Set-GID,
33690Sstevel@tonic-gate 				 * mandatory file and record locking is
33700Sstevel@tonic-gate 				 * unuseable.
33710Sstevel@tonic-gate 				 */
33720Sstevel@tonic-gate 				ip->i_char &= ~(ISUID | ISGID);
33730Sstevel@tonic-gate 			}
33740Sstevel@tonic-gate 		}
33750Sstevel@tonic-gate 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
33760Sstevel@tonic-gate 
33770Sstevel@tonic-gate out:
33780Sstevel@tonic-gate 	/*
33790Sstevel@tonic-gate 	 * Inode is updated according to this table -
33800Sstevel@tonic-gate 	 *
33810Sstevel@tonic-gate 	 *	FSYNC	FDSYNC(posix.4)
33820Sstevel@tonic-gate 	 *	--------------------------
33830Sstevel@tonic-gate 	 *	always@	IATTCHG|IBDWRITE
33840Sstevel@tonic-gate 	 *
33850Sstevel@tonic-gate 	 * @ -  If we are doing synchronous write the only time we should
33860Sstevel@tonic-gate 	 *	not be sync'ing the ip here is if we have the stickyhack
33870Sstevel@tonic-gate 	 *	activated, the file is marked with the sticky bit and
33880Sstevel@tonic-gate 	 *	no exec bit, the file length has not been changed and
33890Sstevel@tonic-gate 	 *	no new blocks have been allocated during this write.
33900Sstevel@tonic-gate 	 */
33910Sstevel@tonic-gate 	if ((ip->i_flag & ISYNC) != 0) {
33920Sstevel@tonic-gate 		/*
33930Sstevel@tonic-gate 		 * we have eliminated nosync
33940Sstevel@tonic-gate 		 */
33950Sstevel@tonic-gate 		if ((ip->i_flag & (IATTCHG|IBDWRITE)) ||
33968059SDonghai.Qiao@Sun.COM 		    ((ioflag & FSYNC) && iupdat_flag)) {
33970Sstevel@tonic-gate 			ud_iupdat(ip, 1);
33980Sstevel@tonic-gate 		}
33990Sstevel@tonic-gate 	}
34000Sstevel@tonic-gate 
34010Sstevel@tonic-gate 	/*
34020Sstevel@tonic-gate 	 * If we've already done a partial-write, terminate
34030Sstevel@tonic-gate 	 * the write but return no error.
34040Sstevel@tonic-gate 	 */
34050Sstevel@tonic-gate 	if (start_resid != uio->uio_resid) {
34060Sstevel@tonic-gate 		error = 0;
34070Sstevel@tonic-gate 	}
34080Sstevel@tonic-gate 	ip->i_flag &= ~(INOACC | ISYNC);
34090Sstevel@tonic-gate 	ITIMES_NOLOCK(ip);
34100Sstevel@tonic-gate 
34110Sstevel@tonic-gate 	return (error);
34120Sstevel@tonic-gate }
34130Sstevel@tonic-gate 
34140Sstevel@tonic-gate int32_t
ud_multi_strat(struct ud_inode * ip,page_t * pp,struct buf * bp,u_offset_t start)34150Sstevel@tonic-gate ud_multi_strat(struct ud_inode *ip,
34160Sstevel@tonic-gate 	page_t *pp, struct buf *bp, u_offset_t start)
34170Sstevel@tonic-gate {
34180Sstevel@tonic-gate 	daddr_t bn;
34190Sstevel@tonic-gate 	int32_t error = 0, io_count, contig, alloc_sz, i;
34200Sstevel@tonic-gate 	uint32_t io_off;
34210Sstevel@tonic-gate 	mio_master_t *mm = NULL;
34220Sstevel@tonic-gate 	mio_slave_t *ms = NULL;
34230Sstevel@tonic-gate 	struct buf *rbp;
34240Sstevel@tonic-gate 
34250Sstevel@tonic-gate 	ASSERT(!(start & PAGEOFFSET));
34260Sstevel@tonic-gate 
34270Sstevel@tonic-gate 	/*
34280Sstevel@tonic-gate 	 * Figure out how many buffers to allocate
34290Sstevel@tonic-gate 	 */
34300Sstevel@tonic-gate 	io_count = 0;
34310Sstevel@tonic-gate 	for (io_off = 0; io_off < bp->b_bcount; io_off += contig) {
34320Sstevel@tonic-gate 		contig = 0;
34330Sstevel@tonic-gate 		if (error = ud_bmap_read(ip, (u_offset_t)(start + io_off),
34348059SDonghai.Qiao@Sun.COM 		    &bn, &contig)) {
34350Sstevel@tonic-gate 			goto end;
34360Sstevel@tonic-gate 		}
34370Sstevel@tonic-gate 		if (contig == 0) {
34380Sstevel@tonic-gate 			goto end;
34390Sstevel@tonic-gate 		}
34400Sstevel@tonic-gate 		contig = MIN(contig, PAGESIZE - io_off);
34410Sstevel@tonic-gate 		if (bn != UDF_HOLE) {
34420Sstevel@tonic-gate 			io_count ++;
34430Sstevel@tonic-gate 		} else {
34440Sstevel@tonic-gate 			/*
34450Sstevel@tonic-gate 			 * HOLE
34460Sstevel@tonic-gate 			 */
34470Sstevel@tonic-gate 			if (bp->b_flags & B_READ) {
34480Sstevel@tonic-gate 
34490Sstevel@tonic-gate 				/*
34500Sstevel@tonic-gate 				 * This is a hole and is read
34510Sstevel@tonic-gate 				 * it should be filled with 0's
34520Sstevel@tonic-gate 				 */
34530Sstevel@tonic-gate 				pagezero(pp, io_off, contig);
34540Sstevel@tonic-gate 			}
34550Sstevel@tonic-gate 		}
34560Sstevel@tonic-gate 	}
34570Sstevel@tonic-gate 
34580Sstevel@tonic-gate 
34590Sstevel@tonic-gate 	if (io_count != 0) {
34600Sstevel@tonic-gate 
34610Sstevel@tonic-gate 		/*
34620Sstevel@tonic-gate 		 * Allocate memory for all the
34630Sstevel@tonic-gate 		 * required number of buffers
34640Sstevel@tonic-gate 		 */
34650Sstevel@tonic-gate 		alloc_sz = sizeof (mio_master_t) +
34668059SDonghai.Qiao@Sun.COM 		    (sizeof (mio_slave_t) * io_count);
34670Sstevel@tonic-gate 		mm = (mio_master_t *)kmem_zalloc(alloc_sz, KM_SLEEP);
34680Sstevel@tonic-gate 		if (mm == NULL) {
34690Sstevel@tonic-gate 			error = ENOMEM;
34700Sstevel@tonic-gate 			goto end;
34710Sstevel@tonic-gate 		}
34720Sstevel@tonic-gate 
34730Sstevel@tonic-gate 		/*
34740Sstevel@tonic-gate 		 * initialize master
34750Sstevel@tonic-gate 		 */
34760Sstevel@tonic-gate 		mutex_init(&mm->mm_mutex, NULL, MUTEX_DEFAULT, NULL);
34770Sstevel@tonic-gate 		mm->mm_size = alloc_sz;
34780Sstevel@tonic-gate 		mm->mm_bp = bp;
34790Sstevel@tonic-gate 		mm->mm_resid = 0;
34800Sstevel@tonic-gate 		mm->mm_error = 0;
34810Sstevel@tonic-gate 		mm->mm_index = master_index++;
34820Sstevel@tonic-gate 
34830Sstevel@tonic-gate 		ms = (mio_slave_t *)(((caddr_t)mm) + sizeof (mio_master_t));
34840Sstevel@tonic-gate 
34850Sstevel@tonic-gate 		/*
34860Sstevel@tonic-gate 		 * Initialize buffers
34870Sstevel@tonic-gate 		 */
34880Sstevel@tonic-gate 		io_count = 0;
34890Sstevel@tonic-gate 		for (io_off = 0; io_off < bp->b_bcount; io_off += contig) {
34900Sstevel@tonic-gate 			contig = 0;
34910Sstevel@tonic-gate 			if (error = ud_bmap_read(ip,
34928059SDonghai.Qiao@Sun.COM 			    (u_offset_t)(start + io_off),
34938059SDonghai.Qiao@Sun.COM 			    &bn, &contig)) {
34940Sstevel@tonic-gate 				goto end;
34950Sstevel@tonic-gate 			}
34960Sstevel@tonic-gate 			ASSERT(contig);
34970Sstevel@tonic-gate 			if ((io_off + contig) > bp->b_bcount) {
34980Sstevel@tonic-gate 				contig = bp->b_bcount - io_off;
34990Sstevel@tonic-gate 			}
35000Sstevel@tonic-gate 			if (bn != UDF_HOLE) {
35010Sstevel@tonic-gate 				/*
35020Sstevel@tonic-gate 				 * Clone the buffer
35030Sstevel@tonic-gate 				 * and prepare to start I/O
35040Sstevel@tonic-gate 				 */
35050Sstevel@tonic-gate 				ms->ms_ptr = mm;
35060Sstevel@tonic-gate 				bioinit(&ms->ms_buf);
35070Sstevel@tonic-gate 				rbp = bioclone(bp, io_off, (size_t)contig,
35088059SDonghai.Qiao@Sun.COM 				    bp->b_edev, bn, ud_slave_done,
35098059SDonghai.Qiao@Sun.COM 				    &ms->ms_buf, KM_NOSLEEP);
35100Sstevel@tonic-gate 				ASSERT(rbp == &ms->ms_buf);
35110Sstevel@tonic-gate 				mm->mm_resid += contig;
35120Sstevel@tonic-gate 				io_count++;
35130Sstevel@tonic-gate 				ms ++;
35140Sstevel@tonic-gate 			}
35150Sstevel@tonic-gate 		}
35160Sstevel@tonic-gate 
35170Sstevel@tonic-gate 		/*
35180Sstevel@tonic-gate 		 * Start I/O's
35190Sstevel@tonic-gate 		 */
35200Sstevel@tonic-gate 		ms = (mio_slave_t *)(((caddr_t)mm) + sizeof (mio_master_t));
35210Sstevel@tonic-gate 		for (i = 0; i < io_count; i++) {
35220Sstevel@tonic-gate 			(void) bdev_strategy(&ms->ms_buf);
35230Sstevel@tonic-gate 			ms ++;
35240Sstevel@tonic-gate 		}
35250Sstevel@tonic-gate 	}
35260Sstevel@tonic-gate 
35270Sstevel@tonic-gate end:
35280Sstevel@tonic-gate 	if (error != 0) {
35290Sstevel@tonic-gate 		bp->b_flags |= B_ERROR;
35300Sstevel@tonic-gate 		bp->b_error = error;
35310Sstevel@tonic-gate 		if (mm != NULL) {
35320Sstevel@tonic-gate 			mutex_destroy(&mm->mm_mutex);
35330Sstevel@tonic-gate 			kmem_free(mm, mm->mm_size);
35340Sstevel@tonic-gate 		}
35350Sstevel@tonic-gate 	}
35360Sstevel@tonic-gate 	return (error);
35370Sstevel@tonic-gate }
35380Sstevel@tonic-gate 
35390Sstevel@tonic-gate int32_t
ud_slave_done(struct buf * bp)35400Sstevel@tonic-gate ud_slave_done(struct buf *bp)
35410Sstevel@tonic-gate {
35420Sstevel@tonic-gate 	mio_master_t *mm;
35430Sstevel@tonic-gate 	int32_t resid;
35440Sstevel@tonic-gate 
35450Sstevel@tonic-gate 	ASSERT(SEMA_HELD(&bp->b_sem));
35460Sstevel@tonic-gate 	ASSERT((bp->b_flags & B_DONE) == 0);
35470Sstevel@tonic-gate 
35480Sstevel@tonic-gate 	mm = ((mio_slave_t *)bp)->ms_ptr;
35490Sstevel@tonic-gate 
35500Sstevel@tonic-gate 	/*
35510Sstevel@tonic-gate 	 * Propagate error and byte count info from slave struct to
35520Sstevel@tonic-gate 	 * the master struct
35530Sstevel@tonic-gate 	 */
35540Sstevel@tonic-gate 	mutex_enter(&mm->mm_mutex);
35550Sstevel@tonic-gate 	if (bp->b_flags & B_ERROR) {
35560Sstevel@tonic-gate 
35570Sstevel@tonic-gate 		/*
35580Sstevel@tonic-gate 		 * If multiple slave buffers get
35590Sstevel@tonic-gate 		 * error we forget the old errors
35600Sstevel@tonic-gate 		 * this is ok because we any way
35610Sstevel@tonic-gate 		 * cannot return multiple errors
35620Sstevel@tonic-gate 		 */
35630Sstevel@tonic-gate 		mm->mm_error = bp->b_error;
35640Sstevel@tonic-gate 	}
35650Sstevel@tonic-gate 	mm->mm_resid -= bp->b_bcount;
35660Sstevel@tonic-gate 	resid = mm->mm_resid;
35670Sstevel@tonic-gate 	mutex_exit(&mm->mm_mutex);
35680Sstevel@tonic-gate 
35690Sstevel@tonic-gate 	/*
35700Sstevel@tonic-gate 	 * free up the resources allocated to cloned buffers.
35710Sstevel@tonic-gate 	 */
35720Sstevel@tonic-gate 	bp_mapout(bp);
35730Sstevel@tonic-gate 	biofini(bp);
35740Sstevel@tonic-gate 
35750Sstevel@tonic-gate 	if (resid == 0) {
35760Sstevel@tonic-gate 
35770Sstevel@tonic-gate 		/*
35780Sstevel@tonic-gate 		 * This is the last I/O operation
35790Sstevel@tonic-gate 		 * clean up and return the original buffer
35800Sstevel@tonic-gate 		 */
35810Sstevel@tonic-gate 		if (mm->mm_error) {
35820Sstevel@tonic-gate 			mm->mm_bp->b_flags |= B_ERROR;
35830Sstevel@tonic-gate 			mm->mm_bp->b_error = mm->mm_error;
35840Sstevel@tonic-gate 		}
35850Sstevel@tonic-gate 		biodone(mm->mm_bp);
35860Sstevel@tonic-gate 		mutex_destroy(&mm->mm_mutex);
35870Sstevel@tonic-gate 		kmem_free(mm, mm->mm_size);
35880Sstevel@tonic-gate 	}
35890Sstevel@tonic-gate 	return (0);
35900Sstevel@tonic-gate }
3591