Home | History | Annotate | Download | only in fs
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   2051  prabahar  * Common Development and Distribution License (the "License").
      6   2051  prabahar  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21      0    stevel /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     22      0    stevel /*	  All Rights Reserved  	*/
     23      0    stevel 
     24      0    stevel 
     25      0    stevel /*
     26   9749       Tim  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     27      0    stevel  * Use is subject to license terms.
     28      0    stevel  */
     29      0    stevel 
     30      0    stevel /*
     31      0    stevel  * Generic vnode operations.
     32      0    stevel  */
     33      0    stevel #include <sys/types.h>
     34      0    stevel #include <sys/param.h>
     35      0    stevel #include <sys/systm.h>
     36      0    stevel #include <sys/errno.h>
     37      0    stevel #include <sys/fcntl.h>
     38      0    stevel #include <sys/flock.h>
     39      0    stevel #include <sys/statvfs.h>
     40      0    stevel #include <sys/vfs.h>
     41      0    stevel #include <sys/vnode.h>
     42      0    stevel #include <sys/proc.h>
     43      0    stevel #include <sys/user.h>
     44      0    stevel #include <sys/unistd.h>
     45      0    stevel #include <sys/cred.h>
     46      0    stevel #include <sys/poll.h>
     47      0    stevel #include <sys/debug.h>
     48      0    stevel #include <sys/cmn_err.h>
     49      0    stevel #include <sys/stream.h>
     50      0    stevel #include <fs/fs_subr.h>
     51  10793       dai #include <fs/fs_reparse.h>
     52  10793       dai #include <sys/door.h>
     53      0    stevel #include <sys/acl.h>
     54      0    stevel #include <sys/share.h>
     55      0    stevel #include <sys/file.h>
     56      0    stevel #include <sys/kmem.h>
     57      0    stevel #include <sys/file.h>
     58      0    stevel #include <sys/nbmlock.h>
     59    789    ahrens #include <acl/acl_common.h>
     60  10793       dai #include <sys/pathname.h>
     61      0    stevel 
     62      0    stevel static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *);
     63   2051  prabahar 
     64   2051  prabahar /*
     65   2051  prabahar  * Tunable to limit the number of retry to recover from STALE error.
     66   2051  prabahar  */
     67   2051  prabahar int fs_estale_retry = 5;
     68  10793       dai 
     69  10793       dai /*
     70  10793       dai  * supports for reparse point door upcall
     71  10793       dai  */
     72  10793       dai static door_handle_t reparsed_door;
     73  10793       dai static kmutex_t reparsed_door_lock;
     74      0    stevel 
     75      0    stevel /*
     76      0    stevel  * The associated operation is not supported by the file system.
     77      0    stevel  */
     78      0    stevel int
     79      0    stevel fs_nosys()
     80      0    stevel {
     81      0    stevel 	return (ENOSYS);
     82      0    stevel }
     83      0    stevel 
     84      0    stevel /*
     85      0    stevel  * The associated operation is invalid (on this vnode).
     86      0    stevel  */
     87      0    stevel int
     88      0    stevel fs_inval()
     89      0    stevel {
     90      0    stevel 	return (EINVAL);
     91      0    stevel }
     92      0    stevel 
     93      0    stevel /*
     94      0    stevel  * The associated operation is valid only for directories.
     95      0    stevel  */
     96      0    stevel int
     97      0    stevel fs_notdir()
     98      0    stevel {
     99      0    stevel 	return (ENOTDIR);
    100      0    stevel }
    101      0    stevel 
    102      0    stevel /*
    103      0    stevel  * Free the file system specific resources. For the file systems that
    104      0    stevel  * do not support the forced unmount, it will be a nop function.
    105      0    stevel  */
    106      0    stevel 
    107      0    stevel /*ARGSUSED*/
    108      0    stevel void
    109      0    stevel fs_freevfs(vfs_t *vfsp)
    110      0    stevel {
    111      0    stevel }
    112      0    stevel 
    113      0    stevel /* ARGSUSED */
    114      0    stevel int
    115      0    stevel fs_nosys_map(struct vnode *vp,
    116      0    stevel 	offset_t off,
    117      0    stevel 	struct as *as,
    118      0    stevel 	caddr_t *addrp,
    119      0    stevel 	size_t len,
    120      0    stevel 	uchar_t prot,
    121      0    stevel 	uchar_t maxprot,
    122      0    stevel 	uint_t flags,
    123   5331       amw 	struct cred *cr,
    124   5331       amw 	caller_context_t *ct)
    125      0    stevel {
    126      0    stevel 	return (ENOSYS);
    127      0    stevel }
    128      0    stevel 
    129      0    stevel /* ARGSUSED */
    130      0    stevel int
    131      0    stevel fs_nosys_addmap(struct vnode *vp,
    132      0    stevel 	offset_t off,
    133      0    stevel 	struct as *as,
    134      0    stevel 	caddr_t addr,
    135      0    stevel 	size_t len,
    136      0    stevel 	uchar_t prot,
    137      0    stevel 	uchar_t maxprot,
    138      0    stevel 	uint_t flags,
    139   5331       amw 	struct cred *cr,
    140   5331       amw 	caller_context_t *ct)
    141      0    stevel {
    142      0    stevel 	return (ENOSYS);
    143      0    stevel }
    144      0    stevel 
    145      0    stevel /* ARGSUSED */
    146      0    stevel int
    147      0    stevel fs_nosys_poll(vnode_t *vp,
    148      0    stevel 	register short events,
    149      0    stevel 	int anyyet,
    150      0    stevel 	register short *reventsp,
    151   5331       amw 	struct pollhead **phpp,
    152   5331       amw 	caller_context_t *ct)
    153      0    stevel {
    154      0    stevel 	return (ENOSYS);
    155      0    stevel }
    156      0    stevel 
    157      0    stevel 
    158      0    stevel /*
    159      0    stevel  * The file system has nothing to sync to disk.  However, the
    160      0    stevel  * VFS_SYNC operation must not fail.
    161      0    stevel  */
    162      0    stevel /* ARGSUSED */
    163      0    stevel int
    164      0    stevel fs_sync(struct vfs *vfspp, short flag, cred_t *cr)
    165   5331       amw {
    166   5331       amw 	return (0);
    167   5331       amw }
    168   5331       amw 
    169   5331       amw /*
    170   5331       amw  * Does nothing but VOP_FSYNC must not fail.
    171   5331       amw  */
    172   5331       amw /* ARGSUSED */
    173   5331       amw int
    174   5331       amw fs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
    175   5331       amw {
    176   5331       amw 	return (0);
    177   5331       amw }
    178   5331       amw 
    179   5331       amw /*
    180   5331       amw  * Does nothing but VOP_PUTPAGE must not fail.
    181   5331       amw  */
    182   5331       amw /* ARGSUSED */
    183   5331       amw int
    184   5331       amw fs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
    185   5331       amw 	caller_context_t *ctp)
    186   5331       amw {
    187   5331       amw 	return (0);
    188   5331       amw }
    189   5331       amw 
    190   5331       amw /*
    191   5331       amw  * Does nothing but VOP_IOCTL must not fail.
    192   5331       amw  */
    193   5331       amw /* ARGSUSED */
    194   5331       amw int
    195   5331       amw fs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred,
    196   5331       amw 	int *rvalp)
    197      0    stevel {
    198      0    stevel 	return (0);
    199      0    stevel }
    200      0    stevel 
    201      0    stevel /*
    202      0    stevel  * Read/write lock/unlock.  Does nothing.
    203      0    stevel  */
    204      0    stevel /* ARGSUSED */
    205      0    stevel int
    206      0    stevel fs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
    207      0    stevel {
    208      0    stevel 	return (-1);
    209      0    stevel }
    210      0    stevel 
    211      0    stevel /* ARGSUSED */
    212      0    stevel void
    213      0    stevel fs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
    214      0    stevel {
    215      0    stevel }
    216      0    stevel 
    217      0    stevel /*
    218      0    stevel  * Compare two vnodes.
    219      0    stevel  */
    220   5331       amw /*ARGSUSED2*/
    221      0    stevel int
    222   5331       amw fs_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
    223      0    stevel {
    224      0    stevel 	return (vp1 == vp2);
    225      0    stevel }
    226      0    stevel 
    227      0    stevel /*
    228      0    stevel  * No-op seek operation.
    229      0    stevel  */
    230      0    stevel /* ARGSUSED */
    231      0    stevel int
    232   5331       amw fs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
    233      0    stevel {
    234      0    stevel 	return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0);
    235      0    stevel }
    236      0    stevel 
    237      0    stevel /*
    238      0    stevel  * File and record locking.
    239      0    stevel  */
    240      0    stevel /* ARGSUSED */
    241      0    stevel int
    242      0    stevel fs_frlock(register vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
    243   5331       amw 	offset_t offset, flk_callback_t *flk_cbp, cred_t *cr,
    244   5331       amw 	caller_context_t *ct)
    245      0    stevel {
    246      0    stevel 	int frcmd;
    247      0    stevel 	int nlmid;
    248      0    stevel 	int error = 0;
    249      0    stevel 	flk_callback_t serialize_callback;
    250      0    stevel 	int serialize = 0;
    251   5331       amw 	v_mode_t mode;
    252      0    stevel 
    253      0    stevel 	switch (cmd) {
    254      0    stevel 
    255      0    stevel 	case F_GETLK:
    256      0    stevel 	case F_O_GETLK:
    257      0    stevel 		if (flag & F_REMOTELOCK) {
    258      0    stevel 			frcmd = RCMDLCK;
    259   5331       amw 		} else if (flag & F_PXFSLOCK) {
    260   5331       amw 			frcmd = PCMDLCK;
    261   5331       amw 		} else {
    262   5331       amw 			frcmd = 0;
    263   5331       amw 			bfp->l_pid = ttoproc(curthread)->p_pid;
    264   5331       amw 			bfp->l_sysid = 0;
    265      0    stevel 		}
    266      0    stevel 		break;
    267      0    stevel 
    268      0    stevel 	case F_SETLK_NBMAND:
    269      0    stevel 		/*
    270      0    stevel 		 * Are NBMAND locks allowed on this file?
    271      0    stevel 		 */
    272      0    stevel 		if (!vp->v_vfsp ||
    273      0    stevel 		    !(vp->v_vfsp->vfs_flag & VFS_NBMAND)) {
    274      0    stevel 			error = EINVAL;
    275      0    stevel 			goto done;
    276      0    stevel 		}
    277      0    stevel 		if (vp->v_type != VREG) {
    278      0    stevel 			error = EINVAL;
    279      0    stevel 			goto done;
    280      0    stevel 		}
    281      0    stevel 		/*FALLTHROUGH*/
    282      0    stevel 
    283      0    stevel 	case F_SETLK:
    284   5331       amw 		if (flag & F_REMOTELOCK) {
    285   5331       amw 			frcmd = SETFLCK|RCMDLCK;
    286   5331       amw 		} else if (flag & F_PXFSLOCK) {
    287   5331       amw 			frcmd = SETFLCK|PCMDLCK;
    288   5331       amw 		} else {
    289   5331       amw 			frcmd = SETFLCK;
    290   5331       amw 			bfp->l_pid = ttoproc(curthread)->p_pid;
    291   5331       amw 			bfp->l_sysid = 0;
    292   5331       amw 		}
    293   5331       amw 		if (cmd == F_SETLK_NBMAND &&
    294   5331       amw 		    (bfp->l_type == F_RDLCK || bfp->l_type == F_WRLCK)) {
    295   5331       amw 			frcmd |= NBMLCK;
    296   5331       amw 		}
    297   7961   Natalie 
    298      0    stevel 		if (nbl_need_check(vp)) {
    299      0    stevel 			nbl_start_crit(vp, RW_WRITER);
    300      0    stevel 			serialize = 1;
    301   5331       amw 			if (frcmd & NBMLCK) {
    302   5331       amw 				mode = (bfp->l_type == F_RDLCK) ?
    303   5331       amw 				    V_READ : V_RDANDWR;
    304   5331       amw 				if (vn_is_mapped(vp, mode)) {
    305   5331       amw 					error = EAGAIN;
    306   5331       amw 					goto done;
    307   5331       amw 				}
    308      0    stevel 			}
    309      0    stevel 		}
    310      0    stevel 		break;
    311      0    stevel 
    312      0    stevel 	case F_SETLKW:
    313   5331       amw 		if (flag & F_REMOTELOCK) {
    314   5331       amw 			frcmd = SETFLCK|SLPFLCK|RCMDLCK;
    315   5331       amw 		} else if (flag & F_PXFSLOCK) {
    316   5331       amw 			frcmd = SETFLCK|SLPFLCK|PCMDLCK;
    317   5331       amw 		} else {
    318   5331       amw 			frcmd = SETFLCK|SLPFLCK;
    319   5331       amw 			bfp->l_pid = ttoproc(curthread)->p_pid;
    320   5331       amw 			bfp->l_sysid = 0;
    321   5331       amw 		}
    322   7961   Natalie 
    323      0    stevel 		if (nbl_need_check(vp)) {
    324      0    stevel 			nbl_start_crit(vp, RW_WRITER);
    325      0    stevel 			serialize = 1;
    326      0    stevel 		}
    327      0    stevel 		break;
    328      0    stevel 
    329      0    stevel 	case F_HASREMOTELOCKS:
    330      0    stevel 		nlmid = GETNLMID(bfp->l_sysid);
    331      0    stevel 		if (nlmid != 0) {	/* booted as a cluster */
    332      0    stevel 			l_has_rmt(bfp) =
    333   5331       amw 			    cl_flk_has_remote_locks_for_nlmid(vp, nlmid);
    334      0    stevel 		} else {		/* not booted as a cluster */
    335      0    stevel 			l_has_rmt(bfp) = flk_has_remote_locks(vp);
    336      0    stevel 		}
    337      0    stevel 
    338      0    stevel 		goto done;
    339      0    stevel 
    340      0    stevel 	default:
    341      0    stevel 		error = EINVAL;
    342      0    stevel 		goto done;
    343      0    stevel 	}
    344      0    stevel 
    345      0    stevel 	/*
    346      0    stevel 	 * If this is a blocking lock request and we're serializing lock
    347      0    stevel 	 * requests, modify the callback list to leave the critical region
    348      0    stevel 	 * while we're waiting for the lock.
    349      0    stevel 	 */
    350      0    stevel 
    351      0    stevel 	if (serialize && (frcmd & SLPFLCK) != 0) {
    352      0    stevel 		flk_add_callback(&serialize_callback,
    353   5331       amw 		    frlock_serialize_blocked, vp, flk_cbp);
    354      0    stevel 		flk_cbp = &serialize_callback;
    355      0    stevel 	}
    356      0    stevel 
    357      0    stevel 	error = reclock(vp, bfp, frcmd, flag, offset, flk_cbp);
    358      0    stevel 
    359      0    stevel done:
    360      0    stevel 	if (serialize)
    361      0    stevel 		nbl_end_crit(vp);
    362      0    stevel 
    363      0    stevel 	return (error);
    364      0    stevel }
    365      0    stevel 
    366      0    stevel /*
    367      0    stevel  * Callback when a lock request blocks and we are serializing requests.  If
    368      0    stevel  * before sleeping, leave the critical region.  If after wakeup, reenter
    369      0    stevel  * the critical region.
    370      0    stevel  */
    371      0    stevel 
    372      0    stevel static callb_cpr_t *
    373      0    stevel frlock_serialize_blocked(flk_cb_when_t when, void *infop)
    374      0    stevel {
    375      0    stevel 	vnode_t *vp = (vnode_t *)infop;
    376      0    stevel 
    377      0    stevel 	if (when == FLK_BEFORE_SLEEP)
    378      0    stevel 		nbl_end_crit(vp);
    379      0    stevel 	else {
    380      0    stevel 		nbl_start_crit(vp, RW_WRITER);
    381      0    stevel 	}
    382      0    stevel 
    383      0    stevel 	return (NULL);
    384      0    stevel }
    385      0    stevel 
    386      0    stevel /*
    387      0    stevel  * Allow any flags.
    388      0    stevel  */
    389      0    stevel /* ARGSUSED */
    390      0    stevel int
    391   5331       amw fs_setfl(
    392   5331       amw 	vnode_t *vp,
    393   5331       amw 	int oflags,
    394   5331       amw 	int nflags,
    395   5331       amw 	cred_t *cr,
    396   5331       amw 	caller_context_t *ct)
    397      0    stevel {
    398      0    stevel 	return (0);
    399      0    stevel }
    400      0    stevel 
    401      0    stevel /*
    402      0    stevel  * Return the answer requested to poll() for non-device files.
    403      0    stevel  * Only POLLIN, POLLRDNORM, and POLLOUT are recognized.
    404      0    stevel  */
    405      0    stevel struct pollhead fs_pollhd;
    406      0    stevel 
    407      0    stevel /* ARGSUSED */
    408      0    stevel int
    409      0    stevel fs_poll(vnode_t *vp,
    410      0    stevel 	register short events,
    411      0    stevel 	int anyyet,
    412      0    stevel 	register short *reventsp,
    413   5331       amw 	struct pollhead **phpp,
    414   5331       amw 	caller_context_t *ct)
    415      0    stevel {
    416      0    stevel 	*reventsp = 0;
    417      0    stevel 	if (events & POLLIN)
    418      0    stevel 		*reventsp |= POLLIN;
    419      0    stevel 	if (events & POLLRDNORM)
    420      0    stevel 		*reventsp |= POLLRDNORM;
    421      0    stevel 	if (events & POLLRDBAND)
    422      0    stevel 		*reventsp |= POLLRDBAND;
    423      0    stevel 	if (events & POLLOUT)
    424      0    stevel 		*reventsp |= POLLOUT;
    425      0    stevel 	if (events & POLLWRBAND)
    426      0    stevel 		*reventsp |= POLLWRBAND;
    427      0    stevel 	*phpp = !anyyet && !*reventsp ? &fs_pollhd : (struct pollhead *)NULL;
    428      0    stevel 	return (0);
    429      0    stevel }
    430      0    stevel 
    431      0    stevel /*
    432      0    stevel  * POSIX pathconf() support.
    433      0    stevel  */
    434      0    stevel /* ARGSUSED */
    435      0    stevel int
    436   5331       amw fs_pathconf(
    437   5331       amw 	vnode_t *vp,
    438   5331       amw 	int cmd,
    439   5331       amw 	ulong_t *valp,
    440   5331       amw 	cred_t *cr,
    441   5331       amw 	caller_context_t *ct)
    442      0    stevel {
    443      0    stevel 	register ulong_t val;
    444      0    stevel 	register int error = 0;
    445      0    stevel 	struct statvfs64 vfsbuf;
    446      0    stevel 
    447      0    stevel 	switch (cmd) {
    448      0    stevel 
    449      0    stevel 	case _PC_LINK_MAX:
    450      0    stevel 		val = MAXLINK;
    451      0    stevel 		break;
    452      0    stevel 
    453      0    stevel 	case _PC_MAX_CANON:
    454      0    stevel 		val = MAX_CANON;
    455      0    stevel 		break;
    456      0    stevel 
    457      0    stevel 	case _PC_MAX_INPUT:
    458      0    stevel 		val = MAX_INPUT;
    459      0    stevel 		break;
    460      0    stevel 
    461      0    stevel 	case _PC_NAME_MAX:
    462      0    stevel 		bzero(&vfsbuf, sizeof (vfsbuf));
    463      0    stevel 		if (error = VFS_STATVFS(vp->v_vfsp, &vfsbuf))
    464      0    stevel 			break;
    465      0    stevel 		val = vfsbuf.f_namemax;
    466      0    stevel 		break;
    467      0    stevel 
    468      0    stevel 	case _PC_PATH_MAX:
    469      0    stevel 	case _PC_SYMLINK_MAX:
    470      0    stevel 		val = MAXPATHLEN;
    471      0    stevel 		break;
    472      0    stevel 
    473      0    stevel 	case _PC_PIPE_BUF:
    474      0    stevel 		val = PIPE_BUF;
    475      0    stevel 		break;
    476      0    stevel 
    477      0    stevel 	case _PC_NO_TRUNC:
    478      0    stevel 		if (vp->v_vfsp->vfs_flag & VFS_NOTRUNC)
    479      0    stevel 			val = 1;	/* NOTRUNC is enabled for vp */
    480      0    stevel 		else
    481      0    stevel 			val = (ulong_t)-1;
    482      0    stevel 		break;
    483      0    stevel 
    484      0    stevel 	case _PC_VDISABLE:
    485      0    stevel 		val = _POSIX_VDISABLE;
    486      0    stevel 		break;
    487      0    stevel 
    488      0    stevel 	case _PC_CHOWN_RESTRICTED:
    489      0    stevel 		if (rstchown)
    490      0    stevel 			val = rstchown; /* chown restricted enabled */
    491      0    stevel 		else
    492      0    stevel 			val = (ulong_t)-1;
    493      0    stevel 		break;
    494      0    stevel 
    495      0    stevel 	case _PC_FILESIZEBITS:
    496      0    stevel 
    497      0    stevel 		/*
    498      0    stevel 		 * If ever we come here it means that underlying file system
    499      0    stevel 		 * does not recognise the command and therefore this
    500      0    stevel 		 * configurable limit cannot be determined. We return -1
    501      0    stevel 		 * and don't change errno.
    502      0    stevel 		 */
    503      0    stevel 
    504      0    stevel 		val = (ulong_t)-1;    /* large file support */
    505      0    stevel 		break;
    506      0    stevel 
    507      0    stevel 	case _PC_ACL_ENABLED:
    508      0    stevel 		val = 0;
    509      0    stevel 		break;
    510      0    stevel 
    511   5331       amw 	case _PC_CASE_BEHAVIOR:
    512   5331       amw 		val = _CASE_SENSITIVE;
    513   5331       amw 		if (vfs_has_feature(vp->v_vfsp, VFSFT_CASEINSENSITIVE) == 1)
    514   5331       amw 			val |= _CASE_INSENSITIVE;
    515   5331       amw 		if (vfs_has_feature(vp->v_vfsp, VFSFT_NOCASESENSITIVE) == 1)
    516   5331       amw 			val &= ~_CASE_SENSITIVE;
    517   5331       amw 		break;
    518   5331       amw 
    519   5331       amw 	case _PC_SATTR_ENABLED:
    520   5331       amw 	case _PC_SATTR_EXISTS:
    521   5331       amw 		val = 0;
    522   5331       amw 		break;
    523   5331       amw 
    524   9749       Tim 	case _PC_ACCESS_FILTERING:
    525   9749       Tim 		val = 0;
    526   9749       Tim 		break;
    527   9749       Tim 
    528      0    stevel 	default:
    529      0    stevel 		error = EINVAL;
    530      0    stevel 		break;
    531      0    stevel 	}
    532      0    stevel 
    533      0    stevel 	if (error == 0)
    534      0    stevel 		*valp = val;
    535      0    stevel 	return (error);
    536      0    stevel }
    537      0    stevel 
    538      0    stevel /*
    539      0    stevel  * Dispose of a page.
    540      0    stevel  */
    541      0    stevel /* ARGSUSED */
    542      0    stevel void
    543   5331       amw fs_dispose(
    544   5331       amw 	struct vnode *vp,
    545   5331       amw 	page_t *pp,
    546   5331       amw 	int fl,
    547   5331       amw 	int dn,
    548   5331       amw 	struct cred *cr,
    549   5331       amw 	caller_context_t *ct)
    550      0    stevel {
    551      0    stevel 
    552      0    stevel 	ASSERT(fl == B_FREE || fl == B_INVAL);
    553      0    stevel 
    554      0    stevel 	if (fl == B_FREE)
    555      0    stevel 		page_free(pp, dn);
    556      0    stevel 	else
    557      0    stevel 		page_destroy(pp, dn);
    558      0    stevel }
    559      0    stevel 
    560      0    stevel /* ARGSUSED */
    561      0    stevel void
    562   5331       amw fs_nodispose(
    563   5331       amw 	struct vnode *vp,
    564   5331       amw 	page_t *pp,
    565   5331       amw 	int fl,
    566   5331       amw 	int dn,
    567   5331       amw 	struct cred *cr,
    568   5331       amw 	caller_context_t *ct)
    569      0    stevel {
    570      0    stevel 	cmn_err(CE_PANIC, "fs_nodispose invoked");
    571      0    stevel }
    572      0    stevel 
    573      0    stevel /*
    574      0    stevel  * fabricate acls for file systems that do not support acls.
    575      0    stevel  */
    576      0    stevel /* ARGSUSED */
    577      0    stevel int
    578   5331       amw fs_fab_acl(
    579   5331       amw 	vnode_t *vp,
    580   5331       amw 	vsecattr_t *vsecattr,
    581   5331       amw 	int flag,
    582   5331       amw 	cred_t *cr,
    583   5331       amw 	caller_context_t *ct)
    584      0    stevel {
    585      0    stevel 	aclent_t	*aclentp;
    586   2123     szhou 	ace_t		*acep;
    587      0    stevel 	struct vattr	vattr;
    588      0    stevel 	int		error;
    589   5331       amw 	size_t		aclsize;
    590      0    stevel 
    591      0    stevel 	vsecattr->vsa_aclcnt	= 0;
    592   5331       amw 	vsecattr->vsa_aclentsz	= 0;
    593      0    stevel 	vsecattr->vsa_aclentp	= NULL;
    594      0    stevel 	vsecattr->vsa_dfaclcnt	= 0;	/* Default ACLs are not fabricated */
    595      0    stevel 	vsecattr->vsa_dfaclentp	= NULL;
    596      0    stevel 
    597   2123     szhou 	vattr.va_mask = AT_MODE | AT_UID | AT_GID;
    598   5331       amw 	if (error = VOP_GETATTR(vp, &vattr, 0, cr, ct))
    599   2123     szhou 		return (error);
    600   2123     szhou 
    601   2143     marks 	if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) {
    602   5331       amw 		aclsize = 4 * sizeof (aclent_t);
    603      0    stevel 		vsecattr->vsa_aclcnt	= 4; /* USER, GROUP, OTHER, and CLASS */
    604   5331       amw 		vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP);
    605      0    stevel 		aclentp = vsecattr->vsa_aclentp;
    606      0    stevel 
    607      0    stevel 		aclentp->a_type = USER_OBJ;	/* Owner */
    608      0    stevel 		aclentp->a_perm = ((ushort_t)(vattr.va_mode & 0700)) >> 6;
    609      0    stevel 		aclentp->a_id = vattr.va_uid;   /* Really undefined */
    610      0    stevel 		aclentp++;
    611      0    stevel 
    612      0    stevel 		aclentp->a_type = GROUP_OBJ;    /* Group */
    613      0    stevel 		aclentp->a_perm = ((ushort_t)(vattr.va_mode & 0070)) >> 3;
    614      0    stevel 		aclentp->a_id = vattr.va_gid;   /* Really undefined */
    615      0    stevel 		aclentp++;
    616      0    stevel 
    617      0    stevel 		aclentp->a_type = OTHER_OBJ;    /* Other */
    618      0    stevel 		aclentp->a_perm = vattr.va_mode & 0007;
    619   4321    casper 		aclentp->a_id = (gid_t)-1;	/* Really undefined */
    620      0    stevel 		aclentp++;
    621      0    stevel 
    622      0    stevel 		aclentp->a_type = CLASS_OBJ;    /* Class */
    623   2123     szhou 		aclentp->a_perm = (ushort_t)(0007);
    624   4321    casper 		aclentp->a_id = (gid_t)-1;	/* Really undefined */
    625   2143     marks 	} else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) {
    626   5331       amw 		aclsize = 6 * sizeof (ace_t);
    627   2123     szhou 		vsecattr->vsa_aclcnt	= 6;
    628   5331       amw 		vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP);
    629   5331       amw 		vsecattr->vsa_aclentsz = aclsize;
    630   2123     szhou 		acep = vsecattr->vsa_aclentp;
    631   2123     szhou 		(void) memcpy(acep, trivial_acl, sizeof (ace_t) * 6);
    632   2123     szhou 		adjust_ace_pair(acep, (vattr.va_mode & 0700) >> 6);
    633   2123     szhou 		adjust_ace_pair(acep + 2, (vattr.va_mode & 0070) >> 3);
    634   2123     szhou 		adjust_ace_pair(acep + 4, vattr.va_mode & 0007);
    635   2143     marks 	}
    636      0    stevel 
    637      0    stevel 	return (0);
    638      0    stevel }
    639      0    stevel 
    640      0    stevel /*
    641      0    stevel  * Common code for implementing DOS share reservations
    642      0    stevel  */
    643      0    stevel /* ARGSUSED4 */
    644      0    stevel int
    645   5331       amw fs_shrlock(
    646   5331       amw 	struct vnode *vp,
    647   5331       amw 	int cmd,
    648   5331       amw 	struct shrlock *shr,
    649   5331       amw 	int flag,
    650   5331       amw 	cred_t *cr,
    651   5331       amw 	caller_context_t *ct)
    652      0    stevel {
    653      0    stevel 	int error;
    654      0    stevel 
    655      0    stevel 	/*
    656      0    stevel 	 * Make sure that the file was opened with permissions appropriate
    657      0    stevel 	 * for the request, and make sure the caller isn't trying to sneak
    658      0    stevel 	 * in an NBMAND request.
    659      0    stevel 	 */
    660      0    stevel 	if (cmd == F_SHARE) {
    661      0    stevel 		if (((shr->s_access & F_RDACC) && (flag & FREAD) == 0) ||
    662      0    stevel 		    ((shr->s_access & F_WRACC) && (flag & FWRITE) == 0))
    663      0    stevel 			return (EBADF);
    664   5331       amw 		if (shr->s_access & (F_RMACC | F_MDACC))
    665   5331       amw 			return (EINVAL);
    666   5331       amw 		if (shr->s_deny & (F_MANDDNY | F_RMDNY))
    667      0    stevel 			return (EINVAL);
    668      0    stevel 	}
    669      0    stevel 	if (cmd == F_SHARE_NBMAND) {
    670      0    stevel 		/* make sure nbmand is allowed on the file */
    671      0    stevel 		if (!vp->v_vfsp ||
    672      0    stevel 		    !(vp->v_vfsp->vfs_flag & VFS_NBMAND)) {
    673      0    stevel 			return (EINVAL);
    674      0    stevel 		}
    675      0    stevel 		if (vp->v_type != VREG) {
    676      0    stevel 			return (EINVAL);
    677      0    stevel 		}
    678      0    stevel 	}
    679      0    stevel 
    680      0    stevel 	nbl_start_crit(vp, RW_WRITER);
    681      0    stevel 
    682      0    stevel 	switch (cmd) {
    683      0    stevel 
    684      0    stevel 	case F_SHARE_NBMAND:
    685      0    stevel 		shr->s_deny |= F_MANDDNY;
    686      0    stevel 		/*FALLTHROUGH*/
    687      0    stevel 	case F_SHARE:
    688      0    stevel 		error = add_share(vp, shr);
    689      0    stevel 		break;
    690      0    stevel 
    691      0    stevel 	case F_UNSHARE:
    692      0    stevel 		error = del_share(vp, shr);
    693      0    stevel 		break;
    694      0    stevel 
    695      0    stevel 	case F_HASREMOTELOCKS:
    696      0    stevel 		/*
    697      0    stevel 		 * We are overloading this command to refer to remote
    698      0    stevel 		 * shares as well as remote locks, despite its name.
    699      0    stevel 		 */
    700      0    stevel 		shr->s_access = shr_has_remote_shares(vp, shr->s_sysid);
    701      0    stevel 		error = 0;
    702      0    stevel 		break;
    703      0    stevel 
    704      0    stevel 	default:
    705      0    stevel 		error = EINVAL;
    706      0    stevel 		break;
    707      0    stevel 	}
    708      0    stevel 
    709      0    stevel 	nbl_end_crit(vp);
    710      0    stevel 	return (error);
    711      0    stevel }
    712      0    stevel 
    713      0    stevel /*ARGSUSED1*/
    714      0    stevel int
    715   5331       amw fs_vnevent_nosupport(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm,
    716   5331       amw     caller_context_t *ct)
    717      0    stevel {
    718      0    stevel 	ASSERT(vp != NULL);
    719      0    stevel 	return (ENOTSUP);
    720      0    stevel }
    721      0    stevel 
    722      0    stevel /*ARGSUSED1*/
    723      0    stevel int
    724   5331       amw fs_vnevent_support(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm,
    725   5331       amw     caller_context_t *ct)
    726      0    stevel {
    727      0    stevel 	ASSERT(vp != NULL);
    728      0    stevel 	return (0);
    729      0    stevel }
    730    789    ahrens 
    731    789    ahrens /*
    732    789    ahrens  * return 1 for non-trivial ACL.
    733    789    ahrens  *
    734    789    ahrens  * NB: It is not necessary for the caller to VOP_RWLOCK since
    735    789    ahrens  *	we only issue VOP_GETSECATTR.
    736    789    ahrens  *
    737    789    ahrens  * Returns 0 == trivial
    738    789    ahrens  *         1 == NOT Trivial
    739    789    ahrens  *	   <0 could not determine.
    740    789    ahrens  */
    741    789    ahrens int
    742    789    ahrens fs_acl_nontrivial(vnode_t *vp, cred_t *cr)
    743    789    ahrens {
    744    789    ahrens 	ulong_t		acl_styles;
    745    789    ahrens 	ulong_t		acl_flavor;
    746    789    ahrens 	vsecattr_t 	vsecattr;
    747    789    ahrens 	int 		error;
    748    789    ahrens 	int		isnontrivial;
    749    789    ahrens 
    750    789    ahrens 	/* determine the forms of ACLs maintained */
    751   5331       amw 	error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &acl_styles, cr, NULL);
    752    789    ahrens 
    753    789    ahrens 	/* clear bits we don't understand and establish default acl_style */
    754    789    ahrens 	acl_styles &= (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED);
    755    789    ahrens 	if (error || (acl_styles == 0))
    756    789    ahrens 		acl_styles = _ACL_ACLENT_ENABLED;
    757    789    ahrens 
    758    789    ahrens 	vsecattr.vsa_aclentp = NULL;
    759    789    ahrens 	vsecattr.vsa_dfaclentp = NULL;
    760    789    ahrens 	vsecattr.vsa_aclcnt = 0;
    761    789    ahrens 	vsecattr.vsa_dfaclcnt = 0;
    762    789    ahrens 
    763    789    ahrens 	while (acl_styles) {
    764    789    ahrens 		/* select one of the styles as current flavor */
    765    789    ahrens 		acl_flavor = 0;
    766    789    ahrens 		if (acl_styles & _ACL_ACLENT_ENABLED) {
    767    789    ahrens 			acl_flavor = _ACL_ACLENT_ENABLED;
    768    789    ahrens 			vsecattr.vsa_mask = VSA_ACLCNT | VSA_DFACLCNT;
    769    789    ahrens 		} else if (acl_styles & _ACL_ACE_ENABLED) {
    770    789    ahrens 			acl_flavor = _ACL_ACE_ENABLED;
    771    789    ahrens 			vsecattr.vsa_mask = VSA_ACECNT | VSA_ACE;
    772    789    ahrens 		}
    773    789    ahrens 
    774    789    ahrens 		ASSERT(vsecattr.vsa_mask && acl_flavor);
    775   5331       amw 		error = VOP_GETSECATTR(vp, &vsecattr, 0, cr, NULL);
    776    789    ahrens 		if (error == 0)
    777    789    ahrens 			break;
    778    789    ahrens 
    779    789    ahrens 		/* that flavor failed */
    780    789    ahrens 		acl_styles &= ~acl_flavor;
    781    789    ahrens 	}
    782    789    ahrens 
    783    789    ahrens 	/* if all styles fail then assume trivial */
    784    789    ahrens 	if (acl_styles == 0)
    785    789    ahrens 		return (0);
    786    789    ahrens 
    787    789    ahrens 	/* process the flavor that worked */
    788    789    ahrens 	isnontrivial = 0;
    789    789    ahrens 	if (acl_flavor & _ACL_ACLENT_ENABLED) {
    790    789    ahrens 		if (vsecattr.vsa_aclcnt > MIN_ACL_ENTRIES)
    791    789    ahrens 			isnontrivial = 1;
    792    789    ahrens 		if (vsecattr.vsa_aclcnt && vsecattr.vsa_aclentp != NULL)
    793    789    ahrens 			kmem_free(vsecattr.vsa_aclentp,
    794    789    ahrens 			    vsecattr.vsa_aclcnt * sizeof (aclent_t));
    795    789    ahrens 		if (vsecattr.vsa_dfaclcnt && vsecattr.vsa_dfaclentp != NULL)
    796    789    ahrens 			kmem_free(vsecattr.vsa_dfaclentp,
    797    789    ahrens 			    vsecattr.vsa_dfaclcnt * sizeof (aclent_t));
    798    789    ahrens 	}
    799    789    ahrens 	if (acl_flavor & _ACL_ACE_ENABLED) {
    800    789    ahrens 
    801    789    ahrens 		isnontrivial = ace_trivial(vsecattr.vsa_aclentp,
    802    789    ahrens 		    vsecattr.vsa_aclcnt);
    803    789    ahrens 
    804    789    ahrens 		if (vsecattr.vsa_aclcnt && vsecattr.vsa_aclentp != NULL)
    805    789    ahrens 			kmem_free(vsecattr.vsa_aclentp,
    806    789    ahrens 			    vsecattr.vsa_aclcnt * sizeof (ace_t));
    807    789    ahrens 		/* ACE has no vsecattr.vsa_dfaclcnt */
    808    789    ahrens 	}
    809    789    ahrens 	return (isnontrivial);
    810    789    ahrens }
    811   2051  prabahar 
    812   2051  prabahar /*
    813   2051  prabahar  * Check whether we need a retry to recover from STALE error.
    814   2051  prabahar  */
    815   2051  prabahar int
    816   2051  prabahar fs_need_estale_retry(int retry_count)
    817   2051  prabahar {
    818   2051  prabahar 	if (retry_count < fs_estale_retry)
    819   2051  prabahar 		return (1);
    820   2051  prabahar 	else
    821   2051  prabahar 		return (0);
    822   2051  prabahar }
    823   5331       amw 
    824   5331       amw 
    825   5331       amw static int (*fs_av_scan)(vnode_t *, cred_t *, int) = NULL;
    826   5331       amw 
    827   5331       amw /*
    828   5331       amw  * Routine for anti-virus scanner to call to register its scanning routine.
    829   5331       amw  */
    830   5331       amw void
    831   5331       amw fs_vscan_register(int (*av_scan)(vnode_t *, cred_t *, int))
    832   5331       amw {
    833   5331       amw 	fs_av_scan = av_scan;
    834   5331       amw }
    835   5331       amw 
    836   5331       amw /*
    837   5331       amw  * Routine for file systems to call to initiate anti-virus scanning.
    838   5331       amw  * Scanning will only be done on REGular files (currently).
    839   5331       amw  */
    840   5331       amw int
    841   5331       amw fs_vscan(vnode_t *vp, cred_t *cr, int async)
    842   5331       amw {
    843   5331       amw 	int ret = 0;
    844   5331       amw 
    845   5331       amw 	if (fs_av_scan && vp->v_type == VREG)
    846   5331       amw 		ret = (*fs_av_scan)(vp, cr, async);
    847   5331       amw 
    848   5331       amw 	return (ret);
    849   5331       amw }
    850  10793       dai 
    851  10793       dai /*
    852  10793       dai  * support functions for reparse point
    853  10793       dai  */
    854  10793       dai /*
    855  10793       dai  * reparse_vnode_parse
    856  10793       dai  *
    857  10793       dai  * Read the symlink data of a reparse point specified by the vnode
    858  10793       dai  * and return the reparse data as name-value pair in the nvlist.
    859  10793       dai  */
    860  10793       dai int
    861  10793       dai reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl)
    862  10793       dai {
    863  10793       dai 	int err;
    864  10793       dai 	char *lkdata;
    865  10793       dai 	struct uio uio;
    866  10793       dai 	struct iovec iov;
    867  10793       dai 
    868  10793       dai 	if (vp == NULL || nvl == NULL)
    869  10793       dai 		return (EINVAL);
    870  10793       dai 
    871  10793       dai 	lkdata = kmem_alloc(MAXREPARSELEN, KM_SLEEP);
    872  10793       dai 
    873  10793       dai 	/*
    874  10793       dai 	 * Set up io vector to read sym link data
    875  10793       dai 	 */
    876  10793       dai 	iov.iov_base = lkdata;
    877  10793       dai 	iov.iov_len = MAXREPARSELEN;
    878  10793       dai 	uio.uio_iov = &iov;
    879  10793       dai 	uio.uio_iovcnt = 1;
    880  10793       dai 	uio.uio_segflg = UIO_SYSSPACE;
    881  10793       dai 	uio.uio_extflg = UIO_COPY_CACHED;
    882  10793       dai 	uio.uio_loffset = (offset_t)0;
    883  10793       dai 	uio.uio_resid = MAXREPARSELEN;
    884  10793       dai 
    885  10793       dai 	if ((err = VOP_READLINK(vp, &uio, kcred, NULL)) == 0) {
    886  10793       dai 		*(lkdata + MAXREPARSELEN - uio.uio_resid) = '\0';
    887  10793       dai 		err = reparse_parse(lkdata, nvl);
    888  10793       dai 	}
    889  10793       dai 	kmem_free(lkdata, MAXREPARSELEN);	/* done with lkdata */
    890  10793       dai 
    891  10793       dai 	return (err);
    892  10793       dai }
    893  10793       dai 
    894  10793       dai void
    895  10793       dai reparse_point_init()
    896  10793       dai {
    897  10793       dai 	mutex_init(&reparsed_door_lock, NULL, MUTEX_DEFAULT, NULL);
    898  10793       dai }
    899  10793       dai 
    900  10793       dai static door_handle_t
    901  10793       dai reparse_door_get_handle()
    902  10793       dai {
    903  10793       dai 	door_handle_t dh;
    904  10793       dai 
    905  10793       dai 	mutex_enter(&reparsed_door_lock);
    906  10793       dai 	if ((dh = reparsed_door) == NULL) {
    907  10793       dai 		if (door_ki_open(REPARSED_DOOR, &reparsed_door) != 0) {
    908  10793       dai 			reparsed_door = NULL;
    909  10793       dai 			dh = NULL;
    910  10793       dai 		} else
    911  10793       dai 			dh = reparsed_door;
    912  10793       dai 	}
    913  10793       dai 	mutex_exit(&reparsed_door_lock);
    914  10793       dai 	return (dh);
    915  10793       dai }
    916  10793       dai 
    917  10793       dai static void
    918  10793       dai reparse_door_reset_handle()
    919  10793       dai {
    920  10793       dai 	mutex_enter(&reparsed_door_lock);
    921  10793       dai 	reparsed_door = NULL;
    922  10793       dai 	mutex_exit(&reparsed_door_lock);
    923  10793       dai }
    924  10793       dai 
    925  10793       dai /*
    926  10793       dai  * reparse_kderef
    927  10793       dai  *
    928  10793       dai  * Accepts the service-specific item from the reparse point and returns
    929  10793       dai  * the service-specific data requested.  The caller specifies the size of
    930  10793       dai  * the buffer provided via *bufsz; the routine will fail with EOVERFLOW
    931  10793       dai  * if the results will not fit in the buffer, in which case, *bufsz will
    932  10793       dai  * contain the number of bytes needed to hold the results.
    933  10793       dai  *
    934  10793       dai  * if ok return 0 and update *bufsize with length of actual result
    935  10793       dai  * else return error code.
    936  10793       dai  */
    937  10793       dai int
    938  10793       dai reparse_kderef(const char *svc_type, const char *svc_data, char *buf,
    939  10793       dai     size_t *bufsize)
    940  10793       dai {
    941  10793       dai 	int err, retries, need_free;
    942  10793       dai 	size_t dlen, res_len;
    943  10793       dai 	char *darg;
    944  10793       dai 	door_arg_t door_args;
    945  10793       dai 	reparsed_door_res_t *resp;
    946  10793       dai 	door_handle_t rp_door;
    947  10793       dai 
    948  10793       dai 	if (svc_type == NULL || svc_data == NULL || buf == NULL ||
    949  10793       dai 	    bufsize == NULL)
    950  10793       dai 		return (EINVAL);
    951  10793       dai 
    952  10793       dai 	/* get reparsed's door handle */
    953  10793       dai 	if ((rp_door = reparse_door_get_handle()) == NULL)
    954  10793       dai 		return (EBADF);
    955  10793       dai 
    956  10793       dai 	/* setup buffer for door_call args and results */
    957  10793       dai 	dlen = strlen(svc_type) + strlen(svc_data) + 2;
    958  10793       dai 	if (*bufsize < dlen) {
    959  10793       dai 		darg = kmem_alloc(dlen, KM_SLEEP);
    960  10793       dai 		need_free = 1;
    961  10793       dai 	} else {
    962  10793       dai 		darg = buf;	/* use same buffer for door's args & results */
    963  10793       dai 		need_free = 0;
    964  10793       dai 	}
    965  10793       dai 
    966  10793       dai 	/* build argument string of door call */
    967  10793       dai 	(void) snprintf(darg, dlen, "%s:%s", svc_type, svc_data);
    968  10793       dai 
    969  10793       dai 	/* setup args for door call */
    970  10793       dai 	door_args.data_ptr = darg;
    971  10793       dai 	door_args.data_size = dlen;
    972  10793       dai 	door_args.desc_ptr = NULL;
    973  10793       dai 	door_args.desc_num = 0;
    974  10793       dai 	door_args.rbuf = buf;
    975  10793       dai 	door_args.rsize = *bufsize;
    976  10793       dai 
    977  10793       dai 	/* do the door_call */
    978  10793       dai 	retries = 0;
    979  10793       dai 	door_ki_hold(rp_door);
    980  10793       dai 	while ((err = door_ki_upcall_limited(rp_door, &door_args,
    981  10793       dai 	    NULL, SIZE_MAX, 0)) != 0) {
    982  10793       dai 		if (err == EAGAIN || err == EINTR) {
    983  10793       dai 			if (++retries < REPARSED_DOORCALL_MAX_RETRY) {
    984  10793       dai 				delay(SEC_TO_TICK(1));
    985  10793       dai 				continue;
    986  10793       dai 			}
    987  10793       dai 		} else if (err == EBADF) {
    988  10793       dai 			/* door server goes away... */
    989  10793       dai 			reparse_door_reset_handle();
    990  10793       dai 		}
    991  10793       dai 		break;
    992  10793       dai 	}
    993  10793       dai 	door_ki_rele(rp_door);
    994  10793       dai 	if (need_free)
    995  10793       dai 		kmem_free(darg, dlen);		/* done with args buffer */
    996  10793       dai 
    997  10793       dai 	if (err != 0)
    998  10793       dai 		return (err);
    999  10793       dai 
   1000  10793       dai 	resp = (reparsed_door_res_t *)door_args.rbuf;
   1001  10793       dai 	if ((err = resp->res_status) == 0) {
   1002  10793       dai 		/*
   1003  10793       dai 		 * have to save the length of the results before the
   1004  10793       dai 		 * bcopy below since it's can be an overlap copy that
   1005  10793       dai 		 * overwrites the reparsed_door_res_t structure at
   1006  10793       dai 		 * the beginning of the buffer.
   1007  10793       dai 		 */
   1008  10793       dai 		res_len = (size_t)resp->res_len;
   1009  10793       dai 
   1010  10793       dai 		/* deref call is ok */
   1011  10793       dai 		if (res_len > *bufsize)
   1012  10793       dai 			err = EOVERFLOW;
   1013  10793       dai 		else
   1014  10793       dai 			bcopy(resp->res_data, buf, res_len);
   1015  10793       dai 		*bufsize = res_len;
   1016  10793       dai 	}
   1017  10793       dai 	if (door_args.rbuf != buf)
   1018  10793       dai 		kmem_free(door_args.rbuf, door_args.rsize);
   1019  10793       dai 
   1020  10793       dai 	return (err);
   1021  10793       dai }
   1022