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 /*
23f46abf18SMarcel Telka * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
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
317c478bd9Sstevel@tonic-gate #include <sys/param.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/systm.h>
347c478bd9Sstevel@tonic-gate #include <sys/cred.h>
357c478bd9Sstevel@tonic-gate #include <sys/buf.h>
367c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
377c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
387c478bd9Sstevel@tonic-gate #include <sys/uio.h>
397c478bd9Sstevel@tonic-gate #include <sys/errno.h>
407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
417c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
427c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
437c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
447c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
457c478bd9Sstevel@tonic-gate #include <sys/debug.h>
467c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
477c478bd9Sstevel@tonic-gate #include <sys/flock.h>
487c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h>
497c478bd9Sstevel@tonic-gate #include <sys/policy.h>
5003986916Sjarrett #include <sys/sdt.h>
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #include <rpc/types.h>
537c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
547c478bd9Sstevel@tonic-gate #include <rpc/svc.h>
550a701b1eSRobert Gordon #include <rpc/rpc_rdma.h>
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
587c478bd9Sstevel@tonic-gate #include <nfs/export.h>
59b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <nfs/nfs_cmd.h>
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
6203986916Sjarrett #include <sys/tsol/label.h>
6303986916Sjarrett #include <sys/tsol/tndb.h>
6403986916Sjarrett
655679c89fSjv227347 #include <sys/zone.h>
665679c89fSjv227347
6703986916Sjarrett #include <inet/ip.h>
6803986916Sjarrett #include <inet/ip6.h>
6903986916Sjarrett
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate * These are the interface routines for the server side of the
727c478bd9Sstevel@tonic-gate * Network File System. See the NFS version 3 protocol specification
737c478bd9Sstevel@tonic-gate * for a description of this interface.
747c478bd9Sstevel@tonic-gate */
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate static writeverf3 write3verf;
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate static int sattr3_to_vattr(sattr3 *, struct vattr *);
797c478bd9Sstevel@tonic-gate static int vattr_to_fattr3(struct vattr *, fattr3 *);
807c478bd9Sstevel@tonic-gate static int vattr_to_wcc_attr(struct vattr *, wcc_attr *);
817c478bd9Sstevel@tonic-gate static void vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
827c478bd9Sstevel@tonic-gate static void vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
830a701b1eSRobert Gordon static int rdma_setup_read_data3(READ3args *, READ3resok *);
847c478bd9Sstevel@tonic-gate
85c242f9a0Schunli zhang - Sun Microsystems - Irvine United States extern int nfs_loaned_buffers;
86c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
87cfae96c2Sjwahlig u_longlong_t nfs3_srv_caller_id;
88cfae96c2Sjwahlig
897c478bd9Sstevel@tonic-gate /* ARGSUSED */
907c478bd9Sstevel@tonic-gate void
rfs3_getattr(GETATTR3args * args,GETATTR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)917c478bd9Sstevel@tonic-gate rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
925cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate int error;
957c478bd9Sstevel@tonic-gate vnode_t *vp;
967c478bd9Sstevel@tonic-gate struct vattr va;
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
99e1adf50cSahl
100e1adf50cSahl DTRACE_NFSV3_4(op__getattr__start, struct svc_req *, req,
101e1adf50cSahl cred_t *, cr, vnode_t *, vp, GETATTR3args *, args);
102e1adf50cSahl
1037c478bd9Sstevel@tonic-gate if (vp == NULL) {
1047c478bd9Sstevel@tonic-gate error = ESTALE;
1057c478bd9Sstevel@tonic-gate goto out;
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1097c478bd9Sstevel@tonic-gate error = rfs4_delegated_getattr(vp, &va, 0, cr);
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate if (!error) {
1122f172c55SRobert Thurlow /* Lie about the object type for a referral */
1132f172c55SRobert Thurlow if (vn_is_nfs_reparse(vp, cr))
1142f172c55SRobert Thurlow va.va_type = VLNK;
1152f172c55SRobert Thurlow
1167c478bd9Sstevel@tonic-gate /* overflow error if time or size is out of range */
1177c478bd9Sstevel@tonic-gate error = vattr_to_fattr3(&va, &resp->resok.obj_attributes);
1187c478bd9Sstevel@tonic-gate if (error)
1197c478bd9Sstevel@tonic-gate goto out;
1207c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
121e1adf50cSahl
122e1adf50cSahl DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
123e1adf50cSahl cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
124e1adf50cSahl
125e1adf50cSahl VN_RELE(vp);
126e1adf50cSahl
1277c478bd9Sstevel@tonic-gate return;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate out:
1317c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
1327c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
1337c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
1347c478bd9Sstevel@tonic-gate } else
1357c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
136e1adf50cSahl
137e1adf50cSahl DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
138e1adf50cSahl cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
139e1adf50cSahl
140e1adf50cSahl if (vp != NULL)
141e1adf50cSahl VN_RELE(vp);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
14427242a7cSthurlow void *
rfs3_getattr_getfh(GETATTR3args * args)1457c478bd9Sstevel@tonic-gate rfs3_getattr_getfh(GETATTR3args *args)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate
14827242a7cSthurlow return (&args->object);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate void
rfs3_setattr(SETATTR3args * args,SETATTR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)1527c478bd9Sstevel@tonic-gate rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
1535cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate int error;
1567c478bd9Sstevel@tonic-gate vnode_t *vp;
1577c478bd9Sstevel@tonic-gate struct vattr *bvap;
1587c478bd9Sstevel@tonic-gate struct vattr bva;
1597c478bd9Sstevel@tonic-gate struct vattr *avap;
1607c478bd9Sstevel@tonic-gate struct vattr ava;
1617c478bd9Sstevel@tonic-gate int flag;
1627c478bd9Sstevel@tonic-gate int in_crit = 0;
1637c478bd9Sstevel@tonic-gate struct flock64 bf;
164cfae96c2Sjwahlig caller_context_t ct;
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate bvap = NULL;
1677c478bd9Sstevel@tonic-gate avap = NULL;
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
170e1adf50cSahl
171e1adf50cSahl DTRACE_NFSV3_4(op__setattr__start, struct svc_req *, req,
172e1adf50cSahl cred_t *, cr, vnode_t *, vp, SETATTR3args *, args);
173e1adf50cSahl
1747c478bd9Sstevel@tonic-gate if (vp == NULL) {
1757c478bd9Sstevel@tonic-gate error = ESTALE;
1767c478bd9Sstevel@tonic-gate goto out;
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->new_attributes, &ava);
1807c478bd9Sstevel@tonic-gate if (error)
1817c478bd9Sstevel@tonic-gate goto out;
1827c478bd9Sstevel@tonic-gate
18303986916Sjarrett if (is_system_labeled()) {
18403986916Sjarrett bslabel_t *clabel = req->rq_label;
18503986916Sjarrett
18603986916Sjarrett ASSERT(clabel != NULL);
18703986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opsetattr__clabel, char *,
18803986916Sjarrett "got client label from request(1)", struct svc_req *, req);
18903986916Sjarrett
19003986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
191bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
192bd6f1640SJarrett Lu exi)) {
19303986916Sjarrett resp->status = NFS3ERR_ACCES;
19403986916Sjarrett goto out1;
19503986916Sjarrett }
19603986916Sjarrett }
19703986916Sjarrett }
19803986916Sjarrett
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate * We need to specially handle size changes because of
2017c478bd9Sstevel@tonic-gate * possible conflicting NBMAND locks. Get into critical
2027c478bd9Sstevel@tonic-gate * region before VOP_GETATTR, so the size attribute is
2037c478bd9Sstevel@tonic-gate * valid when checking conflicts.
2047c478bd9Sstevel@tonic-gate *
2057c478bd9Sstevel@tonic-gate * Also, check to see if the v4 side of the server has
2067c478bd9Sstevel@tonic-gate * delegated this file. If so, then we return JUKEBOX to
2077c478bd9Sstevel@tonic-gate * allow the client to retrasmit its request.
2087c478bd9Sstevel@tonic-gate */
2097c478bd9Sstevel@tonic-gate if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
2107c478bd9Sstevel@tonic-gate if (nbl_need_check(vp)) {
2117c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_READER);
2127c478bd9Sstevel@tonic-gate in_crit = 1;
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
2177c478bd9Sstevel@tonic-gate error = rfs4_delegated_getattr(vp, &bva, 0, cr);
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
2217c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
2227c478bd9Sstevel@tonic-gate */
2237c478bd9Sstevel@tonic-gate if (error)
2247c478bd9Sstevel@tonic-gate goto out;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate bvap = &bva;
2277c478bd9Sstevel@tonic-gate
2285cb0d679SMarcel Telka if (rdonly(ro, vp)) {
2297c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2307c478bd9Sstevel@tonic-gate goto out1;
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate if (args->guard.check &&
2347c478bd9Sstevel@tonic-gate (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
2357c478bd9Sstevel@tonic-gate args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
2367c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOT_SYNC;
2377c478bd9Sstevel@tonic-gate goto out1;
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
2417c478bd9Sstevel@tonic-gate flag = ATTR_UTIME;
2427c478bd9Sstevel@tonic-gate else
2437c478bd9Sstevel@tonic-gate flag = 0;
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate * If the filesystem is exported with nosuid, then mask off
2477c478bd9Sstevel@tonic-gate * the setuid and setgid bits.
2487c478bd9Sstevel@tonic-gate */
2497c478bd9Sstevel@tonic-gate if ((ava.va_mask & AT_MODE) && vp->v_type == VREG &&
2507c478bd9Sstevel@tonic-gate (exi->exi_export.ex_flags & EX_NOSUID))
2517c478bd9Sstevel@tonic-gate ava.va_mode &= ~(VSUID | VSGID);
2527c478bd9Sstevel@tonic-gate
253cfae96c2Sjwahlig ct.cc_sysid = 0;
254cfae96c2Sjwahlig ct.cc_pid = 0;
255cfae96c2Sjwahlig ct.cc_caller_id = nfs3_srv_caller_id;
256cfae96c2Sjwahlig ct.cc_flags = CC_DONTBLOCK;
257cfae96c2Sjwahlig
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate * We need to specially handle size changes because it is
2607c478bd9Sstevel@tonic-gate * possible for the client to create a file with modes
2617c478bd9Sstevel@tonic-gate * which indicate read-only, but with the file opened for
2627c478bd9Sstevel@tonic-gate * writing. If the client then tries to set the size of
2637c478bd9Sstevel@tonic-gate * the file, then the normal access checking done in
2647c478bd9Sstevel@tonic-gate * VOP_SETATTR would prevent the client from doing so,
2657c478bd9Sstevel@tonic-gate * although it should be legal for it to do so. To get
2667c478bd9Sstevel@tonic-gate * around this, we do the access checking for ourselves
2677c478bd9Sstevel@tonic-gate * and then use VOP_SPACE which doesn't do the access
2687c478bd9Sstevel@tonic-gate * checking which VOP_SETATTR does. VOP_SPACE can only
2697c478bd9Sstevel@tonic-gate * operate on VREG files, let VOP_SETATTR handle the other
2707c478bd9Sstevel@tonic-gate * extremely rare cases.
2717c478bd9Sstevel@tonic-gate * Also the client should not be allowed to change the
2727c478bd9Sstevel@tonic-gate * size of the file if there is a conflicting non-blocking
2737c478bd9Sstevel@tonic-gate * mandatory lock in the region the change.
2747c478bd9Sstevel@tonic-gate */
2757c478bd9Sstevel@tonic-gate if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
2767c478bd9Sstevel@tonic-gate if (in_crit) {
2777c478bd9Sstevel@tonic-gate u_offset_t offset;
2787c478bd9Sstevel@tonic-gate ssize_t length;
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate if (ava.va_size < bva.va_size) {
2817c478bd9Sstevel@tonic-gate offset = ava.va_size;
2827c478bd9Sstevel@tonic-gate length = bva.va_size - ava.va_size;
2837c478bd9Sstevel@tonic-gate } else {
2847c478bd9Sstevel@tonic-gate offset = bva.va_size;
2857c478bd9Sstevel@tonic-gate length = ava.va_size - bva.va_size;
2867c478bd9Sstevel@tonic-gate }
287da6c28aaSamw if (nbl_conflict(vp, NBL_WRITE, offset, length, 0,
288da6c28aaSamw NULL)) {
2897c478bd9Sstevel@tonic-gate error = EACCES;
2907c478bd9Sstevel@tonic-gate goto out;
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate if (crgetuid(cr) == bva.va_uid && ava.va_size != bva.va_size) {
2957c478bd9Sstevel@tonic-gate ava.va_mask &= ~AT_SIZE;
2967c478bd9Sstevel@tonic-gate bf.l_type = F_WRLCK;
2977c478bd9Sstevel@tonic-gate bf.l_whence = 0;
2987c478bd9Sstevel@tonic-gate bf.l_start = (off64_t)ava.va_size;
2997c478bd9Sstevel@tonic-gate bf.l_len = 0;
3007c478bd9Sstevel@tonic-gate bf.l_sysid = 0;
3017c478bd9Sstevel@tonic-gate bf.l_pid = 0;
3027c478bd9Sstevel@tonic-gate error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
303cfae96c2Sjwahlig (offset_t)ava.va_size, cr, &ct);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate if (!error && ava.va_mask)
308cfae96c2Sjwahlig error = VOP_SETATTR(vp, &ava, flag, cr, &ct);
309cfae96c2Sjwahlig
310cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
311cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
312cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
313cfae96c2Sjwahlig goto out1;
314cfae96c2Sjwahlig }
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
3177c478bd9Sstevel@tonic-gate avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
3217c478bd9Sstevel@tonic-gate */
322cfae96c2Sjwahlig (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate if (error)
3257c478bd9Sstevel@tonic-gate goto out;
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate if (in_crit)
3287c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
3317c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
332e1adf50cSahl
333e1adf50cSahl DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
334e1adf50cSahl cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
335e1adf50cSahl
336e1adf50cSahl VN_RELE(vp);
337e1adf50cSahl
3387c478bd9Sstevel@tonic-gate return;
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate out:
3417c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
3427c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
3437c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
3447c478bd9Sstevel@tonic-gate } else
3457c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
3467c478bd9Sstevel@tonic-gate out1:
347e1adf50cSahl DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
348e1adf50cSahl cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
349e1adf50cSahl
3507c478bd9Sstevel@tonic-gate if (vp != NULL) {
3517c478bd9Sstevel@tonic-gate if (in_crit)
3527c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
3537c478bd9Sstevel@tonic-gate VN_RELE(vp);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resfail.obj_wcc);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
35827242a7cSthurlow void *
rfs3_setattr_getfh(SETATTR3args * args)3597c478bd9Sstevel@tonic-gate rfs3_setattr_getfh(SETATTR3args *args)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate
36227242a7cSthurlow return (&args->object);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate /* ARGSUSED */
3667c478bd9Sstevel@tonic-gate void
rfs3_lookup(LOOKUP3args * args,LOOKUP3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)3677c478bd9Sstevel@tonic-gate rfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi,
3685cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate int error;
3717c478bd9Sstevel@tonic-gate vnode_t *vp;
3727c478bd9Sstevel@tonic-gate vnode_t *dvp;
3737c478bd9Sstevel@tonic-gate struct vattr *vap;
3747c478bd9Sstevel@tonic-gate struct vattr va;
3757c478bd9Sstevel@tonic-gate struct vattr *dvap;
3767c478bd9Sstevel@tonic-gate struct vattr dva;
3777c478bd9Sstevel@tonic-gate nfs_fh3 *fhp;
3787c478bd9Sstevel@tonic-gate struct sec_ol sec = {0, 0};
3797c478bd9Sstevel@tonic-gate bool_t publicfh_flag = FALSE, auth_weak = FALSE;
380b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
381b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate dvap = NULL;
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate * Allow lookups from the root - the default
3877c478bd9Sstevel@tonic-gate * location of the public filehandle.
3887c478bd9Sstevel@tonic-gate */
3897c478bd9Sstevel@tonic-gate if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
3907c478bd9Sstevel@tonic-gate dvp = rootdir;
3917c478bd9Sstevel@tonic-gate VN_HOLD(dvp);
392e1adf50cSahl
393e1adf50cSahl DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
394e1adf50cSahl cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
3957c478bd9Sstevel@tonic-gate } else {
39627242a7cSthurlow dvp = nfs3_fhtovp(&args->what.dir, exi);
397e1adf50cSahl
398e1adf50cSahl DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
399e1adf50cSahl cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
400e1adf50cSahl
4017c478bd9Sstevel@tonic-gate if (dvp == NULL) {
4027c478bd9Sstevel@tonic-gate error = ESTALE;
4037c478bd9Sstevel@tonic-gate goto out;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate dva.va_mask = AT_ALL;
408da6c28aaSamw dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate if (args->what.name == nfs3nametoolong) {
4117c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
4127c478bd9Sstevel@tonic-gate goto out1;
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate if (args->what.name == NULL || *(args->what.name) == '\0') {
4167c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
4177c478bd9Sstevel@tonic-gate goto out1;
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate
42027242a7cSthurlow fhp = &args->what.dir;
4217c478bd9Sstevel@tonic-gate if (strcmp(args->what.name, "..") == 0 &&
42227242a7cSthurlow EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
4237c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOENT;
4247c478bd9Sstevel@tonic-gate goto out1;
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate
427b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
428b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->what.name,
429b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
430b89a8333Snatalie li - Sun Microsystems - Irvine United States
431b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
432b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_ACCES;
433b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
434b89a8333Snatalie li - Sun Microsystems - Irvine United States }
435b89a8333Snatalie li - Sun Microsystems - Irvine United States
4367c478bd9Sstevel@tonic-gate /*
4377c478bd9Sstevel@tonic-gate * If the public filehandle is used then allow
4387c478bd9Sstevel@tonic-gate * a multi-component lookup
4397c478bd9Sstevel@tonic-gate */
44027242a7cSthurlow if (PUBLIC_FH3(&args->what.dir)) {
4417c478bd9Sstevel@tonic-gate publicfh_flag = TRUE;
442b89a8333Snatalie li - Sun Microsystems - Irvine United States error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
443596bc239SMarcel Telka &exi, &sec);
444596bc239SMarcel Telka if (error && exi != NULL)
445596bc239SMarcel Telka exi_rele(exi); /* See comment below Re: publicfh_flag */
44603986916Sjarrett /*
44703986916Sjarrett * Since WebNFS may bypass MOUNT, we need to ensure this
44803986916Sjarrett * request didn't come from an unlabeled admin_low client.
44903986916Sjarrett */
45003986916Sjarrett if (is_system_labeled() && error == 0) {
45103986916Sjarrett int addr_type;
45203986916Sjarrett void *ipaddr;
45303986916Sjarrett tsol_tpc_t *tp;
45403986916Sjarrett
45503986916Sjarrett if (ca->sa_family == AF_INET) {
45603986916Sjarrett addr_type = IPV4_VERSION;
45703986916Sjarrett ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
45803986916Sjarrett } else if (ca->sa_family == AF_INET6) {
45903986916Sjarrett addr_type = IPV6_VERSION;
46003986916Sjarrett ipaddr = &((struct sockaddr_in6 *)
46103986916Sjarrett ca)->sin6_addr;
46203986916Sjarrett }
46303986916Sjarrett tp = find_tpc(ipaddr, addr_type, B_FALSE);
46403986916Sjarrett if (tp == NULL || tp->tpc_tp.tp_doi !=
46503986916Sjarrett l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
46603986916Sjarrett SUN_CIPSO) {
467596bc239SMarcel Telka if (exi != NULL)
468596bc239SMarcel Telka exi_rele(exi);
46903986916Sjarrett VN_RELE(vp);
470f46abf18SMarcel Telka error = EACCES;
47103986916Sjarrett }
47203986916Sjarrett if (tp != NULL)
47303986916Sjarrett TPC_RELE(tp);
47403986916Sjarrett }
4757c478bd9Sstevel@tonic-gate } else {
476b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &vp,
477da6c28aaSamw NULL, 0, NULL, cr, NULL, NULL, NULL);
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate
480b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->what.name)
481b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
482b89a8333Snatalie li - Sun Microsystems - Irvine United States
48303986916Sjarrett if (is_system_labeled() && error == 0) {
48403986916Sjarrett bslabel_t *clabel = req->rq_label;
48503986916Sjarrett
48603986916Sjarrett ASSERT(clabel != NULL);
48703986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
48803986916Sjarrett "got client label from request(1)", struct svc_req *, req);
48903986916Sjarrett
49003986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
49103986916Sjarrett if (!do_rfs_label_check(clabel, dvp,
492bd6f1640SJarrett Lu DOMINANCE_CHECK, exi)) {
493596bc239SMarcel Telka if (publicfh_flag && exi != NULL)
494596bc239SMarcel Telka exi_rele(exi);
49503986916Sjarrett VN_RELE(vp);
496f46abf18SMarcel Telka error = EACCES;
49703986916Sjarrett }
49803986916Sjarrett }
49903986916Sjarrett }
50003986916Sjarrett
5017c478bd9Sstevel@tonic-gate dva.va_mask = AT_ALL;
502da6c28aaSamw dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate if (error)
5057c478bd9Sstevel@tonic-gate goto out;
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate if (sec.sec_flags & SEC_QUERY) {
5087c478bd9Sstevel@tonic-gate error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
5097c478bd9Sstevel@tonic-gate } else {
5107c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.object, vp, exi);
5117c478bd9Sstevel@tonic-gate if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
5127c478bd9Sstevel@tonic-gate auth_weak = TRUE;
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate
515596bc239SMarcel Telka /*
516596bc239SMarcel Telka * If publicfh_flag is true then we have called rfs_publicfh_mclookup
517596bc239SMarcel Telka * and have obtained a new exportinfo in exi which needs to be
518fd9d0a82SMarcel Telka * released. Note that the original exportinfo pointed to by exi
519596bc239SMarcel Telka * will be released by the caller, common_dispatch.
520596bc239SMarcel Telka */
521596bc239SMarcel Telka if (publicfh_flag)
522596bc239SMarcel Telka exi_rele(exi);
523596bc239SMarcel Telka
524fd9d0a82SMarcel Telka if (error) {
525fd9d0a82SMarcel Telka VN_RELE(vp);
526fd9d0a82SMarcel Telka goto out;
527fd9d0a82SMarcel Telka }
528fd9d0a82SMarcel Telka
5297c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
5307c478bd9Sstevel@tonic-gate vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate VN_RELE(vp);
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
5357c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
5367c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate /*
5397c478bd9Sstevel@tonic-gate * If it's public fh, no 0x81, and client's flavor is
5407c478bd9Sstevel@tonic-gate * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
5417c478bd9Sstevel@tonic-gate * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
5427c478bd9Sstevel@tonic-gate */
5437c478bd9Sstevel@tonic-gate if (auth_weak)
5447c478bd9Sstevel@tonic-gate resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
5457c478bd9Sstevel@tonic-gate
546e1adf50cSahl DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
547e1adf50cSahl cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
548e1adf50cSahl VN_RELE(dvp);
549e1adf50cSahl
5507c478bd9Sstevel@tonic-gate return;
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate out:
5537c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
5547c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
5557c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
5567c478bd9Sstevel@tonic-gate } else
5577c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
5587c478bd9Sstevel@tonic-gate out1:
559e1adf50cSahl DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
560e1adf50cSahl cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
561e1adf50cSahl
5627c478bd9Sstevel@tonic-gate if (dvp != NULL)
5637c478bd9Sstevel@tonic-gate VN_RELE(dvp);
5647c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate
56827242a7cSthurlow void *
rfs3_lookup_getfh(LOOKUP3args * args)5697c478bd9Sstevel@tonic-gate rfs3_lookup_getfh(LOOKUP3args *args)
5707c478bd9Sstevel@tonic-gate {
5717c478bd9Sstevel@tonic-gate
57227242a7cSthurlow return (&args->what.dir);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate /* ARGSUSED */
5767c478bd9Sstevel@tonic-gate void
rfs3_access(ACCESS3args * args,ACCESS3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)5777c478bd9Sstevel@tonic-gate rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi,
5785cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate int error;
5817c478bd9Sstevel@tonic-gate vnode_t *vp;
5827c478bd9Sstevel@tonic-gate struct vattr *vap;
5837c478bd9Sstevel@tonic-gate struct vattr va;
5847c478bd9Sstevel@tonic-gate int checkwriteperm;
58503986916Sjarrett boolean_t dominant_label = B_FALSE;
58603986916Sjarrett boolean_t equal_label = B_FALSE;
58703986916Sjarrett boolean_t admin_low_client;
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate vap = NULL;
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
592e1adf50cSahl
593e1adf50cSahl DTRACE_NFSV3_4(op__access__start, struct svc_req *, req,
594e1adf50cSahl cred_t *, cr, vnode_t *, vp, ACCESS3args *, args);
595e1adf50cSahl
5967c478bd9Sstevel@tonic-gate if (vp == NULL) {
5977c478bd9Sstevel@tonic-gate error = ESTALE;
5987c478bd9Sstevel@tonic-gate goto out;
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate /*
6027c478bd9Sstevel@tonic-gate * If the file system is exported read only, it is not appropriate
6037c478bd9Sstevel@tonic-gate * to check write permissions for regular files and directories.
6047c478bd9Sstevel@tonic-gate * Special files are interpreted by the client, so the underlying
6057c478bd9Sstevel@tonic-gate * permissions are sent back to the client for interpretation.
6067c478bd9Sstevel@tonic-gate */
6075cb0d679SMarcel Telka if (rdonly(ro, vp) && (vp->v_type == VREG || vp->v_type == VDIR))
6087c478bd9Sstevel@tonic-gate checkwriteperm = 0;
6097c478bd9Sstevel@tonic-gate else
6107c478bd9Sstevel@tonic-gate checkwriteperm = 1;
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate * We need the mode so that we can correctly determine access
6147c478bd9Sstevel@tonic-gate * permissions relative to a mandatory lock file. Access to
6157c478bd9Sstevel@tonic-gate * mandatory lock files is denied on the server, so it might
6167c478bd9Sstevel@tonic-gate * as well be reflected to the server during the open.
6177c478bd9Sstevel@tonic-gate */
6187c478bd9Sstevel@tonic-gate va.va_mask = AT_MODE;
619da6c28aaSamw error = VOP_GETATTR(vp, &va, 0, cr, NULL);
6207c478bd9Sstevel@tonic-gate if (error)
6217c478bd9Sstevel@tonic-gate goto out;
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate vap = &va;
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate resp->resok.access = 0;
6267c478bd9Sstevel@tonic-gate
62703986916Sjarrett if (is_system_labeled()) {
62803986916Sjarrett bslabel_t *clabel = req->rq_label;
62903986916Sjarrett
63003986916Sjarrett ASSERT(clabel != NULL);
63103986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *,
63203986916Sjarrett "got client label from request(1)", struct svc_req *, req);
63303986916Sjarrett
63403986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
63503986916Sjarrett if ((equal_label = do_rfs_label_check(clabel, vp,
636bd6f1640SJarrett Lu EQUALITY_CHECK, exi)) == B_FALSE) {
63703986916Sjarrett dominant_label = do_rfs_label_check(clabel,
638bd6f1640SJarrett Lu vp, DOMINANCE_CHECK, exi);
63903986916Sjarrett } else
64003986916Sjarrett dominant_label = B_TRUE;
64103986916Sjarrett admin_low_client = B_FALSE;
64203986916Sjarrett } else
64303986916Sjarrett admin_low_client = B_TRUE;
64403986916Sjarrett }
64503986916Sjarrett
6467c478bd9Sstevel@tonic-gate if (args->access & ACCESS3_READ) {
647da6c28aaSamw error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
6487c478bd9Sstevel@tonic-gate if (error) {
6497c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
6507c478bd9Sstevel@tonic-gate goto out;
65103986916Sjarrett } else if (!MANDLOCK(vp, va.va_mode) &&
65203986916Sjarrett (!is_system_labeled() || admin_low_client ||
65303986916Sjarrett dominant_label))
6547c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_READ;
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate if ((args->access & ACCESS3_LOOKUP) && vp->v_type == VDIR) {
657da6c28aaSamw error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
6587c478bd9Sstevel@tonic-gate if (error) {
6597c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
6607c478bd9Sstevel@tonic-gate goto out;
66103986916Sjarrett } else if (!is_system_labeled() || admin_low_client ||
66203986916Sjarrett dominant_label)
6637c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_LOOKUP;
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate if (checkwriteperm &&
6667c478bd9Sstevel@tonic-gate (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND))) {
667da6c28aaSamw error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
6687c478bd9Sstevel@tonic-gate if (error) {
6697c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
6707c478bd9Sstevel@tonic-gate goto out;
67103986916Sjarrett } else if (!MANDLOCK(vp, va.va_mode) &&
67203986916Sjarrett (!is_system_labeled() || admin_low_client || equal_label)) {
6737c478bd9Sstevel@tonic-gate resp->resok.access |=
6747c478bd9Sstevel@tonic-gate (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND));
6757c478bd9Sstevel@tonic-gate }
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate if (checkwriteperm &&
6787c478bd9Sstevel@tonic-gate (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) {
679da6c28aaSamw error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
6807c478bd9Sstevel@tonic-gate if (error) {
6817c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
6827c478bd9Sstevel@tonic-gate goto out;
68303986916Sjarrett } else if (!is_system_labeled() || admin_low_client ||
68403986916Sjarrett equal_label)
6857c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_DELETE;
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate if (args->access & ACCESS3_EXECUTE) {
688da6c28aaSamw error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
6897c478bd9Sstevel@tonic-gate if (error) {
6907c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
6917c478bd9Sstevel@tonic-gate goto out;
69203986916Sjarrett } else if (!MANDLOCK(vp, va.va_mode) &&
69303986916Sjarrett (!is_system_labeled() || admin_low_client ||
69403986916Sjarrett dominant_label))
6957c478bd9Sstevel@tonic-gate resp->resok.access |= ACCESS3_EXECUTE;
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
6997c478bd9Sstevel@tonic-gate vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
7027c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
703e1adf50cSahl
704e1adf50cSahl DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
705e1adf50cSahl cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
706e1adf50cSahl
707e1adf50cSahl VN_RELE(vp);
708e1adf50cSahl
7097c478bd9Sstevel@tonic-gate return;
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate out:
7127c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
7137c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
7147c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
7157c478bd9Sstevel@tonic-gate } else
7167c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
717e1adf50cSahl DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
718e1adf50cSahl cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
7197c478bd9Sstevel@tonic-gate if (vp != NULL)
7207c478bd9Sstevel@tonic-gate VN_RELE(vp);
7217c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate
72427242a7cSthurlow void *
rfs3_access_getfh(ACCESS3args * args)7257c478bd9Sstevel@tonic-gate rfs3_access_getfh(ACCESS3args *args)
7267c478bd9Sstevel@tonic-gate {
7277c478bd9Sstevel@tonic-gate
72827242a7cSthurlow return (&args->object);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate /* ARGSUSED */
7327c478bd9Sstevel@tonic-gate void
rfs3_readlink(READLINK3args * args,READLINK3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)7337c478bd9Sstevel@tonic-gate rfs3_readlink(READLINK3args *args, READLINK3res *resp, struct exportinfo *exi,
7345cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
7357c478bd9Sstevel@tonic-gate {
7367c478bd9Sstevel@tonic-gate int error;
7377c478bd9Sstevel@tonic-gate vnode_t *vp;
7387c478bd9Sstevel@tonic-gate struct vattr *vap;
7397c478bd9Sstevel@tonic-gate struct vattr va;
7407c478bd9Sstevel@tonic-gate struct iovec iov;
7417c478bd9Sstevel@tonic-gate struct uio uio;
7427c478bd9Sstevel@tonic-gate char *data;
743b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
744b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
7452f172c55SRobert Thurlow int is_referral = 0;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate vap = NULL;
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->symlink, exi);
750e1adf50cSahl
751e1adf50cSahl DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req,
752e1adf50cSahl cred_t *, cr, vnode_t *, vp, READLINK3args *, args);
753e1adf50cSahl
7547c478bd9Sstevel@tonic-gate if (vp == NULL) {
7557c478bd9Sstevel@tonic-gate error = ESTALE;
7567c478bd9Sstevel@tonic-gate goto out;
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
760da6c28aaSamw error = VOP_GETATTR(vp, &va, 0, cr, NULL);
7617c478bd9Sstevel@tonic-gate if (error)
7627c478bd9Sstevel@tonic-gate goto out;
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate vap = &va;
7657c478bd9Sstevel@tonic-gate
7662f172c55SRobert Thurlow /* We lied about the object type for a referral */
7672f172c55SRobert Thurlow if (vn_is_nfs_reparse(vp, cr))
7682f172c55SRobert Thurlow is_referral = 1;
7692f172c55SRobert Thurlow
7702f172c55SRobert Thurlow if (vp->v_type != VLNK && !is_referral) {
7717c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
7727c478bd9Sstevel@tonic-gate goto out1;
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate if (MANDLOCK(vp, va.va_mode)) {
7767c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
7777c478bd9Sstevel@tonic-gate goto out1;
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate
78003986916Sjarrett if (is_system_labeled()) {
78103986916Sjarrett bslabel_t *clabel = req->rq_label;
78203986916Sjarrett
78303986916Sjarrett ASSERT(clabel != NULL);
78403986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *,
78503986916Sjarrett "got client label from request(1)", struct svc_req *, req);
78603986916Sjarrett
78703986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
788bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
789bd6f1640SJarrett Lu exi)) {
79003986916Sjarrett resp->status = NFS3ERR_ACCES;
79103986916Sjarrett goto out1;
79203986916Sjarrett }
79303986916Sjarrett }
79403986916Sjarrett }
79503986916Sjarrett
7967c478bd9Sstevel@tonic-gate data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
7977c478bd9Sstevel@tonic-gate
7982f172c55SRobert Thurlow if (is_referral) {
7992f172c55SRobert Thurlow char *s;
8002f172c55SRobert Thurlow size_t strsz;
8012f172c55SRobert Thurlow
8022f172c55SRobert Thurlow /* Get an artificial symlink based on a referral */
8032f172c55SRobert Thurlow s = build_symlink(vp, cr, &strsz);
8042f172c55SRobert Thurlow global_svstat_ptr[3][NFS_REFERLINKS].value.ui64++;
8052f172c55SRobert Thurlow DTRACE_PROBE2(nfs3serv__func__referral__reflink,
8062f172c55SRobert Thurlow vnode_t *, vp, char *, s);
8072f172c55SRobert Thurlow if (s == NULL)
8082f172c55SRobert Thurlow error = EINVAL;
8092f172c55SRobert Thurlow else {
8102f172c55SRobert Thurlow error = 0;
8112f172c55SRobert Thurlow (void) strlcpy(data, s, MAXPATHLEN + 1);
8122f172c55SRobert Thurlow kmem_free(s, strsz);
8132f172c55SRobert Thurlow }
8142f172c55SRobert Thurlow
8152f172c55SRobert Thurlow } else {
8162f172c55SRobert Thurlow
8177c478bd9Sstevel@tonic-gate iov.iov_base = data;
8187c478bd9Sstevel@tonic-gate iov.iov_len = MAXPATHLEN;
8197c478bd9Sstevel@tonic-gate uio.uio_iov = &iov;
8207c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1;
8217c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
8227c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
8237c478bd9Sstevel@tonic-gate uio.uio_loffset = 0;
8247c478bd9Sstevel@tonic-gate uio.uio_resid = MAXPATHLEN;
8257c478bd9Sstevel@tonic-gate
826da6c28aaSamw error = VOP_READLINK(vp, &uio, cr, NULL);
8277c478bd9Sstevel@tonic-gate
8282f172c55SRobert Thurlow if (!error)
8292f172c55SRobert Thurlow *(data + MAXPATHLEN - uio.uio_resid) = '\0';
8302f172c55SRobert Thurlow }
8312f172c55SRobert Thurlow
8327c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
833da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
83427246829SVitaliy Gusev
8352f172c55SRobert Thurlow /* Lie about object type again just to be consistent */
8362f172c55SRobert Thurlow if (is_referral && vap != NULL)
8372f172c55SRobert Thurlow vap->va_type = VLNK;
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate #if 0 /* notyet */
8407c478bd9Sstevel@tonic-gate /*
8417c478bd9Sstevel@tonic-gate * Don't do this. It causes local disk writes when just
8427c478bd9Sstevel@tonic-gate * reading the file and the overhead is deemed larger
8437c478bd9Sstevel@tonic-gate * than the benefit.
8447c478bd9Sstevel@tonic-gate */
8457c478bd9Sstevel@tonic-gate /*
8467c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
8477c478bd9Sstevel@tonic-gate */
848da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
8497c478bd9Sstevel@tonic-gate #endif
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate if (error) {
8527c478bd9Sstevel@tonic-gate kmem_free(data, MAXPATHLEN + 1);
8537c478bd9Sstevel@tonic-gate goto out;
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate
856b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
857b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, data, NFSCMD_CONV_OUTBOUND,
858b89a8333Snatalie li - Sun Microsystems - Irvine United States MAXPATHLEN + 1);
859b89a8333Snatalie li - Sun Microsystems - Irvine United States
860b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
861b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
862b89a8333Snatalie li - Sun Microsystems - Irvine United States * Even though the conversion failed, we return
863b89a8333Snatalie li - Sun Microsystems - Irvine United States * something. We just don't translate it.
864b89a8333Snatalie li - Sun Microsystems - Irvine United States */
865b89a8333Snatalie li - Sun Microsystems - Irvine United States name = data;
866b89a8333Snatalie li - Sun Microsystems - Irvine United States }
867b89a8333Snatalie li - Sun Microsystems - Irvine United States
8687c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
8697c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.symlink_attributes);
870b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->resok.data = name;
871e1adf50cSahl
872e1adf50cSahl DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
873e1adf50cSahl cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
874e1adf50cSahl VN_RELE(vp);
875e1adf50cSahl
876b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != data)
877b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(data, MAXPATHLEN + 1);
878b89a8333Snatalie li - Sun Microsystems - Irvine United States
8797c478bd9Sstevel@tonic-gate return;
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate out:
8827c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
8837c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
8847c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
8857c478bd9Sstevel@tonic-gate } else
8867c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
8877c478bd9Sstevel@tonic-gate out1:
888e1adf50cSahl DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
889e1adf50cSahl cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
8907c478bd9Sstevel@tonic-gate if (vp != NULL)
8917c478bd9Sstevel@tonic-gate VN_RELE(vp);
8927c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes);
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate
89527242a7cSthurlow void *
rfs3_readlink_getfh(READLINK3args * args)8967c478bd9Sstevel@tonic-gate rfs3_readlink_getfh(READLINK3args *args)
8977c478bd9Sstevel@tonic-gate {
8987c478bd9Sstevel@tonic-gate
89927242a7cSthurlow return (&args->symlink);
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate void
rfs3_readlink_free(READLINK3res * resp)9037c478bd9Sstevel@tonic-gate rfs3_readlink_free(READLINK3res *resp)
9047c478bd9Sstevel@tonic-gate {
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK)
9077c478bd9Sstevel@tonic-gate kmem_free(resp->resok.data, MAXPATHLEN + 1);
9087c478bd9Sstevel@tonic-gate }
9097c478bd9Sstevel@tonic-gate
9100a701b1eSRobert Gordon /*
9110a701b1eSRobert Gordon * Server routine to handle read
9120a701b1eSRobert Gordon * May handle RDMA data as well as mblks
9130a701b1eSRobert Gordon */
9147c478bd9Sstevel@tonic-gate /* ARGSUSED */
9157c478bd9Sstevel@tonic-gate void
rfs3_read(READ3args * args,READ3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)9167c478bd9Sstevel@tonic-gate rfs3_read(READ3args *args, READ3res *resp, struct exportinfo *exi,
9175cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
9187c478bd9Sstevel@tonic-gate {
9197c478bd9Sstevel@tonic-gate int error;
9207c478bd9Sstevel@tonic-gate vnode_t *vp;
9217c478bd9Sstevel@tonic-gate struct vattr *vap;
9227c478bd9Sstevel@tonic-gate struct vattr va;
923e36d7b11SSebastien Roy struct iovec iov, *iovp = NULL;
924e36d7b11SSebastien Roy int iovcnt;
9257c478bd9Sstevel@tonic-gate struct uio uio;
9267c478bd9Sstevel@tonic-gate u_offset_t offset;
92741b8345aSchunli zhang - Sun Microsystems - Irvine United States mblk_t *mp = NULL;
9287c478bd9Sstevel@tonic-gate int in_crit = 0;
9297c478bd9Sstevel@tonic-gate int need_rwunlock = 0;
930cfae96c2Sjwahlig caller_context_t ct;
931c242f9a0Schunli zhang - Sun Microsystems - Irvine United States int rdma_used = 0;
932c242f9a0Schunli zhang - Sun Microsystems - Irvine United States int loaned_buffers;
933c242f9a0Schunli zhang - Sun Microsystems - Irvine United States struct uio *uiop;
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate vap = NULL;
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
938e1adf50cSahl
939e1adf50cSahl DTRACE_NFSV3_4(op__read__start, struct svc_req *, req,
940e1adf50cSahl cred_t *, cr, vnode_t *, vp, READ3args *, args);
941e1adf50cSahl
9427c478bd9Sstevel@tonic-gate if (vp == NULL) {
9437c478bd9Sstevel@tonic-gate error = ESTALE;
9447c478bd9Sstevel@tonic-gate goto out;
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate
94735bbd688SKaren Rochford if (args->wlist) {
94835bbd688SKaren Rochford if (args->count > clist_len(args->wlist)) {
94935bbd688SKaren Rochford error = EINVAL;
95035bbd688SKaren Rochford goto out;
95135bbd688SKaren Rochford }
952c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rdma_used = 1;
95335bbd688SKaren Rochford }
954c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
955c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* use loaned buffers for TCP */
956c242f9a0Schunli zhang - Sun Microsystems - Irvine United States loaned_buffers = (nfs_loaned_buffers && !rdma_used) ? 1 : 0;
957c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
95803986916Sjarrett if (is_system_labeled()) {
95903986916Sjarrett bslabel_t *clabel = req->rq_label;
96003986916Sjarrett
96103986916Sjarrett ASSERT(clabel != NULL);
96203986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opread__clabel, char *,
96303986916Sjarrett "got client label from request(1)", struct svc_req *, req);
96403986916Sjarrett
96503986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
966bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
967bd6f1640SJarrett Lu exi)) {
96803986916Sjarrett resp->status = NFS3ERR_ACCES;
96903986916Sjarrett goto out1;
97003986916Sjarrett }
97103986916Sjarrett }
97203986916Sjarrett }
97303986916Sjarrett
974cfae96c2Sjwahlig ct.cc_sysid = 0;
975cfae96c2Sjwahlig ct.cc_pid = 0;
976cfae96c2Sjwahlig ct.cc_caller_id = nfs3_srv_caller_id;
977cfae96c2Sjwahlig ct.cc_flags = CC_DONTBLOCK;
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate /*
9807c478bd9Sstevel@tonic-gate * Enter the critical region before calling VOP_RWLOCK
9817c478bd9Sstevel@tonic-gate * to avoid a deadlock with write requests.
9827c478bd9Sstevel@tonic-gate */
9837c478bd9Sstevel@tonic-gate if (nbl_need_check(vp)) {
9847c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_READER);
9857c478bd9Sstevel@tonic-gate in_crit = 1;
986da6c28aaSamw if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
987da6c28aaSamw NULL)) {
9887c478bd9Sstevel@tonic-gate error = EACCES;
9897c478bd9Sstevel@tonic-gate goto out;
9907c478bd9Sstevel@tonic-gate }
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate
993cfae96c2Sjwahlig error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct);
994cfae96c2Sjwahlig
995cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
996cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
997cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
998cfae96c2Sjwahlig goto out1;
999cfae96c2Sjwahlig }
1000cfae96c2Sjwahlig
10017c478bd9Sstevel@tonic-gate need_rwunlock = 1;
10027c478bd9Sstevel@tonic-gate
10037c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1004cfae96c2Sjwahlig error = VOP_GETATTR(vp, &va, 0, cr, &ct);
10057c478bd9Sstevel@tonic-gate
10067c478bd9Sstevel@tonic-gate /*
10077c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
10087c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
10097c478bd9Sstevel@tonic-gate */
10107c478bd9Sstevel@tonic-gate if (error)
10117c478bd9Sstevel@tonic-gate goto out;
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate vap = &va;
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) {
10167c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
10177c478bd9Sstevel@tonic-gate goto out1;
10187c478bd9Sstevel@tonic-gate }
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate if (crgetuid(cr) != va.va_uid) {
1021cfae96c2Sjwahlig error = VOP_ACCESS(vp, VREAD, 0, cr, &ct);
10227c478bd9Sstevel@tonic-gate if (error) {
10237c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK)
10247c478bd9Sstevel@tonic-gate goto out;
1025cfae96c2Sjwahlig error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct);
10267c478bd9Sstevel@tonic-gate if (error)
10277c478bd9Sstevel@tonic-gate goto out;
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate }
10307c478bd9Sstevel@tonic-gate
10317c478bd9Sstevel@tonic-gate if (MANDLOCK(vp, va.va_mode)) {
10327c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
10337c478bd9Sstevel@tonic-gate goto out1;
10347c478bd9Sstevel@tonic-gate }
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate offset = args->offset;
10377c478bd9Sstevel@tonic-gate if (offset >= va.va_size) {
1038cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
10397c478bd9Sstevel@tonic-gate if (in_crit)
10407c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
10417c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
10427c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
10437c478bd9Sstevel@tonic-gate resp->resok.count = 0;
10447c478bd9Sstevel@tonic-gate resp->resok.eof = TRUE;
10457c478bd9Sstevel@tonic-gate resp->resok.data.data_len = 0;
10467c478bd9Sstevel@tonic-gate resp->resok.data.data_val = NULL;
10477c478bd9Sstevel@tonic-gate resp->resok.data.mp = NULL;
10480a701b1eSRobert Gordon /* RDMA */
10490a701b1eSRobert Gordon resp->resok.wlist = args->wlist;
10500a701b1eSRobert Gordon resp->resok.wlist_len = resp->resok.count;
1051f837ee4aSSiddheshwar Mahesh if (resp->resok.wlist)
1052f837ee4aSSiddheshwar Mahesh clist_zero_len(resp->resok.wlist);
1053e1adf50cSahl goto done;
10547c478bd9Sstevel@tonic-gate }
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate if (args->count == 0) {
1057cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
10587c478bd9Sstevel@tonic-gate if (in_crit)
10597c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
10607c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
10617c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
10627c478bd9Sstevel@tonic-gate resp->resok.count = 0;
10637c478bd9Sstevel@tonic-gate resp->resok.eof = FALSE;
10647c478bd9Sstevel@tonic-gate resp->resok.data.data_len = 0;
10657c478bd9Sstevel@tonic-gate resp->resok.data.data_val = NULL;
10667c478bd9Sstevel@tonic-gate resp->resok.data.mp = NULL;
10670a701b1eSRobert Gordon /* RDMA */
10680a701b1eSRobert Gordon resp->resok.wlist = args->wlist;
10690a701b1eSRobert Gordon resp->resok.wlist_len = resp->resok.count;
1070f837ee4aSSiddheshwar Mahesh if (resp->resok.wlist)
1071f837ee4aSSiddheshwar Mahesh clist_zero_len(resp->resok.wlist);
1072e1adf50cSahl goto done;
10737c478bd9Sstevel@tonic-gate }
10747c478bd9Sstevel@tonic-gate
10757c478bd9Sstevel@tonic-gate /*
10767c478bd9Sstevel@tonic-gate * do not allocate memory more the max. allowed
10777c478bd9Sstevel@tonic-gate * transfer size
10787c478bd9Sstevel@tonic-gate */
10797c478bd9Sstevel@tonic-gate if (args->count > rfs3_tsize(req))
10807c478bd9Sstevel@tonic-gate args->count = rfs3_tsize(req);
10817c478bd9Sstevel@tonic-gate
1082c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (loaned_buffers) {
1083c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop = (uio_t *)rfs_setup_xuio(vp);
1084c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(uiop != NULL);
1085c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_segflg = UIO_SYSSPACE;
1086c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_loffset = args->offset;
1087c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_resid = args->count;
1088c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1089c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* Jump to do the read if successful */
1090c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (VOP_REQZCBUF(vp, UIO_READ, (xuio_t *)uiop, cr, &ct) == 0) {
1091c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /*
1092c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * Need to hold the vnode until after VOP_RETZCBUF()
1093c242f9a0Schunli zhang - Sun Microsystems - Irvine United States * is called.
1094c242f9a0Schunli zhang - Sun Microsystems - Irvine United States */
1095c242f9a0Schunli zhang - Sun Microsystems - Irvine United States VN_HOLD(vp);
1096c242f9a0Schunli zhang - Sun Microsystems - Irvine United States goto doio_read;
1097c242f9a0Schunli zhang - Sun Microsystems - Irvine United States }
1098c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1099c242f9a0Schunli zhang - Sun Microsystems - Irvine United States DTRACE_PROBE2(nfss__i__reqzcbuf_failed, int,
1100c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_loffset, int, uiop->uio_resid);
1101c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1102c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop->uio_extflg = 0;
1103c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* failure to setup for zero copy */
1104c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rfs_free_xuio((void *)uiop);
1105c242f9a0Schunli zhang - Sun Microsystems - Irvine United States loaned_buffers = 0;
1106c242f9a0Schunli zhang - Sun Microsystems - Irvine United States }
1107c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
11087c478bd9Sstevel@tonic-gate /*
11090a701b1eSRobert Gordon * If returning data via RDMA Write, then grab the chunk list.
11100a701b1eSRobert Gordon * If we aren't returning READ data w/RDMA_WRITE, then grab
11110a701b1eSRobert Gordon * a mblk.
11120a701b1eSRobert Gordon */
1113c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (rdma_used) {
11140a701b1eSRobert Gordon (void) rdma_get_wchunk(req, &iov, args->wlist);
1115e36d7b11SSebastien Roy uio.uio_iov = &iov;
1116e36d7b11SSebastien Roy uio.uio_iovcnt = 1;
11170a701b1eSRobert Gordon } else {
11180a701b1eSRobert Gordon /*
11197c478bd9Sstevel@tonic-gate * mp will contain the data to be sent out in the read reply.
1120e36d7b11SSebastien Roy * For UDP, this will be freed after the reply has been sent
1121e36d7b11SSebastien Roy * out by the driver. For TCP, it will be freed after the last
1122e36d7b11SSebastien Roy * segment associated with the reply has been ACKed by the
1123e36d7b11SSebastien Roy * client.
11247c478bd9Sstevel@tonic-gate */
1125e36d7b11SSebastien Roy mp = rfs_read_alloc(args->count, &iovp, &iovcnt);
1126e36d7b11SSebastien Roy uio.uio_iov = iovp;
1127e36d7b11SSebastien Roy uio.uio_iovcnt = iovcnt;
11280a701b1eSRobert Gordon }
11290a701b1eSRobert Gordon
11307c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
11317c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
11327c478bd9Sstevel@tonic-gate uio.uio_loffset = args->offset;
11337c478bd9Sstevel@tonic-gate uio.uio_resid = args->count;
1134c242f9a0Schunli zhang - Sun Microsystems - Irvine United States uiop = &uio;
11357c478bd9Sstevel@tonic-gate
1136c242f9a0Schunli zhang - Sun Microsystems - Irvine United States doio_read:
1137c242f9a0Schunli zhang - Sun Microsystems - Irvine United States error = VOP_READ(vp, uiop, 0, cr, &ct);
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate if (error) {
1140c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (mp)
1141c242f9a0Schunli zhang - Sun Microsystems - Irvine United States freemsg(mp);
1142cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
1143cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1144cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
1145cfae96c2Sjwahlig goto out1;
1146cfae96c2Sjwahlig }
11477c478bd9Sstevel@tonic-gate goto out;
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate
1150c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* make mblk using zc buffers */
1151c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (loaned_buffers) {
1152c242f9a0Schunli zhang - Sun Microsystems - Irvine United States mp = uio_to_mblk(uiop);
1153c242f9a0Schunli zhang - Sun Microsystems - Irvine United States ASSERT(mp != NULL);
1154c242f9a0Schunli zhang - Sun Microsystems - Irvine United States }
1155c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
11567c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1157cfae96c2Sjwahlig error = VOP_GETATTR(vp, &va, 0, cr, &ct);
11587c478bd9Sstevel@tonic-gate
11597c478bd9Sstevel@tonic-gate if (error)
11607c478bd9Sstevel@tonic-gate vap = NULL;
11617c478bd9Sstevel@tonic-gate else
11627c478bd9Sstevel@tonic-gate vap = &va;
11637c478bd9Sstevel@tonic-gate
1164cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate if (in_crit)
11677c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
11707c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1171c242f9a0Schunli zhang - Sun Microsystems - Irvine United States resp->resok.count = args->count - uiop->uio_resid;
11727c478bd9Sstevel@tonic-gate if (!error && offset + resp->resok.count == va.va_size)
11737c478bd9Sstevel@tonic-gate resp->resok.eof = TRUE;
11747c478bd9Sstevel@tonic-gate else
11757c478bd9Sstevel@tonic-gate resp->resok.eof = FALSE;
11767c478bd9Sstevel@tonic-gate resp->resok.data.data_len = resp->resok.count;
1177c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
1178c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (mp)
1179c242f9a0Schunli zhang - Sun Microsystems - Irvine United States rfs_rndup_mblks(mp, resp->resok.count, loaned_buffers);
1180c242f9a0Schunli zhang - Sun Microsystems - Irvine United States
11817c478bd9Sstevel@tonic-gate resp->resok.data.mp = mp;
11827c478bd9Sstevel@tonic-gate resp->resok.size = (uint_t)args->count;
1183e1adf50cSahl
1184c242f9a0Schunli zhang - Sun Microsystems - Irvine United States if (rdma_used) {
11850a701b1eSRobert Gordon resp->resok.data.data_val = (caddr_t)iov.iov_base;
11860a701b1eSRobert Gordon if (!rdma_setup_read_data3(args, &(resp->resok))) {
11870a701b1eSRobert Gordon resp->status = NFS3ERR_INVAL;
11880a701b1eSRobert Gordon }
11890a701b1eSRobert Gordon } else {
11900a701b1eSRobert Gordon resp->resok.data.data_val = (caddr_t)mp->b_datap->db_base;
11910a701b1eSRobert Gordon (resp->resok).wlist = NULL;
11920a701b1eSRobert Gordon }
11930a701b1eSRobert Gordon
1194e1adf50cSahl done:
1195e1adf50cSahl DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
1196e1adf50cSahl cred_t *, cr, vnode_t *, vp, READ3res *, resp);
1197e1adf50cSahl
1198e1adf50cSahl VN_RELE(vp);
1199e1adf50cSahl
1200e36d7b11SSebastien Roy if (iovp != NULL)
1201e36d7b11SSebastien Roy kmem_free(iovp, iovcnt * sizeof (struct iovec));
1202e36d7b11SSebastien Roy
12037c478bd9Sstevel@tonic-gate return;
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate out:
12067c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
12077c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
12087c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
12097c478bd9Sstevel@tonic-gate } else
12107c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
12117c478bd9Sstevel@tonic-gate out1:
1212e1adf50cSahl DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
1213e1adf50cSahl cred_t *, cr, vnode_t *, vp, READ3res *, resp);
1214e1adf50cSahl
12157c478bd9Sstevel@tonic-gate if (vp != NULL) {
12167c478bd9Sstevel@tonic-gate if (need_rwunlock)
1217cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
12187c478bd9Sstevel@tonic-gate if (in_crit)
12197c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
12207c478bd9Sstevel@tonic-gate VN_RELE(vp);
12217c478bd9Sstevel@tonic-gate }
12227c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
1223e36d7b11SSebastien Roy
1224e36d7b11SSebastien Roy if (iovp != NULL)
1225e36d7b11SSebastien Roy kmem_free(iovp, iovcnt * sizeof (struct iovec));
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate void
rfs3_read_free(READ3res * resp)12297c478bd9Sstevel@tonic-gate rfs3_read_free(READ3res *resp)
12307c478bd9Sstevel@tonic-gate {
12317c478bd9Sstevel@tonic-gate mblk_t *mp;
12327c478bd9Sstevel@tonic-gate
12337c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK) {
12347c478bd9Sstevel@tonic-gate mp = resp->resok.data.mp;
12357c478bd9Sstevel@tonic-gate if (mp != NULL)
1236c242f9a0Schunli zhang - Sun Microsystems - Irvine United States freemsg(mp);
12377c478bd9Sstevel@tonic-gate }
12387c478bd9Sstevel@tonic-gate }
12397c478bd9Sstevel@tonic-gate
124027242a7cSthurlow void *
rfs3_read_getfh(READ3args * args)12417c478bd9Sstevel@tonic-gate rfs3_read_getfh(READ3args *args)
12427c478bd9Sstevel@tonic-gate {
12437c478bd9Sstevel@tonic-gate
124427242a7cSthurlow return (&args->file);
12457c478bd9Sstevel@tonic-gate }
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate #define MAX_IOVECS 12
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate #ifdef DEBUG
12507c478bd9Sstevel@tonic-gate static int rfs3_write_hits = 0;
12517c478bd9Sstevel@tonic-gate static int rfs3_write_misses = 0;
12527c478bd9Sstevel@tonic-gate #endif
12537c478bd9Sstevel@tonic-gate
12547c478bd9Sstevel@tonic-gate void
rfs3_write(WRITE3args * args,WRITE3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)12557c478bd9Sstevel@tonic-gate rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi,
12565cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
12577c478bd9Sstevel@tonic-gate {
12587c478bd9Sstevel@tonic-gate int error;
12597c478bd9Sstevel@tonic-gate vnode_t *vp;
12607c478bd9Sstevel@tonic-gate struct vattr *bvap = NULL;
12617c478bd9Sstevel@tonic-gate struct vattr bva;
12627c478bd9Sstevel@tonic-gate struct vattr *avap = NULL;
12637c478bd9Sstevel@tonic-gate struct vattr ava;
12647c478bd9Sstevel@tonic-gate u_offset_t rlimit;
12657c478bd9Sstevel@tonic-gate struct uio uio;
12667c478bd9Sstevel@tonic-gate struct iovec iov[MAX_IOVECS];
12677c478bd9Sstevel@tonic-gate mblk_t *m;
12687c478bd9Sstevel@tonic-gate struct iovec *iovp;
12697c478bd9Sstevel@tonic-gate int iovcnt;
12707c478bd9Sstevel@tonic-gate int ioflag;
12717c478bd9Sstevel@tonic-gate cred_t *savecred;
12727c478bd9Sstevel@tonic-gate int in_crit = 0;
12737c478bd9Sstevel@tonic-gate int rwlock_ret = -1;
1274cfae96c2Sjwahlig caller_context_t ct;
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
1277e1adf50cSahl
1278e1adf50cSahl DTRACE_NFSV3_4(op__write__start, struct svc_req *, req,
1279e1adf50cSahl cred_t *, cr, vnode_t *, vp, WRITE3args *, args);
1280e1adf50cSahl
12817c478bd9Sstevel@tonic-gate if (vp == NULL) {
12827c478bd9Sstevel@tonic-gate error = ESTALE;
1283e1adf50cSahl goto err;
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate
128603986916Sjarrett if (is_system_labeled()) {
128703986916Sjarrett bslabel_t *clabel = req->rq_label;
128803986916Sjarrett
128903986916Sjarrett ASSERT(clabel != NULL);
129003986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
129103986916Sjarrett "got client label from request(1)", struct svc_req *, req);
129203986916Sjarrett
129303986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
1294bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1295bd6f1640SJarrett Lu exi)) {
129603986916Sjarrett resp->status = NFS3ERR_ACCES;
1297e1adf50cSahl goto err1;
129803986916Sjarrett }
129903986916Sjarrett }
130003986916Sjarrett }
130103986916Sjarrett
1302cfae96c2Sjwahlig ct.cc_sysid = 0;
1303cfae96c2Sjwahlig ct.cc_pid = 0;
1304cfae96c2Sjwahlig ct.cc_caller_id = nfs3_srv_caller_id;
1305cfae96c2Sjwahlig ct.cc_flags = CC_DONTBLOCK;
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate /*
13087c478bd9Sstevel@tonic-gate * We have to enter the critical region before calling VOP_RWLOCK
13097c478bd9Sstevel@tonic-gate * to avoid a deadlock with ufs.
13107c478bd9Sstevel@tonic-gate */
13117c478bd9Sstevel@tonic-gate if (nbl_need_check(vp)) {
13127c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_READER);
13137c478bd9Sstevel@tonic-gate in_crit = 1;
1314da6c28aaSamw if (nbl_conflict(vp, NBL_WRITE, args->offset, args->count, 0,
1315da6c28aaSamw NULL)) {
13167c478bd9Sstevel@tonic-gate error = EACCES;
1317e1adf50cSahl goto err;
13187c478bd9Sstevel@tonic-gate }
13197c478bd9Sstevel@tonic-gate }
13207c478bd9Sstevel@tonic-gate
1321cfae96c2Sjwahlig rwlock_ret = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct);
1322cfae96c2Sjwahlig
1323cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
1324cfae96c2Sjwahlig if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1325cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
1326cfae96c2Sjwahlig rwlock_ret = -1;
1327e1adf50cSahl goto err1;
1328cfae96c2Sjwahlig }
1329cfae96c2Sjwahlig
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
1332cfae96c2Sjwahlig error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
13337c478bd9Sstevel@tonic-gate
13347c478bd9Sstevel@tonic-gate /*
13357c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
13367c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
13377c478bd9Sstevel@tonic-gate */
13387c478bd9Sstevel@tonic-gate if (error)
1339e1adf50cSahl goto err;
13407c478bd9Sstevel@tonic-gate
13417c478bd9Sstevel@tonic-gate bvap = &bva;
13427c478bd9Sstevel@tonic-gate avap = bvap;
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate if (args->count != args->data.data_len) {
13457c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
1346e1adf50cSahl goto err1;
13477c478bd9Sstevel@tonic-gate }
13487c478bd9Sstevel@tonic-gate
13495cb0d679SMarcel Telka if (rdonly(ro, vp)) {
13507c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
1351e1adf50cSahl goto err1;
13527c478bd9Sstevel@tonic-gate }
13537c478bd9Sstevel@tonic-gate
13547c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) {
13557c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
1356e1adf50cSahl goto err1;
13577c478bd9Sstevel@tonic-gate }
13587c478bd9Sstevel@tonic-gate
13597c478bd9Sstevel@tonic-gate if (crgetuid(cr) != bva.va_uid &&
1360cfae96c2Sjwahlig (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
1361e1adf50cSahl goto err;
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate if (MANDLOCK(vp, bva.va_mode)) {
13647c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
1365e1adf50cSahl goto err1;
13667c478bd9Sstevel@tonic-gate }
13677c478bd9Sstevel@tonic-gate
13687c478bd9Sstevel@tonic-gate if (args->count == 0) {
13697c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
13707c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
13717c478bd9Sstevel@tonic-gate resp->resok.count = 0;
13727c478bd9Sstevel@tonic-gate resp->resok.committed = args->stable;
13737c478bd9Sstevel@tonic-gate resp->resok.verf = write3verf;
1374e1adf50cSahl goto out;
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate if (args->mblk != NULL) {
13787c478bd9Sstevel@tonic-gate iovcnt = 0;
13797c478bd9Sstevel@tonic-gate for (m = args->mblk; m != NULL; m = m->b_cont)
13807c478bd9Sstevel@tonic-gate iovcnt++;
13817c478bd9Sstevel@tonic-gate if (iovcnt <= MAX_IOVECS) {
13827c478bd9Sstevel@tonic-gate #ifdef DEBUG
13837c478bd9Sstevel@tonic-gate rfs3_write_hits++;
13847c478bd9Sstevel@tonic-gate #endif
13857c478bd9Sstevel@tonic-gate iovp = iov;
13867c478bd9Sstevel@tonic-gate } else {
13877c478bd9Sstevel@tonic-gate #ifdef DEBUG
13887c478bd9Sstevel@tonic-gate rfs3_write_misses++;
13897c478bd9Sstevel@tonic-gate #endif
13907c478bd9Sstevel@tonic-gate iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP);
13917c478bd9Sstevel@tonic-gate }
13927c478bd9Sstevel@tonic-gate mblk_to_iov(args->mblk, iovcnt, iovp);
13930a701b1eSRobert Gordon
13940a701b1eSRobert Gordon } else if (args->rlist != NULL) {
13950a701b1eSRobert Gordon iovcnt = 1;
13960a701b1eSRobert Gordon iovp = iov;
13970a701b1eSRobert Gordon iovp->iov_base = (char *)((args->rlist)->u.c_daddr3);
13980a701b1eSRobert Gordon iovp->iov_len = args->count;
13997c478bd9Sstevel@tonic-gate } else {
14007c478bd9Sstevel@tonic-gate iovcnt = 1;
14017c478bd9Sstevel@tonic-gate iovp = iov;
14027c478bd9Sstevel@tonic-gate iovp->iov_base = args->data.data_val;
14037c478bd9Sstevel@tonic-gate iovp->iov_len = args->count;
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate
14067c478bd9Sstevel@tonic-gate uio.uio_iov = iovp;
14077c478bd9Sstevel@tonic-gate uio.uio_iovcnt = iovcnt;
14087c478bd9Sstevel@tonic-gate
14097c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
14107c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_DEFAULT;
14117c478bd9Sstevel@tonic-gate uio.uio_loffset = args->offset;
14127c478bd9Sstevel@tonic-gate uio.uio_resid = args->count;
14137c478bd9Sstevel@tonic-gate uio.uio_llimit = curproc->p_fsz_ctl;
14147c478bd9Sstevel@tonic-gate rlimit = uio.uio_llimit - args->offset;
14157c478bd9Sstevel@tonic-gate if (rlimit < (u_offset_t)uio.uio_resid)
14167c478bd9Sstevel@tonic-gate uio.uio_resid = (int)rlimit;
14177c478bd9Sstevel@tonic-gate
14187c478bd9Sstevel@tonic-gate if (args->stable == UNSTABLE)
14197c478bd9Sstevel@tonic-gate ioflag = 0;
14207c478bd9Sstevel@tonic-gate else if (args->stable == FILE_SYNC)
14217c478bd9Sstevel@tonic-gate ioflag = FSYNC;
14227c478bd9Sstevel@tonic-gate else if (args->stable == DATA_SYNC)
14237c478bd9Sstevel@tonic-gate ioflag = FDSYNC;
14247c478bd9Sstevel@tonic-gate else {
14257c478bd9Sstevel@tonic-gate if (iovp != iov)
14267c478bd9Sstevel@tonic-gate kmem_free(iovp, sizeof (*iovp) * iovcnt);
14277c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
1428e1adf50cSahl goto err1;
14297c478bd9Sstevel@tonic-gate }
14307c478bd9Sstevel@tonic-gate
14317c478bd9Sstevel@tonic-gate /*
14327c478bd9Sstevel@tonic-gate * We're changing creds because VM may fault and we need
14337c478bd9Sstevel@tonic-gate * the cred of the current thread to be used if quota
14347c478bd9Sstevel@tonic-gate * checking is enabled.
14357c478bd9Sstevel@tonic-gate */
14367c478bd9Sstevel@tonic-gate savecred = curthread->t_cred;
14377c478bd9Sstevel@tonic-gate curthread->t_cred = cr;
1438cfae96c2Sjwahlig error = VOP_WRITE(vp, &uio, ioflag, cr, &ct);
14397c478bd9Sstevel@tonic-gate curthread->t_cred = savecred;
14407c478bd9Sstevel@tonic-gate
14417c478bd9Sstevel@tonic-gate if (iovp != iov)
14427c478bd9Sstevel@tonic-gate kmem_free(iovp, sizeof (*iovp) * iovcnt);
14437c478bd9Sstevel@tonic-gate
1444cfae96c2Sjwahlig /* check if a monitor detected a delegation conflict */
1445cfae96c2Sjwahlig if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1446cfae96c2Sjwahlig resp->status = NFS3ERR_JUKEBOX;
1447e1adf50cSahl goto err1;
1448cfae96c2Sjwahlig }
1449cfae96c2Sjwahlig
14507c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
1451cfae96c2Sjwahlig avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava;
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate if (error)
1454e1adf50cSahl goto err;
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate /*
14577c478bd9Sstevel@tonic-gate * If we were unable to get the V_WRITELOCK_TRUE, then we
14587c478bd9Sstevel@tonic-gate * may not have accurate after attrs, so check if
14597c478bd9Sstevel@tonic-gate * we have both attributes, they have a non-zero va_seq, and
14607c478bd9Sstevel@tonic-gate * va_seq has changed by exactly one,
14617c478bd9Sstevel@tonic-gate * if not, turn off the before attr.
14627c478bd9Sstevel@tonic-gate */
14637c478bd9Sstevel@tonic-gate if (rwlock_ret != V_WRITELOCK_TRUE) {
14647c478bd9Sstevel@tonic-gate if (bvap == NULL || avap == NULL ||
14657c478bd9Sstevel@tonic-gate bvap->va_seq == 0 || avap->va_seq == 0 ||
14667c478bd9Sstevel@tonic-gate avap->va_seq != (bvap->va_seq + 1)) {
14677c478bd9Sstevel@tonic-gate bvap = NULL;
14687c478bd9Sstevel@tonic-gate }
14697c478bd9Sstevel@tonic-gate }
14707c478bd9Sstevel@tonic-gate
14717c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
14727c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
14737c478bd9Sstevel@tonic-gate resp->resok.count = args->count - uio.uio_resid;
14747c478bd9Sstevel@tonic-gate resp->resok.committed = args->stable;
14757c478bd9Sstevel@tonic-gate resp->resok.verf = write3verf;
1476e1adf50cSahl goto out;
14777c478bd9Sstevel@tonic-gate
1478e1adf50cSahl err:
14797c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
14807c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
14817c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
14827c478bd9Sstevel@tonic-gate } else
14837c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
1484e1adf50cSahl err1:
1485e1adf50cSahl vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
1486e1adf50cSahl out:
1487e1adf50cSahl DTRACE_NFSV3_4(op__write__done, struct svc_req *, req,
1488e1adf50cSahl cred_t *, cr, vnode_t *, vp, WRITE3res *, resp);
1489e1adf50cSahl
14907c478bd9Sstevel@tonic-gate if (vp != NULL) {
14917c478bd9Sstevel@tonic-gate if (rwlock_ret != -1)
1492cfae96c2Sjwahlig VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
14937c478bd9Sstevel@tonic-gate if (in_crit)
14947c478bd9Sstevel@tonic-gate nbl_end_crit(vp);
14957c478bd9Sstevel@tonic-gate VN_RELE(vp);
14967c478bd9Sstevel@tonic-gate }
14977c478bd9Sstevel@tonic-gate }
14987c478bd9Sstevel@tonic-gate
149927242a7cSthurlow void *
rfs3_write_getfh(WRITE3args * args)15007c478bd9Sstevel@tonic-gate rfs3_write_getfh(WRITE3args *args)
15017c478bd9Sstevel@tonic-gate {
15027c478bd9Sstevel@tonic-gate
150327242a7cSthurlow return (&args->file);
15047c478bd9Sstevel@tonic-gate }
15057c478bd9Sstevel@tonic-gate
15067c478bd9Sstevel@tonic-gate void
rfs3_create(CREATE3args * args,CREATE3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)15077c478bd9Sstevel@tonic-gate rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi,
15085cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
15097c478bd9Sstevel@tonic-gate {
15107c478bd9Sstevel@tonic-gate int error;
15117c478bd9Sstevel@tonic-gate int in_crit = 0;
15127c478bd9Sstevel@tonic-gate vnode_t *vp;
15137c478bd9Sstevel@tonic-gate vnode_t *tvp = NULL;
15147c478bd9Sstevel@tonic-gate vnode_t *dvp;
15157c478bd9Sstevel@tonic-gate struct vattr *vap;
15167c478bd9Sstevel@tonic-gate struct vattr va;
15177c478bd9Sstevel@tonic-gate struct vattr *dbvap;
15187c478bd9Sstevel@tonic-gate struct vattr dbva;
15197c478bd9Sstevel@tonic-gate struct vattr *davap;
15207c478bd9Sstevel@tonic-gate struct vattr dava;
15217c478bd9Sstevel@tonic-gate enum vcexcl excl;
15227c478bd9Sstevel@tonic-gate nfstime3 *mtime;
15237c478bd9Sstevel@tonic-gate len_t reqsize;
15247c478bd9Sstevel@tonic-gate bool_t trunc;
1525b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
1526b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate dbvap = NULL;
15297c478bd9Sstevel@tonic-gate davap = NULL;
15307c478bd9Sstevel@tonic-gate
153127242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
1532e1adf50cSahl
1533e1adf50cSahl DTRACE_NFSV3_4(op__create__start, struct svc_req *, req,
1534e1adf50cSahl cred_t *, cr, vnode_t *, dvp, CREATE3args *, args);
1535e1adf50cSahl
15367c478bd9Sstevel@tonic-gate if (dvp == NULL) {
15377c478bd9Sstevel@tonic-gate error = ESTALE;
15387c478bd9Sstevel@tonic-gate goto out;
15397c478bd9Sstevel@tonic-gate }
15407c478bd9Sstevel@tonic-gate
15417c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
1542da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
15437c478bd9Sstevel@tonic-gate davap = dbvap;
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
15467c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
15477c478bd9Sstevel@tonic-gate goto out1;
15487c478bd9Sstevel@tonic-gate }
15497c478bd9Sstevel@tonic-gate
15507c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
15517c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
15527c478bd9Sstevel@tonic-gate goto out1;
15537c478bd9Sstevel@tonic-gate }
15547c478bd9Sstevel@tonic-gate
15555cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
15567c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
15577c478bd9Sstevel@tonic-gate goto out1;
15587c478bd9Sstevel@tonic-gate }
15597c478bd9Sstevel@tonic-gate
156003986916Sjarrett if (is_system_labeled()) {
156103986916Sjarrett bslabel_t *clabel = req->rq_label;
156203986916Sjarrett
156303986916Sjarrett ASSERT(clabel != NULL);
156403986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opcreate__clabel, char *,
156503986916Sjarrett "got client label from request(1)", struct svc_req *, req);
156603986916Sjarrett
156703986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
1568bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
1569bd6f1640SJarrett Lu exi)) {
157003986916Sjarrett resp->status = NFS3ERR_ACCES;
157103986916Sjarrett goto out1;
157203986916Sjarrett }
157303986916Sjarrett }
157403986916Sjarrett }
157503986916Sjarrett
1576b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1577b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
1578b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1579b89a8333Snatalie li - Sun Microsystems - Irvine United States
1580b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
1581b89a8333Snatalie li - Sun Microsystems - Irvine United States /* This is really a Solaris EILSEQ */
1582b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
1583b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
1584b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1585b89a8333Snatalie li - Sun Microsystems - Irvine United States
15867c478bd9Sstevel@tonic-gate if (args->how.mode == EXCLUSIVE) {
15877c478bd9Sstevel@tonic-gate va.va_mask = AT_TYPE | AT_MODE | AT_MTIME;
15887c478bd9Sstevel@tonic-gate va.va_type = VREG;
15897c478bd9Sstevel@tonic-gate va.va_mode = (mode_t)0;
15907c478bd9Sstevel@tonic-gate /*
15917c478bd9Sstevel@tonic-gate * Ensure no time overflows and that types match
15927c478bd9Sstevel@tonic-gate */
15937c478bd9Sstevel@tonic-gate mtime = (nfstime3 *)&args->how.createhow3_u.verf;
15947c478bd9Sstevel@tonic-gate va.va_mtime.tv_sec = mtime->seconds % INT32_MAX;
15957c478bd9Sstevel@tonic-gate va.va_mtime.tv_nsec = mtime->nseconds;
15967c478bd9Sstevel@tonic-gate excl = EXCL;
15977c478bd9Sstevel@tonic-gate } else {
15987c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->how.createhow3_u.obj_attributes,
15997c478bd9Sstevel@tonic-gate &va);
16007c478bd9Sstevel@tonic-gate if (error)
16017c478bd9Sstevel@tonic-gate goto out;
16027c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
16037c478bd9Sstevel@tonic-gate va.va_type = VREG;
16047c478bd9Sstevel@tonic-gate if (args->how.mode == GUARDED)
16057c478bd9Sstevel@tonic-gate excl = EXCL;
16067c478bd9Sstevel@tonic-gate else {
16077c478bd9Sstevel@tonic-gate excl = NONEXCL;
16087c478bd9Sstevel@tonic-gate
16097c478bd9Sstevel@tonic-gate /*
16107c478bd9Sstevel@tonic-gate * During creation of file in non-exclusive mode
16117c478bd9Sstevel@tonic-gate * if size of file is being set then make sure
16127c478bd9Sstevel@tonic-gate * that if the file already exists that no conflicting
16137c478bd9Sstevel@tonic-gate * non-blocking mandatory locks exists in the region
16147c478bd9Sstevel@tonic-gate * being modified. If there are conflicting locks fail
16157c478bd9Sstevel@tonic-gate * the operation with EACCES.
16167c478bd9Sstevel@tonic-gate */
16177c478bd9Sstevel@tonic-gate if (va.va_mask & AT_SIZE) {
16187c478bd9Sstevel@tonic-gate struct vattr tva;
16197c478bd9Sstevel@tonic-gate
16207c478bd9Sstevel@tonic-gate /*
16217c478bd9Sstevel@tonic-gate * Does file already exist?
16227c478bd9Sstevel@tonic-gate */
1623b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &tvp,
1624da6c28aaSamw NULL, 0, NULL, cr, NULL, NULL, NULL);
16257c478bd9Sstevel@tonic-gate
16267c478bd9Sstevel@tonic-gate /*
16277c478bd9Sstevel@tonic-gate * Check to see if the file has been delegated
16287c478bd9Sstevel@tonic-gate * to a v4 client. If so, then begin recall of
16297c478bd9Sstevel@tonic-gate * the delegation and return JUKEBOX to allow
16307c478bd9Sstevel@tonic-gate * the client to retrasmit its request.
16317c478bd9Sstevel@tonic-gate */
16327c478bd9Sstevel@tonic-gate
16337c478bd9Sstevel@tonic-gate trunc = va.va_size == 0;
16347c478bd9Sstevel@tonic-gate if (!error &&
16357c478bd9Sstevel@tonic-gate rfs4_check_delegated(FWRITE, tvp, trunc)) {
16367c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
16377c478bd9Sstevel@tonic-gate goto out1;
16387c478bd9Sstevel@tonic-gate }
16397c478bd9Sstevel@tonic-gate
16407c478bd9Sstevel@tonic-gate /*
16417c478bd9Sstevel@tonic-gate * Check for NBMAND lock conflicts
16427c478bd9Sstevel@tonic-gate */
16437c478bd9Sstevel@tonic-gate if (!error && nbl_need_check(tvp)) {
16447c478bd9Sstevel@tonic-gate u_offset_t offset;
16457c478bd9Sstevel@tonic-gate ssize_t len;
16467c478bd9Sstevel@tonic-gate
16477c478bd9Sstevel@tonic-gate nbl_start_crit(tvp, RW_READER);
16487c478bd9Sstevel@tonic-gate in_crit = 1;
16497c478bd9Sstevel@tonic-gate
16507c478bd9Sstevel@tonic-gate tva.va_mask = AT_SIZE;
1651da6c28aaSamw error = VOP_GETATTR(tvp, &tva, 0, cr,
1652da6c28aaSamw NULL);
16537c478bd9Sstevel@tonic-gate /*
16547c478bd9Sstevel@tonic-gate * Can't check for conflicts, so return
16557c478bd9Sstevel@tonic-gate * error.
16567c478bd9Sstevel@tonic-gate */
16577c478bd9Sstevel@tonic-gate if (error)
16587c478bd9Sstevel@tonic-gate goto out;
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate offset = tva.va_size < va.va_size ?
16617c478bd9Sstevel@tonic-gate tva.va_size : va.va_size;
16627c478bd9Sstevel@tonic-gate len = tva.va_size < va.va_size ?
16637c478bd9Sstevel@tonic-gate va.va_size - tva.va_size :
16647c478bd9Sstevel@tonic-gate tva.va_size - va.va_size;
16657c478bd9Sstevel@tonic-gate if (nbl_conflict(tvp, NBL_WRITE,
1666da6c28aaSamw offset, len, 0, NULL)) {
16677c478bd9Sstevel@tonic-gate error = EACCES;
16687c478bd9Sstevel@tonic-gate goto out;
16697c478bd9Sstevel@tonic-gate }
16707c478bd9Sstevel@tonic-gate } else if (tvp) {
16717c478bd9Sstevel@tonic-gate VN_RELE(tvp);
16727c478bd9Sstevel@tonic-gate tvp = NULL;
16737c478bd9Sstevel@tonic-gate }
16747c478bd9Sstevel@tonic-gate }
16757c478bd9Sstevel@tonic-gate }
16767c478bd9Sstevel@tonic-gate if (va.va_mask & AT_SIZE)
16777c478bd9Sstevel@tonic-gate reqsize = va.va_size;
16787c478bd9Sstevel@tonic-gate }
16797c478bd9Sstevel@tonic-gate
16807c478bd9Sstevel@tonic-gate /*
16817c478bd9Sstevel@tonic-gate * Must specify the mode.
16827c478bd9Sstevel@tonic-gate */
16837c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
16847c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
16857c478bd9Sstevel@tonic-gate goto out1;
16867c478bd9Sstevel@tonic-gate }
16877c478bd9Sstevel@tonic-gate
16887c478bd9Sstevel@tonic-gate /*
16897c478bd9Sstevel@tonic-gate * If the filesystem is exported with nosuid, then mask off
16907c478bd9Sstevel@tonic-gate * the setuid and setgid bits.
16917c478bd9Sstevel@tonic-gate */
16927c478bd9Sstevel@tonic-gate if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID))
16937c478bd9Sstevel@tonic-gate va.va_mode &= ~(VSUID | VSGID);
16947c478bd9Sstevel@tonic-gate
16957c478bd9Sstevel@tonic-gate tryagain:
16967c478bd9Sstevel@tonic-gate /*
16977c478bd9Sstevel@tonic-gate * The file open mode used is VWRITE. If the client needs
16987c478bd9Sstevel@tonic-gate * some other semantic, then it should do the access checking
16997c478bd9Sstevel@tonic-gate * itself. It would have been nice to have the file open mode
17007c478bd9Sstevel@tonic-gate * passed as part of the arguments.
17017c478bd9Sstevel@tonic-gate */
1702b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_CREATE(dvp, name, &va, excl, VWRITE,
1703da6c28aaSamw &vp, cr, 0, NULL, NULL);
17047c478bd9Sstevel@tonic-gate
17057c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
1706da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
17077c478bd9Sstevel@tonic-gate
17087c478bd9Sstevel@tonic-gate if (error) {
17097c478bd9Sstevel@tonic-gate /*
17107c478bd9Sstevel@tonic-gate * If we got something other than file already exists
17117c478bd9Sstevel@tonic-gate * then just return this error. Otherwise, we got
17127c478bd9Sstevel@tonic-gate * EEXIST. If we were doing a GUARDED create, then
17137c478bd9Sstevel@tonic-gate * just return this error. Otherwise, we need to
17147c478bd9Sstevel@tonic-gate * make sure that this wasn't a duplicate of an
17157c478bd9Sstevel@tonic-gate * exclusive create request.
17167c478bd9Sstevel@tonic-gate *
17177c478bd9Sstevel@tonic-gate * The assumption is made that a non-exclusive create
17187c478bd9Sstevel@tonic-gate * request will never return EEXIST.
17197c478bd9Sstevel@tonic-gate */
17207c478bd9Sstevel@tonic-gate if (error != EEXIST || args->how.mode == GUARDED)
17217c478bd9Sstevel@tonic-gate goto out;
17227c478bd9Sstevel@tonic-gate /*
17237c478bd9Sstevel@tonic-gate * Lookup the file so that we can get a vnode for it.
17247c478bd9Sstevel@tonic-gate */
1725b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &vp, NULL, 0,
1726da6c28aaSamw NULL, cr, NULL, NULL, NULL);
17277c478bd9Sstevel@tonic-gate if (error) {
17287c478bd9Sstevel@tonic-gate /*
17297c478bd9Sstevel@tonic-gate * We couldn't find the file that we thought that
17307c478bd9Sstevel@tonic-gate * we just created. So, we'll just try creating
17317c478bd9Sstevel@tonic-gate * it again.
17327c478bd9Sstevel@tonic-gate */
17337c478bd9Sstevel@tonic-gate if (error == ENOENT)
17347c478bd9Sstevel@tonic-gate goto tryagain;
17357c478bd9Sstevel@tonic-gate goto out;
17367c478bd9Sstevel@tonic-gate }
17377c478bd9Sstevel@tonic-gate
17387c478bd9Sstevel@tonic-gate /*
17397c478bd9Sstevel@tonic-gate * If the file is delegated to a v4 client, go ahead
17407c478bd9Sstevel@tonic-gate * and initiate recall, this create is a hint that a
17417c478bd9Sstevel@tonic-gate * conflicting v3 open has occurred.
17427c478bd9Sstevel@tonic-gate */
17437c478bd9Sstevel@tonic-gate
17447c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, vp, FALSE)) {
17457c478bd9Sstevel@tonic-gate VN_RELE(vp);
17467c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
17477c478bd9Sstevel@tonic-gate goto out1;
17487c478bd9Sstevel@tonic-gate }
17497c478bd9Sstevel@tonic-gate
17507c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1751da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
17527c478bd9Sstevel@tonic-gate
17537c478bd9Sstevel@tonic-gate mtime = (nfstime3 *)&args->how.createhow3_u.verf;
17547c478bd9Sstevel@tonic-gate /* % with INT32_MAX to prevent overflows */
17557c478bd9Sstevel@tonic-gate if (args->how.mode == EXCLUSIVE && (vap == NULL ||
17567c478bd9Sstevel@tonic-gate vap->va_mtime.tv_sec !=
17577c478bd9Sstevel@tonic-gate (mtime->seconds % INT32_MAX) ||
17587c478bd9Sstevel@tonic-gate vap->va_mtime.tv_nsec != mtime->nseconds)) {
17597c478bd9Sstevel@tonic-gate VN_RELE(vp);
17607c478bd9Sstevel@tonic-gate error = EEXIST;
17617c478bd9Sstevel@tonic-gate goto out;
17627c478bd9Sstevel@tonic-gate }
17637c478bd9Sstevel@tonic-gate } else {
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate if ((args->how.mode == UNCHECKED ||
17667c478bd9Sstevel@tonic-gate args->how.mode == GUARDED) &&
17677c478bd9Sstevel@tonic-gate args->how.createhow3_u.obj_attributes.size.set_it &&
17687c478bd9Sstevel@tonic-gate va.va_size == 0)
17697c478bd9Sstevel@tonic-gate trunc = TRUE;
17707c478bd9Sstevel@tonic-gate else
17717c478bd9Sstevel@tonic-gate trunc = FALSE;
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, vp, trunc)) {
17747c478bd9Sstevel@tonic-gate VN_RELE(vp);
17757c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
17767c478bd9Sstevel@tonic-gate goto out1;
17777c478bd9Sstevel@tonic-gate }
17787c478bd9Sstevel@tonic-gate
17797c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1780da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
17817c478bd9Sstevel@tonic-gate
17827c478bd9Sstevel@tonic-gate /*
17837c478bd9Sstevel@tonic-gate * We need to check to make sure that the file got
17847c478bd9Sstevel@tonic-gate * created to the indicated size. If not, we do a
17857c478bd9Sstevel@tonic-gate * setattr to try to change the size, but we don't
17867c478bd9Sstevel@tonic-gate * try too hard. This shouldn't a problem as most
17877c478bd9Sstevel@tonic-gate * clients will only specifiy a size of zero which
17887c478bd9Sstevel@tonic-gate * local file systems handle. However, even if
17897c478bd9Sstevel@tonic-gate * the client does specify a non-zero size, it can
17907c478bd9Sstevel@tonic-gate * still recover by checking the size of the file
17917c478bd9Sstevel@tonic-gate * after it has created it and then issue a setattr
17927c478bd9Sstevel@tonic-gate * request of its own to set the size of the file.
17937c478bd9Sstevel@tonic-gate */
17947c478bd9Sstevel@tonic-gate if (vap != NULL &&
17957c478bd9Sstevel@tonic-gate (args->how.mode == UNCHECKED ||
17967c478bd9Sstevel@tonic-gate args->how.mode == GUARDED) &&
17977c478bd9Sstevel@tonic-gate args->how.createhow3_u.obj_attributes.size.set_it &&
17987c478bd9Sstevel@tonic-gate vap->va_size != reqsize) {
17997c478bd9Sstevel@tonic-gate va.va_mask = AT_SIZE;
18007c478bd9Sstevel@tonic-gate va.va_size = reqsize;
18017c478bd9Sstevel@tonic-gate (void) VOP_SETATTR(vp, &va, 0, cr, NULL);
18027c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1803da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
18047c478bd9Sstevel@tonic-gate }
18057c478bd9Sstevel@tonic-gate }
18067c478bd9Sstevel@tonic-gate
1807b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->where.name)
1808b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
1809b89a8333Snatalie li - Sun Microsystems - Irvine United States
18107c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
18117c478bd9Sstevel@tonic-gate if (error)
18127c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
18137c478bd9Sstevel@tonic-gate else
18147c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
18157c478bd9Sstevel@tonic-gate
18167c478bd9Sstevel@tonic-gate /*
18177c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
18187c478bd9Sstevel@tonic-gate */
1819da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
1820da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
18217c478bd9Sstevel@tonic-gate
18227c478bd9Sstevel@tonic-gate VN_RELE(vp);
18237c478bd9Sstevel@tonic-gate if (tvp != NULL) {
18247c478bd9Sstevel@tonic-gate if (in_crit)
18257c478bd9Sstevel@tonic-gate nbl_end_crit(tvp);
18267c478bd9Sstevel@tonic-gate VN_RELE(tvp);
18277c478bd9Sstevel@tonic-gate }
18287c478bd9Sstevel@tonic-gate
18297c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
18307c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
18317c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1832e1adf50cSahl
1833e1adf50cSahl DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1834e1adf50cSahl cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1835e1adf50cSahl
1836e1adf50cSahl VN_RELE(dvp);
18377c478bd9Sstevel@tonic-gate return;
18387c478bd9Sstevel@tonic-gate
18397c478bd9Sstevel@tonic-gate out:
18407c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
18417c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
18427c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
18437c478bd9Sstevel@tonic-gate } else
18447c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
18457c478bd9Sstevel@tonic-gate out1:
1846e1adf50cSahl DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1847e1adf50cSahl cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1848e1adf50cSahl
1849b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->where.name)
1850b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
1851b89a8333Snatalie li - Sun Microsystems - Irvine United States
18527c478bd9Sstevel@tonic-gate if (tvp != NULL) {
18537c478bd9Sstevel@tonic-gate if (in_crit)
18547c478bd9Sstevel@tonic-gate nbl_end_crit(tvp);
18557c478bd9Sstevel@tonic-gate VN_RELE(tvp);
18567c478bd9Sstevel@tonic-gate }
18577c478bd9Sstevel@tonic-gate if (dvp != NULL)
18587c478bd9Sstevel@tonic-gate VN_RELE(dvp);
18597c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
18607c478bd9Sstevel@tonic-gate }
18617c478bd9Sstevel@tonic-gate
186227242a7cSthurlow void *
rfs3_create_getfh(CREATE3args * args)18637c478bd9Sstevel@tonic-gate rfs3_create_getfh(CREATE3args *args)
18647c478bd9Sstevel@tonic-gate {
18657c478bd9Sstevel@tonic-gate
186627242a7cSthurlow return (&args->where.dir);
18677c478bd9Sstevel@tonic-gate }
18687c478bd9Sstevel@tonic-gate
18697c478bd9Sstevel@tonic-gate void
rfs3_mkdir(MKDIR3args * args,MKDIR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)18707c478bd9Sstevel@tonic-gate rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi,
18715cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
18727c478bd9Sstevel@tonic-gate {
18737c478bd9Sstevel@tonic-gate int error;
18747c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
18757c478bd9Sstevel@tonic-gate vnode_t *dvp;
18767c478bd9Sstevel@tonic-gate struct vattr *vap;
18777c478bd9Sstevel@tonic-gate struct vattr va;
18787c478bd9Sstevel@tonic-gate struct vattr *dbvap;
18797c478bd9Sstevel@tonic-gate struct vattr dbva;
18807c478bd9Sstevel@tonic-gate struct vattr *davap;
18817c478bd9Sstevel@tonic-gate struct vattr dava;
1882b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
1883b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
18847c478bd9Sstevel@tonic-gate
18857c478bd9Sstevel@tonic-gate dbvap = NULL;
18867c478bd9Sstevel@tonic-gate davap = NULL;
18877c478bd9Sstevel@tonic-gate
188827242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
1889e1adf50cSahl
1890e1adf50cSahl DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req,
1891e1adf50cSahl cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args);
1892e1adf50cSahl
18937c478bd9Sstevel@tonic-gate if (dvp == NULL) {
18947c478bd9Sstevel@tonic-gate error = ESTALE;
18957c478bd9Sstevel@tonic-gate goto out;
18967c478bd9Sstevel@tonic-gate }
18977c478bd9Sstevel@tonic-gate
18987c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
1899da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
19007c478bd9Sstevel@tonic-gate davap = dbvap;
19017c478bd9Sstevel@tonic-gate
19027c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
19037c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
19047c478bd9Sstevel@tonic-gate goto out1;
19057c478bd9Sstevel@tonic-gate }
19067c478bd9Sstevel@tonic-gate
19077c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
19087c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
19097c478bd9Sstevel@tonic-gate goto out1;
19107c478bd9Sstevel@tonic-gate }
19117c478bd9Sstevel@tonic-gate
19125cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
19137c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
19147c478bd9Sstevel@tonic-gate goto out1;
19157c478bd9Sstevel@tonic-gate }
19167c478bd9Sstevel@tonic-gate
191703986916Sjarrett if (is_system_labeled()) {
191803986916Sjarrett bslabel_t *clabel = req->rq_label;
191903986916Sjarrett
192003986916Sjarrett ASSERT(clabel != NULL);
192103986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opmkdir__clabel, char *,
192203986916Sjarrett "got client label from request(1)", struct svc_req *, req);
192303986916Sjarrett
192403986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
1925bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
1926bd6f1640SJarrett Lu exi)) {
192703986916Sjarrett resp->status = NFS3ERR_ACCES;
192803986916Sjarrett goto out1;
192903986916Sjarrett }
193003986916Sjarrett }
193103986916Sjarrett }
193203986916Sjarrett
19337c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->attributes, &va);
19347c478bd9Sstevel@tonic-gate if (error)
19357c478bd9Sstevel@tonic-gate goto out;
19367c478bd9Sstevel@tonic-gate
19377c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
19387c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
19397c478bd9Sstevel@tonic-gate goto out1;
19407c478bd9Sstevel@tonic-gate }
19417c478bd9Sstevel@tonic-gate
1942b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1943b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
1944b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1945b89a8333Snatalie li - Sun Microsystems - Irvine United States
1946b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
1947b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
1948b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
1949b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1950b89a8333Snatalie li - Sun Microsystems - Irvine United States
19517c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
19527c478bd9Sstevel@tonic-gate va.va_type = VDIR;
19537c478bd9Sstevel@tonic-gate
1954b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL);
1955b89a8333Snatalie li - Sun Microsystems - Irvine United States
1956b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->where.name)
1957b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
19587c478bd9Sstevel@tonic-gate
19597c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
1960da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
19617c478bd9Sstevel@tonic-gate
19627c478bd9Sstevel@tonic-gate /*
19637c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
19647c478bd9Sstevel@tonic-gate */
1965da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
19667c478bd9Sstevel@tonic-gate
19677c478bd9Sstevel@tonic-gate if (error)
19687c478bd9Sstevel@tonic-gate goto out;
19697c478bd9Sstevel@tonic-gate
19707c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
19717c478bd9Sstevel@tonic-gate if (error)
19727c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
19737c478bd9Sstevel@tonic-gate else
19747c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
19757c478bd9Sstevel@tonic-gate
19767c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
1977da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
19787c478bd9Sstevel@tonic-gate
19797c478bd9Sstevel@tonic-gate /*
19807c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
19817c478bd9Sstevel@tonic-gate */
1982da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
19837c478bd9Sstevel@tonic-gate
19847c478bd9Sstevel@tonic-gate VN_RELE(vp);
19857c478bd9Sstevel@tonic-gate
19867c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
19877c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
19887c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1989e1adf50cSahl
1990e1adf50cSahl DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
1991e1adf50cSahl cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
1992e1adf50cSahl VN_RELE(dvp);
1993e1adf50cSahl
19947c478bd9Sstevel@tonic-gate return;
19957c478bd9Sstevel@tonic-gate
19967c478bd9Sstevel@tonic-gate out:
19977c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
19987c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
19997c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
20007c478bd9Sstevel@tonic-gate } else
20017c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
20027c478bd9Sstevel@tonic-gate out1:
2003e1adf50cSahl DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
2004e1adf50cSahl cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
20057c478bd9Sstevel@tonic-gate if (dvp != NULL)
20067c478bd9Sstevel@tonic-gate VN_RELE(dvp);
20077c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
20087c478bd9Sstevel@tonic-gate }
20097c478bd9Sstevel@tonic-gate
201027242a7cSthurlow void *
rfs3_mkdir_getfh(MKDIR3args * args)20117c478bd9Sstevel@tonic-gate rfs3_mkdir_getfh(MKDIR3args *args)
20127c478bd9Sstevel@tonic-gate {
20137c478bd9Sstevel@tonic-gate
201427242a7cSthurlow return (&args->where.dir);
20157c478bd9Sstevel@tonic-gate }
20167c478bd9Sstevel@tonic-gate
20177c478bd9Sstevel@tonic-gate void
rfs3_symlink(SYMLINK3args * args,SYMLINK3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)20187c478bd9Sstevel@tonic-gate rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi,
20195cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
20207c478bd9Sstevel@tonic-gate {
20217c478bd9Sstevel@tonic-gate int error;
20227c478bd9Sstevel@tonic-gate vnode_t *vp;
20237c478bd9Sstevel@tonic-gate vnode_t *dvp;
20247c478bd9Sstevel@tonic-gate struct vattr *vap;
20257c478bd9Sstevel@tonic-gate struct vattr va;
20267c478bd9Sstevel@tonic-gate struct vattr *dbvap;
20277c478bd9Sstevel@tonic-gate struct vattr dbva;
20287c478bd9Sstevel@tonic-gate struct vattr *davap;
20297c478bd9Sstevel@tonic-gate struct vattr dava;
2030b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2031b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
2032b89a8333Snatalie li - Sun Microsystems - Irvine United States char *symdata = NULL;
20337c478bd9Sstevel@tonic-gate
20347c478bd9Sstevel@tonic-gate dbvap = NULL;
20357c478bd9Sstevel@tonic-gate davap = NULL;
20367c478bd9Sstevel@tonic-gate
203727242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
2038e1adf50cSahl
2039e1adf50cSahl DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req,
2040e1adf50cSahl cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args);
2041e1adf50cSahl
20427c478bd9Sstevel@tonic-gate if (dvp == NULL) {
20437c478bd9Sstevel@tonic-gate error = ESTALE;
2044e1adf50cSahl goto err;
20457c478bd9Sstevel@tonic-gate }
20467c478bd9Sstevel@tonic-gate
20477c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
2048da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
20497c478bd9Sstevel@tonic-gate davap = dbvap;
20507c478bd9Sstevel@tonic-gate
20517c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
20527c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2053e1adf50cSahl goto err1;
20547c478bd9Sstevel@tonic-gate }
20557c478bd9Sstevel@tonic-gate
20567c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
20577c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2058e1adf50cSahl goto err1;
20597c478bd9Sstevel@tonic-gate }
20607c478bd9Sstevel@tonic-gate
20615cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
20627c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2063e1adf50cSahl goto err1;
20647c478bd9Sstevel@tonic-gate }
20657c478bd9Sstevel@tonic-gate
206603986916Sjarrett if (is_system_labeled()) {
206703986916Sjarrett bslabel_t *clabel = req->rq_label;
206803986916Sjarrett
206903986916Sjarrett ASSERT(clabel != NULL);
207003986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opsymlink__clabel, char *,
207103986916Sjarrett "got client label from request(1)", struct svc_req *, req);
207203986916Sjarrett
207303986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2074bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2075bd6f1640SJarrett Lu exi)) {
207603986916Sjarrett resp->status = NFS3ERR_ACCES;
2077e1adf50cSahl goto err1;
207803986916Sjarrett }
207903986916Sjarrett }
208003986916Sjarrett }
208103986916Sjarrett
20827c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(&args->symlink.symlink_attributes, &va);
20837c478bd9Sstevel@tonic-gate if (error)
2084e1adf50cSahl goto err;
20857c478bd9Sstevel@tonic-gate
20867c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
20877c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
2088e1adf50cSahl goto err1;
20897c478bd9Sstevel@tonic-gate }
20907c478bd9Sstevel@tonic-gate
20917c478bd9Sstevel@tonic-gate if (args->symlink.symlink_data == nfs3nametoolong) {
20927c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2093e1adf50cSahl goto err1;
20947c478bd9Sstevel@tonic-gate }
20957c478bd9Sstevel@tonic-gate
2096b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2097b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
2098b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2099b89a8333Snatalie li - Sun Microsystems - Irvine United States
2100b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2101b89a8333Snatalie li - Sun Microsystems - Irvine United States /* This is really a Solaris EILSEQ */
2102b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2103b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2104b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2105b89a8333Snatalie li - Sun Microsystems - Irvine United States
2106b89a8333Snatalie li - Sun Microsystems - Irvine United States symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data,
2107b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2108b89a8333Snatalie li - Sun Microsystems - Irvine United States if (symdata == NULL) {
2109b89a8333Snatalie li - Sun Microsystems - Irvine United States /* This is really a Solaris EILSEQ */
2110b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2111b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2112b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2113b89a8333Snatalie li - Sun Microsystems - Irvine United States
2114b89a8333Snatalie li - Sun Microsystems - Irvine United States
21157c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
21167c478bd9Sstevel@tonic-gate va.va_type = VLNK;
21177c478bd9Sstevel@tonic-gate
2118b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0);
21197c478bd9Sstevel@tonic-gate
21207c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
2121da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
21227c478bd9Sstevel@tonic-gate
21237c478bd9Sstevel@tonic-gate if (error)
2124e1adf50cSahl goto err;
21257c478bd9Sstevel@tonic-gate
2126b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
2127da6c28aaSamw NULL, NULL, NULL);
21287c478bd9Sstevel@tonic-gate
21297c478bd9Sstevel@tonic-gate /*
21307c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
21317c478bd9Sstevel@tonic-gate */
2132da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
21337c478bd9Sstevel@tonic-gate
21347c478bd9Sstevel@tonic-gate
21357c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
21367c478bd9Sstevel@tonic-gate if (error) {
21377c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
21387c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
21397c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2140e1adf50cSahl goto out;
21417c478bd9Sstevel@tonic-gate }
21427c478bd9Sstevel@tonic-gate
21437c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
21447c478bd9Sstevel@tonic-gate if (error)
21457c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
21467c478bd9Sstevel@tonic-gate else
21477c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
21487c478bd9Sstevel@tonic-gate
21497c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
2150da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate /*
21537c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
21547c478bd9Sstevel@tonic-gate */
2155da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
21567c478bd9Sstevel@tonic-gate
21577c478bd9Sstevel@tonic-gate VN_RELE(vp);
21587c478bd9Sstevel@tonic-gate
21597c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
21607c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2161e1adf50cSahl goto out;
21627c478bd9Sstevel@tonic-gate
2163e1adf50cSahl err:
21647c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
21657c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
21667c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
21677c478bd9Sstevel@tonic-gate } else
21687c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2169e1adf50cSahl err1:
2170e1adf50cSahl vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2171e1adf50cSahl out:
2172b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->where.name)
2173b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2174b89a8333Snatalie li - Sun Microsystems - Irvine United States if (symdata != NULL && symdata != args->symlink.symlink_data)
2175b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(symdata, MAXPATHLEN + 1);
2176b89a8333Snatalie li - Sun Microsystems - Irvine United States
2177e1adf50cSahl DTRACE_NFSV3_4(op__symlink__done, struct svc_req *, req,
2178e1adf50cSahl cred_t *, cr, vnode_t *, dvp, SYMLINK3res *, resp);
2179e1adf50cSahl
21807c478bd9Sstevel@tonic-gate if (dvp != NULL)
21817c478bd9Sstevel@tonic-gate VN_RELE(dvp);
21827c478bd9Sstevel@tonic-gate }
21837c478bd9Sstevel@tonic-gate
218427242a7cSthurlow void *
rfs3_symlink_getfh(SYMLINK3args * args)21857c478bd9Sstevel@tonic-gate rfs3_symlink_getfh(SYMLINK3args *args)
21867c478bd9Sstevel@tonic-gate {
21877c478bd9Sstevel@tonic-gate
218827242a7cSthurlow return (&args->where.dir);
21897c478bd9Sstevel@tonic-gate }
21907c478bd9Sstevel@tonic-gate
21917c478bd9Sstevel@tonic-gate void
rfs3_mknod(MKNOD3args * args,MKNOD3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)21927c478bd9Sstevel@tonic-gate rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi,
21935cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
21947c478bd9Sstevel@tonic-gate {
21957c478bd9Sstevel@tonic-gate int error;
21967c478bd9Sstevel@tonic-gate vnode_t *vp;
2197fd7da618Sgt29601 vnode_t *realvp;
21987c478bd9Sstevel@tonic-gate vnode_t *dvp;
21997c478bd9Sstevel@tonic-gate struct vattr *vap;
22007c478bd9Sstevel@tonic-gate struct vattr va;
22017c478bd9Sstevel@tonic-gate struct vattr *dbvap;
22027c478bd9Sstevel@tonic-gate struct vattr dbva;
22037c478bd9Sstevel@tonic-gate struct vattr *davap;
22047c478bd9Sstevel@tonic-gate struct vattr dava;
22057c478bd9Sstevel@tonic-gate int mode;
22067c478bd9Sstevel@tonic-gate enum vcexcl excl;
2207b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2208b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
22097c478bd9Sstevel@tonic-gate
22107c478bd9Sstevel@tonic-gate dbvap = NULL;
22117c478bd9Sstevel@tonic-gate davap = NULL;
22127c478bd9Sstevel@tonic-gate
221327242a7cSthurlow dvp = nfs3_fhtovp(&args->where.dir, exi);
2214e1adf50cSahl
2215e1adf50cSahl DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req,
2216e1adf50cSahl cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args);
2217e1adf50cSahl
22187c478bd9Sstevel@tonic-gate if (dvp == NULL) {
22197c478bd9Sstevel@tonic-gate error = ESTALE;
22207c478bd9Sstevel@tonic-gate goto out;
22217c478bd9Sstevel@tonic-gate }
22227c478bd9Sstevel@tonic-gate
22237c478bd9Sstevel@tonic-gate dbva.va_mask = AT_ALL;
2224da6c28aaSamw dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
22257c478bd9Sstevel@tonic-gate davap = dbvap;
22267c478bd9Sstevel@tonic-gate
22277c478bd9Sstevel@tonic-gate if (args->where.name == nfs3nametoolong) {
22287c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
22297c478bd9Sstevel@tonic-gate goto out1;
22307c478bd9Sstevel@tonic-gate }
22317c478bd9Sstevel@tonic-gate
22327c478bd9Sstevel@tonic-gate if (args->where.name == NULL || *(args->where.name) == '\0') {
22337c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
22347c478bd9Sstevel@tonic-gate goto out1;
22357c478bd9Sstevel@tonic-gate }
22367c478bd9Sstevel@tonic-gate
22375cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
22387c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
22397c478bd9Sstevel@tonic-gate goto out1;
22407c478bd9Sstevel@tonic-gate }
22417c478bd9Sstevel@tonic-gate
224203986916Sjarrett if (is_system_labeled()) {
224303986916Sjarrett bslabel_t *clabel = req->rq_label;
224403986916Sjarrett
224503986916Sjarrett ASSERT(clabel != NULL);
224603986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opmknod__clabel, char *,
224703986916Sjarrett "got client label from request(1)", struct svc_req *, req);
224803986916Sjarrett
224903986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2250bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2251bd6f1640SJarrett Lu exi)) {
225203986916Sjarrett resp->status = NFS3ERR_ACCES;
225303986916Sjarrett goto out1;
225403986916Sjarrett }
225503986916Sjarrett }
225603986916Sjarrett }
225703986916Sjarrett
22587c478bd9Sstevel@tonic-gate switch (args->what.type) {
22597c478bd9Sstevel@tonic-gate case NF3CHR:
22607c478bd9Sstevel@tonic-gate case NF3BLK:
22617c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(
22627c478bd9Sstevel@tonic-gate &args->what.mknoddata3_u.device.dev_attributes, &va);
22637c478bd9Sstevel@tonic-gate if (error)
22647c478bd9Sstevel@tonic-gate goto out;
22657c478bd9Sstevel@tonic-gate if (secpolicy_sys_devices(cr) != 0) {
22667c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_PERM;
22677c478bd9Sstevel@tonic-gate goto out1;
22687c478bd9Sstevel@tonic-gate }
22697c478bd9Sstevel@tonic-gate if (args->what.type == NF3CHR)
22707c478bd9Sstevel@tonic-gate va.va_type = VCHR;
22717c478bd9Sstevel@tonic-gate else
22727c478bd9Sstevel@tonic-gate va.va_type = VBLK;
22737c478bd9Sstevel@tonic-gate va.va_rdev = makedevice(
22747c478bd9Sstevel@tonic-gate args->what.mknoddata3_u.device.spec.specdata1,
22757c478bd9Sstevel@tonic-gate args->what.mknoddata3_u.device.spec.specdata2);
22767c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE | AT_RDEV;
22777c478bd9Sstevel@tonic-gate break;
22787c478bd9Sstevel@tonic-gate case NF3SOCK:
22797c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(
22807c478bd9Sstevel@tonic-gate &args->what.mknoddata3_u.pipe_attributes, &va);
22817c478bd9Sstevel@tonic-gate if (error)
22827c478bd9Sstevel@tonic-gate goto out;
22837c478bd9Sstevel@tonic-gate va.va_type = VSOCK;
22847c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
22857c478bd9Sstevel@tonic-gate break;
22867c478bd9Sstevel@tonic-gate case NF3FIFO:
22877c478bd9Sstevel@tonic-gate error = sattr3_to_vattr(
22887c478bd9Sstevel@tonic-gate &args->what.mknoddata3_u.pipe_attributes, &va);
22897c478bd9Sstevel@tonic-gate if (error)
22907c478bd9Sstevel@tonic-gate goto out;
22917c478bd9Sstevel@tonic-gate va.va_type = VFIFO;
22927c478bd9Sstevel@tonic-gate va.va_mask |= AT_TYPE;
22937c478bd9Sstevel@tonic-gate break;
22947c478bd9Sstevel@tonic-gate default:
22957c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_BADTYPE;
22967c478bd9Sstevel@tonic-gate goto out1;
22977c478bd9Sstevel@tonic-gate }
22987c478bd9Sstevel@tonic-gate
22997c478bd9Sstevel@tonic-gate /*
23007c478bd9Sstevel@tonic-gate * Must specify the mode.
23017c478bd9Sstevel@tonic-gate */
23027c478bd9Sstevel@tonic-gate if (!(va.va_mask & AT_MODE)) {
23037c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
23047c478bd9Sstevel@tonic-gate goto out1;
23057c478bd9Sstevel@tonic-gate }
23067c478bd9Sstevel@tonic-gate
2307b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2308b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->where.name,
2309b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2310b89a8333Snatalie li - Sun Microsystems - Irvine United States
2311b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2312b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2313b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
2314b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2315b89a8333Snatalie li - Sun Microsystems - Irvine United States
23167c478bd9Sstevel@tonic-gate excl = EXCL;
23177c478bd9Sstevel@tonic-gate
23187c478bd9Sstevel@tonic-gate mode = 0;
23197c478bd9Sstevel@tonic-gate
2320b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_CREATE(dvp, name, &va, excl, mode,
2321da6c28aaSamw &vp, cr, 0, NULL, NULL);
23227c478bd9Sstevel@tonic-gate
2323b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->where.name)
2324b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2325b89a8333Snatalie li - Sun Microsystems - Irvine United States
23267c478bd9Sstevel@tonic-gate dava.va_mask = AT_ALL;
2327da6c28aaSamw davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
23287c478bd9Sstevel@tonic-gate
23297c478bd9Sstevel@tonic-gate /*
23307c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
23317c478bd9Sstevel@tonic-gate */
2332da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
23337c478bd9Sstevel@tonic-gate
23347c478bd9Sstevel@tonic-gate if (error)
23357c478bd9Sstevel@tonic-gate goto out;
23367c478bd9Sstevel@tonic-gate
23377c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
23387c478bd9Sstevel@tonic-gate
23397c478bd9Sstevel@tonic-gate error = makefh3(&resp->resok.obj.handle, vp, exi);
23407c478bd9Sstevel@tonic-gate if (error)
23417c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = FALSE;
23427c478bd9Sstevel@tonic-gate else
23437c478bd9Sstevel@tonic-gate resp->resok.obj.handle_follows = TRUE;
23447c478bd9Sstevel@tonic-gate
23457c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
2346da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
23477c478bd9Sstevel@tonic-gate
23487c478bd9Sstevel@tonic-gate /*
23497c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
2350fd7da618Sgt29601 *
2351fd7da618Sgt29601 * if a underlying vp exists, pass it to VOP_FSYNC
23527c478bd9Sstevel@tonic-gate */
2353fd7da618Sgt29601 if (VOP_REALVP(vp, &realvp, NULL) == 0)
2354fd7da618Sgt29601 (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL);
2355fd7da618Sgt29601 else
2356da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
23577c478bd9Sstevel@tonic-gate
23587c478bd9Sstevel@tonic-gate VN_RELE(vp);
23597c478bd9Sstevel@tonic-gate
23607c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
23617c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2362e1adf50cSahl DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2363e1adf50cSahl cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
2364e1adf50cSahl VN_RELE(dvp);
23657c478bd9Sstevel@tonic-gate return;
23667c478bd9Sstevel@tonic-gate
23677c478bd9Sstevel@tonic-gate out:
23687c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
23697c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
23707c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
23717c478bd9Sstevel@tonic-gate } else
23727c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
23737c478bd9Sstevel@tonic-gate out1:
2374e1adf50cSahl DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2375e1adf50cSahl cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
23767c478bd9Sstevel@tonic-gate if (dvp != NULL)
23777c478bd9Sstevel@tonic-gate VN_RELE(dvp);
23787c478bd9Sstevel@tonic-gate vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
23797c478bd9Sstevel@tonic-gate }
23807c478bd9Sstevel@tonic-gate
238127242a7cSthurlow void *
rfs3_mknod_getfh(MKNOD3args * args)23827c478bd9Sstevel@tonic-gate rfs3_mknod_getfh(MKNOD3args *args)
23837c478bd9Sstevel@tonic-gate {
23847c478bd9Sstevel@tonic-gate
238527242a7cSthurlow return (&args->where.dir);
23867c478bd9Sstevel@tonic-gate }
23877c478bd9Sstevel@tonic-gate
23887c478bd9Sstevel@tonic-gate void
rfs3_remove(REMOVE3args * args,REMOVE3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)23897c478bd9Sstevel@tonic-gate rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi,
23905cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
23917c478bd9Sstevel@tonic-gate {
23927c478bd9Sstevel@tonic-gate int error = 0;
23937c478bd9Sstevel@tonic-gate vnode_t *vp;
23947c478bd9Sstevel@tonic-gate struct vattr *bvap;
23957c478bd9Sstevel@tonic-gate struct vattr bva;
23967c478bd9Sstevel@tonic-gate struct vattr *avap;
23977c478bd9Sstevel@tonic-gate struct vattr ava;
23987c478bd9Sstevel@tonic-gate vnode_t *targvp = NULL;
2399b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2400b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
24017c478bd9Sstevel@tonic-gate
24027c478bd9Sstevel@tonic-gate bvap = NULL;
24037c478bd9Sstevel@tonic-gate avap = NULL;
24047c478bd9Sstevel@tonic-gate
240527242a7cSthurlow vp = nfs3_fhtovp(&args->object.dir, exi);
2406e1adf50cSahl
2407e1adf50cSahl DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req,
2408e1adf50cSahl cred_t *, cr, vnode_t *, vp, REMOVE3args *, args);
2409e1adf50cSahl
24107c478bd9Sstevel@tonic-gate if (vp == NULL) {
24117c478bd9Sstevel@tonic-gate error = ESTALE;
2412e1adf50cSahl goto err;
24137c478bd9Sstevel@tonic-gate }
24147c478bd9Sstevel@tonic-gate
24157c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
2416da6c28aaSamw bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
24177c478bd9Sstevel@tonic-gate avap = bvap;
24187c478bd9Sstevel@tonic-gate
24197c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
24207c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
2421e1adf50cSahl goto err1;
24227c478bd9Sstevel@tonic-gate }
24237c478bd9Sstevel@tonic-gate
24247c478bd9Sstevel@tonic-gate if (args->object.name == nfs3nametoolong) {
24257c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2426e1adf50cSahl goto err1;
24277c478bd9Sstevel@tonic-gate }
24287c478bd9Sstevel@tonic-gate
24297c478bd9Sstevel@tonic-gate if (args->object.name == NULL || *(args->object.name) == '\0') {
24307c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2431e1adf50cSahl goto err1;
24327c478bd9Sstevel@tonic-gate }
24337c478bd9Sstevel@tonic-gate
24345cb0d679SMarcel Telka if (rdonly(ro, vp)) {
24357c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2436e1adf50cSahl goto err1;
24377c478bd9Sstevel@tonic-gate }
24387c478bd9Sstevel@tonic-gate
243903986916Sjarrett if (is_system_labeled()) {
244003986916Sjarrett bslabel_t *clabel = req->rq_label;
244103986916Sjarrett
244203986916Sjarrett ASSERT(clabel != NULL);
244303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opremove__clabel, char *,
244403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
244503986916Sjarrett
244603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2447bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2448bd6f1640SJarrett Lu exi)) {
244903986916Sjarrett resp->status = NFS3ERR_ACCES;
2450e1adf50cSahl goto err1;
245103986916Sjarrett }
245203986916Sjarrett }
245303986916Sjarrett }
245403986916Sjarrett
2455b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2456b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->object.name,
2457b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2458b89a8333Snatalie li - Sun Microsystems - Irvine United States
2459b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2460b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2461b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2462b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2463b89a8333Snatalie li - Sun Microsystems - Irvine United States
24647c478bd9Sstevel@tonic-gate /*
24657c478bd9Sstevel@tonic-gate * Check for a conflict with a non-blocking mandatory share
24667c478bd9Sstevel@tonic-gate * reservation and V4 delegations
24677c478bd9Sstevel@tonic-gate */
2468b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(vp, name, &targvp, NULL, 0,
2469da6c28aaSamw NULL, cr, NULL, NULL, NULL);
24707c478bd9Sstevel@tonic-gate if (error != 0)
2471e1adf50cSahl goto err;
24727c478bd9Sstevel@tonic-gate
24737c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
24747c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2475e1adf50cSahl goto err1;
24767c478bd9Sstevel@tonic-gate }
24777c478bd9Sstevel@tonic-gate
24787c478bd9Sstevel@tonic-gate if (!nbl_need_check(targvp)) {
2479b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_REMOVE(vp, name, cr, NULL, 0);
24807c478bd9Sstevel@tonic-gate } else {
24817c478bd9Sstevel@tonic-gate nbl_start_crit(targvp, RW_READER);
2482da6c28aaSamw if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
24837c478bd9Sstevel@tonic-gate error = EACCES;
24847c478bd9Sstevel@tonic-gate } else {
2485b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_REMOVE(vp, name, cr, NULL, 0);
24867c478bd9Sstevel@tonic-gate }
24877c478bd9Sstevel@tonic-gate nbl_end_crit(targvp);
24887c478bd9Sstevel@tonic-gate }
24897c478bd9Sstevel@tonic-gate VN_RELE(targvp);
24907c478bd9Sstevel@tonic-gate targvp = NULL;
24917c478bd9Sstevel@tonic-gate
24927c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
2493da6c28aaSamw avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
24947c478bd9Sstevel@tonic-gate
24957c478bd9Sstevel@tonic-gate /*
24967c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
24977c478bd9Sstevel@tonic-gate */
2498da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
24997c478bd9Sstevel@tonic-gate
25007c478bd9Sstevel@tonic-gate if (error)
2501e1adf50cSahl goto err;
25027c478bd9Sstevel@tonic-gate
25037c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
25047c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2505e1adf50cSahl goto out;
25067c478bd9Sstevel@tonic-gate
2507e1adf50cSahl err:
25087c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
25097c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
25107c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
25117c478bd9Sstevel@tonic-gate } else
25127c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2513e1adf50cSahl err1:
2514e1adf50cSahl vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2515e1adf50cSahl out:
2516e1adf50cSahl DTRACE_NFSV3_4(op__remove__done, struct svc_req *, req,
2517e1adf50cSahl cred_t *, cr, vnode_t *, vp, REMOVE3res *, resp);
2518b89a8333Snatalie li - Sun Microsystems - Irvine United States
2519b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->object.name)
2520b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2521b89a8333Snatalie li - Sun Microsystems - Irvine United States
25227c478bd9Sstevel@tonic-gate if (vp != NULL)
25237c478bd9Sstevel@tonic-gate VN_RELE(vp);
25247c478bd9Sstevel@tonic-gate }
25257c478bd9Sstevel@tonic-gate
252627242a7cSthurlow void *
rfs3_remove_getfh(REMOVE3args * args)25277c478bd9Sstevel@tonic-gate rfs3_remove_getfh(REMOVE3args *args)
25287c478bd9Sstevel@tonic-gate {
25297c478bd9Sstevel@tonic-gate
253027242a7cSthurlow return (&args->object.dir);
25317c478bd9Sstevel@tonic-gate }
25327c478bd9Sstevel@tonic-gate
25337c478bd9Sstevel@tonic-gate void
rfs3_rmdir(RMDIR3args * args,RMDIR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)25347c478bd9Sstevel@tonic-gate rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi,
25355cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
25367c478bd9Sstevel@tonic-gate {
25377c478bd9Sstevel@tonic-gate int error;
25387c478bd9Sstevel@tonic-gate vnode_t *vp;
25397c478bd9Sstevel@tonic-gate struct vattr *bvap;
25407c478bd9Sstevel@tonic-gate struct vattr bva;
25417c478bd9Sstevel@tonic-gate struct vattr *avap;
25427c478bd9Sstevel@tonic-gate struct vattr ava;
2543b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2544b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
25457c478bd9Sstevel@tonic-gate
25467c478bd9Sstevel@tonic-gate bvap = NULL;
25477c478bd9Sstevel@tonic-gate avap = NULL;
25487c478bd9Sstevel@tonic-gate
254927242a7cSthurlow vp = nfs3_fhtovp(&args->object.dir, exi);
2550e1adf50cSahl
2551e1adf50cSahl DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req,
2552e1adf50cSahl cred_t *, cr, vnode_t *, vp, RMDIR3args *, args);
2553e1adf50cSahl
25547c478bd9Sstevel@tonic-gate if (vp == NULL) {
25557c478bd9Sstevel@tonic-gate error = ESTALE;
2556e1adf50cSahl goto err;
25577c478bd9Sstevel@tonic-gate }
25587c478bd9Sstevel@tonic-gate
25597c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
2560da6c28aaSamw bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
25617c478bd9Sstevel@tonic-gate avap = bvap;
25627c478bd9Sstevel@tonic-gate
25637c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
25647c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
2565e1adf50cSahl goto err1;
25667c478bd9Sstevel@tonic-gate }
25677c478bd9Sstevel@tonic-gate
25687c478bd9Sstevel@tonic-gate if (args->object.name == nfs3nametoolong) {
25697c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2570e1adf50cSahl goto err1;
25717c478bd9Sstevel@tonic-gate }
25727c478bd9Sstevel@tonic-gate
25737c478bd9Sstevel@tonic-gate if (args->object.name == NULL || *(args->object.name) == '\0') {
25747c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2575e1adf50cSahl goto err1;
25767c478bd9Sstevel@tonic-gate }
25777c478bd9Sstevel@tonic-gate
25785cb0d679SMarcel Telka if (rdonly(ro, vp)) {
25797c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2580e1adf50cSahl goto err1;
25817c478bd9Sstevel@tonic-gate }
25827c478bd9Sstevel@tonic-gate
258303986916Sjarrett if (is_system_labeled()) {
258403986916Sjarrett bslabel_t *clabel = req->rq_label;
258503986916Sjarrett
258603986916Sjarrett ASSERT(clabel != NULL);
258703986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opremovedir__clabel, char *,
258803986916Sjarrett "got client label from request(1)", struct svc_req *, req);
258903986916Sjarrett
259003986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2591bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2592bd6f1640SJarrett Lu exi)) {
259303986916Sjarrett resp->status = NFS3ERR_ACCES;
2594e1adf50cSahl goto err1;
259503986916Sjarrett }
259603986916Sjarrett }
259703986916Sjarrett }
259803986916Sjarrett
2599b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2600b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->object.name,
2601b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2602b89a8333Snatalie li - Sun Microsystems - Irvine United States
2603b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2604b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2605b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2606b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2607b89a8333Snatalie li - Sun Microsystems - Irvine United States
2608b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_RMDIR(vp, name, rootdir, cr, NULL, 0);
2609b89a8333Snatalie li - Sun Microsystems - Irvine United States
2610b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != args->object.name)
2611b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
26127c478bd9Sstevel@tonic-gate
26137c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
2614da6c28aaSamw avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
26157c478bd9Sstevel@tonic-gate
26167c478bd9Sstevel@tonic-gate /*
26177c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
26187c478bd9Sstevel@tonic-gate */
2619da6c28aaSamw (void) VOP_FSYNC(vp, 0, cr, NULL);
26207c478bd9Sstevel@tonic-gate
26217c478bd9Sstevel@tonic-gate if (error) {
26227c478bd9Sstevel@tonic-gate /*
26237c478bd9Sstevel@tonic-gate * System V defines rmdir to return EEXIST, not ENOTEMPTY,
26247c478bd9Sstevel@tonic-gate * if the directory is not empty. A System V NFS server
26257c478bd9Sstevel@tonic-gate * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
26267c478bd9Sstevel@tonic-gate * over the wire.
26277c478bd9Sstevel@tonic-gate */
26287c478bd9Sstevel@tonic-gate if (error == EEXIST)
26297c478bd9Sstevel@tonic-gate error = ENOTEMPTY;
2630e1adf50cSahl goto err;
26317c478bd9Sstevel@tonic-gate }
26327c478bd9Sstevel@tonic-gate
26337c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
26347c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2635e1adf50cSahl goto out;
26367c478bd9Sstevel@tonic-gate
2637e1adf50cSahl err:
26387c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
26397c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
26407c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
26417c478bd9Sstevel@tonic-gate } else
26427c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2643e1adf50cSahl err1:
2644e1adf50cSahl vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2645e1adf50cSahl out:
2646e1adf50cSahl DTRACE_NFSV3_4(op__rmdir__done, struct svc_req *, req,
2647e1adf50cSahl cred_t *, cr, vnode_t *, vp, RMDIR3res *, resp);
26487c478bd9Sstevel@tonic-gate if (vp != NULL)
26497c478bd9Sstevel@tonic-gate VN_RELE(vp);
2650e1adf50cSahl
26517c478bd9Sstevel@tonic-gate }
26527c478bd9Sstevel@tonic-gate
265327242a7cSthurlow void *
rfs3_rmdir_getfh(RMDIR3args * args)26547c478bd9Sstevel@tonic-gate rfs3_rmdir_getfh(RMDIR3args *args)
26557c478bd9Sstevel@tonic-gate {
26567c478bd9Sstevel@tonic-gate
265727242a7cSthurlow return (&args->object.dir);
26587c478bd9Sstevel@tonic-gate }
26597c478bd9Sstevel@tonic-gate
26607c478bd9Sstevel@tonic-gate void
rfs3_rename(RENAME3args * args,RENAME3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)26617c478bd9Sstevel@tonic-gate rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi,
26625cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
26637c478bd9Sstevel@tonic-gate {
26647c478bd9Sstevel@tonic-gate int error = 0;
26657c478bd9Sstevel@tonic-gate vnode_t *fvp;
26667c478bd9Sstevel@tonic-gate vnode_t *tvp;
26677c478bd9Sstevel@tonic-gate vnode_t *targvp;
26687c478bd9Sstevel@tonic-gate struct vattr *fbvap;
26697c478bd9Sstevel@tonic-gate struct vattr fbva;
26707c478bd9Sstevel@tonic-gate struct vattr *favap;
26717c478bd9Sstevel@tonic-gate struct vattr fava;
26727c478bd9Sstevel@tonic-gate struct vattr *tbvap;
26737c478bd9Sstevel@tonic-gate struct vattr tbva;
26747c478bd9Sstevel@tonic-gate struct vattr *tavap;
26757c478bd9Sstevel@tonic-gate struct vattr tava;
26767c478bd9Sstevel@tonic-gate nfs_fh3 *fh3;
26777c478bd9Sstevel@tonic-gate struct exportinfo *to_exi;
26787c478bd9Sstevel@tonic-gate vnode_t *srcvp = NULL;
267903986916Sjarrett bslabel_t *clabel;
2680b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2681b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
2682b89a8333Snatalie li - Sun Microsystems - Irvine United States char *toname = NULL;
26837c478bd9Sstevel@tonic-gate
26847c478bd9Sstevel@tonic-gate fbvap = NULL;
26857c478bd9Sstevel@tonic-gate favap = NULL;
26867c478bd9Sstevel@tonic-gate tbvap = NULL;
26877c478bd9Sstevel@tonic-gate tavap = NULL;
26887c478bd9Sstevel@tonic-gate tvp = NULL;
26897c478bd9Sstevel@tonic-gate
269027242a7cSthurlow fvp = nfs3_fhtovp(&args->from.dir, exi);
2691e1adf50cSahl
2692e1adf50cSahl DTRACE_NFSV3_4(op__rename__start, struct svc_req *, req,
2693e1adf50cSahl cred_t *, cr, vnode_t *, fvp, RENAME3args *, args);
2694e1adf50cSahl
26957c478bd9Sstevel@tonic-gate if (fvp == NULL) {
26967c478bd9Sstevel@tonic-gate error = ESTALE;
2697e1adf50cSahl goto err;
26987c478bd9Sstevel@tonic-gate }
26997c478bd9Sstevel@tonic-gate
270003986916Sjarrett if (is_system_labeled()) {
270103986916Sjarrett clabel = req->rq_label;
270203986916Sjarrett ASSERT(clabel != NULL);
270303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *,
270403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
270503986916Sjarrett
270603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2707bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK,
2708bd6f1640SJarrett Lu exi)) {
270903986916Sjarrett resp->status = NFS3ERR_ACCES;
2710e1adf50cSahl goto err1;
271103986916Sjarrett }
271203986916Sjarrett }
271303986916Sjarrett }
271403986916Sjarrett
27157c478bd9Sstevel@tonic-gate fbva.va_mask = AT_ALL;
2716da6c28aaSamw fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
27177c478bd9Sstevel@tonic-gate favap = fbvap;
27187c478bd9Sstevel@tonic-gate
271927242a7cSthurlow fh3 = &args->to.dir;
2720*fbd2e8e1SArne Jansen to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3), NULL);
27217c478bd9Sstevel@tonic-gate if (to_exi == NULL) {
27227c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2723e1adf50cSahl goto err1;
27247c478bd9Sstevel@tonic-gate }
27257c478bd9Sstevel@tonic-gate exi_rele(to_exi);
27267c478bd9Sstevel@tonic-gate
27277c478bd9Sstevel@tonic-gate if (to_exi != exi) {
27287c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_XDEV;
2729e1adf50cSahl goto err1;
27307c478bd9Sstevel@tonic-gate }
27317c478bd9Sstevel@tonic-gate
273227242a7cSthurlow tvp = nfs3_fhtovp(&args->to.dir, exi);
27337c478bd9Sstevel@tonic-gate if (tvp == NULL) {
27347c478bd9Sstevel@tonic-gate error = ESTALE;
2735e1adf50cSahl goto err;
27367c478bd9Sstevel@tonic-gate }
27377c478bd9Sstevel@tonic-gate
27387c478bd9Sstevel@tonic-gate tbva.va_mask = AT_ALL;
2739da6c28aaSamw tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
27407c478bd9Sstevel@tonic-gate tavap = tbvap;
27417c478bd9Sstevel@tonic-gate
27427c478bd9Sstevel@tonic-gate if (fvp->v_type != VDIR || tvp->v_type != VDIR) {
27437c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
2744e1adf50cSahl goto err1;
27457c478bd9Sstevel@tonic-gate }
27467c478bd9Sstevel@tonic-gate
27477c478bd9Sstevel@tonic-gate if (args->from.name == nfs3nametoolong ||
27487c478bd9Sstevel@tonic-gate args->to.name == nfs3nametoolong) {
27497c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
2750e1adf50cSahl goto err1;
27517c478bd9Sstevel@tonic-gate }
27527c478bd9Sstevel@tonic-gate if (args->from.name == NULL || *(args->from.name) == '\0' ||
27537c478bd9Sstevel@tonic-gate args->to.name == NULL || *(args->to.name) == '\0') {
27547c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
2755e1adf50cSahl goto err1;
27567c478bd9Sstevel@tonic-gate }
27577c478bd9Sstevel@tonic-gate
27585cb0d679SMarcel Telka if (rdonly(ro, tvp)) {
27597c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
2760e1adf50cSahl goto err1;
27617c478bd9Sstevel@tonic-gate }
27627c478bd9Sstevel@tonic-gate
276303986916Sjarrett if (is_system_labeled()) {
276403986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2765bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK,
2766bd6f1640SJarrett Lu exi)) {
276703986916Sjarrett resp->status = NFS3ERR_ACCES;
2768e1adf50cSahl goto err1;
276903986916Sjarrett }
277003986916Sjarrett }
277103986916Sjarrett }
277203986916Sjarrett
2773b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2774b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->from.name,
2775b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2776b89a8333Snatalie li - Sun Microsystems - Irvine United States
2777b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
2778b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2779b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2780b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2781b89a8333Snatalie li - Sun Microsystems - Irvine United States
2782b89a8333Snatalie li - Sun Microsystems - Irvine United States toname = nfscmd_convname(ca, exi, args->to.name,
2783b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2784b89a8333Snatalie li - Sun Microsystems - Irvine United States
2785b89a8333Snatalie li - Sun Microsystems - Irvine United States if (toname == NULL) {
2786b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_INVAL;
2787b89a8333Snatalie li - Sun Microsystems - Irvine United States goto err1;
2788b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2789b89a8333Snatalie li - Sun Microsystems - Irvine United States
27907c478bd9Sstevel@tonic-gate /*
27917c478bd9Sstevel@tonic-gate * Check for a conflict with a non-blocking mandatory share
27927c478bd9Sstevel@tonic-gate * reservation or V4 delegations.
27937c478bd9Sstevel@tonic-gate */
2794b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LOOKUP(fvp, name, &srcvp, NULL, 0,
2795da6c28aaSamw NULL, cr, NULL, NULL, NULL);
27967c478bd9Sstevel@tonic-gate if (error != 0)
2797e1adf50cSahl goto err;
27987c478bd9Sstevel@tonic-gate
27997c478bd9Sstevel@tonic-gate /*
28007c478bd9Sstevel@tonic-gate * If we rename a delegated file we should recall the
28017c478bd9Sstevel@tonic-gate * delegation, since future opens should fail or would
28027c478bd9Sstevel@tonic-gate * refer to a new file.
28037c478bd9Sstevel@tonic-gate */
28047c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, srcvp, FALSE)) {
28057c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2806e1adf50cSahl goto err1;
28077c478bd9Sstevel@tonic-gate }
28087c478bd9Sstevel@tonic-gate
28097c478bd9Sstevel@tonic-gate /*
28107c478bd9Sstevel@tonic-gate * Check for renaming over a delegated file. Check rfs4_deleg_policy
28117c478bd9Sstevel@tonic-gate * first to avoid VOP_LOOKUP if possible.
28127c478bd9Sstevel@tonic-gate */
28137c478bd9Sstevel@tonic-gate if (rfs4_deleg_policy != SRV_NEVER_DELEGATE &&
2814b89a8333Snatalie li - Sun Microsystems - Irvine United States VOP_LOOKUP(tvp, toname, &targvp, NULL, 0, NULL, cr,
2815da6c28aaSamw NULL, NULL, NULL) == 0) {
28167c478bd9Sstevel@tonic-gate
28177c478bd9Sstevel@tonic-gate if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
28187c478bd9Sstevel@tonic-gate VN_RELE(targvp);
28197c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2820e1adf50cSahl goto err1;
28217c478bd9Sstevel@tonic-gate }
28227c478bd9Sstevel@tonic-gate VN_RELE(targvp);
28237c478bd9Sstevel@tonic-gate }
28247c478bd9Sstevel@tonic-gate
28257c478bd9Sstevel@tonic-gate if (!nbl_need_check(srcvp)) {
2826b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
28277c478bd9Sstevel@tonic-gate } else {
28287c478bd9Sstevel@tonic-gate nbl_start_crit(srcvp, RW_READER);
2829b89a8333Snatalie li - Sun Microsystems - Irvine United States if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL))
28307c478bd9Sstevel@tonic-gate error = EACCES;
2831b89a8333Snatalie li - Sun Microsystems - Irvine United States else
2832b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
28337c478bd9Sstevel@tonic-gate nbl_end_crit(srcvp);
28347c478bd9Sstevel@tonic-gate }
283551ece835Seschrock if (error == 0)
283651ece835Seschrock vn_renamepath(tvp, srcvp, args->to.name,
2837c9264041Sjwahlig strlen(args->to.name));
28387c478bd9Sstevel@tonic-gate VN_RELE(srcvp);
28397c478bd9Sstevel@tonic-gate srcvp = NULL;
28407c478bd9Sstevel@tonic-gate
28417c478bd9Sstevel@tonic-gate fava.va_mask = AT_ALL;
2842da6c28aaSamw favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
28437c478bd9Sstevel@tonic-gate tava.va_mask = AT_ALL;
2844da6c28aaSamw tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
28457c478bd9Sstevel@tonic-gate
28467c478bd9Sstevel@tonic-gate /*
28477c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
28487c478bd9Sstevel@tonic-gate */
2849da6c28aaSamw (void) VOP_FSYNC(fvp, 0, cr, NULL);
2850da6c28aaSamw (void) VOP_FSYNC(tvp, 0, cr, NULL);
28517c478bd9Sstevel@tonic-gate
28527c478bd9Sstevel@tonic-gate if (error)
2853e1adf50cSahl goto err;
28547c478bd9Sstevel@tonic-gate
28557c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
28567c478bd9Sstevel@tonic-gate vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc);
28577c478bd9Sstevel@tonic-gate vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc);
2858e1adf50cSahl goto out;
28597c478bd9Sstevel@tonic-gate
2860e1adf50cSahl err:
28617c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
28627c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
28637c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
2864b89a8333Snatalie li - Sun Microsystems - Irvine United States } else {
28657c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
2866b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2867e1adf50cSahl err1:
2868e1adf50cSahl vattr_to_wcc_data(fbvap, favap, &resp->resfail.fromdir_wcc);
2869e1adf50cSahl vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc);
2870b89a8333Snatalie li - Sun Microsystems - Irvine United States
2871e1adf50cSahl out:
2872b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->from.name)
2873b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
2874b89a8333Snatalie li - Sun Microsystems - Irvine United States if (toname != NULL && toname != args->to.name)
2875b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(toname, MAXPATHLEN + 1);
2876b89a8333Snatalie li - Sun Microsystems - Irvine United States
2877e1adf50cSahl DTRACE_NFSV3_4(op__rename__done, struct svc_req *, req,
2878e1adf50cSahl cred_t *, cr, vnode_t *, fvp, RENAME3res *, resp);
28797c478bd9Sstevel@tonic-gate if (fvp != NULL)
28807c478bd9Sstevel@tonic-gate VN_RELE(fvp);
28817c478bd9Sstevel@tonic-gate if (tvp != NULL)
28827c478bd9Sstevel@tonic-gate VN_RELE(tvp);
28837c478bd9Sstevel@tonic-gate }
28847c478bd9Sstevel@tonic-gate
288527242a7cSthurlow void *
rfs3_rename_getfh(RENAME3args * args)28867c478bd9Sstevel@tonic-gate rfs3_rename_getfh(RENAME3args *args)
28877c478bd9Sstevel@tonic-gate {
28887c478bd9Sstevel@tonic-gate
288927242a7cSthurlow return (&args->from.dir);
28907c478bd9Sstevel@tonic-gate }
28917c478bd9Sstevel@tonic-gate
28927c478bd9Sstevel@tonic-gate void
rfs3_link(LINK3args * args,LINK3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)28937c478bd9Sstevel@tonic-gate rfs3_link(LINK3args *args, LINK3res *resp, struct exportinfo *exi,
28945cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
28957c478bd9Sstevel@tonic-gate {
28967c478bd9Sstevel@tonic-gate int error;
28977c478bd9Sstevel@tonic-gate vnode_t *vp;
28987c478bd9Sstevel@tonic-gate vnode_t *dvp;
28997c478bd9Sstevel@tonic-gate struct vattr *vap;
29007c478bd9Sstevel@tonic-gate struct vattr va;
29017c478bd9Sstevel@tonic-gate struct vattr *bvap;
29027c478bd9Sstevel@tonic-gate struct vattr bva;
29037c478bd9Sstevel@tonic-gate struct vattr *avap;
29047c478bd9Sstevel@tonic-gate struct vattr ava;
29057c478bd9Sstevel@tonic-gate nfs_fh3 *fh3;
29067c478bd9Sstevel@tonic-gate struct exportinfo *to_exi;
290703986916Sjarrett bslabel_t *clabel;
2908b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
2909b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name = NULL;
29107c478bd9Sstevel@tonic-gate
29117c478bd9Sstevel@tonic-gate vap = NULL;
29127c478bd9Sstevel@tonic-gate bvap = NULL;
29137c478bd9Sstevel@tonic-gate avap = NULL;
29147c478bd9Sstevel@tonic-gate dvp = NULL;
29157c478bd9Sstevel@tonic-gate
29167c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
2917e1adf50cSahl
2918e1adf50cSahl DTRACE_NFSV3_4(op__link__start, struct svc_req *, req,
2919e1adf50cSahl cred_t *, cr, vnode_t *, vp, LINK3args *, args);
2920e1adf50cSahl
29217c478bd9Sstevel@tonic-gate if (vp == NULL) {
29227c478bd9Sstevel@tonic-gate error = ESTALE;
29237c478bd9Sstevel@tonic-gate goto out;
29247c478bd9Sstevel@tonic-gate }
29257c478bd9Sstevel@tonic-gate
29267c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
2927da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
29287c478bd9Sstevel@tonic-gate
292927242a7cSthurlow fh3 = &args->link.dir;
2930*fbd2e8e1SArne Jansen to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3), NULL);
29317c478bd9Sstevel@tonic-gate if (to_exi == NULL) {
29327c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
29337c478bd9Sstevel@tonic-gate goto out1;
29347c478bd9Sstevel@tonic-gate }
29357c478bd9Sstevel@tonic-gate exi_rele(to_exi);
29367c478bd9Sstevel@tonic-gate
29377c478bd9Sstevel@tonic-gate if (to_exi != exi) {
29387c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_XDEV;
29397c478bd9Sstevel@tonic-gate goto out1;
29407c478bd9Sstevel@tonic-gate }
29417c478bd9Sstevel@tonic-gate
294203986916Sjarrett if (is_system_labeled()) {
294303986916Sjarrett clabel = req->rq_label;
294403986916Sjarrett
294503986916Sjarrett ASSERT(clabel != NULL);
294603986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oplink__clabel, char *,
294703986916Sjarrett "got client label from request(1)", struct svc_req *, req);
294803986916Sjarrett
294903986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2950bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
2951bd6f1640SJarrett Lu exi)) {
295203986916Sjarrett resp->status = NFS3ERR_ACCES;
295303986916Sjarrett goto out1;
295403986916Sjarrett }
295503986916Sjarrett }
295603986916Sjarrett }
295703986916Sjarrett
295827242a7cSthurlow dvp = nfs3_fhtovp(&args->link.dir, exi);
29597c478bd9Sstevel@tonic-gate if (dvp == NULL) {
29607c478bd9Sstevel@tonic-gate error = ESTALE;
29617c478bd9Sstevel@tonic-gate goto out;
29627c478bd9Sstevel@tonic-gate }
29637c478bd9Sstevel@tonic-gate
29647c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
2965da6c28aaSamw bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
29667c478bd9Sstevel@tonic-gate
29677c478bd9Sstevel@tonic-gate if (dvp->v_type != VDIR) {
29687c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
29697c478bd9Sstevel@tonic-gate goto out1;
29707c478bd9Sstevel@tonic-gate }
29717c478bd9Sstevel@tonic-gate
29727c478bd9Sstevel@tonic-gate if (args->link.name == nfs3nametoolong) {
29737c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NAMETOOLONG;
29747c478bd9Sstevel@tonic-gate goto out1;
29757c478bd9Sstevel@tonic-gate }
29767c478bd9Sstevel@tonic-gate
29777c478bd9Sstevel@tonic-gate if (args->link.name == NULL || *(args->link.name) == '\0') {
29787c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ACCES;
29797c478bd9Sstevel@tonic-gate goto out1;
29807c478bd9Sstevel@tonic-gate }
29817c478bd9Sstevel@tonic-gate
29825cb0d679SMarcel Telka if (rdonly(ro, dvp)) {
29837c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
29847c478bd9Sstevel@tonic-gate goto out1;
29857c478bd9Sstevel@tonic-gate }
29867c478bd9Sstevel@tonic-gate
298703986916Sjarrett if (is_system_labeled()) {
298803986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oplinkdir__clabel, char *,
298903986916Sjarrett "got client label from request(1)", struct svc_req *, req);
299003986916Sjarrett
299103986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
2992bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2993bd6f1640SJarrett Lu exi)) {
299403986916Sjarrett resp->status = NFS3ERR_ACCES;
299503986916Sjarrett goto out1;
299603986916Sjarrett }
299703986916Sjarrett }
299803986916Sjarrett }
299903986916Sjarrett
3000b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3001b89a8333Snatalie li - Sun Microsystems - Irvine United States name = nfscmd_convname(ca, exi, args->link.name,
3002b89a8333Snatalie li - Sun Microsystems - Irvine United States NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3003b89a8333Snatalie li - Sun Microsystems - Irvine United States
3004b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name == NULL) {
3005b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->status = NFS3ERR_SERVERFAULT;
3006b89a8333Snatalie li - Sun Microsystems - Irvine United States goto out1;
3007b89a8333Snatalie li - Sun Microsystems - Irvine United States }
3008b89a8333Snatalie li - Sun Microsystems - Irvine United States
3009b89a8333Snatalie li - Sun Microsystems - Irvine United States error = VOP_LINK(dvp, vp, name, cr, NULL, 0);
30107c478bd9Sstevel@tonic-gate
30117c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3012da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
30137c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
3014da6c28aaSamw avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
30157c478bd9Sstevel@tonic-gate
30167c478bd9Sstevel@tonic-gate /*
30177c478bd9Sstevel@tonic-gate * Force modified data and metadata out to stable storage.
30187c478bd9Sstevel@tonic-gate */
3019da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3020da6c28aaSamw (void) VOP_FSYNC(dvp, 0, cr, NULL);
30217c478bd9Sstevel@tonic-gate
30227c478bd9Sstevel@tonic-gate if (error)
30237c478bd9Sstevel@tonic-gate goto out;
30247c478bd9Sstevel@tonic-gate
30257c478bd9Sstevel@tonic-gate VN_RELE(dvp);
30267c478bd9Sstevel@tonic-gate
30277c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
30287c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
30297c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc);
3030e1adf50cSahl
3031e1adf50cSahl DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3032e1adf50cSahl cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3033e1adf50cSahl
3034e1adf50cSahl VN_RELE(vp);
3035e1adf50cSahl
30367c478bd9Sstevel@tonic-gate return;
30377c478bd9Sstevel@tonic-gate
30387c478bd9Sstevel@tonic-gate out:
30397c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
30407c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
30417c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
30427c478bd9Sstevel@tonic-gate } else
30437c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
30447c478bd9Sstevel@tonic-gate out1:
3045b89a8333Snatalie li - Sun Microsystems - Irvine United States if (name != NULL && name != args->link.name)
3046b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(name, MAXPATHLEN + 1);
3047b89a8333Snatalie li - Sun Microsystems - Irvine United States
3048e1adf50cSahl DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3049e1adf50cSahl cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3050e1adf50cSahl
30517c478bd9Sstevel@tonic-gate if (vp != NULL)
30527c478bd9Sstevel@tonic-gate VN_RELE(vp);
30537c478bd9Sstevel@tonic-gate if (dvp != NULL)
30547c478bd9Sstevel@tonic-gate VN_RELE(dvp);
30557c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
30567c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resfail.linkdir_wcc);
30577c478bd9Sstevel@tonic-gate }
30587c478bd9Sstevel@tonic-gate
305927242a7cSthurlow void *
rfs3_link_getfh(LINK3args * args)30607c478bd9Sstevel@tonic-gate rfs3_link_getfh(LINK3args *args)
30617c478bd9Sstevel@tonic-gate {
30627c478bd9Sstevel@tonic-gate
306327242a7cSthurlow return (&args->file);
30647c478bd9Sstevel@tonic-gate }
30657c478bd9Sstevel@tonic-gate
30667c478bd9Sstevel@tonic-gate /*
30677c478bd9Sstevel@tonic-gate * This macro defines the size of a response which contains attribute
30687c478bd9Sstevel@tonic-gate * information and one directory entry (whose length is specified by
30697c478bd9Sstevel@tonic-gate * the macro parameter). If the incoming request is larger than this,
30707c478bd9Sstevel@tonic-gate * then we are guaranteed to be able to return at one directory entry
30717c478bd9Sstevel@tonic-gate * if one exists. Therefore, we do not need to check for
30727c478bd9Sstevel@tonic-gate * NFS3ERR_TOOSMALL if the requested size is larger then this. If it
30737c478bd9Sstevel@tonic-gate * is not, then we need to check to make sure that this error does not
30747c478bd9Sstevel@tonic-gate * need to be returned.
30757c478bd9Sstevel@tonic-gate *
30767c478bd9Sstevel@tonic-gate * NFS3_READDIR_MIN_COUNT is comprised of following :
30777c478bd9Sstevel@tonic-gate *
30787c478bd9Sstevel@tonic-gate * status - 1 * BYTES_PER_XDR_UNIT
30797c478bd9Sstevel@tonic-gate * attr. flag - 1 * BYTES_PER_XDR_UNIT
30807c478bd9Sstevel@tonic-gate * cookie verifier - 2 * BYTES_PER_XDR_UNIT
30817c478bd9Sstevel@tonic-gate * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
30827c478bd9Sstevel@tonic-gate * boolean - 1 * BYTES_PER_XDR_UNIT
30837c478bd9Sstevel@tonic-gate * file id - 2 * BYTES_PER_XDR_UNIT
3084da6c28aaSamw * directory name length - 1 * BYTES_PER_XDR_UNIT
30857c478bd9Sstevel@tonic-gate * cookie - 2 * BYTES_PER_XDR_UNIT
30867c478bd9Sstevel@tonic-gate * end of list - 1 * BYTES_PER_XDR_UNIT
30877c478bd9Sstevel@tonic-gate * end of file - 1 * BYTES_PER_XDR_UNIT
30887c478bd9Sstevel@tonic-gate * Name length of directory to the nearest byte
30897c478bd9Sstevel@tonic-gate */
30907c478bd9Sstevel@tonic-gate
30917c478bd9Sstevel@tonic-gate #define NFS3_READDIR_MIN_COUNT(length) \
30927c478bd9Sstevel@tonic-gate ((1 + 1 + 2 + NFS3_SIZEOF_FATTR3 + 1 + 2 + 1 + 2 + 1 + 1) * \
30937c478bd9Sstevel@tonic-gate BYTES_PER_XDR_UNIT + roundup((length), BYTES_PER_XDR_UNIT))
30947c478bd9Sstevel@tonic-gate
30957c478bd9Sstevel@tonic-gate /* ARGSUSED */
30967c478bd9Sstevel@tonic-gate void
rfs3_readdir(READDIR3args * args,READDIR3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)30977c478bd9Sstevel@tonic-gate rfs3_readdir(READDIR3args *args, READDIR3res *resp, struct exportinfo *exi,
30985cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
30997c478bd9Sstevel@tonic-gate {
31007c478bd9Sstevel@tonic-gate int error;
31017c478bd9Sstevel@tonic-gate vnode_t *vp;
31027c478bd9Sstevel@tonic-gate struct vattr *vap;
31037c478bd9Sstevel@tonic-gate struct vattr va;
31047c478bd9Sstevel@tonic-gate struct iovec iov;
31057c478bd9Sstevel@tonic-gate struct uio uio;
31067c478bd9Sstevel@tonic-gate char *data;
31077c478bd9Sstevel@tonic-gate int iseof;
31087c478bd9Sstevel@tonic-gate int bufsize;
31097c478bd9Sstevel@tonic-gate int namlen;
31107c478bd9Sstevel@tonic-gate uint_t count;
3111b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
31127c478bd9Sstevel@tonic-gate
31137c478bd9Sstevel@tonic-gate vap = NULL;
31147c478bd9Sstevel@tonic-gate
31157c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->dir, exi);
3116e1adf50cSahl
3117e1adf50cSahl DTRACE_NFSV3_4(op__readdir__start, struct svc_req *, req,
3118e1adf50cSahl cred_t *, cr, vnode_t *, vp, READDIR3args *, args);
3119e1adf50cSahl
31207c478bd9Sstevel@tonic-gate if (vp == NULL) {
31217c478bd9Sstevel@tonic-gate error = ESTALE;
31227c478bd9Sstevel@tonic-gate goto out;
31237c478bd9Sstevel@tonic-gate }
31247c478bd9Sstevel@tonic-gate
312503986916Sjarrett if (is_system_labeled()) {
312603986916Sjarrett bslabel_t *clabel = req->rq_label;
312703986916Sjarrett
312803986916Sjarrett ASSERT(clabel != NULL);
312903986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opreaddir__clabel, char *,
313003986916Sjarrett "got client label from request(1)", struct svc_req *, req);
313103986916Sjarrett
313203986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3133bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3134bd6f1640SJarrett Lu exi)) {
313503986916Sjarrett resp->status = NFS3ERR_ACCES;
313603986916Sjarrett goto out1;
313703986916Sjarrett }
313803986916Sjarrett }
313903986916Sjarrett }
314003986916Sjarrett
31417c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
31427c478bd9Sstevel@tonic-gate
31437c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3144da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
31457c478bd9Sstevel@tonic-gate
31467c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
31477c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_NOTDIR;
31487c478bd9Sstevel@tonic-gate goto out1;
31497c478bd9Sstevel@tonic-gate }
31507c478bd9Sstevel@tonic-gate
3151da6c28aaSamw error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
31527c478bd9Sstevel@tonic-gate if (error)
31537c478bd9Sstevel@tonic-gate goto out;
31547c478bd9Sstevel@tonic-gate
31557c478bd9Sstevel@tonic-gate /*
31567c478bd9Sstevel@tonic-gate * Now don't allow arbitrary count to alloc;
31577c478bd9Sstevel@tonic-gate * allow the maximum not to exceed rfs3_tsize()
31587c478bd9Sstevel@tonic-gate */
31597c478bd9Sstevel@tonic-gate if (args->count > rfs3_tsize(req))
31607c478bd9Sstevel@tonic-gate args->count = rfs3_tsize(req);
31617c478bd9Sstevel@tonic-gate
31627c478bd9Sstevel@tonic-gate /*
31637c478bd9Sstevel@tonic-gate * Make sure that there is room to read at least one entry
31647c478bd9Sstevel@tonic-gate * if any are available.
31657c478bd9Sstevel@tonic-gate */
31667c478bd9Sstevel@tonic-gate if (args->count < DIRENT64_RECLEN(MAXNAMELEN))
31677c478bd9Sstevel@tonic-gate count = DIRENT64_RECLEN(MAXNAMELEN);
31687c478bd9Sstevel@tonic-gate else
31697c478bd9Sstevel@tonic-gate count = args->count;
31707c478bd9Sstevel@tonic-gate
31717c478bd9Sstevel@tonic-gate data = kmem_alloc(count, KM_SLEEP);
31727c478bd9Sstevel@tonic-gate
31737c478bd9Sstevel@tonic-gate iov.iov_base = data;
31747c478bd9Sstevel@tonic-gate iov.iov_len = count;
31757c478bd9Sstevel@tonic-gate uio.uio_iov = &iov;
31767c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1;
31777c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
31787c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
31797c478bd9Sstevel@tonic-gate uio.uio_loffset = (offset_t)args->cookie;
31807c478bd9Sstevel@tonic-gate uio.uio_resid = count;
31817c478bd9Sstevel@tonic-gate
3182da6c28aaSamw error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
31837c478bd9Sstevel@tonic-gate
31847c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3185da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
31867c478bd9Sstevel@tonic-gate
31877c478bd9Sstevel@tonic-gate if (error) {
31887c478bd9Sstevel@tonic-gate kmem_free(data, count);
31897c478bd9Sstevel@tonic-gate goto out;
31907c478bd9Sstevel@tonic-gate }
31917c478bd9Sstevel@tonic-gate
31927c478bd9Sstevel@tonic-gate /*
31937c478bd9Sstevel@tonic-gate * If the count was not large enough to be able to guarantee
31947c478bd9Sstevel@tonic-gate * to be able to return at least one entry, then need to
31957c478bd9Sstevel@tonic-gate * check to see if NFS3ERR_TOOSMALL should be returned.
31967c478bd9Sstevel@tonic-gate */
31977c478bd9Sstevel@tonic-gate if (args->count < NFS3_READDIR_MIN_COUNT(MAXNAMELEN)) {
31987c478bd9Sstevel@tonic-gate /*
31997c478bd9Sstevel@tonic-gate * bufsize is used to keep track of the size of the response.
32007c478bd9Sstevel@tonic-gate * It is primed with:
32017c478bd9Sstevel@tonic-gate * 1 for the status +
32027c478bd9Sstevel@tonic-gate * 1 for the dir_attributes.attributes boolean +
32037c478bd9Sstevel@tonic-gate * 2 for the cookie verifier
32047c478bd9Sstevel@tonic-gate * all times BYTES_PER_XDR_UNIT to convert from XDR units
32057c478bd9Sstevel@tonic-gate * to bytes. If there are directory attributes to be
32067c478bd9Sstevel@tonic-gate * returned, then:
32077c478bd9Sstevel@tonic-gate * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
32087c478bd9Sstevel@tonic-gate * time BYTES_PER_XDR_UNIT is added to account for them.
32097c478bd9Sstevel@tonic-gate */
32107c478bd9Sstevel@tonic-gate bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
32117c478bd9Sstevel@tonic-gate if (vap != NULL)
32127c478bd9Sstevel@tonic-gate bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
32137c478bd9Sstevel@tonic-gate /*
32147c478bd9Sstevel@tonic-gate * An entry is composed of:
32157c478bd9Sstevel@tonic-gate * 1 for the true/false list indicator +
32167c478bd9Sstevel@tonic-gate * 2 for the fileid +
32177c478bd9Sstevel@tonic-gate * 1 for the length of the name +
32187c478bd9Sstevel@tonic-gate * 2 for the cookie +
32197c478bd9Sstevel@tonic-gate * all times BYTES_PER_XDR_UNIT to convert from
32207c478bd9Sstevel@tonic-gate * XDR units to bytes, plus the length of the name
32217c478bd9Sstevel@tonic-gate * rounded up to the nearest BYTES_PER_XDR_UNIT.
32227c478bd9Sstevel@tonic-gate */
32237c478bd9Sstevel@tonic-gate if (count != uio.uio_resid) {
32247c478bd9Sstevel@tonic-gate namlen = strlen(((struct dirent64 *)data)->d_name);
32257c478bd9Sstevel@tonic-gate bufsize += (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
32267c478bd9Sstevel@tonic-gate roundup(namlen, BYTES_PER_XDR_UNIT);
32277c478bd9Sstevel@tonic-gate }
32287c478bd9Sstevel@tonic-gate /*
32297c478bd9Sstevel@tonic-gate * We need to check to see if the number of bytes left
32307c478bd9Sstevel@tonic-gate * to go into the buffer will actually fit into the
32317c478bd9Sstevel@tonic-gate * buffer. This is calculated as the size of this
32327c478bd9Sstevel@tonic-gate * entry plus:
32337c478bd9Sstevel@tonic-gate * 1 for the true/false list indicator +
32347c478bd9Sstevel@tonic-gate * 1 for the eof indicator
32357c478bd9Sstevel@tonic-gate * times BYTES_PER_XDR_UNIT to convert from from
32367c478bd9Sstevel@tonic-gate * XDR units to bytes.
32377c478bd9Sstevel@tonic-gate */
32387c478bd9Sstevel@tonic-gate bufsize += (1 + 1) * BYTES_PER_XDR_UNIT;
32397c478bd9Sstevel@tonic-gate if (bufsize > args->count) {
32407c478bd9Sstevel@tonic-gate kmem_free(data, count);
32417c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_TOOSMALL;
32427c478bd9Sstevel@tonic-gate goto out1;
32437c478bd9Sstevel@tonic-gate }
32447c478bd9Sstevel@tonic-gate }
32457c478bd9Sstevel@tonic-gate
3246b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
3247b89a8333Snatalie li - Sun Microsystems - Irvine United States * Have a valid readir buffer for the native character
3248b89a8333Snatalie li - Sun Microsystems - Irvine United States * set. Need to check if a conversion is necessary and
3249b89a8333Snatalie li - Sun Microsystems - Irvine United States * potentially rewrite the whole buffer. Note that if the
3250b89a8333Snatalie li - Sun Microsystems - Irvine United States * conversion expands names enough, the structure may not
3251b89a8333Snatalie li - Sun Microsystems - Irvine United States * fit. In this case, we need to drop entries until if fits
3252b89a8333Snatalie li - Sun Microsystems - Irvine United States * and patch the counts in order that the next readdir will
3253b89a8333Snatalie li - Sun Microsystems - Irvine United States * get the correct entries.
3254b89a8333Snatalie li - Sun Microsystems - Irvine United States */
3255b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3256b89a8333Snatalie li - Sun Microsystems - Irvine United States data = nfscmd_convdirent(ca, exi, data, count, &resp->status);
3257b89a8333Snatalie li - Sun Microsystems - Irvine United States
3258b89a8333Snatalie li - Sun Microsystems - Irvine United States
32597c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
32607c478bd9Sstevel@tonic-gate
32617c478bd9Sstevel@tonic-gate #if 0 /* notyet */
32627c478bd9Sstevel@tonic-gate /*
32637c478bd9Sstevel@tonic-gate * Don't do this. It causes local disk writes when just
32647c478bd9Sstevel@tonic-gate * reading the file and the overhead is deemed larger
32657c478bd9Sstevel@tonic-gate * than the benefit.
32667c478bd9Sstevel@tonic-gate */
32677c478bd9Sstevel@tonic-gate /*
32687c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
32697c478bd9Sstevel@tonic-gate */
3270da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
32717c478bd9Sstevel@tonic-gate #endif
32727c478bd9Sstevel@tonic-gate
32737c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
32747c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
32757c478bd9Sstevel@tonic-gate resp->resok.cookieverf = 0;
32767c478bd9Sstevel@tonic-gate resp->resok.reply.entries = (entry3 *)data;
32777c478bd9Sstevel@tonic-gate resp->resok.reply.eof = iseof;
32787c478bd9Sstevel@tonic-gate resp->resok.size = count - uio.uio_resid;
32797c478bd9Sstevel@tonic-gate resp->resok.count = args->count;
32807c478bd9Sstevel@tonic-gate resp->resok.freecount = count;
3281e1adf50cSahl
3282e1adf50cSahl DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
3283e1adf50cSahl cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
3284e1adf50cSahl
3285e1adf50cSahl VN_RELE(vp);
3286e1adf50cSahl
32877c478bd9Sstevel@tonic-gate return;
32887c478bd9Sstevel@tonic-gate
32897c478bd9Sstevel@tonic-gate out:
32907c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
32917c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
32927c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
32937c478bd9Sstevel@tonic-gate } else
32947c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
32957c478bd9Sstevel@tonic-gate out1:
3296e1adf50cSahl DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
3297e1adf50cSahl cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
3298e1adf50cSahl
32997c478bd9Sstevel@tonic-gate if (vp != NULL) {
33007c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
33017c478bd9Sstevel@tonic-gate VN_RELE(vp);
33027c478bd9Sstevel@tonic-gate }
33037c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
33047c478bd9Sstevel@tonic-gate }
33057c478bd9Sstevel@tonic-gate
330627242a7cSthurlow void *
rfs3_readdir_getfh(READDIR3args * args)33077c478bd9Sstevel@tonic-gate rfs3_readdir_getfh(READDIR3args *args)
33087c478bd9Sstevel@tonic-gate {
33097c478bd9Sstevel@tonic-gate
331027242a7cSthurlow return (&args->dir);
33117c478bd9Sstevel@tonic-gate }
33127c478bd9Sstevel@tonic-gate
33137c478bd9Sstevel@tonic-gate void
rfs3_readdir_free(READDIR3res * resp)33147c478bd9Sstevel@tonic-gate rfs3_readdir_free(READDIR3res *resp)
33157c478bd9Sstevel@tonic-gate {
33167c478bd9Sstevel@tonic-gate
33177c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK)
33187c478bd9Sstevel@tonic-gate kmem_free(resp->resok.reply.entries, resp->resok.freecount);
33197c478bd9Sstevel@tonic-gate }
33207c478bd9Sstevel@tonic-gate
33217c478bd9Sstevel@tonic-gate #ifdef nextdp
33227c478bd9Sstevel@tonic-gate #undef nextdp
33237c478bd9Sstevel@tonic-gate #endif
33247c478bd9Sstevel@tonic-gate #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
33257c478bd9Sstevel@tonic-gate
33267c478bd9Sstevel@tonic-gate /*
33277c478bd9Sstevel@tonic-gate * This macro computes the size of a response which contains
33287c478bd9Sstevel@tonic-gate * one directory entry including the attributes as well as file handle.
33297c478bd9Sstevel@tonic-gate * If the incoming request is larger than this, then we are guaranteed to be
33307c478bd9Sstevel@tonic-gate * able to return at least one more directory entry if one exists.
33317c478bd9Sstevel@tonic-gate *
33327c478bd9Sstevel@tonic-gate * NFS3_READDIRPLUS_ENTRY is made up of the following:
33337c478bd9Sstevel@tonic-gate *
33347c478bd9Sstevel@tonic-gate * boolean - 1 * BYTES_PER_XDR_UNIT
33357c478bd9Sstevel@tonic-gate * file id - 2 * BYTES_PER_XDR_UNIT
33367c478bd9Sstevel@tonic-gate * directory name length - 1 * BYTES_PER_XDR_UNIT
33377c478bd9Sstevel@tonic-gate * cookie - 2 * BYTES_PER_XDR_UNIT
33387c478bd9Sstevel@tonic-gate * attribute flag - 1 * BYTES_PER_XDR_UNIT
33397c478bd9Sstevel@tonic-gate * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
33407c478bd9Sstevel@tonic-gate * status byte for file handle - 1 * BYTES_PER_XDR_UNIT
33417c478bd9Sstevel@tonic-gate * length of a file handle - 1 * BYTES_PER_XDR_UNIT
3342da6c28aaSamw * Maximum length of a file handle (NFS3_MAXFHSIZE)
33437c478bd9Sstevel@tonic-gate * name length of the entry to the nearest bytes
33447c478bd9Sstevel@tonic-gate */
33457c478bd9Sstevel@tonic-gate #define NFS3_READDIRPLUS_ENTRY(namelen) \
33467c478bd9Sstevel@tonic-gate ((1 + 2 + 1 + 2 + 1 + NFS3_SIZEOF_FATTR3 + 1 + 1) * \
33477c478bd9Sstevel@tonic-gate BYTES_PER_XDR_UNIT + \
334827242a7cSthurlow NFS3_MAXFHSIZE + roundup(namelen, BYTES_PER_XDR_UNIT))
33497c478bd9Sstevel@tonic-gate
33507c478bd9Sstevel@tonic-gate static int rfs3_readdir_unit = MAXBSIZE;
33517c478bd9Sstevel@tonic-gate
33527c478bd9Sstevel@tonic-gate /* ARGSUSED */
33537c478bd9Sstevel@tonic-gate void
rfs3_readdirplus(READDIRPLUS3args * args,READDIRPLUS3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)33547c478bd9Sstevel@tonic-gate rfs3_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *resp,
33555cb0d679SMarcel Telka struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
33567c478bd9Sstevel@tonic-gate {
33577c478bd9Sstevel@tonic-gate int error;
33587c478bd9Sstevel@tonic-gate vnode_t *vp;
33597c478bd9Sstevel@tonic-gate struct vattr *vap;
33607c478bd9Sstevel@tonic-gate struct vattr va;
33617c478bd9Sstevel@tonic-gate struct iovec iov;
33627c478bd9Sstevel@tonic-gate struct uio uio;
33637c478bd9Sstevel@tonic-gate char *data;
33647c478bd9Sstevel@tonic-gate int iseof;
33657c478bd9Sstevel@tonic-gate struct dirent64 *dp;
33667c478bd9Sstevel@tonic-gate vnode_t *nvp;
33677c478bd9Sstevel@tonic-gate struct vattr *nvap;
33687c478bd9Sstevel@tonic-gate struct vattr nva;
33697c478bd9Sstevel@tonic-gate entryplus3_info *infop = NULL;
33707c478bd9Sstevel@tonic-gate int size = 0;
33717c478bd9Sstevel@tonic-gate int nents = 0;
33727c478bd9Sstevel@tonic-gate int bufsize = 0;
33737c478bd9Sstevel@tonic-gate int entrysize = 0;
33747c478bd9Sstevel@tonic-gate int tofit = 0;
33757c478bd9Sstevel@tonic-gate int rd_unit = rfs3_readdir_unit;
33767c478bd9Sstevel@tonic-gate int prev_len;
33777c478bd9Sstevel@tonic-gate int space_left;
33787c478bd9Sstevel@tonic-gate int i;
33797c478bd9Sstevel@tonic-gate uint_t *namlen = NULL;
3380b89a8333Snatalie li - Sun Microsystems - Irvine United States char *ndata = NULL;
3381b89a8333Snatalie li - Sun Microsystems - Irvine United States struct sockaddr *ca;
3382b89a8333Snatalie li - Sun Microsystems - Irvine United States size_t ret;
33837c478bd9Sstevel@tonic-gate
33847c478bd9Sstevel@tonic-gate vap = NULL;
33857c478bd9Sstevel@tonic-gate
33867c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->dir, exi);
3387e1adf50cSahl
3388e1adf50cSahl DTRACE_NFSV3_4(op__readdirplus__start, struct svc_req *, req,
3389e1adf50cSahl cred_t *, cr, vnode_t *, vp, READDIRPLUS3args *, args);
3390e1adf50cSahl
33917c478bd9Sstevel@tonic-gate if (vp == NULL) {
33927c478bd9Sstevel@tonic-gate error = ESTALE;
33937c478bd9Sstevel@tonic-gate goto out;
33947c478bd9Sstevel@tonic-gate }
33957c478bd9Sstevel@tonic-gate
339603986916Sjarrett if (is_system_labeled()) {
339703986916Sjarrett bslabel_t *clabel = req->rq_label;
339803986916Sjarrett
339903986916Sjarrett ASSERT(clabel != NULL);
340003986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opreaddirplus__clabel,
340103986916Sjarrett char *, "got client label from request(1)",
340203986916Sjarrett struct svc_req *, req);
340303986916Sjarrett
340403986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3405bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3406bd6f1640SJarrett Lu exi)) {
340703986916Sjarrett resp->status = NFS3ERR_ACCES;
340803986916Sjarrett goto out1;
340903986916Sjarrett }
341003986916Sjarrett }
341103986916Sjarrett }
341203986916Sjarrett
34137c478bd9Sstevel@tonic-gate (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
34147c478bd9Sstevel@tonic-gate
34157c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3416da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
34177c478bd9Sstevel@tonic-gate
34187c478bd9Sstevel@tonic-gate if (vp->v_type != VDIR) {
34197c478bd9Sstevel@tonic-gate error = ENOTDIR;
34207c478bd9Sstevel@tonic-gate goto out;
34217c478bd9Sstevel@tonic-gate }
34227c478bd9Sstevel@tonic-gate
3423da6c28aaSamw error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
34247c478bd9Sstevel@tonic-gate if (error)
34257c478bd9Sstevel@tonic-gate goto out;
34267c478bd9Sstevel@tonic-gate
34277c478bd9Sstevel@tonic-gate /*
34287c478bd9Sstevel@tonic-gate * Don't allow arbitrary counts for allocation
34297c478bd9Sstevel@tonic-gate */
34307c478bd9Sstevel@tonic-gate if (args->maxcount > rfs3_tsize(req))
34317c478bd9Sstevel@tonic-gate args->maxcount = rfs3_tsize(req);
34327c478bd9Sstevel@tonic-gate
34337c478bd9Sstevel@tonic-gate /*
34347c478bd9Sstevel@tonic-gate * Make sure that there is room to read at least one entry
34357c478bd9Sstevel@tonic-gate * if any are available
34367c478bd9Sstevel@tonic-gate */
34377c478bd9Sstevel@tonic-gate args->dircount = MIN(args->dircount, args->maxcount);
34387c478bd9Sstevel@tonic-gate
34397c478bd9Sstevel@tonic-gate if (args->dircount < DIRENT64_RECLEN(MAXNAMELEN))
34407c478bd9Sstevel@tonic-gate args->dircount = DIRENT64_RECLEN(MAXNAMELEN);
34417c478bd9Sstevel@tonic-gate
34427c478bd9Sstevel@tonic-gate /*
34437c478bd9Sstevel@tonic-gate * This allocation relies on a minimum directory entry
34447c478bd9Sstevel@tonic-gate * being roughly 24 bytes. Therefore, the namlen array
34457c478bd9Sstevel@tonic-gate * will have enough space based on the maximum number of
34467c478bd9Sstevel@tonic-gate * entries to read.
34477c478bd9Sstevel@tonic-gate */
34487c478bd9Sstevel@tonic-gate namlen = kmem_alloc(args->dircount, KM_SLEEP);
34497c478bd9Sstevel@tonic-gate
34507c478bd9Sstevel@tonic-gate space_left = args->dircount;
34517c478bd9Sstevel@tonic-gate data = kmem_alloc(args->dircount, KM_SLEEP);
34527c478bd9Sstevel@tonic-gate dp = (struct dirent64 *)data;
34537c478bd9Sstevel@tonic-gate uio.uio_iov = &iov;
34547c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1;
34557c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
34567c478bd9Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
34577c478bd9Sstevel@tonic-gate uio.uio_loffset = (offset_t)args->cookie;
34587c478bd9Sstevel@tonic-gate
34597c478bd9Sstevel@tonic-gate /*
34607c478bd9Sstevel@tonic-gate * bufsize is used to keep track of the size of the response as we
34617c478bd9Sstevel@tonic-gate * get post op attributes and filehandles for each entry. This is
34627c478bd9Sstevel@tonic-gate * an optimization as the server may have read more entries than will
34637c478bd9Sstevel@tonic-gate * fit in the buffer specified by maxcount. We stop calculating
34647c478bd9Sstevel@tonic-gate * post op attributes and filehandles once we have exceeded maxcount.
34657c478bd9Sstevel@tonic-gate * This will minimize the effect of truncation.
34667c478bd9Sstevel@tonic-gate *
34677c478bd9Sstevel@tonic-gate * It is primed with:
34687c478bd9Sstevel@tonic-gate * 1 for the status +
34697c478bd9Sstevel@tonic-gate * 1 for the dir_attributes.attributes boolean +
34707c478bd9Sstevel@tonic-gate * 2 for the cookie verifier
34717c478bd9Sstevel@tonic-gate * all times BYTES_PER_XDR_UNIT to convert from XDR units
34727c478bd9Sstevel@tonic-gate * to bytes. If there are directory attributes to be
34737c478bd9Sstevel@tonic-gate * returned, then:
34747c478bd9Sstevel@tonic-gate * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
34757c478bd9Sstevel@tonic-gate * time BYTES_PER_XDR_UNIT is added to account for them.
34767c478bd9Sstevel@tonic-gate */
34777c478bd9Sstevel@tonic-gate bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
34787c478bd9Sstevel@tonic-gate if (vap != NULL)
34797c478bd9Sstevel@tonic-gate bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
34807c478bd9Sstevel@tonic-gate
34817c478bd9Sstevel@tonic-gate getmoredents:
34827c478bd9Sstevel@tonic-gate /*
34837c478bd9Sstevel@tonic-gate * Here we make a check so that our read unit is not larger than
34847c478bd9Sstevel@tonic-gate * the space left in the buffer.
34857c478bd9Sstevel@tonic-gate */
34867c478bd9Sstevel@tonic-gate rd_unit = MIN(rd_unit, space_left);
34877c478bd9Sstevel@tonic-gate iov.iov_base = (char *)dp;
34887c478bd9Sstevel@tonic-gate iov.iov_len = rd_unit;
34897c478bd9Sstevel@tonic-gate uio.uio_resid = rd_unit;
34907c478bd9Sstevel@tonic-gate prev_len = rd_unit;
34917c478bd9Sstevel@tonic-gate
3492da6c28aaSamw error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
34937c478bd9Sstevel@tonic-gate
34947c478bd9Sstevel@tonic-gate if (error) {
34957c478bd9Sstevel@tonic-gate kmem_free(data, args->dircount);
34967c478bd9Sstevel@tonic-gate goto out;
34977c478bd9Sstevel@tonic-gate }
34987c478bd9Sstevel@tonic-gate
34997c478bd9Sstevel@tonic-gate if (uio.uio_resid == prev_len && !iseof) {
35007c478bd9Sstevel@tonic-gate if (nents == 0) {
35017c478bd9Sstevel@tonic-gate kmem_free(data, args->dircount);
35027c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_TOOSMALL;
35037c478bd9Sstevel@tonic-gate goto out1;
35047c478bd9Sstevel@tonic-gate }
35057c478bd9Sstevel@tonic-gate
35067c478bd9Sstevel@tonic-gate /*
35077c478bd9Sstevel@tonic-gate * We could not get any more entries, so get the attributes
35087c478bd9Sstevel@tonic-gate * and filehandle for the entries already obtained.
35097c478bd9Sstevel@tonic-gate */
35107c478bd9Sstevel@tonic-gate goto good;
35117c478bd9Sstevel@tonic-gate }
35127c478bd9Sstevel@tonic-gate
35137c478bd9Sstevel@tonic-gate /*
35147c478bd9Sstevel@tonic-gate * We estimate the size of the response by assuming the
35157c478bd9Sstevel@tonic-gate * entry exists and attributes and filehandle are also valid
35167c478bd9Sstevel@tonic-gate */
35177c478bd9Sstevel@tonic-gate for (size = prev_len - uio.uio_resid;
35187c478bd9Sstevel@tonic-gate size > 0;
35197c478bd9Sstevel@tonic-gate size -= dp->d_reclen, dp = nextdp(dp)) {
35207c478bd9Sstevel@tonic-gate
35217c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) {
35227c478bd9Sstevel@tonic-gate nents++;
35237c478bd9Sstevel@tonic-gate continue;
35247c478bd9Sstevel@tonic-gate }
35257c478bd9Sstevel@tonic-gate
35267c478bd9Sstevel@tonic-gate namlen[nents] = strlen(dp->d_name);
35277c478bd9Sstevel@tonic-gate entrysize = NFS3_READDIRPLUS_ENTRY(namlen[nents]);
35287c478bd9Sstevel@tonic-gate
35297c478bd9Sstevel@tonic-gate /*
35307c478bd9Sstevel@tonic-gate * We need to check to see if the number of bytes left
35317c478bd9Sstevel@tonic-gate * to go into the buffer will actually fit into the
35327c478bd9Sstevel@tonic-gate * buffer. This is calculated as the size of this
35337c478bd9Sstevel@tonic-gate * entry plus:
35347c478bd9Sstevel@tonic-gate * 1 for the true/false list indicator +
35357c478bd9Sstevel@tonic-gate * 1 for the eof indicator
35367c478bd9Sstevel@tonic-gate * times BYTES_PER_XDR_UNIT to convert from XDR units
35377c478bd9Sstevel@tonic-gate * to bytes.
35387c478bd9Sstevel@tonic-gate *
35397c478bd9Sstevel@tonic-gate * Also check the dircount limit against the first entry read
35407c478bd9Sstevel@tonic-gate *
35417c478bd9Sstevel@tonic-gate */
35427c478bd9Sstevel@tonic-gate tofit = entrysize + (1 + 1) * BYTES_PER_XDR_UNIT;
35437c478bd9Sstevel@tonic-gate if (bufsize + tofit > args->maxcount) {
35447c478bd9Sstevel@tonic-gate /*
35457c478bd9Sstevel@tonic-gate * We make a check here to see if this was the
35467c478bd9Sstevel@tonic-gate * first entry being measured. If so, then maxcount
35477c478bd9Sstevel@tonic-gate * was too small to begin with and so we need to
35487c478bd9Sstevel@tonic-gate * return with NFS3ERR_TOOSMALL.
35497c478bd9Sstevel@tonic-gate */
35507c478bd9Sstevel@tonic-gate if (nents == 0) {
35517c478bd9Sstevel@tonic-gate kmem_free(data, args->dircount);
35527c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_TOOSMALL;
35537c478bd9Sstevel@tonic-gate goto out1;
35547c478bd9Sstevel@tonic-gate }
35557c478bd9Sstevel@tonic-gate iseof = FALSE;
35567c478bd9Sstevel@tonic-gate goto good;
35577c478bd9Sstevel@tonic-gate }
35587c478bd9Sstevel@tonic-gate bufsize += entrysize;
35597c478bd9Sstevel@tonic-gate nents++;
35607c478bd9Sstevel@tonic-gate }
35617c478bd9Sstevel@tonic-gate
35627c478bd9Sstevel@tonic-gate /*
35637c478bd9Sstevel@tonic-gate * If there is enough room to fit at least 1 more entry including
35647c478bd9Sstevel@tonic-gate * post op attributes and filehandle in the buffer AND that we haven't
35657c478bd9Sstevel@tonic-gate * exceeded dircount then go back and get some more.
35667c478bd9Sstevel@tonic-gate */
35677c478bd9Sstevel@tonic-gate if (!iseof &&
35687c478bd9Sstevel@tonic-gate (args->maxcount - bufsize) >= NFS3_READDIRPLUS_ENTRY(MAXNAMELEN)) {
35697c478bd9Sstevel@tonic-gate space_left -= (prev_len - uio.uio_resid);
35707c478bd9Sstevel@tonic-gate if (space_left >= DIRENT64_RECLEN(MAXNAMELEN))
35717c478bd9Sstevel@tonic-gate goto getmoredents;
35727c478bd9Sstevel@tonic-gate
35737c478bd9Sstevel@tonic-gate /* else, fall through */
35747c478bd9Sstevel@tonic-gate }
35757c478bd9Sstevel@tonic-gate good:
35767c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3577da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
35787c478bd9Sstevel@tonic-gate
35797c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
35807c478bd9Sstevel@tonic-gate
35817c478bd9Sstevel@tonic-gate infop = kmem_alloc(nents * sizeof (struct entryplus3_info), KM_SLEEP);
35827c478bd9Sstevel@tonic-gate resp->resok.infop = infop;
35837c478bd9Sstevel@tonic-gate
35847c478bd9Sstevel@tonic-gate dp = (struct dirent64 *)data;
35857c478bd9Sstevel@tonic-gate for (i = 0; i < nents; i++) {
35867c478bd9Sstevel@tonic-gate
35877c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) {
35887c478bd9Sstevel@tonic-gate infop[i].attr.attributes = FALSE;
35897c478bd9Sstevel@tonic-gate infop[i].fh.handle_follows = FALSE;
35907c478bd9Sstevel@tonic-gate dp = nextdp(dp);
35917c478bd9Sstevel@tonic-gate continue;
35927c478bd9Sstevel@tonic-gate }
35937c478bd9Sstevel@tonic-gate
35947c478bd9Sstevel@tonic-gate infop[i].namelen = namlen[i];
35957c478bd9Sstevel@tonic-gate
3596da6c28aaSamw error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr,
3597da6c28aaSamw NULL, NULL, NULL);
35987c478bd9Sstevel@tonic-gate if (error) {
35997c478bd9Sstevel@tonic-gate infop[i].attr.attributes = FALSE;
36007c478bd9Sstevel@tonic-gate infop[i].fh.handle_follows = FALSE;
36017c478bd9Sstevel@tonic-gate dp = nextdp(dp);
36027c478bd9Sstevel@tonic-gate continue;
36037c478bd9Sstevel@tonic-gate }
36047c478bd9Sstevel@tonic-gate
36057c478bd9Sstevel@tonic-gate nva.va_mask = AT_ALL;
36067c478bd9Sstevel@tonic-gate nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL : &nva;
360727246829SVitaliy Gusev
36082f172c55SRobert Thurlow /* Lie about the object type for a referral */
36092f172c55SRobert Thurlow if (vn_is_nfs_reparse(nvp, cr))
36102f172c55SRobert Thurlow nvap->va_type = VLNK;
36112f172c55SRobert Thurlow
36127c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(nvap, &infop[i].attr);
36137c478bd9Sstevel@tonic-gate
36147c478bd9Sstevel@tonic-gate error = makefh3(&infop[i].fh.handle, nvp, exi);
36157c478bd9Sstevel@tonic-gate if (!error)
36167c478bd9Sstevel@tonic-gate infop[i].fh.handle_follows = TRUE;
36177c478bd9Sstevel@tonic-gate else
36187c478bd9Sstevel@tonic-gate infop[i].fh.handle_follows = FALSE;
36197c478bd9Sstevel@tonic-gate
36207c478bd9Sstevel@tonic-gate VN_RELE(nvp);
36217c478bd9Sstevel@tonic-gate dp = nextdp(dp);
36227c478bd9Sstevel@tonic-gate }
36237c478bd9Sstevel@tonic-gate
3624b89a8333Snatalie li - Sun Microsystems - Irvine United States ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3625b89a8333Snatalie li - Sun Microsystems - Irvine United States ret = nfscmd_convdirplus(ca, exi, data, nents, args->dircount, &ndata);
3626b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ndata == NULL)
3627b89a8333Snatalie li - Sun Microsystems - Irvine United States ndata = data;
3628b89a8333Snatalie li - Sun Microsystems - Irvine United States
3629b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ret > 0) {
3630b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
3631b89a8333Snatalie li - Sun Microsystems - Irvine United States * We had to drop one or more entries in order to fit
3632b89a8333Snatalie li - Sun Microsystems - Irvine United States * during the character conversion. We need to patch
3633b89a8333Snatalie li - Sun Microsystems - Irvine United States * up the size and eof info.
3634b89a8333Snatalie li - Sun Microsystems - Irvine United States */
3635b89a8333Snatalie li - Sun Microsystems - Irvine United States if (iseof)
3636b89a8333Snatalie li - Sun Microsystems - Irvine United States iseof = FALSE;
3637b89a8333Snatalie li - Sun Microsystems - Irvine United States
3638b89a8333Snatalie li - Sun Microsystems - Irvine United States ret = nfscmd_dropped_entrysize((struct dirent64 *)data,
3639b89a8333Snatalie li - Sun Microsystems - Irvine United States nents, ret);
3640b89a8333Snatalie li - Sun Microsystems - Irvine United States }
3641b89a8333Snatalie li - Sun Microsystems - Irvine United States
3642b89a8333Snatalie li - Sun Microsystems - Irvine United States
36437c478bd9Sstevel@tonic-gate #if 0 /* notyet */
36447c478bd9Sstevel@tonic-gate /*
36457c478bd9Sstevel@tonic-gate * Don't do this. It causes local disk writes when just
36467c478bd9Sstevel@tonic-gate * reading the file and the overhead is deemed larger
36477c478bd9Sstevel@tonic-gate * than the benefit.
36487c478bd9Sstevel@tonic-gate */
36497c478bd9Sstevel@tonic-gate /*
36507c478bd9Sstevel@tonic-gate * Force modified metadata out to stable storage.
36517c478bd9Sstevel@tonic-gate */
3652da6c28aaSamw (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
36537c478bd9Sstevel@tonic-gate #endif
36547c478bd9Sstevel@tonic-gate
36557c478bd9Sstevel@tonic-gate kmem_free(namlen, args->dircount);
36567c478bd9Sstevel@tonic-gate
36577c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
36587c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
36597c478bd9Sstevel@tonic-gate resp->resok.cookieverf = 0;
3660b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->resok.reply.entries = (entryplus3 *)ndata;
36617c478bd9Sstevel@tonic-gate resp->resok.reply.eof = iseof;
36627c478bd9Sstevel@tonic-gate resp->resok.size = nents;
3663b89a8333Snatalie li - Sun Microsystems - Irvine United States resp->resok.count = args->dircount - ret;
36647c478bd9Sstevel@tonic-gate resp->resok.maxcount = args->maxcount;
3665e1adf50cSahl
3666e1adf50cSahl DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
3667e1adf50cSahl cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
3668b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ndata != data)
3669b89a8333Snatalie li - Sun Microsystems - Irvine United States kmem_free(data, args->dircount);
3670b89a8333Snatalie li - Sun Microsystems - Irvine United States
3671e1adf50cSahl
3672e1adf50cSahl VN_RELE(vp);
3673e1adf50cSahl
36747c478bd9Sstevel@tonic-gate return;
36757c478bd9Sstevel@tonic-gate
36767c478bd9Sstevel@tonic-gate out:
36777c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
36787c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
36797c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
3680b89a8333Snatalie li - Sun Microsystems - Irvine United States } else {
36817c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
3682b89a8333Snatalie li - Sun Microsystems - Irvine United States }
36837c478bd9Sstevel@tonic-gate out1:
3684e1adf50cSahl DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
3685e1adf50cSahl cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
3686e1adf50cSahl
36877c478bd9Sstevel@tonic-gate if (vp != NULL) {
36887c478bd9Sstevel@tonic-gate VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
36897c478bd9Sstevel@tonic-gate VN_RELE(vp);
36907c478bd9Sstevel@tonic-gate }
36917c478bd9Sstevel@tonic-gate
36927c478bd9Sstevel@tonic-gate if (namlen != NULL)
36937c478bd9Sstevel@tonic-gate kmem_free(namlen, args->dircount);
36947c478bd9Sstevel@tonic-gate
36957c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
36967c478bd9Sstevel@tonic-gate }
36977c478bd9Sstevel@tonic-gate
369827242a7cSthurlow void *
rfs3_readdirplus_getfh(READDIRPLUS3args * args)36997c478bd9Sstevel@tonic-gate rfs3_readdirplus_getfh(READDIRPLUS3args *args)
37007c478bd9Sstevel@tonic-gate {
37017c478bd9Sstevel@tonic-gate
370227242a7cSthurlow return (&args->dir);
37037c478bd9Sstevel@tonic-gate }
37047c478bd9Sstevel@tonic-gate
37057c478bd9Sstevel@tonic-gate void
rfs3_readdirplus_free(READDIRPLUS3res * resp)37067c478bd9Sstevel@tonic-gate rfs3_readdirplus_free(READDIRPLUS3res *resp)
37077c478bd9Sstevel@tonic-gate {
37087c478bd9Sstevel@tonic-gate
37097c478bd9Sstevel@tonic-gate if (resp->status == NFS3_OK) {
37107c478bd9Sstevel@tonic-gate kmem_free(resp->resok.reply.entries, resp->resok.count);
37117c478bd9Sstevel@tonic-gate kmem_free(resp->resok.infop,
37127c478bd9Sstevel@tonic-gate resp->resok.size * sizeof (struct entryplus3_info));
37137c478bd9Sstevel@tonic-gate }
37147c478bd9Sstevel@tonic-gate }
37157c478bd9Sstevel@tonic-gate
37167c478bd9Sstevel@tonic-gate /* ARGSUSED */
37177c478bd9Sstevel@tonic-gate void
rfs3_fsstat(FSSTAT3args * args,FSSTAT3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)37187c478bd9Sstevel@tonic-gate rfs3_fsstat(FSSTAT3args *args, FSSTAT3res *resp, struct exportinfo *exi,
37195cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
37207c478bd9Sstevel@tonic-gate {
37217c478bd9Sstevel@tonic-gate int error;
37227c478bd9Sstevel@tonic-gate vnode_t *vp;
37237c478bd9Sstevel@tonic-gate struct vattr *vap;
37247c478bd9Sstevel@tonic-gate struct vattr va;
37257c478bd9Sstevel@tonic-gate struct statvfs64 sb;
37267c478bd9Sstevel@tonic-gate
37277c478bd9Sstevel@tonic-gate vap = NULL;
37287c478bd9Sstevel@tonic-gate
37297c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->fsroot, exi);
3730e1adf50cSahl
3731e1adf50cSahl DTRACE_NFSV3_4(op__fsstat__start, struct svc_req *, req,
3732e1adf50cSahl cred_t *, cr, vnode_t *, vp, FSSTAT3args *, args);
3733e1adf50cSahl
37347c478bd9Sstevel@tonic-gate if (vp == NULL) {
37357c478bd9Sstevel@tonic-gate error = ESTALE;
37367c478bd9Sstevel@tonic-gate goto out;
37377c478bd9Sstevel@tonic-gate }
37387c478bd9Sstevel@tonic-gate
373903986916Sjarrett if (is_system_labeled()) {
374003986916Sjarrett bslabel_t *clabel = req->rq_label;
374103986916Sjarrett
374203986916Sjarrett ASSERT(clabel != NULL);
374303986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opfsstat__clabel, char *,
374403986916Sjarrett "got client label from request(1)", struct svc_req *, req);
374503986916Sjarrett
374603986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3747bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3748bd6f1640SJarrett Lu exi)) {
374903986916Sjarrett resp->status = NFS3ERR_ACCES;
375003986916Sjarrett goto out1;
375103986916Sjarrett }
375203986916Sjarrett }
375303986916Sjarrett }
375403986916Sjarrett
37557c478bd9Sstevel@tonic-gate error = VFS_STATVFS(vp->v_vfsp, &sb);
37567c478bd9Sstevel@tonic-gate
37577c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3758da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
37597c478bd9Sstevel@tonic-gate
37607c478bd9Sstevel@tonic-gate if (error)
37617c478bd9Sstevel@tonic-gate goto out;
37627c478bd9Sstevel@tonic-gate
37637c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
37647c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
37657c478bd9Sstevel@tonic-gate if (sb.f_blocks != (fsblkcnt64_t)-1)
37667c478bd9Sstevel@tonic-gate resp->resok.tbytes = (size3)sb.f_frsize * (size3)sb.f_blocks;
37677c478bd9Sstevel@tonic-gate else
37687c478bd9Sstevel@tonic-gate resp->resok.tbytes = (size3)sb.f_blocks;
37697c478bd9Sstevel@tonic-gate if (sb.f_bfree != (fsblkcnt64_t)-1)
37707c478bd9Sstevel@tonic-gate resp->resok.fbytes = (size3)sb.f_frsize * (size3)sb.f_bfree;
37717c478bd9Sstevel@tonic-gate else
37727c478bd9Sstevel@tonic-gate resp->resok.fbytes = (size3)sb.f_bfree;
37737c478bd9Sstevel@tonic-gate if (sb.f_bavail != (fsblkcnt64_t)-1)
37747c478bd9Sstevel@tonic-gate resp->resok.abytes = (size3)sb.f_frsize * (size3)sb.f_bavail;
37757c478bd9Sstevel@tonic-gate else
37767c478bd9Sstevel@tonic-gate resp->resok.abytes = (size3)sb.f_bavail;
37777c478bd9Sstevel@tonic-gate resp->resok.tfiles = (size3)sb.f_files;
37787c478bd9Sstevel@tonic-gate resp->resok.ffiles = (size3)sb.f_ffree;
37797c478bd9Sstevel@tonic-gate resp->resok.afiles = (size3)sb.f_favail;
37807c478bd9Sstevel@tonic-gate resp->resok.invarsec = 0;
3781e1adf50cSahl
3782e1adf50cSahl DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
3783e1adf50cSahl cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
3784e1adf50cSahl VN_RELE(vp);
3785e1adf50cSahl
37867c478bd9Sstevel@tonic-gate return;
37877c478bd9Sstevel@tonic-gate
37887c478bd9Sstevel@tonic-gate out:
37897c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
37907c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
37917c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
37927c478bd9Sstevel@tonic-gate } else
37937c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
379403986916Sjarrett out1:
3795e1adf50cSahl DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
3796e1adf50cSahl cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
3797e1adf50cSahl
379803986916Sjarrett if (vp != NULL)
379903986916Sjarrett VN_RELE(vp);
38007c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
38017c478bd9Sstevel@tonic-gate }
38027c478bd9Sstevel@tonic-gate
380327242a7cSthurlow void *
rfs3_fsstat_getfh(FSSTAT3args * args)38047c478bd9Sstevel@tonic-gate rfs3_fsstat_getfh(FSSTAT3args *args)
38057c478bd9Sstevel@tonic-gate {
38067c478bd9Sstevel@tonic-gate
380727242a7cSthurlow return (&args->fsroot);
38087c478bd9Sstevel@tonic-gate }
38097c478bd9Sstevel@tonic-gate
38105cb0d679SMarcel Telka /* ARGSUSED */
38117c478bd9Sstevel@tonic-gate void
rfs3_fsinfo(FSINFO3args * args,FSINFO3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)38127c478bd9Sstevel@tonic-gate rfs3_fsinfo(FSINFO3args *args, FSINFO3res *resp, struct exportinfo *exi,
38135cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
38147c478bd9Sstevel@tonic-gate {
38157c478bd9Sstevel@tonic-gate vnode_t *vp;
38167c478bd9Sstevel@tonic-gate struct vattr *vap;
38177c478bd9Sstevel@tonic-gate struct vattr va;
38187c478bd9Sstevel@tonic-gate uint32_t xfer_size;
38197c478bd9Sstevel@tonic-gate ulong_t l = 0;
38207c478bd9Sstevel@tonic-gate int error;
38217c478bd9Sstevel@tonic-gate
38227c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->fsroot, exi);
3823e1adf50cSahl
3824e1adf50cSahl DTRACE_NFSV3_4(op__fsinfo__start, struct svc_req *, req,
3825e1adf50cSahl cred_t *, cr, vnode_t *, vp, FSINFO3args *, args);
3826e1adf50cSahl
38277c478bd9Sstevel@tonic-gate if (vp == NULL) {
38287c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
38297c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
38307c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
38317c478bd9Sstevel@tonic-gate } else
38327c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_STALE;
38337c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(NULL, &resp->resfail.obj_attributes);
3834e1adf50cSahl goto out;
38357c478bd9Sstevel@tonic-gate }
38367c478bd9Sstevel@tonic-gate
383703986916Sjarrett if (is_system_labeled()) {
383803986916Sjarrett bslabel_t *clabel = req->rq_label;
383903986916Sjarrett
384003986916Sjarrett ASSERT(clabel != NULL);
384103986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opfsinfo__clabel, char *,
384203986916Sjarrett "got client label from request(1)", struct svc_req *, req);
384303986916Sjarrett
384403986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3845bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3846bd6f1640SJarrett Lu exi)) {
384703986916Sjarrett resp->status = NFS3ERR_STALE;
384803986916Sjarrett vattr_to_post_op_attr(NULL,
384903986916Sjarrett &resp->resfail.obj_attributes);
3850e1adf50cSahl goto out;
385103986916Sjarrett }
385203986916Sjarrett }
385303986916Sjarrett }
385403986916Sjarrett
38557c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3856da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
38577c478bd9Sstevel@tonic-gate
38587c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
38597c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
38607c478bd9Sstevel@tonic-gate xfer_size = rfs3_tsize(req);
38617c478bd9Sstevel@tonic-gate resp->resok.rtmax = xfer_size;
38627c478bd9Sstevel@tonic-gate resp->resok.rtpref = xfer_size;
38637c478bd9Sstevel@tonic-gate resp->resok.rtmult = DEV_BSIZE;
38647c478bd9Sstevel@tonic-gate resp->resok.wtmax = xfer_size;
38657c478bd9Sstevel@tonic-gate resp->resok.wtpref = xfer_size;
38667c478bd9Sstevel@tonic-gate resp->resok.wtmult = DEV_BSIZE;
38677c478bd9Sstevel@tonic-gate resp->resok.dtpref = MAXBSIZE;
38687c478bd9Sstevel@tonic-gate
38697c478bd9Sstevel@tonic-gate /*
38707c478bd9Sstevel@tonic-gate * Large file spec: want maxfilesize based on limit of
38717c478bd9Sstevel@tonic-gate * underlying filesystem. We can guess 2^31-1 if need be.
38727c478bd9Sstevel@tonic-gate */
3873da6c28aaSamw error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
3874710f82c5SPiyush Shivam if (error) {
3875710f82c5SPiyush Shivam resp->status = puterrno3(error);
3876710f82c5SPiyush Shivam goto out;
3877710f82c5SPiyush Shivam }
38787c478bd9Sstevel@tonic-gate
3879710f82c5SPiyush Shivam /*
3880710f82c5SPiyush Shivam * If the underlying file system does not support _PC_FILESIZEBITS,
3881710f82c5SPiyush Shivam * return a reasonable default. Note that error code on VOP_PATHCONF
3882710f82c5SPiyush Shivam * will be 0, even if the underlying file system does not support
3883710f82c5SPiyush Shivam * _PC_FILESIZEBITS.
3884710f82c5SPiyush Shivam */
3885710f82c5SPiyush Shivam if (l == (ulong_t)-1) {
38867c478bd9Sstevel@tonic-gate resp->resok.maxfilesize = MAXOFF32_T;
3887710f82c5SPiyush Shivam } else {
3888710f82c5SPiyush Shivam if (l >= (sizeof (uint64_t) * 8))
3889710f82c5SPiyush Shivam resp->resok.maxfilesize = INT64_MAX;
3890710f82c5SPiyush Shivam else
3891710f82c5SPiyush Shivam resp->resok.maxfilesize = (1LL << (l-1)) - 1;
3892710f82c5SPiyush Shivam }
38937c478bd9Sstevel@tonic-gate
38947c478bd9Sstevel@tonic-gate resp->resok.time_delta.seconds = 0;
38957c478bd9Sstevel@tonic-gate resp->resok.time_delta.nseconds = 1000;
38967c478bd9Sstevel@tonic-gate resp->resok.properties = FSF3_LINK | FSF3_SYMLINK |
38977c478bd9Sstevel@tonic-gate FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
3898e1adf50cSahl
3899e1adf50cSahl DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
3900e1adf50cSahl cred_t *, cr, vnode_t *, vp, FSINFO3res *, resp);
3901e1adf50cSahl
3902e1adf50cSahl VN_RELE(vp);
3903e1adf50cSahl
3904e1adf50cSahl return;
3905e1adf50cSahl
3906e1adf50cSahl out:
3907e1adf50cSahl DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
3908e1adf50cSahl cred_t *, cr, vnode_t *, NULL, FSINFO3res *, resp);
3909e1adf50cSahl if (vp != NULL)
3910e1adf50cSahl VN_RELE(vp);
39117c478bd9Sstevel@tonic-gate }
39127c478bd9Sstevel@tonic-gate
391327242a7cSthurlow void *
rfs3_fsinfo_getfh(FSINFO3args * args)39147c478bd9Sstevel@tonic-gate rfs3_fsinfo_getfh(FSINFO3args *args)
39157c478bd9Sstevel@tonic-gate {
391627242a7cSthurlow return (&args->fsroot);
39177c478bd9Sstevel@tonic-gate }
39187c478bd9Sstevel@tonic-gate
39197c478bd9Sstevel@tonic-gate /* ARGSUSED */
39207c478bd9Sstevel@tonic-gate void
rfs3_pathconf(PATHCONF3args * args,PATHCONF3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)39217c478bd9Sstevel@tonic-gate rfs3_pathconf(PATHCONF3args *args, PATHCONF3res *resp, struct exportinfo *exi,
39225cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
39237c478bd9Sstevel@tonic-gate {
39247c478bd9Sstevel@tonic-gate int error;
39257c478bd9Sstevel@tonic-gate vnode_t *vp;
39267c478bd9Sstevel@tonic-gate struct vattr *vap;
39277c478bd9Sstevel@tonic-gate struct vattr va;
39287c478bd9Sstevel@tonic-gate ulong_t val;
39297c478bd9Sstevel@tonic-gate
39307c478bd9Sstevel@tonic-gate vap = NULL;
39317c478bd9Sstevel@tonic-gate
39327c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->object, exi);
3933e1adf50cSahl
3934e1adf50cSahl DTRACE_NFSV3_4(op__pathconf__start, struct svc_req *, req,
3935e1adf50cSahl cred_t *, cr, vnode_t *, vp, PATHCONF3args *, args);
3936e1adf50cSahl
39377c478bd9Sstevel@tonic-gate if (vp == NULL) {
39387c478bd9Sstevel@tonic-gate error = ESTALE;
39397c478bd9Sstevel@tonic-gate goto out;
39407c478bd9Sstevel@tonic-gate }
39417c478bd9Sstevel@tonic-gate
394203986916Sjarrett if (is_system_labeled()) {
394303986916Sjarrett bslabel_t *clabel = req->rq_label;
394403986916Sjarrett
394503986916Sjarrett ASSERT(clabel != NULL);
394603986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__oppathconf__clabel, char *,
394703986916Sjarrett "got client label from request(1)", struct svc_req *, req);
394803986916Sjarrett
394903986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
3950bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3951bd6f1640SJarrett Lu exi)) {
395203986916Sjarrett resp->status = NFS3ERR_ACCES;
395303986916Sjarrett goto out1;
395403986916Sjarrett }
395503986916Sjarrett }
395603986916Sjarrett }
395703986916Sjarrett
39587c478bd9Sstevel@tonic-gate va.va_mask = AT_ALL;
3959da6c28aaSamw vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
39607c478bd9Sstevel@tonic-gate
3961da6c28aaSamw error = VOP_PATHCONF(vp, _PC_LINK_MAX, &val, cr, NULL);
39627c478bd9Sstevel@tonic-gate if (error)
39637c478bd9Sstevel@tonic-gate goto out;
39647c478bd9Sstevel@tonic-gate resp->resok.info.link_max = (uint32)val;
39657c478bd9Sstevel@tonic-gate
3966da6c28aaSamw error = VOP_PATHCONF(vp, _PC_NAME_MAX, &val, cr, NULL);
39677c478bd9Sstevel@tonic-gate if (error)
39687c478bd9Sstevel@tonic-gate goto out;
39697c478bd9Sstevel@tonic-gate resp->resok.info.name_max = (uint32)val;
39707c478bd9Sstevel@tonic-gate
3971da6c28aaSamw error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &val, cr, NULL);
39727c478bd9Sstevel@tonic-gate if (error)
39737c478bd9Sstevel@tonic-gate goto out;
39747c478bd9Sstevel@tonic-gate if (val == 1)
39757c478bd9Sstevel@tonic-gate resp->resok.info.no_trunc = TRUE;
39767c478bd9Sstevel@tonic-gate else
39777c478bd9Sstevel@tonic-gate resp->resok.info.no_trunc = FALSE;
39787c478bd9Sstevel@tonic-gate
3979da6c28aaSamw error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &val, cr, NULL);
39807c478bd9Sstevel@tonic-gate if (error)
39817c478bd9Sstevel@tonic-gate goto out;
39827c478bd9Sstevel@tonic-gate if (val == 1)
39837c478bd9Sstevel@tonic-gate resp->resok.info.chown_restricted = TRUE;
39847c478bd9Sstevel@tonic-gate else
39857c478bd9Sstevel@tonic-gate resp->resok.info.chown_restricted = FALSE;
39867c478bd9Sstevel@tonic-gate
39877c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
39887c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
39897c478bd9Sstevel@tonic-gate resp->resok.info.case_insensitive = FALSE;
39907c478bd9Sstevel@tonic-gate resp->resok.info.case_preserving = TRUE;
3991e1adf50cSahl DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
3992e1adf50cSahl cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
3993e1adf50cSahl VN_RELE(vp);
39947c478bd9Sstevel@tonic-gate return;
39957c478bd9Sstevel@tonic-gate
39967c478bd9Sstevel@tonic-gate out:
39977c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
39987c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
39997c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
40007c478bd9Sstevel@tonic-gate } else
40017c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
400203986916Sjarrett out1:
4003e1adf50cSahl DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
4004e1adf50cSahl cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
40057c478bd9Sstevel@tonic-gate if (vp != NULL)
40067c478bd9Sstevel@tonic-gate VN_RELE(vp);
40077c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
40087c478bd9Sstevel@tonic-gate }
40097c478bd9Sstevel@tonic-gate
401027242a7cSthurlow void *
rfs3_pathconf_getfh(PATHCONF3args * args)40117c478bd9Sstevel@tonic-gate rfs3_pathconf_getfh(PATHCONF3args *args)
40127c478bd9Sstevel@tonic-gate {
40137c478bd9Sstevel@tonic-gate
401427242a7cSthurlow return (&args->object);
40157c478bd9Sstevel@tonic-gate }
40167c478bd9Sstevel@tonic-gate
40177c478bd9Sstevel@tonic-gate void
rfs3_commit(COMMIT3args * args,COMMIT3res * resp,struct exportinfo * exi,struct svc_req * req,cred_t * cr,bool_t ro)40187c478bd9Sstevel@tonic-gate rfs3_commit(COMMIT3args *args, COMMIT3res *resp, struct exportinfo *exi,
40195cb0d679SMarcel Telka struct svc_req *req, cred_t *cr, bool_t ro)
40207c478bd9Sstevel@tonic-gate {
40217c478bd9Sstevel@tonic-gate int error;
40227c478bd9Sstevel@tonic-gate vnode_t *vp;
40237c478bd9Sstevel@tonic-gate struct vattr *bvap;
40247c478bd9Sstevel@tonic-gate struct vattr bva;
40257c478bd9Sstevel@tonic-gate struct vattr *avap;
40267c478bd9Sstevel@tonic-gate struct vattr ava;
40277c478bd9Sstevel@tonic-gate
40287c478bd9Sstevel@tonic-gate bvap = NULL;
40297c478bd9Sstevel@tonic-gate avap = NULL;
40307c478bd9Sstevel@tonic-gate
40317c478bd9Sstevel@tonic-gate vp = nfs3_fhtovp(&args->file, exi);
4032e1adf50cSahl
4033e1adf50cSahl DTRACE_NFSV3_4(op__commit__start, struct svc_req *, req,
4034e1adf50cSahl cred_t *, cr, vnode_t *, vp, COMMIT3args *, args);
4035e1adf50cSahl
40367c478bd9Sstevel@tonic-gate if (vp == NULL) {
40377c478bd9Sstevel@tonic-gate error = ESTALE;
40387c478bd9Sstevel@tonic-gate goto out;
40397c478bd9Sstevel@tonic-gate }
40407c478bd9Sstevel@tonic-gate
40417c478bd9Sstevel@tonic-gate bva.va_mask = AT_ALL;
4042da6c28aaSamw error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
40437c478bd9Sstevel@tonic-gate
40447c478bd9Sstevel@tonic-gate /*
40457c478bd9Sstevel@tonic-gate * If we can't get the attributes, then we can't do the
40467c478bd9Sstevel@tonic-gate * right access checking. So, we'll fail the request.
40477c478bd9Sstevel@tonic-gate */
40487c478bd9Sstevel@tonic-gate if (error)
40497c478bd9Sstevel@tonic-gate goto out;
40507c478bd9Sstevel@tonic-gate
40517c478bd9Sstevel@tonic-gate bvap = &bva;
40527c478bd9Sstevel@tonic-gate
40535cb0d679SMarcel Telka if (rdonly(ro, vp)) {
40547c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_ROFS;
40557c478bd9Sstevel@tonic-gate goto out1;
40567c478bd9Sstevel@tonic-gate }
40577c478bd9Sstevel@tonic-gate
40587c478bd9Sstevel@tonic-gate if (vp->v_type != VREG) {
40597c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_INVAL;
40607c478bd9Sstevel@tonic-gate goto out1;
40617c478bd9Sstevel@tonic-gate }
40627c478bd9Sstevel@tonic-gate
406303986916Sjarrett if (is_system_labeled()) {
406403986916Sjarrett bslabel_t *clabel = req->rq_label;
406503986916Sjarrett
406603986916Sjarrett ASSERT(clabel != NULL);
406703986916Sjarrett DTRACE_PROBE2(tx__rfs3__log__info__opcommit__clabel, char *,
406803986916Sjarrett "got client label from request(1)", struct svc_req *, req);
406903986916Sjarrett
407003986916Sjarrett if (!blequal(&l_admin_low->tsl_label, clabel)) {
4071bd6f1640SJarrett Lu if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4072bd6f1640SJarrett Lu exi)) {
407303986916Sjarrett resp->status = NFS3ERR_ACCES;
407403986916Sjarrett goto out1;
407503986916Sjarrett }
407603986916Sjarrett }
407703986916Sjarrett }
407803986916Sjarrett
40797c478bd9Sstevel@tonic-gate if (crgetuid(cr) != bva.va_uid &&
4080da6c28aaSamw (error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL)))
40817c478bd9Sstevel@tonic-gate goto out;
40827c478bd9Sstevel@tonic-gate
4083f63200e6SJeff A. Smith error = VOP_FSYNC(vp, FSYNC, cr, NULL);
40847c478bd9Sstevel@tonic-gate
40857c478bd9Sstevel@tonic-gate ava.va_mask = AT_ALL;
4086da6c28aaSamw avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
40877c478bd9Sstevel@tonic-gate
40887c478bd9Sstevel@tonic-gate if (error)
40897c478bd9Sstevel@tonic-gate goto out;
40907c478bd9Sstevel@tonic-gate
40917c478bd9Sstevel@tonic-gate resp->status = NFS3_OK;
40927c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
40937c478bd9Sstevel@tonic-gate resp->resok.verf = write3verf;
4094e1adf50cSahl
4095e1adf50cSahl DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4096e1adf50cSahl cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4097e1adf50cSahl
4098e1adf50cSahl VN_RELE(vp);
4099e1adf50cSahl
41007c478bd9Sstevel@tonic-gate return;
41017c478bd9Sstevel@tonic-gate
41027c478bd9Sstevel@tonic-gate out:
41037c478bd9Sstevel@tonic-gate if (curthread->t_flag & T_WOULDBLOCK) {
41047c478bd9Sstevel@tonic-gate curthread->t_flag &= ~T_WOULDBLOCK;
41057c478bd9Sstevel@tonic-gate resp->status = NFS3ERR_JUKEBOX;
41067c478bd9Sstevel@tonic-gate } else
41077c478bd9Sstevel@tonic-gate resp->status = puterrno3(error);
41087c478bd9Sstevel@tonic-gate out1:
4109e1adf50cSahl DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4110e1adf50cSahl cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4111e1adf50cSahl
41127c478bd9Sstevel@tonic-gate if (vp != NULL)
41137c478bd9Sstevel@tonic-gate VN_RELE(vp);
41147c478bd9Sstevel@tonic-gate vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
41157c478bd9Sstevel@tonic-gate }
41167c478bd9Sstevel@tonic-gate
411727242a7cSthurlow void *
rfs3_commit_getfh(COMMIT3args * args)41187c478bd9Sstevel@tonic-gate rfs3_commit_getfh(COMMIT3args *args)
41197c478bd9Sstevel@tonic-gate {
41207c478bd9Sstevel@tonic-gate
412127242a7cSthurlow return (&args->file);
41227c478bd9Sstevel@tonic-gate }
41237c478bd9Sstevel@tonic-gate
41247c478bd9Sstevel@tonic-gate static int
sattr3_to_vattr(sattr3 * sap,struct vattr * vap)41257c478bd9Sstevel@tonic-gate sattr3_to_vattr(sattr3 *sap, struct vattr *vap)
41267c478bd9Sstevel@tonic-gate {
41277c478bd9Sstevel@tonic-gate
41287c478bd9Sstevel@tonic-gate vap->va_mask = 0;
41297c478bd9Sstevel@tonic-gate
41307c478bd9Sstevel@tonic-gate if (sap->mode.set_it) {
41317c478bd9Sstevel@tonic-gate vap->va_mode = (mode_t)sap->mode.mode;
41327c478bd9Sstevel@tonic-gate vap->va_mask |= AT_MODE;
41337c478bd9Sstevel@tonic-gate }
41347c478bd9Sstevel@tonic-gate if (sap->uid.set_it) {
41357c478bd9Sstevel@tonic-gate vap->va_uid = (uid_t)sap->uid.uid;
41367c478bd9Sstevel@tonic-gate vap->va_mask |= AT_UID;
41377c478bd9Sstevel@tonic-gate }
41387c478bd9Sstevel@tonic-gate if (sap->gid.set_it) {
41397c478bd9Sstevel@tonic-gate vap->va_gid = (gid_t)sap->gid.gid;
41407c478bd9Sstevel@tonic-gate vap->va_mask |= AT_GID;
41417c478bd9Sstevel@tonic-gate }
41427c478bd9Sstevel@tonic-gate if (sap->size.set_it) {
41437c478bd9Sstevel@tonic-gate if (sap->size.size > (size3)((u_longlong_t)-1))
41447c478bd9Sstevel@tonic-gate return (EINVAL);
41457c478bd9Sstevel@tonic-gate vap->va_size = sap->size.size;
41467c478bd9Sstevel@tonic-gate vap->va_mask |= AT_SIZE;
41477c478bd9Sstevel@tonic-gate }
41487c478bd9Sstevel@tonic-gate if (sap->atime.set_it == SET_TO_CLIENT_TIME) {
41497c478bd9Sstevel@tonic-gate #ifndef _LP64
41507c478bd9Sstevel@tonic-gate /* check time validity */
41517c478bd9Sstevel@tonic-gate if (!NFS3_TIME_OK(sap->atime.atime.seconds))
41527c478bd9Sstevel@tonic-gate return (EOVERFLOW);
41537c478bd9Sstevel@tonic-gate #endif
41547c478bd9Sstevel@tonic-gate /*
41557c478bd9Sstevel@tonic-gate * nfs protocol defines times as unsigned so don't extend sign,
41567c478bd9Sstevel@tonic-gate * unless sysadmin set nfs_allow_preepoch_time.
41577c478bd9Sstevel@tonic-gate */
41587c478bd9Sstevel@tonic-gate NFS_TIME_T_CONVERT(vap->va_atime.tv_sec,
41597c478bd9Sstevel@tonic-gate sap->atime.atime.seconds);
41607c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = (uint32_t)sap->atime.atime.nseconds;
41617c478bd9Sstevel@tonic-gate vap->va_mask |= AT_ATIME;
41627c478bd9Sstevel@tonic-gate } else if (sap->atime.set_it == SET_TO_SERVER_TIME) {
41637c478bd9Sstevel@tonic-gate gethrestime(&vap->va_atime);
41647c478bd9Sstevel@tonic-gate vap->va_mask |= AT_ATIME;
41657c478bd9Sstevel@tonic-gate }
41667c478bd9Sstevel@tonic-gate if (sap->mtime.set_it == SET_TO_CLIENT_TIME) {
41677c478bd9Sstevel@tonic-gate #ifndef _LP64
41687c478bd9Sstevel@tonic-gate /* check time validity */
41697c478bd9Sstevel@tonic-gate if (!NFS3_TIME_OK(sap->mtime.mtime.seconds))
41707c478bd9Sstevel@tonic-gate return (EOVERFLOW);
41717c478bd9Sstevel@tonic-gate #endif
41727c478bd9Sstevel@tonic-gate /*
41737c478bd9Sstevel@tonic-gate * nfs protocol defines times as unsigned so don't extend sign,
41747c478bd9Sstevel@tonic-gate * unless sysadmin set nfs_allow_preepoch_time.
41757c478bd9Sstevel@tonic-gate */
41767c478bd9Sstevel@tonic-gate NFS_TIME_T_CONVERT(vap->va_mtime.tv_sec,
41777c478bd9Sstevel@tonic-gate sap->mtime.mtime.seconds);
41787c478bd9Sstevel@tonic-gate vap->va_mtime.tv_nsec = (uint32_t)sap->mtime.mtime.nseconds;
41797c478bd9Sstevel@tonic-gate vap->va_mask |= AT_MTIME;
41807c478bd9Sstevel@tonic-gate } else if (sap->mtime.set_it == SET_TO_SERVER_TIME) {
41817c478bd9Sstevel@tonic-gate gethrestime(&vap->va_mtime);
41827c478bd9Sstevel@tonic-gate vap->va_mask |= AT_MTIME;
41837c478bd9Sstevel@tonic-gate }
41847c478bd9Sstevel@tonic-gate
41857c478bd9Sstevel@tonic-gate return (0);
41867c478bd9Sstevel@tonic-gate }
41877c478bd9Sstevel@tonic-gate
41887c478bd9Sstevel@tonic-gate static ftype3 vt_to_nf3[] = {
41897c478bd9Sstevel@tonic-gate 0, NF3REG, NF3DIR, NF3BLK, NF3CHR, NF3LNK, NF3FIFO, 0, 0, NF3SOCK, 0
41907c478bd9Sstevel@tonic-gate };
41917c478bd9Sstevel@tonic-gate
41927c478bd9Sstevel@tonic-gate static int
vattr_to_fattr3(struct vattr * vap,fattr3 * fap)41937c478bd9Sstevel@tonic-gate vattr_to_fattr3(struct vattr *vap, fattr3 *fap)
41947c478bd9Sstevel@tonic-gate {
41957c478bd9Sstevel@tonic-gate
41967c478bd9Sstevel@tonic-gate ASSERT(vap->va_type >= VNON && vap->va_type <= VBAD);
41977c478bd9Sstevel@tonic-gate /* Return error if time or size overflow */
41987c478bd9Sstevel@tonic-gate if (! (NFS_VAP_TIME_OK(vap) && NFS3_SIZE_OK(vap->va_size))) {
41997c478bd9Sstevel@tonic-gate return (EOVERFLOW);
42007c478bd9Sstevel@tonic-gate }
42017c478bd9Sstevel@tonic-gate fap->type = vt_to_nf3[vap->va_type];
42027c478bd9Sstevel@tonic-gate fap->mode = (mode3)(vap->va_mode & MODEMASK);
42037c478bd9Sstevel@tonic-gate fap->nlink = (uint32)vap->va_nlink;
42047c478bd9Sstevel@tonic-gate if (vap->va_uid == UID_NOBODY)
42057c478bd9Sstevel@tonic-gate fap->uid = (uid3)NFS_UID_NOBODY;
42067c478bd9Sstevel@tonic-gate else
42077c478bd9Sstevel@tonic-gate fap->uid = (uid3)vap->va_uid;
42087c478bd9Sstevel@tonic-gate if (vap->va_gid == GID_NOBODY)
42097c478bd9Sstevel@tonic-gate fap->gid = (gid3)NFS_GID_NOBODY;
42107c478bd9Sstevel@tonic-gate else
42117c478bd9Sstevel@tonic-gate fap->gid = (gid3)vap->va_gid;
42127c478bd9Sstevel@tonic-gate fap->size = (size3)vap->va_size;
42137c478bd9Sstevel@tonic-gate fap->used = (size3)DEV_BSIZE * (size3)vap->va_nblocks;
42147c478bd9Sstevel@tonic-gate fap->rdev.specdata1 = (uint32)getmajor(vap->va_rdev);
42157c478bd9Sstevel@tonic-gate fap->rdev.specdata2 = (uint32)getminor(vap->va_rdev);
42167c478bd9Sstevel@tonic-gate fap->fsid = (uint64)vap->va_fsid;
42177c478bd9Sstevel@tonic-gate fap->fileid = (fileid3)vap->va_nodeid;
42187c478bd9Sstevel@tonic-gate fap->atime.seconds = vap->va_atime.tv_sec;
42197c478bd9Sstevel@tonic-gate fap->atime.nseconds = vap->va_atime.tv_nsec;
42207c478bd9Sstevel@tonic-gate fap->mtime.seconds = vap->va_mtime.tv_sec;
42217c478bd9Sstevel@tonic-gate fap->mtime.nseconds = vap->va_mtime.tv_nsec;
42227c478bd9Sstevel@tonic-gate fap->ctime.seconds = vap->va_ctime.tv_sec;
42237c478bd9Sstevel@tonic-gate fap->ctime.nseconds = vap->va_ctime.tv_nsec;
42247c478bd9Sstevel@tonic-gate return (0);
42257c478bd9Sstevel@tonic-gate }
42267c478bd9Sstevel@tonic-gate
42277c478bd9Sstevel@tonic-gate static int
vattr_to_wcc_attr(struct vattr * vap,wcc_attr * wccap)42287c478bd9Sstevel@tonic-gate vattr_to_wcc_attr(struct vattr *vap, wcc_attr *wccap)
42297c478bd9Sstevel@tonic-gate {
42307c478bd9Sstevel@tonic-gate
42317c478bd9Sstevel@tonic-gate /* Return error if time or size overflow */
42327c478bd9Sstevel@tonic-gate if (!(NFS_TIME_T_OK(vap->va_mtime.tv_sec) &&
42337c478bd9Sstevel@tonic-gate NFS_TIME_T_OK(vap->va_ctime.tv_sec) &&
42347c478bd9Sstevel@tonic-gate NFS3_SIZE_OK(vap->va_size))) {
42357c478bd9Sstevel@tonic-gate return (EOVERFLOW);
42367c478bd9Sstevel@tonic-gate }
42377c478bd9Sstevel@tonic-gate wccap->size = (size3)vap->va_size;
42387c478bd9Sstevel@tonic-gate wccap->mtime.seconds = vap->va_mtime.tv_sec;
42397c478bd9Sstevel@tonic-gate wccap->mtime.nseconds = vap->va_mtime.tv_nsec;
42407c478bd9Sstevel@tonic-gate wccap->ctime.seconds = vap->va_ctime.tv_sec;
42417c478bd9Sstevel@tonic-gate wccap->ctime.nseconds = vap->va_ctime.tv_nsec;
42427c478bd9Sstevel@tonic-gate return (0);
42437c478bd9Sstevel@tonic-gate }
42447c478bd9Sstevel@tonic-gate
42457c478bd9Sstevel@tonic-gate static void
vattr_to_pre_op_attr(struct vattr * vap,pre_op_attr * poap)42467c478bd9Sstevel@tonic-gate vattr_to_pre_op_attr(struct vattr *vap, pre_op_attr *poap)
42477c478bd9Sstevel@tonic-gate {
42487c478bd9Sstevel@tonic-gate
42497c478bd9Sstevel@tonic-gate /* don't return attrs if time overflow */
42507c478bd9Sstevel@tonic-gate if ((vap != NULL) && !vattr_to_wcc_attr(vap, &poap->attr)) {
42517c478bd9Sstevel@tonic-gate poap->attributes = TRUE;
42527c478bd9Sstevel@tonic-gate } else
42537c478bd9Sstevel@tonic-gate poap->attributes = FALSE;
42547c478bd9Sstevel@tonic-gate }
42557c478bd9Sstevel@tonic-gate
42567c478bd9Sstevel@tonic-gate void
vattr_to_post_op_attr(struct vattr * vap,post_op_attr * poap)42577c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(struct vattr *vap, post_op_attr *poap)
42587c478bd9Sstevel@tonic-gate {
42597c478bd9Sstevel@tonic-gate
42607c478bd9Sstevel@tonic-gate /* don't return attrs if time overflow */
42617c478bd9Sstevel@tonic-gate if ((vap != NULL) && !vattr_to_fattr3(vap, &poap->attr)) {
42627c478bd9Sstevel@tonic-gate poap->attributes = TRUE;
42637c478bd9Sstevel@tonic-gate } else
42647c478bd9Sstevel@tonic-gate poap->attributes = FALSE;
42657c478bd9Sstevel@tonic-gate }
42667c478bd9Sstevel@tonic-gate
42677c478bd9Sstevel@tonic-gate static void
vattr_to_wcc_data(struct vattr * bvap,struct vattr * avap,wcc_data * wccp)42687c478bd9Sstevel@tonic-gate vattr_to_wcc_data(struct vattr *bvap, struct vattr *avap, wcc_data *wccp)
42697c478bd9Sstevel@tonic-gate {
42707c478bd9Sstevel@tonic-gate
42717c478bd9Sstevel@tonic-gate vattr_to_pre_op_attr(bvap, &wccp->before);
42727c478bd9Sstevel@tonic-gate vattr_to_post_op_attr(avap, &wccp->after);
42737c478bd9Sstevel@tonic-gate }
42747c478bd9Sstevel@tonic-gate
42757c478bd9Sstevel@tonic-gate void
rfs3_srvrinit(void)42767c478bd9Sstevel@tonic-gate rfs3_srvrinit(void)
42777c478bd9Sstevel@tonic-gate {
42787c478bd9Sstevel@tonic-gate struct rfs3_verf_overlay {
42797c478bd9Sstevel@tonic-gate uint_t id; /* a "unique" identifier */
42807c478bd9Sstevel@tonic-gate int ts; /* a unique timestamp */
42817c478bd9Sstevel@tonic-gate } *verfp;
42827c478bd9Sstevel@tonic-gate timestruc_t now;
42837c478bd9Sstevel@tonic-gate
42847c478bd9Sstevel@tonic-gate /*
42857c478bd9Sstevel@tonic-gate * The following algorithm attempts to find a unique verifier
42867c478bd9Sstevel@tonic-gate * to be used as the write verifier returned from the server
42877c478bd9Sstevel@tonic-gate * to the client. It is important that this verifier change
42887c478bd9Sstevel@tonic-gate * whenever the server reboots. Of secondary importance, it
42897c478bd9Sstevel@tonic-gate * is important for the verifier to be unique between two
42907c478bd9Sstevel@tonic-gate * different servers.
42917c478bd9Sstevel@tonic-gate *
42927c478bd9Sstevel@tonic-gate * Thus, an attempt is made to use the system hostid and the
42937c478bd9Sstevel@tonic-gate * current time in seconds when the nfssrv kernel module is
42947c478bd9Sstevel@tonic-gate * loaded. It is assumed that an NFS server will not be able
42957c478bd9Sstevel@tonic-gate * to boot and then to reboot in less than a second. If the
42967c478bd9Sstevel@tonic-gate * hostid has not been set, then the current high resolution
42977c478bd9Sstevel@tonic-gate * time is used. This will ensure different verifiers each
42987c478bd9Sstevel@tonic-gate * time the server reboots and minimize the chances that two
42997c478bd9Sstevel@tonic-gate * different servers will have the same verifier.
43007c478bd9Sstevel@tonic-gate */
43017c478bd9Sstevel@tonic-gate
43027c478bd9Sstevel@tonic-gate #ifndef lint
43037c478bd9Sstevel@tonic-gate /*
43047c478bd9Sstevel@tonic-gate * We ASSERT that this constant logic expression is
43057c478bd9Sstevel@tonic-gate * always true because in the past, it wasn't.
43067c478bd9Sstevel@tonic-gate */
43077c478bd9Sstevel@tonic-gate ASSERT(sizeof (*verfp) <= sizeof (write3verf));
43087c478bd9Sstevel@tonic-gate #endif
43097c478bd9Sstevel@tonic-gate
43107c478bd9Sstevel@tonic-gate gethrestime(&now);
43117c478bd9Sstevel@tonic-gate verfp = (struct rfs3_verf_overlay *)&write3verf;
43127c478bd9Sstevel@tonic-gate verfp->ts = (int)now.tv_sec;
43135679c89fSjv227347 verfp->id = zone_get_hostid(NULL);
43147c478bd9Sstevel@tonic-gate
43157c478bd9Sstevel@tonic-gate if (verfp->id == 0)
43167c478bd9Sstevel@tonic-gate verfp->id = (uint_t)now.tv_nsec;
43177c478bd9Sstevel@tonic-gate
4318cfae96c2Sjwahlig nfs3_srv_caller_id = fs_new_caller_id();
4319cfae96c2Sjwahlig
43207c478bd9Sstevel@tonic-gate }
43217c478bd9Sstevel@tonic-gate
43220a701b1eSRobert Gordon static int
rdma_setup_read_data3(READ3args * args,READ3resok * rok)43230a701b1eSRobert Gordon rdma_setup_read_data3(READ3args *args, READ3resok *rok)
43240a701b1eSRobert Gordon {
43250a701b1eSRobert Gordon struct clist *wcl;
4326f837ee4aSSiddheshwar Mahesh int wlist_len;
43270a701b1eSRobert Gordon count3 count = rok->count;
43280a701b1eSRobert Gordon
43290a701b1eSRobert Gordon wcl = args->wlist;
4330f837ee4aSSiddheshwar Mahesh if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE) {
43310a701b1eSRobert Gordon return (FALSE);
43320a701b1eSRobert Gordon }
43330a701b1eSRobert Gordon
43340a701b1eSRobert Gordon wcl = args->wlist;
4335f837ee4aSSiddheshwar Mahesh rok->wlist_len = wlist_len;
43360a701b1eSRobert Gordon rok->wlist = wcl;
43370a701b1eSRobert Gordon return (TRUE);
43380a701b1eSRobert Gordon }
43390a701b1eSRobert Gordon
43407c478bd9Sstevel@tonic-gate void
rfs3_srvrfini(void)43417c478bd9Sstevel@tonic-gate rfs3_srvrfini(void)
43427c478bd9Sstevel@tonic-gate {
43437c478bd9Sstevel@tonic-gate /* Nothing to do */
43447c478bd9Sstevel@tonic-gate }
4345