Home | History | Annotate | Download | only in nfs
      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   1610      thurlow  * Common Development and Distribution License (the "License").
      6   1610      thurlow  * 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 /*
     22   8662       Jordan  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0       stevel  * Use is subject to license terms.
     24      0       stevel  */
     25      0       stevel 
     26      0       stevel /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
     27      0       stevel /* All Rights Reserved */
     28      0       stevel 
     29      0       stevel #include <sys/param.h>
     30      0       stevel #include <sys/types.h>
     31      0       stevel #include <sys/systm.h>
     32      0       stevel #include <sys/cred.h>
     33      0       stevel #include <sys/buf.h>
     34      0       stevel #include <sys/vfs.h>
     35      0       stevel #include <sys/vnode.h>
     36      0       stevel #include <sys/uio.h>
     37      0       stevel #include <sys/errno.h>
     38      0       stevel #include <sys/sysmacros.h>
     39      0       stevel #include <sys/statvfs.h>
     40      0       stevel #include <sys/kmem.h>
     41      0       stevel #include <sys/dirent.h>
     42      0       stevel #include <sys/cmn_err.h>
     43      0       stevel #include <sys/debug.h>
     44      0       stevel #include <sys/systeminfo.h>
     45      0       stevel #include <sys/flock.h>
     46      0       stevel #include <sys/nbmlock.h>
     47      0       stevel #include <sys/policy.h>
     48   4971      jarrett #include <sys/sdt.h>
     49      0       stevel 
     50      0       stevel #include <rpc/types.h>
     51      0       stevel #include <rpc/auth.h>
     52      0       stevel #include <rpc/svc.h>
     53   7387       Robert #include <rpc/rpc_rdma.h>
     54      0       stevel 
     55      0       stevel #include <nfs/nfs.h>
     56      0       stevel #include <nfs/export.h>
     57   7961      Natalie #include <nfs/nfs_cmd.h>
     58      0       stevel 
     59      0       stevel #include <sys/strsubr.h>
     60   4971      jarrett 
     61   4971      jarrett #include <sys/tsol/label.h>
     62   4971      jarrett #include <sys/tsol/tndb.h>
     63   4971      jarrett 
     64   8662       Jordan #include <sys/zone.h>
     65   8662       Jordan 
     66   4971      jarrett #include <inet/ip.h>
     67   4971      jarrett #include <inet/ip6.h>
     68      0       stevel 
     69      0       stevel /*
     70      0       stevel  * These are the interface routines for the server side of the
     71      0       stevel  * Network File System.  See the NFS version 3 protocol specification
     72      0       stevel  * for a description of this interface.
     73      0       stevel  */
     74      0       stevel 
     75      0       stevel #ifdef DEBUG
     76      0       stevel int rfs3_do_pre_op_attr = 1;
     77      0       stevel int rfs3_do_post_op_attr = 1;
     78      0       stevel int rfs3_do_post_op_fh3 = 1;
     79      0       stevel #endif
     80      0       stevel 
     81      0       stevel static writeverf3 write3verf;
     82      0       stevel 
     83      0       stevel static int	sattr3_to_vattr(sattr3 *, struct vattr *);
     84      0       stevel static int	vattr_to_fattr3(struct vattr *, fattr3 *);
     85      0       stevel static int	vattr_to_wcc_attr(struct vattr *, wcc_attr *);
     86      0       stevel static void	vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
     87      0       stevel static void	vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
     88   7387       Robert static int	rdma_setup_read_data3(READ3args *, READ3resok *);
     89      0       stevel 
     90   5599      jwahlig u_longlong_t nfs3_srv_caller_id;
     91   5599      jwahlig 
     92      0       stevel /* ARGSUSED */
     93      0       stevel void
     94      0       stevel rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
     95      0       stevel 	struct svc_req *req, cred_t *cr)
     96      0       stevel {
     97      0       stevel 	int error;
     98      0       stevel 	vnode_t *vp;
     99      0       stevel 	struct vattr va;
    100      0       stevel 
    101      0       stevel 	vp = nfs3_fhtovp(&args->object, exi);
    102   5982          ahl 
    103   5982          ahl 	DTRACE_NFSV3_4(op__getattr__start, struct svc_req *, req,
    104   5982          ahl 	    cred_t *, cr, vnode_t *, vp, GETATTR3args *, args);
    105   5982          ahl 
    106      0       stevel 	if (vp == NULL) {
    107      0       stevel 		error = ESTALE;
    108      0       stevel 		goto out;
    109      0       stevel 	}
    110      0       stevel 
    111      0       stevel 	va.va_mask = AT_ALL;
    112      0       stevel 	error = rfs4_delegated_getattr(vp, &va, 0, cr);
    113      0       stevel 
    114      0       stevel 	if (!error) {
    115      0       stevel 		/* overflow error if time or size is out of range */
    116      0       stevel 		error = vattr_to_fattr3(&va, &resp->resok.obj_attributes);
    117      0       stevel 		if (error)
    118      0       stevel 			goto out;
    119      0       stevel 		resp->status = NFS3_OK;
    120   5982          ahl 
    121   5982          ahl 		DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
    122   5982          ahl 		    cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
    123   5982          ahl 
    124   5982          ahl 		VN_RELE(vp);
    125   5982          ahl 
    126      0       stevel 		return;
    127      0       stevel 	}
    128      0       stevel 
    129      0       stevel out:
    130      0       stevel 	if (curthread->t_flag & T_WOULDBLOCK) {
    131      0       stevel 		curthread->t_flag &= ~T_WOULDBLOCK;
    132      0       stevel 		resp->status = NFS3ERR_JUKEBOX;
    133      0       stevel 	} else
    134      0       stevel 		resp->status = puterrno3(error);
    135   5982          ahl 
    136   5982          ahl 	DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
    137   5982          ahl 	    cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
    138   5982          ahl 
    139   5982          ahl 	if (vp != NULL)
    140   5982          ahl 		VN_RELE(vp);
    141      0       stevel }
    142      0       stevel 
    143   1610      thurlow void *
    144      0       stevel rfs3_getattr_getfh(GETATTR3args *args)
    145      0       stevel {
    146      0       stevel 
    147   1610      thurlow 	return (&args->object);
    148      0       stevel }
    149      0       stevel 
    150      0       stevel void
    151      0       stevel rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
    152      0       stevel 	struct svc_req *req, cred_t *cr)
    153      0       stevel {
    154      0       stevel 	int error;
    155      0       stevel 	vnode_t *vp;
    156      0       stevel 	struct vattr *bvap;
    157      0       stevel 	struct vattr bva;
    158      0       stevel 	struct vattr *avap;
    159      0       stevel 	struct vattr ava;
    160      0       stevel 	int flag;
    161      0       stevel 	int in_crit = 0;
    162      0       stevel 	struct flock64 bf;
    163   5599      jwahlig 	caller_context_t ct;
    164      0       stevel 
    165      0       stevel 	bvap = NULL;
    166      0       stevel 	avap = NULL;
    167      0       stevel 
    168      0       stevel 	vp = nfs3_fhtovp(&args->object, exi);
    169   5982          ahl 
    170   5982          ahl 	DTRACE_NFSV3_4(op__setattr__start, struct svc_req *, req,
    171   5982          ahl 	    cred_t *, cr, vnode_t *, vp, SETATTR3args *, args);
    172   5982          ahl 
    173      0       stevel 	if (vp == NULL) {
    174      0       stevel 		error = ESTALE;
    175      0       stevel 		goto out;
    176      0       stevel 	}
    177      0       stevel 
    178      0       stevel 	error = sattr3_to_vattr(&args->new_attributes, &ava);
    179      0       stevel 	if (error)
    180      0       stevel 		goto out;
    181   4971      jarrett 
    182   4971      jarrett 	if (is_system_labeled()) {
    183   4971      jarrett 		bslabel_t *clabel = req->rq_label;
    184   4971      jarrett 
    185   4971      jarrett 		ASSERT(clabel != NULL);
    186   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opsetattr__clabel, char *,
    187   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
    188   4971      jarrett 
    189   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
    190   9871      Jarrett 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
    191   9871      Jarrett 			    exi)) {
    192   4971      jarrett 				resp->status = NFS3ERR_ACCES;
    193   4971      jarrett 				goto out1;
    194   4971      jarrett 			}
    195   4971      jarrett 		}
    196   4971      jarrett 	}
    197      0       stevel 
    198      0       stevel 	/*
    199      0       stevel 	 * We need to specially handle size changes because of
    200      0       stevel 	 * possible conflicting NBMAND locks. Get into critical
    201      0       stevel 	 * region before VOP_GETATTR, so the size attribute is
    202      0       stevel 	 * valid when checking conflicts.
    203      0       stevel 	 *
    204      0       stevel 	 * Also, check to see if the v4 side of the server has
    205      0       stevel 	 * delegated this file.  If so, then we return JUKEBOX to
    206      0       stevel 	 * allow the client to retrasmit its request.
    207      0       stevel 	 */
    208      0       stevel 	if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
    209      0       stevel 		if (nbl_need_check(vp)) {
    210      0       stevel 			nbl_start_crit(vp, RW_READER);
    211      0       stevel 			in_crit = 1;
    212      0       stevel 		}
    213      0       stevel 	}
    214      0       stevel 
    215      0       stevel 	bva.va_mask = AT_ALL;
    216      0       stevel 	error = rfs4_delegated_getattr(vp, &bva, 0, cr);
    217      0       stevel 
    218      0       stevel 	/*
    219      0       stevel 	 * If we can't get the attributes, then we can't do the
    220      0       stevel 	 * right access checking.  So, we'll fail the request.
    221      0       stevel 	 */
    222      0       stevel 	if (error)
    223      0       stevel 		goto out;
    224      0       stevel 
    225      0       stevel #ifdef DEBUG
    226      0       stevel 	if (rfs3_do_pre_op_attr)
    227      0       stevel 		bvap = &bva;
    228      0       stevel #else
    229      0       stevel 	bvap = &bva;
    230      0       stevel #endif
    231      0       stevel 
    232      0       stevel 	if (rdonly(exi, req) || vn_is_readonly(vp)) {
    233      0       stevel 		resp->status = NFS3ERR_ROFS;
    234      0       stevel 		goto out1;
    235      0       stevel 	}
    236      0       stevel 
    237      0       stevel 	if (args->guard.check &&
    238      0       stevel 	    (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
    239      0       stevel 	    args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
    240      0       stevel 		resp->status = NFS3ERR_NOT_SYNC;
    241      0       stevel 		goto out1;
    242      0       stevel 	}
    243      0       stevel 
    244      0       stevel 	if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
    245      0       stevel 		flag = ATTR_UTIME;
    246      0       stevel 	else
    247      0       stevel 		flag = 0;
    248      0       stevel 
    249      0       stevel 	/*
    250      0       stevel 	 * If the filesystem is exported with nosuid, then mask off
    251      0       stevel 	 * the setuid and setgid bits.
    252      0       stevel 	 */
    253      0       stevel 	if ((ava.va_mask & AT_MODE) && vp->v_type == VREG &&
    254      0       stevel 	    (exi->exi_export.ex_flags & EX_NOSUID))
    255      0       stevel 		ava.va_mode &= ~(VSUID | VSGID);
    256   5599      jwahlig 
    257   5599      jwahlig 	ct.cc_sysid = 0;
    258   5599      jwahlig 	ct.cc_pid = 0;
    259   5599      jwahlig 	ct.cc_caller_id = nfs3_srv_caller_id;
    260   5599      jwahlig 	ct.cc_flags = CC_DONTBLOCK;
    261      0       stevel 
    262      0       stevel 	/*
    263      0       stevel 	 * We need to specially handle size changes because it is
    264      0       stevel 	 * possible for the client to create a file with modes
    265      0       stevel 	 * which indicate read-only, but with the file opened for
    266      0       stevel 	 * writing.  If the client then tries to set the size of
    267      0       stevel 	 * the file, then the normal access checking done in
    268      0       stevel 	 * VOP_SETATTR would prevent the client from doing so,
    269      0       stevel 	 * although it should be legal for it to do so.  To get
    270      0       stevel 	 * around this, we do the access checking for ourselves
    271      0       stevel 	 * and then use VOP_SPACE which doesn't do the access
    272      0       stevel 	 * checking which VOP_SETATTR does. VOP_SPACE can only
    273      0       stevel 	 * operate on VREG files, let VOP_SETATTR handle the other
    274      0       stevel 	 * extremely rare cases.
    275      0       stevel 	 * Also the client should not be allowed to change the
    276      0       stevel 	 * size of the file if there is a conflicting non-blocking
    277      0       stevel 	 * mandatory lock in the region the change.
    278      0       stevel 	 */
    279      0       stevel 	if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
    280      0       stevel 		if (in_crit) {
    281      0       stevel 			u_offset_t offset;
    282      0       stevel 			ssize_t length;
    283      0       stevel 
    284      0       stevel 			if (ava.va_size < bva.va_size) {
    285      0       stevel 				offset = ava.va_size;
    286      0       stevel 				length = bva.va_size - ava.va_size;
    287      0       stevel 			} else {
    288      0       stevel 				offset = bva.va_size;
    289      0       stevel 				length = ava.va_size - bva.va_size;
    290      0       stevel 			}
    291   5331          amw 			if (nbl_conflict(vp, NBL_WRITE, offset, length, 0,
    292   5331          amw 			    NULL)) {
    293      0       stevel 				error = EACCES;
    294      0       stevel 				goto out;
    295      0       stevel 			}
    296      0       stevel 		}
    297      0       stevel 
    298      0       stevel 		if (crgetuid(cr) == bva.va_uid && ava.va_size != bva.va_size) {
    299      0       stevel 			ava.va_mask &= ~AT_SIZE;
    300      0       stevel 			bf.l_type = F_WRLCK;
    301      0       stevel 			bf.l_whence = 0;
    302      0       stevel 			bf.l_start = (off64_t)ava.va_size;
    303      0       stevel 			bf.l_len = 0;
    304      0       stevel 			bf.l_sysid = 0;
    305      0       stevel 			bf.l_pid = 0;
    306      0       stevel 			error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
    307   5599      jwahlig 			    (offset_t)ava.va_size, cr, &ct);
    308      0       stevel 		}
    309      0       stevel 	}
    310      0       stevel 
    311      0       stevel 	if (!error && ava.va_mask)
    312   5599      jwahlig 		error = VOP_SETATTR(vp, &ava, flag, cr, &ct);
    313   5599      jwahlig 
    314   5599      jwahlig 	/* check if a monitor detected a delegation conflict */
    315   5599      jwahlig 	if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
    316   5599      jwahlig 		resp->status = NFS3ERR_JUKEBOX;
    317   5599      jwahlig 		goto out1;
    318   5599      jwahlig 	}
    319      0       stevel 
    320      0       stevel #ifdef DEBUG
    321      0       stevel 	if (rfs3_do_post_op_attr) {
    322      0       stevel 		ava.va_mask = AT_ALL;
    323      0       stevel 		avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
    324      0       stevel 	} else
    325      0       stevel 		avap = NULL;
    326      0       stevel #else
    327      0       stevel 	ava.va_mask = AT_ALL;
    328      0       stevel 	avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
    329      0       stevel #endif
    330      0       stevel 
    331      0       stevel 	/*
    332      0       stevel 	 * Force modified metadata out to stable storage.
    333      0       stevel 	 */
    334   5599      jwahlig 	(void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
    335      0       stevel 
    336      0       stevel 	if (error)
    337      0       stevel 		goto out;
    338      0       stevel 
    339      0       stevel 	if (in_crit)
    340      0       stevel 		nbl_end_crit(vp);
    341      0       stevel 
    342      0       stevel 	resp->status = NFS3_OK;
    343      0       stevel 	vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
    344   5982          ahl 
    345   5982          ahl 	DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
    346   5982          ahl 	    cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
    347   5982          ahl 
    348   5982          ahl 	VN_RELE(vp);
    349   5982          ahl 
    350   5982          ahl 	return;
    351   5982          ahl 
    352   5982          ahl out:
    353   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
    354   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
    355   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
    356   5982          ahl 	} else
    357   5982          ahl 		resp->status = puterrno3(error);
    358   5982          ahl out1:
    359   5982          ahl 	DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
    360   5982          ahl 	    cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
    361   5982          ahl 
    362      0       stevel 	if (vp != NULL) {
    363      0       stevel 		if (in_crit)
    364      0       stevel 			nbl_end_crit(vp);
    365      0       stevel 		VN_RELE(vp);
    366      0       stevel 	}
    367      0       stevel 	vattr_to_wcc_data(bvap, avap, &resp->resfail.obj_wcc);
    368      0       stevel }
    369      0       stevel 
    370   1610      thurlow void *
    371      0       stevel rfs3_setattr_getfh(SETATTR3args *args)
    372      0       stevel {
    373      0       stevel 
    374   1610      thurlow 	return (&args->object);
    375      0       stevel }
    376      0       stevel 
    377      0       stevel /* ARGSUSED */
    378      0       stevel void
    379      0       stevel rfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi,
    380      0       stevel 	struct svc_req *req, cred_t *cr)
    381      0       stevel {
    382      0       stevel 	int error;
    383      0       stevel 	vnode_t *vp;
    384      0       stevel 	vnode_t *dvp;
    385      0       stevel 	struct vattr *vap;
    386      0       stevel 	struct vattr va;
    387      0       stevel 	struct vattr *dvap;
    388      0       stevel 	struct vattr dva;
    389      0       stevel 	nfs_fh3 *fhp;
    390      0       stevel 	struct sec_ol sec = {0, 0};
    391      0       stevel 	bool_t publicfh_flag = FALSE, auth_weak = FALSE;
    392   7961      Natalie 	struct sockaddr *ca;
    393   7961      Natalie 	char *name = NULL;
    394      0       stevel 
    395      0       stevel 	dvap = NULL;
    396      0       stevel 
    397      0       stevel 	/*
    398      0       stevel 	 * Allow lookups from the root - the default
    399      0       stevel 	 * location of the public filehandle.
    400      0       stevel 	 */
    401      0       stevel 	if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
    402      0       stevel 		dvp = rootdir;
    403      0       stevel 		VN_HOLD(dvp);
    404   5982          ahl 
    405   5982          ahl 		DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
    406   5982          ahl 		    cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
    407      0       stevel 	} else {
    408   1610      thurlow 		dvp = nfs3_fhtovp(&args->what.dir, exi);
    409   5982          ahl 
    410   5982          ahl 		DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
    411   5982          ahl 		    cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
    412   5982          ahl 
    413      0       stevel 		if (dvp == NULL) {
    414      0       stevel 			error = ESTALE;
    415      0       stevel 			goto out;
    416      0       stevel 		}
    417      0       stevel 	}
    418      0       stevel 
    419      0       stevel #ifdef DEBUG
    420      0       stevel 	if (rfs3_do_pre_op_attr) {
    421      0       stevel 		dva.va_mask = AT_ALL;
    422   5331          amw 		dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
    423      0       stevel 	}
    424      0       stevel #else
    425      0       stevel 	dva.va_mask = AT_ALL;
    426   5331          amw 	dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
    427      0       stevel #endif
    428      0       stevel 
    429      0       stevel 	if (args->what.name == nfs3nametoolong) {
    430      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
    431      0       stevel 		goto out1;
    432      0       stevel 	}
    433      0       stevel 
    434      0       stevel 	if (args->what.name == NULL || *(args->what.name) == '\0') {
    435      0       stevel 		resp->status = NFS3ERR_ACCES;
    436      0       stevel 		goto out1;
    437      0       stevel 	}
    438      0       stevel 
    439   1610      thurlow 	fhp = &args->what.dir;
    440      0       stevel 	if (strcmp(args->what.name, "..") == 0 &&
    441   1610      thurlow 	    EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
    442      0       stevel 		resp->status = NFS3ERR_NOENT;
    443      0       stevel 		goto out1;
    444      0       stevel 	}
    445      0       stevel 
    446   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
    447   7961      Natalie 	name = nfscmd_convname(ca, exi, args->what.name,
    448   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
    449   7961      Natalie 
    450   7961      Natalie 	if (name == NULL) {
    451   7961      Natalie 		resp->status = NFS3ERR_ACCES;
    452   7961      Natalie 		goto out1;
    453   7961      Natalie 	}
    454   7961      Natalie 
    455      0       stevel 	/*
    456      0       stevel 	 * If the public filehandle is used then allow
    457      0       stevel 	 * a multi-component lookup
    458      0       stevel 	 */
    459   1610      thurlow 	if (PUBLIC_FH3(&args->what.dir)) {
    460      0       stevel 		publicfh_flag = TRUE;
    461   7961      Natalie 		error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
    462   5599      jwahlig 		    &exi, &sec);
    463      0       stevel 		if (error && exi != NULL)
    464   4971      jarrett 			exi_rele(exi); /* See comment below Re: publicfh_flag */
    465   4971      jarrett 		/*
    466   4971      jarrett 		 * Since WebNFS may bypass MOUNT, we need to ensure this
    467   4971      jarrett 		 * request didn't come from an unlabeled admin_low client.
    468   4971      jarrett 		 */
    469   4971      jarrett 		if (is_system_labeled() && error == 0) {
    470   4971      jarrett 			int		addr_type;
    471   4971      jarrett 			void		*ipaddr;
    472   4971      jarrett 			tsol_tpc_t	*tp;
    473   4971      jarrett 
    474   4971      jarrett 			if (ca->sa_family == AF_INET) {
    475   4971      jarrett 				addr_type = IPV4_VERSION;
    476   4971      jarrett 				ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
    477   4971      jarrett 			} else if (ca->sa_family == AF_INET6) {
    478   4971      jarrett 				addr_type = IPV6_VERSION;
    479   4971      jarrett 				ipaddr = &((struct sockaddr_in6 *)
    480   4971      jarrett 				    ca)->sin6_addr;
    481   4971      jarrett 			}
    482   4971      jarrett 			tp = find_tpc(ipaddr, addr_type, B_FALSE);
    483   4971      jarrett 			if (tp == NULL || tp->tpc_tp.tp_doi !=
    484   4971      jarrett 			    l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
    485   4971      jarrett 			    SUN_CIPSO) {
    486   4971      jarrett 				if (exi != NULL)
    487   4971      jarrett 					exi_rele(exi);
    488   4971      jarrett 				VN_RELE(vp);
    489   4971      jarrett 				resp->status = NFS3ERR_ACCES;
    490   4971      jarrett 				error = 1;
    491   4971      jarrett 			}
    492   4971      jarrett 			if (tp != NULL)
    493   4971      jarrett 				TPC_RELE(tp);
    494   4971      jarrett 		}
    495      0       stevel 	} else {
    496   7961      Natalie 		error = VOP_LOOKUP(dvp, name, &vp,
    497   5599      jwahlig 		    NULL, 0, NULL, cr, NULL, NULL, NULL);
    498   4971      jarrett 	}
    499   7961      Natalie 
    500   7961      Natalie 	if (name != args->what.name)
    501   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
    502   4971      jarrett 
    503   4971      jarrett 	if (is_system_labeled() && error == 0) {
    504   4971      jarrett 		bslabel_t *clabel = req->rq_label;
    505   4971      jarrett 
    506   4971      jarrett 		ASSERT(clabel != NULL);
    507   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
    508   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
    509   4971      jarrett 
    510   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
    511   4971      jarrett 			if (!do_rfs_label_check(clabel, dvp,
    512   9871      Jarrett 			    DOMINANCE_CHECK, exi)) {
    513   4971      jarrett 				if (publicfh_flag && exi != NULL)
    514   4971      jarrett 					exi_rele(exi);
    515   4971      jarrett 				VN_RELE(vp);
    516   4971      jarrett 				resp->status = NFS3ERR_ACCES;
    517   4971      jarrett 				error = 1;
    518   4971      jarrett 			}
    519   4971      jarrett 		}
    520      0       stevel 	}
    521      0       stevel 
    522      0       stevel #ifdef DEBUG
    523      0       stevel 	if (rfs3_do_post_op_attr) {
    524      0       stevel 		dva.va_mask = AT_ALL;
    525   5331          amw 		dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
    526      0       stevel 	} else
    527      0       stevel 		dvap = NULL;
    528      0       stevel #else
    529      0       stevel 	dva.va_mask = AT_ALL;
    530   5331          amw 	dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
    531      0       stevel #endif
    532      0       stevel 
    533      0       stevel 	if (error)
    534      0       stevel 		goto out;
    535      0       stevel 
    536      0       stevel 	if (sec.sec_flags & SEC_QUERY) {
    537      0       stevel 		error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
    538      0       stevel 	} else {
    539      0       stevel 		error = makefh3(&resp->resok.object, vp, exi);
    540      0       stevel 		if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
    541      0       stevel 			auth_weak = TRUE;
    542      0       stevel 	}
    543      0       stevel 
    544      0       stevel 	if (error) {
    545      0       stevel 		VN_RELE(vp);
    546      0       stevel 		goto out;
    547      0       stevel 	}
    548      0       stevel 
    549      0       stevel 	/*
    550      0       stevel 	 * If publicfh_flag is true then we have called rfs_publicfh_mclookup
    551      0       stevel 	 * and have obtained a new exportinfo in exi which needs to be
    552      0       stevel 	 * released. Note the the original exportinfo pointed to by exi
    553      0       stevel 	 * will be released by the caller, common_dispatch.
    554      0       stevel 	 */
    555      0       stevel 	if (publicfh_flag)
    556      0       stevel 		exi_rele(exi);
    557      0       stevel 
    558      0       stevel #ifdef DEBUG
    559      0       stevel 	if (rfs3_do_post_op_attr) {
    560      0       stevel 		va.va_mask = AT_ALL;
    561      0       stevel 		vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
    562      0       stevel 	} else
    563      0       stevel 		vap = NULL;
    564      0       stevel #else
    565      0       stevel 	va.va_mask = AT_ALL;
    566      0       stevel 	vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
    567      0       stevel #endif
    568      0       stevel 
    569      0       stevel 	VN_RELE(vp);
    570      0       stevel 
    571      0       stevel 	resp->status = NFS3_OK;
    572      0       stevel 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
    573      0       stevel 	vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
    574      0       stevel 
    575      0       stevel 	/*
    576      0       stevel 	 * If it's public fh, no 0x81, and client's flavor is
    577      0       stevel 	 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
    578      0       stevel 	 * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
    579      0       stevel 	 */
    580      0       stevel 	if (auth_weak)
    581      0       stevel 		resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
    582      0       stevel 
    583   5982          ahl 	DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
    584   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
    585   5982          ahl 	VN_RELE(dvp);
    586   5982          ahl 
    587   5982          ahl 	return;
    588   5982          ahl 
    589   5982          ahl out:
    590   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
    591   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
    592   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
    593   5982          ahl 	} else
    594   5982          ahl 		resp->status = puterrno3(error);
    595   5982          ahl out1:
    596   5982          ahl 	DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
    597   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
    598   5982          ahl 
    599      0       stevel 	if (dvp != NULL)
    600      0       stevel 		VN_RELE(dvp);
    601      0       stevel 	vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);
    602      0       stevel 
    603      0       stevel }
    604      0       stevel 
    605   1610      thurlow void *
    606      0       stevel rfs3_lookup_getfh(LOOKUP3args *args)
    607      0       stevel {
    608      0       stevel 
    609   1610      thurlow 	return (&args->what.dir);
    610      0       stevel }
    611      0       stevel 
    612      0       stevel /* ARGSUSED */
    613      0       stevel void
    614      0       stevel rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi,
    615      0       stevel 	struct svc_req *req, cred_t *cr)
    616      0       stevel {
    617      0       stevel 	int error;
    618      0       stevel 	vnode_t *vp;
    619      0       stevel 	struct vattr *vap;
    620      0       stevel 	struct vattr va;
    621      0       stevel 	int checkwriteperm;
    622   4971      jarrett 	boolean_t dominant_label = B_FALSE;
    623   4971      jarrett 	boolean_t equal_label = B_FALSE;
    624   4971      jarrett 	boolean_t admin_low_client;
    625      0       stevel 
    626      0       stevel 	vap = NULL;
    627      0       stevel 
    628      0       stevel 	vp = nfs3_fhtovp(&args->object, exi);
    629   5982          ahl 
    630   5982          ahl 	DTRACE_NFSV3_4(op__access__start, struct svc_req *, req,
    631   5982          ahl 	    cred_t *, cr, vnode_t *, vp, ACCESS3args *, args);
    632   5982          ahl 
    633      0       stevel 	if (vp == NULL) {
    634      0       stevel 		error = ESTALE;
    635      0       stevel 		goto out;
    636      0       stevel 	}
    637      0       stevel 
    638      0       stevel 	/*
    639      0       stevel 	 * If the file system is exported read only, it is not appropriate
    640      0       stevel 	 * to check write permissions for regular files and directories.
    641      0       stevel 	 * Special files are interpreted by the client, so the underlying
    642      0       stevel 	 * permissions are sent back to the client for interpretation.
    643      0       stevel 	 */
    644      0       stevel 	if (rdonly(exi, req) && (vp->v_type == VREG || vp->v_type == VDIR))
    645      0       stevel 		checkwriteperm = 0;
    646      0       stevel 	else
    647      0       stevel 		checkwriteperm = 1;
    648      0       stevel 
    649      0       stevel 	/*
    650      0       stevel 	 * We need the mode so that we can correctly determine access
    651      0       stevel 	 * permissions relative to a mandatory lock file.  Access to
    652      0       stevel 	 * mandatory lock files is denied on the server, so it might
    653      0       stevel 	 * as well be reflected to the server during the open.
    654      0       stevel 	 */
    655      0       stevel 	va.va_mask = AT_MODE;
    656   5331          amw 	error = VOP_GETATTR(vp, &va, 0, cr, NULL);
    657      0       stevel 	if (error)
    658      0       stevel 		goto out;
    659      0       stevel 
    660      0       stevel #ifdef DEBUG
    661      0       stevel 	if (rfs3_do_post_op_attr)
    662      0       stevel 		vap = &va;
    663      0       stevel #else
    664      0       stevel 	vap = &va;
    665      0       stevel #endif
    666      0       stevel 
    667      0       stevel 	resp->resok.access = 0;
    668      0       stevel 
    669   4971      jarrett 	if (is_system_labeled()) {
    670   4971      jarrett 		bslabel_t *clabel = req->rq_label;
    671   4971      jarrett 
    672   4971      jarrett 		ASSERT(clabel != NULL);
    673   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *,
    674   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
    675   4971      jarrett 
    676   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
    677   4971      jarrett 			if ((equal_label = do_rfs_label_check(clabel, vp,
    678   9871      Jarrett 			    EQUALITY_CHECK, exi)) == B_FALSE) {
    679   4971      jarrett 				dominant_label = do_rfs_label_check(clabel,
    680   9871      Jarrett 				    vp, DOMINANCE_CHECK, exi);
    681   4971      jarrett 			} else
    682   4971      jarrett 				dominant_label = B_TRUE;
    683   4971      jarrett 			admin_low_client = B_FALSE;
    684   4971      jarrett 		} else
    685   4971      jarrett 			admin_low_client = B_TRUE;
    686   4971      jarrett 	}
    687   4971      jarrett 
    688      0       stevel 	if (args->access & ACCESS3_READ) {
    689   5331          amw 		error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
    690      0       stevel 		if (error) {
    691      0       stevel 			if (curthread->t_flag & T_WOULDBLOCK)
    692      0       stevel 				goto out;
    693   4971      jarrett 		} else if (!MANDLOCK(vp, va.va_mode) &&
    694   4971      jarrett 		    (!is_system_labeled() || admin_low_client ||
    695   4971      jarrett 		    dominant_label))
    696      0       stevel 			resp->resok.access |= ACCESS3_READ;
    697      0       stevel 	}
    698      0       stevel 	if ((args->access & ACCESS3_LOOKUP) && vp->v_type == VDIR) {
    699   5331          amw 		error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
    700      0       stevel 		if (error) {
    701      0       stevel 			if (curthread->t_flag & T_WOULDBLOCK)
    702      0       stevel 				goto out;
    703   4971      jarrett 		} else if (!is_system_labeled() || admin_low_client ||
    704   4971      jarrett 		    dominant_label)
    705      0       stevel 			resp->resok.access |= ACCESS3_LOOKUP;
    706      0       stevel 	}
    707      0       stevel 	if (checkwriteperm &&
    708      0       stevel 	    (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND))) {
    709   5331          amw 		error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
    710      0       stevel 		if (error) {
    711      0       stevel 			if (curthread->t_flag & T_WOULDBLOCK)
    712      0       stevel 				goto out;
    713   4971      jarrett 		} else if (!MANDLOCK(vp, va.va_mode) &&
    714   4971      jarrett 		    (!is_system_labeled() || admin_low_client || equal_label)) {
    715      0       stevel 			resp->resok.access |=
    716      0       stevel 			    (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND));
    717      0       stevel 		}
    718      0       stevel 	}
    719      0       stevel 	if (checkwriteperm &&
    720      0       stevel 	    (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) {
    721   5331          amw 		error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
    722      0       stevel 		if (error) {
    723      0       stevel 			if (curthread->t_flag & T_WOULDBLOCK)
    724      0       stevel 				goto out;
    725   4971      jarrett 		} else if (!is_system_labeled() || admin_low_client ||
    726   4971      jarrett 		    equal_label)
    727      0       stevel 			resp->resok.access |= ACCESS3_DELETE;
    728      0       stevel 	}
    729      0       stevel 	if (args->access & ACCESS3_EXECUTE) {
    730   5331          amw 		error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
    731      0       stevel 		if (error) {
    732      0       stevel 			if (curthread->t_flag & T_WOULDBLOCK)
    733      0       stevel 				goto out;
    734   4971      jarrett 		} else if (!MANDLOCK(vp, va.va_mode) &&
    735   4971      jarrett 		    (!is_system_labeled() || admin_low_client ||
    736   4971      jarrett 		    dominant_label))
    737      0       stevel 			resp->resok.access |= ACCESS3_EXECUTE;
    738      0       stevel 	}
    739      0       stevel 
    740      0       stevel #ifdef DEBUG
    741      0       stevel 	if (rfs3_do_post_op_attr) {
    742      0       stevel 		va.va_mask = AT_ALL;
    743      0       stevel 		vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
    744      0       stevel 	} else
    745      0       stevel 		vap = NULL;
    746      0       stevel #else
    747      0       stevel 	va.va_mask = AT_ALL;
    748      0       stevel 	vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
    749      0       stevel #endif
    750      0       stevel 
    751   5982          ahl 	resp->status = NFS3_OK;
    752   5982          ahl 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
    753   5982          ahl 
    754   5982          ahl 	DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
    755   5982          ahl 	    cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
    756   5982          ahl 
    757   5982          ahl 	VN_RELE(vp);
    758   5982          ahl 
    759   5982          ahl 	return;
    760   5982          ahl 
    761   5982          ahl out:
    762   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
    763   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
    764   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
    765   5982          ahl 	} else
    766   5982          ahl 		resp->status = puterrno3(error);
    767   5982          ahl 	DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
    768   5982          ahl 	    cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
    769      0       stevel 	if (vp != NULL)
    770      0       stevel 		VN_RELE(vp);
    771      0       stevel 	vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
    772      0       stevel }
    773      0       stevel 
    774   1610      thurlow void *
    775      0       stevel rfs3_access_getfh(ACCESS3args *args)
    776      0       stevel {
    777      0       stevel 
    778   1610      thurlow 	return (&args->object);
    779      0       stevel }
    780      0       stevel 
    781      0       stevel /* ARGSUSED */
    782      0       stevel void
    783      0       stevel rfs3_readlink(READLINK3args *args, READLINK3res *resp, struct exportinfo *exi,
    784      0       stevel 	struct svc_req *req, cred_t *cr)
    785      0       stevel {
    786      0       stevel 	int error;
    787      0       stevel 	vnode_t *vp;
    788      0       stevel 	struct vattr *vap;
    789      0       stevel 	struct vattr va;
    790      0       stevel 	struct iovec iov;
    791      0       stevel 	struct uio uio;
    792      0       stevel 	char *data;
    793   7961      Natalie 	struct sockaddr *ca;
    794   7961      Natalie 	char *name = NULL;
    795      0       stevel 
    796      0       stevel 	vap = NULL;
    797      0       stevel 
    798      0       stevel 	vp = nfs3_fhtovp(&args->symlink, exi);
    799   5982          ahl 
    800   5982          ahl 	DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req,
    801   5982          ahl 	    cred_t *, cr, vnode_t *, vp, READLINK3args *, args);
    802   5982          ahl 
    803      0       stevel 	if (vp == NULL) {
    804      0       stevel 		error = ESTALE;
    805      0       stevel 		goto out;
    806      0       stevel 	}
    807      0       stevel 
    808      0       stevel 	va.va_mask = AT_ALL;
    809   5331          amw 	error = VOP_GETATTR(vp, &va, 0, cr, NULL);
    810      0       stevel 	if (error)
    811      0       stevel 		goto out;
    812      0       stevel 
    813      0       stevel #ifdef DEBUG
    814      0       stevel 	if (rfs3_do_post_op_attr)
    815      0       stevel 		vap = &va;
    816      0       stevel #else
    817      0       stevel 	vap = &va;
    818      0       stevel #endif
    819      0       stevel 
    820      0       stevel 	if (vp->v_type != VLNK) {
    821      0       stevel 		resp->status = NFS3ERR_INVAL;
    822      0       stevel 		goto out1;
    823      0       stevel 	}
    824      0       stevel 
    825      0       stevel 	if (MANDLOCK(vp, va.va_mode)) {
    826      0       stevel 		resp->status = NFS3ERR_ACCES;
    827      0       stevel 		goto out1;
    828   4971      jarrett 	}
    829   4971      jarrett 
    830   4971      jarrett 	if (is_system_labeled()) {
    831   4971      jarrett 		bslabel_t *clabel = req->rq_label;
    832   4971      jarrett 
    833   4971      jarrett 		ASSERT(clabel != NULL);
    834   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *,
    835   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
    836   4971      jarrett 
    837   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
    838   9871      Jarrett 			if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
    839   9871      Jarrett 			    exi)) {
    840   4971      jarrett 				resp->status = NFS3ERR_ACCES;
    841   4971      jarrett 				goto out1;
    842   4971      jarrett 			}
    843   4971      jarrett 		}
    844      0       stevel 	}
    845      0       stevel 
    846      0       stevel 	data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
    847      0       stevel 
    848      0       stevel 	iov.iov_base = data;
    849      0       stevel 	iov.iov_len = MAXPATHLEN;
    850      0       stevel 	uio.uio_iov = &iov;
    851      0       stevel 	uio.uio_iovcnt = 1;
    852      0       stevel 	uio.uio_segflg = UIO_SYSSPACE;
    853      0       stevel 	uio.uio_extflg = UIO_COPY_CACHED;
    854      0       stevel 	uio.uio_loffset = 0;
    855      0       stevel 	uio.uio_resid = MAXPATHLEN;
    856      0       stevel 
    857   5331          amw 	error = VOP_READLINK(vp, &uio, cr, NULL);
    858   5331          amw 
    859   5331          amw #ifdef DEBUG
    860   5331          amw 	if (rfs3_do_post_op_attr) {
    861   5331          amw 		va.va_mask = AT_ALL;
    862   5331          amw 		vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
    863   5331          amw 	} else
    864   5331          amw 		vap = NULL;
    865   5331          amw #else
    866   5331          amw 	va.va_mask = AT_ALL;
    867   5331          amw 	vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
    868      0       stevel #endif
    869      0       stevel 
    870      0       stevel #if 0 /* notyet */
    871      0       stevel 	/*
    872      0       stevel 	 * Don't do this.  It causes local disk writes when just
    873      0       stevel 	 * reading the file and the overhead is deemed larger
    874      0       stevel 	 * than the benefit.
    875      0       stevel 	 */
    876      0       stevel 	/*
    877      0       stevel 	 * Force modified metadata out to stable storage.
    878      0       stevel 	 */
    879   5331          amw 	(void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
    880      0       stevel #endif
    881      0       stevel 
    882      0       stevel 	if (error) {
    883      0       stevel 		kmem_free(data, MAXPATHLEN + 1);
    884      0       stevel 		goto out;
    885      0       stevel 	}
    886      0       stevel 
    887   7961      Natalie 	*(data + MAXPATHLEN - uio.uio_resid) = '\0';
    888   7961      Natalie 
    889   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
    890   7961      Natalie 	name = nfscmd_convname(ca, exi, data, NFSCMD_CONV_OUTBOUND,
    891   7961      Natalie 	    MAXPATHLEN + 1);
    892   7961      Natalie 
    893   7961      Natalie 	if (name == NULL) {
    894   7961      Natalie 		/*
    895   7961      Natalie 		 * Even though the conversion failed, we return
    896   7961      Natalie 		 * something. We just don't translate it.
    897   7961      Natalie 		 */
    898   7961      Natalie 		name = data;
    899   7961      Natalie 	}
    900   7961      Natalie 
    901      0       stevel 	resp->status = NFS3_OK;
    902      0       stevel 	vattr_to_post_op_attr(vap, &resp->resok.symlink_attributes);
    903   7961      Natalie 	resp->resok.data = name;
    904   5982          ahl 
    905   5982          ahl 	DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
    906   5982          ahl 	    cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
    907   5982          ahl 	VN_RELE(vp);
    908   7961      Natalie 
    909   7961      Natalie 	if (name != data)
    910   7961      Natalie 		kmem_free(data, MAXPATHLEN + 1);
    911   5982          ahl 
    912   5982          ahl 	return;
    913   5982          ahl 
    914   5982          ahl out:
    915   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
    916   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
    917   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
    918   5982          ahl 	} else
    919   5982          ahl 		resp->status = puterrno3(error);
    920   5982          ahl out1:
    921   5982          ahl 	DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
    922   5982          ahl 	    cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
    923      0       stevel 	if (vp != NULL)
    924      0       stevel 		VN_RELE(vp);
    925      0       stevel 	vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes);
    926      0       stevel }
    927      0       stevel 
    928   1610      thurlow void *
    929      0       stevel rfs3_readlink_getfh(READLINK3args *args)
    930      0       stevel {
    931      0       stevel 
    932   1610      thurlow 	return (&args->symlink);
    933      0       stevel }
    934      0       stevel 
    935      0       stevel void
    936      0       stevel rfs3_readlink_free(READLINK3res *resp)
    937      0       stevel {
    938      0       stevel 
    939      0       stevel 	if (resp->status == NFS3_OK)
    940      0       stevel 		kmem_free(resp->resok.data, MAXPATHLEN + 1);
    941      0       stevel }
    942      0       stevel 
    943   7387       Robert /*
    944   7387       Robert  * Server routine to handle read
    945   7387       Robert  * May handle RDMA data as well as mblks
    946   7387       Robert  */
    947      0       stevel /* ARGSUSED */
    948      0       stevel void
    949      0       stevel rfs3_read(READ3args *args, READ3res *resp, struct exportinfo *exi,
    950      0       stevel 	struct svc_req *req, cred_t *cr)
    951      0       stevel {
    952      0       stevel 	int error;
    953      0       stevel 	vnode_t *vp;
    954      0       stevel 	struct vattr *vap;
    955      0       stevel 	struct vattr va;
    956      0       stevel 	struct iovec iov;
    957      0       stevel 	struct uio uio;
    958      0       stevel 	u_offset_t offset;
    959      0       stevel 	mblk_t *mp;
    960      0       stevel 	int alloc_err = 0;
    961      0       stevel 	int in_crit = 0;
    962      0       stevel 	int need_rwunlock = 0;
    963   5599      jwahlig 	caller_context_t ct;
    964      0       stevel 
    965      0       stevel 	vap = NULL;
    966      0       stevel 
    967      0       stevel 	vp = nfs3_fhtovp(&args->file, exi);
    968   5982          ahl 
    969   5982          ahl 	DTRACE_NFSV3_4(op__read__start, struct svc_req *, req,
    970   5982          ahl 	    cred_t *, cr, vnode_t *, vp, READ3args *, args);
    971   5982          ahl 
    972      0       stevel 	if (vp == NULL) {
    973      0       stevel 		error = ESTALE;
    974      0       stevel 		goto out;
    975   4971      jarrett 	}
    976   4971      jarrett 
    977   4971      jarrett 	if (is_system_labeled()) {
    978   4971      jarrett 		bslabel_t *clabel = req->rq_label;
    979   4971      jarrett 
    980   4971      jarrett 		ASSERT(clabel != NULL);
    981   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opread__clabel, char *,
    982   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
    983   4971      jarrett 
    984   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
    985   9871      Jarrett 			if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
    986   9871      Jarrett 			    exi)) {
    987   4971      jarrett 				resp->status = NFS3ERR_ACCES;
    988   4971      jarrett 				goto out1;
    989   4971      jarrett 			}
    990   4971      jarrett 		}
    991      0       stevel 	}
    992      0       stevel 
    993   5599      jwahlig 	ct.cc_sysid = 0;
    994   5599      jwahlig 	ct.cc_pid = 0;
    995   5599      jwahlig 	ct.cc_caller_id = nfs3_srv_caller_id;
    996   5599      jwahlig 	ct.cc_flags = CC_DONTBLOCK;
    997      0       stevel 
    998      0       stevel 	/*
    999      0       stevel 	 * Enter the critical region before calling VOP_RWLOCK
   1000      0       stevel 	 * to avoid a deadlock with write requests.
   1001      0       stevel 	 */
   1002      0       stevel 	if (nbl_need_check(vp)) {
   1003      0       stevel 		nbl_start_crit(vp, RW_READER);
   1004      0       stevel 		in_crit = 1;
   1005   5331          amw 		if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
   1006   5331          amw 		    NULL)) {
   1007      0       stevel 			error = EACCES;
   1008      0       stevel 			goto out;
   1009      0       stevel 		}
   1010      0       stevel 	}
   1011      0       stevel 
   1012   5599      jwahlig 	error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct);
   1013   5599      jwahlig 
   1014   5599      jwahlig 	/* check if a monitor detected a delegation conflict */
   1015   5599      jwahlig 	if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
   1016   5599      jwahlig 		resp->status = NFS3ERR_JUKEBOX;
   1017   5599      jwahlig 		goto out1;
   1018   5599      jwahlig 	}
   1019   5599      jwahlig 
   1020      0       stevel 	need_rwunlock = 1;
   1021      0       stevel 
   1022      0       stevel 	va.va_mask = AT_ALL;
   1023   5599      jwahlig 	error = VOP_GETATTR(vp, &va, 0, cr, &ct);
   1024      0       stevel 
   1025      0       stevel 	/*
   1026      0       stevel 	 * If we can't get the attributes, then we can't do the
   1027      0       stevel 	 * right access checking.  So, we'll fail the request.
   1028      0       stevel 	 */
   1029      0       stevel 	if (error)
   1030      0       stevel 		goto out;
   1031      0       stevel 
   1032      0       stevel #ifdef DEBUG
   1033      0       stevel 	if (rfs3_do_post_op_attr)
   1034      0       stevel 		vap = &va;
   1035      0       stevel #else
   1036      0       stevel 	vap = &va;
   1037      0       stevel #endif
   1038      0       stevel 
   1039      0       stevel 	if (vp->v_type != VREG) {
   1040      0       stevel 		resp->status = NFS3ERR_INVAL;
   1041      0       stevel 		goto out1;
   1042      0       stevel 	}
   1043      0       stevel 
   1044      0       stevel 	if (crgetuid(cr) != va.va_uid) {
   1045   5599      jwahlig 		error = VOP_ACCESS(vp, VREAD, 0, cr, &ct);
   1046   5599      jwahlig 		if (error) {
   1047   5599      jwahlig 			if (curthread->t_flag & T_WOULDBLOCK)
   1048   5599      jwahlig 				goto out;
   1049   5599      jwahlig 			error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct);
   1050      0       stevel 			if (error)
   1051      0       stevel 				goto out;
   1052      0       stevel 		}
   1053      0       stevel 	}
   1054      0       stevel 
   1055      0       stevel 	if (MANDLOCK(vp, va.va_mode)) {
   1056      0       stevel 		resp->status = NFS3ERR_ACCES;
   1057      0       stevel 		goto out1;
   1058      0       stevel 	}
   1059      0       stevel 
   1060      0       stevel 	offset = args->offset;
   1061      0       stevel 	if (offset >= va.va_size) {
   1062   5599      jwahlig 		VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
   1063      0       stevel 		if (in_crit)
   1064      0       stevel 			nbl_end_crit(vp);
   1065      0       stevel 		resp->status = NFS3_OK;
   1066      0       stevel 		vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
   1067      0       stevel 		resp->resok.count = 0;
   1068      0       stevel 		resp->resok.eof = TRUE;
   1069      0       stevel 		resp->resok.data.data_len = 0;
   1070      0       stevel 		resp->resok.data.data_val = NULL;
   1071      0       stevel 		resp->resok.data.mp = NULL;
   1072   7387       Robert 		/* RDMA */
   1073   7387       Robert 		resp->resok.wlist = args->wlist;
   1074   7387       Robert 		resp->resok.wlist_len = resp->resok.count;
   1075   9348  Siddheshwar 		if (resp->resok.wlist)
   1076   9348  Siddheshwar 			clist_zero_len(resp->resok.wlist);
   1077   5982          ahl 		goto done;
   1078      0       stevel 	}
   1079      0       stevel 
   1080      0       stevel 	if (args->count == 0) {
   1081   5599      jwahlig 		VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
   1082      0       stevel 		if (in_crit)
   1083      0       stevel 			nbl_end_crit(vp);
   1084      0       stevel 		resp->status = NFS3_OK;
   1085      0       stevel 		vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
   1086      0       stevel 		resp->resok.count = 0;
   1087      0       stevel 		resp->resok.eof = FALSE;
   1088      0       stevel 		resp->resok.data.data_len = 0;
   1089      0       stevel 		resp->resok.data.data_val = NULL;
   1090      0       stevel 		resp->resok.data.mp = NULL;
   1091   7387       Robert 		/* RDMA */
   1092   7387       Robert 		resp->resok.wlist = args->wlist;
   1093   7387       Robert 		resp->resok.wlist_len = resp->resok.count;
   1094   9348  Siddheshwar 		if (resp->resok.wlist)
   1095   9348  Siddheshwar 			clist_zero_len(resp->resok.wlist);
   1096   5982          ahl 		goto done;
   1097      0       stevel 	}
   1098      0       stevel 
   1099      0       stevel 	/*
   1100      0       stevel 	 * do not allocate memory more the max. allowed
   1101      0       stevel 	 * transfer size
   1102      0       stevel 	 */
   1103      0       stevel 	if (args->count > rfs3_tsize(req))
   1104      0       stevel 		args->count = rfs3_tsize(req);
   1105      0       stevel 
   1106      0       stevel 	/*
   1107   7387       Robert 	 * If returning data via RDMA Write, then grab the chunk list.
   1108   7387       Robert 	 * If we aren't returning READ data w/RDMA_WRITE, then grab
   1109   7387       Robert 	 * a mblk.
   1110   7387       Robert 	 */
   1111   7387       Robert 	if (args->wlist) {
   1112   7387       Robert 		mp = NULL;
   1113   7387       Robert 		(void) rdma_get_wchunk(req, &iov, args->wlist);
   1114   7387       Robert 	} else {
   1115   7387       Robert 		/*
   1116   7387       Robert 		 * mp will contain the data to be sent out in the read reply.
   1117   7387       Robert 		 * This will be freed after the reply has been sent out (by the
   1118   7387       Robert 		 * driver).
   1119   7387       Robert 		 * Let's roundup the data to a BYTES_PER_XDR_UNIT multiple, so
   1120   7387       Robert 		 * that the call to xdrmblk_putmblk() never fails.
   1121   7387       Robert 		 */
   1122   7387       Robert 		mp = allocb_wait(RNDUP(args->count), BPRI_MED, STR_NOSIG,
   1123   7387       Robert 		    &alloc_err);
   1124   7387       Robert 		ASSERT(mp != NULL);
   1125   7387       Robert 		ASSERT(alloc_err == 0);
   1126   7387       Robert 
   1127   7387       Robert 		iov.iov_base = (caddr_t)mp->b_datap->db_base;
   1128   7387       Robert 		iov.iov_len = args->count;
   1129   7387       Robert 	}
   1130   7387       Robert 
   1131      0       stevel 	uio.uio_iov = &iov;
   1132      0       stevel 	uio.uio_iovcnt = 1;
   1133      0       stevel 	uio.uio_segflg = UIO_SYSSPACE;
   1134      0       stevel 	uio.uio_extflg = UIO_COPY_CACHED;
   1135      0       stevel 	uio.uio_loffset = args->offset;
   1136      0       stevel 	uio.uio_resid = args->count;
   1137      0       stevel 
   1138   5599      jwahlig 	error = VOP_READ(vp, &uio, 0, cr, &ct);
   1139      0       stevel 
   1140      0       stevel 	if (error) {
   1141      0       stevel 		freeb(mp);
   1142   5599      jwahlig 		/* check if a monitor detected a delegation conflict */
   1143   5599      jwahlig 		if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
   1144   5599      jwahlig 			resp->status = NFS3ERR_JUKEBOX;
   1145   5599      jwahlig 			goto out1;
   1146   5599      jwahlig 		}
   1147   5599      jwahlig 		goto out;
   1148   5599      jwahlig 	}
   1149   5599      jwahlig 
   1150   5599      jwahlig 	va.va_mask = AT_ALL;
   1151   5599      jwahlig 	error = VOP_GETATTR(vp, &va, 0, cr, &ct);
   1152      0       stevel 
   1153      0       stevel #ifdef DEBUG
   1154      0       stevel 	if (rfs3_do_post_op_attr) {
   1155      0       stevel 		if (error)
   1156      0       stevel 			vap = NULL;
   1157      0       stevel 		else
   1158      0       stevel 			vap = &va;
   1159      0       stevel 	} else
   1160      0       stevel 		vap = NULL;
   1161      0       stevel #else
   1162      0       stevel 	if (error)
   1163      0       stevel 		vap = NULL;
   1164      0       stevel 	else
   1165      0       stevel 		vap = &va;
   1166      0       stevel #endif
   1167      0       stevel 
   1168   5599      jwahlig 	VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
   1169      0       stevel 
   1170      0       stevel 	if (in_crit)
   1171      0       stevel 		nbl_end_crit(vp);
   1172      0       stevel 
   1173      0       stevel 	resp->status = NFS3_OK;
   1174      0       stevel 	vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
   1175      0       stevel 	resp->resok.count = args->count - uio.uio_resid;
   1176      0       stevel 	if (!error && offset + resp->resok.count == va.va_size)
   1177      0       stevel 		resp->resok.eof = TRUE;
   1178      0       stevel 	else
   1179      0       stevel 		resp->resok.eof = FALSE;
   1180      0       stevel 	resp->resok.data.data_len = resp->resok.count;
   1181      0       stevel 	resp->resok.data.mp = mp;
   1182      0       stevel 	resp->resok.size = (uint_t)args->count;
   1183   7387       Robert 
   1184   7387       Robert 	if (args->wlist) {
   1185   7387       Robert 		resp->resok.data.data_val = (caddr_t)iov.iov_base;
   1186   7387       Robert 		if (!rdma_setup_read_data3(args, &(resp->resok))) {
   1187   7387       Robert 			resp->status = NFS3ERR_INVAL;
   1188   7387       Robert 		}
   1189   7387       Robert 	} else {
   1190   7387       Robert 		resp->resok.data.data_val = (caddr_t)mp->b_datap->db_base;
   1191   7387       Robert 		(resp->resok).wlist = NULL;
   1192   7387       Robert 	}
   1193   5982          ahl 
   1194   5982          ahl done:
   1195   5982          ahl 	DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
   1196   5982          ahl 	    cred_t *, cr, vnode_t *, vp, READ3res *, resp);
   1197   5982          ahl 
   1198   5982          ahl 	VN_RELE(vp);
   1199   5982          ahl 
   1200   5982          ahl 	return;
   1201   5982          ahl 
   1202   5982          ahl out:
   1203   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   1204   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   1205   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   1206   5982          ahl 	} else
   1207   5982          ahl 		resp->status = puterrno3(error);
   1208   5982          ahl out1:
   1209   5982          ahl 	DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
   1210   5982          ahl 	    cred_t *, cr, vnode_t *, vp, READ3res *, resp);
   1211   5982          ahl 
   1212      0       stevel 	if (vp != NULL) {
   1213      0       stevel 		if (need_rwunlock)
   1214   5599      jwahlig 			VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
   1215      0       stevel 		if (in_crit)
   1216      0       stevel 			nbl_end_crit(vp);
   1217      0       stevel 		VN_RELE(vp);
   1218      0       stevel 	}
   1219      0       stevel 	vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
   1220      0       stevel }
   1221      0       stevel 
   1222      0       stevel void
   1223      0       stevel rfs3_read_free(READ3res *resp)
   1224      0       stevel {
   1225      0       stevel 	mblk_t *mp;
   1226      0       stevel 
   1227      0       stevel 	if (resp->status == NFS3_OK) {
   1228      0       stevel 		mp = resp->resok.data.mp;
   1229      0       stevel 		if (mp != NULL)
   1230      0       stevel 			freeb(mp);
   1231      0       stevel 	}
   1232      0       stevel }
   1233      0       stevel 
   1234   1610      thurlow void *
   1235      0       stevel rfs3_read_getfh(READ3args *args)
   1236      0       stevel {
   1237      0       stevel 
   1238   1610      thurlow 	return (&args->file);
   1239      0       stevel }
   1240      0       stevel 
   1241      0       stevel #define	MAX_IOVECS	12
   1242      0       stevel 
   1243      0       stevel #ifdef DEBUG
   1244      0       stevel static int rfs3_write_hits = 0;
   1245      0       stevel static int rfs3_write_misses = 0;
   1246      0       stevel #endif
   1247      0       stevel 
   1248      0       stevel void
   1249      0       stevel rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi,
   1250      0       stevel 	struct svc_req *req, cred_t *cr)
   1251      0       stevel {
   1252      0       stevel 	int error;
   1253      0       stevel 	vnode_t *vp;
   1254      0       stevel 	struct vattr *bvap = NULL;
   1255      0       stevel 	struct vattr bva;
   1256      0       stevel 	struct vattr *avap = NULL;
   1257      0       stevel 	struct vattr ava;
   1258      0       stevel 	u_offset_t rlimit;
   1259      0       stevel 	struct uio uio;
   1260      0       stevel 	struct iovec iov[MAX_IOVECS];
   1261      0       stevel 	mblk_t *m;
   1262      0       stevel 	struct iovec *iovp;
   1263      0       stevel 	int iovcnt;
   1264      0       stevel 	int ioflag;
   1265      0       stevel 	cred_t *savecred;
   1266      0       stevel 	int in_crit = 0;
   1267      0       stevel 	int rwlock_ret = -1;
   1268   5599      jwahlig 	caller_context_t ct;
   1269      0       stevel 
   1270      0       stevel 	vp = nfs3_fhtovp(&args->file, exi);
   1271   5982          ahl 
   1272   5982          ahl 	DTRACE_NFSV3_4(op__write__start, struct svc_req *, req,
   1273   5982          ahl 	    cred_t *, cr, vnode_t *, vp, WRITE3args *, args);
   1274   5982          ahl 
   1275   5982          ahl 	if (vp == NULL) {
   1276   5982          ahl 		error = ESTALE;
   1277   5982          ahl 		goto err;
   1278      0       stevel 	}
   1279      0       stevel 
   1280   4971      jarrett 	if (is_system_labeled()) {
   1281   4971      jarrett 		bslabel_t *clabel = req->rq_label;
   1282   4971      jarrett 
   1283   4971      jarrett 		ASSERT(clabel != NULL);
   1284   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
   1285   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   1286   4971      jarrett 
   1287   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   1288   9871      Jarrett 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
   1289   9871      Jarrett 			    exi)) {
   1290   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   1291   5982          ahl 				goto err1;
   1292   4971      jarrett 			}
   1293   4971      jarrett 		}
   1294   4971      jarrett 	}
   1295   4971      jarrett 
   1296   5599      jwahlig 	ct.cc_sysid = 0;
   1297   5599      jwahlig 	ct.cc_pid = 0;
   1298   5599      jwahlig 	ct.cc_caller_id = nfs3_srv_caller_id;
   1299   5599      jwahlig 	ct.cc_flags = CC_DONTBLOCK;
   1300      0       stevel 
   1301      0       stevel 	/*
   1302      0       stevel 	 * We have to enter the critical region before calling VOP_RWLOCK
   1303      0       stevel 	 * to avoid a deadlock with ufs.
   1304      0       stevel 	 */
   1305      0       stevel 	if (nbl_need_check(vp)) {
   1306      0       stevel 		nbl_start_crit(vp, RW_READER);
   1307      0       stevel 		in_crit = 1;
   1308   5331          amw 		if (nbl_conflict(vp, NBL_WRITE, args->offset, args->count, 0,
   1309   5331          amw 		    NULL)) {
   1310      0       stevel 			error = EACCES;
   1311   5982          ahl 			goto err;
   1312      0       stevel 		}
   1313      0       stevel 	}
   1314      0       stevel 
   1315   5599      jwahlig 	rwlock_ret = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct);
   1316   5599      jwahlig 
   1317   5599      jwahlig 	/* check if a monitor detected a delegation conflict */
   1318   5599      jwahlig 	if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
   1319   5599      jwahlig 		resp->status = NFS3ERR_JUKEBOX;
   1320   5599      jwahlig 		rwlock_ret = -1;
   1321   5982          ahl 		goto err1;
   1322   5599      jwahlig 	}
   1323   5599      jwahlig 
   1324   5599      jwahlig 
   1325   5599      jwahlig 	bva.va_mask = AT_ALL;
   1326   5599      jwahlig 	error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
   1327      0       stevel 
   1328      0       stevel 	/*
   1329      0       stevel 	 * If we can't get the attributes, then we can't do the
   1330      0       stevel 	 * right access checking.  So, we'll fail the request.
   1331      0       stevel 	 */
   1332      0       stevel 	if (error)
   1333   5982          ahl 		goto err;
   1334      0       stevel 
   1335      0       stevel 	bvap = &bva;
   1336      0       stevel #ifdef DEBUG
   1337      0       stevel 	if (!rfs3_do_pre_op_attr)
   1338      0       stevel 		bvap = NULL;
   1339      0       stevel #endif
   1340      0       stevel 	avap = bvap;
   1341      0       stevel 
   1342      0       stevel 	if (args->count != args->data.data_len) {
   1343      0       stevel 		resp->status = NFS3ERR_INVAL;
   1344   5982          ahl 		goto err1;
   1345   5982          ahl 	}
   1346   5982          ahl 
   1347   5982          ahl 	if (rdonly(exi, req)) {
   1348   5982          ahl 		resp->status = NFS3ERR_ROFS;
   1349   5982          ahl 		goto err1;
   1350      0       stevel 	}
   1351      0       stevel 
   1352      0       stevel 	if (vp->v_type != VREG) {
   1353      0       stevel 		resp->status = NFS3ERR_INVAL;
   1354   5982          ahl 		goto err1;
   1355      0       stevel 	}
   1356      0       stevel 
   1357      0       stevel 	if (crgetuid(cr) != bva.va_uid &&
   1358   5599      jwahlig 	    (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
   1359   5982          ahl 		goto err;
   1360      0       stevel 
   1361      0       stevel 	if (MANDLOCK(vp, bva.va_mode)) {
   1362      0       stevel 		resp->status = NFS3ERR_ACCES;
   1363   5982          ahl 		goto err1;
   1364      0       stevel 	}
   1365      0       stevel 
   1366      0       stevel 	if (args->count == 0) {
   1367      0       stevel 		resp->status = NFS3_OK;
   1368      0       stevel 		vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
   1369      0       stevel 		resp->resok.count = 0;
   1370      0       stevel 		resp->resok.committed = args->stable;
   1371      0       stevel 		resp->resok.verf = write3verf;
   1372   5982          ahl 		goto out;
   1373      0       stevel 	}
   1374      0       stevel 
   1375      0       stevel 	if (args->mblk != NULL) {
   1376      0       stevel 		iovcnt = 0;
   1377      0       stevel 		for (m = args->mblk; m != NULL; m = m->b_cont)
   1378      0       stevel 			iovcnt++;
   1379      0       stevel 		if (iovcnt <= MAX_IOVECS) {
   1380      0       stevel #ifdef DEBUG
   1381      0       stevel 			rfs3_write_hits++;
   1382      0       stevel #endif
   1383      0       stevel 			iovp = iov;
   1384      0       stevel 		} else {
   1385      0       stevel #ifdef DEBUG
   1386      0       stevel 			rfs3_write_misses++;
   1387      0       stevel #endif
   1388      0       stevel 			iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP);
   1389      0       stevel 		}
   1390      0       stevel 		mblk_to_iov(args->mblk, iovcnt, iovp);
   1391   7387       Robert 
   1392   7387       Robert 	} else if (args->rlist != NULL) {
   1393   7387       Robert 		iovcnt = 1;
   1394   7387       Robert 		iovp = iov;
   1395   7387       Robert 		iovp->iov_base = (char *)((args->rlist)->u.c_daddr3);
   1396   7387       Robert 		iovp->iov_len = args->count;
   1397      0       stevel 	} else {
   1398      0       stevel 		iovcnt = 1;
   1399      0       stevel 		iovp = iov;
   1400      0       stevel 		iovp->iov_base = args->data.data_val;
   1401      0       stevel 		iovp->iov_len = args->count;
   1402      0       stevel 	}
   1403      0       stevel 
   1404      0       stevel 	uio.uio_iov = iovp;
   1405      0       stevel 	uio.uio_iovcnt = iovcnt;
   1406      0       stevel 
   1407      0       stevel 	uio.uio_segflg = UIO_SYSSPACE;
   1408      0       stevel 	uio.uio_extflg = UIO_COPY_DEFAULT;
   1409      0       stevel 	uio.uio_loffset = args->offset;
   1410      0       stevel 	uio.uio_resid = args->count;
   1411      0       stevel 	uio.uio_llimit = curproc->p_fsz_ctl;
   1412      0       stevel 	rlimit = uio.uio_llimit - args->offset;
   1413      0       stevel 	if (rlimit < (u_offset_t)uio.uio_resid)
   1414      0       stevel 		uio.uio_resid = (int)rlimit;
   1415      0       stevel 
   1416      0       stevel 	if (args->stable == UNSTABLE)
   1417      0       stevel 		ioflag = 0;
   1418      0       stevel 	else if (args->stable == FILE_SYNC)
   1419      0       stevel 		ioflag = FSYNC;
   1420      0       stevel 	else if (args->stable == DATA_SYNC)
   1421      0       stevel 		ioflag = FDSYNC;
   1422      0       stevel 	else {
   1423      0       stevel 		if (iovp != iov)
   1424      0       stevel 			kmem_free(iovp, sizeof (*iovp) * iovcnt);
   1425      0       stevel 		resp->status = NFS3ERR_INVAL;
   1426   5982          ahl 		goto err1;
   1427      0       stevel 	}
   1428      0       stevel 
   1429      0       stevel 	/*
   1430      0       stevel 	 * We're changing creds because VM may fault and we need
   1431      0       stevel 	 * the cred of the current thread to be used if quota
   1432      0       stevel 	 * checking is enabled.
   1433      0       stevel 	 */
   1434      0       stevel 	savecred = curthread->t_cred;
   1435      0       stevel 	curthread->t_cred = cr;
   1436   5599      jwahlig 	error = VOP_WRITE(vp, &uio, ioflag, cr, &ct);
   1437      0       stevel 	curthread->t_cred = savecred;
   1438      0       stevel 
   1439      0       stevel 	if (iovp != iov)
   1440      0       stevel 		kmem_free(iovp, sizeof (*iovp) * iovcnt);
   1441      0       stevel 
   1442   5599      jwahlig 	/* check if a monitor detected a delegation conflict */
   1443   5599      jwahlig 	if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
   1444   5599      jwahlig 		resp->status = NFS3ERR_JUKEBOX;
   1445   5982          ahl 		goto err1;
   1446   5599      jwahlig 	}
   1447   5599      jwahlig 
   1448   5599      jwahlig 	ava.va_mask = AT_ALL;
   1449   5599      jwahlig 	avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava;
   1450      0       stevel 
   1451      0       stevel #ifdef DEBUG
   1452      0       stevel 	if (!rfs3_do_post_op_attr)
   1453      0       stevel 		avap = NULL;
   1454      0       stevel #endif
   1455      0       stevel 
   1456      0       stevel 	if (error)
   1457   5982          ahl 		goto err;
   1458      0       stevel 
   1459      0       stevel 	/*
   1460      0       stevel 	 * If we were unable to get the V_WRITELOCK_TRUE, then we
   1461      0       stevel 	 * may not have accurate after attrs, so check if
   1462      0       stevel 	 * we have both attributes, they have a non-zero va_seq, and
   1463      0       stevel 	 * va_seq has changed by exactly one,
   1464      0       stevel 	 * if not, turn off the before attr.
   1465      0       stevel 	 */
   1466      0       stevel 	if (rwlock_ret != V_WRITELOCK_TRUE) {
   1467      0       stevel 		if (bvap == NULL || avap == NULL ||
   1468   5599      jwahlig 		    bvap->va_seq == 0 || avap->va_seq == 0 ||
   1469   5599      jwahlig 		    avap->va_seq != (bvap->va_seq + 1)) {
   1470      0       stevel 			bvap = NULL;
   1471      0       stevel 		}
   1472      0       stevel 	}
   1473      0       stevel 
   1474      0       stevel 	resp->status = NFS3_OK;
   1475      0       stevel 	vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
   1476      0       stevel 	resp->resok.count = args->count - uio.uio_resid;
   1477      0       stevel 	resp->resok.committed = args->stable;
   1478      0       stevel 	resp->resok.verf = write3verf;
   1479   5982          ahl 	goto out;
   1480   5982          ahl 
   1481   5982          ahl err:
   1482   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   1483   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   1484   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   1485   5982          ahl 	} else
   1486   5982          ahl 		resp->status = puterrno3(error);
   1487   5982          ahl err1:
   1488   5982          ahl 	vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
   1489   5982          ahl out:
   1490   5982          ahl 	DTRACE_NFSV3_4(op__write__done, struct svc_req *, req,
   1491   5982          ahl 	    cred_t *, cr, vnode_t *, vp, WRITE3res *, resp);
   1492   5982          ahl 
   1493      0       stevel 	if (vp != NULL) {
   1494      0       stevel 		if (rwlock_ret != -1)
   1495   5599      jwahlig 			VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
   1496      0       stevel 		if (in_crit)
   1497      0       stevel 			nbl_end_crit(vp);
   1498      0       stevel 		VN_RELE(vp);
   1499      0       stevel 	}
   1500      0       stevel }
   1501      0       stevel 
   1502   1610      thurlow void *
   1503      0       stevel rfs3_write_getfh(WRITE3args *args)
   1504      0       stevel {
   1505      0       stevel 
   1506   1610      thurlow 	return (&args->file);
   1507      0       stevel }
   1508      0       stevel 
   1509      0       stevel void
   1510      0       stevel rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi,
   1511      0       stevel 	struct svc_req *req, cred_t *cr)
   1512      0       stevel {
   1513      0       stevel 	int error;
   1514      0       stevel 	int in_crit = 0;
   1515      0       stevel 	vnode_t *vp;
   1516      0       stevel 	vnode_t *tvp = NULL;
   1517      0       stevel 	vnode_t *dvp;
   1518      0       stevel 	struct vattr *vap;
   1519      0       stevel 	struct vattr va;
   1520      0       stevel 	struct vattr *dbvap;
   1521      0       stevel 	struct vattr dbva;
   1522      0       stevel 	struct vattr *davap;
   1523      0       stevel 	struct vattr dava;
   1524      0       stevel 	enum vcexcl excl;
   1525      0       stevel 	nfstime3 *mtime;
   1526      0       stevel 	len_t reqsize;
   1527      0       stevel 	bool_t trunc;
   1528   7961      Natalie 	struct sockaddr *ca;
   1529   7961      Natalie 	char *name = NULL;
   1530      0       stevel 
   1531      0       stevel 	dbvap = NULL;
   1532      0       stevel 	davap = NULL;
   1533      0       stevel 
   1534   1610      thurlow 	dvp = nfs3_fhtovp(&args->where.dir, exi);
   1535   5982          ahl 
   1536   5982          ahl 	DTRACE_NFSV3_4(op__create__start, struct svc_req *, req,
   1537   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, CREATE3args *, args);
   1538   5982          ahl 
   1539      0       stevel 	if (dvp == NULL) {
   1540      0       stevel 		error = ESTALE;
   1541      0       stevel 		goto out;
   1542      0       stevel 	}
   1543      0       stevel 
   1544      0       stevel #ifdef DEBUG
   1545      0       stevel 	if (rfs3_do_pre_op_attr) {
   1546      0       stevel 		dbva.va_mask = AT_ALL;
   1547   5331          amw 		dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   1548      0       stevel 	} else
   1549      0       stevel 		dbvap = NULL;
   1550      0       stevel #else
   1551      0       stevel 	dbva.va_mask = AT_ALL;
   1552   5331          amw 	dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   1553      0       stevel #endif
   1554      0       stevel 	davap = dbvap;
   1555      0       stevel 
   1556      0       stevel 	if (args->where.name == nfs3nametoolong) {
   1557      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
   1558      0       stevel 		goto out1;
   1559      0       stevel 	}
   1560      0       stevel 
   1561      0       stevel 	if (args->where.name == NULL || *(args->where.name) == '\0') {
   1562      0       stevel 		resp->status = NFS3ERR_ACCES;
   1563      0       stevel 		goto out1;
   1564      0       stevel 	}
   1565      0       stevel 
   1566      0       stevel 	if (rdonly(exi, req)) {
   1567      0       stevel 		resp->status = NFS3ERR_ROFS;
   1568      0       stevel 		goto out1;
   1569   4971      jarrett 	}
   1570   4971      jarrett 
   1571   4971      jarrett 	if (is_system_labeled()) {
   1572   4971      jarrett 		bslabel_t *clabel = req->rq_label;
   1573   4971      jarrett 
   1574   4971      jarrett 		ASSERT(clabel != NULL);
   1575   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opcreate__clabel, char *,
   1576   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   1577   4971      jarrett 
   1578   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   1579   9871      Jarrett 			if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
   1580   9871      Jarrett 			    exi)) {
   1581   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   1582   4971      jarrett 				goto out1;
   1583   4971      jarrett 			}
   1584   4971      jarrett 		}
   1585   7961      Natalie 	}
   1586   7961      Natalie 
   1587   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
   1588   7961      Natalie 	name = nfscmd_convname(ca, exi, args->where.name,
   1589   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
   1590   7961      Natalie 
   1591   7961      Natalie 	if (name == NULL) {
   1592   7961      Natalie 		/* This is really a Solaris EILSEQ */
   1593   7961      Natalie 		resp->status = NFS3ERR_INVAL;
   1594   7961      Natalie 		goto out1;
   1595      0       stevel 	}
   1596      0       stevel 
   1597      0       stevel 	if (args->how.mode == EXCLUSIVE) {
   1598      0       stevel 		va.va_mask = AT_TYPE | AT_MODE | AT_MTIME;
   1599      0       stevel 		va.va_type = VREG;
   1600      0       stevel 		va.va_mode = (mode_t)0;
   1601      0       stevel 		/*
   1602      0       stevel 		 * Ensure no time overflows and that types match
   1603      0       stevel 		 */
   1604      0       stevel 		mtime = (nfstime3 *)&args->how.createhow3_u.verf;
   1605      0       stevel 		va.va_mtime.tv_sec = mtime->seconds % INT32_MAX;
   1606      0       stevel 		va.va_mtime.tv_nsec = mtime->nseconds;
   1607      0       stevel 		excl = EXCL;
   1608      0       stevel 	} else {
   1609      0       stevel 		error = sattr3_to_vattr(&args->how.createhow3_u.obj_attributes,
   1610      0       stevel 		    &va);
   1611      0       stevel 		if (error)
   1612      0       stevel 			goto out;
   1613      0       stevel 		va.va_mask |= AT_TYPE;
   1614      0       stevel 		va.va_type = VREG;
   1615      0       stevel 		if (args->how.mode == GUARDED)
   1616      0       stevel 			excl = EXCL;
   1617      0       stevel 		else {
   1618      0       stevel 			excl = NONEXCL;
   1619      0       stevel 
   1620      0       stevel 			/*
   1621      0       stevel 			 * During creation of file in non-exclusive mode
   1622      0       stevel 			 * if size of file is being set then make sure
   1623      0       stevel 			 * that if the file already exists that no conflicting
   1624      0       stevel 			 * non-blocking mandatory locks exists in the region
   1625      0       stevel 			 * being modified. If there are conflicting locks fail
   1626      0       stevel 			 * the operation with EACCES.
   1627      0       stevel 			 */
   1628      0       stevel 			if (va.va_mask & AT_SIZE) {
   1629      0       stevel 				struct vattr tva;
   1630      0       stevel 
   1631      0       stevel 				/*
   1632      0       stevel 				 * Does file already exist?
   1633      0       stevel 				 */
   1634   7961      Natalie 				error = VOP_LOOKUP(dvp, name, &tvp,
   1635   5599      jwahlig 				    NULL, 0, NULL, cr, NULL, NULL, NULL);
   1636      0       stevel 
   1637      0       stevel 				/*
   1638      0       stevel 				 * Check to see if the file has been delegated
   1639      0       stevel 				 * to a v4 client.  If so, then begin recall of
   1640      0       stevel 				 * the delegation and return JUKEBOX to allow
   1641      0       stevel 				 * the client to retrasmit its request.
   1642      0       stevel 				 */
   1643      0       stevel 
   1644      0       stevel 				trunc = va.va_size == 0;
   1645      0       stevel 				if (!error &&
   1646      0       stevel 				    rfs4_check_delegated(FWRITE, tvp, trunc)) {
   1647      0       stevel 					resp->status = NFS3ERR_JUKEBOX;
   1648      0       stevel 					goto out1;
   1649      0       stevel 				}
   1650      0       stevel 
   1651      0       stevel 				/*
   1652      0       stevel 				 * Check for NBMAND lock conflicts
   1653      0       stevel 				 */
   1654      0       stevel 				if (!error && nbl_need_check(tvp)) {
   1655      0       stevel 					u_offset_t offset;
   1656      0       stevel 					ssize_t len;
   1657      0       stevel 
   1658      0       stevel 					nbl_start_crit(tvp, RW_READER);
   1659      0       stevel 					in_crit = 1;
   1660      0       stevel 
   1661      0       stevel 					tva.va_mask = AT_SIZE;
   1662   5331          amw 					error = VOP_GETATTR(tvp, &tva, 0, cr,
   1663   5599      jwahlig 					    NULL);
   1664      0       stevel 					/*
   1665      0       stevel 					 * Can't check for conflicts, so return
   1666      0       stevel 					 * error.
   1667      0       stevel 					 */
   1668      0       stevel 					if (error)
   1669      0       stevel 						goto out;
   1670      0       stevel 
   1671      0       stevel 					offset = tva.va_size < va.va_size ?
   1672   5599      jwahlig 					    tva.va_size : va.va_size;
   1673      0       stevel 					len = tva.va_size < va.va_size ?
   1674   5599      jwahlig 					    va.va_size - tva.va_size :
   1675   5599      jwahlig 					    tva.va_size - va.va_size;
   1676      0       stevel 					if (nbl_conflict(tvp, NBL_WRITE,
   1677   5599      jwahlig 					    offset, len, 0, NULL)) {
   1678      0       stevel 						error = EACCES;
   1679      0       stevel 						goto out;
   1680      0       stevel 					}
   1681      0       stevel 				} else if (tvp) {
   1682      0       stevel 					VN_RELE(tvp);
   1683      0       stevel 					tvp = NULL;
   1684      0       stevel 				}
   1685      0       stevel 			}
   1686      0       stevel 		}
   1687      0       stevel 		if (va.va_mask & AT_SIZE)
   1688      0       stevel 			reqsize = va.va_size;
   1689      0       stevel 	}
   1690      0       stevel 
   1691      0       stevel 	/*
   1692      0       stevel 	 * Must specify the mode.
   1693      0       stevel 	 */
   1694      0       stevel 	if (!(va.va_mask & AT_MODE)) {
   1695      0       stevel 		resp->status = NFS3ERR_INVAL;
   1696      0       stevel 		goto out1;
   1697      0       stevel 	}
   1698      0       stevel 
   1699      0       stevel 	/*
   1700      0       stevel 	 * If the filesystem is exported with nosuid, then mask off
   1701      0       stevel 	 * the setuid and setgid bits.
   1702      0       stevel 	 */
   1703      0       stevel 	if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID))
   1704      0       stevel 		va.va_mode &= ~(VSUID | VSGID);
   1705      0       stevel 
   1706      0       stevel tryagain:
   1707      0       stevel 	/*
   1708      0       stevel 	 * The file open mode used is VWRITE.  If the client needs
   1709      0       stevel 	 * some other semantic, then it should do the access checking
   1710      0       stevel 	 * itself.  It would have been nice to have the file open mode
   1711      0       stevel 	 * passed as part of the arguments.
   1712      0       stevel 	 */
   1713   7961      Natalie 	error = VOP_CREATE(dvp, name, &va, excl, VWRITE,
   1714   5331          amw 	    &vp, cr, 0, NULL, NULL);
   1715      0       stevel 
   1716      0       stevel #ifdef DEBUG
   1717      0       stevel 	if (rfs3_do_post_op_attr) {
   1718      0       stevel 		dava.va_mask = AT_ALL;
   1719   5331          amw 		davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   1720      0       stevel 	} else
   1721      0       stevel 		davap = NULL;
   1722      0       stevel #else
   1723      0       stevel 	dava.va_mask = AT_ALL;
   1724   5331          amw 	davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   1725      0       stevel #endif
   1726      0       stevel 
   1727      0       stevel 	if (error) {
   1728      0       stevel 		/*
   1729      0       stevel 		 * If we got something other than file already exists
   1730      0       stevel 		 * then just return this error.  Otherwise, we got
   1731      0       stevel 		 * EEXIST.  If we were doing a GUARDED create, then
   1732      0       stevel 		 * just return this error.  Otherwise, we need to
   1733      0       stevel 		 * make sure that this wasn't a duplicate of an
   1734      0       stevel 		 * exclusive create request.
   1735      0       stevel 		 *
   1736      0       stevel 		 * The assumption is made that a non-exclusive create
   1737      0       stevel 		 * request will never return EEXIST.
   1738      0       stevel 		 */
   1739      0       stevel 		if (error != EEXIST || args->how.mode == GUARDED)
   1740      0       stevel 			goto out;
   1741      0       stevel 		/*
   1742      0       stevel 		 * Lookup the file so that we can get a vnode for it.
   1743      0       stevel 		 */
   1744   7961      Natalie 		error = VOP_LOOKUP(dvp, name, &vp, NULL, 0,
   1745   5331          amw 		    NULL, cr, NULL, NULL, NULL);
   1746      0       stevel 		if (error) {
   1747      0       stevel 			/*
   1748      0       stevel 			 * We couldn't find the file that we thought that
   1749      0       stevel 			 * we just created.  So, we'll just try creating
   1750      0       stevel 			 * it again.
   1751      0       stevel 			 */
   1752      0       stevel 			if (error == ENOENT)
   1753      0       stevel 				goto tryagain;
   1754      0       stevel 			goto out;
   1755      0       stevel 		}
   1756      0       stevel 
   1757      0       stevel 		/*
   1758      0       stevel 		 * If the file is delegated to a v4 client, go ahead
   1759      0       stevel 		 * and initiate recall, this create is a hint that a
   1760      0       stevel 		 * conflicting v3 open has occurred.
   1761      0       stevel 		 */
   1762      0       stevel 
   1763      0       stevel 		if (rfs4_check_delegated(FWRITE, vp, FALSE)) {
   1764      0       stevel 			VN_RELE(vp);
   1765      0       stevel 			resp->status = NFS3ERR_JUKEBOX;
   1766      0       stevel 			goto out1;
   1767      0       stevel 		}
   1768      0       stevel 
   1769      0       stevel 		va.va_mask = AT_ALL;
   1770   5331          amw 		vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   1771      0       stevel 
   1772      0       stevel 		mtime = (nfstime3 *)&args->how.createhow3_u.verf;
   1773      0       stevel 		/* % with INT32_MAX to prevent overflows */
   1774      0       stevel 		if (args->how.mode == EXCLUSIVE && (vap == NULL ||
   1775      0       stevel 		    vap->va_mtime.tv_sec !=
   1776      0       stevel 		    (mtime->seconds % INT32_MAX) ||
   1777      0       stevel 		    vap->va_mtime.tv_nsec != mtime->nseconds)) {
   1778      0       stevel 			VN_RELE(vp);
   1779      0       stevel 			error = EEXIST;
   1780      0       stevel 			goto out;
   1781      0       stevel 		}
   1782      0       stevel 	} else {
   1783      0       stevel 
   1784      0       stevel 		if ((args->how.mode == UNCHECKED ||
   1785      0       stevel 		    args->how.mode == GUARDED) &&
   1786      0       stevel 		    args->how.createhow3_u.obj_attributes.size.set_it &&
   1787      0       stevel 		    va.va_size == 0)
   1788      0       stevel 			trunc = TRUE;
   1789      0       stevel 		else
   1790      0       stevel 			trunc = FALSE;
   1791      0       stevel 
   1792      0       stevel 		if (rfs4_check_delegated(FWRITE, vp, trunc)) {
   1793      0       stevel 			VN_RELE(vp);
   1794      0       stevel 			resp->status = NFS3ERR_JUKEBOX;
   1795      0       stevel 			goto out1;
   1796      0       stevel 		}
   1797      0       stevel 
   1798      0       stevel 		va.va_mask = AT_ALL;
   1799   5331          amw 		vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   1800      0       stevel 
   1801      0       stevel 		/*
   1802      0       stevel 		 * We need to check to make sure that the file got
   1803      0       stevel 		 * created to the indicated size.  If not, we do a
   1804      0       stevel 		 * setattr to try to change the size, but we don't
   1805      0       stevel 		 * try too hard.  This shouldn't a problem as most
   1806      0       stevel 		 * clients will only specifiy a size of zero which
   1807      0       stevel 		 * local file systems handle.  However, even if
   1808      0       stevel 		 * the client does specify a non-zero size, it can
   1809      0       stevel 		 * still recover by checking the size of the file
   1810      0       stevel 		 * after it has created it and then issue a setattr
   1811      0       stevel 		 * request of its own to set the size of the file.
   1812      0       stevel 		 */
   1813      0       stevel 		if (vap != NULL &&
   1814      0       stevel 		    (args->how.mode == UNCHECKED ||
   1815      0       stevel 		    args->how.mode == GUARDED) &&
   1816      0       stevel 		    args->how.createhow3_u.obj_attributes.size.set_it &&
   1817      0       stevel 		    vap->va_size != reqsize) {
   1818      0       stevel 			va.va_mask = AT_SIZE;
   1819      0       stevel 			va.va_size = reqsize;
   1820      0       stevel 			(void) VOP_SETATTR(vp, &va, 0, cr, NULL);
   1821      0       stevel 			va.va_mask = AT_ALL;
   1822   5331          amw 			vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   1823      0       stevel 		}
   1824      0       stevel 	}
   1825      0       stevel 
   1826   7961      Natalie 	if (name != args->where.name)
   1827   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
   1828   7961      Natalie 
   1829      0       stevel #ifdef DEBUG
   1830      0       stevel 	if (!rfs3_do_post_op_attr)
   1831      0       stevel 		vap = NULL;
   1832      0       stevel #endif
   1833      0       stevel 
   1834      0       stevel #ifdef DEBUG
   1835      0       stevel 	if (!rfs3_do_post_op_fh3)
   1836      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   1837      0       stevel 	else {
   1838      0       stevel #endif
   1839      0       stevel 	error = makefh3(&resp->resok.obj.handle, vp, exi);
   1840      0       stevel 	if (error)
   1841      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   1842      0       stevel 	else
   1843      0       stevel 		resp->resok.obj.handle_follows = TRUE;
   1844      0       stevel #ifdef DEBUG
   1845      0       stevel 	}
   1846      0       stevel #endif
   1847      0       stevel 
   1848      0       stevel 	/*
   1849      0       stevel 	 * Force modified data and metadata out to stable storage.
   1850      0       stevel 	 */
   1851   5331          amw 	(void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
   1852   5331          amw 	(void) VOP_FSYNC(dvp, 0, cr, NULL);
   1853      0       stevel 
   1854      0       stevel 	VN_RELE(vp);
   1855      0       stevel 	if (tvp != NULL) {
   1856      0       stevel 		if (in_crit)
   1857      0       stevel 			nbl_end_crit(tvp);
   1858      0       stevel 		VN_RELE(tvp);
   1859      0       stevel 	}
   1860      0       stevel 
   1861      0       stevel 	resp->status = NFS3_OK;
   1862      0       stevel 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
   1863      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
   1864   5982          ahl 
   1865   5982          ahl 	DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
   1866   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
   1867   5982          ahl 
   1868   5982          ahl 	VN_RELE(dvp);
   1869   5982          ahl 	return;
   1870   5982          ahl 
   1871   5982          ahl out:
   1872   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   1873   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   1874   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   1875   5982          ahl 	} else
   1876   5982          ahl 		resp->status = puterrno3(error);
   1877   5982          ahl out1:
   1878   5982          ahl 	DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
   1879   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
   1880   7961      Natalie 
   1881   7961      Natalie 	if (name != NULL && name != args->where.name)
   1882   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
   1883   5982          ahl 
   1884      0       stevel 	if (tvp != NULL) {
   1885      0       stevel 		if (in_crit)
   1886      0       stevel 			nbl_end_crit(tvp);
   1887      0       stevel 		VN_RELE(tvp);
   1888      0       stevel 	}
   1889      0       stevel 	if (dvp != NULL)
   1890      0       stevel 		VN_RELE(dvp);
   1891      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
   1892      0       stevel }
   1893      0       stevel 
   1894   1610      thurlow void *
   1895      0       stevel rfs3_create_getfh(CREATE3args *args)
   1896      0       stevel {
   1897      0       stevel 
   1898   1610      thurlow 	return (&args->where.dir);
   1899      0       stevel }
   1900      0       stevel 
   1901      0       stevel void
   1902      0       stevel rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi,
   1903      0       stevel 	struct svc_req *req, cred_t *cr)
   1904      0       stevel {
   1905      0       stevel 	int error;
   1906      0       stevel 	vnode_t *vp = NULL;
   1907      0       stevel 	vnode_t *dvp;
   1908      0       stevel 	struct vattr *vap;
   1909      0       stevel 	struct vattr va;
   1910      0       stevel 	struct vattr *dbvap;
   1911      0       stevel 	struct vattr dbva;
   1912      0       stevel 	struct vattr *davap;
   1913      0       stevel 	struct vattr dava;
   1914   7961      Natalie 	struct sockaddr *ca;
   1915   7961      Natalie 	char *name = NULL;
   1916      0       stevel 
   1917      0       stevel 	dbvap = NULL;
   1918      0       stevel 	davap = NULL;
   1919      0       stevel 
   1920   1610      thurlow 	dvp = nfs3_fhtovp(&args->where.dir, exi);
   1921   5982          ahl 
   1922   5982          ahl 	DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req,
   1923   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args);
   1924   5982          ahl 
   1925      0       stevel 	if (dvp == NULL) {
   1926      0       stevel 		error = ESTALE;
   1927      0       stevel 		goto out;
   1928      0       stevel 	}
   1929      0       stevel 
   1930      0       stevel #ifdef DEBUG
   1931      0       stevel 	if (rfs3_do_pre_op_attr) {
   1932      0       stevel 		dbva.va_mask = AT_ALL;
   1933   5331          amw 		dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   1934      0       stevel 	} else
   1935      0       stevel 		dbvap = NULL;
   1936      0       stevel #else
   1937      0       stevel 	dbva.va_mask = AT_ALL;
   1938   5331          amw 	dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   1939      0       stevel #endif
   1940      0       stevel 	davap = dbvap;
   1941      0       stevel 
   1942      0       stevel 	if (args->where.name == nfs3nametoolong) {
   1943      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
   1944      0       stevel 		goto out1;
   1945      0       stevel 	}
   1946      0       stevel 
   1947      0       stevel 	if (args->where.name == NULL || *(args->where.name) == '\0') {
   1948      0       stevel 		resp->status = NFS3ERR_ACCES;
   1949      0       stevel 		goto out1;
   1950      0       stevel 	}
   1951      0       stevel 
   1952      0       stevel 	if (rdonly(exi, req)) {
   1953      0       stevel 		resp->status = NFS3ERR_ROFS;
   1954      0       stevel 		goto out1;
   1955      0       stevel 	}
   1956      0       stevel 
   1957   4971      jarrett 	if (is_system_labeled()) {
   1958   4971      jarrett 		bslabel_t *clabel = req->rq_label;
   1959   4971      jarrett 
   1960   4971      jarrett 		ASSERT(clabel != NULL);
   1961   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opmkdir__clabel, char *,
   1962   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   1963   4971      jarrett 
   1964   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   1965   9871      Jarrett 			if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
   1966   9871      Jarrett 			    exi)) {
   1967   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   1968   4971      jarrett 				goto out1;
   1969   4971      jarrett 			}
   1970   4971      jarrett 		}
   1971   4971      jarrett 	}
   1972   4971      jarrett 
   1973      0       stevel 	error = sattr3_to_vattr(&args->attributes, &va);
   1974      0       stevel 	if (error)
   1975      0       stevel 		goto out;
   1976      0       stevel 
   1977      0       stevel 	if (!(va.va_mask & AT_MODE)) {
   1978      0       stevel 		resp->status = NFS3ERR_INVAL;
   1979      0       stevel 		goto out1;
   1980      0       stevel 	}
   1981      0       stevel 
   1982   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
   1983   7961      Natalie 	name = nfscmd_convname(ca, exi, args->where.name,
   1984   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
   1985   7961      Natalie 
   1986   7961      Natalie 	if (name == NULL) {
   1987   7961      Natalie 		resp->status = NFS3ERR_INVAL;
   1988   7961      Natalie 		goto out1;
   1989   7961      Natalie 	}
   1990   7961      Natalie 
   1991      0       stevel 	va.va_mask |= AT_TYPE;
   1992      0       stevel 	va.va_type = VDIR;
   1993      0       stevel 
   1994   7961      Natalie 	error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL);
   1995   7961      Natalie 
   1996   7961      Natalie 	if (name != args->where.name)
   1997   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
   1998      0       stevel 
   1999      0       stevel #ifdef DEBUG
   2000      0       stevel 	if (rfs3_do_post_op_attr) {
   2001      0       stevel 		dava.va_mask = AT_ALL;
   2002   5331          amw 		davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   2003      0       stevel 	} else
   2004      0       stevel 		davap = NULL;
   2005      0       stevel #else
   2006      0       stevel 	dava.va_mask = AT_ALL;
   2007   5331          amw 	davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   2008   5331          amw #endif
   2009   5331          amw 
   2010   5331          amw 	/*
   2011   5331          amw 	 * Force modified data and metadata out to stable storage.
   2012   5331          amw 	 */
   2013   5331          amw 	(void) VOP_FSYNC(dvp, 0, cr, NULL);
   2014      0       stevel 
   2015      0       stevel 	if (error)
   2016      0       stevel 		goto out;
   2017      0       stevel 
   2018      0       stevel #ifdef DEBUG
   2019      0       stevel 	if (!rfs3_do_post_op_fh3)
   2020      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   2021      0       stevel 	else {
   2022      0       stevel #endif
   2023      0       stevel 	error = makefh3(&resp->resok.obj.handle, vp, exi);
   2024      0       stevel 	if (error)
   2025      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   2026      0       stevel 	else
   2027      0       stevel 		resp->resok.obj.handle_follows = TRUE;
   2028      0       stevel #ifdef DEBUG
   2029      0       stevel 	}
   2030      0       stevel #endif
   2031      0       stevel 
   2032      0       stevel #ifdef DEBUG
   2033      0       stevel 	if (rfs3_do_post_op_attr) {
   2034      0       stevel 		va.va_mask = AT_ALL;
   2035   5331          amw 		vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   2036   5331          amw 	} else
   2037   5331          amw 		vap = NULL;
   2038   5331          amw #else
   2039   5331          amw 	va.va_mask = AT_ALL;
   2040   5331          amw 	vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   2041   5331          amw #endif
   2042   5331          amw 
   2043   5331          amw 	/*
   2044   5331          amw 	 * Force modified data and metadata out to stable storage.
   2045   5331          amw 	 */
   2046   5331          amw 	(void) VOP_FSYNC(vp, 0, cr, NULL);
   2047      0       stevel 
   2048      0       stevel 	VN_RELE(vp);
   2049      0       stevel 
   2050      0       stevel 	resp->status = NFS3_OK;
   2051      0       stevel 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
   2052      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
   2053   5982          ahl 
   2054   5982          ahl 	DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
   2055   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
   2056   5982          ahl 	VN_RELE(dvp);
   2057   5982          ahl 
   2058   5982          ahl 	return;
   2059   5982          ahl 
   2060   5982          ahl out:
   2061   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   2062   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   2063   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   2064   5982          ahl 	} else
   2065   5982          ahl 		resp->status = puterrno3(error);
   2066   5982          ahl out1:
   2067   5982          ahl 	DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
   2068   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
   2069      0       stevel 	if (dvp != NULL)
   2070      0       stevel 		VN_RELE(dvp);
   2071      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
   2072      0       stevel }
   2073      0       stevel 
   2074   1610      thurlow void *
   2075      0       stevel rfs3_mkdir_getfh(MKDIR3args *args)
   2076      0       stevel {
   2077      0       stevel 
   2078   1610      thurlow 	return (&args->where.dir);
   2079      0       stevel }
   2080      0       stevel 
   2081      0       stevel void
   2082      0       stevel rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi,
   2083      0       stevel 	struct svc_req *req, cred_t *cr)
   2084      0       stevel {
   2085      0       stevel 	int error;
   2086      0       stevel 	vnode_t *vp;
   2087      0       stevel 	vnode_t *dvp;
   2088      0       stevel 	struct vattr *vap;
   2089      0       stevel 	struct vattr va;
   2090      0       stevel 	struct vattr *dbvap;
   2091      0       stevel 	struct vattr dbva;
   2092      0       stevel 	struct vattr *davap;
   2093      0       stevel 	struct vattr dava;
   2094   7961      Natalie 	struct sockaddr *ca;
   2095   7961      Natalie 	char *name = NULL;
   2096   7961      Natalie 	char *symdata = NULL;
   2097      0       stevel 
   2098      0       stevel 	dbvap = NULL;
   2099      0       stevel 	davap = NULL;
   2100      0       stevel 
   2101   1610      thurlow 	dvp = nfs3_fhtovp(&args->where.dir, exi);
   2102   5982          ahl 
   2103   5982          ahl 	DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req,
   2104   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args);
   2105   5982          ahl 
   2106   5982          ahl 	if (dvp == NULL) {
   2107   5982          ahl 		error = ESTALE;
   2108   5982          ahl 		goto err;
   2109      0       stevel 	}
   2110      0       stevel 
   2111      0       stevel #ifdef DEBUG
   2112      0       stevel 	if (rfs3_do_pre_op_attr) {
   2113      0       stevel 		dbva.va_mask = AT_ALL;
   2114   5331          amw 		dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   2115      0       stevel 	} else
   2116      0       stevel 		dbvap = NULL;
   2117      0       stevel #else
   2118      0       stevel 	dbva.va_mask = AT_ALL;
   2119   5331          amw 	dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   2120      0       stevel #endif
   2121      0       stevel 	davap = dbvap;
   2122      0       stevel 
   2123      0       stevel 	if (args->where.name == nfs3nametoolong) {
   2124      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
   2125   5982          ahl 		goto err1;
   2126      0       stevel 	}
   2127      0       stevel 
   2128      0       stevel 	if (args->where.name == NULL || *(args->where.name) == '\0') {
   2129      0       stevel 		resp->status = NFS3ERR_ACCES;
   2130   5982          ahl 		goto err1;
   2131   5982          ahl 	}
   2132   5982          ahl 
   2133   5982          ahl 	if (rdonly(exi, req)) {
   2134   5982          ahl 		resp->status = NFS3ERR_ROFS;
   2135   5982          ahl 		goto err1;
   2136   4971      jarrett 	}
   2137   4971      jarrett 
   2138   4971      jarrett 	if (is_system_labeled()) {
   2139   4971      jarrett 		bslabel_t *clabel = req->rq_label;
   2140   4971      jarrett 
   2141   4971      jarrett 		ASSERT(clabel != NULL);
   2142   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opsymlink__clabel, char *,
   2143   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   2144   4971      jarrett 
   2145   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   2146   9871      Jarrett 			if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
   2147   9871      Jarrett 			    exi)) {
   2148   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   2149   5982          ahl 				goto err1;
   2150   4971      jarrett 			}
   2151   4971      jarrett 		}
   2152      0       stevel 	}
   2153      0       stevel 
   2154      0       stevel 	error = sattr3_to_vattr(&args->symlink.symlink_attributes, &va);
   2155      0       stevel 	if (error)
   2156   5982          ahl 		goto err;
   2157      0       stevel 
   2158      0       stevel 	if (!(va.va_mask & AT_MODE)) {
   2159      0       stevel 		resp->status = NFS3ERR_INVAL;
   2160   5982          ahl 		goto err1;
   2161      0       stevel 	}
   2162      0       stevel 
   2163      0       stevel 	if (args->symlink.symlink_data == nfs3nametoolong) {
   2164      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
   2165   5982          ahl 		goto err1;
   2166      0       stevel 	}
   2167      0       stevel 
   2168   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
   2169   7961      Natalie 	name = nfscmd_convname(ca, exi, args->where.name,
   2170   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
   2171   7961      Natalie 
   2172   7961      Natalie 	if (name == NULL) {
   2173   7961      Natalie 		/* This is really a Solaris EILSEQ */
   2174   7961      Natalie 		resp->status = NFS3ERR_INVAL;
   2175   7961      Natalie 		goto err1;
   2176   7961      Natalie 	}
   2177   7961      Natalie 
   2178   7961      Natalie 	symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data,
   2179   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
   2180   7961      Natalie 	if (symdata == NULL) {
   2181   7961      Natalie 		/* This is really a Solaris EILSEQ */
   2182   7961      Natalie 		resp->status = NFS3ERR_INVAL;
   2183   7961      Natalie 		goto err1;
   2184   7961      Natalie 	}
   2185   7961      Natalie 
   2186   7961      Natalie 
   2187      0       stevel 	va.va_mask |= AT_TYPE;
   2188      0       stevel 	va.va_type = VLNK;
   2189      0       stevel 
   2190   7961      Natalie 	error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0);
   2191      0       stevel 
   2192      0       stevel #ifdef DEBUG
   2193      0       stevel 	if (rfs3_do_post_op_attr) {
   2194      0       stevel 		dava.va_mask = AT_ALL;
   2195   5331          amw 		davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   2196      0       stevel 	} else
   2197      0       stevel 		davap = NULL;
   2198      0       stevel #else
   2199      0       stevel 	dava.va_mask = AT_ALL;
   2200   5331          amw 	davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   2201   5331          amw #endif
   2202   5331          amw 
   2203   5331          amw 	if (error)
   2204   5982          ahl 		goto err;
   2205   5331          amw 
   2206   7961      Natalie 	error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
   2207   5599      jwahlig 	    NULL, NULL, NULL);
   2208   5331          amw 
   2209   5331          amw 	/*
   2210   5331          amw 	 * Force modified data and metadata out to stable storage.
   2211   5331          amw 	 */
   2212   5331          amw 	(void) VOP_FSYNC(dvp, 0, cr, NULL);
   2213      0       stevel 
   2214      0       stevel 
   2215      0       stevel 	resp->status = NFS3_OK;
   2216      0       stevel 	if (error) {
   2217      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   2218      0       stevel 		vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
   2219      0       stevel 		vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
   2220   5982          ahl 		goto out;
   2221      0       stevel 	}
   2222      0       stevel 
   2223      0       stevel #ifdef DEBUG
   2224      0       stevel 	if (!rfs3_do_post_op_fh3)
   2225      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   2226      0       stevel 	else {
   2227      0       stevel #endif
   2228      0       stevel 	error = makefh3(&resp->resok.obj.handle, vp, exi);
   2229      0       stevel 	if (error)
   2230      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   2231      0       stevel 	else
   2232      0       stevel 		resp->resok.obj.handle_follows = TRUE;
   2233      0       stevel #ifdef DEBUG
   2234      0       stevel 	}
   2235      0       stevel #endif
   2236      0       stevel 
   2237      0       stevel #ifdef DEBUG
   2238      0       stevel 	if (rfs3_do_post_op_attr) {
   2239      0       stevel 		va.va_mask = AT_ALL;
   2240   5331          amw 		vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   2241   5331          amw 	} else
   2242   5331          amw 		vap = NULL;
   2243   5331          amw #else
   2244   5331          amw 	va.va_mask = AT_ALL;
   2245   5331          amw 	vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   2246   5331          amw #endif
   2247   5331          amw 
   2248   5331          amw 	/*
   2249   5331          amw 	 * Force modified data and metadata out to stable storage.
   2250   5331          amw 	 */
   2251   5331          amw 	(void) VOP_FSYNC(vp, 0, cr, NULL);
   2252      0       stevel 
   2253      0       stevel 	VN_RELE(vp);
   2254      0       stevel 
   2255      0       stevel 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
   2256      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
   2257   5982          ahl 	goto out;
   2258   5982          ahl 
   2259   5982          ahl err:
   2260   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   2261   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   2262   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   2263   5982          ahl 	} else
   2264   5982          ahl 		resp->status = puterrno3(error);
   2265   5982          ahl err1:
   2266      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
   2267   5982          ahl out:
   2268   7961      Natalie 	if (name != NULL && name != args->where.name)
   2269   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
   2270   7961      Natalie 	if (symdata != NULL && symdata != args->symlink.symlink_data)
   2271   7961      Natalie 		kmem_free(symdata, MAXPATHLEN + 1);
   2272   7961      Natalie 
   2273   5982          ahl 	DTRACE_NFSV3_4(op__symlink__done, struct svc_req *, req,
   2274   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, SYMLINK3res *, resp);
   2275   5982          ahl 
   2276   5982          ahl 	if (dvp != NULL)
   2277   5982          ahl 		VN_RELE(dvp);
   2278      0       stevel }
   2279      0       stevel 
   2280   1610      thurlow void *
   2281      0       stevel rfs3_symlink_getfh(SYMLINK3args *args)
   2282      0       stevel {
   2283      0       stevel 
   2284   1610      thurlow 	return (&args->where.dir);
   2285      0       stevel }
   2286      0       stevel 
   2287      0       stevel void
   2288      0       stevel rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi,
   2289      0       stevel 	struct svc_req *req, cred_t *cr)
   2290      0       stevel {
   2291      0       stevel 	int error;
   2292      0       stevel 	vnode_t *vp;
   2293   6402      gt29601 	vnode_t *realvp;
   2294      0       stevel 	vnode_t *dvp;
   2295      0       stevel 	struct vattr *vap;
   2296      0       stevel 	struct vattr va;
   2297      0       stevel 	struct vattr *dbvap;
   2298      0       stevel 	struct vattr dbva;
   2299      0       stevel 	struct vattr *davap;
   2300      0       stevel 	struct vattr dava;
   2301      0       stevel 	int mode;
   2302      0       stevel 	enum vcexcl excl;
   2303   7961      Natalie 	struct sockaddr *ca;
   2304   7961      Natalie 	char *name = NULL;
   2305      0       stevel 
   2306      0       stevel 	dbvap = NULL;
   2307      0       stevel 	davap = NULL;
   2308      0       stevel 
   2309   1610      thurlow 	dvp = nfs3_fhtovp(&args->where.dir, exi);
   2310   5982          ahl 
   2311   5982          ahl 	DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req,
   2312   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args);
   2313   5982          ahl 
   2314      0       stevel 	if (dvp == NULL) {
   2315      0       stevel 		error = ESTALE;
   2316      0       stevel 		goto out;
   2317      0       stevel 	}
   2318      0       stevel 
   2319      0       stevel #ifdef DEBUG
   2320      0       stevel 	if (rfs3_do_pre_op_attr) {
   2321      0       stevel 		dbva.va_mask = AT_ALL;
   2322   5331          amw 		dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   2323      0       stevel 	} else
   2324      0       stevel 		dbvap = NULL;
   2325      0       stevel #else
   2326      0       stevel 	dbva.va_mask = AT_ALL;
   2327   5331          amw 	dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
   2328      0       stevel #endif
   2329      0       stevel 	davap = dbvap;
   2330      0       stevel 
   2331      0       stevel 	if (args->where.name == nfs3nametoolong) {
   2332      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
   2333      0       stevel 		goto out1;
   2334      0       stevel 	}
   2335      0       stevel 
   2336      0       stevel 	if (args->where.name == NULL || *(args->where.name) == '\0') {
   2337      0       stevel 		resp->status = NFS3ERR_ACCES;
   2338      0       stevel 		goto out1;
   2339      0       stevel 	}
   2340      0       stevel 
   2341      0       stevel 	if (rdonly(exi, req)) {
   2342      0       stevel 		resp->status = NFS3ERR_ROFS;
   2343      0       stevel 		goto out1;
   2344   4971      jarrett 	}
   2345   4971      jarrett 
   2346   4971      jarrett 	if (is_system_labeled()) {
   2347   4971      jarrett 		bslabel_t *clabel = req->rq_label;
   2348   4971      jarrett 
   2349   4971      jarrett 		ASSERT(clabel != NULL);
   2350   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opmknod__clabel, char *,
   2351   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   2352   4971      jarrett 
   2353   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   2354   9871      Jarrett 			if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
   2355   9871      Jarrett 			    exi)) {
   2356   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   2357   4971      jarrett 				goto out1;
   2358   4971      jarrett 			}
   2359   4971      jarrett 		}
   2360      0       stevel 	}
   2361      0       stevel 
   2362      0       stevel 	switch (args->what.type) {
   2363      0       stevel 	case NF3CHR:
   2364      0       stevel 	case NF3BLK:
   2365      0       stevel 		error = sattr3_to_vattr(
   2366      0       stevel 		    &args->what.mknoddata3_u.device.dev_attributes, &va);
   2367      0       stevel 		if (error)
   2368      0       stevel 			goto out;
   2369      0       stevel 		if (secpolicy_sys_devices(cr) != 0) {
   2370      0       stevel 			resp->status = NFS3ERR_PERM;
   2371      0       stevel 			goto out1;
   2372      0       stevel 		}
   2373      0       stevel 		if (args->what.type == NF3CHR)
   2374      0       stevel 			va.va_type = VCHR;
   2375      0       stevel 		else
   2376      0       stevel 			va.va_type = VBLK;
   2377      0       stevel 		va.va_rdev = makedevice(
   2378      0       stevel 		    args->what.mknoddata3_u.device.spec.specdata1,
   2379      0       stevel 		    args->what.mknoddata3_u.device.spec.specdata2);
   2380      0       stevel 		va.va_mask |= AT_TYPE | AT_RDEV;
   2381      0       stevel 		break;
   2382      0       stevel 	case NF3SOCK:
   2383      0       stevel 		error = sattr3_to_vattr(
   2384      0       stevel 		    &args->what.mknoddata3_u.pipe_attributes, &va);
   2385      0       stevel 		if (error)
   2386      0       stevel 			goto out;
   2387      0       stevel 		va.va_type = VSOCK;
   2388      0       stevel 		va.va_mask |= AT_TYPE;
   2389      0       stevel 		break;
   2390      0       stevel 	case NF3FIFO:
   2391      0       stevel 		error = sattr3_to_vattr(
   2392      0       stevel 		    &args->what.mknoddata3_u.pipe_attributes, &va);
   2393      0       stevel 		if (error)
   2394      0       stevel 			goto out;
   2395      0       stevel 		va.va_type = VFIFO;
   2396      0       stevel 		va.va_mask |= AT_TYPE;
   2397      0       stevel 		break;
   2398      0       stevel 	default:
   2399      0       stevel 		resp->status = NFS3ERR_BADTYPE;
   2400      0       stevel 		goto out1;
   2401      0       stevel 	}
   2402      0       stevel 
   2403      0       stevel 	/*
   2404      0       stevel 	 * Must specify the mode.
   2405      0       stevel 	 */
   2406      0       stevel 	if (!(va.va_mask & AT_MODE)) {
   2407      0       stevel 		resp->status = NFS3ERR_INVAL;
   2408      0       stevel 		goto out1;
   2409      0       stevel 	}
   2410      0       stevel 
   2411   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
   2412   7961      Natalie 	name = nfscmd_convname(ca, exi, args->where.name,
   2413   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
   2414   7961      Natalie 
   2415   7961      Natalie 	if (name == NULL) {
   2416   7961      Natalie 		resp->status = NFS3ERR_INVAL;
   2417   7961      Natalie 		goto out1;
   2418   7961      Natalie 	}
   2419   7961      Natalie 
   2420      0       stevel 	excl = EXCL;
   2421      0       stevel 
   2422      0       stevel 	mode = 0;
   2423      0       stevel 
   2424   7961      Natalie 	error = VOP_CREATE(dvp, name, &va, excl, mode,
   2425   5331          amw 	    &vp, cr, 0, NULL, NULL);
   2426   7961      Natalie 
   2427   7961      Natalie 	if (name != args->where.name)
   2428   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
   2429      0       stevel 
   2430      0       stevel #ifdef DEBUG
   2431      0       stevel 	if (rfs3_do_post_op_attr) {
   2432      0       stevel 		dava.va_mask = AT_ALL;
   2433   5331          amw 		davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   2434      0       stevel 	} else
   2435      0       stevel 		davap = NULL;
   2436      0       stevel #else
   2437      0       stevel 	dava.va_mask = AT_ALL;
   2438   5331          amw 	davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
   2439   5331          amw #endif
   2440   5331          amw 
   2441   5331          amw 	/*
   2442   5331          amw 	 * Force modified data and metadata out to stable storage.
   2443   5331          amw 	 */
   2444   5331          amw 	(void) VOP_FSYNC(dvp, 0, cr, NULL);
   2445      0       stevel 
   2446      0       stevel 	if (error)
   2447      0       stevel 		goto out;
   2448      0       stevel 
   2449      0       stevel 	resp->status = NFS3_OK;
   2450      0       stevel 
   2451      0       stevel #ifdef DEBUG
   2452      0       stevel 	if (!rfs3_do_post_op_fh3)
   2453      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   2454      0       stevel 	else {
   2455      0       stevel #endif
   2456      0       stevel 	error = makefh3(&resp->resok.obj.handle, vp, exi);
   2457      0       stevel 	if (error)
   2458      0       stevel 		resp->resok.obj.handle_follows = FALSE;
   2459      0       stevel 	else
   2460      0       stevel 		resp->resok.obj.handle_follows = TRUE;
   2461      0       stevel #ifdef DEBUG
   2462      0       stevel 	}
   2463      0       stevel #endif
   2464      0       stevel 
   2465      0       stevel #ifdef DEBUG
   2466      0       stevel 	if (rfs3_do_post_op_attr) {
   2467      0       stevel 		va.va_mask = AT_ALL;
   2468   5331          amw 		vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   2469   5331          amw 	} else
   2470   5331          amw 		vap = NULL;
   2471   5331          amw #else
   2472   5331          amw 	va.va_mask = AT_ALL;
   2473   5331          amw 	vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
   2474   5331          amw #endif
   2475   5331          amw 
   2476   5331          amw 	/*
   2477   5331          amw 	 * Force modified metadata out to stable storage.
   2478   6402      gt29601 	 *
   2479   6402      gt29601 	 * if a underlying vp exists, pass it to VOP_FSYNC
   2480   6402      gt29601 	 */
   2481   6402      gt29601 	if (VOP_REALVP(vp, &realvp, NULL) == 0)
   2482   6402      gt29601 		(void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL);
   2483   6402      gt29601 	else
   2484   6402      gt29601 		(void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
   2485      0       stevel 
   2486      0       stevel 	VN_RELE(vp);
   2487      0       stevel 
   2488      0       stevel 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
   2489      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
   2490   5982          ahl 	DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
   2491   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
   2492   5982          ahl 	VN_RELE(dvp);
   2493   5982          ahl 	return;
   2494   5982          ahl 
   2495   5982          ahl out:
   2496   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   2497   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   2498   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   2499   5982          ahl 	} else
   2500   5982          ahl 		resp->status = puterrno3(error);
   2501   5982          ahl out1:
   2502   5982          ahl 	DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
   2503   5982          ahl 	    cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
   2504      0       stevel 	if (dvp != NULL)
   2505      0       stevel 		VN_RELE(dvp);
   2506      0       stevel 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
   2507      0       stevel }
   2508      0       stevel 
   2509   1610      thurlow void *
   2510      0       stevel rfs3_mknod_getfh(MKNOD3args *args)
   2511      0       stevel {
   2512      0       stevel 
   2513   1610      thurlow 	return (&args->where.dir);
   2514      0       stevel }
   2515      0       stevel 
   2516      0       stevel void
   2517      0       stevel rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi,
   2518      0       stevel 	struct svc_req *req, cred_t *cr)
   2519      0       stevel {
   2520      0       stevel 	int error = 0;
   2521      0       stevel 	vnode_t *vp;
   2522      0       stevel 	struct vattr *bvap;
   2523      0       stevel 	struct vattr bva;
   2524      0       stevel 	struct vattr *avap;
   2525      0       stevel 	struct vattr ava;
   2526      0       stevel 	vnode_t *targvp = NULL;
   2527   7961      Natalie 	struct sockaddr *ca;
   2528   7961      Natalie 	char *name = NULL;
   2529      0       stevel 
   2530      0       stevel 	bvap = NULL;
   2531      0       stevel 	avap = NULL;
   2532      0       stevel 
   2533   1610      thurlow 	vp = nfs3_fhtovp(&args->object.dir, exi);
   2534   5982          ahl 
   2535   5982          ahl 	DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req,
   2536   5982          ahl 	    cred_t *, cr, vnode_t *, vp, REMOVE3args *, args);
   2537   5982          ahl 
   2538   5982          ahl 	if (vp == NULL) {
   2539   5982          ahl 		error = ESTALE;
   2540   5982          ahl 		goto err;
   2541      0       stevel 	}
   2542      0       stevel 
   2543      0       stevel #ifdef DEBUG
   2544      0       stevel 	if (rfs3_do_pre_op_attr) {
   2545      0       stevel 		bva.va_mask = AT_ALL;
   2546   5331          amw 		bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
   2547   5331          amw 	} else
   2548   5331          amw 		bvap = NULL;
   2549   5331          amw #else
   2550   5331          amw 	bva.va_mask = AT_ALL;
   2551   5331          amw 	bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
   2552      0       stevel #endif
   2553      0       stevel 	avap = bvap;
   2554      0       stevel 
   2555      0       stevel 	if (vp->v_type != VDIR) {
   2556      0       stevel 		resp->status = NFS3ERR_NOTDIR;
   2557   5982          ahl 		goto err1;
   2558      0       stevel 	}
   2559      0       stevel 
   2560      0       stevel 	if (args->object.name == nfs3nametoolong) {
   2561      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
   2562   5982          ahl 		goto err1;
   2563      0       stevel 	}
   2564      0       stevel 
   2565      0       stevel 	if (args->object.name == NULL || *(args->object.name) == '\0') {
   2566      0       stevel 		resp->status = NFS3ERR_ACCES;
   2567   5982          ahl 		goto err1;
   2568   5982          ahl 	}
   2569   5982          ahl 
   2570   5982          ahl 	if (rdonly(exi, req)) {
   2571   5982          ahl 		resp->status = NFS3ERR_ROFS;
   2572   5982          ahl 		goto err1;
   2573      0       stevel 	}
   2574      0       stevel 
   2575   4971      jarrett 	if (is_system_labeled()) {
   2576   4971      jarrett 		bslabel_t *clabel = req->rq_label;
   2577   4971      jarrett 
   2578   4971      jarrett 		ASSERT(clabel != NULL);
   2579   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opremove__clabel, char *,
   2580   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   2581   4971      jarrett 
   2582   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   2583   9871      Jarrett 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
   2584   9871      Jarrett 			    exi)) {
   2585   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   2586   5982          ahl 				goto err1;
   2587   4971      jarrett 			}
   2588   4971      jarrett 		}
   2589   4971      jarrett 	}
   2590   4971      jarrett 
   2591   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
   2592   7961      Natalie 	name = nfscmd_convname(ca, exi, args->object.name,
   2593   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
   2594   7961      Natalie 
   2595   7961      Natalie 	if (name == NULL) {
   2596   7961      Natalie 		resp->status = NFS3ERR_INVAL;
   2597   7961      Natalie 		goto err1;
   2598   7961      Natalie 	}
   2599   7961      Natalie 
   2600      0       stevel 	/*
   2601      0       stevel 	 * Check for a conflict with a non-blocking mandatory share
   2602      0       stevel 	 * reservation and V4 delegations
   2603      0       stevel 	 */
   2604   7961      Natalie 	error = VOP_LOOKUP(vp, name, &targvp, NULL, 0,
   2605   5599      jwahlig 	    NULL, cr, NULL, NULL, NULL);
   2606      0       stevel 	if (error != 0)
   2607   5982          ahl 		goto err;
   2608      0       stevel 
   2609      0       stevel 	if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
   2610      0       stevel 		resp->status = NFS3ERR_JUKEBOX;
   2611   5982          ahl 		goto err1;
   2612      0       stevel 	}
   2613      0       stevel 
   2614      0       stevel 	if (!nbl_need_check(targvp)) {
   2615   7961      Natalie 		error = VOP_REMOVE(vp, name, cr, NULL, 0);
   2616      0       stevel 	} else {
   2617      0       stevel 		nbl_start_crit(targvp, RW_READER);
   2618   5331          amw 		if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
   2619      0       stevel 			error = EACCES;
   2620      0       stevel 		} else {
   2621   7961      Natalie 			error = VOP_REMOVE(vp, name, cr, NULL, 0);
   2622      0       stevel 		}
   2623      0       stevel 		nbl_end_crit(targvp);
   2624      0       stevel 	}
   2625      0       stevel 	VN_RELE(targvp);
   2626      0       stevel 	targvp = NULL;
   2627      0       stevel 
   2628      0       stevel #ifdef DEBUG
   2629      0       stevel 	if (rfs3_do_post_op_attr) {
   2630      0       stevel 		ava.va_mask = AT_ALL;
   2631   5331          amw 		avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
   2632   5331          amw 	} else
   2633   5331          amw 		avap = NULL;
   2634   5331          amw #else
   2635   5331          amw 	ava.va_mask = AT_ALL;
   2636   5331          amw 	avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
   2637   5331          amw #endif
   2638   5331          amw 
   2639   5331          amw 	/*
   2640   5331          amw 	 * Force modified data and metadata out to stable storage.
   2641   5331          amw 	 */
   2642   5331          amw 	(void) VOP_FSYNC(vp, 0, cr, NULL);
   2643      0       stevel 
   2644      0       stevel 	if (error)
   2645   5982          ahl 		goto err;
   2646      0       stevel 
   2647      0       stevel 	resp->status = NFS3_OK;
   2648      0       stevel 	vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
   2649   5982          ahl 	goto out;
   2650   5982          ahl 
   2651   5982          ahl err:
   2652   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   2653   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   2654   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   2655   5982          ahl 	} else
   2656   5982          ahl 		resp->status = puterrno3(error);
   2657   5982          ahl err1:
   2658      0       stevel 	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
   2659   5982          ahl out:
   2660   5982          ahl 	DTRACE_NFSV3_4(op__remove__done, struct svc_req *, req,
   2661   5982          ahl 	    cred_t *, cr, vnode_t *, vp, REMOVE3res *, resp);
   2662   7961      Natalie 
   2663   7961      Natalie 	if (name != NULL && name != args->object.name)
   2664   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
   2665   7961      Natalie 
   2666   5982          ahl 	if (vp != NULL)
   2667   5982          ahl 		VN_RELE(vp);
   2668      0       stevel }
   2669      0       stevel 
   2670   1610      thurlow void *
   2671      0       stevel rfs3_remove_getfh(REMOVE3args *args)
   2672      0       stevel {
   2673      0       stevel 
   2674   1610      thurlow 	return (&args->object.dir);
   2675      0       stevel }
   2676      0       stevel 
   2677      0       stevel void
   2678      0       stevel rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi,
   2679      0       stevel 	struct svc_req *req, cred_t *cr)
   2680      0       stevel {
   2681      0       stevel 	int error;
   2682      0       stevel 	vnode_t *vp;
   2683      0       stevel 	struct vattr *bvap;
   2684      0       stevel 	struct vattr bva;
   2685      0       stevel 	struct vattr *avap;
   2686      0       stevel 	struct vattr ava;
   2687   7961      Natalie 	struct sockaddr *ca;
   2688   7961      Natalie 	char *name = NULL;
   2689      0       stevel 
   2690      0       stevel 	bvap = NULL;
   2691      0       stevel 	avap = NULL;
   2692      0       stevel 
   2693   1610      thurlow 	vp = nfs3_fhtovp(&args->object.dir, exi);
   2694   5982          ahl 
   2695   5982          ahl 	DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req,
   2696   5982          ahl 	    cred_t *, cr, vnode_t *, vp, RMDIR3args *, args);
   2697   5982          ahl 
   2698   5982          ahl 	if (vp == NULL) {
   2699   5982          ahl 		error = ESTALE;
   2700   5982          ahl 		goto err;
   2701      0       stevel 	}
   2702      0       stevel 
   2703      0       stevel #ifdef DEBUG
   2704      0       stevel 	if (rfs3_do_pre_op_attr) {
   2705      0       stevel 		bva.va_mask = AT_ALL;
   2706   5331          amw 		bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
   2707   5331          amw 	} else
   2708   5331          amw 		bvap = NULL;
   2709   5331          amw #else
   2710   5331          amw 	bva.va_mask = AT_ALL;
   2711   5331          amw 	bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
   2712      0       stevel #endif
   2713      0       stevel 	avap = bvap;
   2714      0       stevel 
   2715      0       stevel 	if (vp->v_type != VDIR) {
   2716      0       stevel 		resp->status = NFS3ERR_NOTDIR;
   2717   5982          ahl 		goto err1;
   2718      0       stevel 	}
   2719      0       stevel 
   2720      0       stevel 	if (args->object.name == nfs3nametoolong) {
   2721      0       stevel 		resp->status = NFS3ERR_NAMETOOLONG;
   2722   5982          ahl 		goto err1;
   2723      0       stevel 	}
   2724      0       stevel 
   2725      0       stevel 	if (args->object.name == NULL || *(args->object.name) == '\0') {
   2726      0       stevel 		resp->status = NFS3ERR_ACCES;
   2727   5982          ahl 		goto err1;
   2728   5982          ahl 	}
   2729   5982          ahl 
   2730   5982          ahl 	if (rdonly(exi, req)) {
   2731   5982          ahl 		resp->status = NFS3ERR_ROFS;
   2732   5982          ahl 		goto err1;
   2733   4971      jarrett 	}
   2734   4971      jarrett 
   2735   4971      jarrett 	if (is_system_labeled()) {
   2736   4971      jarrett 		bslabel_t *clabel = req->rq_label;
   2737   4971      jarrett 
   2738   4971      jarrett 		ASSERT(clabel != NULL);
   2739   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__opremovedir__clabel, char *,
   2740   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   2741   4971      jarrett 
   2742   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   2743   9871      Jarrett 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
   2744   9871      Jarrett 			    exi)) {
   2745   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   2746   5982          ahl 				goto err1;
   2747   4971      jarrett 			}
   2748   4971      jarrett 		}
   2749      0       stevel 	}
   2750      0       stevel 
   2751   7961      Natalie 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
   2752   7961      Natalie 	name = nfscmd_convname(ca, exi, args->object.name,
   2753   7961      Natalie 	    NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
   2754   7961      Natalie 
   2755   7961      Natalie 	if (name == NULL) {
   2756   7961      Natalie 		resp->status = NFS3ERR_INVAL;
   2757   7961      Natalie 		goto err1;
   2758   7961      Natalie 	}
   2759   7961      Natalie 
   2760   7961      Natalie 	error = VOP_RMDIR(vp, name, rootdir, cr, NULL, 0);
   2761   7961      Natalie 
   2762   7961      Natalie 	if (name != args->object.name)
   2763   7961      Natalie 		kmem_free(name, MAXPATHLEN + 1);
   2764   5331          amw 
   2765   5331          amw #ifdef DEBUG
   2766   5331          amw 	if (rfs3_do_post_op_attr) {
   2767   5331          amw 		ava.va_mask = AT_ALL;
   2768   5331          amw 		avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
   2769   5331          amw 	} else
   2770   5331          amw 		avap = NULL;
   2771   5331          amw #else
   2772   5331          amw 	ava.va_mask = AT_ALL;
   2773   5331          amw 	avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
   2774   5331          amw #endif
   2775   5331          amw 
   2776   5331          amw 	/*
   2777   5331          amw 	 * Force modified data and metadata out to stable storage.
   2778   5331          amw 	 */
   2779   5331          amw 	(void) VOP_FSYNC(vp, 0, cr, NULL);
   2780      0       stevel 
   2781      0       stevel 	if (error) {
   2782      0       stevel 		/*
   2783      0       stevel 		 * System V defines rmdir to return EEXIST, not ENOTEMPTY,
   2784      0       stevel 		 * if the directory is not empty.  A System V NFS server
   2785      0       stevel 		 * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
   2786      0       stevel 		 * over the wire.
   2787      0       stevel 		 */
   2788      0       stevel 		if (error == EEXIST)
   2789      0       stevel 			error = ENOTEMPTY;
   2790   5982          ahl 		goto err;
   2791   5982          ahl 	}
   2792      0       stevel 
   2793      0       stevel 	resp->status = NFS3_OK;
   2794      0       stevel 	vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
   2795   5982          ahl 	goto out;
   2796   5982          ahl 
   2797   5982          ahl err:
   2798   5982          ahl 	if (curthread->t_flag & T_WOULDBLOCK) {
   2799   5982          ahl 		curthread->t_flag &= ~T_WOULDBLOCK;
   2800   5982          ahl 		resp->status = NFS3ERR_JUKEBOX;
   2801   5982          ahl 	} else
   2802   5982          ahl 		resp->status = puterrno3(error);
   2803   5982          ahl err1:
   2804      0       stevel 	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
   2805   5982          ahl out:
   2806   5982          ahl 	DTRACE_NFSV3_4(op__rmdir__done, struct svc_req *, req,
   2807   5982          ahl 	    cred_t *, cr, vnode_t *, vp, RMDIR3res *, resp);
   2808   5982          ahl 	if (vp != NULL)
   2809   5982          ahl 		VN_RELE(vp);
   2810   5982          ahl 
   2811      0       stevel }
   2812      0       stevel 
   2813   1610      thurlow void *
   2814      0       stevel rfs3_rmdir_getfh(RMDIR3args *args)
   2815      0       stevel {
   2816      0       stevel 
   2817   1610      thurlow 	return (&args->object.dir);
   2818      0       stevel }
   2819      0       stevel 
   2820      0       stevel void
   2821      0       stevel rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi,
   2822      0       stevel 	struct svc_req *req, cred_t *cr)
   2823      0       stevel {
   2824      0       stevel 	int error = 0;
   2825      0       stevel 	vnode_t *fvp;
   2826      0       stevel 	vnode_t *tvp;
   2827      0       stevel 	vnode_t *targvp;
   2828      0       stevel 	struct vattr *fbvap;
   2829      0       stevel 	struct vattr fbva;
   2830      0       stevel 	struct vattr *favap;
   2831      0       stevel 	struct vattr fava;
   2832      0       stevel 	struct vattr *tbvap;
   2833      0       stevel 	struct vattr tbva;
   2834      0       stevel 	struct vattr *tavap;
   2835      0       stevel 	struct vattr tava;
   2836   1610      thurlow 	nfs_fh3 *fh3;
   2837      0       stevel 	struct exportinfo *to_exi;
   2838      0       stevel 	vnode_t *srcvp = NULL;
   2839   4971      jarrett 	bslabel_t *clabel;
   2840   7961      Natalie 	struct sockaddr *ca;
   2841   7961      Natalie 	char *name = NULL;
   2842   7961      Natalie 	char *toname = NULL;
   2843      0       stevel 
   2844      0       stevel 	fbvap = NULL;
   2845      0       stevel 	favap = NULL;
   2846      0       stevel 	tbvap = NULL;
   2847      0       stevel 	tavap = NULL;
   2848      0       stevel 	tvp = NULL;
   2849      0       stevel 
   2850   1610      thurlow 	fvp = nfs3_fhtovp(&args->from.dir, exi);
   2851   5982          ahl 
   2852   5982          ahl 	DTRACE_NFSV3_4(op__rename__start, struct svc_req *, req,
   2853   5982          ahl 	    cred_t *, cr, vnode_t *, fvp, RENAME3args *, args);
   2854   5982          ahl 
   2855      0       stevel 	if (fvp == NULL) {
   2856      0       stevel 		error = ESTALE;
   2857   5982          ahl 		goto err;
   2858      0       stevel 	}
   2859      0       stevel 
   2860   4971      jarrett 	if (is_system_labeled()) {
   2861   4971      jarrett 		clabel = req->rq_label;
   2862   4971      jarrett 		ASSERT(clabel != NULL);
   2863   4971      jarrett 		DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *,
   2864   4971      jarrett 		    "got client label from request(1)", struct svc_req *, req);
   2865   4971      jarrett 
   2866   4971      jarrett 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
   2867   9871      Jarrett 			if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK,
   2868   9871      Jarrett 			    exi)) {
   2869   4971      jarrett 				resp->status = NFS3ERR_ACCES;
   2870   5982          ahl 				goto err1;
   2871   4971      jarrett 			}
   2872   4971      jarrett 		}
   2873   4971      jarrett 	}
   2874   4971      jarrett 
   2875      0       stevel #ifdef DEBUG
   2876      0       stevel 	if (rfs3_do_pre_op_attr) {
   2877      0       stevel 		fbva.va_mask = AT_ALL;
   2878   5331          amw 		fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
   2879      0       stevel 	} else
   2880      0       stevel 		fbvap = NULL;
   2881      0       stevel #else
   2882      0       stevel 	fbva.va_mask = AT_ALL;
   2883   5331          amw 	fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
   2884      0       stevel #endif
   2885      0       stevel 	favap = fbvap;
   2886      0       stevel 
   2887   1610      thurlow 	fh3 = &args->to.dir;
   2888   1610      thurlow 	to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
   2889      0       stevel 	if (to_exi == NULL) {
   2890      0       stevel 		resp->status = NFS3ERR_ACCES;
   2891   5982          ahl 		goto err1;
   2892      0       stevel 	}
   2893      0       stevel 	exi_rele(to_exi);
   2894      0       stevel 
   2895      0       stevel 	if (to_exi != exi) {
   2896      0       stevel 		resp->status = NFS3ERR_XDEV;
   2897   5982          ahl 		goto err1;
   2898      0       stevel 	}
   2899      0       stevel 
   2900   1610      thurlow 	tvp = nfs3_fhtovp(&args->to.dir, exi);
   2901      0       stevel 	if (tvp == NULL) {
   2902      0       stevel 		error = ESTALE;
   2903   5982          ahl 		goto err;
   2904      0       stevel 	}
   2905      0       stevel 
   2906      0       stevel #ifdef DEBUG
   2907      0       stevel 	if (rfs3_do_pre_op_attr) {
   2908      0       stevel 		tbva.va_mask = AT_ALL;
   2909   5331