17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
527242a7cSthurlow * Common Development and Distribution License (the "License").
627242a7cSthurlow * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21f46abf18SMarcel Telka
227c478bd9Sstevel@tonic-gate /*
230dfe541eSEvan Layton * Copyright 2018 Nexenta Systems, Inc.
2435bbd688SKaren Rochford * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
25e36d7b11SSebastien Roy * Copyright (c) 2013 by Delphix. All rights reserved.
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
297c478bd9Sstevel@tonic-gate /* All Rights Reserved */
307c478bd9Sstevel@tonic-gate
310dfe541eSEvan Layton
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <sys/systm.h>
357c478bd9Sstevel@tonic-gate #include <sys/cred.h>
367c478bd9Sstevel@tonic-gate #include <sys/buf.h>
377c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
387c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
397c478bd9Sstevel@tonic-gate #include <sys/uio.h>
407c478bd9Sstevel@tonic-gate #include <sys/errno.h>
417c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
427c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
437c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
447c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
457c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
467c478bd9Sstevel@tonic-gate #include <sys/debug.h>
477c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
487c478bd9Sstevel@tonic-gate #include <sys/flock.h>
497c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h>
507c478bd9Sstevel@tonic-gate #include <sys/policy.h>
5103986916Sjarrett #include <sys/sdt.h>
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate #include <rpc/types.h>
547c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
557c478bd9Sstevel@tonic-gate #include <rpc/svc.h>
560a701b1eSRobert Gordon #include <rpc/rpc_rdma.h>
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
597c478bd9Sstevel@tonic-gate #include <nfs/export.h>
60b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <nfs/nfs_cmd.h>
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
6303986916Sjarrett #include <sys/tsol/label.h>
6403986916Sjarrett #include <sys/tsol/tndb.h>
6503986916Sjarrett
665679c89fSjv #include <sys/zone.h>
675679c89fSjv
6803986916Sjarrett #include <inet/ip.h>
6903986916Sjarrett #include <inet/ip6.h>
7003986916Sjarrett
710dfe541eSEvan Layton /*
720dfe541eSEvan Layton * Zone global variables of NFSv3 server
730dfe541eSEvan Layton */
740dfe541eSEvan Layton typedef struct nfs3_srv {
750dfe541eSEvan Layton writeverf3 write3verf;
760dfe541eSEvan Layton } nfs3_srv_t;
770dfe541eSEvan Layton
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate * These are the interface routines for the server side of the
807c478bd9Sstevel@tonic-gate * Network File System. See the NFS version 3 protocol specification
817c478bd9Sstevel@tonic-gate * for a description of this interface.
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate static int sattr3_to_vattr(sattr3 *, struct vattr *);
857c478bd9Sstevel@tonic-gate static int vattr_to_fattr3(struct vattr *, fattr3 *);
867c478bd9Sstevel@tonic-gate static int vattr_to_wcc_attr(struct vattr *, wcc_attr *);
877c478bd9Sstevel@tonic-gate static void vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
887c478bd9Sstevel@tonic-gate static void vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
890a701b1eSRobert Gordon static int rdma_setup_read_data3(READ3args *, READ3resok *);
907c478bd9Sstevel@tonic-gate
91c242f9a0Schunli zhang - Sun Microsystems - Irvine United States extern int nfs_loaned_buffers;
92c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
93cfae96c2Sjwahlig u_longlong_t nfs3_srv_caller_id;
94cfae96c2Sjwahlig
950dfe541eSEvan Layton static nfs3_srv_t *
nfs3_get_srv(void)960dfe541eSEvan Layton nfs3_get_srv(void)
970dfe541eSEvan Layton {
980dfe541eSEvan Layton nfs_globals_t *ng = nfs_srv_getzg();
990dfe541eSEvan Layton nfs3_srv_t *srv = ng->nfs3_srv;
1000dfe541eSEvan Layton ASSERT(srv != NULL);
1010dfe541eSEvan Layton return (srv);
1020dfe541eSEvan Layton }
1030dfe541eSEvan Layton
1047c478bd9Sstevel@tonic-gate /* ARGSUSED */
1057c478bd9Sstevel@tonic-gate void
rfs3_getattr(GETATTR3args * args,GETATTR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)1067c478bd9Sstevel@tonic-gate rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
1075cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate int error;
1107c478bd9Sstevel@tonic-gate vnode_t *vp;
1117c478bd9Sstevel@tonic-gate struct vattr va;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
114e1adf50cSahl
1150dfe541eSEvan Layton DTRACE_NFSV3_5(op__getattr__start, struct svc_req *, req,
1160dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1170dfe541eSEvan Layton GETATTR3args *, args);
118e1adf50cSahl
1197c478bd9Sstevel@tonic-gate if (vp == NULL) {
1207c478bd9Sstevel@tonic-gate error = ESTALE;
1217c478bd9Sstevel@tonic-gate goto out;
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1257c478bd9Sstevel@tonic-gate error = rfs4_delegated_getattr(vp, &va, 0, cr);
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate if (!error) {
1282f172c55SRobert Thurlow /* Lie about the object type for a referral */
1292f172c55SRobert Thurlow if (vn_is_nfs_reparse(vp, cr))
1302f172c55SRobert Thurlow va.va_type = VLNK;
1312f172c55SRobert Thurlow
1327c478bd9Sstevel@tonic-gate /* overflow error if time or size is out of range */
1337c478bd9Sstevel@tonic-gate error = vattr_to_fattr3(&va, &resp->resok.obj_attributes);
1347c478bd9Sstevel@tonic-gate if (error)
1357c478bd9Sstevel@tonic-gate goto out;
1367c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
137e1adf50cSahl
1380dfe541eSEvan Layton DTRACE_NFSV3_5(op__getattr__done, struct svc_req *, req,
1390dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1400dfe541eSEvan Layton GETATTR3res *, resp);
141e1adf50cSahl
142e1adf50cSahl VN_RELE(vp);
143e1adf50cSahl
1447c478bd9Sstevel@tonic-gate return;
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate out:
1487c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
1497c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
1507c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
1517c478bd9Sstevel@tonic-gate } else
1527c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
153e1adf50cSahl
1540dfe541eSEvan Layton DTRACE_NFSV3_5(op__getattr__done, struct svc_req *, req,
1550dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1560dfe541eSEvan Layton GETATTR3res *, resp);
157e1adf50cSahl
158e1adf50cSahl if (vp != NULL)
159e1adf50cSahl VN_RELE(vp);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate
16227242a7cSthurlow void *
rfs3_getattr_getfh(GETATTR3args * args)1637c478bd9Sstevel@tonic-gate rfs3_getattr_getfh(GETATTR3args *args)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate
16627242a7cSthurlow return (&args->object);
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate void
rfs3_setattr(SETATTR3args * args,SETATTR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)1707c478bd9Sstevel@tonic-gate rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
1715cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate int error;
1747c478bd9Sstevel@tonic-gate vnode_t *vp;
1757c478bd9Sstevel@tonic-gate struct vattr *bvap;
1767c478bd9Sstevel@tonic-gate struct vattr bva;
1777c478bd9Sstevel@tonic-gate struct vattr *avap;
1787c478bd9Sstevel@tonic-gate struct vattr ava;
1797c478bd9Sstevel@tonic-gate int flag;
1807c478bd9Sstevel@tonic-gate int in_crit = 0;
1817c478bd9Sstevel@tonic-gate struct flock64 bf;
182cfae96c2Sjwahlig caller_context_t ct;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate bvap = NULL;
1857c478bd9Sstevel@tonic-gate avap = NULL;
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
188e1adf50cSahl
1890dfe541eSEvan Layton DTRACE_NFSV3_5(op__setattr__start, struct svc_req *, req,
1900dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1910dfe541eSEvan Layton SETATTR3args *, args);
192e1adf50cSahl
1937c478bd9Sstevel@tonic-gate if (vp == NULL) {
1947c478bd9Sstevel@tonic-gate error = ESTALE;
1957c478bd9Sstevel@tonic-gate goto out;
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->new_attributes, &ava);
1997c478bd9Sstevel@tonic-gate if (error)
2007c478bd9Sstevel@tonic-gate goto out;
2017c478bd9Sstevel@tonic-gate
20203986916Sjarrett if (is_system_labeled()) {
20303986916Sjarrett bslabel_t *clabel = req->rq_label;
20403986916Sjarrett
20503986916Sjarrett ASSERT(clabel != NULL);
20603986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opsetattr__clabel, char *,
20703986916Sjarrett "got client label from request(1)", struct svc_req *, req);
20803986916Sjarrett
20903986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
210bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
211bd6f1640SJarrett Lu exi)) {
21203986916Sjarrett resp->status = NFS3ERR_ACCES;
21303986916Sjarrett goto out1;
21403986916Sjarrett }
21503986916Sjarrett }
21603986916Sjarrett }
21703986916Sjarrett
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate * We need to specially handle size changes because of
2207c478bd9Sstevel@tonic-gate * possible conflicting NBMAND locks. Get into critical
2217c478bd9Sstevel@tonic-gate * region before VOP_GETATTR, so the size attribute is
2227c478bd9Sstevel@tonic-gate * valid when checking conflicts.
2237c478bd9Sstevel@tonic-gate *
2247c478bd9Sstevel@tonic-gate * Also, check to see if the v4 side of the server has
2257c478bd9Sstevel@tonic-gate * delegated this file. If so, then we return JUKEBOX to
2267c478bd9Sstevel@tonic-gate * allow the client to retrasmit its request.
2277c478bd9Sstevel@tonic-gate */
2287c478bd9Sstevel@tonic-gate if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
2297c478bd9Sstevel@tonic-gate if (nbl_need_check(vp)) {
2307c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_READER);
2317c478bd9Sstevel@tonic-gate in_crit = 1;
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
2367c478bd9Sstevel@tonic-gate error = rfs4_delegated_getattr(vp, &bva, 0, cr);
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
2407c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
2417c478bd9Sstevel@tonic-gate */
2427c478bd9Sstevel@tonic-gate if (error)
2437c478bd9Sstevel@tonic-gate goto out;
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate bvap = &bva;
2467c478bd9Sstevel@tonic-gate
2475cb0d679SMarcel Telka if (rdonly(ro, vp)) {
2487c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2497c478bd9Sstevel@tonic-gate goto out1;
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate if (args->guard.check &&
2537c478bd9Sstevel@tonic-gate (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
2547c478bd9Sstevel@tonic-gate args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
2557c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOT_SYNC;
2567c478bd9Sstevel@tonic-gate goto out1;
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
2607c478bd9Sstevel@tonic-gate flag = ATTR_UTIME;
2617c478bd9Sstevel@tonic-gate else
2627c478bd9Sstevel@tonic-gate flag = 0;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate /*
2657c478bd9Sstevel@tonic-gate * If the filesystem is exported with nosuid, then mask off
2667c478bd9Sstevel@tonic-gate * the setuid and setgid bits.
2677c478bd9Sstevel@tonic-gate */
2687c478bd9Sstevel@tonic-gate if ((ava.va_mask & AT_MODE) && vp->v_type == VREG &&
2697c478bd9Sstevel@tonic-gate (exi->exi_export.ex_flags & EX_NOSUID))
2707c478bd9Sstevel@tonic-gate ava.va_mode &= ~(VSUID | VSGID);
2717c478bd9Sstevel@tonic-gate
272cfae96c2Sjwahlig ct.cc_sysid = 0;
273cfae96c2Sjwahlig ct.cc_pid = 0;
274cfae96c2Sjwahlig ct.cc_caller_id = nfs3_srv_caller_id;
275cfae96c2Sjwahlig ct.cc_flags = CC_DONTBLOCK;
276cfae96c2Sjwahlig
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate * We need to specially handle size changes because it is
2797c478bd9Sstevel@tonic-gate * possible for the client to create a file with modes
2807c478bd9Sstevel@tonic-gate * which indicate read-only, but with the file opened for
2817c478bd9Sstevel@tonic-gate * writing. If the client then tries to set the size of
2827c478bd9Sstevel@tonic-gate * the file, then the normal access checking done in
2837c478bd9Sstevel@tonic-gate * VOP_SETATTR would prevent the client from doing so,
2847c478bd9Sstevel@tonic-gate * although it should be legal for it to do so. To get
2857c478bd9Sstevel@tonic-gate * around this, we do the access checking for ourselves
2867c478bd9Sstevel@tonic-gate * and then use VOP_SPACE which doesn't do the access
2877c478bd9Sstevel@tonic-gate * checking which VOP_SETATTR does. VOP_SPACE can only
2887c478bd9Sstevel@tonic-gate * operate on VREG files, let VOP_SETATTR handle the other
2897c478bd9Sstevel@tonic-gate * extremely rare cases.
2907c478bd9Sstevel@tonic-gate * Also the client should not be allowed to change the
2917c478bd9Sstevel@tonic-gate * size of the file if there is a conflicting non-blocking
2927c478bd9Sstevel@tonic-gate * mandatory lock in the region the change.
2937c478bd9Sstevel@tonic-gate */
2947c478bd9Sstevel@tonic-gate if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
2957c478bd9Sstevel@tonic-gate if (in_crit) {
2967c478bd9Sstevel@tonic-gate u_offset_t offset;
2977c478bd9Sstevel@tonic-gate ssize_t length;
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate if (ava.va_size < bva.va_size) {
3007c478bd9Sstevel@tonic-gate offset = ava.va_size;
3017c478bd9Sstevel@tonic-gate length = bva.va_size - ava.va_size;
3027c478bd9Sstevel@tonic-gate } else {
3037c478bd9Sstevel@tonic-gate offset = bva.va_size;
3047c478bd9Sstevel@tonic-gate length = ava.va_size - bva.va_size;
3057c478bd9Sstevel@tonic-gate }
306da6c28aaSamw if (nbl_conflict(vp, NBL_WRITE, offset, length, 0,
307da6c28aaSamw NULL)) {
3087c478bd9Sstevel@tonic-gate error = EACCES;
3097c478bd9Sstevel@tonic-gate goto out;
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate if (crgetuid(cr) == bva.va_uid && ava.va_size != bva.va_size) {
3147c478bd9Sstevel@tonic-gate ava.va_mask &= ~AT_SIZE;
3157c478bd9Sstevel@tonic-gate bf.l_type = F_WRLCK;
3167c478bd9Sstevel@tonic-gate bf.l_whence = 0;
3177c478bd9Sstevel@tonic-gate bf.l_start = (off64_t)ava.va_size;
3187c478bd9Sstevel@tonic-gate bf.l_len = 0;
3197c478bd9Sstevel@tonic-gate bf.l_sysid = 0;
3207c478bd9Sstevel@tonic-gate bf.l_pid = 0;
3217c478bd9Sstevel@tonic-gate error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
322cfae96c2Sjwahlig (offset_t)ava.va_size, cr, &ct);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate if (!error && ava.va_mask)
327cfae96c2Sjwahlig error = VOP_SETATTR(vp, &ava, flag, cr, &ct);
328cfae96c2Sjwahlig
329cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
330cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
331cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
332cfae96c2Sjwahlig goto out1;
333cfae96c2Sjwahlig }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
3367c478bd9Sstevel@tonic-gate avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate /*
3397c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
3407c478bd9Sstevel@tonic-gate */
341cfae96c2Sjwahlig (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate if (error)
3447c478bd9Sstevel@tonic-gate goto out;
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate if (in_crit)
3477c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
3507c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
351e1adf50cSahl
3520dfe541eSEvan Layton DTRACE_NFSV3_5(op__setattr__done, struct svc_req *, req,
3530dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3540dfe541eSEvan Layton SETATTR3res *, resp);
355e1adf50cSahl
356e1adf50cSahl VN_RELE(vp);
357e1adf50cSahl
3587c478bd9Sstevel@tonic-gate return;
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate out:
3617c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
3627c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
3637c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
3647c478bd9Sstevel@tonic-gate } else
3657c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
3667c478bd9Sstevel@tonic-gate out1:
3670dfe541eSEvan Layton DTRACE_NFSV3_5(op__setattr__done, struct svc_req *, req,
3680dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3690dfe541eSEvan Layton SETATTR3res *, resp);
370e1adf50cSahl
3717c478bd9Sstevel@tonic-gate if (vp != NULL) {
3727c478bd9Sstevel@tonic-gate if (in_crit)
3737c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
3747c478bd9Sstevel@tonic-gate VN_RELE(vp);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resfail.obj_wcc);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate
37927242a7cSthurlow void *
rfs3_setattr_getfh(SETATTR3args * args)3807c478bd9Sstevel@tonic-gate rfs3_setattr_getfh(SETATTR3args *args)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate
38327242a7cSthurlow return (&args->object);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate /* ARGSUSED */
3877c478bd9Sstevel@tonic-gate void
rfs3_lookup(LOOKUP3args * args,LOOKUP3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)3887c478bd9Sstevel@tonic-gate rfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi,
3895cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate int error;
3927c478bd9Sstevel@tonic-gate vnode_t *vp;
3937c478bd9Sstevel@tonic-gate vnode_t *dvp;
3947c478bd9Sstevel@tonic-gate struct vattr *vap;
3957c478bd9Sstevel@tonic-gate struct vattr va;
3967c478bd9Sstevel@tonic-gate struct vattr *dvap;
3977c478bd9Sstevel@tonic-gate struct vattr dva;
3987c478bd9Sstevel@tonic-gate nfs_fh3 *fhp;
3997c478bd9Sstevel@tonic-gate struct sec_ol sec = {0, 0};
4007c478bd9Sstevel@tonic-gate bool_t publicfh_flag = FALSE, auth_weak = FALSE;
401b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
402b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate dvap = NULL;
4057c478bd9Sstevel@tonic-gate
406f7db5903SVitaliy Gusev if (exi != NULL)
407f7db5903SVitaliy Gusev exi_hold(exi);
408f7db5903SVitaliy Gusev
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * Allow lookups from the root - the default
4117c478bd9Sstevel@tonic-gate * location of the public filehandle.
4127c478bd9Sstevel@tonic-gate */
4137c478bd9Sstevel@tonic-gate if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
4140dfe541eSEvan Layton ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
4150dfe541eSEvan Layton dvp = ZONE_ROOTVP();
4167c478bd9Sstevel@tonic-gate VN_HOLD(dvp);
417e1adf50cSahl
4180dfe541eSEvan Layton DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
4190dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
4200dfe541eSEvan Layton LOOKUP3args *, args);
4217c478bd9Sstevel@tonic-gate } else {
42227242a7cSthurlow dvp = nfs3_fhtovp(&args->what.dir, exi);
423e1adf50cSahl
4240dfe541eSEvan Layton DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
4250dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
4260dfe541eSEvan Layton LOOKUP3args *, args);
427e1adf50cSahl
4287c478bd9Sstevel@tonic-gate if (dvp == NULL) {
4297c478bd9Sstevel@tonic-gate error = ESTALE;
4307c478bd9Sstevel@tonic-gate goto out;
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate dva.va_mask = AT_ALL;
435da6c28aaSamw dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate if (args->what.name == nfs3nametoolong) {
4387c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
4397c478bd9Sstevel@tonic-gate goto out1;
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate if (args->what.name == NULL || *(args->what.name) == '\0') {
4437c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
4447c478bd9Sstevel@tonic-gate goto out1;
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate
44727242a7cSthurlow fhp = &args->what.dir;
4480dfe541eSEvan Layton ASSERT3U(curzone->zone_id, ==, exi->exi_zoneid); /* exi is non-NULL */
4497c478bd9Sstevel@tonic-gate if (strcmp(args->what.name, "..") == 0 &&
45027242a7cSthurlow EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
451f7db5903SVitaliy Gusev if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
4520dfe541eSEvan Layton ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp))) {
453f7db5903SVitaliy Gusev /*
454f7db5903SVitaliy Gusev * special case for ".." and 'nohide'exported root
455f7db5903SVitaliy Gusev */
456f7db5903SVitaliy Gusev if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
457f7db5903SVitaliy Gusev resp->status = NFS3ERR_ACCES;
458f7db5903SVitaliy Gusev goto out1;
459f7db5903SVitaliy Gusev }
460f7db5903SVitaliy Gusev } else {
461f7db5903SVitaliy Gusev resp->status = NFS3ERR_NOENT;
462f7db5903SVitaliy Gusev goto out1;
463f7db5903SVitaliy Gusev }
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate
466b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
467b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->what.name,
468b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
469b89a8333Snatalie li - Sun Microsystems - Irvine United States
470b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
471b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_ACCES;
472b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
473b89a8333Snatalie li - Sun Microsystems - Irvine United States }
474b89a8333Snatalie li - Sun Microsystems - Irvine United States
4757c478bd9Sstevel@tonic-gate /*
4767c478bd9Sstevel@tonic-gate * If the public filehandle is used then allow
4777c478bd9Sstevel@tonic-gate * a multi-component lookup
4787c478bd9Sstevel@tonic-gate */
47927242a7cSthurlow if (PUBLIC_FH3(&args->what.dir)) {
4807c478bd9Sstevel@tonic-gate publicfh_flag = TRUE;
481f7db5903SVitaliy Gusev
482f7db5903SVitaliy Gusev exi_rele(exi);
4830dfe541eSEvan Layton exi = NULL;
484f7db5903SVitaliy Gusev
485b89a8333Snatalie li - Sun Microsystems - Irvine United States error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
486596bc239SMarcel Telka &exi, &sec);
487f7db5903SVitaliy Gusev
48803986916Sjarrett /*
48903986916Sjarrett * Since WebNFS may bypass MOUNT, we need to ensure this
49003986916Sjarrett * request didn't come from an unlabeled admin_low client.
49103986916Sjarrett */
49203986916Sjarrett if (is_system_labeled() && error == 0) {
49303986916Sjarrett int addr_type;
49403986916Sjarrett void *ipaddr;
49503986916Sjarrett tsol_tpc_t *tp;
49603986916Sjarrett
49703986916Sjarrett if (ca->sa_family == AF_INET) {
49803986916Sjarrett addr_type = IPV4_VERSION;
49903986916Sjarrett ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
50003986916Sjarrett } else if (ca->sa_family == AF_INET6) {
50103986916Sjarrett addr_type = IPV6_VERSION;
50203986916Sjarrett ipaddr = &((struct sockaddr_in6 *)
50303986916Sjarrett ca)->sin6_addr;
50403986916Sjarrett }
50503986916Sjarrett tp = find_tpc(ipaddr, addr_type, B_FALSE);
50603986916Sjarrett if (tp == NULL || tp->tpc_tp.tp_doi !=
50703986916Sjarrett l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
50803986916Sjarrett SUN_CIPSO) {
50903986916Sjarrett VN_RELE(vp);
510f46abf18SMarcel Telka error = EACCES;
51103986916Sjarrett }
51203986916Sjarrett if (tp != NULL)
51303986916Sjarrett TPC_RELE(tp);
51403986916Sjarrett }
5157c478bd9Sstevel@tonic-gate } else {
516b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &vp,
517cfae96c2Sjwahlig NULL, 0, NULL, cr, NULL, NULL, NULL);
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate
520b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->what.name)
521b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
522b89a8333Snatalie li - Sun Microsystems - Irvine United States
523f7db5903SVitaliy Gusev if (error == 0 && vn_ismntpt(vp)) {
524f7db5903SVitaliy Gusev error = rfs_cross_mnt(&vp, &exi);
525f7db5903SVitaliy Gusev if (error)
526f7db5903SVitaliy Gusev VN_RELE(vp);
527f7db5903SVitaliy Gusev }
528f7db5903SVitaliy Gusev
52903986916Sjarrett if (is_system_labeled() && error == 0) {
53003986916Sjarrett bslabel_t *clabel = req->rq_label;
53103986916Sjarrett
53203986916Sjarrett ASSERT(clabel != NULL);
53303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
53403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
53503986916Sjarrett
53603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
53703986916Sjarrett if (!do_rfs_label_check(clabel, dvp,
538bd6f1640SJarrett Lu DOMINANCE_CHECK, exi)) {
53903986916Sjarrett VN_RELE(vp);
540f46abf18SMarcel Telka error = EACCES;
54103986916Sjarrett }
54203986916Sjarrett }
54303986916Sjarrett }
54403986916Sjarrett
5457c478bd9Sstevel@tonic-gate dva.va_mask = AT_ALL;
546da6c28aaSamw dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate if (error)
5497c478bd9Sstevel@tonic-gate goto out;
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate if (sec.sec_flags & SEC_QUERY) {
5527c478bd9Sstevel@tonic-gate error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
5537c478bd9Sstevel@tonic-gate } else {
5547c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.object, vp, exi);
5557c478bd9Sstevel@tonic-gate if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
5567c478bd9Sstevel@tonic-gate auth_weak = TRUE;
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate
559fd9d0a82SMarcel Telka if (error) {
560fd9d0a82SMarcel Telka VN_RELE(vp);
561fd9d0a82SMarcel Telka goto out;
562fd9d0a82SMarcel Telka }
563fd9d0a82SMarcel Telka
5647c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
5657c478bd9Sstevel@tonic-gate vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate VN_RELE(vp);
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
5707c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
5717c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate /*
5747c478bd9Sstevel@tonic-gate * If it's public fh, no 0x81, and client's flavor is
5757c478bd9Sstevel@tonic-gate * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
5767c478bd9Sstevel@tonic-gate * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
5777c478bd9Sstevel@tonic-gate */
5787c478bd9Sstevel@tonic-gate if (auth_weak)
5797c478bd9Sstevel@tonic-gate resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
5807c478bd9Sstevel@tonic-gate
5810dfe541eSEvan Layton DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
5820dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
5830dfe541eSEvan Layton LOOKUP3res *, resp);
584e1adf50cSahl VN_RELE(dvp);
5850dfe541eSEvan Layton exi_rele(exi);
586e1adf50cSahl
5877c478bd9Sstevel@tonic-gate return;
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate out:
5907c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
5917c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
5927c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
5937c478bd9Sstevel@tonic-gate } else
5947c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
5957c478bd9Sstevel@tonic-gate out1:
5960dfe541eSEvan Layton DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
5970dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
5980dfe541eSEvan Layton LOOKUP3res *, resp);
5990dfe541eSEvan Layton
600f7db5903SVitaliy Gusev if (exi != NULL)
601f7db5903SVitaliy Gusev exi_rele(exi);
602f7db5903SVitaliy Gusev
6037c478bd9Sstevel@tonic-gate if (dvp != NULL)
6047c478bd9Sstevel@tonic-gate VN_RELE(dvp);
6057c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate
60927242a7cSthurlow void *
rfs3_lookup_getfh(LOOKUP3args * args)6107c478bd9Sstevel@tonic-gate rfs3_lookup_getfh(LOOKUP3args *args)
6117c478bd9Sstevel@tonic-gate {
6127c478bd9Sstevel@tonic-gate
61327242a7cSthurlow return (&args->what.dir);
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate /* ARGSUSED */
6177c478bd9Sstevel@tonic-gate void
rfs3_access(ACCESS3args * args,ACCESS3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)6187c478bd9Sstevel@tonic-gate rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi,
6195cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
6207c478bd9Sstevel@tonic-gate {
6217c478bd9Sstevel@tonic-gate int error;
6227c478bd9Sstevel@tonic-gate vnode_t *vp;
6237c478bd9Sstevel@tonic-gate struct vattr *vap;
6247c478bd9Sstevel@tonic-gate struct vattr va;
6257c478bd9Sstevel@tonic-gate int checkwriteperm;
62603986916Sjarrett boolean_t dominant_label = B_FALSE;
62703986916Sjarrett boolean_t equal_label = B_FALSE;
62803986916Sjarrett boolean_t admin_low_client;
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate vap = NULL;
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
633e1adf50cSahl
6340dfe541eSEvan Layton DTRACE_NFSV3_5(op__access__start, struct svc_req *, req,
6350dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
6360dfe541eSEvan Layton ACCESS3args *, args);
637e1adf50cSahl
6387c478bd9Sstevel@tonic-gate if (vp == NULL) {
6397c478bd9Sstevel@tonic-gate error = ESTALE;
6407c478bd9Sstevel@tonic-gate goto out;
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate * If the file system is exported read only, it is not appropriate
6457c478bd9Sstevel@tonic-gate * to check write permissions for regular files and directories.
6467c478bd9Sstevel@tonic-gate * Special files are interpreted by the client, so the underlying
6477c478bd9Sstevel@tonic-gate * permissions are sent back to the client for interpretation.
6487c478bd9Sstevel@tonic-gate */
6495cb0d679SMarcel Telka if (rdonly(ro, vp) && (vp->v_type == VREG || vp->v_type == VDIR))
6507c478bd9Sstevel@tonic-gate checkwriteperm = 0;
6517c478bd9Sstevel@tonic-gate else
6527c478bd9Sstevel@tonic-gate checkwriteperm = 1;
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate /*
6557c478bd9Sstevel@tonic-gate * We need the mode so that we can correctly determine access
6567c478bd9Sstevel@tonic-gate * permissions relative to a mandatory lock file. Access to
6577c478bd9Sstevel@tonic-gate * mandatory lock files is denied on the server, so it might
6587c478bd9Sstevel@tonic-gate * as well be reflected to the server during the open.
6597c478bd9Sstevel@tonic-gate */
6607c478bd9Sstevel@tonic-gate va.va_mask = AT_MODE;
661da6c28aaSamw error = VOP_GETATTR(vp, &va, 0, cr, NULL);
6627c478bd9Sstevel@tonic-gate if (error)
6637c478bd9Sstevel@tonic-gate goto out;
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate vap = &va;
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gate resp->resok.access = 0;
6687c478bd9Sstevel@tonic-gate
66903986916Sjarrett if (is_system_labeled()) {
67003986916Sjarrett bslabel_t *clabel = req->rq_label;
67103986916Sjarrett
67203986916Sjarrett ASSERT(clabel != NULL);
67303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *,
67403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
67503986916Sjarrett
67603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
67703986916Sjarrett if ((equal_label = do_rfs_label_check(clabel, vp,
678bd6f1640SJarrett Lu EQUALITY_CHECK, exi)) == B_FALSE) {
67903986916Sjarrett dominant_label = do_rfs_label_check(clabel,
680bd6f1640SJarrett Lu vp, DOMINANCE_CHECK, exi);
68103986916Sjarrett } else
68203986916Sjarrett dominant_label = B_TRUE;
68303986916Sjarrett admin_low_client = B_FALSE;
68403986916Sjarrett } else
68503986916Sjarrett admin_low_client = B_TRUE;
68603986916Sjarrett }
68703986916Sjarrett
6887c478bd9Sstevel@tonic-gate if (args->access & ACCESS3_READ) {
689da6c28aaSamw error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
6907c478bd9Sstevel@tonic-gate if (error) {
6917c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
6927c478bd9Sstevel@tonic-gate goto out;
69303986916Sjarrett } else if (!MANDLOCK(vp, va.va_mode) &&
69403986916Sjarrett (!is_system_labeled() || admin_low_client ||
69503986916Sjarrett dominant_label))
6967c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_READ;
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate if ((args->access & ACCESS3_LOOKUP) && vp->v_type == VDIR) {
699da6c28aaSamw error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
7007c478bd9Sstevel@tonic-gate if (error) {
7017c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
7027c478bd9Sstevel@tonic-gate goto out;
70303986916Sjarrett } else if (!is_system_labeled() || admin_low_client ||
70403986916Sjarrett dominant_label)
7057c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_LOOKUP;
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate if (checkwriteperm &&
7087c478bd9Sstevel@tonic-gate (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND))) {
709da6c28aaSamw error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
7107c478bd9Sstevel@tonic-gate if (error) {
7117c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
7127c478bd9Sstevel@tonic-gate goto out;
71303986916Sjarrett } else if (!MANDLOCK(vp, va.va_mode) &&
71403986916Sjarrett (!is_system_labeled() || admin_low_client || equal_label)) {
7157c478bd9Sstevel@tonic-gate resp->resok.access |=
7167c478bd9Sstevel@tonic-gate (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND));
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate if (checkwriteperm &&
7207c478bd9Sstevel@tonic-gate (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) {
721da6c28aaSamw error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
7227c478bd9Sstevel@tonic-gate if (error) {
7237c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
7247c478bd9Sstevel@tonic-gate goto out;
72503986916Sjarrett } else if (!is_system_labeled() || admin_low_client ||
72603986916Sjarrett equal_label)
7277c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_DELETE;
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate if (args->access & ACCESS3_EXECUTE) {
730da6c28aaSamw error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
7317c478bd9Sstevel@tonic-gate if (error) {
7327c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
7337c478bd9Sstevel@tonic-gate goto out;
73403986916Sjarrett } else if (!MANDLOCK(vp, va.va_mode) &&
73503986916Sjarrett (!is_system_labeled() || admin_low_client ||
73603986916Sjarrett dominant_label))
7377c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_EXECUTE;
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate
7407c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
7417c478bd9Sstevel@tonic-gate vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
7447c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
745e1adf50cSahl
7460dfe541eSEvan Layton DTRACE_NFSV3_5(op__access__done, struct svc_req *, req,
7470dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
7480dfe541eSEvan Layton ACCESS3res *, resp);
749e1adf50cSahl
750e1adf50cSahl VN_RELE(vp);
751e1adf50cSahl
7527c478bd9Sstevel@tonic-gate return;
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate out:
7557c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
7567c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
7577c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
7587c478bd9Sstevel@tonic-gate } else
7597c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
7600dfe541eSEvan Layton DTRACE_NFSV3_5(op__access__done, struct svc_req *, req,
7610dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
7620dfe541eSEvan Layton ACCESS3res *, resp);
7637c478bd9Sstevel@tonic-gate if (vp != NULL)
7647c478bd9Sstevel@tonic-gate VN_RELE(vp);
7657c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate
76827242a7cSthurlow void *
rfs3_access_getfh(ACCESS3args * args)7697c478bd9Sstevel@tonic-gate rfs3_access_getfh(ACCESS3args *args)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate
77227242a7cSthurlow return (&args->object);
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate /* ARGSUSED */
7767c478bd9Sstevel@tonic-gate void
rfs3_readlink(READLINK3args * args,READLINK3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)7777c478bd9Sstevel@tonic-gate rfs3_readlink(READLINK3args *args, READLINK3res *resp, struct exportinfo *exi,
7785cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
7797c478bd9Sstevel@tonic-gate {
7807c478bd9Sstevel@tonic-gate int error;
7817c478bd9Sstevel@tonic-gate vnode_t *vp;
7827c478bd9Sstevel@tonic-gate struct vattr *vap;
7837c478bd9Sstevel@tonic-gate struct vattr va;
7847c478bd9Sstevel@tonic-gate struct iovec iov;
7857c478bd9Sstevel@tonic-gate struct uio uio;
7867c478bd9Sstevel@tonic-gate char *data;
787b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
788b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
7892f172c55SRobert Thurlow int is_referral = 0;
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate vap = NULL;
7927c478bd9Sstevel@tonic-gate
7937c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->symlink, exi);
794e1adf50cSahl
7950dfe541eSEvan Layton DTRACE_NFSV3_5(op__readlink__start, struct svc_req *, req,
7960dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
7970dfe541eSEvan Layton READLINK3args *, args);
798e1adf50cSahl
7997c478bd9Sstevel@tonic-gate if (vp == NULL) {
8007c478bd9Sstevel@tonic-gate error = ESTALE;
8017c478bd9Sstevel@tonic-gate goto out;
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
805da6c28aaSamw error = VOP_GETATTR(vp, &va, 0, cr, NULL);
8067c478bd9Sstevel@tonic-gate if (error)
8077c478bd9Sstevel@tonic-gate goto out;
8087c478bd9Sstevel@tonic-gate
8097c478bd9Sstevel@tonic-gate vap = &va;
8107c478bd9Sstevel@tonic-gate
8112f172c55SRobert Thurlow /* We lied about the object type for a referral */
8122f172c55SRobert Thurlow if (vn_is_nfs_reparse(vp, cr))
8132f172c55SRobert Thurlow is_referral = 1;
8142f172c55SRobert Thurlow
8152f172c55SRobert Thurlow if (vp->v_type != VLNK && !is_referral) {
8167c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
8177c478bd9Sstevel@tonic-gate goto out1;
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate
8207c478bd9Sstevel@tonic-gate if (MANDLOCK(vp, va.va_mode)) {
8217c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
8227c478bd9Sstevel@tonic-gate goto out1;
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate
82503986916Sjarrett if (is_system_labeled()) {
82603986916Sjarrett bslabel_t *clabel = req->rq_label;
82703986916Sjarrett
82803986916Sjarrett ASSERT(clabel != NULL);
82903986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *,
83003986916Sjarrett "got client label from request(1)", struct svc_req *, req);
83103986916Sjarrett
83203986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
833bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
834bd6f1640SJarrett Lu exi)) {
83503986916Sjarrett resp->status = NFS3ERR_ACCES;
83603986916Sjarrett goto out1;
83703986916Sjarrett }
83803986916Sjarrett }
83903986916Sjarrett }
84003986916Sjarrett
8417c478bd9Sstevel@tonic-gate data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
8427c478bd9Sstevel@tonic-gate
8432f172c55SRobert Thurlow if (is_referral) {
8442f172c55SRobert Thurlow char *s;
8452f172c55SRobert Thurlow size_t strsz;
8460dfe541eSEvan Layton kstat_named_t *stat = exi->exi_ne->ne_globals->svstat[NFS_V3];
8472f172c55SRobert Thurlow
8482f172c55SRobert Thurlow /* Get an artificial symlink based on a referral */
8492f172c55SRobert Thurlow s = build_symlink(vp, cr, &strsz);
8500dfe541eSEvan Layton stat[NFS_REFERLINKS].value.ui64++;
8512f172c55SRobert Thurlow DTRACE_PROBE2(nfs3serv__func__referral__reflink,
8522f172c55SRobert Thurlow vnode_t *, vp, char *, s);
8532f172c55SRobert Thurlow if (s == NULL)
8542f172c55SRobert Thurlow error = EINVAL;
8552f172c55SRobert Thurlow else {
8562f172c55SRobert Thurlow error = 0;
8572f172c55SRobert Thurlow (void) strlcpy(data, s, MAXPATHLEN + 1);
8582f172c55SRobert Thurlow kmem_free(s, strsz);
8592f172c55SRobert Thurlow }
8607c478bd9Sstevel@tonic-gate
8612f172c55SRobert Thurlow } else {
8622f172c55SRobert Thurlow
8632f172c55SRobert Thurlow iov.iov_base = data;
8642f172c55SRobert Thurlow iov.iov_len = MAXPATHLEN;
8652f172c55SRobert Thurlow uio.uio_iov = &iov;
8662f172c55SRobert Thurlow uio.uio_iovcnt = 1;
8672f172c55SRobert Thurlow uio.uio_segflg = UIO_SYSSPACE;
8682f172c55SRobert Thurlow uio.uio_extflg = UIO_COPY_CACHED;
8692f172c55SRobert Thurlow uio.uio_loffset = 0;
8702f172c55SRobert Thurlow uio.uio_resid = MAXPATHLEN;
8712f172c55SRobert Thurlow
8722f172c55SRobert Thurlow error = VOP_READLINK(vp, &uio, cr, NULL);
8732f172c55SRobert Thurlow
8742f172c55SRobert Thurlow if (!error)
8752f172c55SRobert Thurlow *(data + MAXPATHLEN - uio.uio_resid) = '\0';
8762f172c55SRobert Thurlow }
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
879da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
88027246829SVitaliy Gusev
8812f172c55SRobert Thurlow /* Lie about object type again just to be consistent */
8822f172c55SRobert Thurlow if (is_referral && vap != NULL)
8832f172c55SRobert Thurlow vap->va_type = VLNK;
8847c478bd9Sstevel@tonic-gate
8857c478bd9Sstevel@tonic-gate #if 0 /* notyet */
8867c478bd9Sstevel@tonic-gate /*
8877c478bd9Sstevel@tonic-gate * Don't do this. It causes local disk writes when just
8887c478bd9Sstevel@tonic-gate * reading the file and the overhead is deemed larger
8897c478bd9Sstevel@tonic-gate * than the benefit.
8907c478bd9Sstevel@tonic-gate */
8917c478bd9Sstevel@tonic-gate /*
8927c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
8937c478bd9Sstevel@tonic-gate */
894da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
8957c478bd9Sstevel@tonic-gate #endif
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate if (error) {
8987c478bd9Sstevel@tonic-gate kmem_free(data, MAXPATHLEN + 1);
8997c478bd9Sstevel@tonic-gate goto out;
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate
902b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
903b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, data, NFSCMD_CONV_OUTBOUND,
904b89a8333Snatalie li - Sun Microsystems - Irvine United States MAXPATHLEN + 1);
905b89a8333Snatalie li - Sun Microsystems - Irvine United States
906b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
907b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
908b89a8333Snatalie li - Sun Microsystems - Irvine United States * Even though the conversion failed, we return
909b89a8333Snatalie li - Sun Microsystems - Irvine United States * something. We just don't translate it.
910b89a8333Snatalie li - Sun Microsystems - Irvine United States */
911b89a8333Snatalie li - Sun Microsystems - Irvine United States name = data;
912b89a8333Snatalie li - Sun Microsystems - Irvine United States }
913b89a8333Snatalie li - Sun Microsystems - Irvine United States
9147c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
9157c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.symlink_attributes);
916b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->resok.data = name;
917e1adf50cSahl
9180dfe541eSEvan Layton DTRACE_NFSV3_5(op__readlink__done, struct svc_req *, req,
9190dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
9200dfe541eSEvan Layton READLINK3res *, resp);
921e1adf50cSahl VN_RELE(vp);
922e1adf50cSahl
923b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != data)
924b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(data, MAXPATHLEN + 1);
925b89a8333Snatalie li - Sun Microsystems - Irvine United States
9267c478bd9Sstevel@tonic-gate return;
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate out:
9297c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
9307c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
9317c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
9327c478bd9Sstevel@tonic-gate } else
9337c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
9347c478bd9Sstevel@tonic-gate out1:
9350dfe541eSEvan Layton DTRACE_NFSV3_5(op__readlink__done, struct svc_req *, req,
9360dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
9370dfe541eSEvan Layton READLINK3res *, resp);
9387c478bd9Sstevel@tonic-gate if (vp != NULL)
9397c478bd9Sstevel@tonic-gate VN_RELE(vp);
9407c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes);
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate
94327242a7cSthurlow void *
rfs3_readlink_getfh(READLINK3args * args)9447c478bd9Sstevel@tonic-gate rfs3_readlink_getfh(READLINK3args *args)
9457c478bd9Sstevel@tonic-gate {
9467c478bd9Sstevel@tonic-gate
94727242a7cSthurlow return (&args->symlink);
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate void
rfs3_readlink_free(READLINK3res * resp)9517c478bd9Sstevel@tonic-gate rfs3_readlink_free(READLINK3res *resp)
9527c478bd9Sstevel@tonic-gate {
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK)
9557c478bd9Sstevel@tonic-gate kmem_free(resp->resok.data, MAXPATHLEN + 1);
9567c478bd9Sstevel@tonic-gate }
9577c478bd9Sstevel@tonic-gate
9580a701b1eSRobert Gordon /*
9590a701b1eSRobert Gordon * Server routine to handle read
9600a701b1eSRobert Gordon * May handle RDMA data as well as mblks
9610a701b1eSRobert Gordon */
9627c478bd9Sstevel@tonic-gate /* ARGSUSED */
9637c478bd9Sstevel@tonic-gate void
rfs3_read(READ3args * args,READ3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)9647c478bd9Sstevel@tonic-gate rfs3_read(READ3args *args, READ3res *resp, struct exportinfo *exi,
9655cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
9667c478bd9Sstevel@tonic-gate {
9677c478bd9Sstevel@tonic-gate int error;
9687c478bd9Sstevel@tonic-gate vnode_t *vp;
9697c478bd9Sstevel@tonic-gate struct vattr *vap;
9707c478bd9Sstevel@tonic-gate struct vattr va;
971e36d7b11SSebastien Roy struct iovec iov, *iovp = NULL;
972e36d7b11SSebastien Roy int iovcnt;
9737c478bd9Sstevel@tonic-gate struct uio uio;
9747c478bd9Sstevel@tonic-gate u_offset_t offset;
97541b8345aSchunli zhang - Sun Microsystems - Irvine United States mblk_t *mp = NULL;
9767c478bd9Sstevel@tonic-gate int in_crit = 0;
9777c478bd9Sstevel@tonic-gate int need_rwunlock = 0;
978cfae96c2Sjwahlig caller_context_t ct;
979c242f9a0Schunli zhang - Sun Microsystems - Irvine United States int rdma_used = 0;
980c242f9a0Schunli zhang - Sun Microsystems - Irvine United States int loaned_buffers;
981c242f9a0Schunli zhang - Sun Microsystems - Irvine United States struct uio *uiop;
9827c478bd9Sstevel@tonic-gate
9837c478bd9Sstevel@tonic-gate vap = NULL;
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
986e1adf50cSahl
9870dfe541eSEvan Layton DTRACE_NFSV3_5(op__read__start, struct svc_req *, req,
9880dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
9890dfe541eSEvan Layton READ3args *, args);
9900dfe541eSEvan Layton
991e1adf50cSahl
9927c478bd9Sstevel@tonic-gate if (vp == NULL) {
9937c478bd9Sstevel@tonic-gate error = ESTALE;
9947c478bd9Sstevel@tonic-gate goto out;
9957c478bd9Sstevel@tonic-gate }
9967c478bd9Sstevel@tonic-gate
99735bbd688SKaren Rochford if (args->wlist) {
99835bbd688SKaren Rochford if (args->count > clist_len(args->wlist)) {
99935bbd688SKaren Rochford error = EINVAL;
100035bbd688SKaren Rochford goto out;
100135bbd688SKaren Rochford }
1002c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rdma_used = 1;
100335bbd688SKaren Rochford }
1004c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1005c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* use loaned buffers for TCP */
1006c242f9a0Schunli zhang - Sun Microsystems - Irvine United States loaned_buffers = (nfs_loaned_buffers && !rdma_used) ? 1 : 0;
1007c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
100803986916Sjarrett if (is_system_labeled()) {
100903986916Sjarrett bslabel_t *clabel = req->rq_label;
101003986916Sjarrett
101103986916Sjarrett ASSERT(clabel != NULL);
101203986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opread__clabel, char *,
101303986916Sjarrett "got client label from request(1)", struct svc_req *, req);
101403986916Sjarrett
101503986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
1016bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
1017bd6f1640SJarrett Lu exi)) {
101803986916Sjarrett resp->status = NFS3ERR_ACCES;
101903986916Sjarrett goto out1;
102003986916Sjarrett }
102103986916Sjarrett }
102203986916Sjarrett }
102303986916Sjarrett
1024cfae96c2Sjwahlig ct.cc_sysid = 0;
1025cfae96c2Sjwahlig ct.cc_pid = 0;
1026cfae96c2Sjwahlig ct.cc_caller_id = nfs3_srv_caller_id;
1027cfae96c2Sjwahlig ct.cc_flags = CC_DONTBLOCK;
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate /*
10307c478bd9Sstevel@tonic-gate * Enter the critical region before calling VOP_RWLOCK
10317c478bd9Sstevel@tonic-gate * to avoid a deadlock with write requests.
10327c478bd9Sstevel@tonic-gate */
10337c478bd9Sstevel@tonic-gate if (nbl_need_check(vp)) {
10347c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_READER);
10357c478bd9Sstevel@tonic-gate in_crit = 1;
1036da6c28aaSamw if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
1037da6c28aaSamw NULL)) {
10387c478bd9Sstevel@tonic-gate error = EACCES;
10397c478bd9Sstevel@tonic-gate goto out;
10407c478bd9Sstevel@tonic-gate }
10417c478bd9Sstevel@tonic-gate }
10427c478bd9Sstevel@tonic-gate
1043cfae96c2Sjwahlig error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct);
1044cfae96c2Sjwahlig
1045cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
1046cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1047cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
1048cfae96c2Sjwahlig goto out1;
1049cfae96c2Sjwahlig }
1050cfae96c2Sjwahlig
10517c478bd9Sstevel@tonic-gate need_rwunlock = 1;
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1054cfae96c2Sjwahlig error = VOP_GETATTR(vp, &va, 0, cr, &ct);
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate /*
10577c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
10587c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
10597c478bd9Sstevel@tonic-gate */
10607c478bd9Sstevel@tonic-gate if (error)
10617c478bd9Sstevel@tonic-gate goto out;
10627c478bd9Sstevel@tonic-gate
10637c478bd9Sstevel@tonic-gate vap = &va;
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) {
10667c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
10677c478bd9Sstevel@tonic-gate goto out1;
10687c478bd9Sstevel@tonic-gate }
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate if (crgetuid(cr) != va.va_uid) {
1071cfae96c2Sjwahlig error = VOP_ACCESS(vp, VREAD, 0, cr, &ct);
10727c478bd9Sstevel@tonic-gate if (error) {
10737c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
10747c478bd9Sstevel@tonic-gate goto out;
1075cfae96c2Sjwahlig error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct);
10767c478bd9Sstevel@tonic-gate if (error)
10777c478bd9Sstevel@tonic-gate goto out;
10787c478bd9Sstevel@tonic-gate }
10797c478bd9Sstevel@tonic-gate }
10807c478bd9Sstevel@tonic-gate
10817c478bd9Sstevel@tonic-gate if (MANDLOCK(vp, va.va_mode)) {
10827c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
10837c478bd9Sstevel@tonic-gate goto out1;
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate offset = args->offset;
10877c478bd9Sstevel@tonic-gate if (offset >= va.va_size) {
1088cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
10897c478bd9Sstevel@tonic-gate if (in_crit)
10907c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
10917c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
10927c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
10937c478bd9Sstevel@tonic-gate resp->resok.count = 0;
10947c478bd9Sstevel@tonic-gate resp->resok.eof = TRUE;
10957c478bd9Sstevel@tonic-gate resp->resok.data.data_len = 0;
10967c478bd9Sstevel@tonic-gate resp->resok.data.data_val = NULL;
10977c478bd9Sstevel@tonic-gate resp->resok.data.mp = NULL;
10980a701b1eSRobert Gordon /* RDMA */
10990a701b1eSRobert Gordon resp->resok.wlist = args->wlist;
11000a701b1eSRobert Gordon resp->resok.wlist_len = resp->resok.count;
1101f837ee4aSSiddheshwar Mahesh if (resp->resok.wlist)
1102f837ee4aSSiddheshwar Mahesh clist_zero_len(resp->resok.wlist);
1103e1adf50cSahl goto done;
11047c478bd9Sstevel@tonic-gate }
11057c478bd9Sstevel@tonic-gate
11067c478bd9Sstevel@tonic-gate if (args->count == 0) {
1107cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
11087c478bd9Sstevel@tonic-gate if (in_crit)
11097c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
11107c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
11117c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
11127c478bd9Sstevel@tonic-gate resp->resok.count = 0;
11137c478bd9Sstevel@tonic-gate resp->resok.eof = FALSE;
11147c478bd9Sstevel@tonic-gate resp->resok.data.data_len = 0;
11157c478bd9Sstevel@tonic-gate resp->resok.data.data_val = NULL;
11167c478bd9Sstevel@tonic-gate resp->resok.data.mp = NULL;
11170a701b1eSRobert Gordon /* RDMA */
11180a701b1eSRobert Gordon resp->resok.wlist = args->wlist;
11190a701b1eSRobert Gordon resp->resok.wlist_len = resp->resok.count;
1120f837ee4aSSiddheshwar Mahesh if (resp->resok.wlist)
1121f837ee4aSSiddheshwar Mahesh clist_zero_len(resp->resok.wlist);
1122e1adf50cSahl goto done;
11237c478bd9Sstevel@tonic-gate }
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate /*
11267c478bd9Sstevel@tonic-gate * do not allocate memory more the max. allowed
11277c478bd9Sstevel@tonic-gate * transfer size
11287c478bd9Sstevel@tonic-gate */
11297c478bd9Sstevel@tonic-gate if (args->count > rfs3_tsize(req))
11307c478bd9Sstevel@tonic-gate args->count = rfs3_tsize(req);
11317c478bd9Sstevel@tonic-gate
1132c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (loaned_buffers) {
1133c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop = (uio_t *)rfs_setup_xuio(vp);
1134c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(uiop != NULL);
1135c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_segflg = UIO_SYSSPACE;
1136c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_loffset = args->offset;
1137c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_resid = args->count;
1138c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1139c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* Jump to do the read if successful */
1140c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (VOP_REQZCBUF(vp, UIO_READ, (xuio_t *)uiop, cr, &ct) == 0) {
1141c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /*
1142c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * Need to hold the vnode until after VOP_RETZCBUF()
1143c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * is called.
1144c242f9a0Schunli zhang - Sun Microsystems - Irvine United States */
1145c242f9a0Schunli zhang - Sun Microsystems - Irvine United States VN_HOLD(vp);
1146c242f9a0Schunli zhang - Sun Microsystems - Irvine United States goto doio_read;
1147c242f9a0Schunli zhang - Sun Microsystems - Irvine United States }
1148c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1149c242f9a0Schunli zhang - Sun Microsystems - Irvine United States DTRACE_PROBE2(nfss__i__reqzcbuf_failed, int,
1150c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_loffset, int, uiop->uio_resid);
1151c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1152c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_extflg = 0;
1153c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* failure to setup for zero copy */
1154c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rfs_free_xuio((void *)uiop);
1155c242f9a0Schunli zhang - Sun Microsystems - Irvine United States loaned_buffers = 0;
1156c242f9a0Schunli zhang - Sun Microsystems - Irvine United States }
1157c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
11587c478bd9Sstevel@tonic-gate /*
11590a701b1eSRobert Gordon * If returning data via RDMA Write, then grab the chunk list.
11600a701b1eSRobert Gordon * If we aren't returning READ data w/RDMA_WRITE, then grab
11610a701b1eSRobert Gordon * a mblk.
11627c478bd9Sstevel@tonic-gate */
1163c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (rdma_used) {
11640a701b1eSRobert Gordon (void) rdma_get_wchunk(req, &iov, args->wlist);
1165e36d7b11SSebastien Roy uio.uio_iov = &iov;
1166e36d7b11SSebastien Roy uio.uio_iovcnt = 1;
11670a701b1eSRobert Gordon } else {
11680a701b1eSRobert Gordon /*
11690a701b1eSRobert Gordon * mp will contain the data to be sent out in the read reply.
1170e36d7b11SSebastien Roy * For UDP, this will be freed after the reply has been sent
1171e36d7b11SSebastien Roy * out by the driver. For TCP, it will be freed after the last
1172e36d7b11SSebastien Roy * segment associated with the reply has been ACKed by the
1173e36d7b11SSebastien Roy * client.
11740a701b1eSRobert Gordon */
1175e36d7b11SSebastien Roy mp = rfs_read_alloc(args->count, &iovp, &iovcnt);
1176e36d7b11SSebastien Roy uio.uio_iov = iovp;
1177e36d7b11SSebastien Roy uio.uio_iovcnt = iovcnt;
11780a701b1eSRobert Gordon }
11797c478bd9Sstevel@tonic-gate
11807c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
11817c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
11827c478bd9Sstevel@tonic-gate uio.uio_loffset = args->offset;
11837c478bd9Sstevel@tonic-gate uio.uio_resid = args->count;
1184c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop = &uio;
11857c478bd9Sstevel@tonic-gate
1186c242f9a0Schunli zhang - Sun Microsystems - Irvine United States doio_read:
1187c242f9a0Schunli zhang - Sun Microsystems - Irvine United States error = VOP_READ(vp, uiop, 0, cr, &ct);
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate if (error) {
1190c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (mp)
1191c242f9a0Schunli zhang - Sun Microsystems - Irvine United States freemsg(mp);
1192cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
1193cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1194cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
1195cfae96c2Sjwahlig goto out1;
1196cfae96c2Sjwahlig }
11977c478bd9Sstevel@tonic-gate goto out;
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate
1200c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* make mblk using zc buffers */
1201c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (loaned_buffers) {
1202c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp = uio_to_mblk(uiop);
1203c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(mp != NULL);
1204c242f9a0Schunli zhang - Sun Microsystems - Irvine United States }
1205c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
12067c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1207cfae96c2Sjwahlig error = VOP_GETATTR(vp, &va, 0, cr, &ct);
12087c478bd9Sstevel@tonic-gate
12097c478bd9Sstevel@tonic-gate if (error)
12107c478bd9Sstevel@tonic-gate vap = NULL;
12117c478bd9Sstevel@tonic-gate else
12127c478bd9Sstevel@tonic-gate vap = &va;
12137c478bd9Sstevel@tonic-gate
1214cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gate if (in_crit)
12177c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
12207c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1221c242f9a0Schunli zhang - Sun Microsystems - Irvine United States resp->resok.count = args->count - uiop->uio_resid;
12227c478bd9Sstevel@tonic-gate if (!error && offset + resp->resok.count == va.va_size)
12237c478bd9Sstevel@tonic-gate resp->resok.eof = TRUE;
12247c478bd9Sstevel@tonic-gate else
12257c478bd9Sstevel@tonic-gate resp->resok.eof = FALSE;
12267c478bd9Sstevel@tonic-gate resp->resok.data.data_len = resp->resok.count;
1227c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1228c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (mp)
1229c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rfs_rndup_mblks(mp, resp->resok.count, loaned_buffers);
1230c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
12317c478bd9Sstevel@tonic-gate resp->resok.data.mp = mp;
12327c478bd9Sstevel@tonic-gate resp->resok.size = (uint_t)args->count;
1233e1adf50cSahl
1234c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (rdma_used) {
12350a701b1eSRobert Gordon resp->resok.data.data_val = (caddr_t)iov.iov_base;
12360a701b1eSRobert Gordon if (!rdma_setup_read_data3(args, &(resp->resok))) {
12370a701b1eSRobert Gordon resp->status = NFS3ERR_INVAL;
12380a701b1eSRobert Gordon }
12390a701b1eSRobert Gordon } else {
12400a701b1eSRobert Gordon resp->resok.data.data_val = (caddr_t)mp->b_datap->db_base;
12410a701b1eSRobert Gordon (resp->resok).wlist = NULL;
12420a701b1eSRobert Gordon }
12430a701b1eSRobert Gordon
1244e1adf50cSahl done:
12450dfe541eSEvan Layton DTRACE_NFSV3_5(op__read__done, struct svc_req *, req,
12460dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
12470dfe541eSEvan Layton READ3res *, resp);
1248e1adf50cSahl
1249e1adf50cSahl VN_RELE(vp);
1250e1adf50cSahl
1251e36d7b11SSebastien Roy if (iovp != NULL)
1252e36d7b11SSebastien Roy kmem_free(iovp, iovcnt * sizeof (struct iovec));
1253e36d7b11SSebastien Roy
12547c478bd9Sstevel@tonic-gate return;
12557c478bd9Sstevel@tonic-gate
12567c478bd9Sstevel@tonic-gate out:
12577c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
12587c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
12597c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
12607c478bd9Sstevel@tonic-gate } else
12617c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
12627c478bd9Sstevel@tonic-gate out1:
12630dfe541eSEvan Layton DTRACE_NFSV3_5(op__read__done, struct svc_req *, req,
12640dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
12650dfe541eSEvan Layton READ3res *, resp);
1266e1adf50cSahl
12677c478bd9Sstevel@tonic-gate if (vp != NULL) {
12687c478bd9Sstevel@tonic-gate if (need_rwunlock)
1269cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
12707c478bd9Sstevel@tonic-gate if (in_crit)
12717c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
12727c478bd9Sstevel@tonic-gate VN_RELE(vp);
12737c478bd9Sstevel@tonic-gate }
12747c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
1275e36d7b11SSebastien Roy
1276e36d7b11SSebastien Roy if (iovp != NULL)
1277e36d7b11SSebastien Roy kmem_free(iovp, iovcnt * sizeof (struct iovec));
12787c478bd9Sstevel@tonic-gate }
12797c478bd9Sstevel@tonic-gate
12807c478bd9Sstevel@tonic-gate void
rfs3_read_free(READ3res * resp)12817c478bd9Sstevel@tonic-gate rfs3_read_free(READ3res *resp)
12827c478bd9Sstevel@tonic-gate {
12837c478bd9Sstevel@tonic-gate mblk_t *mp;
12847c478bd9Sstevel@tonic-gate
12857c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK) {
12867c478bd9Sstevel@tonic-gate mp = resp->resok.data.mp;
12877c478bd9Sstevel@tonic-gate if (mp != NULL)
1288c242f9a0Schunli zhang - Sun Microsystems - Irvine United States freemsg(mp);
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate }
12917c478bd9Sstevel@tonic-gate
129227242a7cSthurlow void *
rfs3_read_getfh(READ3args * args)12937c478bd9Sstevel@tonic-gate rfs3_read_getfh(READ3args *args)
12947c478bd9Sstevel@tonic-gate {
12957c478bd9Sstevel@tonic-gate
129627242a7cSthurlow return (&args->file);
12977c478bd9Sstevel@tonic-gate }
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate #define MAX_IOVECS 12
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate #ifdef DEBUG
13027c478bd9Sstevel@tonic-gate static int rfs3_write_hits = 0;
13037c478bd9Sstevel@tonic-gate static int rfs3_write_misses = 0;
13047c478bd9Sstevel@tonic-gate #endif
13057c478bd9Sstevel@tonic-gate
13067c478bd9Sstevel@tonic-gate void
rfs3_write(WRITE3args * args,WRITE3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)13077c478bd9Sstevel@tonic-gate rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi,
13085cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
13097c478bd9Sstevel@tonic-gate {
13100dfe541eSEvan Layton nfs3_srv_t *ns;
13117c478bd9Sstevel@tonic-gate int error;
13127c478bd9Sstevel@tonic-gate vnode_t *vp;
13137c478bd9Sstevel@tonic-gate struct vattr *bvap = NULL;
13147c478bd9Sstevel@tonic-gate struct vattr bva;
13157c478bd9Sstevel@tonic-gate struct vattr *avap = NULL;
13167c478bd9Sstevel@tonic-gate struct vattr ava;
13177c478bd9Sstevel@tonic-gate u_offset_t rlimit;
13187c478bd9Sstevel@tonic-gate struct uio uio;
13197c478bd9Sstevel@tonic-gate struct iovec iov[MAX_IOVECS];
13207c478bd9Sstevel@tonic-gate mblk_t *m;
13217c478bd9Sstevel@tonic-gate struct iovec *iovp;
13227c478bd9Sstevel@tonic-gate int iovcnt;
13237c478bd9Sstevel@tonic-gate int ioflag;
13247c478bd9Sstevel@tonic-gate cred_t *savecred;
13257c478bd9Sstevel@tonic-gate int in_crit = 0;
13267c478bd9Sstevel@tonic-gate int rwlock_ret = -1;
1327cfae96c2Sjwahlig caller_context_t ct;
13287c478bd9Sstevel@tonic-gate
13297c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
1330e1adf50cSahl
13310dfe541eSEvan Layton DTRACE_NFSV3_5(op__write__start, struct svc_req *, req,
13320dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
13330dfe541eSEvan Layton WRITE3args *, args);
1334e1adf50cSahl
13357c478bd9Sstevel@tonic-gate if (vp == NULL) {
13367c478bd9Sstevel@tonic-gate error = ESTALE;
1337e1adf50cSahl goto err;
13387c478bd9Sstevel@tonic-gate }
13397c478bd9Sstevel@tonic-gate
13400dfe541eSEvan Layton ASSERT3U(curzone->zone_id, ==, exi->exi_zoneid); /* exi is non-NULL. */
13410dfe541eSEvan Layton ns = nfs3_get_srv();
13420dfe541eSEvan Layton
134303986916Sjarrett if (is_system_labeled()) {
134403986916Sjarrett bslabel_t *clabel = req->rq_label;
134503986916Sjarrett
134603986916Sjarrett ASSERT(clabel != NULL);
134703986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
134803986916Sjarrett "got client label from request(1)", struct svc_req *, req);
134903986916Sjarrett
135003986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
1351bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1352bd6f1640SJarrett Lu exi)) {
135303986916Sjarrett resp->status = NFS3ERR_ACCES;
1354e1adf50cSahl goto err1;
135503986916Sjarrett }
135603986916Sjarrett }
135703986916Sjarrett }
135803986916Sjarrett
1359cfae96c2Sjwahlig ct.cc_sysid = 0;
1360cfae96c2Sjwahlig ct.cc_pid = 0;
1361cfae96c2Sjwahlig ct.cc_caller_id = nfs3_srv_caller_id;
1362cfae96c2Sjwahlig ct.cc_flags = CC_DONTBLOCK;
13637c478bd9Sstevel@tonic-gate
13647c478bd9Sstevel@tonic-gate /*
13657c478bd9Sstevel@tonic-gate * We have to enter the critical region before calling VOP_RWLOCK
13667c478bd9Sstevel@tonic-gate * to avoid a deadlock with ufs.
13677c478bd9Sstevel@tonic-gate */
13687c478bd9Sstevel@tonic-gate if (nbl_need_check(vp)) {
13697c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_READER);
13707c478bd9Sstevel@tonic-gate in_crit = 1;
1371da6c28aaSamw if (nbl_conflict(vp, NBL_WRITE, args->offset, args->count, 0,
1372da6c28aaSamw NULL)) {
13737c478bd9Sstevel@tonic-gate error = EACCES;
1374e1adf50cSahl goto err;
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate
1378cfae96c2Sjwahlig rwlock_ret = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct);
1379cfae96c2Sjwahlig
1380cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
1381cfae96c2Sjwahlig if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1382cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
1383cfae96c2Sjwahlig rwlock_ret = -1;
1384e1adf50cSahl goto err1;
1385cfae96c2Sjwahlig }
1386cfae96c2Sjwahlig
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
1389cfae96c2Sjwahlig error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
13907c478bd9Sstevel@tonic-gate
13917c478bd9Sstevel@tonic-gate /*
13927c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
13937c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
13947c478bd9Sstevel@tonic-gate */
13957c478bd9Sstevel@tonic-gate if (error)
1396e1adf50cSahl goto err;
13977c478bd9Sstevel@tonic-gate
13987c478bd9Sstevel@tonic-gate bvap = &bva;
13997c478bd9Sstevel@tonic-gate avap = bvap;
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate if (args->count != args->data.data_len) {
14027c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
1403e1adf50cSahl goto err1;
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate
14065cb0d679SMarcel Telka if (rdonly(ro, vp)) {
14077c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
1408e1adf50cSahl goto err1;
14097c478bd9Sstevel@tonic-gate }
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) {
14127c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
1413e1adf50cSahl goto err1;
14147c478bd9Sstevel@tonic-gate }
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate if (crgetuid(cr) != bva.va_uid &&
1417cfae96c2Sjwahlig (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
1418e1adf50cSahl goto err;
14197c478bd9Sstevel@tonic-gate
14207c478bd9Sstevel@tonic-gate if (MANDLOCK(vp, bva.va_mode)) {
14217c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
1422e1adf50cSahl goto err1;
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate if (args->count == 0) {
14267c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
14277c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
14287c478bd9Sstevel@tonic-gate resp->resok.count = 0;
14297c478bd9Sstevel@tonic-gate resp->resok.committed = args->stable;
14300dfe541eSEvan Layton resp->resok.verf = ns->write3verf;
1431e1adf50cSahl goto out;
14327c478bd9Sstevel@tonic-gate }
14337c478bd9Sstevel@tonic-gate
14347c478bd9Sstevel@tonic-gate if (args->mblk != NULL) {
14357c478bd9Sstevel@tonic-gate iovcnt = 0;
14367c478bd9Sstevel@tonic-gate for (m = args->mblk; m != NULL; m = m->b_cont)
14377c478bd9Sstevel@tonic-gate iovcnt++;
14387c478bd9Sstevel@tonic-gate if (iovcnt <= MAX_IOVECS) {
14397c478bd9Sstevel@tonic-gate #ifdef DEBUG
14407c478bd9Sstevel@tonic-gate rfs3_write_hits++;
14417c478bd9Sstevel@tonic-gate #endif
14427c478bd9Sstevel@tonic-gate iovp = iov;
14437c478bd9Sstevel@tonic-gate } else {
14447c478bd9Sstevel@tonic-gate #ifdef DEBUG
14457c478bd9Sstevel@tonic-gate rfs3_write_misses++;
14467c478bd9Sstevel@tonic-gate #endif
14477c478bd9Sstevel@tonic-gate iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP);
14487c478bd9Sstevel@tonic-gate }
14497c478bd9Sstevel@tonic-gate mblk_to_iov(args->mblk, iovcnt, iovp);
14500a701b1eSRobert Gordon
14510a701b1eSRobert Gordon } else if (args->rlist != NULL) {
14520a701b1eSRobert Gordon iovcnt = 1;
14530a701b1eSRobert Gordon iovp = iov;
14540a701b1eSRobert Gordon iovp->iov_base = (char *)((args->rlist)->u.c_daddr3);
14550a701b1eSRobert Gordon iovp->iov_len = args->count;
14567c478bd9Sstevel@tonic-gate } else {
14577c478bd9Sstevel@tonic-gate iovcnt = 1;
14587c478bd9Sstevel@tonic-gate iovp = iov;
14597c478bd9Sstevel@tonic-gate iovp->iov_base = args->data.data_val;
14607c478bd9Sstevel@tonic-gate iovp->iov_len = args->count;
14617c478bd9Sstevel@tonic-gate }
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate uio.uio_iov = iovp;
14647c478bd9Sstevel@tonic-gate uio.uio_iovcnt = iovcnt;
14657c478bd9Sstevel@tonic-gate
14667c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
14677c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_DEFAULT;
14687c478bd9Sstevel@tonic-gate uio.uio_loffset = args->offset;
14697c478bd9Sstevel@tonic-gate uio.uio_resid = args->count;
14707c478bd9Sstevel@tonic-gate uio.uio_llimit = curproc->p_fsz_ctl;
14717c478bd9Sstevel@tonic-gate rlimit = uio.uio_llimit - args->offset;
14727c478bd9Sstevel@tonic-gate if (rlimit < (u_offset_t)uio.uio_resid)
14737c478bd9Sstevel@tonic-gate uio.uio_resid = (int)rlimit;
14747c478bd9Sstevel@tonic-gate
14757c478bd9Sstevel@tonic-gate if (args->stable == UNSTABLE)
14767c478bd9Sstevel@tonic-gate ioflag = 0;
14777c478bd9Sstevel@tonic-gate else if (args->stable == FILE_SYNC)
14787c478bd9Sstevel@tonic-gate ioflag = FSYNC;
14797c478bd9Sstevel@tonic-gate else if (args->stable == DATA_SYNC)
14807c478bd9Sstevel@tonic-gate ioflag = FDSYNC;
14817c478bd9Sstevel@tonic-gate else {
14827c478bd9Sstevel@tonic-gate if (iovp != iov)
14837c478bd9Sstevel@tonic-gate kmem_free(iovp, sizeof (*iovp) * iovcnt);
14847c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
1485e1adf50cSahl goto err1;
14867c478bd9Sstevel@tonic-gate }
14877c478bd9Sstevel@tonic-gate
14887c478bd9Sstevel@tonic-gate /*
14897c478bd9Sstevel@tonic-gate * We're changing creds because VM may fault and we need
14907c478bd9Sstevel@tonic-gate * the cred of the current thread to be used if quota
14917c478bd9Sstevel@tonic-gate * checking is enabled.
14927c478bd9Sstevel@tonic-gate */
14937c478bd9Sstevel@tonic-gate savecred = curthread->t_cred;
14947c478bd9Sstevel@tonic-gate curthread->t_cred = cr;
1495cfae96c2Sjwahlig error = VOP_WRITE(vp, &uio, ioflag, cr, &ct);
14967c478bd9Sstevel@tonic-gate curthread->t_cred = savecred;
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate if (iovp != iov)
14997c478bd9Sstevel@tonic-gate kmem_free(iovp, sizeof (*iovp) * iovcnt);
15007c478bd9Sstevel@tonic-gate
1501cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
1502cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1503cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
1504e1adf50cSahl goto err1;
1505cfae96c2Sjwahlig }
1506cfae96c2Sjwahlig
15077c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
1508cfae96c2Sjwahlig avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava;
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate if (error)
1511e1adf50cSahl goto err;
15127c478bd9Sstevel@tonic-gate
15137c478bd9Sstevel@tonic-gate /*
15147c478bd9Sstevel@tonic-gate * If we were unable to get the V_WRITELOCK_TRUE, then we
15157c478bd9Sstevel@tonic-gate * may not have accurate after attrs, so check if
15167c478bd9Sstevel@tonic-gate * we have both attributes, they have a non-zero va_seq, and
15177c478bd9Sstevel@tonic-gate * va_seq has changed by exactly one,
15187c478bd9Sstevel@tonic-gate * if not, turn off the before attr.
15197c478bd9Sstevel@tonic-gate */
15207c478bd9Sstevel@tonic-gate if (rwlock_ret != V_WRITELOCK_TRUE) {
15217c478bd9Sstevel@tonic-gate if (bvap == NULL || avap == NULL ||
1522cfae96c2Sjwahlig bvap->va_seq == 0 || avap->va_seq == 0 ||
1523cfae96c2Sjwahlig avap->va_seq != (bvap->va_seq + 1)) {
15247c478bd9Sstevel@tonic-gate bvap = NULL;
15257c478bd9Sstevel@tonic-gate }
15267c478bd9Sstevel@tonic-gate }
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
15297c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
15307c478bd9Sstevel@tonic-gate resp->resok.count = args->count - uio.uio_resid;
15317c478bd9Sstevel@tonic-gate resp->resok.committed = args->stable;
15320dfe541eSEvan Layton resp->resok.verf = ns->write3verf;
1533e1adf50cSahl goto out;
15347c478bd9Sstevel@tonic-gate
1535e1adf50cSahl err:
15367c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
15377c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
15387c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
15397c478bd9Sstevel@tonic-gate } else
15407c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
1541e1adf50cSahl err1:
1542e1adf50cSahl vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
1543e1adf50cSahl out:
15440dfe541eSEvan Layton DTRACE_NFSV3_5(op__write__done, struct svc_req *, req,
15450dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
15460dfe541eSEvan Layton WRITE3res *, resp);
1547e1adf50cSahl
15487c478bd9Sstevel@tonic-gate if (vp != NULL) {
15497c478bd9Sstevel@tonic-gate if (rwlock_ret != -1)
1550cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
15517c478bd9Sstevel@tonic-gate if (in_crit)
15527c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
15537c478bd9Sstevel@tonic-gate VN_RELE(vp);
15547c478bd9Sstevel@tonic-gate }
15557c478bd9Sstevel@tonic-gate }
15567c478bd9Sstevel@tonic-gate
155727242a7cSthurlow void *
rfs3_write_getfh(WRITE3args * args)15587c478bd9Sstevel@tonic-gate rfs3_write_getfh(WRITE3args *args)
15597c478bd9Sstevel@tonic-gate {
15607c478bd9Sstevel@tonic-gate
156127242a7cSthurlow return (&args->file);
15627c478bd9Sstevel@tonic-gate }
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate void
rfs3_create(CREATE3args * args,CREATE3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)15657c478bd9Sstevel@tonic-gate rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi,
15665cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
15677c478bd9Sstevel@tonic-gate {
15687c478bd9Sstevel@tonic-gate int error;
15697c478bd9Sstevel@tonic-gate int in_crit = 0;
15707c478bd9Sstevel@tonic-gate vnode_t *vp;
15717c478bd9Sstevel@tonic-gate vnode_t *tvp = NULL;
15727c478bd9Sstevel@tonic-gate vnode_t *dvp;
15737c478bd9Sstevel@tonic-gate struct vattr *vap;
15747c478bd9Sstevel@tonic-gate struct vattr va;
15757c478bd9Sstevel@tonic-gate struct vattr *dbvap;
15767c478bd9Sstevel@tonic-gate struct vattr dbva;
15777c478bd9Sstevel@tonic-gate struct vattr *davap;
15787c478bd9Sstevel@tonic-gate struct vattr dava;
15797c478bd9Sstevel@tonic-gate enum vcexcl excl;
15807c478bd9Sstevel@tonic-gate nfstime3 *mtime;
15817c478bd9Sstevel@tonic-gate len_t reqsize;
15827c478bd9Sstevel@tonic-gate bool_t trunc;
1583b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
1584b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate dbvap = NULL;
15877c478bd9Sstevel@tonic-gate davap = NULL;
15887c478bd9Sstevel@tonic-gate
158927242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
1590e1adf50cSahl
15910dfe541eSEvan Layton DTRACE_NFSV3_5(op__create__start, struct svc_req *, req,
15920dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
15930dfe541eSEvan Layton CREATE3args *, args);
1594e1adf50cSahl
15957c478bd9Sstevel@tonic-gate if (dvp == NULL) {
15967c478bd9Sstevel@tonic-gate error = ESTALE;
15977c478bd9Sstevel@tonic-gate goto out;
15987c478bd9Sstevel@tonic-gate }
15997c478bd9Sstevel@tonic-gate
16007c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
1601da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
16027c478bd9Sstevel@tonic-gate davap = dbvap;
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
16057c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
16067c478bd9Sstevel@tonic-gate goto out1;
16077c478bd9Sstevel@tonic-gate }
16087c478bd9Sstevel@tonic-gate
16097c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
16107c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
16117c478bd9Sstevel@tonic-gate goto out1;
16127c478bd9Sstevel@tonic-gate }
16137c478bd9Sstevel@tonic-gate
16145cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
16157c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
16167c478bd9Sstevel@tonic-gate goto out1;
16177c478bd9Sstevel@tonic-gate }
16187c478bd9Sstevel@tonic-gate
161903986916Sjarrett if (is_system_labeled()) {
162003986916Sjarrett bslabel_t *clabel = req->rq_label;
162103986916Sjarrett
162203986916Sjarrett ASSERT(clabel != NULL);
162303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opcreate__clabel, char *,
162403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
162503986916Sjarrett
162603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
1627bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
1628bd6f1640SJarrett Lu exi)) {
162903986916Sjarrett resp->status = NFS3ERR_ACCES;
163003986916Sjarrett goto out1;
163103986916Sjarrett }
163203986916Sjarrett }
163303986916Sjarrett }
163403986916Sjarrett
1635b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1636b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
1637b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1638b89a8333Snatalie li - Sun Microsystems - Irvine United States
1639b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
1640b89a8333Snatalie li - Sun Microsystems - Irvine United States /* This is really a Solaris EILSEQ */
1641b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
1642b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
1643b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1644b89a8333Snatalie li - Sun Microsystems - Irvine United States
16457c478bd9Sstevel@tonic-gate if (args->how.mode == EXCLUSIVE) {
16467c478bd9Sstevel@tonic-gate va.va_mask = AT_TYPE | AT_MODE | AT_MTIME;
16477c478bd9Sstevel@tonic-gate va.va_type = VREG;
16487c478bd9Sstevel@tonic-gate va.va_mode = (mode_t)0;
16497c478bd9Sstevel@tonic-gate /*
16507c478bd9Sstevel@tonic-gate * Ensure no time overflows and that types match
16517c478bd9Sstevel@tonic-gate */
16527c478bd9Sstevel@tonic-gate mtime = (nfstime3 *)&args->how.createhow3_u.verf;
16537c478bd9Sstevel@tonic-gate va.va_mtime.tv_sec = mtime->seconds % INT32_MAX;
16547c478bd9Sstevel@tonic-gate va.va_mtime.tv_nsec = mtime->nseconds;
16557c478bd9Sstevel@tonic-gate excl = EXCL;
16567c478bd9Sstevel@tonic-gate } else {
16577c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->how.createhow3_u.obj_attributes,
16587c478bd9Sstevel@tonic-gate &va);
16597c478bd9Sstevel@tonic-gate if (error)
16607c478bd9Sstevel@tonic-gate goto out;
16617c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
16627c478bd9Sstevel@tonic-gate va.va_type = VREG;
16637c478bd9Sstevel@tonic-gate if (args->how.mode == GUARDED)
16647c478bd9Sstevel@tonic-gate excl = EXCL;
16657c478bd9Sstevel@tonic-gate else {
16667c478bd9Sstevel@tonic-gate excl = NONEXCL;
16677c478bd9Sstevel@tonic-gate
16687c478bd9Sstevel@tonic-gate /*
16697c478bd9Sstevel@tonic-gate * During creation of file in non-exclusive mode
16707c478bd9Sstevel@tonic-gate * if size of file is being set then make sure
16717c478bd9Sstevel@tonic-gate * that if the file already exists that no conflicting
16727c478bd9Sstevel@tonic-gate * non-blocking mandatory locks exists in the region
16737c478bd9Sstevel@tonic-gate * being modified. If there are conflicting locks fail
16747c478bd9Sstevel@tonic-gate * the operation with EACCES.
16757c478bd9Sstevel@tonic-gate */
16767c478bd9Sstevel@tonic-gate if (va.va_mask & AT_SIZE) {
16777c478bd9Sstevel@tonic-gate struct vattr tva;
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate /*
16807c478bd9Sstevel@tonic-gate * Does file already exist?
16817c478bd9Sstevel@tonic-gate */
1682b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &tvp,
1683cfae96c2Sjwahlig NULL, 0, NULL, cr, NULL, NULL, NULL);
16847c478bd9Sstevel@tonic-gate
16857c478bd9Sstevel@tonic-gate /*
16867c478bd9Sstevel@tonic-gate * Check to see if the file has been delegated
16877c478bd9Sstevel@tonic-gate * to a v4 client. If so, then begin recall of
16887c478bd9Sstevel@tonic-gate * the delegation and return JUKEBOX to allow
16897c478bd9Sstevel@tonic-gate * the client to retrasmit its request.
16907c478bd9Sstevel@tonic-gate */
16917c478bd9Sstevel@tonic-gate
16927c478bd9Sstevel@tonic-gate trunc = va.va_size == 0;
16937c478bd9Sstevel@tonic-gate if (!error &&
16947c478bd9Sstevel@tonic-gate rfs4_check_delegated(FWRITE, tvp, trunc)) {
16957c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
16967c478bd9Sstevel@tonic-gate goto out1;
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate
16997c478bd9Sstevel@tonic-gate /*
17007c478bd9Sstevel@tonic-gate * Check for NBMAND lock conflicts
17017c478bd9Sstevel@tonic-gate */
17027c478bd9Sstevel@tonic-gate if (!error && nbl_need_check(tvp)) {
17037c478bd9Sstevel@tonic-gate u_offset_t offset;
17047c478bd9Sstevel@tonic-gate ssize_t len;
17057c478bd9Sstevel@tonic-gate
17067c478bd9Sstevel@tonic-gate nbl_start_crit(tvp, RW_READER);
17077c478bd9Sstevel@tonic-gate in_crit = 1;
17087c478bd9Sstevel@tonic-gate
17097c478bd9Sstevel@tonic-gate tva.va_mask = AT_SIZE;
1710da6c28aaSamw error = VOP_GETATTR(tvp, &tva, 0, cr,
1711cfae96c2Sjwahlig NULL);
17127c478bd9Sstevel@tonic-gate /*
17137c478bd9Sstevel@tonic-gate * Can't check for conflicts, so return
17147c478bd9Sstevel@tonic-gate * error.
17157c478bd9Sstevel@tonic-gate */
17167c478bd9Sstevel@tonic-gate if (error)
17177c478bd9Sstevel@tonic-gate goto out;
17187c478bd9Sstevel@tonic-gate
17197c478bd9Sstevel@tonic-gate offset = tva.va_size < va.va_size ?
1720cfae96c2Sjwahlig tva.va_size : va.va_size;
17217c478bd9Sstevel@tonic-gate len = tva.va_size < va.va_size ?
1722cfae96c2Sjwahlig va.va_size - tva.va_size :
1723cfae96c2Sjwahlig tva.va_size - va.va_size;
17247c478bd9Sstevel@tonic-gate if (nbl_conflict(tvp, NBL_WRITE,
1725cfae96c2Sjwahlig offset, len, 0, NULL)) {
17267c478bd9Sstevel@tonic-gate error = EACCES;
17277c478bd9Sstevel@tonic-gate goto out;
17287c478bd9Sstevel@tonic-gate }
17297c478bd9Sstevel@tonic-gate } else if (tvp) {
17307c478bd9Sstevel@tonic-gate VN_RELE(tvp);
17317c478bd9Sstevel@tonic-gate tvp = NULL;
17327c478bd9Sstevel@tonic-gate }
17337c478bd9Sstevel@tonic-gate }
17347c478bd9Sstevel@tonic-gate }
17357c478bd9Sstevel@tonic-gate if (va.va_mask & AT_SIZE)
17367c478bd9Sstevel@tonic-gate reqsize = va.va_size;
17377c478bd9Sstevel@tonic-gate }
17387c478bd9Sstevel@tonic-gate
17397c478bd9Sstevel@tonic-gate /*
17407c478bd9Sstevel@tonic-gate * Must specify the mode.
17417c478bd9Sstevel@tonic-gate */
17427c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
17437c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
17447c478bd9Sstevel@tonic-gate goto out1;
17457c478bd9Sstevel@tonic-gate }
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate /*
17487c478bd9Sstevel@tonic-gate * If the filesystem is exported with nosuid, then mask off
17497c478bd9Sstevel@tonic-gate * the setuid and setgid bits.
17507c478bd9Sstevel@tonic-gate */
17517c478bd9Sstevel@tonic-gate if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID))
17527c478bd9Sstevel@tonic-gate va.va_mode &= ~(VSUID | VSGID);
17537c478bd9Sstevel@tonic-gate
17547c478bd9Sstevel@tonic-gate tryagain:
17557c478bd9Sstevel@tonic-gate /*
17567c478bd9Sstevel@tonic-gate * The file open mode used is VWRITE. If the client needs
17577c478bd9Sstevel@tonic-gate * some other semantic, then it should do the access checking
17587c478bd9Sstevel@tonic-gate * itself. It would have been nice to have the file open mode
17597c478bd9Sstevel@tonic-gate * passed as part of the arguments.
17607c478bd9Sstevel@tonic-gate */
1761b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_CREATE(dvp, name, &va, excl, VWRITE,
1762da6c28aaSamw &vp, cr, 0, NULL, NULL);
17637c478bd9Sstevel@tonic-gate
17647c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
1765da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
17667c478bd9Sstevel@tonic-gate
17677c478bd9Sstevel@tonic-gate if (error) {
17687c478bd9Sstevel@tonic-gate /*
17697c478bd9Sstevel@tonic-gate * If we got something other than file already exists
17707c478bd9Sstevel@tonic-gate * then just return this error. Otherwise, we got
17717c478bd9Sstevel@tonic-gate * EEXIST. If we were doing a GUARDED create, then
17727c478bd9Sstevel@tonic-gate * just return this error. Otherwise, we need to
17737c478bd9Sstevel@tonic-gate * make sure that this wasn't a duplicate of an
17747c478bd9Sstevel@tonic-gate * exclusive create request.
17757c478bd9Sstevel@tonic-gate *
17767c478bd9Sstevel@tonic-gate * The assumption is made that a non-exclusive create
17777c478bd9Sstevel@tonic-gate * request will never return EEXIST.
17787c478bd9Sstevel@tonic-gate */
17797c478bd9Sstevel@tonic-gate if (error != EEXIST || args->how.mode == GUARDED)
17807c478bd9Sstevel@tonic-gate goto out;
17817c478bd9Sstevel@tonic-gate /*
17827c478bd9Sstevel@tonic-gate * Lookup the file so that we can get a vnode for it.
17837c478bd9Sstevel@tonic-gate */
1784b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &vp, NULL, 0,
1785da6c28aaSamw NULL, cr, NULL, NULL, NULL);
17867c478bd9Sstevel@tonic-gate if (error) {
17877c478bd9Sstevel@tonic-gate /*
17887c478bd9Sstevel@tonic-gate * We couldn't find the file that we thought that
17897c478bd9Sstevel@tonic-gate * we just created. So, we'll just try creating
17907c478bd9Sstevel@tonic-gate * it again.
17917c478bd9Sstevel@tonic-gate */
17927c478bd9Sstevel@tonic-gate if (error == ENOENT)
17937c478bd9Sstevel@tonic-gate goto tryagain;
17947c478bd9Sstevel@tonic-gate goto out;
17957c478bd9Sstevel@tonic-gate }
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate /*
17987c478bd9Sstevel@tonic-gate * If the file is delegated to a v4 client, go ahead
17997c478bd9Sstevel@tonic-gate * and initiate recall, this create is a hint that a
18007c478bd9Sstevel@tonic-gate * conflicting v3 open has occurred.
18017c478bd9Sstevel@tonic-gate */
18027c478bd9Sstevel@tonic-gate
18037c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, vp, FALSE)) {
18047c478bd9Sstevel@tonic-gate VN_RELE(vp);
18057c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
18067c478bd9Sstevel@tonic-gate goto out1;
18077c478bd9Sstevel@tonic-gate }
18087c478bd9Sstevel@tonic-gate
18097c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1810da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
18117c478bd9Sstevel@tonic-gate
18127c478bd9Sstevel@tonic-gate mtime = (nfstime3 *)&args->how.createhow3_u.verf;
18137c478bd9Sstevel@tonic-gate /* % with INT32_MAX to prevent overflows */
18147c478bd9Sstevel@tonic-gate if (args->how.mode == EXCLUSIVE && (vap == NULL ||
18157c478bd9Sstevel@tonic-gate vap->va_mtime.tv_sec !=
18167c478bd9Sstevel@tonic-gate (mtime->seconds % INT32_MAX) ||
18177c478bd9Sstevel@tonic-gate vap->va_mtime.tv_nsec != mtime->nseconds)) {
18187c478bd9Sstevel@tonic-gate VN_RELE(vp);
18197c478bd9Sstevel@tonic-gate error = EEXIST;
18207c478bd9Sstevel@tonic-gate goto out;
18217c478bd9Sstevel@tonic-gate }
18227c478bd9Sstevel@tonic-gate } else {
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gate if ((args->how.mode == UNCHECKED ||
18257c478bd9Sstevel@tonic-gate args->how.mode == GUARDED) &&
18267c478bd9Sstevel@tonic-gate args->how.createhow3_u.obj_attributes.size.set_it &&
18277c478bd9Sstevel@tonic-gate va.va_size == 0)
18287c478bd9Sstevel@tonic-gate trunc = TRUE;
18297c478bd9Sstevel@tonic-gate else
18307c478bd9Sstevel@tonic-gate trunc = FALSE;
18317c478bd9Sstevel@tonic-gate
18327c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, vp, trunc)) {
18337c478bd9Sstevel@tonic-gate VN_RELE(vp);
18347c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
18357c478bd9Sstevel@tonic-gate goto out1;
18367c478bd9Sstevel@tonic-gate }
18377c478bd9Sstevel@tonic-gate
18387c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1839da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
18407c478bd9Sstevel@tonic-gate
18417c478bd9Sstevel@tonic-gate /*
18427c478bd9Sstevel@tonic-gate * We need to check to make sure that the file got
18437c478bd9Sstevel@tonic-gate * created to the indicated size. If not, we do a
18447c478bd9Sstevel@tonic-gate * setattr to try to change the size, but we don't
18457c478bd9Sstevel@tonic-gate * try too hard. This shouldn't a problem as most
18467c478bd9Sstevel@tonic-gate * clients will only specifiy a size of zero which
18477c478bd9Sstevel@tonic-gate * local file systems handle. However, even if
18487c478bd9Sstevel@tonic-gate * the client does specify a non-zero size, it can
18497c478bd9Sstevel@tonic-gate * still recover by checking the size of the file
18507c478bd9Sstevel@tonic-gate * after it has created it and then issue a setattr
18517c478bd9Sstevel@tonic-gate * request of its own to set the size of the file.
18527c478bd9Sstevel@tonic-gate */
18537c478bd9Sstevel@tonic-gate if (vap != NULL &&
18547c478bd9Sstevel@tonic-gate (args->how.mode == UNCHECKED ||
18557c478bd9Sstevel@tonic-gate args->how.mode == GUARDED) &&
18567c478bd9Sstevel@tonic-gate args->how.createhow3_u.obj_attributes.size.set_it &&
18577c478bd9Sstevel@tonic-gate vap->va_size != reqsize) {
18587c478bd9Sstevel@tonic-gate va.va_mask = AT_SIZE;
18597c478bd9Sstevel@tonic-gate va.va_size = reqsize;
18607c478bd9Sstevel@tonic-gate (void) VOP_SETATTR(vp, &va, 0, cr, NULL);
18617c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1862da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
18637c478bd9Sstevel@tonic-gate }
18647c478bd9Sstevel@tonic-gate }
18657c478bd9Sstevel@tonic-gate
1866b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->where.name)
1867b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
1868b89a8333Snatalie li - Sun Microsystems - Irvine United States
18697c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
18707c478bd9Sstevel@tonic-gate if (error)
18717c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
18727c478bd9Sstevel@tonic-gate else
18737c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
18747c478bd9Sstevel@tonic-gate
18757c478bd9Sstevel@tonic-gate /*
18767c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
18777c478bd9Sstevel@tonic-gate */
1878da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
1879da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
18807c478bd9Sstevel@tonic-gate
18817c478bd9Sstevel@tonic-gate VN_RELE(vp);
18827c478bd9Sstevel@tonic-gate if (tvp != NULL) {
18837c478bd9Sstevel@tonic-gate if (in_crit)
18847c478bd9Sstevel@tonic-gate nbl_end_crit(tvp);
18857c478bd9Sstevel@tonic-gate VN_RELE(tvp);
18867c478bd9Sstevel@tonic-gate }
18877c478bd9Sstevel@tonic-gate
18887c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
18897c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
18907c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1891e1adf50cSahl
18920dfe541eSEvan Layton DTRACE_NFSV3_5(op__create__done, struct svc_req *, req,
18930dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
18940dfe541eSEvan Layton CREATE3res *, resp);
1895e1adf50cSahl
1896e1adf50cSahl VN_RELE(dvp);
18977c478bd9Sstevel@tonic-gate return;
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate out:
19007c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
19017c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
19027c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
19037c478bd9Sstevel@tonic-gate } else
19047c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
19057c478bd9Sstevel@tonic-gate out1:
19060dfe541eSEvan Layton DTRACE_NFSV3_5(op__create__done, struct svc_req *, req,
19070dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
19080dfe541eSEvan Layton CREATE3res *, resp);
1909e1adf50cSahl
1910b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->where.name)
1911b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
1912b89a8333Snatalie li - Sun Microsystems - Irvine United States
19137c478bd9Sstevel@tonic-gate if (tvp != NULL) {
19147c478bd9Sstevel@tonic-gate if (in_crit)
19157c478bd9Sstevel@tonic-gate nbl_end_crit(tvp);
19167c478bd9Sstevel@tonic-gate VN_RELE(tvp);
19177c478bd9Sstevel@tonic-gate }
19187c478bd9Sstevel@tonic-gate if (dvp != NULL)
19197c478bd9Sstevel@tonic-gate VN_RELE(dvp);
19207c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
19217c478bd9Sstevel@tonic-gate }
19227c478bd9Sstevel@tonic-gate
192327242a7cSthurlow void *
rfs3_create_getfh(CREATE3args * args)19247c478bd9Sstevel@tonic-gate rfs3_create_getfh(CREATE3args *args)
19257c478bd9Sstevel@tonic-gate {
19267c478bd9Sstevel@tonic-gate
192727242a7cSthurlow return (&args->where.dir);
19287c478bd9Sstevel@tonic-gate }
19297c478bd9Sstevel@tonic-gate
19307c478bd9Sstevel@tonic-gate void
rfs3_mkdir(MKDIR3args * args,MKDIR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)19317c478bd9Sstevel@tonic-gate rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi,
19325cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
19337c478bd9Sstevel@tonic-gate {
19347c478bd9Sstevel@tonic-gate int error;
19357c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
19367c478bd9Sstevel@tonic-gate vnode_t *dvp;
19377c478bd9Sstevel@tonic-gate struct vattr *vap;
19387c478bd9Sstevel@tonic-gate struct vattr va;
19397c478bd9Sstevel@tonic-gate struct vattr *dbvap;
19407c478bd9Sstevel@tonic-gate struct vattr dbva;
19417c478bd9Sstevel@tonic-gate struct vattr *davap;
19427c478bd9Sstevel@tonic-gate struct vattr dava;
1943b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
1944b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
19457c478bd9Sstevel@tonic-gate
19467c478bd9Sstevel@tonic-gate dbvap = NULL;
19477c478bd9Sstevel@tonic-gate davap = NULL;
19487c478bd9Sstevel@tonic-gate
194927242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
1950e1adf50cSahl
19510dfe541eSEvan Layton DTRACE_NFSV3_5(op__mkdir__start, struct svc_req *, req,
19520dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
19530dfe541eSEvan Layton MKDIR3args *, args);
1954e1adf50cSahl
19557c478bd9Sstevel@tonic-gate if (dvp == NULL) {
19567c478bd9Sstevel@tonic-gate error = ESTALE;
19577c478bd9Sstevel@tonic-gate goto out;
19587c478bd9Sstevel@tonic-gate }
19597c478bd9Sstevel@tonic-gate
19607c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
1961da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
19627c478bd9Sstevel@tonic-gate davap = dbvap;
19637c478bd9Sstevel@tonic-gate
19647c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
19657c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
19667c478bd9Sstevel@tonic-gate goto out1;
19677c478bd9Sstevel@tonic-gate }
19687c478bd9Sstevel@tonic-gate
19697c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
19707c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
19717c478bd9Sstevel@tonic-gate goto out1;
19727c478bd9Sstevel@tonic-gate }
19737c478bd9Sstevel@tonic-gate
19745cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
19757c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
19767c478bd9Sstevel@tonic-gate goto out1;
19777c478bd9Sstevel@tonic-gate }
19787c478bd9Sstevel@tonic-gate
197903986916Sjarrett if (is_system_labeled()) {
198003986916Sjarrett bslabel_t *clabel = req->rq_label;
198103986916Sjarrett
198203986916Sjarrett ASSERT(clabel != NULL);
198303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opmkdir__clabel, char *,
198403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
198503986916Sjarrett
198603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
1987bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
1988bd6f1640SJarrett Lu exi)) {
198903986916Sjarrett resp->status = NFS3ERR_ACCES;
199003986916Sjarrett goto out1;
199103986916Sjarrett }
199203986916Sjarrett }
199303986916Sjarrett }
199403986916Sjarrett
19957c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->attributes, &va);
19967c478bd9Sstevel@tonic-gate if (error)
19977c478bd9Sstevel@tonic-gate goto out;
19987c478bd9Sstevel@tonic-gate
19997c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
20007c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
20017c478bd9Sstevel@tonic-gate goto out1;
20027c478bd9Sstevel@tonic-gate }
20037c478bd9Sstevel@tonic-gate
2004b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2005b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
2006b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2007b89a8333Snatalie li - Sun Microsystems - Irvine United States
2008b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2009b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2010b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
2011b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2012b89a8333Snatalie li - Sun Microsystems - Irvine United States
20137c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
20147c478bd9Sstevel@tonic-gate va.va_type = VDIR;
20157c478bd9Sstevel@tonic-gate
2016b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL);
2017b89a8333Snatalie li - Sun Microsystems - Irvine United States
2018b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->where.name)
2019b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
20207c478bd9Sstevel@tonic-gate
20217c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
2022da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
20237c478bd9Sstevel@tonic-gate
20247c478bd9Sstevel@tonic-gate /*
20257c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
20267c478bd9Sstevel@tonic-gate */
2027da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
20287c478bd9Sstevel@tonic-gate
20297c478bd9Sstevel@tonic-gate if (error)
20307c478bd9Sstevel@tonic-gate goto out;
20317c478bd9Sstevel@tonic-gate
20327c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
20337c478bd9Sstevel@tonic-gate if (error)
20347c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
20357c478bd9Sstevel@tonic-gate else
20367c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
20377c478bd9Sstevel@tonic-gate
20387c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
2039da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
20407c478bd9Sstevel@tonic-gate
20417c478bd9Sstevel@tonic-gate /*
20427c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
20437c478bd9Sstevel@tonic-gate */
2044da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
20457c478bd9Sstevel@tonic-gate
20467c478bd9Sstevel@tonic-gate VN_RELE(vp);
20477c478bd9Sstevel@tonic-gate
20487c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
20497c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
20507c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2051e1adf50cSahl
20520dfe541eSEvan Layton DTRACE_NFSV3_5(op__mkdir__done, struct svc_req *, req,
20530dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
20540dfe541eSEvan Layton MKDIR3res *, resp);
2055e1adf50cSahl VN_RELE(dvp);
2056e1adf50cSahl
20577c478bd9Sstevel@tonic-gate return;
20587c478bd9Sstevel@tonic-gate
20597c478bd9Sstevel@tonic-gate out:
20607c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
20617c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
20627c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
20637c478bd9Sstevel@tonic-gate } else
20647c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
20657c478bd9Sstevel@tonic-gate out1:
20660dfe541eSEvan Layton DTRACE_NFSV3_5(op__mkdir__done, struct svc_req *, req,
20670dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
20680dfe541eSEvan Layton MKDIR3res *, resp);
20697c478bd9Sstevel@tonic-gate if (dvp != NULL)
20707c478bd9Sstevel@tonic-gate VN_RELE(dvp);
20717c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
20727c478bd9Sstevel@tonic-gate }
20737c478bd9Sstevel@tonic-gate
207427242a7cSthurlow void *
rfs3_mkdir_getfh(MKDIR3args * args)20757c478bd9Sstevel@tonic-gate rfs3_mkdir_getfh(MKDIR3args *args)
20767c478bd9Sstevel@tonic-gate {
20777c478bd9Sstevel@tonic-gate
207827242a7cSthurlow return (&args->where.dir);
20797c478bd9Sstevel@tonic-gate }
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate void
rfs3_symlink(SYMLINK3args * args,SYMLINK3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)20827c478bd9Sstevel@tonic-gate rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi,
20835cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
20847c478bd9Sstevel@tonic-gate {
20857c478bd9Sstevel@tonic-gate int error;
20867c478bd9Sstevel@tonic-gate vnode_t *vp;
20877c478bd9Sstevel@tonic-gate vnode_t *dvp;
20887c478bd9Sstevel@tonic-gate struct vattr *vap;
20897c478bd9Sstevel@tonic-gate struct vattr va;
20907c478bd9Sstevel@tonic-gate struct vattr *dbvap;
20917c478bd9Sstevel@tonic-gate struct vattr dbva;
20927c478bd9Sstevel@tonic-gate struct vattr *davap;
20937c478bd9Sstevel@tonic-gate struct vattr dava;
2094b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2095b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
2096b89a8333Snatalie li - Sun Microsystems - Irvine United States char *symdata = NULL;
20977c478bd9Sstevel@tonic-gate
20987c478bd9Sstevel@tonic-gate dbvap = NULL;
20997c478bd9Sstevel@tonic-gate davap = NULL;
21007c478bd9Sstevel@tonic-gate
210127242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
2102e1adf50cSahl
21030dfe541eSEvan Layton DTRACE_NFSV3_5(op__symlink__start, struct svc_req *, req,
21040dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
21050dfe541eSEvan Layton SYMLINK3args *, args);
2106e1adf50cSahl
21077c478bd9Sstevel@tonic-gate if (dvp == NULL) {
21087c478bd9Sstevel@tonic-gate error = ESTALE;
2109e1adf50cSahl goto err;
21107c478bd9Sstevel@tonic-gate }
21117c478bd9Sstevel@tonic-gate
21127c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
2113da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
21147c478bd9Sstevel@tonic-gate davap = dbvap;
21157c478bd9Sstevel@tonic-gate
21167c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
21177c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2118e1adf50cSahl goto err1;
21197c478bd9Sstevel@tonic-gate }
21207c478bd9Sstevel@tonic-gate
21217c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
21227c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2123e1adf50cSahl goto err1;
21247c478bd9Sstevel@tonic-gate }
21257c478bd9Sstevel@tonic-gate
21265cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
21277c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2128e1adf50cSahl goto err1;
21297c478bd9Sstevel@tonic-gate }
21307c478bd9Sstevel@tonic-gate
213103986916Sjarrett if (is_system_labeled()) {
213203986916Sjarrett bslabel_t *clabel = req->rq_label;
213303986916Sjarrett
213403986916Sjarrett ASSERT(clabel != NULL);
213503986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opsymlink__clabel, char *,
213603986916Sjarrett "got client label from request(1)", struct svc_req *, req);
213703986916Sjarrett
213803986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2139bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2140bd6f1640SJarrett Lu exi)) {
214103986916Sjarrett resp->status = NFS3ERR_ACCES;
2142e1adf50cSahl goto err1;
214303986916Sjarrett }
214403986916Sjarrett }
214503986916Sjarrett }
214603986916Sjarrett
21477c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->symlink.symlink_attributes, &va);
21487c478bd9Sstevel@tonic-gate if (error)
2149e1adf50cSahl goto err;
21507c478bd9Sstevel@tonic-gate
21517c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
21527c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
2153e1adf50cSahl goto err1;
21547c478bd9Sstevel@tonic-gate }
21557c478bd9Sstevel@tonic-gate
21567c478bd9Sstevel@tonic-gate if (args->symlink.symlink_data == nfs3nametoolong) {
21577c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2158e1adf50cSahl goto err1;
21597c478bd9Sstevel@tonic-gate }
21607c478bd9Sstevel@tonic-gate
2161b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2162b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
2163b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2164b89a8333Snatalie li - Sun Microsystems - Irvine United States
2165b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2166b89a8333Snatalie li - Sun Microsystems - Irvine United States /* This is really a Solaris EILSEQ */
2167b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2168b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2169b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2170b89a8333Snatalie li - Sun Microsystems - Irvine United States
2171b89a8333Snatalie li - Sun Microsystems - Irvine United States symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data,
2172b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2173b89a8333Snatalie li - Sun Microsystems - Irvine United States if (symdata == NULL) {
2174b89a8333Snatalie li - Sun Microsystems - Irvine United States /* This is really a Solaris EILSEQ */
2175b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2176b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2177b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2178b89a8333Snatalie li - Sun Microsystems - Irvine United States
2179b89a8333Snatalie li - Sun Microsystems - Irvine United States
21807c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
21817c478bd9Sstevel@tonic-gate va.va_type = VLNK;
21827c478bd9Sstevel@tonic-gate
2183b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0);
21847c478bd9Sstevel@tonic-gate
21857c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
2186da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
21877c478bd9Sstevel@tonic-gate
21887c478bd9Sstevel@tonic-gate if (error)
2189e1adf50cSahl goto err;
21907c478bd9Sstevel@tonic-gate
2191b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
2192cfae96c2Sjwahlig NULL, NULL, NULL);
21937c478bd9Sstevel@tonic-gate
21947c478bd9Sstevel@tonic-gate /*
21957c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
21967c478bd9Sstevel@tonic-gate */
2197da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
21987c478bd9Sstevel@tonic-gate
21997c478bd9Sstevel@tonic-gate
22007c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
22017c478bd9Sstevel@tonic-gate if (error) {
22027c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
22037c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
22047c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2205e1adf50cSahl goto out;
22067c478bd9Sstevel@tonic-gate }
22077c478bd9Sstevel@tonic-gate
22087c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
22097c478bd9Sstevel@tonic-gate if (error)
22107c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
22117c478bd9Sstevel@tonic-gate else
22127c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
22137c478bd9Sstevel@tonic-gate
22147c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
2215da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
22167c478bd9Sstevel@tonic-gate
22177c478bd9Sstevel@tonic-gate /*
22187c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
22197c478bd9Sstevel@tonic-gate */
2220da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
22217c478bd9Sstevel@tonic-gate
22227c478bd9Sstevel@tonic-gate VN_RELE(vp);
22237c478bd9Sstevel@tonic-gate
22247c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
22257c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2226e1adf50cSahl goto out;
22277c478bd9Sstevel@tonic-gate
2228e1adf50cSahl err:
22297c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
22307c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
22317c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
22327c478bd9Sstevel@tonic-gate } else
22337c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2234e1adf50cSahl err1:
2235e1adf50cSahl vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2236e1adf50cSahl out:
2237b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->where.name)
2238b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2239b89a8333Snatalie li - Sun Microsystems - Irvine United States if (symdata != NULL && symdata != args->symlink.symlink_data)
2240b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(symdata, MAXPATHLEN + 1);
2241b89a8333Snatalie li - Sun Microsystems - Irvine United States
22420dfe541eSEvan Layton DTRACE_NFSV3_5(op__symlink__done, struct svc_req *, req,
22430dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
22440dfe541eSEvan Layton SYMLINK3res *, resp);
2245e1adf50cSahl
22467c478bd9Sstevel@tonic-gate if (dvp != NULL)
22477c478bd9Sstevel@tonic-gate VN_RELE(dvp);
22487c478bd9Sstevel@tonic-gate }
22497c478bd9Sstevel@tonic-gate
225027242a7cSthurlow void *
rfs3_symlink_getfh(SYMLINK3args * args)22517c478bd9Sstevel@tonic-gate rfs3_symlink_getfh(SYMLINK3args *args)
22527c478bd9Sstevel@tonic-gate {
22537c478bd9Sstevel@tonic-gate
225427242a7cSthurlow return (&args->where.dir);
22557c478bd9Sstevel@tonic-gate }
22567c478bd9Sstevel@tonic-gate
22577c478bd9Sstevel@tonic-gate void
rfs3_mknod(MKNOD3args * args,MKNOD3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)22587c478bd9Sstevel@tonic-gate rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi,
22595cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
22607c478bd9Sstevel@tonic-gate {
22617c478bd9Sstevel@tonic-gate int error;
22627c478bd9Sstevel@tonic-gate vnode_t *vp;
2263fd7da618Sgt vnode_t *realvp;
22647c478bd9Sstevel@tonic-gate vnode_t *dvp;
22657c478bd9Sstevel@tonic-gate struct vattr *vap;
22667c478bd9Sstevel@tonic-gate struct vattr va;
22677c478bd9Sstevel@tonic-gate struct vattr *dbvap;
22687c478bd9Sstevel@tonic-gate struct vattr dbva;
22697c478bd9Sstevel@tonic-gate struct vattr *davap;
22707c478bd9Sstevel@tonic-gate struct vattr dava;
22717c478bd9Sstevel@tonic-gate int mode;
22727c478bd9Sstevel@tonic-gate enum vcexcl excl;
2273b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2274b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
22757c478bd9Sstevel@tonic-gate
22767c478bd9Sstevel@tonic-gate dbvap = NULL;
22777c478bd9Sstevel@tonic-gate davap = NULL;
22787c478bd9Sstevel@tonic-gate
227927242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
2280e1adf50cSahl
22810dfe541eSEvan Layton DTRACE_NFSV3_5(op__mknod__start, struct svc_req *, req,
22820dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
22830dfe541eSEvan Layton MKNOD3args *, args);
2284e1adf50cSahl
22857c478bd9Sstevel@tonic-gate if (dvp == NULL) {
22867c478bd9Sstevel@tonic-gate error = ESTALE;
22877c478bd9Sstevel@tonic-gate goto out;
22887c478bd9Sstevel@tonic-gate }
22897c478bd9Sstevel@tonic-gate
22907c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
2291da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
22927c478bd9Sstevel@tonic-gate davap = dbvap;
22937c478bd9Sstevel@tonic-gate
22947c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
22957c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
22967c478bd9Sstevel@tonic-gate goto out1;
22977c478bd9Sstevel@tonic-gate }
22987c478bd9Sstevel@tonic-gate
22997c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
23007c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
23017c478bd9Sstevel@tonic-gate goto out1;
23027c478bd9Sstevel@tonic-gate }
23037c478bd9Sstevel@tonic-gate
23045cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
23057c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
23067c478bd9Sstevel@tonic-gate goto out1;
23077c478bd9Sstevel@tonic-gate }
23087c478bd9Sstevel@tonic-gate
230903986916Sjarrett if (is_system_labeled()) {
231003986916Sjarrett bslabel_t *clabel = req->rq_label;
231103986916Sjarrett
231203986916Sjarrett ASSERT(clabel != NULL);
231303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opmknod__clabel, char *,
231403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
231503986916Sjarrett
231603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2317bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2318bd6f1640SJarrett Lu exi)) {
231903986916Sjarrett resp->status = NFS3ERR_ACCES;
232003986916Sjarrett goto out1;
232103986916Sjarrett }
232203986916Sjarrett }
232303986916Sjarrett }
232403986916Sjarrett
23257c478bd9Sstevel@tonic-gate switch (args->what.type) {
23267c478bd9Sstevel@tonic-gate case NF3CHR:
23277c478bd9Sstevel@tonic-gate case NF3BLK:
23287c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(
23297c478bd9Sstevel@tonic-gate &args->what.mknoddata3_u.device.dev_attributes, &va);
23307c478bd9Sstevel@tonic-gate if (error)
23317c478bd9Sstevel@tonic-gate goto out;
23327c478bd9Sstevel@tonic-gate if (secpolicy_sys_devices(cr) != 0) {
23337c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_PERM;
23347c478bd9Sstevel@tonic-gate goto out1;
23357c478bd9Sstevel@tonic-gate }
23367c478bd9Sstevel@tonic-gate if (args->what.type == NF3CHR)
23377c478bd9Sstevel@tonic-gate va.va_type = VCHR;
23387c478bd9Sstevel@tonic-gate else
23397c478bd9Sstevel@tonic-gate va.va_type = VBLK;
23407c478bd9Sstevel@tonic-gate va.va_rdev = makedevice(
23417c478bd9Sstevel@tonic-gate args->what.mknoddata3_u.device.spec.specdata1,
23427c478bd9Sstevel@tonic-gate args->what.mknoddata3_u.device.spec.specdata2);
23437c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE | AT_RDEV;
23447c478bd9Sstevel@tonic-gate break;
23457c478bd9Sstevel@tonic-gate case NF3SOCK:
23467c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(
23477c478bd9Sstevel@tonic-gate &args->what.mknoddata3_u.pipe_attributes, &va);
23487c478bd9Sstevel@tonic-gate if (error)
23497c478bd9Sstevel@tonic-gate goto out;
23507c478bd9Sstevel@tonic-gate va.va_type = VSOCK;
23517c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
23527c478bd9Sstevel@tonic-gate break;
23537c478bd9Sstevel@tonic-gate case NF3FIFO:
23547c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(
23557c478bd9Sstevel@tonic-gate &args->what.mknoddata3_u.pipe_attributes, &va);
23567c478bd9Sstevel@tonic-gate if (error)
23577c478bd9Sstevel@tonic-gate goto out;
23587c478bd9Sstevel@tonic-gate va.va_type = VFIFO;
23597c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
23607c478bd9Sstevel@tonic-gate break;
23617c478bd9Sstevel@tonic-gate default:
23627c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_BADTYPE;
23637c478bd9Sstevel@tonic-gate goto out1;
23647c478bd9Sstevel@tonic-gate }
23657c478bd9Sstevel@tonic-gate
23667c478bd9Sstevel@tonic-gate /*
23677c478bd9Sstevel@tonic-gate * Must specify the mode.
23687c478bd9Sstevel@tonic-gate */
23697c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
23707c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
23717c478bd9Sstevel@tonic-gate goto out1;
23727c478bd9Sstevel@tonic-gate }
23737c478bd9Sstevel@tonic-gate
2374b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2375b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
2376b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2377b89a8333Snatalie li - Sun Microsystems - Irvine United States
2378b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2379b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2380b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
2381b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2382b89a8333Snatalie li - Sun Microsystems - Irvine United States
23837c478bd9Sstevel@tonic-gate excl = EXCL;
23847c478bd9Sstevel@tonic-gate
23857c478bd9Sstevel@tonic-gate mode = 0;
23867c478bd9Sstevel@tonic-gate
2387b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_CREATE(dvp, name, &va, excl, mode,
2388da6c28aaSamw &vp, cr, 0, NULL, NULL);
23897c478bd9Sstevel@tonic-gate
2390b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->where.name)
2391b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2392b89a8333Snatalie li - Sun Microsystems - Irvine United States
23937c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
2394da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
23957c478bd9Sstevel@tonic-gate
23967c478bd9Sstevel@tonic-gate /*
23977c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
23987c478bd9Sstevel@tonic-gate */
2399da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
24007c478bd9Sstevel@tonic-gate
24017c478bd9Sstevel@tonic-gate if (error)
24027c478bd9Sstevel@tonic-gate goto out;
24037c478bd9Sstevel@tonic-gate
24047c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
24057c478bd9Sstevel@tonic-gate
24067c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
24077c478bd9Sstevel@tonic-gate if (error)
24087c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
24097c478bd9Sstevel@tonic-gate else
24107c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
24117c478bd9Sstevel@tonic-gate
24127c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
2413da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
24147c478bd9Sstevel@tonic-gate
24157c478bd9Sstevel@tonic-gate /*
24167c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
2417fd7da618Sgt *
2418fd7da618Sgt * if a underlying vp exists, pass it to VOP_FSYNC
24197c478bd9Sstevel@tonic-gate */
2420fd7da618Sgt if (VOP_REALVP(vp, &realvp, NULL) == 0)
2421fd7da618Sgt (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL);
2422fd7da618Sgt else
2423fd7da618Sgt (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
24247c478bd9Sstevel@tonic-gate
24257c478bd9Sstevel@tonic-gate VN_RELE(vp);
24267c478bd9Sstevel@tonic-gate
24277c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
24287c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
24290dfe541eSEvan Layton DTRACE_NFSV3_5(op__mknod__done, struct svc_req *, req,
24300dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
24310dfe541eSEvan Layton MKNOD3res *, resp);
2432e1adf50cSahl VN_RELE(dvp);
24337c478bd9Sstevel@tonic-gate return;
24347c478bd9Sstevel@tonic-gate
24357c478bd9Sstevel@tonic-gate out:
24367c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
24377c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
24387c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
24397c478bd9Sstevel@tonic-gate } else
24407c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
24417c478bd9Sstevel@tonic-gate out1:
24420dfe541eSEvan Layton DTRACE_NFSV3_5(op__mknod__done, struct svc_req *, req,
24430dfe541eSEvan Layton cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
24440dfe541eSEvan Layton MKNOD3res *, resp);
24457c478bd9Sstevel@tonic-gate if (dvp != NULL)
24467c478bd9Sstevel@tonic-gate VN_RELE(dvp);
24477c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
24487c478bd9Sstevel@tonic-gate }
24497c478bd9Sstevel@tonic-gate
245027242a7cSthurlow void *
rfs3_mknod_getfh(MKNOD3args * args)24517c478bd9Sstevel@tonic-gate rfs3_mknod_getfh(MKNOD3args *args)
24527c478bd9Sstevel@tonic-gate {
24537c478bd9Sstevel@tonic-gate
245427242a7cSthurlow return (&args->where.dir);
24557c478bd9Sstevel@tonic-gate }
24567c478bd9Sstevel@tonic-gate
24577c478bd9Sstevel@tonic-gate void
rfs3_remove(REMOVE3args * args,REMOVE3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)24587c478bd9Sstevel@tonic-gate rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi,
24595cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
24607c478bd9Sstevel@tonic-gate {
24617c478bd9Sstevel@tonic-gate int error = 0;
24627c478bd9Sstevel@tonic-gate vnode_t *vp;
24637c478bd9Sstevel@tonic-gate struct vattr *bvap;
24647c478bd9Sstevel@tonic-gate struct vattr bva;
24657c478bd9Sstevel@tonic-gate struct vattr *avap;
24667c478bd9Sstevel@tonic-gate struct vattr ava;
24677c478bd9Sstevel@tonic-gate vnode_t *targvp = NULL;
2468b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2469b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
24707c478bd9Sstevel@tonic-gate
24717c478bd9Sstevel@tonic-gate bvap = NULL;
24727c478bd9Sstevel@tonic-gate avap = NULL;
24737c478bd9Sstevel@tonic-gate
247427242a7cSthurlow vp = nfs3_fhtovp(&args->object.dir, exi);
2475e1adf50cSahl
24760dfe541eSEvan Layton DTRACE_NFSV3_5(op__remove__start, struct svc_req *, req,
24770dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
24780dfe541eSEvan Layton REMOVE3args *, args);
2479e1adf50cSahl
24807c478bd9Sstevel@tonic-gate if (vp == NULL) {
24817c478bd9Sstevel@tonic-gate error = ESTALE;
2482e1adf50cSahl goto err;
24837c478bd9Sstevel@tonic-gate }
24847c478bd9Sstevel@tonic-gate
24857c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
2486da6c28aaSamw bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
24877c478bd9Sstevel@tonic-gate avap = bvap;
24887c478bd9Sstevel@tonic-gate
24897c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
24907c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
2491e1adf50cSahl goto err1;
24927c478bd9Sstevel@tonic-gate }
24937c478bd9Sstevel@tonic-gate
24947c478bd9Sstevel@tonic-gate if (args->object.name == nfs3nametoolong) {
24957c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2496e1adf50cSahl goto err1;
24977c478bd9Sstevel@tonic-gate }
24987c478bd9Sstevel@tonic-gate
24997c478bd9Sstevel@tonic-gate if (args->object.name == NULL || *(args->object.name) == '\0') {
25007c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2501e1adf50cSahl goto err1;
25027c478bd9Sstevel@tonic-gate }
25037c478bd9Sstevel@tonic-gate
25045cb0d679SMarcel Telka if (rdonly(ro, vp)) {
25057c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2506e1adf50cSahl goto err1;
25077c478bd9Sstevel@tonic-gate }
25087c478bd9Sstevel@tonic-gate
250903986916Sjarrett if (is_system_labeled()) {
251003986916Sjarrett bslabel_t *clabel = req->rq_label;
251103986916Sjarrett
251203986916Sjarrett ASSERT(clabel != NULL);
251303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opremove__clabel, char *,
251403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
251503986916Sjarrett
251603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2517bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2518bd6f1640SJarrett Lu exi)) {
251903986916Sjarrett resp->status = NFS3ERR_ACCES;
2520e1adf50cSahl goto err1;
252103986916Sjarrett }
252203986916Sjarrett }
252303986916Sjarrett }
252403986916Sjarrett
2525b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2526b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->object.name,
2527b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2528b89a8333Snatalie li - Sun Microsystems - Irvine United States
2529b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2530b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2531b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2532b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2533b89a8333Snatalie li - Sun Microsystems - Irvine United States
25347c478bd9Sstevel@tonic-gate /*
25357c478bd9Sstevel@tonic-gate * Check for a conflict with a non-blocking mandatory share
25367c478bd9Sstevel@tonic-gate * reservation and V4 delegations
25377c478bd9Sstevel@tonic-gate */
2538b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(vp, name, &targvp, NULL, 0,
2539cfae96c2Sjwahlig NULL, cr, NULL, NULL, NULL);
25407c478bd9Sstevel@tonic-gate if (error != 0)
2541e1adf50cSahl goto err;
25427c478bd9Sstevel@tonic-gate
25437c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
25447c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2545e1adf50cSahl goto err1;
25467c478bd9Sstevel@tonic-gate }
25477c478bd9Sstevel@tonic-gate
25487c478bd9Sstevel@tonic-gate if (!nbl_need_check(targvp)) {
2549b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_REMOVE(vp, name, cr, NULL, 0);
25507c478bd9Sstevel@tonic-gate } else {
25517c478bd9Sstevel@tonic-gate nbl_start_crit(targvp, RW_READER);
2552da6c28aaSamw if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
25537c478bd9Sstevel@tonic-gate error = EACCES;
25547c478bd9Sstevel@tonic-gate } else {
2555b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_REMOVE(vp, name, cr, NULL, 0);
25567c478bd9Sstevel@tonic-gate }
25577c478bd9Sstevel@tonic-gate nbl_end_crit(targvp);
25587c478bd9Sstevel@tonic-gate }
25597c478bd9Sstevel@tonic-gate VN_RELE(targvp);
25607c478bd9Sstevel@tonic-gate targvp = NULL;
25617c478bd9Sstevel@tonic-gate
25627c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
2563da6c28aaSamw avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
25647c478bd9Sstevel@tonic-gate
25657c478bd9Sstevel@tonic-gate /*
25667c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
25677c478bd9Sstevel@tonic-gate */
2568da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
25697c478bd9Sstevel@tonic-gate
25707c478bd9Sstevel@tonic-gate if (error)
2571e1adf50cSahl goto err;
25727c478bd9Sstevel@tonic-gate
25737c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
25747c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2575e1adf50cSahl goto out;
25767c478bd9Sstevel@tonic-gate
2577e1adf50cSahl err:
25787c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
25797c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
25807c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
25817c478bd9Sstevel@tonic-gate } else
25827c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2583e1adf50cSahl err1:
2584e1adf50cSahl vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2585e1adf50cSahl out:
25860dfe541eSEvan Layton DTRACE_NFSV3_5(op__remove__done, struct svc_req *, req,
25870dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
25880dfe541eSEvan Layton REMOVE3res *, resp);
2589b89a8333Snatalie li - Sun Microsystems - Irvine United States
2590b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->object.name)
2591b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2592b89a8333Snatalie li - Sun Microsystems - Irvine United States
25937c478bd9Sstevel@tonic-gate if (vp != NULL)
25947c478bd9Sstevel@tonic-gate VN_RELE(vp);
25957c478bd9Sstevel@tonic-gate }
25967c478bd9Sstevel@tonic-gate
259727242a7cSthurlow void *
rfs3_remove_getfh(REMOVE3args * args)25987c478bd9Sstevel@tonic-gate rfs3_remove_getfh(REMOVE3args *args)
25997c478bd9Sstevel@tonic-gate {
26007c478bd9Sstevel@tonic-gate
260127242a7cSthurlow return (&args->object.dir);
26027c478bd9Sstevel@tonic-gate }
26037c478bd9Sstevel@tonic-gate
26047c478bd9Sstevel@tonic-gate void
rfs3_rmdir(RMDIR3args * args,RMDIR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)26057c478bd9Sstevel@tonic-gate rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi,
26065cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
26077c478bd9Sstevel@tonic-gate {
26087c478bd9Sstevel@tonic-gate int error;
26097c478bd9Sstevel@tonic-gate vnode_t *vp;
26107c478bd9Sstevel@tonic-gate struct vattr *bvap;
26117c478bd9Sstevel@tonic-gate struct vattr bva;
26127c478bd9Sstevel@tonic-gate struct vattr *avap;
26137c478bd9Sstevel@tonic-gate struct vattr ava;
2614b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2615b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
26167c478bd9Sstevel@tonic-gate
26177c478bd9Sstevel@tonic-gate bvap = NULL;
26187c478bd9Sstevel@tonic-gate avap = NULL;
26197c478bd9Sstevel@tonic-gate
262027242a7cSthurlow vp = nfs3_fhtovp(&args->object.dir, exi);
2621e1adf50cSahl
26220dfe541eSEvan Layton DTRACE_NFSV3_5(op__rmdir__start, struct svc_req *, req,
26230dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
26240dfe541eSEvan Layton RMDIR3args *, args);
2625e1adf50cSahl
26267c478bd9Sstevel@tonic-gate if (vp == NULL) {
26277c478bd9Sstevel@tonic-gate error = ESTALE;
2628e1adf50cSahl goto err;
26297c478bd9Sstevel@tonic-gate }
26307c478bd9Sstevel@tonic-gate
26317c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
2632da6c28aaSamw bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
26337c478bd9Sstevel@tonic-gate avap = bvap;
26347c478bd9Sstevel@tonic-gate
26357c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
26367c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
2637e1adf50cSahl goto err1;
26387c478bd9Sstevel@tonic-gate }
26397c478bd9Sstevel@tonic-gate
26407c478bd9Sstevel@tonic-gate if (args->object.name == nfs3nametoolong) {
26417c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2642e1adf50cSahl goto err1;
26437c478bd9Sstevel@tonic-gate }
26447c478bd9Sstevel@tonic-gate
26457c478bd9Sstevel@tonic-gate if (args->object.name == NULL || *(args->object.name) == '\0') {
26467c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2647e1adf50cSahl goto err1;
26487c478bd9Sstevel@tonic-gate }
26497c478bd9Sstevel@tonic-gate
26505cb0d679SMarcel Telka if (rdonly(ro, vp)) {
26517c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2652e1adf50cSahl goto err1;
26537c478bd9Sstevel@tonic-gate }
26547c478bd9Sstevel@tonic-gate
265503986916Sjarrett if (is_system_labeled()) {
265603986916Sjarrett bslabel_t *clabel = req->rq_label;
265703986916Sjarrett
265803986916Sjarrett ASSERT(clabel != NULL);
265903986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opremovedir__clabel, char *,
266003986916Sjarrett "got client label from request(1)", struct svc_req *, req);
266103986916Sjarrett
266203986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2663bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2664bd6f1640SJarrett Lu exi)) {
266503986916Sjarrett resp->status = NFS3ERR_ACCES;
2666e1adf50cSahl goto err1;
266703986916Sjarrett }
266803986916Sjarrett }
266903986916Sjarrett }
267003986916Sjarrett
2671b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2672b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->object.name,
2673b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2674b89a8333Snatalie li - Sun Microsystems - Irvine United States
2675b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2676b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2677b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2678b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2679b89a8333Snatalie li - Sun Microsystems - Irvine United States
26800dfe541eSEvan Layton ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
26810dfe541eSEvan Layton error = VOP_RMDIR(vp, name, ZONE_ROOTVP(), cr, NULL, 0);
2682b89a8333Snatalie li - Sun Microsystems - Irvine United States
2683b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->object.name)
2684b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
26857c478bd9Sstevel@tonic-gate
26867c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
2687da6c28aaSamw avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
26887c478bd9Sstevel@tonic-gate
26897c478bd9Sstevel@tonic-gate /*
26907c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
26917c478bd9Sstevel@tonic-gate */
2692da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
26937c478bd9Sstevel@tonic-gate
26947c478bd9Sstevel@tonic-gate if (error) {
26957c478bd9Sstevel@tonic-gate /*
26967c478bd9Sstevel@tonic-gate * System V defines rmdir to return EEXIST, not ENOTEMPTY,
26977c478bd9Sstevel@tonic-gate * if the directory is not empty. A System V NFS server
26987c478bd9Sstevel@tonic-gate * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
26997c478bd9Sstevel@tonic-gate * over the wire.
27007c478bd9Sstevel@tonic-gate */
27017c478bd9Sstevel@tonic-gate if (error == EEXIST)
27027c478bd9Sstevel@tonic-gate error = ENOTEMPTY;
2703e1adf50cSahl goto err;
27047c478bd9Sstevel@tonic-gate }
27057c478bd9Sstevel@tonic-gate
27067c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
27077c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2708e1adf50cSahl goto out;
27097c478bd9Sstevel@tonic-gate
2710e1adf50cSahl err:
27117c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
27127c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
27137c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
27147c478bd9Sstevel@tonic-gate } else
27157c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2716e1adf50cSahl err1:
2717e1adf50cSahl vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2718e1adf50cSahl out:
27190dfe541eSEvan Layton DTRACE_NFSV3_5(op__rmdir__done, struct svc_req *, req,
27200dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
27210dfe541eSEvan Layton RMDIR3res *, resp);
27227c478bd9Sstevel@tonic-gate if (vp != NULL)
27237c478bd9Sstevel@tonic-gate VN_RELE(vp);
2724e1adf50cSahl
27257c478bd9Sstevel@tonic-gate }
27267c478bd9Sstevel@tonic-gate
272727242a7cSthurlow void *
rfs3_rmdir_getfh(RMDIR3args * args)27287c478bd9Sstevel@tonic-gate rfs3_rmdir_getfh(RMDIR3args *args)
27297c478bd9Sstevel@tonic-gate {
27307c478bd9Sstevel@tonic-gate
273127242a7cSthurlow return (&args->object.dir);
27327c478bd9Sstevel@tonic-gate }
27337c478bd9Sstevel@tonic-gate
27347c478bd9Sstevel@tonic-gate void
rfs3_rename(RENAME3args * args,RENAME3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)27357c478bd9Sstevel@tonic-gate rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi,
27365cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
27377c478bd9Sstevel@tonic-gate {
27387c478bd9Sstevel@tonic-gate int error = 0;
27397c478bd9Sstevel@tonic-gate vnode_t *fvp;
27407c478bd9Sstevel@tonic-gate vnode_t *tvp;
27417c478bd9Sstevel@tonic-gate vnode_t *targvp;
27427c478bd9Sstevel@tonic-gate struct vattr *fbvap;
27437c478bd9Sstevel@tonic-gate struct vattr fbva;
27447c478bd9Sstevel@tonic-gate struct vattr *favap;
27457c478bd9Sstevel@tonic-gate struct vattr fava;
27467c478bd9Sstevel@tonic-gate struct vattr *tbvap;
27477c478bd9Sstevel@tonic-gate struct vattr tbva;
27487c478bd9Sstevel@tonic-gate struct vattr *tavap;
27497c478bd9Sstevel@tonic-gate struct vattr tava;
275027242a7cSthurlow nfs_fh3 *fh3;
27517c478bd9Sstevel@tonic-gate struct exportinfo *to_exi;
27527c478bd9Sstevel@tonic-gate vnode_t *srcvp = NULL;
275303986916Sjarrett bslabel_t *clabel;
2754b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2755b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
2756b89a8333Snatalie li - Sun Microsystems - Irvine United States char *toname = NULL;
27577c478bd9Sstevel@tonic-gate
27587c478bd9Sstevel@tonic-gate fbvap = NULL;
27597c478bd9Sstevel@tonic-gate favap = NULL;
27607c478bd9Sstevel@tonic-gate tbvap = NULL;
27617c478bd9Sstevel@tonic-gate tavap = NULL;
27627c478bd9Sstevel@tonic-gate tvp = NULL;
27637c478bd9Sstevel@tonic-gate
276427242a7cSthurlow fvp = nfs3_fhtovp(&args->from.dir, exi);
2765e1adf50cSahl
27660dfe541eSEvan Layton DTRACE_NFSV3_5(op__rename__start, struct svc_req *, req,
27670dfe541eSEvan Layton cred_t *, cr, vnode_t *, fvp, struct exportinfo *, exi,
27680dfe541eSEvan Layton RENAME3args *, args);
2769e1adf50cSahl
27707c478bd9Sstevel@tonic-gate if (fvp == NULL) {
27717c478bd9Sstevel@tonic-gate error = ESTALE;
2772e1adf50cSahl goto err;
27737c478bd9Sstevel@tonic-gate }
27747c478bd9Sstevel@tonic-gate
277503986916Sjarrett if (is_system_labeled()) {
277603986916Sjarrett clabel = req->rq_label;
277703986916Sjarrett ASSERT(clabel != NULL);
277803986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *,
277903986916Sjarrett "got client label from request(1)", struct svc_req *, req);
278003986916Sjarrett
278103986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2782bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK,
2783bd6f1640SJarrett Lu exi)) {
278403986916Sjarrett resp->status = NFS3ERR_ACCES;
2785e1adf50cSahl goto err1;
278603986916Sjarrett }
278703986916Sjarrett }
278803986916Sjarrett }
278903986916Sjarrett
27907c478bd9Sstevel@tonic-gate fbva.va_mask = AT_ALL;
2791da6c28aaSamw fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
27927c478bd9Sstevel@tonic-gate favap = fbvap;
27937c478bd9Sstevel@tonic-gate
279427242a7cSthurlow fh3 = &args->to.dir;
279527242a7cSthurlow to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
27967c478bd9Sstevel@tonic-gate if (to_exi == NULL) {
27977c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2798e1adf50cSahl goto err1;
27997c478bd9Sstevel@tonic-gate }
28007c478bd9Sstevel@tonic-gate exi_rele(to_exi);
28017c478bd9Sstevel@tonic-gate
28027c478bd9Sstevel@tonic-gate if (to_exi != exi) {
28037c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_XDEV;
2804e1adf50cSahl goto err1;
28057c478bd9Sstevel@tonic-gate }
28067c478bd9Sstevel@tonic-gate
280727242a7cSthurlow tvp = nfs3_fhtovp(&args->to.dir, exi);
28087c478bd9Sstevel@tonic-gate if (tvp == NULL) {
28097c478bd9Sstevel@tonic-gate error = ESTALE;
2810e1adf50cSahl goto err;
28117c478bd9Sstevel@tonic-gate }
28127c478bd9Sstevel@tonic-gate
28137c478bd9Sstevel@tonic-gate tbva.va_mask = AT_ALL;
2814da6c28aaSamw tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
28157c478bd9Sstevel@tonic-gate tavap = tbvap;
28167c478bd9Sstevel@tonic-gate
28177c478bd9Sstevel@tonic-gate if (fvp->v_type != VDIR || tvp->v_type != VDIR) {
28187c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
2819e1adf50cSahl goto err1;
28207c478bd9Sstevel@tonic-gate }
28217c478bd9Sstevel@tonic-gate
28227c478bd9Sstevel@tonic-gate if (args->from.name == nfs3nametoolong ||
28237c478bd9Sstevel@tonic-gate args->to.name == nfs3nametoolong) {
28247c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2825e1adf50cSahl goto err1;
28267c478bd9Sstevel@tonic-gate }
28277c478bd9Sstevel@tonic-gate if (args->from.name == NULL || *(args->from.name) == '\0' ||
28287c478bd9Sstevel@tonic-gate args->to.name == NULL || *(args->to.name) == '\0') {
28297c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2830e1adf50cSahl goto err1;
28317c478bd9Sstevel@tonic-gate }
28327c478bd9Sstevel@tonic-gate
28335cb0d679SMarcel Telka if (rdonly(ro, tvp)) {
28347c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2835e1adf50cSahl goto err1;
28367c478bd9Sstevel@tonic-gate }
28377c478bd9Sstevel@tonic-gate
283803986916Sjarrett if (is_system_labeled()) {
283903986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2840bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK,
2841bd6f1640SJarrett Lu exi)) {
284203986916Sjarrett resp->status = NFS3ERR_ACCES;
2843e1adf50cSahl goto err1;
284403986916Sjarrett }
284503986916Sjarrett }
284603986916Sjarrett }
284703986916Sjarrett
2848b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2849b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->from.name,
2850b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2851b89a8333Snatalie li - Sun Microsystems - Irvine United States
2852b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2853b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2854b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2855b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2856b89a8333Snatalie li - Sun Microsystems - Irvine United States
2857b89a8333Snatalie li - Sun Microsystems - Irvine United States toname = nfscmd_convname(ca, exi, args->to.name,
2858b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2859b89a8333Snatalie li - Sun Microsystems - Irvine United States
2860b89a8333Snatalie li - Sun Microsystems - Irvine United States if (toname == NULL) {
2861b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2862b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2863b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2864b89a8333Snatalie li - Sun Microsystems - Irvine United States
28657c478bd9Sstevel@tonic-gate /*
28667c478bd9Sstevel@tonic-gate * Check for a conflict with a non-blocking mandatory share
28677c478bd9Sstevel@tonic-gate * reservation or V4 delegations.
28687c478bd9Sstevel@tonic-gate */
2869b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(fvp, name, &srcvp, NULL, 0,
2870cfae96c2Sjwahlig NULL, cr, NULL, NULL, NULL);
28717c478bd9Sstevel@tonic-gate if (error != 0)
2872e1adf50cSahl goto err;
28737c478bd9Sstevel@tonic-gate
28747c478bd9Sstevel@tonic-gate /*
28757c478bd9Sstevel@tonic-gate * If we rename a delegated file we should recall the
28767c478bd9Sstevel@tonic-gate * delegation, since future opens should fail or would
28777c478bd9Sstevel@tonic-gate * refer to a new file.
28787c478bd9Sstevel@tonic-gate */
28797c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, srcvp, FALSE)) {
28807c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2881e1adf50cSahl goto err1;
28827c478bd9Sstevel@tonic-gate }
28837c478bd9Sstevel@tonic-gate
28847c478bd9Sstevel@tonic-gate /*
28850dfe541eSEvan Layton * Check for renaming over a delegated file. Check nfs4_deleg_policy
28867c478bd9Sstevel@tonic-gate * first to avoid VOP_LOOKUP if possible.
28877c478bd9Sstevel@tonic-gate */
28880dfe541eSEvan Layton if (nfs4_get_deleg_policy() != SRV_NEVER_DELEGATE &&
2889b89a8333Snatalie li - Sun Microsystems - Irvine United States VOP_LOOKUP(tvp, toname, &targvp, NULL, 0, NULL, cr,
2890da6c28aaSamw NULL, NULL, NULL) == 0) {
28917c478bd9Sstevel@tonic-gate
28927c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
28937c478bd9Sstevel@tonic-gate VN_RELE(targvp);
28947c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2895e1adf50cSahl goto err1;
28967c478bd9Sstevel@tonic-gate }
28977c478bd9Sstevel@tonic-gate VN_RELE(targvp);
28987c478bd9Sstevel@tonic-gate }
28997c478bd9Sstevel@tonic-gate
29007c478bd9Sstevel@tonic-gate if (!nbl_need_check(srcvp)) {
2901b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
29027c478bd9Sstevel@tonic-gate } else {
29037c478bd9Sstevel@tonic-gate nbl_start_crit(srcvp, RW_READER);
2904b89a8333Snatalie li - Sun Microsystems - Irvine United States if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL))
29057c478bd9Sstevel@tonic-gate error = EACCES;
2906b89a8333Snatalie li - Sun Microsystems - Irvine United States else
2907b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
29087c478bd9Sstevel@tonic-gate nbl_end_crit(srcvp);
29097c478bd9Sstevel@tonic-gate }
291051ece835Seschrock if (error == 0)
291151ece835Seschrock vn_renamepath(tvp, srcvp, args->to.name,
2912cfae96c2Sjwahlig strlen(args->to.name));
29137c478bd9Sstevel@tonic-gate VN_RELE(srcvp);
29147c478bd9Sstevel@tonic-gate srcvp = NULL;
29157c478bd9Sstevel@tonic-gate
29167c478bd9Sstevel@tonic-gate fava.va_mask = AT_ALL;
2917da6c28aaSamw favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
29187c478bd9Sstevel@tonic-gate tava.va_mask = AT_ALL;
2919da6c28aaSamw tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
29207c478bd9Sstevel@tonic-gate
29217c478bd9Sstevel@tonic-gate /*
29227c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
29237c478bd9Sstevel@tonic-gate */
2924da6c28aaSamw (void) VOP_FSYNC(fvp, 0, cr, NULL);
2925da6c28aaSamw (void) VOP_FSYNC(tvp, 0, cr, NULL);
29267c478bd9Sstevel@tonic-gate
29277c478bd9Sstevel@tonic-gate if (error)
2928e1adf50cSahl goto err;
29297c478bd9Sstevel@tonic-gate
29307c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
29317c478bd9Sstevel@tonic-gate vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc);
29327c478bd9Sstevel@tonic-gate vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc);
2933e1adf50cSahl goto out;
29347c478bd9Sstevel@tonic-gate
2935e1adf50cSahl err:
29367c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
29377c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
29387c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2939b89a8333Snatalie li - Sun Microsystems - Irvine United States } else {
29407c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2941b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2942e1adf50cSahl err1:
2943e1adf50cSahl vattr_to_wcc_data(fbvap, favap, &resp->resfail.fromdir_wcc);
2944e1adf50cSahl vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc);
2945b89a8333Snatalie li - Sun Microsystems - Irvine United States
2946e1adf50cSahl out:
2947b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->from.name)
2948b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2949b89a8333Snatalie li - Sun Microsystems - Irvine United States if (toname != NULL && toname != args->to.name)
2950b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(toname, MAXPATHLEN + 1);
2951b89a8333Snatalie li - Sun Microsystems - Irvine United States
29520dfe541eSEvan Layton DTRACE_NFSV3_5(op__rename__done, struct svc_req *, req,
29530dfe541eSEvan Layton cred_t *, cr, vnode_t *, fvp, struct exportinfo *, exi,
29540dfe541eSEvan Layton RENAME3res *, resp);
29557c478bd9Sstevel@tonic-gate if (fvp != NULL)
29567c478bd9Sstevel@tonic-gate VN_RELE(fvp);
29577c478bd9Sstevel@tonic-gate if (tvp != NULL)
29587c478bd9Sstevel@tonic-gate VN_RELE(tvp);
29597c478bd9Sstevel@tonic-gate }
29607c478bd9Sstevel@tonic-gate
296127242a7cSthurlow void *
rfs3_rename_getfh(RENAME3args * args)29627c478bd9Sstevel@tonic-gate rfs3_rename_getfh(RENAME3args *args)
29637c478bd9Sstevel@tonic-gate {
29647c478bd9Sstevel@tonic-gate
296527242a7cSthurlow return (&args->from.dir);
29667c478bd9Sstevel@tonic-gate }
29677c478bd9Sstevel@tonic-gate
29687c478bd9Sstevel@tonic-gate void
rfs3_link(LINK3args * args,LINK3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)29697c478bd9Sstevel@tonic-gate rfs3_link(LINK3args *args, LINK3res *resp, struct exportinfo *exi,
29705cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
29717c478bd9Sstevel@tonic-gate {
29727c478bd9Sstevel@tonic-gate int error;
29737c478bd9Sstevel@tonic-gate vnode_t *vp;
29747c478bd9Sstevel@tonic-gate vnode_t *dvp;
29757c478bd9Sstevel@tonic-gate struct vattr *vap;
29767c478bd9Sstevel@tonic-gate struct vattr va;
29777c478bd9Sstevel@tonic-gate struct vattr *bvap;
29787c478bd9Sstevel@tonic-gate struct vattr bva;
29797c478bd9Sstevel@tonic-gate struct vattr *avap;
29807c478bd9Sstevel@tonic-gate struct vattr ava;
29817c478bd9Sstevel@tonic-gate nfs_fh3 *fh3;
29827c478bd9Sstevel@tonic-gate struct exportinfo *to_exi;
298303986916Sjarrett bslabel_t *clabel;
2984b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2985b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
29867c478bd9Sstevel@tonic-gate
29877c478bd9Sstevel@tonic-gate vap = NULL;
29887c478bd9Sstevel@tonic-gate bvap = NULL;
29897c478bd9Sstevel@tonic-gate avap = NULL;
29907c478bd9Sstevel@tonic-gate dvp = NULL;
29917c478bd9Sstevel@tonic-gate
29927c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
2993e1adf50cSahl
29940dfe541eSEvan Layton DTRACE_NFSV3_5(op__link__start, struct svc_req *, req,
29950dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
29960dfe541eSEvan Layton LINK3args *, args);
2997e1adf50cSahl
29987c478bd9Sstevel@tonic-gate if (vp == NULL) {
29997c478bd9Sstevel@tonic-gate error = ESTALE;
30007c478bd9Sstevel@tonic-gate goto out;
30017c478bd9Sstevel@tonic-gate }
30027c478bd9Sstevel@tonic-gate
30037c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3004da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
30057c478bd9Sstevel@tonic-gate
300627242a7cSthurlow fh3 = &args->link.dir;
300727242a7cSthurlow to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
30087c478bd9Sstevel@tonic-gate if (to_exi == NULL) {
30097c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
30107c478bd9Sstevel@tonic-gate goto out1;
30117c478bd9Sstevel@tonic-gate }
30127c478bd9Sstevel@tonic-gate exi_rele(to_exi);
30137c478bd9Sstevel@tonic-gate
30147c478bd9Sstevel@tonic-gate if (to_exi != exi) {
30157c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_XDEV;
30167c478bd9Sstevel@tonic-gate goto out1;
30177c478bd9Sstevel@tonic-gate }
30187c478bd9Sstevel@tonic-gate
301903986916Sjarrett if (is_system_labeled()) {
302003986916Sjarrett clabel = req->rq_label;
302103986916Sjarrett
302203986916Sjarrett ASSERT(clabel != NULL);
302303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oplink__clabel, char *,
302403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
302503986916Sjarrett
302603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3027bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3028bd6f1640SJarrett Lu exi)) {
302903986916Sjarrett resp->status = NFS3ERR_ACCES;
303003986916Sjarrett goto out1;
303103986916Sjarrett }
303203986916Sjarrett }
303303986916Sjarrett }
303403986916Sjarrett
303527242a7cSthurlow dvp = nfs3_fhtovp(&args->link.dir, exi);
30367c478bd9Sstevel@tonic-gate if (dvp == NULL) {
30377c478bd9Sstevel@tonic-gate error = ESTALE;
30387c478bd9Sstevel@tonic-gate goto out;
30397c478bd9Sstevel@tonic-gate }
30407c478bd9Sstevel@tonic-gate
30417c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
3042da6c28aaSamw bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
30437c478bd9Sstevel@tonic-gate
30447c478bd9Sstevel@tonic-gate if (dvp->v_type != VDIR) {
30457c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
30467c478bd9Sstevel@tonic-gate goto out1;
30477c478bd9Sstevel@tonic-gate }
30487c478bd9Sstevel@tonic-gate
30497c478bd9Sstevel@tonic-gate if (args->link.name == nfs3nametoolong) {
30507c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
30517c478bd9Sstevel@tonic-gate goto out1;
30527c478bd9Sstevel@tonic-gate }
30537c478bd9Sstevel@tonic-gate
30547c478bd9Sstevel@tonic-gate if (args->link.name == NULL || *(args->link.name) == '\0') {
30557c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
30567c478bd9Sstevel@tonic-gate goto out1;
30577c478bd9Sstevel@tonic-gate }
30587c478bd9Sstevel@tonic-gate
30595cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
30607c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
30617c478bd9Sstevel@tonic-gate goto out1;
30627c478bd9Sstevel@tonic-gate }
30637c478bd9Sstevel@tonic-gate
306403986916Sjarrett if (is_system_labeled()) {
306503986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oplinkdir__clabel, char *,
306603986916Sjarrett "got client label from request(1)", struct svc_req *, req);
306703986916Sjarrett
306803986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3069bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
3070bd6f1640SJarrett Lu exi)) {
307103986916Sjarrett resp->status = NFS3ERR_ACCES;
307203986916Sjarrett goto out1;
307303986916Sjarrett }
307403986916Sjarrett }
307503986916Sjarrett }
307603986916Sjarrett
3077b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3078b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->link.name,
3079b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3080b89a8333Snatalie li - Sun Microsystems - Irvine United States
3081b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
3082b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_SERVERFAULT;
3083b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
3084b89a8333Snatalie li - Sun Microsystems - Irvine United States }
3085b89a8333Snatalie li - Sun Microsystems - Irvine United States
3086b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LINK(dvp, vp, name, cr, NULL, 0);
30877c478bd9Sstevel@tonic-gate
30887c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3089da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
30907c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
3091da6c28aaSamw avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
30927c478bd9Sstevel@tonic-gate
30937c478bd9Sstevel@tonic-gate /*
30947c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
30957c478bd9Sstevel@tonic-gate */
3096da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3097da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
30987c478bd9Sstevel@tonic-gate
30997c478bd9Sstevel@tonic-gate if (error)
31007c478bd9Sstevel@tonic-gate goto out;
31017c478bd9Sstevel@tonic-gate
31027c478bd9Sstevel@tonic-gate VN_RELE(dvp);
31037c478bd9Sstevel@tonic-gate
31047c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
31057c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
31067c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc);
3107e1adf50cSahl
31080dfe541eSEvan Layton DTRACE_NFSV3_5(op__link__done, struct svc_req *, req,
31090dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
31100dfe541eSEvan Layton LINK3res *, resp);
3111e1adf50cSahl
3112e1adf50cSahl VN_RELE(vp);
3113e1adf50cSahl
31147c478bd9Sstevel@tonic-gate return;
31157c478bd9Sstevel@tonic-gate
31167c478bd9Sstevel@tonic-gate out:
31177c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
31187c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
31197c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
31207c478bd9Sstevel@tonic-gate } else
31217c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
31227c478bd9Sstevel@tonic-gate out1:
3123b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->link.name)
3124b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
3125b89a8333Snatalie li - Sun Microsystems - Irvine United States
31260dfe541eSEvan Layton DTRACE_NFSV3_5(op__link__done, struct svc_req *, req,
31270dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
31280dfe541eSEvan Layton LINK3res *, resp);
3129e1adf50cSahl
31307c478bd9Sstevel@tonic-gate if (vp != NULL)
31317c478bd9Sstevel@tonic-gate VN_RELE(vp);
31327c478bd9Sstevel@tonic-gate if (dvp != NULL)
31337c478bd9Sstevel@tonic-gate VN_RELE(dvp);
31347c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
31357c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resfail.linkdir_wcc);
31367c478bd9Sstevel@tonic-gate }
31377c478bd9Sstevel@tonic-gate
313827242a7cSthurlow void *
rfs3_link_getfh(LINK3args * args)31397c478bd9Sstevel@tonic-gate rfs3_link_getfh(LINK3args *args)
31407c478bd9Sstevel@tonic-gate {
31417c478bd9Sstevel@tonic-gate
314227242a7cSthurlow return (&args->file);
31437c478bd9Sstevel@tonic-gate }
31447c478bd9Sstevel@tonic-gate
31457c478bd9Sstevel@tonic-gate /*
31467c478bd9Sstevel@tonic-gate * This macro defines the size of a response which contains attribute
31477c478bd9Sstevel@tonic-gate * information and one directory entry (whose length is specified by
31487c478bd9Sstevel@tonic-gate * the macro parameter). If the incoming request is larger than this,
31497c478bd9Sstevel@tonic-gate * then we are guaranteed to be able to return at one directory entry
31507c478bd9Sstevel@tonic-gate * if one exists. Therefore, we do not need to check for
31517c478bd9Sstevel@tonic-gate * NFS3ERR_TOOSMALL if the requested size is larger then this. If it
31527c478bd9Sstevel@tonic-gate * is not, then we need to check to make sure that this error does not
31537c478bd9Sstevel@tonic-gate * need to be returned.
31547c478bd9Sstevel@tonic-gate *
31557c478bd9Sstevel@tonic-gate * NFS3_READDIR_MIN_COUNT is comprised of following :
31567c478bd9Sstevel@tonic-gate *
31577c478bd9Sstevel@tonic-gate * status - 1 * BYTES_PER_XDR_UNIT
31587c478bd9Sstevel@tonic-gate * attr. flag - 1 * BYTES_PER_XDR_UNIT
31597c478bd9Sstevel@tonic-gate * cookie verifier - 2 * BYTES_PER_XDR_UNIT
31607c478bd9Sstevel@tonic-gate * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
31617c478bd9Sstevel@tonic-gate * boolean - 1 * BYTES_PER_XDR_UNIT
31627c478bd9Sstevel@tonic-gate * file id - 2 * BYTES_PER_XDR_UNIT
3163da6c28aaSamw * directory name length - 1 * BYTES_PER_XDR_UNIT
31647c478bd9Sstevel@tonic-gate * cookie - 2 * BYTES_PER_XDR_UNIT
31657c478bd9Sstevel@tonic-gate * end of list - 1 * BYTES_PER_XDR_UNIT
31667c478bd9Sstevel@tonic-gate * end of file - 1 * BYTES_PER_XDR_UNIT
31677c478bd9Sstevel@tonic-gate * Name length of directory to the nearest byte
31687c478bd9Sstevel@tonic-gate */
31697c478bd9Sstevel@tonic-gate
31707c478bd9Sstevel@tonic-gate #define NFS3_READDIR_MIN_COUNT(length) \
31717c478bd9Sstevel@tonic-gate ((1 + 1 + 2 + NFS3_SIZEOF_FATTR3 + 1 + 2 + 1 + 2 + 1 + 1) * \
31727c478bd9Sstevel@tonic-gate BYTES_PER_XDR_UNIT + roundup((length), BYTES_PER_XDR_UNIT))
31737c478bd9Sstevel@tonic-gate
31747c478bd9Sstevel@tonic-gate /* ARGSUSED */
31757c478bd9Sstevel@tonic-gate void
rfs3_readdir(READDIR3args * args,READDIR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)31767c478bd9Sstevel@tonic-gate rfs3_readdir(READDIR3args *args, READDIR3res *resp, struct exportinfo *exi,
31775cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
31787c478bd9Sstevel@tonic-gate {
31797c478bd9Sstevel@tonic-gate int error;
31807c478bd9Sstevel@tonic-gate vnode_t *vp;
31817c478bd9Sstevel@tonic-gate struct vattr *vap;
31827c478bd9Sstevel@tonic-gate struct vattr va;
31837c478bd9Sstevel@tonic-gate struct iovec iov;
31847c478bd9Sstevel@tonic-gate struct uio uio;
31857c478bd9Sstevel@tonic-gate char *data;
31867c478bd9Sstevel@tonic-gate int iseof;
31877c478bd9Sstevel@tonic-gate int bufsize;
31887c478bd9Sstevel@tonic-gate int namlen;
31897c478bd9Sstevel@tonic-gate uint_t count;
3190b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
31917c478bd9Sstevel@tonic-gate
31927c478bd9Sstevel@tonic-gate vap = NULL;
31937c478bd9Sstevel@tonic-gate
31947c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->dir, exi);
3195e1adf50cSahl
31960dfe541eSEvan Layton DTRACE_NFSV3_5(op__readdir__start, struct svc_req *, req,
31970dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
31980dfe541eSEvan Layton READDIR3args *, args);
3199e1adf50cSahl
32007c478bd9Sstevel@tonic-gate if (vp == NULL) {
32017c478bd9Sstevel@tonic-gate error = ESTALE;
32027c478bd9Sstevel@tonic-gate goto out;
32037c478bd9Sstevel@tonic-gate }
32047c478bd9Sstevel@tonic-gate
320503986916Sjarrett if (is_system_labeled()) {
320603986916Sjarrett bslabel_t *clabel = req->rq_label;
320703986916Sjarrett
320803986916Sjarrett ASSERT(clabel != NULL);
320903986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opreaddir__clabel, char *,
321003986916Sjarrett "got client label from request(1)", struct svc_req *, req);
321103986916Sjarrett
321203986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3213bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3214bd6f1640SJarrett Lu exi)) {
321503986916Sjarrett resp->status = NFS3ERR_ACCES;
321603986916Sjarrett goto out1;
321703986916Sjarrett }
321803986916Sjarrett }
321903986916Sjarrett }
322003986916Sjarrett
32217c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
32227c478bd9Sstevel@tonic-gate
32237c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3224da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
32257c478bd9Sstevel@tonic-gate
32267c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
32277c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
32287c478bd9Sstevel@tonic-gate goto out1;
32297c478bd9Sstevel@tonic-gate }
32307c478bd9Sstevel@tonic-gate
3231da6c28aaSamw error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
32327c478bd9Sstevel@tonic-gate if (error)
32337c478bd9Sstevel@tonic-gate goto out;
32347c478bd9Sstevel@tonic-gate
32357c478bd9Sstevel@tonic-gate /*
32367c478bd9Sstevel@tonic-gate * Now don't allow arbitrary count to alloc;
32377c478bd9Sstevel@tonic-gate * allow the maximum not to exceed rfs3_tsize()
32387c478bd9Sstevel@tonic-gate */
32397c478bd9Sstevel@tonic-gate if (args->count > rfs3_tsize(req))
32407c478bd9Sstevel@tonic-gate args->count = rfs3_tsize(req);
32417c478bd9Sstevel@tonic-gate
32427c478bd9Sstevel@tonic-gate /*
32437c478bd9Sstevel@tonic-gate * Make sure that there is room to read at least one entry
32447c478bd9Sstevel@tonic-gate * if any are available.
32457c478bd9Sstevel@tonic-gate */
32467c478bd9Sstevel@tonic-gate if (args->count < DIRENT64_RECLEN(MAXNAMELEN))
32477c478bd9Sstevel@tonic-gate count = DIRENT64_RECLEN(MAXNAMELEN);
32487c478bd9Sstevel@tonic-gate else
32497c478bd9Sstevel@tonic-gate count = args->count;
32507c478bd9Sstevel@tonic-gate
32517c478bd9Sstevel@tonic-gate data = kmem_alloc(count, KM_SLEEP);
32527c478bd9Sstevel@tonic-gate
32537c478bd9Sstevel@tonic-gate iov.iov_base = data;
32547c478bd9Sstevel@tonic-gate iov.iov_len = count;
32557c478bd9Sstevel@tonic-gate uio.uio_iov = &iov;
32567c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1;
32577c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
32587c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
32597c478bd9Sstevel@tonic-gate uio.uio_loffset = (offset_t)args->cookie;
32607c478bd9Sstevel@tonic-gate uio.uio_resid = count;
32617c478bd9Sstevel@tonic-gate
3262da6c28aaSamw error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
32637c478bd9Sstevel@tonic-gate
32647c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3265da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
32667c478bd9Sstevel@tonic-gate
32677c478bd9Sstevel@tonic-gate if (error) {
32687c478bd9Sstevel@tonic-gate kmem_free(data, count);
32697c478bd9Sstevel@tonic-gate goto out;
32707c478bd9Sstevel@tonic-gate }
32717c478bd9Sstevel@tonic-gate
32727c478bd9Sstevel@tonic-gate /*
32737c478bd9Sstevel@tonic-gate * If the count was not large enough to be able to guarantee
32747c478bd9Sstevel@tonic-gate * to be able to return at least one entry, then need to
32757c478bd9Sstevel@tonic-gate * check to see if NFS3ERR_TOOSMALL should be returned.
32767c478bd9Sstevel@tonic-gate */
32777c478bd9Sstevel@tonic-gate if (args->count < NFS3_READDIR_MIN_COUNT(MAXNAMELEN)) {
32787c478bd9Sstevel@tonic-gate /*
32797c478bd9Sstevel@tonic-gate * bufsize is used to keep track of the size of the response.
32807c478bd9Sstevel@tonic-gate * It is primed with:
32817c478bd9Sstevel@tonic-gate * 1 for the status +
32827c478bd9Sstevel@tonic-gate * 1 for the dir_attributes.attributes boolean +
32837c478bd9Sstevel@tonic-gate * 2 for the cookie verifier
32847c478bd9Sstevel@tonic-gate * all times BYTES_PER_XDR_UNIT to convert from XDR units
32857c478bd9Sstevel@tonic-gate * to bytes. If there are directory attributes to be
32867c478bd9Sstevel@tonic-gate * returned, then:
32877c478bd9Sstevel@tonic-gate * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
32887c478bd9Sstevel@tonic-gate * time BYTES_PER_XDR_UNIT is added to account for them.
32897c478bd9Sstevel@tonic-gate */
32907c478bd9Sstevel@tonic-gate bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
32917c478bd9Sstevel@tonic-gate if (vap != NULL)
32927c478bd9Sstevel@tonic-gate bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
32937c478bd9Sstevel@tonic-gate /*
32947c478bd9Sstevel@tonic-gate * An entry is composed of:
32957c478bd9Sstevel@tonic-gate * 1 for the true/false list indicator +
32967c478bd9Sstevel@tonic-gate * 2 for the fileid +
32977c478bd9Sstevel@tonic-gate * 1 for the length of the name +
32987c478bd9Sstevel@tonic-gate * 2 for the cookie +
32997c478bd9Sstevel@tonic-gate * all times BYTES_PER_XDR_UNIT to convert from
33007c478bd9Sstevel@tonic-gate * XDR units to bytes, plus the length of the name
33017c478bd9Sstevel@tonic-gate * rounded up to the nearest BYTES_PER_XDR_UNIT.
33027c478bd9Sstevel@tonic-gate */
33037c478bd9Sstevel@tonic-gate if (count != uio.uio_resid) {
33047c478bd9Sstevel@tonic-gate namlen = strlen(((struct dirent64 *)data)->d_name);
33057c478bd9Sstevel@tonic-gate bufsize += (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
3306cfae96c2Sjwahlig roundup(namlen, BYTES_PER_XDR_UNIT);
33077c478bd9Sstevel@tonic-gate }
33087c478bd9Sstevel@tonic-gate /*
33097c478bd9Sstevel@tonic-gate * We need to check to see if the number of bytes left
33107c478bd9Sstevel@tonic-gate * to go into the buffer will actually fit into the
33117c478bd9Sstevel@tonic-gate * buffer. This is calculated as the size of this
33127c478bd9Sstevel@tonic-gate * entry plus:
33137c478bd9Sstevel@tonic-gate * 1 for the true/false list indicator +
33147c478bd9Sstevel@tonic-gate * 1 for the eof indicator
33157c478bd9Sstevel@tonic-gate * times BYTES_PER_XDR_UNIT to convert from from
33167c478bd9Sstevel@tonic-gate * XDR units to bytes.
33177c478bd9Sstevel@tonic-gate */
33187c478bd9Sstevel@tonic-gate bufsize += (1 + 1) * BYTES_PER_XDR_UNIT;
33197c478bd9Sstevel@tonic-gate if (bufsize > args->count) {
33207c478bd9Sstevel@tonic-gate kmem_free(data, count);
33217c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_TOOSMALL;
33227c478bd9Sstevel@tonic-gate goto out1;
33237c478bd9Sstevel@tonic-gate }
33247c478bd9Sstevel@tonic-gate }
33257c478bd9Sstevel@tonic-gate
3326b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
3327b89a8333Snatalie li - Sun Microsystems - Irvine United States * Have a valid readir buffer for the native character
3328b89a8333Snatalie li - Sun Microsystems - Irvine United States * set. Need to check if a conversion is necessary and
3329b89a8333Snatalie li - Sun Microsystems - Irvine United States * potentially rewrite the whole buffer. Note that if the
3330b89a8333Snatalie li - Sun Microsystems - Irvine United States * conversion expands names enough, the structure may not
3331b89a8333Snatalie li - Sun Microsystems - Irvine United States * fit. In this case, we need to drop entries until if fits
3332b89a8333Snatalie li - Sun Microsystems - Irvine United States * and patch the counts in order that the next readdir will
3333b89a8333Snatalie li - Sun Microsystems - Irvine United States * get the correct entries.
3334b89a8333Snatalie li - Sun Microsystems - Irvine United States */
3335b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3336b89a8333Snatalie li - Sun Microsystems - Irvine United States data = nfscmd_convdirent(ca, exi, data, count, &resp->status);
3337b89a8333Snatalie li - Sun Microsystems - Irvine United States
3338b89a8333Snatalie li - Sun Microsystems - Irvine United States
33397c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
33407c478bd9Sstevel@tonic-gate
33417c478bd9Sstevel@tonic-gate #if 0 /* notyet */
33427c478bd9Sstevel@tonic-gate /*
33437c478bd9Sstevel@tonic-gate * Don't do this. It causes local disk writes when just
33447c478bd9Sstevel@tonic-gate * reading the file and the overhead is deemed larger
33457c478bd9Sstevel@tonic-gate * than the benefit.
33467c478bd9Sstevel@tonic-gate */
33477c478bd9Sstevel@tonic-gate /*
33487c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
33497c478bd9Sstevel@tonic-gate */
3350da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
33517c478bd9Sstevel@tonic-gate #endif
33527c478bd9Sstevel@tonic-gate
33537c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
33547c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
33557c478bd9Sstevel@tonic-gate resp->resok.cookieverf = 0;
33567c478bd9Sstevel@tonic-gate resp->resok.reply.entries = (entry3 *)data;
33577c478bd9Sstevel@tonic-gate resp->resok.reply.eof = iseof;
33587c478bd9Sstevel@tonic-gate resp->resok.size = count - uio.uio_resid;
33597c478bd9Sstevel@tonic-gate resp->resok.count = args->count;
33607c478bd9Sstevel@tonic-gate resp->resok.freecount = count;
3361e1adf50cSahl
33620dfe541eSEvan Layton DTRACE_NFSV3_5(op__readdir__done, struct svc_req *, req,
33630dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
33640dfe541eSEvan Layton READDIR3res *, resp);
3365e1adf50cSahl
3366e1adf50cSahl VN_RELE(vp);
3367e1adf50cSahl
33687c478bd9Sstevel@tonic-gate return;
33697c478bd9Sstevel@tonic-gate
33707c478bd9Sstevel@tonic-gate out:
33717c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
33727c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
33737c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
33747c478bd9Sstevel@tonic-gate } else
33757c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
33767c478bd9Sstevel@tonic-gate out1:
33770dfe541eSEvan Layton vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
33780dfe541eSEvan Layton
33790dfe541eSEvan Layton DTRACE_NFSV3_5(op__readdir__done, struct svc_req *, req,
33800dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
33810dfe541eSEvan Layton READDIR3res *, resp);
3382e1adf50cSahl
33837c478bd9Sstevel@tonic-gate if (vp != NULL) {
33847c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
33857c478bd9Sstevel@tonic-gate VN_RELE(vp);
33867c478bd9Sstevel@tonic-gate }
33877c478bd9Sstevel@tonic-gate }
33887c478bd9Sstevel@tonic-gate
338927242a7cSthurlow void *
rfs3_readdir_getfh(READDIR3args * args)33907c478bd9Sstevel@tonic-gate rfs3_readdir_getfh(READDIR3args *args)
33917c478bd9Sstevel@tonic-gate {
33927c478bd9Sstevel@tonic-gate
339327242a7cSthurlow return (&args->dir);
33947c478bd9Sstevel@tonic-gate }
33957c478bd9Sstevel@tonic-gate
33967c478bd9Sstevel@tonic-gate void
rfs3_readdir_free(READDIR3res * resp)33977c478bd9Sstevel@tonic-gate rfs3_readdir_free(READDIR3res *resp)
33987c478bd9Sstevel@tonic-gate {
33997c478bd9Sstevel@tonic-gate
34007c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK)
34017c478bd9Sstevel@tonic-gate kmem_free(resp->resok.reply.entries, resp->resok.freecount);
34027c478bd9Sstevel@tonic-gate }
34037c478bd9Sstevel@tonic-gate
34047c478bd9Sstevel@tonic-gate #ifdef nextdp
34057c478bd9Sstevel@tonic-gate #undef nextdp
34067c478bd9Sstevel@tonic-gate #endif
34077c478bd9Sstevel@tonic-gate #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
34087c478bd9Sstevel@tonic-gate
34097c478bd9Sstevel@tonic-gate /*
34107c478bd9Sstevel@tonic-gate * This macro computes the size of a response which contains
34117c478bd9Sstevel@tonic-gate * one directory entry including the attributes as well as file handle.
34127c478bd9Sstevel@tonic-gate * If the incoming request is larger than this, then we are guaranteed to be
34137c478bd9Sstevel@tonic-gate * able to return at least one more directory entry if one exists.
34147c478bd9Sstevel@tonic-gate *
34157c478bd9Sstevel@tonic-gate * NFS3_READDIRPLUS_ENTRY is made up of the following:
34167c478bd9Sstevel@tonic-gate *
34177c478bd9Sstevel@tonic-gate * boolean - 1 * BYTES_PER_XDR_UNIT
34187c478bd9Sstevel@tonic-gate * file id - 2 * BYTES_PER_XDR_UNIT
34197c478bd9Sstevel@tonic-gate * directory name length - 1 * BYTES_PER_XDR_UNIT
34207c478bd9Sstevel@tonic-gate * cookie - 2 * BYTES_PER_XDR_UNIT
34217c478bd9Sstevel@tonic-gate * attribute flag - 1 * BYTES_PER_XDR_UNIT
34227c478bd9Sstevel@tonic-gate * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
34237c478bd9Sstevel@tonic-gate * status byte for file handle - 1 * BYTES_PER_XDR_UNIT
34247c478bd9Sstevel@tonic-gate * length of a file handle - 1 * BYTES_PER_XDR_UNIT
3425da6c28aaSamw * Maximum length of a file handle (NFS3_MAXFHSIZE)
34267c478bd9Sstevel@tonic-gate * name length of the entry to the nearest bytes
34277c478bd9Sstevel@tonic-gate */
34287c478bd9Sstevel@tonic-gate #define NFS3_READDIRPLUS_ENTRY(namelen) \
34297c478bd9Sstevel@tonic-gate ((1 + 2 + 1 + 2 + 1 + NFS3_SIZEOF_FATTR3 + 1 + 1) * \
34307c478bd9Sstevel@tonic-gate BYTES_PER_XDR_UNIT + \
343127242a7cSthurlow NFS3_MAXFHSIZE + roundup(namelen, BYTES_PER_XDR_UNIT))
34327c478bd9Sstevel@tonic-gate
34337c478bd9Sstevel@tonic-gate static int rfs3_readdir_unit = MAXBSIZE;
34347c478bd9Sstevel@tonic-gate
34357c478bd9Sstevel@tonic-gate /* ARGSUSED */
34367c478bd9Sstevel@tonic-gate void
rfs3_readdirplus(READDIRPLUS3args * args,READDIRPLUS3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)34377c478bd9Sstevel@tonic-gate rfs3_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *resp,
34385cb0d679SMarcel Telka struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
34397c478bd9Sstevel@tonic-gate {
34407c478bd9Sstevel@tonic-gate int error;
34417c478bd9Sstevel@tonic-gate vnode_t *vp;
34427c478bd9Sstevel@tonic-gate struct vattr *vap;
34437c478bd9Sstevel@tonic-gate struct vattr va;
34447c478bd9Sstevel@tonic-gate struct iovec iov;
34457c478bd9Sstevel@tonic-gate struct uio uio;
34467c478bd9Sstevel@tonic-gate char *data;
34477c478bd9Sstevel@tonic-gate int iseof;
34487c478bd9Sstevel@tonic-gate struct dirent64 *dp;
34497c478bd9Sstevel@tonic-gate vnode_t *nvp;
34507c478bd9Sstevel@tonic-gate struct vattr *nvap;
34517c478bd9Sstevel@tonic-gate struct vattr nva;
34527c478bd9Sstevel@tonic-gate entryplus3_info *infop = NULL;
34537c478bd9Sstevel@tonic-gate int size = 0;
34547c478bd9Sstevel@tonic-gate int nents = 0;
34557c478bd9Sstevel@tonic-gate int bufsize = 0;
34567c478bd9Sstevel@tonic-gate int entrysize = 0;
34577c478bd9Sstevel@tonic-gate int tofit = 0;
34587c478bd9Sstevel@tonic-gate int rd_unit = rfs3_readdir_unit;
34597c478bd9Sstevel@tonic-gate int prev_len;
34607c478bd9Sstevel@tonic-gate int space_left;
34617c478bd9Sstevel@tonic-gate int i;
34627c478bd9Sstevel@tonic-gate uint_t *namlen = NULL;
3463b89a8333Snatalie li - Sun Microsystems - Irvine United States char *ndata = NULL;
3464b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
3465b89a8333Snatalie li - Sun Microsystems - Irvine United States size_t ret;
34667c478bd9Sstevel@tonic-gate
34677c478bd9Sstevel@tonic-gate vap = NULL;
34687c478bd9Sstevel@tonic-gate
34697c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->dir, exi);
3470e1adf50cSahl
34710dfe541eSEvan Layton DTRACE_NFSV3_5(op__readdirplus__start, struct svc_req *, req,
34720dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
34730dfe541eSEvan Layton READDIRPLUS3args *, args);
3474e1adf50cSahl
34757c478bd9Sstevel@tonic-gate if (vp == NULL) {
34767c478bd9Sstevel@tonic-gate error = ESTALE;
34777c478bd9Sstevel@tonic-gate goto out;
34787c478bd9Sstevel@tonic-gate }
34797c478bd9Sstevel@tonic-gate
348003986916Sjarrett if (is_system_labeled()) {
348103986916Sjarrett bslabel_t *clabel = req->rq_label;
348203986916Sjarrett
348303986916Sjarrett ASSERT(clabel != NULL);
348403986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opreaddirplus__clabel,
348503986916Sjarrett char *, "got client label from request(1)",
348603986916Sjarrett struct svc_req *, req);
348703986916Sjarrett
348803986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3489bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3490bd6f1640SJarrett Lu exi)) {
349103986916Sjarrett resp->status = NFS3ERR_ACCES;
349203986916Sjarrett goto out1;
349303986916Sjarrett }
349403986916Sjarrett }
349503986916Sjarrett }
349603986916Sjarrett
34977c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
34987c478bd9Sstevel@tonic-gate
34997c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3500da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
35017c478bd9Sstevel@tonic-gate
35027c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
35037c478bd9Sstevel@tonic-gate error = ENOTDIR;
35047c478bd9Sstevel@tonic-gate goto out;
35057c478bd9Sstevel@tonic-gate }
35067c478bd9Sstevel@tonic-gate
3507da6c28aaSamw error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
35087c478bd9Sstevel@tonic-gate if (error)
35097c478bd9Sstevel@tonic-gate goto out;
35107c478bd9Sstevel@tonic-gate
35117c478bd9Sstevel@tonic-gate /*
35127c478bd9Sstevel@tonic-gate * Don't allow arbitrary counts for allocation
35137c478bd9Sstevel@tonic-gate */
35147c478bd9Sstevel@tonic-gate if (args->maxcount > rfs3_tsize(req))
35157c478bd9Sstevel@tonic-gate args->maxcount = rfs3_tsize(req);
35167c478bd9Sstevel@tonic-gate
35177c478bd9Sstevel@tonic-gate /*
35187c478bd9Sstevel@tonic-gate * Make sure that there is room to read at least one entry
35197c478bd9Sstevel@tonic-gate * if any are available
35207c478bd9Sstevel@tonic-gate */
35217c478bd9Sstevel@tonic-gate args->dircount = MIN(args->dircount, args->maxcount);
35227c478bd9Sstevel@tonic-gate
35237c478bd9Sstevel@tonic-gate if (args->dircount < DIRENT64_RECLEN(MAXNAMELEN))
35247c478bd9Sstevel@tonic-gate args->dircount = DIRENT64_RECLEN(MAXNAMELEN);
35257c478bd9Sstevel@tonic-gate
35267c478bd9Sstevel@tonic-gate /*
35277c478bd9Sstevel@tonic-gate * This allocation relies on a minimum directory entry
35287c478bd9Sstevel@tonic-gate * being roughly 24 bytes. Therefore, the namlen array
35297c478bd9Sstevel@tonic-gate * will have enough space based on the maximum number of
35307c478bd9Sstevel@tonic-gate * entries to read.
35317c478bd9Sstevel@tonic-gate */
35327c478bd9Sstevel@tonic-gate namlen = kmem_alloc(args->dircount, KM_SLEEP);
35337c478bd9Sstevel@tonic-gate
35347c478bd9Sstevel@tonic-gate space_left = args->dircount;
35357c478bd9Sstevel@tonic-gate data = kmem_alloc(args->dircount, KM_SLEEP);
35367c478bd9Sstevel@tonic-gate dp = (struct dirent64 *)data;
35377c478bd9Sstevel@tonic-gate uio.uio_iov = &iov;
35387c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1;
35397c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
35407c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
35417c478bd9Sstevel@tonic-gate uio.uio_loffset = (offset_t)args->cookie;
35427c478bd9Sstevel@tonic-gate
35437c478bd9Sstevel@tonic-gate /*
35447c478bd9Sstevel@tonic-gate * bufsize is used to keep track of the size of the response as we
35457c478bd9Sstevel@tonic-gate * get post op attributes and filehandles for each entry. This is
35467c478bd9Sstevel@tonic-gate * an optimization as the server may have read more entries than will
35477c478bd9Sstevel@tonic-gate * fit in the buffer specified by maxcount. We stop calculating
35487c478bd9Sstevel@tonic-gate * post op attributes and filehandles once we have exceeded maxcount.
35497c478bd9Sstevel@tonic-gate * This will minimize the effect of truncation.
35507c478bd9Sstevel@tonic-gate *
35517c478bd9Sstevel@tonic-gate * It is primed with:
35527c478bd9Sstevel@tonic-gate * 1 for the status +
35537c478bd9Sstevel@tonic-gate * 1 for the dir_attributes.attributes boolean +
35547c478bd9Sstevel@tonic-gate * 2 for the cookie verifier
35557c478bd9Sstevel@tonic-gate * all times BYTES_PER_XDR_UNIT to convert from XDR units
35567c478bd9Sstevel@tonic-gate * to bytes. If there are directory attributes to be
35577c478bd9Sstevel@tonic-gate * returned, then:
35587c478bd9Sstevel@tonic-gate * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
35597c478bd9Sstevel@tonic-gate * time BYTES_PER_XDR_UNIT is added to account for them.
35607c478bd9Sstevel@tonic-gate */
35617c478bd9Sstevel@tonic-gate bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
35627c478bd9Sstevel@tonic-gate if (vap != NULL)
35637c478bd9Sstevel@tonic-gate bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
35647c478bd9Sstevel@tonic-gate
35657c478bd9Sstevel@tonic-gate getmoredents:
35667c478bd9Sstevel@tonic-gate /*
35677c478bd9Sstevel@tonic-gate * Here we make a check so that our read unit is not larger than
35687c478bd9Sstevel@tonic-gate * the space left in the buffer.
35697c478bd9Sstevel@tonic-gate */
35707c478bd9Sstevel@tonic-gate rd_unit = MIN(rd_unit, space_left);
35717c478bd9Sstevel@tonic-gate iov.iov_base = (char *)dp;
35727c478bd9Sstevel@tonic-gate iov.iov_len = rd_unit;
35737c478bd9Sstevel@tonic-gate uio.uio_resid = rd_unit;
35747c478bd9Sstevel@tonic-gate prev_len = rd_unit;
35757c478bd9Sstevel@tonic-gate
3576da6c28aaSamw error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
35777c478bd9Sstevel@tonic-gate
35787c478bd9Sstevel@tonic-gate if (error) {
35797c478bd9Sstevel@tonic-gate kmem_free(data, args->dircount);
35807c478bd9Sstevel@tonic-gate goto out;
35817c478bd9Sstevel@tonic-gate }
35827c478bd9Sstevel@tonic-gate
35837c478bd9Sstevel@tonic-gate if (uio.uio_resid == prev_len && !iseof) {
35847c478bd9Sstevel@tonic-gate if (nents == 0) {
35857c478bd9Sstevel@tonic-gate kmem_free(data, args->dircount);
35867c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_TOOSMALL;
35877c478bd9Sstevel@tonic-gate goto out1;
35887c478bd9Sstevel@tonic-gate }
35897c478bd9Sstevel@tonic-gate
35907c478bd9Sstevel@tonic-gate /*
35917c478bd9Sstevel@tonic-gate * We could not get any more entries, so get the attributes
35927c478bd9Sstevel@tonic-gate * and filehandle for the entries already obtained.
35937c478bd9Sstevel@tonic-gate */
35947c478bd9Sstevel@tonic-gate goto good;
35957c478bd9Sstevel@tonic-gate }
35967c478bd9Sstevel@tonic-gate
35977c478bd9Sstevel@tonic-gate /*
35987c478bd9Sstevel@tonic-gate * We estimate the size of the response by assuming the
35997c478bd9Sstevel@tonic-gate * entry exists and attributes and filehandle are also valid
36007c478bd9Sstevel@tonic-gate */
36017c478bd9Sstevel@tonic-gate for (size = prev_len - uio.uio_resid;
3602cfae96c2Sjwahlig size > 0;
3603cfae96c2Sjwahlig size -= dp->d_reclen, dp = nextdp(dp)) {
36047c478bd9Sstevel@tonic-gate
36057c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) {
36067c478bd9Sstevel@tonic-gate nents++;
36077c478bd9Sstevel@tonic-gate continue;
36087c478bd9Sstevel@tonic-gate }
36097c478bd9Sstevel@tonic-gate
36107c478bd9Sstevel@tonic-gate namlen[nents] = strlen(dp->d_name);
36117c478bd9Sstevel@tonic-gate entrysize = NFS3_READDIRPLUS_ENTRY(namlen[nents]);
36127c478bd9Sstevel@tonic-gate
36137c478bd9Sstevel@tonic-gate /*
36147c478bd9Sstevel@tonic-gate * We need to check to see if the number of bytes left
36157c478bd9Sstevel@tonic-gate * to go into the buffer will actually fit into the
36167c478bd9Sstevel@tonic-gate * buffer. This is calculated as the size of this
36177c478bd9Sstevel@tonic-gate * entry plus:
36187c478bd9Sstevel@tonic-gate * 1 for the true/false list indicator +
36197c478bd9Sstevel@tonic-gate * 1 for the eof indicator
36207c478bd9Sstevel@tonic-gate * times BYTES_PER_XDR_UNIT to convert from XDR units
36217c478bd9Sstevel@tonic-gate * to bytes.
36227c478bd9Sstevel@tonic-gate *
36237c478bd9Sstevel@tonic-gate * Also check the dircount limit against the first entry read
36247c478bd9Sstevel@tonic-gate *
36257c478bd9Sstevel@tonic-gate */
36267c478bd9Sstevel@tonic-gate tofit = entrysize + (1 + 1) * BYTES_PER_XDR_UNIT;
36277c478bd9Sstevel@tonic-gate if (bufsize + tofit > args->maxcount) {
36287c478bd9Sstevel@tonic-gate /*
36297c478bd9Sstevel@tonic-gate * We make a check here to see if this was the
36307c478bd9Sstevel@tonic-gate * first entry being measured. If so, then maxcount
36317c478bd9Sstevel@tonic-gate * was too small to begin with and so we need to
36327c478bd9Sstevel@tonic-gate * return with NFS3ERR_TOOSMALL.
36337c478bd9Sstevel@tonic-gate */
36347c478bd9Sstevel@tonic-gate if (nents == 0) {
36357c478bd9Sstevel@tonic-gate kmem_free(data, args->dircount);
36367c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_TOOSMALL;
36377c478bd9Sstevel@tonic-gate goto out1;
36387c478bd9Sstevel@tonic-gate }
36397c478bd9Sstevel@tonic-gate iseof = FALSE;
36407c478bd9Sstevel@tonic-gate goto good;
36417c478bd9Sstevel@tonic-gate }
36427c478bd9Sstevel@tonic-gate bufsize += entrysize;
36437c478bd9Sstevel@tonic-gate nents++;
36447c478bd9Sstevel@tonic-gate }
36457c478bd9Sstevel@tonic-gate
36467c478bd9Sstevel@tonic-gate /*
36477c478bd9Sstevel@tonic-gate * If there is enough room to fit at least 1 more entry including
36487c478bd9Sstevel@tonic-gate * post op attributes and filehandle in the buffer AND that we haven't
36497c478bd9Sstevel@tonic-gate * exceeded dircount then go back and get some more.
36507c478bd9Sstevel@tonic-gate */
36517c478bd9Sstevel@tonic-gate if (!iseof &&
36527c478bd9Sstevel@tonic-gate (args->maxcount - bufsize) >= NFS3_READDIRPLUS_ENTRY(MAXNAMELEN)) {
36537c478bd9Sstevel@tonic-gate space_left -= (prev_len - uio.uio_resid);
36547c478bd9Sstevel@tonic-gate if (space_left >= DIRENT64_RECLEN(MAXNAMELEN))
36557c478bd9Sstevel@tonic-gate goto getmoredents;
36567c478bd9Sstevel@tonic-gate
36577c478bd9Sstevel@tonic-gate /* else, fall through */
36587c478bd9Sstevel@tonic-gate }
36597c478bd9Sstevel@tonic-gate good:
36607c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3661da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
36627c478bd9Sstevel@tonic-gate
36637c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
36647c478bd9Sstevel@tonic-gate
36657c478bd9Sstevel@tonic-gate infop = kmem_alloc(nents * sizeof (struct entryplus3_info), KM_SLEEP);
36667c478bd9Sstevel@tonic-gate resp->resok.infop = infop;
36677c478bd9Sstevel@tonic-gate
36687c478bd9Sstevel@tonic-gate dp = (struct dirent64 *)data;
36697c478bd9Sstevel@tonic-gate for (i = 0; i < nents; i++) {
36707c478bd9Sstevel@tonic-gate
36717c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) {
36727c478bd9Sstevel@tonic-gate infop[i].attr.attributes = FALSE;
36737c478bd9Sstevel@tonic-gate infop[i].fh.handle_follows = FALSE;
36747c478bd9Sstevel@tonic-gate dp = nextdp(dp);
36757c478bd9Sstevel@tonic-gate continue;
36767c478bd9Sstevel@tonic-gate }
36777c478bd9Sstevel@tonic-gate
36787c478bd9Sstevel@tonic-gate infop[i].namelen = namlen[i];
36797c478bd9Sstevel@tonic-gate
3680da6c28aaSamw error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr,
3681cfae96c2Sjwahlig NULL, NULL, NULL);
36827c478bd9Sstevel@tonic-gate if (error) {
36837c478bd9Sstevel@tonic-gate infop[i].attr.attributes = FALSE;
36847c478bd9Sstevel@tonic-gate infop[i].fh.handle_follows = FALSE;
36857c478bd9Sstevel@tonic-gate dp = nextdp(dp);
36867c478bd9Sstevel@tonic-gate continue;
36877c478bd9Sstevel@tonic-gate }
36887c478bd9Sstevel@tonic-gate
36897c478bd9Sstevel@tonic-gate nva.va_mask = AT_ALL;
36907c478bd9Sstevel@tonic-gate nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL : &nva;
369127246829SVitaliy Gusev
36922f172c55SRobert Thurlow /* Lie about the object type for a referral */
36932f172c55SRobert Thurlow if (vn_is_nfs_reparse(nvp, cr))
36942f172c55SRobert Thurlow nvap->va_type = VLNK;
36952f172c55SRobert Thurlow
3696f7db5903SVitaliy Gusev if (vn_ismntpt(nvp)) {
3697f7db5903SVitaliy Gusev infop[i].attr.attributes = FALSE;
36987c478bd9Sstevel@tonic-gate infop[i].fh.handle_follows = FALSE;
3699f7db5903SVitaliy Gusev } else {
3700f7db5903SVitaliy Gusev vattr_to_post_op_attr(nvap, &infop[i].attr);
3701f7db5903SVitaliy Gusev
3702f7db5903SVitaliy Gusev error = makefh3(&infop[i].fh.handle, nvp, exi);
3703f7db5903SVitaliy Gusev if (!error)
3704f7db5903SVitaliy Gusev infop[i].fh.handle_follows = TRUE;
3705f7db5903SVitaliy Gusev else
3706f7db5903SVitaliy Gusev infop[i].fh.handle_follows = FALSE;
3707f7db5903SVitaliy Gusev }
37087c478bd9Sstevel@tonic-gate
37097c478bd9Sstevel@tonic-gate VN_RELE(nvp);
37107c478bd9Sstevel@tonic-gate dp = nextdp(dp);
37117c478bd9Sstevel@tonic-gate }
37127c478bd9Sstevel@tonic-gate
3713b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3714b89a8333Snatalie li - Sun Microsystems - Irvine United States ret = nfscmd_convdirplus(ca, exi, data, nents, args->dircount, &ndata);
3715b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ndata == NULL)
3716b89a8333Snatalie li - Sun Microsystems - Irvine United States ndata = data;
3717b89a8333Snatalie li - Sun Microsystems - Irvine United States
3718b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ret > 0) {
3719b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
3720b89a8333Snatalie li - Sun Microsystems - Irvine United States * We had to drop one or more entries in order to fit
3721b89a8333Snatalie li - Sun Microsystems - Irvine United States * during the character conversion. We need to patch
3722b89a8333Snatalie li - Sun Microsystems - Irvine United States * up the size and eof info.
3723b89a8333Snatalie li - Sun Microsystems - Irvine United States */
3724b89a8333Snatalie li - Sun Microsystems - Irvine United States if (iseof)
3725b89a8333Snatalie li - Sun Microsystems - Irvine United States iseof = FALSE;
3726b89a8333Snatalie li - Sun Microsystems - Irvine United States
3727b89a8333Snatalie li - Sun Microsystems - Irvine United States ret = nfscmd_dropped_entrysize((struct dirent64 *)data,
3728b89a8333Snatalie li - Sun Microsystems - Irvine United States nents, ret);
3729b89a8333Snatalie li - Sun Microsystems - Irvine United States }
3730b89a8333Snatalie li - Sun Microsystems - Irvine United States
3731b89a8333Snatalie li - Sun Microsystems - Irvine United States
37327c478bd9Sstevel@tonic-gate #if 0 /* notyet */
37337c478bd9Sstevel@tonic-gate /*
37347c478bd9Sstevel@tonic-gate * Don't do this. It causes local disk writes when just
37357c478bd9Sstevel@tonic-gate * reading the file and the overhead is deemed larger
37367c478bd9Sstevel@tonic-gate * than the benefit.
37377c478bd9Sstevel@tonic-gate */
37387c478bd9Sstevel@tonic-gate /*
37397c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
37407c478bd9Sstevel@tonic-gate */
3741da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
37427c478bd9Sstevel@tonic-gate #endif
37437c478bd9Sstevel@tonic-gate
37447c478bd9Sstevel@tonic-gate kmem_free(namlen, args->dircount);
3745*dfdcac05SMarcel Telka if (ndata != data)
3746*dfdcac05SMarcel Telka kmem_free(data, args->dircount);
37477c478bd9Sstevel@tonic-gate
37487c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
37497c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
37507c478bd9Sstevel@tonic-gate resp->resok.cookieverf = 0;
3751b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->resok.reply.entries = (entryplus3 *)ndata;
37527c478bd9Sstevel@tonic-gate resp->resok.reply.eof = iseof;
37537c478bd9Sstevel@tonic-gate resp->resok.size = nents;
3754b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->resok.count = args->dircount - ret;
37557c478bd9Sstevel@tonic-gate resp->resok.maxcount = args->maxcount;
3756e1adf50cSahl
37570dfe541eSEvan Layton DTRACE_NFSV3_5(op__readdirplus__done, struct svc_req *, req,
37580dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
37590dfe541eSEvan Layton READDIRPLUS3res *, resp);
3760e1adf50cSahl
3761e1adf50cSahl VN_RELE(vp);
3762e1adf50cSahl
37637c478bd9Sstevel@tonic-gate return;
37647c478bd9Sstevel@tonic-gate
37657c478bd9Sstevel@tonic-gate out:
37667c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
37677c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
37687c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
3769b89a8333Snatalie li - Sun Microsystems - Irvine United States } else {
37707c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
3771b89a8333Snatalie li - Sun Microsystems - Irvine United States }
37727c478bd9Sstevel@tonic-gate out1:
37730dfe541eSEvan Layton vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
37740dfe541eSEvan Layton
37750dfe541eSEvan Layton DTRACE_NFSV3_5(op__readdirplus__done, struct svc_req *, req,
37760dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
37770dfe541eSEvan Layton READDIRPLUS3res *, resp);
3778e1adf50cSahl
37797c478bd9Sstevel@tonic-gate if (vp != NULL) {
37807c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
37817c478bd9Sstevel@tonic-gate VN_RELE(vp);
37827c478bd9Sstevel@tonic-gate }
37837c478bd9Sstevel@tonic-gate
37847c478bd9Sstevel@tonic-gate if (namlen != NULL)
37857c478bd9Sstevel@tonic-gate kmem_free(namlen, args->dircount);
37867c478bd9Sstevel@tonic-gate }
37877c478bd9Sstevel@tonic-gate
378827242a7cSthurlow void *
rfs3_readdirplus_getfh(READDIRPLUS3args * args)37897c478bd9Sstevel@tonic-gate rfs3_readdirplus_getfh(READDIRPLUS3args *args)
37907c478bd9Sstevel@tonic-gate {
37917c478bd9Sstevel@tonic-gate
379227242a7cSthurlow return (&args->dir);
37937c478bd9Sstevel@tonic-gate }
37947c478bd9Sstevel@tonic-gate
37957c478bd9Sstevel@tonic-gate void
rfs3_readdirplus_free(READDIRPLUS3res * resp)37967c478bd9Sstevel@tonic-gate rfs3_readdirplus_free(READDIRPLUS3res *resp)
37977c478bd9Sstevel@tonic-gate {
37987c478bd9Sstevel@tonic-gate
37997c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK) {
38007c478bd9Sstevel@tonic-gate kmem_free(resp->resok.reply.entries, resp->resok.count);
38017c478bd9Sstevel@tonic-gate kmem_free(resp->resok.infop,
3802cfae96c2Sjwahlig resp->resok.size * sizeof (struct entryplus3_info));
38037c478bd9Sstevel@tonic-gate }
38047c478bd9Sstevel@tonic-gate }
38057c478bd9Sstevel@tonic-gate
38067c478bd9Sstevel@tonic-gate /* ARGSUSED */
38077c478bd9Sstevel@tonic-gate void
rfs3_fsstat(FSSTAT3args * args,FSSTAT3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)38087c478bd9Sstevel@tonic-gate rfs3_fsstat(FSSTAT3args *args, FSSTAT3res *resp, struct exportinfo *exi,
38095cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
38107c478bd9Sstevel@tonic-gate {
38117c478bd9Sstevel@tonic-gate int error;
38127c478bd9Sstevel@tonic-gate vnode_t *vp;
38137c478bd9Sstevel@tonic-gate struct vattr *vap;
38147c478bd9Sstevel@tonic-gate struct vattr va;
38157c478bd9Sstevel@tonic-gate struct statvfs64 sb;
38167c478bd9Sstevel@tonic-gate
38177c478bd9Sstevel@tonic-gate vap = NULL;
38187c478bd9Sstevel@tonic-gate
38197c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->fsroot, exi);
3820e1adf50cSahl
38210dfe541eSEvan Layton DTRACE_NFSV3_5(op__fsstat__start, struct svc_req *, req,
38220dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
38230dfe541eSEvan Layton FSSTAT3args *, args);
3824e1adf50cSahl
38257c478bd9Sstevel@tonic-gate if (vp == NULL) {
38267c478bd9Sstevel@tonic-gate error = ESTALE;
38277c478bd9Sstevel@tonic-gate goto out;
38287c478bd9Sstevel@tonic-gate }
38297c478bd9Sstevel@tonic-gate
383003986916Sjarrett if (is_system_labeled()) {
383103986916Sjarrett bslabel_t *clabel = req->rq_label;
383203986916Sjarrett
383303986916Sjarrett ASSERT(clabel != NULL);
383403986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opfsstat__clabel, char *,
383503986916Sjarrett "got client label from request(1)", struct svc_req *, req);
383603986916Sjarrett
383703986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3838bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3839bd6f1640SJarrett Lu exi)) {
384003986916Sjarrett resp->status = NFS3ERR_ACCES;
384103986916Sjarrett goto out1;
384203986916Sjarrett }
384303986916Sjarrett }
384403986916Sjarrett }
384503986916Sjarrett
38467c478bd9Sstevel@tonic-gate error = VFS_STATVFS(vp->v_vfsp, &sb);
38477c478bd9Sstevel@tonic-gate
38487c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3849da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
38507c478bd9Sstevel@tonic-gate
38517c478bd9Sstevel@tonic-gate if (error)
38527c478bd9Sstevel@tonic-gate goto out;
38537c478bd9Sstevel@tonic-gate
38547c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
38557c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
38567c478bd9Sstevel@tonic-gate if (sb.f_blocks != (fsblkcnt64_t)-1)
38577c478bd9Sstevel@tonic-gate resp->resok.tbytes = (size3)sb.f_frsize * (size3)sb.f_blocks;
38587c478bd9Sstevel@tonic-gate else
38597c478bd9Sstevel@tonic-gate resp->resok.tbytes = (size3)sb.f_blocks;
38607c478bd9Sstevel@tonic-gate if (sb.f_bfree != (fsblkcnt64_t)-1)
38617c478bd9Sstevel@tonic-gate resp->resok.fbytes = (size3)sb.f_frsize * (size3)sb.f_bfree;
38627c478bd9Sstevel@tonic-gate else
38637c478bd9Sstevel@tonic-gate resp->resok.fbytes = (size3)sb.f_bfree;
38647c478bd9Sstevel@tonic-gate if (sb.f_bavail != (fsblkcnt64_t)-1)
38657c478bd9Sstevel@tonic-gate resp->resok.abytes = (size3)sb.f_frsize * (size3)sb.f_bavail;
38667c478bd9Sstevel@tonic-gate else
38677c478bd9Sstevel@tonic-gate resp->resok.abytes = (size3)sb.f_bavail;
38687c478bd9Sstevel@tonic-gate resp->resok.tfiles = (size3)sb.f_files;
38697c478bd9Sstevel@tonic-gate resp->resok.ffiles = (size3)sb.f_ffree;
38707c478bd9Sstevel@tonic-gate resp->resok.afiles = (size3)sb.f_favail;
38717c478bd9Sstevel@tonic-gate resp->resok.invarsec = 0;
3872e1adf50cSahl
38730dfe541eSEvan Layton DTRACE_NFSV3_5(op__fsstat__done, struct svc_req *, req,
38740dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
38750dfe541eSEvan Layton FSSTAT3res *, resp);
3876e1adf50cSahl VN_RELE(vp);
3877e1adf50cSahl
38787c478bd9Sstevel@tonic-gate return;
38797c478bd9Sstevel@tonic-gate
38807c478bd9Sstevel@tonic-gate out:
38817c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
38827c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
38837c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
38847c478bd9Sstevel@tonic-gate } else
38857c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
388603986916Sjarrett out1:
38870dfe541eSEvan Layton DTRACE_NFSV3_5(op__fsstat__done, struct svc_req *, req,
38880dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
38890dfe541eSEvan Layton FSSTAT3res *, resp);
3890e1adf50cSahl
389103986916Sjarrett if (vp != NULL)
389203986916Sjarrett VN_RELE(vp);
38937c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
38947c478bd9Sstevel@tonic-gate }
38957c478bd9Sstevel@tonic-gate
389627242a7cSthurlow void *
rfs3_fsstat_getfh(FSSTAT3args * args)38977c478bd9Sstevel@tonic-gate rfs3_fsstat_getfh(FSSTAT3args *args)
38987c478bd9Sstevel@tonic-gate {
38997c478bd9Sstevel@tonic-gate
390027242a7cSthurlow return (&args->fsroot);
39017c478bd9Sstevel@tonic-gate }
39027c478bd9Sstevel@tonic-gate
39035cb0d679SMarcel Telka /* ARGSUSED */
39047c478bd9Sstevel@tonic-gate void
rfs3_fsinfo(FSINFO3args * args,FSINFO3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)39057c478bd9Sstevel@tonic-gate rfs3_fsinfo(FSINFO3args *args, FSINFO3res *resp, struct exportinfo *exi,
39065cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
39077c478bd9Sstevel@tonic-gate {
39087c478bd9Sstevel@tonic-gate vnode_t *vp;
39097c478bd9Sstevel@tonic-gate struct vattr *vap;
39107c478bd9Sstevel@tonic-gate struct vattr va;
39117c478bd9Sstevel@tonic-gate uint32_t xfer_size;
39127c478bd9Sstevel@tonic-gate ulong_t l = 0;
39137c478bd9Sstevel@tonic-gate int error;
39147c478bd9Sstevel@tonic-gate
39157c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->fsroot, exi);
3916e1adf50cSahl
39170dfe541eSEvan Layton DTRACE_NFSV3_5(op__fsinfo__start, struct svc_req *, req,
39180dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
39190dfe541eSEvan Layton FSINFO3args *, args);
3920e1adf50cSahl
39217c478bd9Sstevel@tonic-gate if (vp == NULL) {
39227c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
39237c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
39247c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
39257c478bd9Sstevel@tonic-gate } else
39267c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_STALE;
39277c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(NULL, &resp->resfail.obj_attributes);
3928e1adf50cSahl goto out;
39297c478bd9Sstevel@tonic-gate }
39307c478bd9Sstevel@tonic-gate
393103986916Sjarrett if (is_system_labeled()) {
393203986916Sjarrett bslabel_t *clabel = req->rq_label;
393303986916Sjarrett
393403986916Sjarrett ASSERT(clabel != NULL);
393503986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opfsinfo__clabel, char *,
393603986916Sjarrett "got client label from request(1)", struct svc_req *, req);
393703986916Sjarrett
393803986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3939bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3940bd6f1640SJarrett Lu exi)) {
394103986916Sjarrett resp->status = NFS3ERR_STALE;
394203986916Sjarrett vattr_to_post_op_attr(NULL,
394303986916Sjarrett &resp->resfail.obj_attributes);
3944e1adf50cSahl goto out;
394503986916Sjarrett }
394603986916Sjarrett }
394703986916Sjarrett }
394803986916Sjarrett
39497c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3950da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
39517c478bd9Sstevel@tonic-gate
39527c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
39537c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
39547c478bd9Sstevel@tonic-gate xfer_size = rfs3_tsize(req);
39557c478bd9Sstevel@tonic-gate resp->resok.rtmax = xfer_size;
39567c478bd9Sstevel@tonic-gate resp->resok.rtpref = xfer_size;
39577c478bd9Sstevel@tonic-gate resp->resok.rtmult = DEV_BSIZE;
39587c478bd9Sstevel@tonic-gate resp->resok.wtmax = xfer_size;
39597c478bd9Sstevel@tonic-gate resp->resok.wtpref = xfer_size;
39607c478bd9Sstevel@tonic-gate resp->resok.wtmult = DEV_BSIZE;
39617c478bd9Sstevel@tonic-gate resp->resok.dtpref = MAXBSIZE;
39627c478bd9Sstevel@tonic-gate
39637c478bd9Sstevel@tonic-gate /*
39647c478bd9Sstevel@tonic-gate * Large file spec: want maxfilesize based on limit of
39657c478bd9Sstevel@tonic-gate * underlying filesystem. We can guess 2^31-1 if need be.
39667c478bd9Sstevel@tonic-gate */
3967da6c28aaSamw error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
3968710f82c5SPiyush Shivam if (error) {
3969710f82c5SPiyush Shivam resp->status = puterrno3(error);
3970710f82c5SPiyush Shivam goto out;
3971710f82c5SPiyush Shivam }
39727c478bd9Sstevel@tonic-gate
3973710f82c5SPiyush Shivam /*
3974710f82c5SPiyush Shivam * If the underlying file system does not support _PC_FILESIZEBITS,
3975710f82c5SPiyush Shivam * return a reasonable default. Note that error code on VOP_PATHCONF
3976710f82c5SPiyush Shivam * will be 0, even if the underlying file system does not support
3977710f82c5SPiyush Shivam * _PC_FILESIZEBITS.
3978710f82c5SPiyush Shivam */
3979710f82c5SPiyush Shivam if (l == (ulong_t)-1) {
39807c478bd9Sstevel@tonic-gate resp->resok.maxfilesize = MAXOFF32_T;
3981710f82c5SPiyush Shivam } else {
3982710f82c5SPiyush Shivam if (l >= (sizeof (uint64_t) * 8))
3983710f82c5SPiyush Shivam resp->resok.maxfilesize = INT64_MAX;
3984710f82c5SPiyush Shivam else
3985710f82c5SPiyush Shivam resp->resok.maxfilesize = (1LL << (l-1)) - 1;
3986710f82c5SPiyush Shivam }
39877c478bd9Sstevel@tonic-gate
39887c478bd9Sstevel@tonic-gate resp->resok.time_delta.seconds = 0;
39897c478bd9Sstevel@tonic-gate resp->resok.time_delta.nseconds = 1000;
39907c478bd9Sstevel@tonic-gate resp->resok.properties = FSF3_LINK | FSF3_SYMLINK |
39917c478bd9Sstevel@tonic-gate FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
3992e1adf50cSahl
39930dfe541eSEvan Layton DTRACE_NFSV3_5(op__fsinfo__done, struct svc_req *, req,
39940dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
39950dfe541eSEvan Layton FSINFO3res *, resp);
3996e1adf50cSahl
3997e1adf50cSahl VN_RELE(vp);
3998e1adf50cSahl
3999e1adf50cSahl return;
4000e1adf50cSahl
4001e1adf50cSahl out:
40020dfe541eSEvan Layton DTRACE_NFSV3_5(op__fsinfo__done, struct svc_req *, req,
40030dfe541eSEvan Layton cred_t *, cr, vnode_t *, NULL, struct exportinfo *, exi,
40040dfe541eSEvan Layton FSINFO3res *, resp);
4005e1adf50cSahl if (vp != NULL)
4006e1adf50cSahl VN_RELE(vp);
40077c478bd9Sstevel@tonic-gate }
40087c478bd9Sstevel@tonic-gate
400927242a7cSthurlow void *
rfs3_fsinfo_getfh(FSINFO3args * args)40107c478bd9Sstevel@tonic-gate rfs3_fsinfo_getfh(FSINFO3args *args)
40117c478bd9Sstevel@tonic-gate {
401227242a7cSthurlow return (&args->fsroot);
40137c478bd9Sstevel@tonic-gate }
40147c478bd9Sstevel@tonic-gate
40157c478bd9Sstevel@tonic-gate /* ARGSUSED */
40167c478bd9Sstevel@tonic-gate void
rfs3_pathconf(PATHCONF3args * args,PATHCONF3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)40177c478bd9Sstevel@tonic-gate rfs3_pathconf(PATHCONF3args *args, PATHCONF3res *resp, struct exportinfo *exi,
40185cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
40197c478bd9Sstevel@tonic-gate {
40207c478bd9Sstevel@tonic-gate int error;
40217c478bd9Sstevel@tonic-gate vnode_t *vp;
40227c478bd9Sstevel@tonic-gate struct vattr *vap;
40237c478bd9Sstevel@tonic-gate struct vattr va;
40247c478bd9Sstevel@tonic-gate ulong_t val;
40257c478bd9Sstevel@tonic-gate
40267c478bd9Sstevel@tonic-gate vap = NULL;
40277c478bd9Sstevel@tonic-gate
40287c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
4029e1adf50cSahl
40300dfe541eSEvan Layton DTRACE_NFSV3_5(op__pathconf__start, struct svc_req *, req,
40310dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
40320dfe541eSEvan Layton PATHCONF3args *, args);
4033e1adf50cSahl
40347c478bd9Sstevel@tonic-gate if (vp == NULL) {
40357c478bd9Sstevel@tonic-gate error = ESTALE;
40367c478bd9Sstevel@tonic-gate goto out;
40377c478bd9Sstevel@tonic-gate }
40387c478bd9Sstevel@tonic-gate
403903986916Sjarrett if (is_system_labeled()) {
404003986916Sjarrett bslabel_t *clabel = req->rq_label;
404103986916Sjarrett
404203986916Sjarrett ASSERT(clabel != NULL);
404303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oppathconf__clabel, char *,
404403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
404503986916Sjarrett
404603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
4047bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
4048bd6f1640SJarrett Lu exi)) {
404903986916Sjarrett resp->status = NFS3ERR_ACCES;
405003986916Sjarrett goto out1;
405103986916Sjarrett }
405203986916Sjarrett }
405303986916Sjarrett }
405403986916Sjarrett
40557c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
4056da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
40577c478bd9Sstevel@tonic-gate
4058da6c28aaSamw error = VOP_PATHCONF(vp, _PC_LINK_MAX, &val, cr, NULL);
40597c478bd9Sstevel@tonic-gate if (error)
40607c478bd9Sstevel@tonic-gate goto out;
40617c478bd9Sstevel@tonic-gate resp->resok.info.link_max = (uint32)val;
40627c478bd9Sstevel@tonic-gate
4063da6c28aaSamw error = VOP_PATHCONF(vp, _PC_NAME_MAX, &val, cr, NULL);
40647c478bd9Sstevel@tonic-gate if (error)
40657c478bd9Sstevel@tonic-gate goto out;
40667c478bd9Sstevel@tonic-gate resp->resok.info.name_max = (uint32)val;
40677c478bd9Sstevel@tonic-gate
4068da6c28aaSamw error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &val, cr, NULL);
40697c478bd9Sstevel@tonic-gate if (error)
40707c478bd9Sstevel@tonic-gate goto out;
40717c478bd9Sstevel@tonic-gate if (val == 1)
40727c478bd9Sstevel@tonic-gate resp->resok.info.no_trunc = TRUE;
40737c478bd9Sstevel@tonic-gate else
40747c478bd9Sstevel@tonic-gate resp->resok.info.no_trunc = FALSE;
40757c478bd9Sstevel@tonic-gate
4076da6c28aaSamw error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &val, cr, NULL);
40777c478bd9Sstevel@tonic-gate if (error)
40787c478bd9Sstevel@tonic-gate goto out;
40797c478bd9Sstevel@tonic-gate if (val == 1)
40807c478bd9Sstevel@tonic-gate resp->resok.info.chown_restricted = TRUE;
40817c478bd9Sstevel@tonic-gate else
40827c478bd9Sstevel@tonic-gate resp->resok.info.chown_restricted = FALSE;
40837c478bd9Sstevel@tonic-gate
40847c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
40857c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
40867c478bd9Sstevel@tonic-gate resp->resok.info.case_insensitive = FALSE;
40877c478bd9Sstevel@tonic-gate resp->resok.info.case_preserving = TRUE;
40880dfe541eSEvan Layton DTRACE_NFSV3_5(op__pathconf__done, struct svc_req *, req,
40890dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
40900dfe541eSEvan Layton PATHCONF3res *, resp);
4091e1adf50cSahl VN_RELE(vp);
40927c478bd9Sstevel@tonic-gate return;
40937c478bd9Sstevel@tonic-gate
40947c478bd9Sstevel@tonic-gate out:
40957c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
40967c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
40977c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
40987c478bd9Sstevel@tonic-gate } else
40997c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
410003986916Sjarrett out1:
41010dfe541eSEvan Layton DTRACE_NFSV3_5(op__pathconf__done, struct svc_req *, req,
41020dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
41030dfe541eSEvan Layton PATHCONF3res *, resp);
41047c478bd9Sstevel@tonic-gate if (vp != NULL)
41057c478bd9Sstevel@tonic-gate VN_RELE(vp);
41067c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
41077c478bd9Sstevel@tonic-gate }
41087c478bd9Sstevel@tonic-gate
410927242a7cSthurlow void *
rfs3_pathconf_getfh(PATHCONF3args * args)41107c478bd9Sstevel@tonic-gate rfs3_pathconf_getfh(PATHCONF3args *args)
41117c478bd9Sstevel@tonic-gate {
41127c478bd9Sstevel@tonic-gate
411327242a7cSthurlow return (&args->object);
41147c478bd9Sstevel@tonic-gate }
41157c478bd9Sstevel@tonic-gate
41167c478bd9Sstevel@tonic-gate void
rfs3_commit(COMMIT3args * args,COMMIT3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)41177c478bd9Sstevel@tonic-gate rfs3_commit(COMMIT3args *args, COMMIT3res *resp, struct exportinfo *exi,
41185cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
41197c478bd9Sstevel@tonic-gate {
41200dfe541eSEvan Layton nfs3_srv_t *ns;
41217c478bd9Sstevel@tonic-gate int error;
41227c478bd9Sstevel@tonic-gate vnode_t *vp;
41237c478bd9Sstevel@tonic-gate struct vattr *bvap;
41247c478bd9Sstevel@tonic-gate struct vattr bva;
41257c478bd9Sstevel@tonic-gate struct vattr *avap;
41267c478bd9Sstevel@tonic-gate struct vattr ava;
41277c478bd9Sstevel@tonic-gate
41287c478bd9Sstevel@tonic-gate bvap = NULL;
41297c478bd9Sstevel@tonic-gate avap = NULL;
41307c478bd9Sstevel@tonic-gate
41317c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
4132e1adf50cSahl
41330dfe541eSEvan Layton DTRACE_NFSV3_5(op__commit__start, struct svc_req *, req,
41340dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
41350dfe541eSEvan Layton COMMIT3args *, args);
4136e1adf50cSahl
41377c478bd9Sstevel@tonic-gate if (vp == NULL) {
41387c478bd9Sstevel@tonic-gate error = ESTALE;
41397c478bd9Sstevel@tonic-gate goto out;
41407c478bd9Sstevel@tonic-gate }
41417c478bd9Sstevel@tonic-gate
41420dfe541eSEvan Layton ASSERT3U(curzone->zone_id, ==, exi->exi_zoneid); /* exi is non-NULL. */
41430dfe541eSEvan Layton ns = nfs3_get_srv();
41447c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
4145da6c28aaSamw error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
41467c478bd9Sstevel@tonic-gate
41477c478bd9Sstevel@tonic-gate /*
41487c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
41497c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
41507c478bd9Sstevel@tonic-gate */
41517c478bd9Sstevel@tonic-gate if (error)
41527c478bd9Sstevel@tonic-gate goto out;
41537c478bd9Sstevel@tonic-gate
41547c478bd9Sstevel@tonic-gate bvap = &bva;
41557c478bd9Sstevel@tonic-gate
41565cb0d679SMarcel Telka if (rdonly(ro, vp)) {
41577c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
41587c478bd9Sstevel@tonic-gate goto out1;
41597c478bd9Sstevel@tonic-gate }
41607c478bd9Sstevel@tonic-gate
41617c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) {
41627c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
41637c478bd9Sstevel@tonic-gate goto out1;
41647c478bd9Sstevel@tonic-gate }
41657c478bd9Sstevel@tonic-gate
416603986916Sjarrett if (is_system_labeled()) {
416703986916Sjarrett bslabel_t *clabel = req->rq_label;
416803986916Sjarrett
416903986916Sjarrett ASSERT(clabel != NULL);
417003986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opcommit__clabel, char *,
417103986916Sjarrett "got client label from request(1)", struct svc_req *, req);
417203986916Sjarrett
417303986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
4174bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4175bd6f1640SJarrett Lu exi)) {
417603986916Sjarrett resp->status = NFS3ERR_ACCES;
417703986916Sjarrett goto out1;
417803986916Sjarrett }
417903986916Sjarrett }
418003986916Sjarrett }
418103986916Sjarrett
41827c478bd9Sstevel@tonic-gate if (crgetuid(cr) != bva.va_uid &&
4183da6c28aaSamw (error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL)))
41847c478bd9Sstevel@tonic-gate goto out;
41857c478bd9Sstevel@tonic-gate
4186f63200e6SJeff A. Smith error = VOP_FSYNC(vp, FSYNC, cr, NULL);
41877c478bd9Sstevel@tonic-gate
41887c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
4189da6c28aaSamw avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
41907c478bd9Sstevel@tonic-gate
41917c478bd9Sstevel@tonic-gate if (error)
41927c478bd9Sstevel@tonic-gate goto out;
41937c478bd9Sstevel@tonic-gate
41947c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
41957c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
41960dfe541eSEvan Layton resp->resok.verf = ns->write3verf;
4197e1adf50cSahl
41980dfe541eSEvan Layton DTRACE_NFSV3_5(op__commit__done, struct svc_req *, req,
41990dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
42000dfe541eSEvan Layton COMMIT3res *, resp);
4201e1adf50cSahl
4202e1adf50cSahl VN_RELE(vp);
4203e1adf50cSahl
42047c478bd9Sstevel@tonic-gate return;
42057c478bd9Sstevel@tonic-gate
42067c478bd9Sstevel@tonic-gate out:
42077c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
42087c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
42097c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
42107c478bd9Sstevel@tonic-gate } else
42117c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
42127c478bd9Sstevel@tonic-gate out1:
42130dfe541eSEvan Layton DTRACE_NFSV3_5(op__commit__done, struct svc_req *, req,
42140dfe541eSEvan Layton cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
42150dfe541eSEvan Layton COMMIT3res *, resp);
4216e1adf50cSahl
42177c478bd9Sstevel@tonic-gate if (vp != NULL)
42187c478bd9Sstevel@tonic-gate VN_RELE(vp);
42197c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
42207c478bd9Sstevel@tonic-gate }
42217c478bd9Sstevel@tonic-gate
422227242a7cSthurlow void *
rfs3_commit_getfh(COMMIT3args * args)42237c478bd9Sstevel@tonic-gate rfs3_commit_getfh(COMMIT3args *args)
42247c478bd9Sstevel@tonic-gate {
42257c478bd9Sstevel@tonic-gate
422627242a7cSthurlow return (&args->file);
42277c478bd9Sstevel@tonic-gate }
42287c478bd9Sstevel@tonic-gate
42297c478bd9Sstevel@tonic-gate static int
sattr3_to_vattr(sattr3 * sap,struct vattr * vap)42307c478bd9Sstevel@tonic-gate sattr3_to_vattr(sattr3 *sap, struct vattr *vap)
42317c478bd9Sstevel@tonic-gate {
42327c478bd9Sstevel@tonic-gate
42337c478bd9Sstevel@tonic-gate vap->va_mask = 0;
42347c478bd9Sstevel@tonic-gate
42357c478bd9Sstevel@tonic-gate if (sap->mode.set_it) {
42367c478bd9Sstevel@tonic-gate vap->va_mode = (mode_t)sap->mode.mode;
42377c478bd9Sstevel@tonic-gate vap->va_mask |= AT_MODE;
42387c478bd9Sstevel@tonic-gate }
42397c478bd9Sstevel@tonic-gate if (sap->uid.set_it) {
42407c478bd9Sstevel@tonic-gate vap->va_uid = (uid_t)sap->uid.uid;
42417c478bd9Sstevel@tonic-gate vap->va_mask |= AT_UID;
42427c478bd9Sstevel@tonic-gate }
42437c478bd9Sstevel@tonic-gate if (sap->gid.set_it) {
42447c478bd9Sstevel@tonic-gate vap->va_gid = (gid_t)sap->gid.gid;
42457c478bd9Sstevel@tonic-gate vap->va_mask |= AT_GID;
42467c478bd9Sstevel@tonic-gate }
42477c478bd9Sstevel@tonic-gate if (sap->size.set_it) {
42487c478bd9Sstevel@tonic-gate if (sap->size.size > (size3)((u_longlong_t)-1))
42497c478bd9Sstevel@tonic-gate return (EINVAL);
42507c478bd9Sstevel@tonic-gate vap->va_size = sap->size.size;
42517c478bd9Sstevel@tonic-gate vap->va_mask |= AT_SIZE;
42527c478bd9Sstevel@tonic-gate }
42537c478bd9Sstevel@tonic-gate if (sap->atime.set_it == SET_TO_CLIENT_TIME) {
42547c478bd9Sstevel@tonic-gate #ifndef _LP64
42557c478bd9Sstevel@tonic-gate /* check time validity */
42567c478bd9Sstevel@tonic-gate if (!NFS3_TIME_OK(sap->atime.atime.seconds))
42577c478bd9Sstevel@tonic-gate return (EOVERFLOW);
42587c478bd9Sstevel@tonic-gate #endif
42597c478bd9Sstevel@tonic-gate /*
42607c478bd9Sstevel@tonic-gate * nfs protocol defines times as unsigned so don't extend sign,
42617c478bd9Sstevel@tonic-gate * unless sysadmin set nfs_allow_preepoch_time.
42627c478bd9Sstevel@tonic-gate */
42637c478bd9Sstevel@tonic-gate NFS_TIME_T_CONVERT(vap->va_atime.tv_sec,
4264cfae96c2Sjwahlig sap->atime.atime.seconds);
42657c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = (uint32_t)sap->atime.atime.nseconds;
42667c478bd9Sstevel@tonic-gate vap->va_mask |= AT_ATIME;
42677c478bd9Sstevel@tonic-gate } else if (sap->atime.set_it == SET_TO_SERVER_TIME) {
42687c478bd9Sstevel@tonic-gate gethrestime(&vap->va_atime);
42697c478bd9Sstevel@tonic-gate vap->va_mask |= AT_ATIME;
42707c478bd9Sstevel@tonic-gate }
42717c478bd9Sstevel@tonic-gate if (sap->mtime.set_it == SET_TO_CLIENT_TIME) {
42727c478bd9Sstevel@tonic-gate #ifndef _LP64
42737c478bd9Sstevel@tonic-gate /* check time validity */
42747c478bd9Sstevel@tonic-gate if (!NFS3_TIME_OK(sap->mtime.mtime.seconds))
42757c478bd9Sstevel@tonic-gate return (EOVERFLOW);
42767c478bd9Sstevel@tonic-gate #endif
42777c478bd9Sstevel@tonic-gate /*
42787c478bd9Sstevel@tonic-gate * nfs protocol defines times as unsigned so don't extend sign,
42797c478bd9Sstevel@tonic-gate * unless sysadmin set nfs_allow_preepoch_time.
42807c478bd9Sstevel@tonic-gate */
42817c478bd9Sstevel@tonic-gate NFS_TIME_T_CONVERT(vap->va_mtime.tv_sec,
4282cfae96c2Sjwahlig sap->mtime.mtime.seconds);
42837c478bd9Sstevel@tonic-gate vap->va_mtime.tv_nsec = (uint32_t)sap->mtime.mtime.nseconds;
42847c478bd9Sstevel@tonic-gate vap->va_mask |= AT_MTIME;
42857c478bd9Sstevel@tonic-gate } else if (sap->mtime.set_it == SET_TO_SERVER_TIME) {
42867c478bd9Sstevel@tonic-gate gethrestime(&vap->va_mtime);
42877c478bd9Sstevel@tonic-gate vap->va_mask |= AT_MTIME;
42887c478bd9Sstevel@tonic-gate }
42897c478bd9Sstevel@tonic-gate
42907c478bd9Sstevel@tonic-gate return (0);
42917c478bd9Sstevel@tonic-gate }
42927c478bd9Sstevel@tonic-gate
42930dfe541eSEvan Layton static const ftype3 vt_to_nf3[] = {
42947c478bd9Sstevel@tonic-gate 0, NF3REG, NF3DIR, NF3BLK, NF3CHR, NF3LNK, NF3FIFO, 0, 0, NF3SOCK, 0
42957c478bd9Sstevel@tonic-gate };
42967c478bd9Sstevel@tonic-gate
42977c478bd9Sstevel@tonic-gate static int
vattr_to_fattr3(struct vattr * vap,fattr3 * fap)42987c478bd9Sstevel@tonic-gate vattr_to_fattr3(struct vattr *vap, fattr3 *fap)
42997c478bd9Sstevel@tonic-gate {
43007c478bd9Sstevel@tonic-gate
43017c478bd9Sstevel@tonic-gate ASSERT(vap->va_type >= VNON && vap->va_type <= VBAD);
43027c478bd9Sstevel@tonic-gate /* Return error if time or size overflow */
43037c478bd9Sstevel@tonic-gate if (! (NFS_VAP_TIME_OK(vap) && NFS3_SIZE_OK(vap->va_size))) {
43047c478bd9Sstevel@tonic-gate return (EOVERFLOW);
43057c478bd9Sstevel@tonic-gate }
43067c478bd9Sstevel@tonic-gate fap->type = vt_to_nf3[vap->va_type];
43077c478bd9Sstevel@tonic-gate fap->mode = (mode3)(vap->va_mode & MODEMASK);
43087c478bd9Sstevel@tonic-gate fap->nlink = (uint32)vap->va_nlink;
43097c478bd9Sstevel@tonic-gate if (vap->va_uid == UID_NOBODY)
43107c478bd9Sstevel@tonic-gate fap->uid = (uid3)NFS_UID_NOBODY;
43117c478bd9Sstevel@tonic-gate else
43127c478bd9Sstevel@tonic-gate fap->uid = (uid3)vap->va_uid;
43137c478bd9Sstevel@tonic-gate if (vap->va_gid == GID_NOBODY)
43147c478bd9Sstevel@tonic-gate fap->gid = (gid3)NFS_GID_NOBODY;
43157c478bd9Sstevel@tonic-gate else
43167c478bd9Sstevel@tonic-gate fap->gid = (gid3)vap->va_gid;
43177c478bd9Sstevel@tonic-gate fap->size = (size3)vap->va_size;
43187c478bd9Sstevel@tonic-gate fap->used = (size3)DEV_BSIZE * (size3)vap->va_nblocks;
43197c478bd9Sstevel@tonic-gate fap->rdev.specdata1 = (uint32)getmajor(vap->va_rdev);
43207c478bd9Sstevel@tonic-gate fap->rdev.specdata2 = (uint32)getminor(vap->va_rdev);
43217c478bd9Sstevel@tonic-gate fap->fsid = (uint64)vap->va_fsid;
43227c478bd9Sstevel@tonic-gate fap->fileid = (fileid3)vap->va_nodeid;
43237c478bd9Sstevel@tonic-gate fap->atime.seconds = vap->va_atime.tv_sec;
43247c478bd9Sstevel@tonic-gate fap->atime.nseconds = vap->va_atime.tv_nsec;
43257c478bd9Sstevel@tonic-gate fap->mtime.seconds = vap->va_mtime.tv_sec;
43267c478bd9Sstevel@tonic-gate fap->mtime.nseconds = vap->va_mtime.tv_nsec;
43277c478bd9Sstevel@tonic-gate fap->ctime.seconds = vap->va_ctime.tv_sec;
43287c478bd9Sstevel@tonic-gate fap->ctime.nseconds = vap->va_ctime.tv_nsec;
43297c478bd9Sstevel@tonic-gate return (0);
43307c478bd9Sstevel@tonic-gate }
43317c478bd9Sstevel@tonic-gate
43327c478bd9Sstevel@tonic-gate static int
vattr_to_wcc_attr(struct vattr * vap,wcc_attr * wccap)43337c478bd9Sstevel@tonic-gate vattr_to_wcc_attr(struct vattr *vap, wcc_attr *wccap)
43347c478bd9Sstevel@tonic-gate {
43357c478bd9Sstevel@tonic-gate
43367c478bd9Sstevel@tonic-gate /* Return error if time or size overflow */
43370a701b1eSRobert Gordon if (!(NFS_TIME_T_OK(vap->va_mtime.tv_sec) &&
4338cfae96c2Sjwahlig NFS_TIME_T_OK(vap->va_ctime.tv_sec) &&
4339cfae96c2Sjwahlig NFS3_SIZE_OK(vap->va_size))) {
43407c478bd9Sstevel@tonic-gate return (EOVERFLOW);
43417c478bd9Sstevel@tonic-gate }
43427c478bd9Sstevel@tonic-gate wccap->size = (size3)vap->va_size;
43437c478bd9Sstevel@tonic-gate wccap->mtime.seconds = vap->va_mtime.tv_sec;
43447c478bd9Sstevel@tonic-gate wccap->mtime.nseconds = vap->va_mtime.tv_nsec;
43457c478bd9Sstevel@tonic-gate wccap->ctime.seconds = vap->va_ctime.tv_sec;
43467c478bd9Sstevel@tonic-gate wccap->ctime.nseconds = vap->va_ctime.tv_nsec;
43477c478bd9Sstevel@tonic-gate return (0);
43487c478bd9Sstevel@tonic-gate }
43497c478bd9Sstevel@tonic-gate
43507c478bd9Sstevel@tonic-gate static void
vattr_to_pre_op_attr(struct vattr * vap,pre_op_attr * poap)43517c478bd9Sstevel@tonic-gate vattr_to_pre_op_attr(struct vattr *vap, pre_op_attr *poap)
43527c478bd9Sstevel@tonic-gate {
43537c478bd9Sstevel@tonic-gate
43547c478bd9Sstevel@tonic-gate /* don't return attrs if time overflow */
43557c478bd9Sstevel@tonic-gate if ((vap != NULL) && !vattr_to_wcc_attr(vap, &poap->attr)) {
43567c478bd9Sstevel@tonic-gate poap->attributes = TRUE;
43577c478bd9Sstevel@tonic-gate } else
43587c478bd9Sstevel@tonic-gate poap->attributes = FALSE;
43597c478bd9Sstevel@tonic-gate }
43607c478bd9Sstevel@tonic-gate
43617c478bd9Sstevel@tonic-gate void
vattr_to_post_op_attr(struct vattr * vap,post_op_attr * poap)43627c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(struct vattr *vap, post_op_attr *poap)
43637c478bd9Sstevel@tonic-gate {
43647c478bd9Sstevel@tonic-gate
43657c478bd9Sstevel@tonic-gate /* don't return attrs if time overflow */
43667c478bd9Sstevel@tonic-gate if ((vap != NULL) && !vattr_to_fattr3(vap, &poap->attr)) {
43677c478bd9Sstevel@tonic-gate poap->attributes = TRUE;
43687c478bd9Sstevel@tonic-gate } else
43697c478bd9Sstevel@tonic-gate poap->attributes = FALSE;
43707c478bd9Sstevel@tonic-gate }
43717c478bd9Sstevel@tonic-gate
43727c478bd9Sstevel@tonic-gate static void
vattr_to_wcc_data(struct vattr * bvap,struct vattr * avap,wcc_data * wccp)43737c478bd9Sstevel@tonic-gate vattr_to_wcc_data(struct vattr *bvap, struct vattr *avap, wcc_data *wccp)
43747c478bd9Sstevel@tonic-gate {
43757c478bd9Sstevel@tonic-gate vattr_to_pre_op_attr(bvap, &wccp->before);
43767c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(avap, &wccp->after);
43777c478bd9Sstevel@tonic-gate }
43787c478bd9Sstevel@tonic-gate
43790dfe541eSEvan Layton static int
rdma_setup_read_data3(READ3args * args,READ3resok * rok)43800dfe541eSEvan Layton rdma_setup_read_data3(READ3args *args, READ3resok *rok)
43810dfe541eSEvan Layton {
43820dfe541eSEvan Layton struct clist *wcl;
43830dfe541eSEvan Layton int wlist_len;
43840dfe541eSEvan Layton count3 count = rok->count;
43850dfe541eSEvan Layton
43860dfe541eSEvan Layton wcl = args->wlist;
43870dfe541eSEvan Layton if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE)
43880dfe541eSEvan Layton return (FALSE);
43890dfe541eSEvan Layton
43900dfe541eSEvan Layton wcl = args->wlist;
43910dfe541eSEvan Layton rok->wlist_len = wlist_len;
43920dfe541eSEvan Layton rok->wlist = wcl;
43930dfe541eSEvan Layton return (TRUE);
43940dfe541eSEvan Layton }
43950dfe541eSEvan Layton
43967c478bd9Sstevel@tonic-gate void
rfs3_srv_zone_init(nfs_globals_t * ng)43970dfe541eSEvan Layton rfs3_srv_zone_init(nfs_globals_t *ng)
43987c478bd9Sstevel@tonic-gate {
43990dfe541eSEvan Layton nfs3_srv_t *ns;
44007c478bd9Sstevel@tonic-gate struct rfs3_verf_overlay {
44017c478bd9Sstevel@tonic-gate uint_t id; /* a "unique" identifier */
44027c478bd9Sstevel@tonic-gate int ts; /* a unique timestamp */
44037c478bd9Sstevel@tonic-gate } *verfp;
44047c478bd9Sstevel@tonic-gate timestruc_t now;
44057c478bd9Sstevel@tonic-gate
44060dfe541eSEvan Layton ns = kmem_zalloc(sizeof (*ns), KM_SLEEP);
44070dfe541eSEvan Layton
44087c478bd9Sstevel@tonic-gate /*
44097c478bd9Sstevel@tonic-gate * The following algorithm attempts to find a unique verifier
44107c478bd9Sstevel@tonic-gate * to be used as the write verifier returned from the server
44117c478bd9Sstevel@tonic-gate * to the client. It is important that this verifier change
44127c478bd9Sstevel@tonic-gate * whenever the server reboots. Of secondary importance, it
44137c478bd9Sstevel@tonic-gate * is important for the verifier to be unique between two
44147c478bd9Sstevel@tonic-gate * different servers.
44157c478bd9Sstevel@tonic-gate *
44167c478bd9Sstevel@tonic-gate * Thus, an attempt is made to use the system hostid and the
44177c478bd9Sstevel@tonic-gate * current time in seconds when the nfssrv kernel module is
44187c478bd9Sstevel@tonic-gate * loaded. It is assumed that an NFS server will not be able
44197c478bd9Sstevel@tonic-gate * to boot and then to reboot in less than a second. If the
44207c478bd9Sstevel@tonic-gate * hostid has not been set, then the current high resolution
44217c478bd9Sstevel@tonic-gate * time is used. This will ensure different verifiers each
44227c478bd9Sstevel@tonic-gate * time the server reboots and minimize the chances that two
44237c478bd9Sstevel@tonic-gate * different servers will have the same verifier.
44247c478bd9Sstevel@tonic-gate */
44257c478bd9Sstevel@tonic-gate
44267c478bd9Sstevel@tonic-gate #ifndef lint
44277c478bd9Sstevel@tonic-gate /*
44287c478bd9Sstevel@tonic-gate * We ASSERT that this constant logic expression is
44297c478bd9Sstevel@tonic-gate * always true because in the past, it wasn't.
44307c478bd9Sstevel@tonic-gate */
44310dfe541eSEvan Layton ASSERT(sizeof (*verfp) <= sizeof (ns->write3verf));
44327c478bd9Sstevel@tonic-gate #endif
44337c478bd9Sstevel@tonic-gate
44347c478bd9Sstevel@tonic-gate gethrestime(&now);
44350dfe541eSEvan Layton verfp = (struct rfs3_verf_overlay *)&ns->write3verf;
44367c478bd9Sstevel@tonic-gate verfp->ts = (int)now.tv_sec;
44375679c89fSjv verfp->id = zone_get_hostid(NULL);
44387c478bd9Sstevel@tonic-gate
44397c478bd9Sstevel@tonic-gate if (verfp->id == 0)
44407c478bd9Sstevel@tonic-gate verfp->id = (uint_t)now.tv_nsec;
44417c478bd9Sstevel@tonic-gate
44420dfe541eSEvan Layton ng->nfs3_srv = ns;
44437c478bd9Sstevel@tonic-gate }
44447c478bd9Sstevel@tonic-gate
44450dfe541eSEvan Layton void
rfs3_srv_zone_fini(nfs_globals_t * ng)44460dfe541eSEvan Layton rfs3_srv_zone_fini(nfs_globals_t *ng)
44470a701b1eSRobert Gordon {
44480dfe541eSEvan Layton nfs3_srv_t *ns = ng->nfs3_srv;
44490a701b1eSRobert Gordon
44500dfe541eSEvan Layton ng->nfs3_srv = NULL;
44510a701b1eSRobert Gordon
44520dfe541eSEvan Layton kmem_free(ns, sizeof (*ns));
44530dfe541eSEvan Layton }
44540dfe541eSEvan Layton
44550dfe541eSEvan Layton void
rfs3_srvrinit(void)44560dfe541eSEvan Layton rfs3_srvrinit(void)
44570dfe541eSEvan Layton {
44580dfe541eSEvan Layton nfs3_srv_caller_id = fs_new_caller_id();
44590a701b1eSRobert Gordon }
44600a701b1eSRobert Gordon
44617c478bd9Sstevel@tonic-gate void
rfs3_srvrfini(void)44627c478bd9Sstevel@tonic-gate rfs3_srvrfini(void)
44637c478bd9Sstevel@tonic-gate {
44647c478bd9Sstevel@tonic-gate /* Nothing to do */
44657c478bd9Sstevel@tonic-gate }
4466