Print this page
NEX-16712 NFS dtrace providers do not support per-share filtering
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankon <yuri.pankov@nexenta.com>
NEX-15279 support NFS server in zone
NEX-15520 online NFS shares cause zoneadm halt to hang in nfs_export_zone_fini
Portions contributed by: Dan Kruchinin dan.kruchinin@nexenta.com
Portions contributed by: Stepan Zastupov stepan.zastupov@gmail.com
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-9275 Got "bad mutex" panic when run IO to nfs share from clients
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-3524 CLONE - Port NEX-3505 "wrong authentication" messages with root=@0.0.0.0/0 set, result in loss of client access
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3533 CLONE - Port NEX-3019 NFSv3 writes underneath mounted filesystem to directory
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-3095 Issues related to NFS nohide
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-1128 NFS server: Generic uid and gid remapping for AUTH_SYS
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
OS-20 share_nfs(1m) charset handling is unreliable
OS-22 Page fault at nfscmd_dropped_entrysize+0x1e()
OS-23 NFSv2/3/4: READDIR responses are inconsistent when charset conversion fails
OS-24 rfs3_readdir(): Issues related to nfscmd_convdirent()
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
closes #12112 rb3823 - nfs-nohide: lookup("..") for submount should be correct
re #3541 rb11254 - nfs nohide - "nfssrv: need ability to go to submounts for v3 and v2 protocols"
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs3_srv.c
+++ new/usr/src/uts/common/fs/nfs/nfs3_srv.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2018 Nexenta Systems, Inc.
24 24 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
25 25 * Copyright (c) 2013 by Delphix. All rights reserved.
26 26 */
27 27
28 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 29 /* All Rights Reserved */
30 30
31 +
31 32 #include <sys/param.h>
32 33 #include <sys/types.h>
33 34 #include <sys/systm.h>
34 35 #include <sys/cred.h>
35 36 #include <sys/buf.h>
36 37 #include <sys/vfs.h>
37 38 #include <sys/vnode.h>
38 39 #include <sys/uio.h>
39 40 #include <sys/errno.h>
40 41 #include <sys/sysmacros.h>
41 42 #include <sys/statvfs.h>
42 43 #include <sys/kmem.h>
43 44 #include <sys/dirent.h>
44 45 #include <sys/cmn_err.h>
45 46 #include <sys/debug.h>
46 47 #include <sys/systeminfo.h>
47 48 #include <sys/flock.h>
48 49 #include <sys/nbmlock.h>
49 50 #include <sys/policy.h>
50 51 #include <sys/sdt.h>
51 52
52 53 #include <rpc/types.h>
53 54 #include <rpc/auth.h>
54 55 #include <rpc/svc.h>
55 56 #include <rpc/rpc_rdma.h>
56 57
57 58 #include <nfs/nfs.h>
58 59 #include <nfs/export.h>
59 60 #include <nfs/nfs_cmd.h>
60 61
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
61 62 #include <sys/strsubr.h>
62 63 #include <sys/tsol/label.h>
63 64 #include <sys/tsol/tndb.h>
64 65
65 66 #include <sys/zone.h>
66 67
67 68 #include <inet/ip.h>
68 69 #include <inet/ip6.h>
69 70
70 71 /*
72 + * Zone global variables of NFSv3 server
73 + */
74 +typedef struct nfs3_srv {
75 + writeverf3 write3verf;
76 +} nfs3_srv_t;
77 +
78 +/*
71 79 * These are the interface routines for the server side of the
72 80 * Network File System. See the NFS version 3 protocol specification
73 81 * for a description of this interface.
74 82 */
75 83
76 -static writeverf3 write3verf;
77 -
78 84 static int sattr3_to_vattr(sattr3 *, struct vattr *);
79 85 static int vattr_to_fattr3(struct vattr *, fattr3 *);
80 86 static int vattr_to_wcc_attr(struct vattr *, wcc_attr *);
81 87 static void vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
82 88 static void vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
83 89 static int rdma_setup_read_data3(READ3args *, READ3resok *);
84 90
85 91 extern int nfs_loaned_buffers;
86 92
87 93 u_longlong_t nfs3_srv_caller_id;
94 +static zone_key_t rfs3_zone_key;
88 95
89 96 /* ARGSUSED */
90 97 void
91 98 rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
92 99 struct svc_req *req, cred_t *cr, bool_t ro)
93 100 {
94 101 int error;
95 102 vnode_t *vp;
96 103 struct vattr va;
97 104
98 105 vp = nfs3_fhtovp(&args->object, exi);
99 106
100 - DTRACE_NFSV3_4(op__getattr__start, struct svc_req *, req,
101 - cred_t *, cr, vnode_t *, vp, GETATTR3args *, args);
107 + DTRACE_NFSV3_5(op__getattr__start, struct svc_req *, req,
108 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
109 + GETATTR3args *, args);
102 110
103 111 if (vp == NULL) {
104 112 error = ESTALE;
105 113 goto out;
106 114 }
107 115
108 116 va.va_mask = AT_ALL;
109 117 error = rfs4_delegated_getattr(vp, &va, 0, cr);
110 118
111 119 if (!error) {
112 120 /* Lie about the object type for a referral */
113 121 if (vn_is_nfs_reparse(vp, cr))
114 122 va.va_type = VLNK;
115 123
116 124 /* overflow error if time or size is out of range */
117 125 error = vattr_to_fattr3(&va, &resp->resok.obj_attributes);
118 126 if (error)
119 127 goto out;
120 128 resp->status = NFS3_OK;
121 129
122 - DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
123 - cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
130 + DTRACE_NFSV3_5(op__getattr__done, struct svc_req *, req,
131 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
132 + GETATTR3res *, resp);
124 133
125 134 VN_RELE(vp);
126 135
127 136 return;
128 137 }
129 138
130 139 out:
131 140 if (curthread->t_flag & T_WOULDBLOCK) {
132 141 curthread->t_flag &= ~T_WOULDBLOCK;
133 142 resp->status = NFS3ERR_JUKEBOX;
134 143 } else
135 144 resp->status = puterrno3(error);
136 145
137 - DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
138 - cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
146 + DTRACE_NFSV3_5(op__getattr__done, struct svc_req *, req,
147 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
148 + GETATTR3res *, resp);
139 149
140 150 if (vp != NULL)
141 151 VN_RELE(vp);
142 152 }
143 153
144 154 void *
145 155 rfs3_getattr_getfh(GETATTR3args *args)
146 156 {
147 -
148 157 return (&args->object);
149 158 }
150 159
151 160 void
152 161 rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
153 162 struct svc_req *req, cred_t *cr, bool_t ro)
154 163 {
155 164 int error;
156 165 vnode_t *vp;
157 166 struct vattr *bvap;
158 167 struct vattr bva;
159 168 struct vattr *avap;
160 169 struct vattr ava;
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
161 170 int flag;
162 171 int in_crit = 0;
163 172 struct flock64 bf;
164 173 caller_context_t ct;
165 174
166 175 bvap = NULL;
167 176 avap = NULL;
168 177
169 178 vp = nfs3_fhtovp(&args->object, exi);
170 179
171 - DTRACE_NFSV3_4(op__setattr__start, struct svc_req *, req,
172 - cred_t *, cr, vnode_t *, vp, SETATTR3args *, args);
180 + DTRACE_NFSV3_5(op__setattr__start, struct svc_req *, req,
181 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
182 + SETATTR3args *, args);
173 183
174 184 if (vp == NULL) {
175 185 error = ESTALE;
176 186 goto out;
177 187 }
178 188
179 189 error = sattr3_to_vattr(&args->new_attributes, &ava);
180 190 if (error)
181 191 goto out;
182 192
183 193 if (is_system_labeled()) {
184 194 bslabel_t *clabel = req->rq_label;
185 195
186 196 ASSERT(clabel != NULL);
187 197 DTRACE_PROBE2(tx__rfs3__log__info__opsetattr__clabel, char *,
188 198 "got client label from request(1)", struct svc_req *, req);
189 199
190 200 if (!blequal(&l_admin_low->tsl_label, clabel)) {
191 201 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
192 202 exi)) {
193 203 resp->status = NFS3ERR_ACCES;
194 204 goto out1;
195 205 }
196 206 }
197 207 }
198 208
199 209 /*
200 210 * We need to specially handle size changes because of
201 211 * possible conflicting NBMAND locks. Get into critical
202 212 * region before VOP_GETATTR, so the size attribute is
203 213 * valid when checking conflicts.
204 214 *
205 215 * Also, check to see if the v4 side of the server has
206 216 * delegated this file. If so, then we return JUKEBOX to
207 217 * allow the client to retrasmit its request.
208 218 */
209 219 if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
210 220 if (nbl_need_check(vp)) {
211 221 nbl_start_crit(vp, RW_READER);
212 222 in_crit = 1;
213 223 }
214 224 }
215 225
216 226 bva.va_mask = AT_ALL;
217 227 error = rfs4_delegated_getattr(vp, &bva, 0, cr);
218 228
219 229 /*
220 230 * If we can't get the attributes, then we can't do the
221 231 * right access checking. So, we'll fail the request.
222 232 */
223 233 if (error)
224 234 goto out;
225 235
226 236 bvap = &bva;
227 237
228 238 if (rdonly(ro, vp)) {
229 239 resp->status = NFS3ERR_ROFS;
230 240 goto out1;
231 241 }
232 242
233 243 if (args->guard.check &&
234 244 (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
235 245 args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
236 246 resp->status = NFS3ERR_NOT_SYNC;
237 247 goto out1;
238 248 }
239 249
240 250 if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
241 251 flag = ATTR_UTIME;
242 252 else
243 253 flag = 0;
244 254
245 255 /*
246 256 * If the filesystem is exported with nosuid, then mask off
247 257 * the setuid and setgid bits.
248 258 */
249 259 if ((ava.va_mask & AT_MODE) && vp->v_type == VREG &&
250 260 (exi->exi_export.ex_flags & EX_NOSUID))
251 261 ava.va_mode &= ~(VSUID | VSGID);
252 262
253 263 ct.cc_sysid = 0;
254 264 ct.cc_pid = 0;
255 265 ct.cc_caller_id = nfs3_srv_caller_id;
256 266 ct.cc_flags = CC_DONTBLOCK;
257 267
258 268 /*
259 269 * We need to specially handle size changes because it is
260 270 * possible for the client to create a file with modes
261 271 * which indicate read-only, but with the file opened for
262 272 * writing. If the client then tries to set the size of
263 273 * the file, then the normal access checking done in
264 274 * VOP_SETATTR would prevent the client from doing so,
265 275 * although it should be legal for it to do so. To get
266 276 * around this, we do the access checking for ourselves
267 277 * and then use VOP_SPACE which doesn't do the access
268 278 * checking which VOP_SETATTR does. VOP_SPACE can only
269 279 * operate on VREG files, let VOP_SETATTR handle the other
270 280 * extremely rare cases.
271 281 * Also the client should not be allowed to change the
272 282 * size of the file if there is a conflicting non-blocking
273 283 * mandatory lock in the region the change.
274 284 */
275 285 if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
276 286 if (in_crit) {
277 287 u_offset_t offset;
278 288 ssize_t length;
279 289
280 290 if (ava.va_size < bva.va_size) {
281 291 offset = ava.va_size;
282 292 length = bva.va_size - ava.va_size;
283 293 } else {
284 294 offset = bva.va_size;
285 295 length = ava.va_size - bva.va_size;
286 296 }
287 297 if (nbl_conflict(vp, NBL_WRITE, offset, length, 0,
288 298 NULL)) {
289 299 error = EACCES;
290 300 goto out;
291 301 }
292 302 }
293 303
294 304 if (crgetuid(cr) == bva.va_uid && ava.va_size != bva.va_size) {
295 305 ava.va_mask &= ~AT_SIZE;
296 306 bf.l_type = F_WRLCK;
297 307 bf.l_whence = 0;
298 308 bf.l_start = (off64_t)ava.va_size;
299 309 bf.l_len = 0;
300 310 bf.l_sysid = 0;
301 311 bf.l_pid = 0;
302 312 error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
303 313 (offset_t)ava.va_size, cr, &ct);
304 314 }
305 315 }
306 316
307 317 if (!error && ava.va_mask)
308 318 error = VOP_SETATTR(vp, &ava, flag, cr, &ct);
309 319
310 320 /* check if a monitor detected a delegation conflict */
311 321 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
312 322 resp->status = NFS3ERR_JUKEBOX;
313 323 goto out1;
314 324 }
315 325
316 326 ava.va_mask = AT_ALL;
317 327 avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
318 328
319 329 /*
320 330 * Force modified metadata out to stable storage.
321 331 */
322 332 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
|
↓ open down ↓ |
140 lines elided |
↑ open up ↑ |
323 333
324 334 if (error)
325 335 goto out;
326 336
327 337 if (in_crit)
328 338 nbl_end_crit(vp);
329 339
330 340 resp->status = NFS3_OK;
331 341 vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
332 342
333 - DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
334 - cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
343 + DTRACE_NFSV3_5(op__setattr__done, struct svc_req *, req,
344 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
345 + SETATTR3res *, resp);
335 346
336 347 VN_RELE(vp);
337 348
338 349 return;
339 350
340 351 out:
341 352 if (curthread->t_flag & T_WOULDBLOCK) {
342 353 curthread->t_flag &= ~T_WOULDBLOCK;
343 354 resp->status = NFS3ERR_JUKEBOX;
344 355 } else
345 356 resp->status = puterrno3(error);
346 357 out1:
347 - DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
348 - cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
358 + DTRACE_NFSV3_5(op__setattr__done, struct svc_req *, req,
359 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
360 + SETATTR3res *, resp);
349 361
350 362 if (vp != NULL) {
351 363 if (in_crit)
352 364 nbl_end_crit(vp);
353 365 VN_RELE(vp);
354 366 }
355 367 vattr_to_wcc_data(bvap, avap, &resp->resfail.obj_wcc);
356 368 }
357 369
358 370 void *
359 371 rfs3_setattr_getfh(SETATTR3args *args)
360 372 {
361 -
362 373 return (&args->object);
363 374 }
364 375
365 376 /* ARGSUSED */
366 377 void
367 378 rfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi,
368 379 struct svc_req *req, cred_t *cr, bool_t ro)
369 380 {
370 381 int error;
371 382 vnode_t *vp;
372 383 vnode_t *dvp;
373 384 struct vattr *vap;
374 385 struct vattr va;
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
375 386 struct vattr *dvap;
376 387 struct vattr dva;
377 388 nfs_fh3 *fhp;
378 389 struct sec_ol sec = {0, 0};
379 390 bool_t publicfh_flag = FALSE, auth_weak = FALSE;
380 391 struct sockaddr *ca;
381 392 char *name = NULL;
382 393
383 394 dvap = NULL;
384 395
396 + if (exi != NULL)
397 + exi_hold(exi);
398 +
385 399 /*
386 400 * Allow lookups from the root - the default
387 401 * location of the public filehandle.
388 402 */
389 403 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
390 - dvp = rootdir;
404 + dvp = ZONE_ROOTVP();
391 405 VN_HOLD(dvp);
392 406
393 - DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
394 - cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
407 + DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
408 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
409 + LOOKUP3args *, args);
395 410 } else {
396 411 dvp = nfs3_fhtovp(&args->what.dir, exi);
397 412
398 - DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
399 - cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
413 + DTRACE_NFSV3_5(op__lookup__start, struct svc_req *, req,
414 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
415 + LOOKUP3args *, args);
400 416
401 417 if (dvp == NULL) {
402 418 error = ESTALE;
403 419 goto out;
404 420 }
405 421 }
406 422
407 423 dva.va_mask = AT_ALL;
408 424 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
409 425
410 426 if (args->what.name == nfs3nametoolong) {
411 427 resp->status = NFS3ERR_NAMETOOLONG;
412 428 goto out1;
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
413 429 }
414 430
415 431 if (args->what.name == NULL || *(args->what.name) == '\0') {
416 432 resp->status = NFS3ERR_ACCES;
417 433 goto out1;
418 434 }
419 435
420 436 fhp = &args->what.dir;
421 437 if (strcmp(args->what.name, "..") == 0 &&
422 438 EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
423 - resp->status = NFS3ERR_NOENT;
424 - goto out1;
439 + if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
440 + (dvp->v_flag & VROOT)) {
441 + /*
442 + * special case for ".." and 'nohide'exported root
443 + */
444 + if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
445 + resp->status = NFS3ERR_ACCES;
446 + goto out1;
447 + }
448 + } else {
449 + resp->status = NFS3ERR_NOENT;
450 + goto out1;
451 + }
425 452 }
426 453
427 454 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
428 455 name = nfscmd_convname(ca, exi, args->what.name,
429 456 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
430 457
431 458 if (name == NULL) {
432 459 resp->status = NFS3ERR_ACCES;
433 460 goto out1;
434 461 }
435 462
436 463 /*
437 464 * If the public filehandle is used then allow
438 465 * a multi-component lookup
439 466 */
440 467 if (PUBLIC_FH3(&args->what.dir)) {
441 468 publicfh_flag = TRUE;
469 +
470 + exi_rele(&exi);
471 +
442 472 error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
443 473 &exi, &sec);
444 - if (error && exi != NULL)
445 - exi_rele(exi); /* See comment below Re: publicfh_flag */
474 +
446 475 /*
447 476 * Since WebNFS may bypass MOUNT, we need to ensure this
448 477 * request didn't come from an unlabeled admin_low client.
449 478 */
450 479 if (is_system_labeled() && error == 0) {
451 480 int addr_type;
452 481 void *ipaddr;
453 482 tsol_tpc_t *tp;
454 483
455 484 if (ca->sa_family == AF_INET) {
456 485 addr_type = IPV4_VERSION;
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
457 486 ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
458 487 } else if (ca->sa_family == AF_INET6) {
459 488 addr_type = IPV6_VERSION;
460 489 ipaddr = &((struct sockaddr_in6 *)
461 490 ca)->sin6_addr;
462 491 }
463 492 tp = find_tpc(ipaddr, addr_type, B_FALSE);
464 493 if (tp == NULL || tp->tpc_tp.tp_doi !=
465 494 l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
466 495 SUN_CIPSO) {
467 - if (exi != NULL)
468 - exi_rele(exi);
469 496 VN_RELE(vp);
470 497 error = EACCES;
471 498 }
472 499 if (tp != NULL)
473 500 TPC_RELE(tp);
474 501 }
475 502 } else {
476 503 error = VOP_LOOKUP(dvp, name, &vp,
477 504 NULL, 0, NULL, cr, NULL, NULL, NULL);
478 505 }
479 506
480 507 if (name != args->what.name)
481 508 kmem_free(name, MAXPATHLEN + 1);
482 509
510 + if (error == 0 && vn_ismntpt(vp)) {
511 + error = rfs_cross_mnt(&vp, &exi);
512 + if (error)
513 + VN_RELE(vp);
514 + }
515 +
483 516 if (is_system_labeled() && error == 0) {
484 517 bslabel_t *clabel = req->rq_label;
485 518
486 519 ASSERT(clabel != NULL);
487 520 DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
488 521 "got client label from request(1)", struct svc_req *, req);
489 522
490 523 if (!blequal(&l_admin_low->tsl_label, clabel)) {
491 524 if (!do_rfs_label_check(clabel, dvp,
492 525 DOMINANCE_CHECK, exi)) {
493 - if (publicfh_flag && exi != NULL)
494 - exi_rele(exi);
495 526 VN_RELE(vp);
496 527 error = EACCES;
497 528 }
498 529 }
499 530 }
500 531
501 532 dva.va_mask = AT_ALL;
502 533 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
503 534
504 535 if (error)
505 536 goto out;
506 537
507 538 if (sec.sec_flags & SEC_QUERY) {
508 539 error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
509 540 } else {
510 541 error = makefh3(&resp->resok.object, vp, exi);
511 542 if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
512 543 auth_weak = TRUE;
513 544 }
514 545
515 - /*
516 - * If publicfh_flag is true then we have called rfs_publicfh_mclookup
517 - * and have obtained a new exportinfo in exi which needs to be
518 - * released. Note that the original exportinfo pointed to by exi
519 - * will be released by the caller, common_dispatch.
520 - */
521 - if (publicfh_flag)
522 - exi_rele(exi);
523 -
524 546 if (error) {
525 547 VN_RELE(vp);
526 548 goto out;
527 549 }
528 550
529 551 va.va_mask = AT_ALL;
530 552 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
531 553
554 + exi_rele(&exi);
532 555 VN_RELE(vp);
533 556
534 557 resp->status = NFS3_OK;
535 558 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
536 559 vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
537 560
538 561 /*
539 562 * If it's public fh, no 0x81, and client's flavor is
540 563 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
541 564 * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
542 565 */
543 566 if (auth_weak)
544 567 resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
545 568
546 - DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
547 - cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
569 + DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
570 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
571 + LOOKUP3res *, resp);
548 572 VN_RELE(dvp);
549 573
550 574 return;
551 575
552 576 out:
553 577 if (curthread->t_flag & T_WOULDBLOCK) {
554 578 curthread->t_flag &= ~T_WOULDBLOCK;
555 579 resp->status = NFS3ERR_JUKEBOX;
556 580 } else
557 581 resp->status = puterrno3(error);
558 582 out1:
559 - DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
560 - cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
583 + if (exi != NULL)
584 + exi_rele(&exi);
561 585
586 + DTRACE_NFSV3_5(op__lookup__done, struct svc_req *, req,
587 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
588 + LOOKUP3res *, resp);
589 +
562 590 if (dvp != NULL)
563 591 VN_RELE(dvp);
564 592 vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);
565 593
566 594 }
567 595
568 596 void *
569 597 rfs3_lookup_getfh(LOOKUP3args *args)
570 598 {
571 -
572 599 return (&args->what.dir);
573 600 }
574 601
575 -/* ARGSUSED */
576 602 void
577 603 rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi,
578 604 struct svc_req *req, cred_t *cr, bool_t ro)
579 605 {
580 606 int error;
581 607 vnode_t *vp;
582 608 struct vattr *vap;
583 609 struct vattr va;
584 610 int checkwriteperm;
585 611 boolean_t dominant_label = B_FALSE;
586 612 boolean_t equal_label = B_FALSE;
587 613 boolean_t admin_low_client;
588 614
589 615 vap = NULL;
590 616
591 617 vp = nfs3_fhtovp(&args->object, exi);
592 618
593 - DTRACE_NFSV3_4(op__access__start, struct svc_req *, req,
594 - cred_t *, cr, vnode_t *, vp, ACCESS3args *, args);
619 + DTRACE_NFSV3_5(op__access__start, struct svc_req *, req,
620 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
621 + ACCESS3args *, args);
595 622
596 623 if (vp == NULL) {
597 624 error = ESTALE;
598 625 goto out;
599 626 }
600 627
601 628 /*
602 629 * If the file system is exported read only, it is not appropriate
603 630 * to check write permissions for regular files and directories.
604 631 * Special files are interpreted by the client, so the underlying
605 632 * permissions are sent back to the client for interpretation.
606 633 */
607 634 if (rdonly(ro, vp) && (vp->v_type == VREG || vp->v_type == VDIR))
608 635 checkwriteperm = 0;
609 636 else
610 637 checkwriteperm = 1;
611 638
612 639 /*
613 640 * We need the mode so that we can correctly determine access
614 641 * permissions relative to a mandatory lock file. Access to
615 642 * mandatory lock files is denied on the server, so it might
616 643 * as well be reflected to the server during the open.
617 644 */
618 645 va.va_mask = AT_MODE;
619 646 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
620 647 if (error)
621 648 goto out;
622 649
623 650 vap = &va;
624 651
625 652 resp->resok.access = 0;
626 653
627 654 if (is_system_labeled()) {
628 655 bslabel_t *clabel = req->rq_label;
629 656
630 657 ASSERT(clabel != NULL);
631 658 DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *,
632 659 "got client label from request(1)", struct svc_req *, req);
633 660
634 661 if (!blequal(&l_admin_low->tsl_label, clabel)) {
635 662 if ((equal_label = do_rfs_label_check(clabel, vp,
636 663 EQUALITY_CHECK, exi)) == B_FALSE) {
637 664 dominant_label = do_rfs_label_check(clabel,
638 665 vp, DOMINANCE_CHECK, exi);
639 666 } else
640 667 dominant_label = B_TRUE;
641 668 admin_low_client = B_FALSE;
642 669 } else
643 670 admin_low_client = B_TRUE;
644 671 }
645 672
646 673 if (args->access & ACCESS3_READ) {
647 674 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
648 675 if (error) {
649 676 if (curthread->t_flag & T_WOULDBLOCK)
650 677 goto out;
651 678 } else if (!MANDLOCK(vp, va.va_mode) &&
652 679 (!is_system_labeled() || admin_low_client ||
653 680 dominant_label))
654 681 resp->resok.access |= ACCESS3_READ;
655 682 }
656 683 if ((args->access & ACCESS3_LOOKUP) && vp->v_type == VDIR) {
657 684 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
658 685 if (error) {
659 686 if (curthread->t_flag & T_WOULDBLOCK)
660 687 goto out;
661 688 } else if (!is_system_labeled() || admin_low_client ||
662 689 dominant_label)
663 690 resp->resok.access |= ACCESS3_LOOKUP;
664 691 }
665 692 if (checkwriteperm &&
666 693 (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND))) {
667 694 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
668 695 if (error) {
669 696 if (curthread->t_flag & T_WOULDBLOCK)
670 697 goto out;
671 698 } else if (!MANDLOCK(vp, va.va_mode) &&
672 699 (!is_system_labeled() || admin_low_client || equal_label)) {
673 700 resp->resok.access |=
674 701 (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND));
675 702 }
676 703 }
677 704 if (checkwriteperm &&
678 705 (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) {
679 706 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
680 707 if (error) {
681 708 if (curthread->t_flag & T_WOULDBLOCK)
682 709 goto out;
683 710 } else if (!is_system_labeled() || admin_low_client ||
684 711 equal_label)
685 712 resp->resok.access |= ACCESS3_DELETE;
686 713 }
687 714 if (args->access & ACCESS3_EXECUTE) {
688 715 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
689 716 if (error) {
690 717 if (curthread->t_flag & T_WOULDBLOCK)
691 718 goto out;
692 719 } else if (!MANDLOCK(vp, va.va_mode) &&
693 720 (!is_system_labeled() || admin_low_client ||
|
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
694 721 dominant_label))
695 722 resp->resok.access |= ACCESS3_EXECUTE;
696 723 }
697 724
698 725 va.va_mask = AT_ALL;
699 726 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
700 727
701 728 resp->status = NFS3_OK;
702 729 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
703 730
704 - DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
705 - cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
731 + DTRACE_NFSV3_5(op__access__done, struct svc_req *, req,
732 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
733 + ACCESS3res *, resp);
706 734
707 735 VN_RELE(vp);
708 736
709 737 return;
710 738
711 739 out:
712 740 if (curthread->t_flag & T_WOULDBLOCK) {
713 741 curthread->t_flag &= ~T_WOULDBLOCK;
714 742 resp->status = NFS3ERR_JUKEBOX;
715 743 } else
716 744 resp->status = puterrno3(error);
717 - DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
718 - cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
745 + DTRACE_NFSV3_5(op__access__done, struct svc_req *, req,
746 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
747 + ACCESS3res *, resp);
719 748 if (vp != NULL)
720 749 VN_RELE(vp);
721 750 vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
722 751 }
723 752
724 753 void *
725 754 rfs3_access_getfh(ACCESS3args *args)
726 755 {
727 -
728 756 return (&args->object);
729 757 }
730 758
731 759 /* ARGSUSED */
732 760 void
733 761 rfs3_readlink(READLINK3args *args, READLINK3res *resp, struct exportinfo *exi,
734 762 struct svc_req *req, cred_t *cr, bool_t ro)
735 763 {
736 764 int error;
737 765 vnode_t *vp;
738 766 struct vattr *vap;
739 767 struct vattr va;
740 768 struct iovec iov;
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
741 769 struct uio uio;
742 770 char *data;
743 771 struct sockaddr *ca;
744 772 char *name = NULL;
745 773 int is_referral = 0;
746 774
747 775 vap = NULL;
748 776
749 777 vp = nfs3_fhtovp(&args->symlink, exi);
750 778
751 - DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req,
752 - cred_t *, cr, vnode_t *, vp, READLINK3args *, args);
779 + DTRACE_NFSV3_5(op__readlink__start, struct svc_req *, req,
780 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
781 + READLINK3args *, args);
753 782
754 783 if (vp == NULL) {
755 784 error = ESTALE;
756 785 goto out;
757 786 }
758 787
759 788 va.va_mask = AT_ALL;
760 789 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
761 790 if (error)
762 791 goto out;
763 792
764 793 vap = &va;
765 794
766 795 /* We lied about the object type for a referral */
767 796 if (vn_is_nfs_reparse(vp, cr))
768 797 is_referral = 1;
769 798
770 799 if (vp->v_type != VLNK && !is_referral) {
771 800 resp->status = NFS3ERR_INVAL;
772 801 goto out1;
773 802 }
774 803
775 804 if (MANDLOCK(vp, va.va_mode)) {
776 805 resp->status = NFS3ERR_ACCES;
777 806 goto out1;
778 807 }
779 808
780 809 if (is_system_labeled()) {
781 810 bslabel_t *clabel = req->rq_label;
782 811
783 812 ASSERT(clabel != NULL);
784 813 DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *,
785 814 "got client label from request(1)", struct svc_req *, req);
786 815
787 816 if (!blequal(&l_admin_low->tsl_label, clabel)) {
788 817 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
789 818 exi)) {
790 819 resp->status = NFS3ERR_ACCES;
791 820 goto out1;
792 821 }
793 822 }
794 823 }
795 824
796 825 data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
797 826
798 827 if (is_referral) {
799 828 char *s;
800 829 size_t strsz;
801 830
802 831 /* Get an artificial symlink based on a referral */
803 832 s = build_symlink(vp, cr, &strsz);
804 833 global_svstat_ptr[3][NFS_REFERLINKS].value.ui64++;
805 834 DTRACE_PROBE2(nfs3serv__func__referral__reflink,
806 835 vnode_t *, vp, char *, s);
807 836 if (s == NULL)
808 837 error = EINVAL;
809 838 else {
810 839 error = 0;
811 840 (void) strlcpy(data, s, MAXPATHLEN + 1);
812 841 kmem_free(s, strsz);
813 842 }
814 843
815 844 } else {
816 845
817 846 iov.iov_base = data;
818 847 iov.iov_len = MAXPATHLEN;
819 848 uio.uio_iov = &iov;
820 849 uio.uio_iovcnt = 1;
821 850 uio.uio_segflg = UIO_SYSSPACE;
822 851 uio.uio_extflg = UIO_COPY_CACHED;
823 852 uio.uio_loffset = 0;
824 853 uio.uio_resid = MAXPATHLEN;
825 854
826 855 error = VOP_READLINK(vp, &uio, cr, NULL);
827 856
828 857 if (!error)
829 858 *(data + MAXPATHLEN - uio.uio_resid) = '\0';
830 859 }
831 860
832 861 va.va_mask = AT_ALL;
833 862 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
834 863
835 864 /* Lie about object type again just to be consistent */
836 865 if (is_referral && vap != NULL)
837 866 vap->va_type = VLNK;
838 867
839 868 #if 0 /* notyet */
840 869 /*
841 870 * Don't do this. It causes local disk writes when just
842 871 * reading the file and the overhead is deemed larger
843 872 * than the benefit.
844 873 */
845 874 /*
846 875 * Force modified metadata out to stable storage.
847 876 */
848 877 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
849 878 #endif
850 879
851 880 if (error) {
852 881 kmem_free(data, MAXPATHLEN + 1);
853 882 goto out;
854 883 }
855 884
856 885 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
857 886 name = nfscmd_convname(ca, exi, data, NFSCMD_CONV_OUTBOUND,
858 887 MAXPATHLEN + 1);
859 888
860 889 if (name == NULL) {
861 890 /*
|
↓ open down ↓ |
99 lines elided |
↑ open up ↑ |
862 891 * Even though the conversion failed, we return
863 892 * something. We just don't translate it.
864 893 */
865 894 name = data;
866 895 }
867 896
868 897 resp->status = NFS3_OK;
869 898 vattr_to_post_op_attr(vap, &resp->resok.symlink_attributes);
870 899 resp->resok.data = name;
871 900
872 - DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
873 - cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
901 + DTRACE_NFSV3_5(op__readlink__done, struct svc_req *, req,
902 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
903 + READLINK3res *, resp);
874 904 VN_RELE(vp);
875 905
876 906 if (name != data)
877 907 kmem_free(data, MAXPATHLEN + 1);
878 908
879 909 return;
880 910
881 911 out:
882 912 if (curthread->t_flag & T_WOULDBLOCK) {
883 913 curthread->t_flag &= ~T_WOULDBLOCK;
884 914 resp->status = NFS3ERR_JUKEBOX;
885 915 } else
886 916 resp->status = puterrno3(error);
887 917 out1:
888 - DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
889 - cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
918 + DTRACE_NFSV3_5(op__readlink__done, struct svc_req *, req,
919 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
920 + READLINK3res *, resp);
890 921 if (vp != NULL)
891 922 VN_RELE(vp);
892 923 vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes);
893 924 }
894 925
895 926 void *
896 927 rfs3_readlink_getfh(READLINK3args *args)
897 928 {
898 -
899 929 return (&args->symlink);
900 930 }
901 931
902 932 void
903 933 rfs3_readlink_free(READLINK3res *resp)
904 934 {
905 -
906 935 if (resp->status == NFS3_OK)
907 936 kmem_free(resp->resok.data, MAXPATHLEN + 1);
908 937 }
909 938
910 939 /*
911 940 * Server routine to handle read
912 941 * May handle RDMA data as well as mblks
913 942 */
914 943 /* ARGSUSED */
915 944 void
916 945 rfs3_read(READ3args *args, READ3res *resp, struct exportinfo *exi,
917 946 struct svc_req *req, cred_t *cr, bool_t ro)
918 947 {
919 948 int error;
920 949 vnode_t *vp;
921 950 struct vattr *vap;
922 951 struct vattr va;
923 952 struct iovec iov, *iovp = NULL;
924 953 int iovcnt;
925 954 struct uio uio;
926 955 u_offset_t offset;
927 956 mblk_t *mp = NULL;
928 957 int in_crit = 0;
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
929 958 int need_rwunlock = 0;
930 959 caller_context_t ct;
931 960 int rdma_used = 0;
932 961 int loaned_buffers;
933 962 struct uio *uiop;
934 963
935 964 vap = NULL;
936 965
937 966 vp = nfs3_fhtovp(&args->file, exi);
938 967
939 - DTRACE_NFSV3_4(op__read__start, struct svc_req *, req,
940 - cred_t *, cr, vnode_t *, vp, READ3args *, args);
968 + DTRACE_NFSV3_5(op__read__start, struct svc_req *, req,
969 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
970 + READ3args *, args);
941 971
972 +
942 973 if (vp == NULL) {
943 974 error = ESTALE;
944 975 goto out;
945 976 }
946 977
947 978 if (args->wlist) {
948 979 if (args->count > clist_len(args->wlist)) {
949 980 error = EINVAL;
950 981 goto out;
951 982 }
952 983 rdma_used = 1;
953 984 }
954 985
955 986 /* use loaned buffers for TCP */
956 987 loaned_buffers = (nfs_loaned_buffers && !rdma_used) ? 1 : 0;
957 988
958 989 if (is_system_labeled()) {
959 990 bslabel_t *clabel = req->rq_label;
960 991
961 992 ASSERT(clabel != NULL);
962 993 DTRACE_PROBE2(tx__rfs3__log__info__opread__clabel, char *,
963 994 "got client label from request(1)", struct svc_req *, req);
964 995
965 996 if (!blequal(&l_admin_low->tsl_label, clabel)) {
966 997 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
967 998 exi)) {
968 999 resp->status = NFS3ERR_ACCES;
969 1000 goto out1;
970 1001 }
971 1002 }
972 1003 }
973 1004
974 1005 ct.cc_sysid = 0;
975 1006 ct.cc_pid = 0;
976 1007 ct.cc_caller_id = nfs3_srv_caller_id;
977 1008 ct.cc_flags = CC_DONTBLOCK;
978 1009
979 1010 /*
980 1011 * Enter the critical region before calling VOP_RWLOCK
981 1012 * to avoid a deadlock with write requests.
982 1013 */
983 1014 if (nbl_need_check(vp)) {
984 1015 nbl_start_crit(vp, RW_READER);
985 1016 in_crit = 1;
986 1017 if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
987 1018 NULL)) {
988 1019 error = EACCES;
989 1020 goto out;
990 1021 }
991 1022 }
992 1023
993 1024 error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct);
994 1025
995 1026 /* check if a monitor detected a delegation conflict */
996 1027 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
997 1028 resp->status = NFS3ERR_JUKEBOX;
998 1029 goto out1;
999 1030 }
1000 1031
1001 1032 need_rwunlock = 1;
1002 1033
1003 1034 va.va_mask = AT_ALL;
1004 1035 error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1005 1036
1006 1037 /*
1007 1038 * If we can't get the attributes, then we can't do the
1008 1039 * right access checking. So, we'll fail the request.
1009 1040 */
1010 1041 if (error)
1011 1042 goto out;
1012 1043
1013 1044 vap = &va;
1014 1045
1015 1046 if (vp->v_type != VREG) {
1016 1047 resp->status = NFS3ERR_INVAL;
1017 1048 goto out1;
1018 1049 }
1019 1050
1020 1051 if (crgetuid(cr) != va.va_uid) {
1021 1052 error = VOP_ACCESS(vp, VREAD, 0, cr, &ct);
1022 1053 if (error) {
1023 1054 if (curthread->t_flag & T_WOULDBLOCK)
1024 1055 goto out;
1025 1056 error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct);
1026 1057 if (error)
1027 1058 goto out;
1028 1059 }
1029 1060 }
1030 1061
1031 1062 if (MANDLOCK(vp, va.va_mode)) {
1032 1063 resp->status = NFS3ERR_ACCES;
1033 1064 goto out1;
1034 1065 }
1035 1066
1036 1067 offset = args->offset;
1037 1068 if (offset >= va.va_size) {
1038 1069 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1039 1070 if (in_crit)
1040 1071 nbl_end_crit(vp);
1041 1072 resp->status = NFS3_OK;
1042 1073 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1043 1074 resp->resok.count = 0;
1044 1075 resp->resok.eof = TRUE;
1045 1076 resp->resok.data.data_len = 0;
1046 1077 resp->resok.data.data_val = NULL;
1047 1078 resp->resok.data.mp = NULL;
1048 1079 /* RDMA */
1049 1080 resp->resok.wlist = args->wlist;
1050 1081 resp->resok.wlist_len = resp->resok.count;
1051 1082 if (resp->resok.wlist)
1052 1083 clist_zero_len(resp->resok.wlist);
1053 1084 goto done;
1054 1085 }
1055 1086
1056 1087 if (args->count == 0) {
1057 1088 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1058 1089 if (in_crit)
1059 1090 nbl_end_crit(vp);
1060 1091 resp->status = NFS3_OK;
1061 1092 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1062 1093 resp->resok.count = 0;
1063 1094 resp->resok.eof = FALSE;
1064 1095 resp->resok.data.data_len = 0;
1065 1096 resp->resok.data.data_val = NULL;
1066 1097 resp->resok.data.mp = NULL;
1067 1098 /* RDMA */
1068 1099 resp->resok.wlist = args->wlist;
1069 1100 resp->resok.wlist_len = resp->resok.count;
1070 1101 if (resp->resok.wlist)
1071 1102 clist_zero_len(resp->resok.wlist);
1072 1103 goto done;
1073 1104 }
1074 1105
1075 1106 /*
1076 1107 * do not allocate memory more the max. allowed
1077 1108 * transfer size
1078 1109 */
1079 1110 if (args->count > rfs3_tsize(req))
1080 1111 args->count = rfs3_tsize(req);
1081 1112
1082 1113 if (loaned_buffers) {
1083 1114 uiop = (uio_t *)rfs_setup_xuio(vp);
1084 1115 ASSERT(uiop != NULL);
1085 1116 uiop->uio_segflg = UIO_SYSSPACE;
1086 1117 uiop->uio_loffset = args->offset;
1087 1118 uiop->uio_resid = args->count;
1088 1119
1089 1120 /* Jump to do the read if successful */
1090 1121 if (VOP_REQZCBUF(vp, UIO_READ, (xuio_t *)uiop, cr, &ct) == 0) {
1091 1122 /*
1092 1123 * Need to hold the vnode until after VOP_RETZCBUF()
1093 1124 * is called.
1094 1125 */
1095 1126 VN_HOLD(vp);
1096 1127 goto doio_read;
1097 1128 }
1098 1129
1099 1130 DTRACE_PROBE2(nfss__i__reqzcbuf_failed, int,
1100 1131 uiop->uio_loffset, int, uiop->uio_resid);
1101 1132
1102 1133 uiop->uio_extflg = 0;
1103 1134 /* failure to setup for zero copy */
1104 1135 rfs_free_xuio((void *)uiop);
1105 1136 loaned_buffers = 0;
1106 1137 }
1107 1138
1108 1139 /*
1109 1140 * If returning data via RDMA Write, then grab the chunk list.
1110 1141 * If we aren't returning READ data w/RDMA_WRITE, then grab
1111 1142 * a mblk.
1112 1143 */
1113 1144 if (rdma_used) {
1114 1145 (void) rdma_get_wchunk(req, &iov, args->wlist);
1115 1146 uio.uio_iov = &iov;
1116 1147 uio.uio_iovcnt = 1;
1117 1148 } else {
1118 1149 /*
1119 1150 * mp will contain the data to be sent out in the read reply.
1120 1151 * For UDP, this will be freed after the reply has been sent
1121 1152 * out by the driver. For TCP, it will be freed after the last
1122 1153 * segment associated with the reply has been ACKed by the
1123 1154 * client.
1124 1155 */
1125 1156 mp = rfs_read_alloc(args->count, &iovp, &iovcnt);
1126 1157 uio.uio_iov = iovp;
1127 1158 uio.uio_iovcnt = iovcnt;
1128 1159 }
1129 1160
1130 1161 uio.uio_segflg = UIO_SYSSPACE;
1131 1162 uio.uio_extflg = UIO_COPY_CACHED;
1132 1163 uio.uio_loffset = args->offset;
1133 1164 uio.uio_resid = args->count;
1134 1165 uiop = &uio;
1135 1166
1136 1167 doio_read:
1137 1168 error = VOP_READ(vp, uiop, 0, cr, &ct);
1138 1169
1139 1170 if (error) {
1140 1171 if (mp)
1141 1172 freemsg(mp);
1142 1173 /* check if a monitor detected a delegation conflict */
1143 1174 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1144 1175 resp->status = NFS3ERR_JUKEBOX;
1145 1176 goto out1;
1146 1177 }
1147 1178 goto out;
1148 1179 }
1149 1180
1150 1181 /* make mblk using zc buffers */
1151 1182 if (loaned_buffers) {
1152 1183 mp = uio_to_mblk(uiop);
1153 1184 ASSERT(mp != NULL);
1154 1185 }
1155 1186
1156 1187 va.va_mask = AT_ALL;
1157 1188 error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1158 1189
1159 1190 if (error)
1160 1191 vap = NULL;
1161 1192 else
1162 1193 vap = &va;
1163 1194
1164 1195 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1165 1196
1166 1197 if (in_crit)
1167 1198 nbl_end_crit(vp);
1168 1199
1169 1200 resp->status = NFS3_OK;
1170 1201 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1171 1202 resp->resok.count = args->count - uiop->uio_resid;
1172 1203 if (!error && offset + resp->resok.count == va.va_size)
1173 1204 resp->resok.eof = TRUE;
1174 1205 else
1175 1206 resp->resok.eof = FALSE;
1176 1207 resp->resok.data.data_len = resp->resok.count;
1177 1208
1178 1209 if (mp)
1179 1210 rfs_rndup_mblks(mp, resp->resok.count, loaned_buffers);
1180 1211
1181 1212 resp->resok.data.mp = mp;
1182 1213 resp->resok.size = (uint_t)args->count;
1183 1214
1184 1215 if (rdma_used) {
|
↓ open down ↓ |
233 lines elided |
↑ open up ↑ |
1185 1216 resp->resok.data.data_val = (caddr_t)iov.iov_base;
1186 1217 if (!rdma_setup_read_data3(args, &(resp->resok))) {
1187 1218 resp->status = NFS3ERR_INVAL;
1188 1219 }
1189 1220 } else {
1190 1221 resp->resok.data.data_val = (caddr_t)mp->b_datap->db_base;
1191 1222 (resp->resok).wlist = NULL;
1192 1223 }
1193 1224
1194 1225 done:
1195 - DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
1196 - cred_t *, cr, vnode_t *, vp, READ3res *, resp);
1226 + DTRACE_NFSV3_5(op__read__done, struct svc_req *, req,
1227 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1228 + READ3res *, resp);
1197 1229
1198 1230 VN_RELE(vp);
1199 1231
1200 1232 if (iovp != NULL)
1201 1233 kmem_free(iovp, iovcnt * sizeof (struct iovec));
1202 1234
1203 1235 return;
1204 1236
1205 1237 out:
1206 1238 if (curthread->t_flag & T_WOULDBLOCK) {
1207 1239 curthread->t_flag &= ~T_WOULDBLOCK;
1208 1240 resp->status = NFS3ERR_JUKEBOX;
1209 1241 } else
1210 1242 resp->status = puterrno3(error);
1211 1243 out1:
1212 - DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
1213 - cred_t *, cr, vnode_t *, vp, READ3res *, resp);
1244 + DTRACE_NFSV3_5(op__read__done, struct svc_req *, req,
1245 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1246 + READ3res *, resp);
1214 1247
1215 1248 if (vp != NULL) {
1216 1249 if (need_rwunlock)
1217 1250 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1218 1251 if (in_crit)
1219 1252 nbl_end_crit(vp);
1220 1253 VN_RELE(vp);
1221 1254 }
1222 1255 vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
1223 1256
1224 1257 if (iovp != NULL)
1225 1258 kmem_free(iovp, iovcnt * sizeof (struct iovec));
1226 1259 }
1227 1260
1228 1261 void
1229 1262 rfs3_read_free(READ3res *resp)
1230 1263 {
1231 1264 mblk_t *mp;
1232 1265
|
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
1233 1266 if (resp->status == NFS3_OK) {
1234 1267 mp = resp->resok.data.mp;
1235 1268 if (mp != NULL)
1236 1269 freemsg(mp);
1237 1270 }
1238 1271 }
1239 1272
1240 1273 void *
1241 1274 rfs3_read_getfh(READ3args *args)
1242 1275 {
1243 -
1244 1276 return (&args->file);
1245 1277 }
1246 1278
1247 1279 #define MAX_IOVECS 12
1248 1280
1249 1281 #ifdef DEBUG
1250 1282 static int rfs3_write_hits = 0;
1251 1283 static int rfs3_write_misses = 0;
1252 1284 #endif
1253 1285
1254 1286 void
1255 1287 rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi,
1256 1288 struct svc_req *req, cred_t *cr, bool_t ro)
1257 1289 {
1290 + nfs3_srv_t *ns;
1258 1291 int error;
1259 1292 vnode_t *vp;
1260 1293 struct vattr *bvap = NULL;
1261 1294 struct vattr bva;
1262 1295 struct vattr *avap = NULL;
1263 1296 struct vattr ava;
1264 1297 u_offset_t rlimit;
1265 1298 struct uio uio;
1266 1299 struct iovec iov[MAX_IOVECS];
1267 1300 mblk_t *m;
1268 1301 struct iovec *iovp;
1269 1302 int iovcnt;
1270 1303 int ioflag;
1271 1304 cred_t *savecred;
1272 1305 int in_crit = 0;
1273 1306 int rwlock_ret = -1;
1274 1307 caller_context_t ct;
1275 1308
1276 1309 vp = nfs3_fhtovp(&args->file, exi);
1277 1310
1278 - DTRACE_NFSV3_4(op__write__start, struct svc_req *, req,
1279 - cred_t *, cr, vnode_t *, vp, WRITE3args *, args);
1311 + DTRACE_NFSV3_5(op__write__start, struct svc_req *, req,
1312 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1313 + WRITE3args *, args);
1280 1314
1281 1315 if (vp == NULL) {
1282 1316 error = ESTALE;
1283 1317 goto err;
1284 1318 }
1285 1319
1320 + ns = zone_getspecific(rfs3_zone_key, curzone);
1286 1321 if (is_system_labeled()) {
1287 1322 bslabel_t *clabel = req->rq_label;
1288 1323
1289 1324 ASSERT(clabel != NULL);
1290 1325 DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
1291 1326 "got client label from request(1)", struct svc_req *, req);
1292 1327
1293 1328 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1294 1329 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1295 1330 exi)) {
1296 1331 resp->status = NFS3ERR_ACCES;
1297 1332 goto err1;
1298 1333 }
1299 1334 }
1300 1335 }
1301 1336
1302 1337 ct.cc_sysid = 0;
1303 1338 ct.cc_pid = 0;
1304 1339 ct.cc_caller_id = nfs3_srv_caller_id;
1305 1340 ct.cc_flags = CC_DONTBLOCK;
1306 1341
1307 1342 /*
1308 1343 * We have to enter the critical region before calling VOP_RWLOCK
1309 1344 * to avoid a deadlock with ufs.
1310 1345 */
1311 1346 if (nbl_need_check(vp)) {
1312 1347 nbl_start_crit(vp, RW_READER);
1313 1348 in_crit = 1;
1314 1349 if (nbl_conflict(vp, NBL_WRITE, args->offset, args->count, 0,
1315 1350 NULL)) {
1316 1351 error = EACCES;
1317 1352 goto err;
1318 1353 }
1319 1354 }
1320 1355
1321 1356 rwlock_ret = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct);
1322 1357
1323 1358 /* check if a monitor detected a delegation conflict */
1324 1359 if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1325 1360 resp->status = NFS3ERR_JUKEBOX;
1326 1361 rwlock_ret = -1;
1327 1362 goto err1;
1328 1363 }
1329 1364
1330 1365
1331 1366 bva.va_mask = AT_ALL;
1332 1367 error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
1333 1368
1334 1369 /*
1335 1370 * If we can't get the attributes, then we can't do the
1336 1371 * right access checking. So, we'll fail the request.
1337 1372 */
1338 1373 if (error)
1339 1374 goto err;
1340 1375
1341 1376 bvap = &bva;
1342 1377 avap = bvap;
1343 1378
1344 1379 if (args->count != args->data.data_len) {
1345 1380 resp->status = NFS3ERR_INVAL;
1346 1381 goto err1;
1347 1382 }
1348 1383
1349 1384 if (rdonly(ro, vp)) {
1350 1385 resp->status = NFS3ERR_ROFS;
1351 1386 goto err1;
1352 1387 }
1353 1388
1354 1389 if (vp->v_type != VREG) {
1355 1390 resp->status = NFS3ERR_INVAL;
1356 1391 goto err1;
1357 1392 }
1358 1393
1359 1394 if (crgetuid(cr) != bva.va_uid &&
1360 1395 (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
1361 1396 goto err;
1362 1397
|
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
1363 1398 if (MANDLOCK(vp, bva.va_mode)) {
1364 1399 resp->status = NFS3ERR_ACCES;
1365 1400 goto err1;
1366 1401 }
1367 1402
1368 1403 if (args->count == 0) {
1369 1404 resp->status = NFS3_OK;
1370 1405 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
1371 1406 resp->resok.count = 0;
1372 1407 resp->resok.committed = args->stable;
1373 - resp->resok.verf = write3verf;
1408 + resp->resok.verf = ns->write3verf;
1374 1409 goto out;
1375 1410 }
1376 1411
1377 1412 if (args->mblk != NULL) {
1378 1413 iovcnt = 0;
1379 1414 for (m = args->mblk; m != NULL; m = m->b_cont)
1380 1415 iovcnt++;
1381 1416 if (iovcnt <= MAX_IOVECS) {
1382 1417 #ifdef DEBUG
1383 1418 rfs3_write_hits++;
1384 1419 #endif
1385 1420 iovp = iov;
1386 1421 } else {
1387 1422 #ifdef DEBUG
1388 1423 rfs3_write_misses++;
1389 1424 #endif
1390 1425 iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP);
1391 1426 }
1392 1427 mblk_to_iov(args->mblk, iovcnt, iovp);
1393 1428
1394 1429 } else if (args->rlist != NULL) {
1395 1430 iovcnt = 1;
1396 1431 iovp = iov;
1397 1432 iovp->iov_base = (char *)((args->rlist)->u.c_daddr3);
1398 1433 iovp->iov_len = args->count;
1399 1434 } else {
1400 1435 iovcnt = 1;
1401 1436 iovp = iov;
1402 1437 iovp->iov_base = args->data.data_val;
1403 1438 iovp->iov_len = args->count;
1404 1439 }
1405 1440
1406 1441 uio.uio_iov = iovp;
1407 1442 uio.uio_iovcnt = iovcnt;
1408 1443
1409 1444 uio.uio_segflg = UIO_SYSSPACE;
1410 1445 uio.uio_extflg = UIO_COPY_DEFAULT;
1411 1446 uio.uio_loffset = args->offset;
1412 1447 uio.uio_resid = args->count;
1413 1448 uio.uio_llimit = curproc->p_fsz_ctl;
1414 1449 rlimit = uio.uio_llimit - args->offset;
1415 1450 if (rlimit < (u_offset_t)uio.uio_resid)
1416 1451 uio.uio_resid = (int)rlimit;
1417 1452
1418 1453 if (args->stable == UNSTABLE)
1419 1454 ioflag = 0;
1420 1455 else if (args->stable == FILE_SYNC)
1421 1456 ioflag = FSYNC;
1422 1457 else if (args->stable == DATA_SYNC)
1423 1458 ioflag = FDSYNC;
1424 1459 else {
1425 1460 if (iovp != iov)
1426 1461 kmem_free(iovp, sizeof (*iovp) * iovcnt);
1427 1462 resp->status = NFS3ERR_INVAL;
1428 1463 goto err1;
1429 1464 }
1430 1465
1431 1466 /*
1432 1467 * We're changing creds because VM may fault and we need
1433 1468 * the cred of the current thread to be used if quota
1434 1469 * checking is enabled.
1435 1470 */
1436 1471 savecred = curthread->t_cred;
1437 1472 curthread->t_cred = cr;
1438 1473 error = VOP_WRITE(vp, &uio, ioflag, cr, &ct);
1439 1474 curthread->t_cred = savecred;
1440 1475
1441 1476 if (iovp != iov)
1442 1477 kmem_free(iovp, sizeof (*iovp) * iovcnt);
1443 1478
1444 1479 /* check if a monitor detected a delegation conflict */
1445 1480 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1446 1481 resp->status = NFS3ERR_JUKEBOX;
1447 1482 goto err1;
1448 1483 }
1449 1484
1450 1485 ava.va_mask = AT_ALL;
1451 1486 avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava;
1452 1487
1453 1488 if (error)
1454 1489 goto err;
1455 1490
1456 1491 /*
1457 1492 * If we were unable to get the V_WRITELOCK_TRUE, then we
1458 1493 * may not have accurate after attrs, so check if
1459 1494 * we have both attributes, they have a non-zero va_seq, and
1460 1495 * va_seq has changed by exactly one,
1461 1496 * if not, turn off the before attr.
1462 1497 */
1463 1498 if (rwlock_ret != V_WRITELOCK_TRUE) {
1464 1499 if (bvap == NULL || avap == NULL ||
|
↓ open down ↓ |
81 lines elided |
↑ open up ↑ |
1465 1500 bvap->va_seq == 0 || avap->va_seq == 0 ||
1466 1501 avap->va_seq != (bvap->va_seq + 1)) {
1467 1502 bvap = NULL;
1468 1503 }
1469 1504 }
1470 1505
1471 1506 resp->status = NFS3_OK;
1472 1507 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
1473 1508 resp->resok.count = args->count - uio.uio_resid;
1474 1509 resp->resok.committed = args->stable;
1475 - resp->resok.verf = write3verf;
1510 + resp->resok.verf = ns->write3verf;
1476 1511 goto out;
1477 1512
1478 1513 err:
1479 1514 if (curthread->t_flag & T_WOULDBLOCK) {
1480 1515 curthread->t_flag &= ~T_WOULDBLOCK;
1481 1516 resp->status = NFS3ERR_JUKEBOX;
1482 1517 } else
1483 1518 resp->status = puterrno3(error);
1484 1519 err1:
1485 1520 vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
1486 1521 out:
1487 - DTRACE_NFSV3_4(op__write__done, struct svc_req *, req,
1488 - cred_t *, cr, vnode_t *, vp, WRITE3res *, resp);
1522 + DTRACE_NFSV3_5(op__write__done, struct svc_req *, req,
1523 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
1524 + WRITE3res *, resp);
1489 1525
1490 1526 if (vp != NULL) {
1491 1527 if (rwlock_ret != -1)
1492 1528 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
1493 1529 if (in_crit)
1494 1530 nbl_end_crit(vp);
1495 1531 VN_RELE(vp);
1496 1532 }
1497 1533 }
1498 1534
1499 1535 void *
1500 1536 rfs3_write_getfh(WRITE3args *args)
1501 1537 {
1502 -
1503 1538 return (&args->file);
1504 1539 }
1505 1540
1506 1541 void
1507 1542 rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi,
1508 1543 struct svc_req *req, cred_t *cr, bool_t ro)
1509 1544 {
1510 1545 int error;
1511 1546 int in_crit = 0;
1512 1547 vnode_t *vp;
1513 1548 vnode_t *tvp = NULL;
1514 1549 vnode_t *dvp;
1515 1550 struct vattr *vap;
1516 1551 struct vattr va;
1517 1552 struct vattr *dbvap;
1518 1553 struct vattr dbva;
1519 1554 struct vattr *davap;
1520 1555 struct vattr dava;
1521 1556 enum vcexcl excl;
1522 1557 nfstime3 *mtime;
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1523 1558 len_t reqsize;
1524 1559 bool_t trunc;
1525 1560 struct sockaddr *ca;
1526 1561 char *name = NULL;
1527 1562
1528 1563 dbvap = NULL;
1529 1564 davap = NULL;
1530 1565
1531 1566 dvp = nfs3_fhtovp(&args->where.dir, exi);
1532 1567
1533 - DTRACE_NFSV3_4(op__create__start, struct svc_req *, req,
1534 - cred_t *, cr, vnode_t *, dvp, CREATE3args *, args);
1568 + DTRACE_NFSV3_5(op__create__start, struct svc_req *, req,
1569 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
1570 + CREATE3args *, args);
1535 1571
1536 1572 if (dvp == NULL) {
1537 1573 error = ESTALE;
1538 1574 goto out;
1539 1575 }
1540 1576
1541 1577 dbva.va_mask = AT_ALL;
1542 1578 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1543 1579 davap = dbvap;
1544 1580
1545 1581 if (args->where.name == nfs3nametoolong) {
1546 1582 resp->status = NFS3ERR_NAMETOOLONG;
1547 1583 goto out1;
1548 1584 }
1549 1585
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1550 1586 if (args->where.name == NULL || *(args->where.name) == '\0') {
1551 1587 resp->status = NFS3ERR_ACCES;
1552 1588 goto out1;
1553 1589 }
1554 1590
1555 1591 if (rdonly(ro, dvp)) {
1556 1592 resp->status = NFS3ERR_ROFS;
1557 1593 goto out1;
1558 1594 }
1559 1595
1596 + if (protect_zfs_mntpt(dvp) != 0) {
1597 + resp->status = NFS3ERR_ACCES;
1598 + goto out1;
1599 + }
1600 +
1560 1601 if (is_system_labeled()) {
1561 1602 bslabel_t *clabel = req->rq_label;
1562 1603
1563 1604 ASSERT(clabel != NULL);
1564 1605 DTRACE_PROBE2(tx__rfs3__log__info__opcreate__clabel, char *,
1565 1606 "got client label from request(1)", struct svc_req *, req);
1566 1607
1567 1608 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1568 1609 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
1569 1610 exi)) {
1570 1611 resp->status = NFS3ERR_ACCES;
1571 1612 goto out1;
1572 1613 }
1573 1614 }
1574 1615 }
1575 1616
1576 1617 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1577 1618 name = nfscmd_convname(ca, exi, args->where.name,
1578 1619 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1579 1620
1580 1621 if (name == NULL) {
1581 1622 /* This is really a Solaris EILSEQ */
1582 1623 resp->status = NFS3ERR_INVAL;
1583 1624 goto out1;
1584 1625 }
1585 1626
1586 1627 if (args->how.mode == EXCLUSIVE) {
1587 1628 va.va_mask = AT_TYPE | AT_MODE | AT_MTIME;
1588 1629 va.va_type = VREG;
1589 1630 va.va_mode = (mode_t)0;
1590 1631 /*
1591 1632 * Ensure no time overflows and that types match
1592 1633 */
1593 1634 mtime = (nfstime3 *)&args->how.createhow3_u.verf;
1594 1635 va.va_mtime.tv_sec = mtime->seconds % INT32_MAX;
1595 1636 va.va_mtime.tv_nsec = mtime->nseconds;
1596 1637 excl = EXCL;
1597 1638 } else {
1598 1639 error = sattr3_to_vattr(&args->how.createhow3_u.obj_attributes,
1599 1640 &va);
1600 1641 if (error)
1601 1642 goto out;
1602 1643 va.va_mask |= AT_TYPE;
1603 1644 va.va_type = VREG;
1604 1645 if (args->how.mode == GUARDED)
1605 1646 excl = EXCL;
1606 1647 else {
1607 1648 excl = NONEXCL;
1608 1649
1609 1650 /*
1610 1651 * During creation of file in non-exclusive mode
1611 1652 * if size of file is being set then make sure
1612 1653 * that if the file already exists that no conflicting
1613 1654 * non-blocking mandatory locks exists in the region
1614 1655 * being modified. If there are conflicting locks fail
1615 1656 * the operation with EACCES.
1616 1657 */
1617 1658 if (va.va_mask & AT_SIZE) {
1618 1659 struct vattr tva;
1619 1660
1620 1661 /*
1621 1662 * Does file already exist?
1622 1663 */
1623 1664 error = VOP_LOOKUP(dvp, name, &tvp,
1624 1665 NULL, 0, NULL, cr, NULL, NULL, NULL);
1625 1666
1626 1667 /*
1627 1668 * Check to see if the file has been delegated
1628 1669 * to a v4 client. If so, then begin recall of
1629 1670 * the delegation and return JUKEBOX to allow
1630 1671 * the client to retrasmit its request.
1631 1672 */
1632 1673
1633 1674 trunc = va.va_size == 0;
1634 1675 if (!error &&
1635 1676 rfs4_check_delegated(FWRITE, tvp, trunc)) {
1636 1677 resp->status = NFS3ERR_JUKEBOX;
1637 1678 goto out1;
1638 1679 }
1639 1680
1640 1681 /*
1641 1682 * Check for NBMAND lock conflicts
1642 1683 */
1643 1684 if (!error && nbl_need_check(tvp)) {
1644 1685 u_offset_t offset;
1645 1686 ssize_t len;
1646 1687
1647 1688 nbl_start_crit(tvp, RW_READER);
1648 1689 in_crit = 1;
1649 1690
1650 1691 tva.va_mask = AT_SIZE;
1651 1692 error = VOP_GETATTR(tvp, &tva, 0, cr,
1652 1693 NULL);
1653 1694 /*
1654 1695 * Can't check for conflicts, so return
1655 1696 * error.
1656 1697 */
1657 1698 if (error)
1658 1699 goto out;
1659 1700
1660 1701 offset = tva.va_size < va.va_size ?
1661 1702 tva.va_size : va.va_size;
1662 1703 len = tva.va_size < va.va_size ?
1663 1704 va.va_size - tva.va_size :
1664 1705 tva.va_size - va.va_size;
1665 1706 if (nbl_conflict(tvp, NBL_WRITE,
1666 1707 offset, len, 0, NULL)) {
1667 1708 error = EACCES;
1668 1709 goto out;
1669 1710 }
1670 1711 } else if (tvp) {
1671 1712 VN_RELE(tvp);
1672 1713 tvp = NULL;
1673 1714 }
1674 1715 }
1675 1716 }
1676 1717 if (va.va_mask & AT_SIZE)
1677 1718 reqsize = va.va_size;
1678 1719 }
1679 1720
1680 1721 /*
1681 1722 * Must specify the mode.
1682 1723 */
1683 1724 if (!(va.va_mask & AT_MODE)) {
1684 1725 resp->status = NFS3ERR_INVAL;
1685 1726 goto out1;
1686 1727 }
1687 1728
1688 1729 /*
1689 1730 * If the filesystem is exported with nosuid, then mask off
1690 1731 * the setuid and setgid bits.
1691 1732 */
1692 1733 if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID))
1693 1734 va.va_mode &= ~(VSUID | VSGID);
1694 1735
1695 1736 tryagain:
1696 1737 /*
1697 1738 * The file open mode used is VWRITE. If the client needs
1698 1739 * some other semantic, then it should do the access checking
1699 1740 * itself. It would have been nice to have the file open mode
1700 1741 * passed as part of the arguments.
1701 1742 */
1702 1743 error = VOP_CREATE(dvp, name, &va, excl, VWRITE,
1703 1744 &vp, cr, 0, NULL, NULL);
1704 1745
1705 1746 dava.va_mask = AT_ALL;
1706 1747 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1707 1748
1708 1749 if (error) {
1709 1750 /*
1710 1751 * If we got something other than file already exists
1711 1752 * then just return this error. Otherwise, we got
1712 1753 * EEXIST. If we were doing a GUARDED create, then
1713 1754 * just return this error. Otherwise, we need to
1714 1755 * make sure that this wasn't a duplicate of an
1715 1756 * exclusive create request.
1716 1757 *
1717 1758 * The assumption is made that a non-exclusive create
1718 1759 * request will never return EEXIST.
1719 1760 */
1720 1761 if (error != EEXIST || args->how.mode == GUARDED)
1721 1762 goto out;
1722 1763 /*
1723 1764 * Lookup the file so that we can get a vnode for it.
1724 1765 */
1725 1766 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0,
1726 1767 NULL, cr, NULL, NULL, NULL);
1727 1768 if (error) {
1728 1769 /*
1729 1770 * We couldn't find the file that we thought that
1730 1771 * we just created. So, we'll just try creating
1731 1772 * it again.
1732 1773 */
1733 1774 if (error == ENOENT)
1734 1775 goto tryagain;
1735 1776 goto out;
1736 1777 }
1737 1778
1738 1779 /*
1739 1780 * If the file is delegated to a v4 client, go ahead
1740 1781 * and initiate recall, this create is a hint that a
1741 1782 * conflicting v3 open has occurred.
1742 1783 */
1743 1784
1744 1785 if (rfs4_check_delegated(FWRITE, vp, FALSE)) {
1745 1786 VN_RELE(vp);
1746 1787 resp->status = NFS3ERR_JUKEBOX;
1747 1788 goto out1;
1748 1789 }
1749 1790
1750 1791 va.va_mask = AT_ALL;
1751 1792 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1752 1793
1753 1794 mtime = (nfstime3 *)&args->how.createhow3_u.verf;
1754 1795 /* % with INT32_MAX to prevent overflows */
1755 1796 if (args->how.mode == EXCLUSIVE && (vap == NULL ||
1756 1797 vap->va_mtime.tv_sec !=
1757 1798 (mtime->seconds % INT32_MAX) ||
1758 1799 vap->va_mtime.tv_nsec != mtime->nseconds)) {
1759 1800 VN_RELE(vp);
1760 1801 error = EEXIST;
1761 1802 goto out;
1762 1803 }
1763 1804 } else {
1764 1805
1765 1806 if ((args->how.mode == UNCHECKED ||
1766 1807 args->how.mode == GUARDED) &&
1767 1808 args->how.createhow3_u.obj_attributes.size.set_it &&
1768 1809 va.va_size == 0)
1769 1810 trunc = TRUE;
1770 1811 else
1771 1812 trunc = FALSE;
1772 1813
1773 1814 if (rfs4_check_delegated(FWRITE, vp, trunc)) {
1774 1815 VN_RELE(vp);
1775 1816 resp->status = NFS3ERR_JUKEBOX;
1776 1817 goto out1;
1777 1818 }
1778 1819
1779 1820 va.va_mask = AT_ALL;
1780 1821 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1781 1822
1782 1823 /*
1783 1824 * We need to check to make sure that the file got
1784 1825 * created to the indicated size. If not, we do a
1785 1826 * setattr to try to change the size, but we don't
1786 1827 * try too hard. This shouldn't a problem as most
1787 1828 * clients will only specifiy a size of zero which
1788 1829 * local file systems handle. However, even if
1789 1830 * the client does specify a non-zero size, it can
1790 1831 * still recover by checking the size of the file
1791 1832 * after it has created it and then issue a setattr
1792 1833 * request of its own to set the size of the file.
1793 1834 */
1794 1835 if (vap != NULL &&
1795 1836 (args->how.mode == UNCHECKED ||
1796 1837 args->how.mode == GUARDED) &&
1797 1838 args->how.createhow3_u.obj_attributes.size.set_it &&
1798 1839 vap->va_size != reqsize) {
1799 1840 va.va_mask = AT_SIZE;
1800 1841 va.va_size = reqsize;
1801 1842 (void) VOP_SETATTR(vp, &va, 0, cr, NULL);
1802 1843 va.va_mask = AT_ALL;
1803 1844 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1804 1845 }
1805 1846 }
1806 1847
1807 1848 if (name != args->where.name)
1808 1849 kmem_free(name, MAXPATHLEN + 1);
1809 1850
1810 1851 error = makefh3(&resp->resok.obj.handle, vp, exi);
1811 1852 if (error)
1812 1853 resp->resok.obj.handle_follows = FALSE;
1813 1854 else
1814 1855 resp->resok.obj.handle_follows = TRUE;
1815 1856
1816 1857 /*
1817 1858 * Force modified data and metadata out to stable storage.
1818 1859 */
1819 1860 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
1820 1861 (void) VOP_FSYNC(dvp, 0, cr, NULL);
1821 1862
1822 1863 VN_RELE(vp);
|
↓ open down ↓ |
253 lines elided |
↑ open up ↑ |
1823 1864 if (tvp != NULL) {
1824 1865 if (in_crit)
1825 1866 nbl_end_crit(tvp);
1826 1867 VN_RELE(tvp);
1827 1868 }
1828 1869
1829 1870 resp->status = NFS3_OK;
1830 1871 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
1831 1872 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1832 1873
1833 - DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1834 - cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1874 + DTRACE_NFSV3_5(op__create__done, struct svc_req *, req,
1875 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
1876 + CREATE3res *, resp);
1835 1877
1836 1878 VN_RELE(dvp);
1837 1879 return;
1838 1880
1839 1881 out:
1840 1882 if (curthread->t_flag & T_WOULDBLOCK) {
1841 1883 curthread->t_flag &= ~T_WOULDBLOCK;
1842 1884 resp->status = NFS3ERR_JUKEBOX;
1843 1885 } else
1844 1886 resp->status = puterrno3(error);
1845 1887 out1:
1846 - DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1847 - cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1888 + DTRACE_NFSV3_5(op__create__done, struct svc_req *, req,
1889 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
1890 + CREATE3res *, resp);
1848 1891
1849 1892 if (name != NULL && name != args->where.name)
1850 1893 kmem_free(name, MAXPATHLEN + 1);
1851 1894
1852 1895 if (tvp != NULL) {
1853 1896 if (in_crit)
1854 1897 nbl_end_crit(tvp);
1855 1898 VN_RELE(tvp);
1856 1899 }
1857 1900 if (dvp != NULL)
1858 1901 VN_RELE(dvp);
1859 1902 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
1860 1903 }
1861 1904
1862 1905 void *
1863 1906 rfs3_create_getfh(CREATE3args *args)
1864 1907 {
1865 -
1866 1908 return (&args->where.dir);
1867 1909 }
1868 1910
1869 1911 void
1870 1912 rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi,
1871 1913 struct svc_req *req, cred_t *cr, bool_t ro)
1872 1914 {
1873 1915 int error;
1874 1916 vnode_t *vp = NULL;
1875 1917 vnode_t *dvp;
1876 1918 struct vattr *vap;
1877 1919 struct vattr va;
1878 1920 struct vattr *dbvap;
1879 1921 struct vattr dbva;
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
1880 1922 struct vattr *davap;
1881 1923 struct vattr dava;
1882 1924 struct sockaddr *ca;
1883 1925 char *name = NULL;
1884 1926
1885 1927 dbvap = NULL;
1886 1928 davap = NULL;
1887 1929
1888 1930 dvp = nfs3_fhtovp(&args->where.dir, exi);
1889 1931
1890 - DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req,
1891 - cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args);
1932 + DTRACE_NFSV3_5(op__mkdir__start, struct svc_req *, req,
1933 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
1934 + MKDIR3args *, args);
1892 1935
1893 1936 if (dvp == NULL) {
1894 1937 error = ESTALE;
1895 1938 goto out;
1896 1939 }
1897 1940
1898 1941 dbva.va_mask = AT_ALL;
1899 1942 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1900 1943 davap = dbvap;
1901 1944
1902 1945 if (args->where.name == nfs3nametoolong) {
1903 1946 resp->status = NFS3ERR_NAMETOOLONG;
1904 1947 goto out1;
1905 1948 }
1906 1949
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1907 1950 if (args->where.name == NULL || *(args->where.name) == '\0') {
1908 1951 resp->status = NFS3ERR_ACCES;
1909 1952 goto out1;
1910 1953 }
1911 1954
1912 1955 if (rdonly(ro, dvp)) {
1913 1956 resp->status = NFS3ERR_ROFS;
1914 1957 goto out1;
1915 1958 }
1916 1959
1960 + if (protect_zfs_mntpt(dvp) != 0) {
1961 + resp->status = NFS3ERR_ACCES;
1962 + goto out1;
1963 + }
1964 +
1917 1965 if (is_system_labeled()) {
1918 1966 bslabel_t *clabel = req->rq_label;
1919 1967
1920 1968 ASSERT(clabel != NULL);
1921 1969 DTRACE_PROBE2(tx__rfs3__log__info__opmkdir__clabel, char *,
1922 1970 "got client label from request(1)", struct svc_req *, req);
1923 1971
1924 1972 if (!blequal(&l_admin_low->tsl_label, clabel)) {
1925 1973 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
1926 1974 exi)) {
1927 1975 resp->status = NFS3ERR_ACCES;
1928 1976 goto out1;
1929 1977 }
1930 1978 }
1931 1979 }
1932 1980
1933 1981 error = sattr3_to_vattr(&args->attributes, &va);
1934 1982 if (error)
1935 1983 goto out;
1936 1984
1937 1985 if (!(va.va_mask & AT_MODE)) {
1938 1986 resp->status = NFS3ERR_INVAL;
1939 1987 goto out1;
1940 1988 }
1941 1989
1942 1990 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1943 1991 name = nfscmd_convname(ca, exi, args->where.name,
1944 1992 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1945 1993
1946 1994 if (name == NULL) {
1947 1995 resp->status = NFS3ERR_INVAL;
1948 1996 goto out1;
1949 1997 }
1950 1998
1951 1999 va.va_mask |= AT_TYPE;
1952 2000 va.va_type = VDIR;
1953 2001
1954 2002 error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL);
1955 2003
1956 2004 if (name != args->where.name)
1957 2005 kmem_free(name, MAXPATHLEN + 1);
1958 2006
1959 2007 dava.va_mask = AT_ALL;
1960 2008 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1961 2009
1962 2010 /*
1963 2011 * Force modified data and metadata out to stable storage.
1964 2012 */
1965 2013 (void) VOP_FSYNC(dvp, 0, cr, NULL);
1966 2014
1967 2015 if (error)
1968 2016 goto out;
1969 2017
1970 2018 error = makefh3(&resp->resok.obj.handle, vp, exi);
1971 2019 if (error)
1972 2020 resp->resok.obj.handle_follows = FALSE;
1973 2021 else
1974 2022 resp->resok.obj.handle_follows = TRUE;
1975 2023
1976 2024 va.va_mask = AT_ALL;
1977 2025 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1978 2026
1979 2027 /*
|
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
1980 2028 * Force modified data and metadata out to stable storage.
1981 2029 */
1982 2030 (void) VOP_FSYNC(vp, 0, cr, NULL);
1983 2031
1984 2032 VN_RELE(vp);
1985 2033
1986 2034 resp->status = NFS3_OK;
1987 2035 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
1988 2036 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1989 2037
1990 - DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
1991 - cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
2038 + DTRACE_NFSV3_5(op__mkdir__done, struct svc_req *, req,
2039 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
2040 + MKDIR3res *, resp);
1992 2041 VN_RELE(dvp);
1993 2042
1994 2043 return;
1995 2044
1996 2045 out:
1997 2046 if (curthread->t_flag & T_WOULDBLOCK) {
1998 2047 curthread->t_flag &= ~T_WOULDBLOCK;
1999 2048 resp->status = NFS3ERR_JUKEBOX;
2000 2049 } else
2001 2050 resp->status = puterrno3(error);
2002 2051 out1:
2003 - DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
2004 - cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
2052 + DTRACE_NFSV3_5(op__mkdir__done, struct svc_req *, req,
2053 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
2054 + MKDIR3res *, resp);
2005 2055 if (dvp != NULL)
2006 2056 VN_RELE(dvp);
2007 2057 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2008 2058 }
2009 2059
2010 2060 void *
2011 2061 rfs3_mkdir_getfh(MKDIR3args *args)
2012 2062 {
2013 -
2014 2063 return (&args->where.dir);
2015 2064 }
2016 2065
2017 2066 void
2018 2067 rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi,
2019 2068 struct svc_req *req, cred_t *cr, bool_t ro)
2020 2069 {
2021 2070 int error;
2022 2071 vnode_t *vp;
2023 2072 vnode_t *dvp;
2024 2073 struct vattr *vap;
2025 2074 struct vattr va;
2026 2075 struct vattr *dbvap;
2027 2076 struct vattr dbva;
2028 2077 struct vattr *davap;
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
2029 2078 struct vattr dava;
2030 2079 struct sockaddr *ca;
2031 2080 char *name = NULL;
2032 2081 char *symdata = NULL;
2033 2082
2034 2083 dbvap = NULL;
2035 2084 davap = NULL;
2036 2085
2037 2086 dvp = nfs3_fhtovp(&args->where.dir, exi);
2038 2087
2039 - DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req,
2040 - cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args);
2088 + DTRACE_NFSV3_5(op__symlink__start, struct svc_req *, req,
2089 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
2090 + SYMLINK3args *, args);
2041 2091
2042 2092 if (dvp == NULL) {
2043 2093 error = ESTALE;
2044 2094 goto err;
2045 2095 }
2046 2096
2047 2097 dbva.va_mask = AT_ALL;
2048 2098 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2049 2099 davap = dbvap;
2050 2100
2051 2101 if (args->where.name == nfs3nametoolong) {
2052 2102 resp->status = NFS3ERR_NAMETOOLONG;
2053 2103 goto err1;
2054 2104 }
2055 2105
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
2056 2106 if (args->where.name == NULL || *(args->where.name) == '\0') {
2057 2107 resp->status = NFS3ERR_ACCES;
2058 2108 goto err1;
2059 2109 }
2060 2110
2061 2111 if (rdonly(ro, dvp)) {
2062 2112 resp->status = NFS3ERR_ROFS;
2063 2113 goto err1;
2064 2114 }
2065 2115
2116 + if (protect_zfs_mntpt(dvp) != 0) {
2117 + resp->status = NFS3ERR_ACCES;
2118 + goto err1;
2119 + }
2120 +
2066 2121 if (is_system_labeled()) {
2067 2122 bslabel_t *clabel = req->rq_label;
2068 2123
2069 2124 ASSERT(clabel != NULL);
2070 2125 DTRACE_PROBE2(tx__rfs3__log__info__opsymlink__clabel, char *,
2071 2126 "got client label from request(1)", struct svc_req *, req);
2072 2127
2073 2128 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2074 2129 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2075 2130 exi)) {
2076 2131 resp->status = NFS3ERR_ACCES;
2077 2132 goto err1;
2078 2133 }
2079 2134 }
2080 2135 }
2081 2136
2082 2137 error = sattr3_to_vattr(&args->symlink.symlink_attributes, &va);
2083 2138 if (error)
2084 2139 goto err;
2085 2140
2086 2141 if (!(va.va_mask & AT_MODE)) {
2087 2142 resp->status = NFS3ERR_INVAL;
2088 2143 goto err1;
2089 2144 }
2090 2145
2091 2146 if (args->symlink.symlink_data == nfs3nametoolong) {
2092 2147 resp->status = NFS3ERR_NAMETOOLONG;
2093 2148 goto err1;
2094 2149 }
2095 2150
2096 2151 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2097 2152 name = nfscmd_convname(ca, exi, args->where.name,
2098 2153 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2099 2154
2100 2155 if (name == NULL) {
2101 2156 /* This is really a Solaris EILSEQ */
2102 2157 resp->status = NFS3ERR_INVAL;
2103 2158 goto err1;
2104 2159 }
2105 2160
2106 2161 symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data,
2107 2162 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2108 2163 if (symdata == NULL) {
2109 2164 /* This is really a Solaris EILSEQ */
2110 2165 resp->status = NFS3ERR_INVAL;
2111 2166 goto err1;
2112 2167 }
2113 2168
2114 2169
2115 2170 va.va_mask |= AT_TYPE;
2116 2171 va.va_type = VLNK;
2117 2172
2118 2173 error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0);
2119 2174
2120 2175 dava.va_mask = AT_ALL;
2121 2176 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2122 2177
2123 2178 if (error)
2124 2179 goto err;
2125 2180
2126 2181 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
2127 2182 NULL, NULL, NULL);
2128 2183
2129 2184 /*
2130 2185 * Force modified data and metadata out to stable storage.
2131 2186 */
2132 2187 (void) VOP_FSYNC(dvp, 0, cr, NULL);
2133 2188
2134 2189
2135 2190 resp->status = NFS3_OK;
2136 2191 if (error) {
2137 2192 resp->resok.obj.handle_follows = FALSE;
2138 2193 vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
2139 2194 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2140 2195 goto out;
2141 2196 }
2142 2197
2143 2198 error = makefh3(&resp->resok.obj.handle, vp, exi);
2144 2199 if (error)
2145 2200 resp->resok.obj.handle_follows = FALSE;
2146 2201 else
2147 2202 resp->resok.obj.handle_follows = TRUE;
2148 2203
2149 2204 va.va_mask = AT_ALL;
2150 2205 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2151 2206
2152 2207 /*
2153 2208 * Force modified data and metadata out to stable storage.
2154 2209 */
2155 2210 (void) VOP_FSYNC(vp, 0, cr, NULL);
2156 2211
2157 2212 VN_RELE(vp);
2158 2213
2159 2214 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2160 2215 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2161 2216 goto out;
2162 2217
2163 2218 err:
2164 2219 if (curthread->t_flag & T_WOULDBLOCK) {
2165 2220 curthread->t_flag &= ~T_WOULDBLOCK;
2166 2221 resp->status = NFS3ERR_JUKEBOX;
|
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
2167 2222 } else
2168 2223 resp->status = puterrno3(error);
2169 2224 err1:
2170 2225 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2171 2226 out:
2172 2227 if (name != NULL && name != args->where.name)
2173 2228 kmem_free(name, MAXPATHLEN + 1);
2174 2229 if (symdata != NULL && symdata != args->symlink.symlink_data)
2175 2230 kmem_free(symdata, MAXPATHLEN + 1);
2176 2231
2177 - DTRACE_NFSV3_4(op__symlink__done, struct svc_req *, req,
2178 - cred_t *, cr, vnode_t *, dvp, SYMLINK3res *, resp);
2232 + DTRACE_NFSV3_5(op__symlink__done, struct svc_req *, req,
2233 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
2234 + SYMLINK3res *, resp);
2179 2235
2180 2236 if (dvp != NULL)
2181 2237 VN_RELE(dvp);
2182 2238 }
2183 2239
2184 2240 void *
2185 2241 rfs3_symlink_getfh(SYMLINK3args *args)
2186 2242 {
2187 -
2188 2243 return (&args->where.dir);
2189 2244 }
2190 2245
2191 2246 void
2192 2247 rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi,
2193 2248 struct svc_req *req, cred_t *cr, bool_t ro)
2194 2249 {
2195 2250 int error;
2196 2251 vnode_t *vp;
2197 2252 vnode_t *realvp;
2198 2253 vnode_t *dvp;
2199 2254 struct vattr *vap;
2200 2255 struct vattr va;
2201 2256 struct vattr *dbvap;
2202 2257 struct vattr dbva;
2203 2258 struct vattr *davap;
2204 2259 struct vattr dava;
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
2205 2260 int mode;
2206 2261 enum vcexcl excl;
2207 2262 struct sockaddr *ca;
2208 2263 char *name = NULL;
2209 2264
2210 2265 dbvap = NULL;
2211 2266 davap = NULL;
2212 2267
2213 2268 dvp = nfs3_fhtovp(&args->where.dir, exi);
2214 2269
2215 - DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req,
2216 - cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args);
2270 + DTRACE_NFSV3_5(op__mknod__start, struct svc_req *, req,
2271 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
2272 + MKNOD3args *, args);
2217 2273
2218 2274 if (dvp == NULL) {
2219 2275 error = ESTALE;
2220 2276 goto out;
2221 2277 }
2222 2278
2223 2279 dbva.va_mask = AT_ALL;
2224 2280 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2225 2281 davap = dbvap;
2226 2282
2227 2283 if (args->where.name == nfs3nametoolong) {
2228 2284 resp->status = NFS3ERR_NAMETOOLONG;
2229 2285 goto out1;
2230 2286 }
2231 2287
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
2232 2288 if (args->where.name == NULL || *(args->where.name) == '\0') {
2233 2289 resp->status = NFS3ERR_ACCES;
2234 2290 goto out1;
2235 2291 }
2236 2292
2237 2293 if (rdonly(ro, dvp)) {
2238 2294 resp->status = NFS3ERR_ROFS;
2239 2295 goto out1;
2240 2296 }
2241 2297
2298 + if (protect_zfs_mntpt(dvp) != 0) {
2299 + resp->status = NFS3ERR_ACCES;
2300 + goto out1;
2301 + }
2302 +
2242 2303 if (is_system_labeled()) {
2243 2304 bslabel_t *clabel = req->rq_label;
2244 2305
2245 2306 ASSERT(clabel != NULL);
2246 2307 DTRACE_PROBE2(tx__rfs3__log__info__opmknod__clabel, char *,
2247 2308 "got client label from request(1)", struct svc_req *, req);
2248 2309
2249 2310 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2250 2311 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2251 2312 exi)) {
2252 2313 resp->status = NFS3ERR_ACCES;
2253 2314 goto out1;
2254 2315 }
2255 2316 }
2256 2317 }
2257 2318
2258 2319 switch (args->what.type) {
2259 2320 case NF3CHR:
2260 2321 case NF3BLK:
2261 2322 error = sattr3_to_vattr(
2262 2323 &args->what.mknoddata3_u.device.dev_attributes, &va);
2263 2324 if (error)
2264 2325 goto out;
2265 2326 if (secpolicy_sys_devices(cr) != 0) {
2266 2327 resp->status = NFS3ERR_PERM;
2267 2328 goto out1;
2268 2329 }
2269 2330 if (args->what.type == NF3CHR)
2270 2331 va.va_type = VCHR;
2271 2332 else
2272 2333 va.va_type = VBLK;
2273 2334 va.va_rdev = makedevice(
2274 2335 args->what.mknoddata3_u.device.spec.specdata1,
2275 2336 args->what.mknoddata3_u.device.spec.specdata2);
2276 2337 va.va_mask |= AT_TYPE | AT_RDEV;
2277 2338 break;
2278 2339 case NF3SOCK:
2279 2340 error = sattr3_to_vattr(
2280 2341 &args->what.mknoddata3_u.pipe_attributes, &va);
2281 2342 if (error)
2282 2343 goto out;
2283 2344 va.va_type = VSOCK;
2284 2345 va.va_mask |= AT_TYPE;
2285 2346 break;
2286 2347 case NF3FIFO:
2287 2348 error = sattr3_to_vattr(
2288 2349 &args->what.mknoddata3_u.pipe_attributes, &va);
2289 2350 if (error)
2290 2351 goto out;
2291 2352 va.va_type = VFIFO;
2292 2353 va.va_mask |= AT_TYPE;
2293 2354 break;
2294 2355 default:
2295 2356 resp->status = NFS3ERR_BADTYPE;
2296 2357 goto out1;
2297 2358 }
2298 2359
2299 2360 /*
2300 2361 * Must specify the mode.
2301 2362 */
2302 2363 if (!(va.va_mask & AT_MODE)) {
2303 2364 resp->status = NFS3ERR_INVAL;
2304 2365 goto out1;
2305 2366 }
2306 2367
2307 2368 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2308 2369 name = nfscmd_convname(ca, exi, args->where.name,
2309 2370 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2310 2371
2311 2372 if (name == NULL) {
2312 2373 resp->status = NFS3ERR_INVAL;
2313 2374 goto out1;
2314 2375 }
2315 2376
2316 2377 excl = EXCL;
2317 2378
2318 2379 mode = 0;
2319 2380
2320 2381 error = VOP_CREATE(dvp, name, &va, excl, mode,
2321 2382 &vp, cr, 0, NULL, NULL);
2322 2383
2323 2384 if (name != args->where.name)
2324 2385 kmem_free(name, MAXPATHLEN + 1);
2325 2386
2326 2387 dava.va_mask = AT_ALL;
2327 2388 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2328 2389
2329 2390 /*
2330 2391 * Force modified data and metadata out to stable storage.
2331 2392 */
2332 2393 (void) VOP_FSYNC(dvp, 0, cr, NULL);
2333 2394
2334 2395 if (error)
2335 2396 goto out;
2336 2397
2337 2398 resp->status = NFS3_OK;
2338 2399
2339 2400 error = makefh3(&resp->resok.obj.handle, vp, exi);
2340 2401 if (error)
2341 2402 resp->resok.obj.handle_follows = FALSE;
2342 2403 else
2343 2404 resp->resok.obj.handle_follows = TRUE;
2344 2405
2345 2406 va.va_mask = AT_ALL;
2346 2407 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2347 2408
2348 2409 /*
2349 2410 * Force modified metadata out to stable storage.
2350 2411 *
2351 2412 * if a underlying vp exists, pass it to VOP_FSYNC
|
↓ open down ↓ |
100 lines elided |
↑ open up ↑ |
2352 2413 */
2353 2414 if (VOP_REALVP(vp, &realvp, NULL) == 0)
2354 2415 (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL);
2355 2416 else
2356 2417 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
2357 2418
2358 2419 VN_RELE(vp);
2359 2420
2360 2421 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2361 2422 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2362 - DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2363 - cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
2423 + DTRACE_NFSV3_5(op__mknod__done, struct svc_req *, req,
2424 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
2425 + MKNOD3res *, resp);
2364 2426 VN_RELE(dvp);
2365 2427 return;
2366 2428
2367 2429 out:
2368 2430 if (curthread->t_flag & T_WOULDBLOCK) {
2369 2431 curthread->t_flag &= ~T_WOULDBLOCK;
2370 2432 resp->status = NFS3ERR_JUKEBOX;
2371 2433 } else
2372 2434 resp->status = puterrno3(error);
2373 2435 out1:
2374 - DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2375 - cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
2436 + DTRACE_NFSV3_5(op__mknod__done, struct svc_req *, req,
2437 + cred_t *, cr, vnode_t *, dvp, struct exportinfo *, exi,
2438 + MKNOD3res *, resp);
2376 2439 if (dvp != NULL)
2377 2440 VN_RELE(dvp);
2378 2441 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2379 2442 }
2380 2443
2381 2444 void *
2382 2445 rfs3_mknod_getfh(MKNOD3args *args)
2383 2446 {
2384 -
2385 2447 return (&args->where.dir);
2386 2448 }
2387 2449
2388 2450 void
2389 2451 rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi,
2390 2452 struct svc_req *req, cred_t *cr, bool_t ro)
2391 2453 {
2392 2454 int error = 0;
2393 2455 vnode_t *vp;
2394 2456 struct vattr *bvap;
2395 2457 struct vattr bva;
2396 2458 struct vattr *avap;
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
2397 2459 struct vattr ava;
2398 2460 vnode_t *targvp = NULL;
2399 2461 struct sockaddr *ca;
2400 2462 char *name = NULL;
2401 2463
2402 2464 bvap = NULL;
2403 2465 avap = NULL;
2404 2466
2405 2467 vp = nfs3_fhtovp(&args->object.dir, exi);
2406 2468
2407 - DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req,
2408 - cred_t *, cr, vnode_t *, vp, REMOVE3args *, args);
2469 + DTRACE_NFSV3_5(op__remove__start, struct svc_req *, req,
2470 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
2471 + REMOVE3args *, args);
2409 2472
2410 2473 if (vp == NULL) {
2411 2474 error = ESTALE;
2412 2475 goto err;
2413 2476 }
2414 2477
2415 2478 bva.va_mask = AT_ALL;
2416 2479 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2417 2480 avap = bvap;
2418 2481
2419 2482 if (vp->v_type != VDIR) {
2420 2483 resp->status = NFS3ERR_NOTDIR;
2421 2484 goto err1;
2422 2485 }
2423 2486
2424 2487 if (args->object.name == nfs3nametoolong) {
2425 2488 resp->status = NFS3ERR_NAMETOOLONG;
2426 2489 goto err1;
2427 2490 }
2428 2491
2429 2492 if (args->object.name == NULL || *(args->object.name) == '\0') {
2430 2493 resp->status = NFS3ERR_ACCES;
2431 2494 goto err1;
2432 2495 }
2433 2496
2434 2497 if (rdonly(ro, vp)) {
2435 2498 resp->status = NFS3ERR_ROFS;
2436 2499 goto err1;
2437 2500 }
2438 2501
2439 2502 if (is_system_labeled()) {
2440 2503 bslabel_t *clabel = req->rq_label;
2441 2504
2442 2505 ASSERT(clabel != NULL);
2443 2506 DTRACE_PROBE2(tx__rfs3__log__info__opremove__clabel, char *,
2444 2507 "got client label from request(1)", struct svc_req *, req);
2445 2508
2446 2509 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2447 2510 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2448 2511 exi)) {
2449 2512 resp->status = NFS3ERR_ACCES;
2450 2513 goto err1;
2451 2514 }
2452 2515 }
2453 2516 }
2454 2517
2455 2518 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2456 2519 name = nfscmd_convname(ca, exi, args->object.name,
2457 2520 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2458 2521
2459 2522 if (name == NULL) {
2460 2523 resp->status = NFS3ERR_INVAL;
2461 2524 goto err1;
2462 2525 }
2463 2526
2464 2527 /*
2465 2528 * Check for a conflict with a non-blocking mandatory share
2466 2529 * reservation and V4 delegations
2467 2530 */
2468 2531 error = VOP_LOOKUP(vp, name, &targvp, NULL, 0,
2469 2532 NULL, cr, NULL, NULL, NULL);
2470 2533 if (error != 0)
2471 2534 goto err;
2472 2535
2473 2536 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
2474 2537 resp->status = NFS3ERR_JUKEBOX;
2475 2538 goto err1;
2476 2539 }
2477 2540
2478 2541 if (!nbl_need_check(targvp)) {
2479 2542 error = VOP_REMOVE(vp, name, cr, NULL, 0);
2480 2543 } else {
2481 2544 nbl_start_crit(targvp, RW_READER);
2482 2545 if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
2483 2546 error = EACCES;
2484 2547 } else {
2485 2548 error = VOP_REMOVE(vp, name, cr, NULL, 0);
2486 2549 }
2487 2550 nbl_end_crit(targvp);
2488 2551 }
2489 2552 VN_RELE(targvp);
2490 2553 targvp = NULL;
2491 2554
2492 2555 ava.va_mask = AT_ALL;
2493 2556 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2494 2557
2495 2558 /*
2496 2559 * Force modified data and metadata out to stable storage.
2497 2560 */
2498 2561 (void) VOP_FSYNC(vp, 0, cr, NULL);
2499 2562
2500 2563 if (error)
2501 2564 goto err;
2502 2565
2503 2566 resp->status = NFS3_OK;
2504 2567 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2505 2568 goto out;
|
↓ open down ↓ |
87 lines elided |
↑ open up ↑ |
2506 2569
2507 2570 err:
2508 2571 if (curthread->t_flag & T_WOULDBLOCK) {
2509 2572 curthread->t_flag &= ~T_WOULDBLOCK;
2510 2573 resp->status = NFS3ERR_JUKEBOX;
2511 2574 } else
2512 2575 resp->status = puterrno3(error);
2513 2576 err1:
2514 2577 vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2515 2578 out:
2516 - DTRACE_NFSV3_4(op__remove__done, struct svc_req *, req,
2517 - cred_t *, cr, vnode_t *, vp, REMOVE3res *, resp);
2579 + DTRACE_NFSV3_5(op__remove__done, struct svc_req *, req,
2580 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
2581 + REMOVE3res *, resp);
2518 2582
2519 2583 if (name != NULL && name != args->object.name)
2520 2584 kmem_free(name, MAXPATHLEN + 1);
2521 2585
2522 2586 if (vp != NULL)
2523 2587 VN_RELE(vp);
2524 2588 }
2525 2589
2526 2590 void *
2527 2591 rfs3_remove_getfh(REMOVE3args *args)
2528 2592 {
2529 -
2530 2593 return (&args->object.dir);
2531 2594 }
2532 2595
2533 2596 void
2534 2597 rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi,
2535 2598 struct svc_req *req, cred_t *cr, bool_t ro)
2536 2599 {
2537 2600 int error;
2538 2601 vnode_t *vp;
2539 2602 struct vattr *bvap;
2540 2603 struct vattr bva;
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
2541 2604 struct vattr *avap;
2542 2605 struct vattr ava;
2543 2606 struct sockaddr *ca;
2544 2607 char *name = NULL;
2545 2608
2546 2609 bvap = NULL;
2547 2610 avap = NULL;
2548 2611
2549 2612 vp = nfs3_fhtovp(&args->object.dir, exi);
2550 2613
2551 - DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req,
2552 - cred_t *, cr, vnode_t *, vp, RMDIR3args *, args);
2614 + DTRACE_NFSV3_5(op__rmdir__start, struct svc_req *, req,
2615 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
2616 + RMDIR3args *, args);
2553 2617
2554 2618 if (vp == NULL) {
2555 2619 error = ESTALE;
2556 2620 goto err;
2557 2621 }
2558 2622
2559 2623 bva.va_mask = AT_ALL;
2560 2624 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2561 2625 avap = bvap;
2562 2626
2563 2627 if (vp->v_type != VDIR) {
2564 2628 resp->status = NFS3ERR_NOTDIR;
2565 2629 goto err1;
2566 2630 }
2567 2631
2568 2632 if (args->object.name == nfs3nametoolong) {
2569 2633 resp->status = NFS3ERR_NAMETOOLONG;
2570 2634 goto err1;
2571 2635 }
2572 2636
2573 2637 if (args->object.name == NULL || *(args->object.name) == '\0') {
2574 2638 resp->status = NFS3ERR_ACCES;
2575 2639 goto err1;
2576 2640 }
2577 2641
2578 2642 if (rdonly(ro, vp)) {
2579 2643 resp->status = NFS3ERR_ROFS;
2580 2644 goto err1;
2581 2645 }
2582 2646
2583 2647 if (is_system_labeled()) {
2584 2648 bslabel_t *clabel = req->rq_label;
2585 2649
2586 2650 ASSERT(clabel != NULL);
2587 2651 DTRACE_PROBE2(tx__rfs3__log__info__opremovedir__clabel, char *,
2588 2652 "got client label from request(1)", struct svc_req *, req);
2589 2653
2590 2654 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2591 2655 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2592 2656 exi)) {
2593 2657 resp->status = NFS3ERR_ACCES;
2594 2658 goto err1;
2595 2659 }
2596 2660 }
2597 2661 }
|
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
2598 2662
2599 2663 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2600 2664 name = nfscmd_convname(ca, exi, args->object.name,
2601 2665 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2602 2666
2603 2667 if (name == NULL) {
2604 2668 resp->status = NFS3ERR_INVAL;
2605 2669 goto err1;
2606 2670 }
2607 2671
2608 - error = VOP_RMDIR(vp, name, rootdir, cr, NULL, 0);
2672 + error = VOP_RMDIR(vp, name, ZONE_ROOTVP(), cr, NULL, 0);
2609 2673
2610 2674 if (name != args->object.name)
2611 2675 kmem_free(name, MAXPATHLEN + 1);
2612 2676
2613 2677 ava.va_mask = AT_ALL;
2614 2678 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2615 2679
2616 2680 /*
2617 2681 * Force modified data and metadata out to stable storage.
2618 2682 */
2619 2683 (void) VOP_FSYNC(vp, 0, cr, NULL);
2620 2684
2621 2685 if (error) {
2622 2686 /*
2623 2687 * System V defines rmdir to return EEXIST, not ENOTEMPTY,
2624 2688 * if the directory is not empty. A System V NFS server
2625 2689 * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
2626 2690 * over the wire.
2627 2691 */
2628 2692 if (error == EEXIST)
2629 2693 error = ENOTEMPTY;
2630 2694 goto err;
2631 2695 }
2632 2696
2633 2697 resp->status = NFS3_OK;
2634 2698 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2635 2699 goto out;
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
2636 2700
2637 2701 err:
2638 2702 if (curthread->t_flag & T_WOULDBLOCK) {
2639 2703 curthread->t_flag &= ~T_WOULDBLOCK;
2640 2704 resp->status = NFS3ERR_JUKEBOX;
2641 2705 } else
2642 2706 resp->status = puterrno3(error);
2643 2707 err1:
2644 2708 vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2645 2709 out:
2646 - DTRACE_NFSV3_4(op__rmdir__done, struct svc_req *, req,
2647 - cred_t *, cr, vnode_t *, vp, RMDIR3res *, resp);
2710 + DTRACE_NFSV3_5(op__rmdir__done, struct svc_req *, req,
2711 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
2712 + RMDIR3res *, resp);
2648 2713 if (vp != NULL)
2649 2714 VN_RELE(vp);
2650 2715
2651 2716 }
2652 2717
2653 2718 void *
2654 2719 rfs3_rmdir_getfh(RMDIR3args *args)
2655 2720 {
2656 -
2657 2721 return (&args->object.dir);
2658 2722 }
2659 2723
2660 2724 void
2661 2725 rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi,
2662 2726 struct svc_req *req, cred_t *cr, bool_t ro)
2663 2727 {
2664 2728 int error = 0;
2665 2729 vnode_t *fvp;
2666 2730 vnode_t *tvp;
2667 2731 vnode_t *targvp;
2668 2732 struct vattr *fbvap;
2669 2733 struct vattr fbva;
2670 2734 struct vattr *favap;
2671 2735 struct vattr fava;
2672 2736 struct vattr *tbvap;
2673 2737 struct vattr tbva;
2674 2738 struct vattr *tavap;
2675 2739 struct vattr tava;
2676 2740 nfs_fh3 *fh3;
2677 2741 struct exportinfo *to_exi;
2678 2742 vnode_t *srcvp = NULL;
2679 2743 bslabel_t *clabel;
2680 2744 struct sockaddr *ca;
2681 2745 char *name = NULL;
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
2682 2746 char *toname = NULL;
2683 2747
2684 2748 fbvap = NULL;
2685 2749 favap = NULL;
2686 2750 tbvap = NULL;
2687 2751 tavap = NULL;
2688 2752 tvp = NULL;
2689 2753
2690 2754 fvp = nfs3_fhtovp(&args->from.dir, exi);
2691 2755
2692 - DTRACE_NFSV3_4(op__rename__start, struct svc_req *, req,
2693 - cred_t *, cr, vnode_t *, fvp, RENAME3args *, args);
2756 + DTRACE_NFSV3_5(op__rename__start, struct svc_req *, req,
2757 + cred_t *, cr, vnode_t *, fvp, struct exportinfo *, exi,
2758 + RENAME3args *, args);
2694 2759
2695 2760 if (fvp == NULL) {
2696 2761 error = ESTALE;
2697 2762 goto err;
2698 2763 }
2699 2764
2700 2765 if (is_system_labeled()) {
2701 2766 clabel = req->rq_label;
2702 2767 ASSERT(clabel != NULL);
2703 2768 DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *,
2704 2769 "got client label from request(1)", struct svc_req *, req);
2705 2770
2706 2771 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2707 2772 if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK,
2708 2773 exi)) {
2709 2774 resp->status = NFS3ERR_ACCES;
2710 2775 goto err1;
2711 2776 }
2712 2777 }
2713 2778 }
2714 2779
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
2715 2780 fbva.va_mask = AT_ALL;
2716 2781 fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
2717 2782 favap = fbvap;
2718 2783
2719 2784 fh3 = &args->to.dir;
2720 2785 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
2721 2786 if (to_exi == NULL) {
2722 2787 resp->status = NFS3ERR_ACCES;
2723 2788 goto err1;
2724 2789 }
2725 - exi_rele(to_exi);
2790 + exi_rele(&to_exi);
2726 2791
2727 2792 if (to_exi != exi) {
2728 2793 resp->status = NFS3ERR_XDEV;
2729 2794 goto err1;
2730 2795 }
2731 2796
2732 2797 tvp = nfs3_fhtovp(&args->to.dir, exi);
2733 2798 if (tvp == NULL) {
2734 2799 error = ESTALE;
2735 2800 goto err;
2736 2801 }
2737 2802
2738 2803 tbva.va_mask = AT_ALL;
2739 2804 tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
2740 2805 tavap = tbvap;
2741 2806
2742 2807 if (fvp->v_type != VDIR || tvp->v_type != VDIR) {
2743 2808 resp->status = NFS3ERR_NOTDIR;
2744 2809 goto err1;
2745 2810 }
2746 2811
2747 2812 if (args->from.name == nfs3nametoolong ||
2748 2813 args->to.name == nfs3nametoolong) {
2749 2814 resp->status = NFS3ERR_NAMETOOLONG;
2750 2815 goto err1;
2751 2816 }
2752 2817 if (args->from.name == NULL || *(args->from.name) == '\0' ||
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
2753 2818 args->to.name == NULL || *(args->to.name) == '\0') {
2754 2819 resp->status = NFS3ERR_ACCES;
2755 2820 goto err1;
2756 2821 }
2757 2822
2758 2823 if (rdonly(ro, tvp)) {
2759 2824 resp->status = NFS3ERR_ROFS;
2760 2825 goto err1;
2761 2826 }
2762 2827
2828 + if (protect_zfs_mntpt(tvp) != 0) {
2829 + resp->status = NFS3ERR_ACCES;
2830 + goto err1;
2831 + }
2832 +
2763 2833 if (is_system_labeled()) {
2764 2834 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2765 2835 if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK,
2766 2836 exi)) {
2767 2837 resp->status = NFS3ERR_ACCES;
2768 2838 goto err1;
2769 2839 }
2770 2840 }
2771 2841 }
2772 2842
2773 2843 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2774 2844 name = nfscmd_convname(ca, exi, args->from.name,
2775 2845 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2776 2846
2777 2847 if (name == NULL) {
2778 2848 resp->status = NFS3ERR_INVAL;
2779 2849 goto err1;
2780 2850 }
2781 2851
2782 2852 toname = nfscmd_convname(ca, exi, args->to.name,
2783 2853 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2784 2854
2785 2855 if (toname == NULL) {
2786 2856 resp->status = NFS3ERR_INVAL;
2787 2857 goto err1;
2788 2858 }
2789 2859
2790 2860 /*
2791 2861 * Check for a conflict with a non-blocking mandatory share
2792 2862 * reservation or V4 delegations.
2793 2863 */
2794 2864 error = VOP_LOOKUP(fvp, name, &srcvp, NULL, 0,
2795 2865 NULL, cr, NULL, NULL, NULL);
2796 2866 if (error != 0)
2797 2867 goto err;
2798 2868
2799 2869 /*
|
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
2800 2870 * If we rename a delegated file we should recall the
2801 2871 * delegation, since future opens should fail or would
2802 2872 * refer to a new file.
2803 2873 */
2804 2874 if (rfs4_check_delegated(FWRITE, srcvp, FALSE)) {
2805 2875 resp->status = NFS3ERR_JUKEBOX;
2806 2876 goto err1;
2807 2877 }
2808 2878
2809 2879 /*
2810 - * Check for renaming over a delegated file. Check rfs4_deleg_policy
2880 + * Check for renaming over a delegated file. Check nfs4_deleg_policy
2811 2881 * first to avoid VOP_LOOKUP if possible.
2812 2882 */
2813 - if (rfs4_deleg_policy != SRV_NEVER_DELEGATE &&
2883 + if (nfs4_get_deleg_policy() != SRV_NEVER_DELEGATE &&
2814 2884 VOP_LOOKUP(tvp, toname, &targvp, NULL, 0, NULL, cr,
2815 2885 NULL, NULL, NULL) == 0) {
2816 2886
2817 2887 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
2818 2888 VN_RELE(targvp);
2819 2889 resp->status = NFS3ERR_JUKEBOX;
2820 2890 goto err1;
2821 2891 }
2822 2892 VN_RELE(targvp);
2823 2893 }
2824 2894
2825 2895 if (!nbl_need_check(srcvp)) {
2826 2896 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
2827 2897 } else {
2828 2898 nbl_start_crit(srcvp, RW_READER);
2829 2899 if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL))
2830 2900 error = EACCES;
2831 2901 else
2832 2902 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
2833 2903 nbl_end_crit(srcvp);
2834 2904 }
2835 2905 if (error == 0)
2836 2906 vn_renamepath(tvp, srcvp, args->to.name,
2837 2907 strlen(args->to.name));
2838 2908 VN_RELE(srcvp);
2839 2909 srcvp = NULL;
2840 2910
2841 2911 fava.va_mask = AT_ALL;
2842 2912 favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
2843 2913 tava.va_mask = AT_ALL;
2844 2914 tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
2845 2915
2846 2916 /*
2847 2917 * Force modified data and metadata out to stable storage.
2848 2918 */
2849 2919 (void) VOP_FSYNC(fvp, 0, cr, NULL);
2850 2920 (void) VOP_FSYNC(tvp, 0, cr, NULL);
2851 2921
2852 2922 if (error)
2853 2923 goto err;
2854 2924
2855 2925 resp->status = NFS3_OK;
2856 2926 vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc);
2857 2927 vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc);
2858 2928 goto out;
2859 2929
2860 2930 err:
2861 2931 if (curthread->t_flag & T_WOULDBLOCK) {
2862 2932 curthread->t_flag &= ~T_WOULDBLOCK;
2863 2933 resp->status = NFS3ERR_JUKEBOX;
2864 2934 } else {
2865 2935 resp->status = puterrno3(error);
2866 2936 }
|
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
2867 2937 err1:
2868 2938 vattr_to_wcc_data(fbvap, favap, &resp->resfail.fromdir_wcc);
2869 2939 vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc);
2870 2940
2871 2941 out:
2872 2942 if (name != NULL && name != args->from.name)
2873 2943 kmem_free(name, MAXPATHLEN + 1);
2874 2944 if (toname != NULL && toname != args->to.name)
2875 2945 kmem_free(toname, MAXPATHLEN + 1);
2876 2946
2877 - DTRACE_NFSV3_4(op__rename__done, struct svc_req *, req,
2878 - cred_t *, cr, vnode_t *, fvp, RENAME3res *, resp);
2947 + DTRACE_NFSV3_5(op__rename__done, struct svc_req *, req,
2948 + cred_t *, cr, vnode_t *, fvp, struct exportinfo *, exi,
2949 + RENAME3res *, resp);
2879 2950 if (fvp != NULL)
2880 2951 VN_RELE(fvp);
2881 2952 if (tvp != NULL)
2882 2953 VN_RELE(tvp);
2883 2954 }
2884 2955
2885 2956 void *
2886 2957 rfs3_rename_getfh(RENAME3args *args)
2887 2958 {
2888 -
2889 2959 return (&args->from.dir);
2890 2960 }
2891 2961
2892 2962 void
2893 2963 rfs3_link(LINK3args *args, LINK3res *resp, struct exportinfo *exi,
2894 2964 struct svc_req *req, cred_t *cr, bool_t ro)
2895 2965 {
2896 2966 int error;
2897 2967 vnode_t *vp;
2898 2968 vnode_t *dvp;
2899 2969 struct vattr *vap;
2900 2970 struct vattr va;
2901 2971 struct vattr *bvap;
2902 2972 struct vattr bva;
2903 2973 struct vattr *avap;
2904 2974 struct vattr ava;
2905 2975 nfs_fh3 *fh3;
2906 2976 struct exportinfo *to_exi;
2907 2977 bslabel_t *clabel;
|
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
2908 2978 struct sockaddr *ca;
2909 2979 char *name = NULL;
2910 2980
2911 2981 vap = NULL;
2912 2982 bvap = NULL;
2913 2983 avap = NULL;
2914 2984 dvp = NULL;
2915 2985
2916 2986 vp = nfs3_fhtovp(&args->file, exi);
2917 2987
2918 - DTRACE_NFSV3_4(op__link__start, struct svc_req *, req,
2919 - cred_t *, cr, vnode_t *, vp, LINK3args *, args);
2988 + DTRACE_NFSV3_5(op__link__start, struct svc_req *, req,
2989 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
2990 + LINK3args *, args);
2920 2991
2921 2992 if (vp == NULL) {
2922 2993 error = ESTALE;
2923 2994 goto out;
2924 2995 }
2925 2996
2926 2997 va.va_mask = AT_ALL;
2927 2998 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2928 2999
2929 3000 fh3 = &args->link.dir;
2930 3001 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
2931 3002 if (to_exi == NULL) {
2932 3003 resp->status = NFS3ERR_ACCES;
2933 3004 goto out1;
2934 3005 }
2935 - exi_rele(to_exi);
3006 + exi_rele(&to_exi);
2936 3007
2937 3008 if (to_exi != exi) {
2938 3009 resp->status = NFS3ERR_XDEV;
2939 3010 goto out1;
2940 3011 }
2941 3012
2942 3013 if (is_system_labeled()) {
2943 3014 clabel = req->rq_label;
2944 3015
2945 3016 ASSERT(clabel != NULL);
2946 3017 DTRACE_PROBE2(tx__rfs3__log__info__oplink__clabel, char *,
2947 3018 "got client label from request(1)", struct svc_req *, req);
2948 3019
2949 3020 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2950 3021 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
2951 3022 exi)) {
2952 3023 resp->status = NFS3ERR_ACCES;
2953 3024 goto out1;
2954 3025 }
2955 3026 }
2956 3027 }
2957 3028
2958 3029 dvp = nfs3_fhtovp(&args->link.dir, exi);
2959 3030 if (dvp == NULL) {
2960 3031 error = ESTALE;
2961 3032 goto out;
2962 3033 }
2963 3034
2964 3035 bva.va_mask = AT_ALL;
2965 3036 bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
2966 3037
2967 3038 if (dvp->v_type != VDIR) {
2968 3039 resp->status = NFS3ERR_NOTDIR;
2969 3040 goto out1;
2970 3041 }
2971 3042
2972 3043 if (args->link.name == nfs3nametoolong) {
2973 3044 resp->status = NFS3ERR_NAMETOOLONG;
2974 3045 goto out1;
2975 3046 }
2976 3047
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
2977 3048 if (args->link.name == NULL || *(args->link.name) == '\0') {
2978 3049 resp->status = NFS3ERR_ACCES;
2979 3050 goto out1;
2980 3051 }
2981 3052
2982 3053 if (rdonly(ro, dvp)) {
2983 3054 resp->status = NFS3ERR_ROFS;
2984 3055 goto out1;
2985 3056 }
2986 3057
3058 + if (protect_zfs_mntpt(dvp) != 0) {
3059 + resp->status = NFS3ERR_ACCES;
3060 + goto out1;
3061 + }
3062 +
2987 3063 if (is_system_labeled()) {
2988 3064 DTRACE_PROBE2(tx__rfs3__log__info__oplinkdir__clabel, char *,
2989 3065 "got client label from request(1)", struct svc_req *, req);
2990 3066
2991 3067 if (!blequal(&l_admin_low->tsl_label, clabel)) {
2992 3068 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2993 3069 exi)) {
2994 3070 resp->status = NFS3ERR_ACCES;
2995 3071 goto out1;
2996 3072 }
2997 3073 }
2998 3074 }
2999 3075
3000 3076 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3001 3077 name = nfscmd_convname(ca, exi, args->link.name,
3002 3078 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3003 3079
3004 3080 if (name == NULL) {
3005 3081 resp->status = NFS3ERR_SERVERFAULT;
3006 3082 goto out1;
3007 3083 }
3008 3084
3009 3085 error = VOP_LINK(dvp, vp, name, cr, NULL, 0);
3010 3086
3011 3087 va.va_mask = AT_ALL;
3012 3088 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3013 3089 ava.va_mask = AT_ALL;
3014 3090 avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
3015 3091
3016 3092 /*
3017 3093 * Force modified data and metadata out to stable storage.
3018 3094 */
3019 3095 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3020 3096 (void) VOP_FSYNC(dvp, 0, cr, NULL);
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
3021 3097
3022 3098 if (error)
3023 3099 goto out;
3024 3100
3025 3101 VN_RELE(dvp);
3026 3102
3027 3103 resp->status = NFS3_OK;
3028 3104 vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
3029 3105 vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc);
3030 3106
3031 - DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3032 - cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3107 + DTRACE_NFSV3_5(op__link__done, struct svc_req *, req,
3108 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3109 + LINK3res *, resp);
3033 3110
3034 3111 VN_RELE(vp);
3035 3112
3036 3113 return;
3037 3114
3038 3115 out:
3039 3116 if (curthread->t_flag & T_WOULDBLOCK) {
3040 3117 curthread->t_flag &= ~T_WOULDBLOCK;
3041 3118 resp->status = NFS3ERR_JUKEBOX;
3042 3119 } else
3043 3120 resp->status = puterrno3(error);
3044 3121 out1:
3045 3122 if (name != NULL && name != args->link.name)
3046 3123 kmem_free(name, MAXPATHLEN + 1);
3047 3124
3048 - DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3049 - cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3125 + DTRACE_NFSV3_5(op__link__done, struct svc_req *, req,
3126 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3127 + LINK3res *, resp);
3050 3128
3051 3129 if (vp != NULL)
3052 3130 VN_RELE(vp);
3053 3131 if (dvp != NULL)
3054 3132 VN_RELE(dvp);
3055 3133 vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
3056 3134 vattr_to_wcc_data(bvap, avap, &resp->resfail.linkdir_wcc);
3057 3135 }
3058 3136
3059 3137 void *
3060 3138 rfs3_link_getfh(LINK3args *args)
3061 3139 {
3062 -
3063 3140 return (&args->file);
3064 3141 }
3065 3142
3066 -/*
3067 - * This macro defines the size of a response which contains attribute
3068 - * information and one directory entry (whose length is specified by
3069 - * the macro parameter). If the incoming request is larger than this,
3070 - * then we are guaranteed to be able to return at one directory entry
3071 - * if one exists. Therefore, we do not need to check for
3072 - * NFS3ERR_TOOSMALL if the requested size is larger then this. If it
3073 - * is not, then we need to check to make sure that this error does not
3074 - * need to be returned.
3075 - *
3076 - * NFS3_READDIR_MIN_COUNT is comprised of following :
3077 - *
3078 - * status - 1 * BYTES_PER_XDR_UNIT
3079 - * attr. flag - 1 * BYTES_PER_XDR_UNIT
3080 - * cookie verifier - 2 * BYTES_PER_XDR_UNIT
3081 - * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
3082 - * boolean - 1 * BYTES_PER_XDR_UNIT
3083 - * file id - 2 * BYTES_PER_XDR_UNIT
3084 - * directory name length - 1 * BYTES_PER_XDR_UNIT
3085 - * cookie - 2 * BYTES_PER_XDR_UNIT
3086 - * end of list - 1 * BYTES_PER_XDR_UNIT
3087 - * end of file - 1 * BYTES_PER_XDR_UNIT
3088 - * Name length of directory to the nearest byte
3089 - */
3143 +#ifdef nextdp
3144 +#undef nextdp
3145 +#endif
3146 +#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
3090 3147
3091 -#define NFS3_READDIR_MIN_COUNT(length) \
3092 - ((1 + 1 + 2 + NFS3_SIZEOF_FATTR3 + 1 + 2 + 1 + 2 + 1 + 1) * \
3093 - BYTES_PER_XDR_UNIT + roundup((length), BYTES_PER_XDR_UNIT))
3094 -
3095 3148 /* ARGSUSED */
3096 3149 void
3097 3150 rfs3_readdir(READDIR3args *args, READDIR3res *resp, struct exportinfo *exi,
3098 3151 struct svc_req *req, cred_t *cr, bool_t ro)
3099 3152 {
3100 3153 int error;
3101 3154 vnode_t *vp;
3102 3155 struct vattr *vap;
3103 3156 struct vattr va;
3104 3157 struct iovec iov;
3105 3158 struct uio uio;
3106 - char *data;
3107 3159 int iseof;
3108 - int bufsize;
3109 - int namlen;
3110 - uint_t count;
3111 - struct sockaddr *ca;
3112 3160
3113 - vap = NULL;
3161 + count3 count = args->count;
3162 + count3 size; /* size of the READDIR3resok structure */
3114 3163
3164 + size_t datasz;
3165 + char *data = NULL;
3166 + dirent64_t *dp;
3167 +
3168 + struct sockaddr *ca;
3169 + entry3 **eptr;
3170 + entry3 *entry;
3171 +
3115 3172 vp = nfs3_fhtovp(&args->dir, exi);
3116 3173
3117 - DTRACE_NFSV3_4(op__readdir__start, struct svc_req *, req,
3118 - cred_t *, cr, vnode_t *, vp, READDIR3args *, args);
3174 + DTRACE_NFSV3_5(op__readdir__start, struct svc_req *, req,
3175 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3176 + READDIR3args *, args);
3119 3177
3120 3178 if (vp == NULL) {
3121 - error = ESTALE;
3122 - goto out;
3179 + resp->status = NFS3ERR_STALE;
3180 + vap = NULL;
3181 + goto out1;
3123 3182 }
3124 3183
3184 + if (vp->v_type != VDIR) {
3185 + resp->status = NFS3ERR_NOTDIR;
3186 + vap = NULL;
3187 + goto out1;
3188 + }
3189 +
3125 3190 if (is_system_labeled()) {
3126 3191 bslabel_t *clabel = req->rq_label;
3127 3192
3128 3193 ASSERT(clabel != NULL);
3129 3194 DTRACE_PROBE2(tx__rfs3__log__info__opreaddir__clabel, char *,
3130 3195 "got client label from request(1)", struct svc_req *, req);
3131 3196
3132 3197 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3133 3198 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3134 3199 exi)) {
3135 3200 resp->status = NFS3ERR_ACCES;
3201 + vap = NULL;
3136 3202 goto out1;
3137 3203 }
3138 3204 }
3139 3205 }
3140 3206
3141 3207 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3142 3208
3143 3209 va.va_mask = AT_ALL;
3144 3210 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3145 3211
3146 - if (vp->v_type != VDIR) {
3147 - resp->status = NFS3ERR_NOTDIR;
3148 - goto out1;
3149 - }
3150 -
3151 3212 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3152 3213 if (error)
3153 3214 goto out;
3154 3215
3155 3216 /*
3156 - * Now don't allow arbitrary count to alloc;
3157 - * allow the maximum not to exceed rfs3_tsize()
3217 + * Don't allow arbitrary counts for allocation
3158 3218 */
3159 - if (args->count > rfs3_tsize(req))
3160 - args->count = rfs3_tsize(req);
3219 + if (count > rfs3_tsize(req))
3220 + count = rfs3_tsize(req);
3161 3221
3162 3222 /*
3223 + * struct READDIR3resok:
3224 + * dir_attributes: 1 + NFS3_SIZEOF_FATTR3
3225 + * cookieverf: 2
3226 + * entries (bool): 1
3227 + * eof: 1
3228 + */
3229 + size = (1 + NFS3_SIZEOF_FATTR3 + 2 + 1 + 1) * BYTES_PER_XDR_UNIT;
3230 +
3231 + if (size > count) {
3232 + resp->status = NFS3ERR_TOOSMALL;
3233 + goto out1;
3234 + }
3235 +
3236 + /*
3237 + * This is simplification. The dirent64_t size is not the same as the
3238 + * size of XDR representation of entry3, but the sizes are similar so
3239 + * we'll assume they are same. This assumption should not cause any
3240 + * harm. In worst case we will need to issue VOP_READDIR() once more.
3241 + */
3242 + datasz = count;
3243 +
3244 + /*
3163 3245 * Make sure that there is room to read at least one entry
3164 3246 * if any are available.
3165 3247 */
3166 - if (args->count < DIRENT64_RECLEN(MAXNAMELEN))
3167 - count = DIRENT64_RECLEN(MAXNAMELEN);
3168 - else
3169 - count = args->count;
3248 + if (datasz < DIRENT64_RECLEN(MAXNAMELEN))
3249 + datasz = DIRENT64_RECLEN(MAXNAMELEN);
3170 3250
3171 - data = kmem_alloc(count, KM_SLEEP);
3251 + data = kmem_alloc(datasz, KM_NOSLEEP);
3252 + if (data == NULL) {
3253 + /* The allocation failed; downsize and wait for it this time */
3254 + if (datasz > MAXBSIZE)
3255 + datasz = MAXBSIZE;
3256 + data = kmem_alloc(datasz, KM_SLEEP);
3257 + }
3172 3258
3173 - iov.iov_base = data;
3174 - iov.iov_len = count;
3175 3259 uio.uio_iov = &iov;
3176 3260 uio.uio_iovcnt = 1;
3177 3261 uio.uio_segflg = UIO_SYSSPACE;
3178 3262 uio.uio_extflg = UIO_COPY_CACHED;
3179 3263 uio.uio_loffset = (offset_t)args->cookie;
3180 - uio.uio_resid = count;
3264 + uio.uio_resid = datasz;
3181 3265
3182 - error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
3266 + ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3267 + eptr = &resp->resok.reply.entries;
3268 + entry = NULL;
3183 3269
3184 - va.va_mask = AT_ALL;
3185 - vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3270 +getmoredents:
3271 + iov.iov_base = data;
3272 + iov.iov_len = datasz;
3186 3273
3274 + error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
3187 3275 if (error) {
3188 - kmem_free(data, count);
3189 - goto out;
3276 + iseof = 0;
3277 + goto done;
3190 3278 }
3191 3279
3192 - /*
3193 - * If the count was not large enough to be able to guarantee
3194 - * to be able to return at least one entry, then need to
3195 - * check to see if NFS3ERR_TOOSMALL should be returned.
3196 - */
3197 - if (args->count < NFS3_READDIR_MIN_COUNT(MAXNAMELEN)) {
3198 - /*
3199 - * bufsize is used to keep track of the size of the response.
3200 - * It is primed with:
3201 - * 1 for the status +
3202 - * 1 for the dir_attributes.attributes boolean +
3203 - * 2 for the cookie verifier
3204 - * all times BYTES_PER_XDR_UNIT to convert from XDR units
3205 - * to bytes. If there are directory attributes to be
3206 - * returned, then:
3207 - * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
3208 - * time BYTES_PER_XDR_UNIT is added to account for them.
3209 - */
3210 - bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
3211 - if (vap != NULL)
3212 - bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
3213 - /*
3214 - * An entry is composed of:
3215 - * 1 for the true/false list indicator +
3216 - * 2 for the fileid +
3217 - * 1 for the length of the name +
3218 - * 2 for the cookie +
3219 - * all times BYTES_PER_XDR_UNIT to convert from
3220 - * XDR units to bytes, plus the length of the name
3221 - * rounded up to the nearest BYTES_PER_XDR_UNIT.
3222 - */
3223 - if (count != uio.uio_resid) {
3224 - namlen = strlen(((struct dirent64 *)data)->d_name);
3225 - bufsize += (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
3226 - roundup(namlen, BYTES_PER_XDR_UNIT);
3280 + if (iov.iov_len == datasz)
3281 + goto done;
3282 +
3283 + for (dp = (dirent64_t *)data; (char *)dp - data < datasz - iov.iov_len;
3284 + dp = nextdp(dp)) {
3285 + char *name;
3286 + count3 esize;
3287 +
3288 + if (dp->d_ino == 0) {
3289 + if (entry != NULL)
3290 + entry->cookie = (cookie3)dp->d_off;
3291 + continue;
3227 3292 }
3293 +
3294 + name = nfscmd_convname(ca, exi, dp->d_name,
3295 + NFSCMD_CONV_OUTBOUND, MAXPATHLEN + 1);
3296 + if (name == NULL) {
3297 + if (entry != NULL)
3298 + entry->cookie = (cookie3)dp->d_off;
3299 + continue;
3300 + }
3301 +
3228 3302 /*
3229 - * We need to check to see if the number of bytes left
3230 - * to go into the buffer will actually fit into the
3231 - * buffer. This is calculated as the size of this
3232 - * entry plus:
3233 - * 1 for the true/false list indicator +
3234 - * 1 for the eof indicator
3235 - * times BYTES_PER_XDR_UNIT to convert from from
3236 - * XDR units to bytes.
3303 + * struct entry3:
3304 + * fileid: 2
3305 + * name (length): 1
3306 + * name (data): length (rounded up)
3307 + * cookie: 2
3308 + * nextentry (bool): 1
3237 3309 */
3238 - bufsize += (1 + 1) * BYTES_PER_XDR_UNIT;
3239 - if (bufsize > args->count) {
3240 - kmem_free(data, count);
3241 - resp->status = NFS3ERR_TOOSMALL;
3242 - goto out1;
3310 + esize = (2 + 1 + 2 + 1) * BYTES_PER_XDR_UNIT +
3311 + RNDUP(strlen(name));
3312 +
3313 + /* If the new entry does not fit, discard it */
3314 + if (esize > count - size) {
3315 + if (name != dp->d_name)
3316 + kmem_free(name, MAXPATHLEN + 1);
3317 + iseof = 0;
3318 + goto done;
3243 3319 }
3320 +
3321 + entry = kmem_alloc(sizeof (entry3), KM_SLEEP);
3322 +
3323 + entry->fileid = (fileid3)dp->d_ino;
3324 + entry->name = strdup(name);
3325 + if (name != dp->d_name)
3326 + kmem_free(name, MAXPATHLEN + 1);
3327 + entry->cookie = (cookie3)dp->d_off;
3328 +
3329 + size += esize;
3330 +
3331 + /* Add the entry to the linked list */
3332 + *eptr = entry;
3333 + eptr = &entry->nextentry;
3244 3334 }
3245 3335
3246 - /*
3247 - * Have a valid readir buffer for the native character
3248 - * set. Need to check if a conversion is necessary and
3249 - * potentially rewrite the whole buffer. Note that if the
3250 - * conversion expands names enough, the structure may not
3251 - * fit. In this case, we need to drop entries until if fits
3252 - * and patch the counts in order that the next readdir will
3253 - * get the correct entries.
3254 - */
3255 - ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3256 - data = nfscmd_convdirent(ca, exi, data, count, &resp->status);
3336 + if (!iseof && size < count) {
3337 + uio.uio_resid = MIN(datasz, MAXBSIZE);
3338 + goto getmoredents;
3339 + }
3257 3340
3341 +done:
3342 + *eptr = NULL;
3258 3343
3344 + va.va_mask = AT_ALL;
3345 + vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3346 +
3347 + if (!iseof && resp->resok.reply.entries == NULL) {
3348 + if (error)
3349 + goto out;
3350 + resp->status = NFS3ERR_TOOSMALL;
3351 + goto out1;
3352 + }
3353 +
3259 3354 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3260 3355
3261 3356 #if 0 /* notyet */
3262 3357 /*
3263 3358 * Don't do this. It causes local disk writes when just
3264 3359 * reading the file and the overhead is deemed larger
3265 3360 * than the benefit.
3266 3361 */
3267 3362 /*
3268 3363 * Force modified metadata out to stable storage.
3269 3364 */
3270 3365 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3271 3366 #endif
3272 3367
3273 3368 resp->status = NFS3_OK;
3274 - vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
3275 3369 resp->resok.cookieverf = 0;
3276 - resp->resok.reply.entries = (entry3 *)data;
3277 - resp->resok.reply.eof = iseof;
3278 - resp->resok.size = count - uio.uio_resid;
3279 - resp->resok.count = args->count;
3280 - resp->resok.freecount = count;
3370 + resp->resok.reply.eof = iseof ? TRUE : FALSE;
3281 3371
3282 - DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
3283 - cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
3372 + vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
3284 3373
3374 + DTRACE_NFSV3_5(op__readdir__done, struct svc_req *, req,
3375 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3376 + READDIR3res *, resp);
3377 +
3285 3378 VN_RELE(vp);
3286 3379
3380 + if (data != NULL)
3381 + kmem_free(data, datasz);
3382 +
3287 3383 return;
3288 3384
3289 3385 out:
3290 3386 if (curthread->t_flag & T_WOULDBLOCK) {
3291 3387 curthread->t_flag &= ~T_WOULDBLOCK;
3292 3388 resp->status = NFS3ERR_JUKEBOX;
3293 3389 } else
3294 3390 resp->status = puterrno3(error);
3295 3391 out1:
3296 - DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
3297 - cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
3392 + vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
3298 3393
3394 + DTRACE_NFSV3_5(op__readdir__done, struct svc_req *, req,
3395 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3396 + READDIR3res *, resp);
3397 +
3299 3398 if (vp != NULL) {
3300 3399 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3301 3400 VN_RELE(vp);
3302 3401 }
3303 - vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
3402 +
3403 + if (data != NULL)
3404 + kmem_free(data, datasz);
3304 3405 }
3305 3406
3306 3407 void *
3307 3408 rfs3_readdir_getfh(READDIR3args *args)
3308 3409 {
3309 -
3310 3410 return (&args->dir);
3311 3411 }
3312 3412
3313 3413 void
3314 3414 rfs3_readdir_free(READDIR3res *resp)
3315 3415 {
3416 + if (resp->status == NFS3_OK) {
3417 + entry3 *entry, *nentry;
3316 3418
3317 - if (resp->status == NFS3_OK)
3318 - kmem_free(resp->resok.reply.entries, resp->resok.freecount);
3419 + for (entry = resp->resok.reply.entries; entry != NULL;
3420 + entry = nentry) {
3421 + nentry = entry->nextentry;
3422 + strfree(entry->name);
3423 + kmem_free(entry, sizeof (entry3));
3424 + }
3425 + }
3319 3426 }
3320 3427
3321 3428 #ifdef nextdp
3322 3429 #undef nextdp
3323 3430 #endif
3324 3431 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
3325 3432
3326 -/*
3327 - * This macro computes the size of a response which contains
3328 - * one directory entry including the attributes as well as file handle.
3329 - * If the incoming request is larger than this, then we are guaranteed to be
3330 - * able to return at least one more directory entry if one exists.
3331 - *
3332 - * NFS3_READDIRPLUS_ENTRY is made up of the following:
3333 - *
3334 - * boolean - 1 * BYTES_PER_XDR_UNIT
3335 - * file id - 2 * BYTES_PER_XDR_UNIT
3336 - * directory name length - 1 * BYTES_PER_XDR_UNIT
3337 - * cookie - 2 * BYTES_PER_XDR_UNIT
3338 - * attribute flag - 1 * BYTES_PER_XDR_UNIT
3339 - * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
3340 - * status byte for file handle - 1 * BYTES_PER_XDR_UNIT
3341 - * length of a file handle - 1 * BYTES_PER_XDR_UNIT
3342 - * Maximum length of a file handle (NFS3_MAXFHSIZE)
3343 - * name length of the entry to the nearest bytes
3344 - */
3345 -#define NFS3_READDIRPLUS_ENTRY(namelen) \
3346 - ((1 + 2 + 1 + 2 + 1 + NFS3_SIZEOF_FATTR3 + 1 + 1) * \
3347 - BYTES_PER_XDR_UNIT + \
3348 - NFS3_MAXFHSIZE + roundup(namelen, BYTES_PER_XDR_UNIT))
3349 -
3350 -static int rfs3_readdir_unit = MAXBSIZE;
3351 -
3352 3433 /* ARGSUSED */
3353 3434 void
3354 3435 rfs3_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *resp,
3355 3436 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
3356 3437 {
3357 3438 int error;
3358 3439 vnode_t *vp;
3359 3440 struct vattr *vap;
3360 3441 struct vattr va;
3361 3442 struct iovec iov;
3362 3443 struct uio uio;
3363 - char *data;
3364 3444 int iseof;
3365 - struct dirent64 *dp;
3366 - vnode_t *nvp;
3367 - struct vattr *nvap;
3368 - struct vattr nva;
3369 - entryplus3_info *infop = NULL;
3370 - int size = 0;
3371 - int nents = 0;
3372 - int bufsize = 0;
3373 - int entrysize = 0;
3374 - int tofit = 0;
3375 - int rd_unit = rfs3_readdir_unit;
3376 - int prev_len;
3377 - int space_left;
3378 - int i;
3379 - uint_t *namlen = NULL;
3380 - char *ndata = NULL;
3381 - struct sockaddr *ca;
3382 - size_t ret;
3383 3445
3384 - vap = NULL;
3446 + count3 dircount = args->dircount;
3447 + count3 maxcount = args->maxcount;
3448 + count3 dirsize = 0;
3449 + count3 size; /* size of the READDIRPLUS3resok structure */
3385 3450
3451 + size_t datasz;
3452 + char *data = NULL;
3453 + dirent64_t *dp;
3454 +
3455 + struct sockaddr *ca;
3456 + entryplus3 **eptr;
3457 + entryplus3 *entry;
3458 +
3386 3459 vp = nfs3_fhtovp(&args->dir, exi);
3387 3460
3388 - DTRACE_NFSV3_4(op__readdirplus__start, struct svc_req *, req,
3389 - cred_t *, cr, vnode_t *, vp, READDIRPLUS3args *, args);
3461 + DTRACE_NFSV3_5(op__readdirplus__start, struct svc_req *, req,
3462 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3463 + READDIRPLUS3args *, args);
3390 3464
3391 3465 if (vp == NULL) {
3392 - error = ESTALE;
3393 - goto out;
3466 + resp->status = NFS3ERR_STALE;
3467 + vap = NULL;
3468 + goto out1;
3394 3469 }
3395 3470
3471 + if (vp->v_type != VDIR) {
3472 + resp->status = NFS3ERR_NOTDIR;
3473 + vap = NULL;
3474 + goto out1;
3475 + }
3476 +
3396 3477 if (is_system_labeled()) {
3397 3478 bslabel_t *clabel = req->rq_label;
3398 3479
3399 3480 ASSERT(clabel != NULL);
3400 3481 DTRACE_PROBE2(tx__rfs3__log__info__opreaddirplus__clabel,
3401 3482 char *, "got client label from request(1)",
3402 3483 struct svc_req *, req);
3403 3484
3404 3485 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3405 3486 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3406 3487 exi)) {
3407 3488 resp->status = NFS3ERR_ACCES;
3489 + vap = NULL;
3408 3490 goto out1;
3409 3491 }
3410 3492 }
3411 3493 }
3412 3494
3413 3495 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3414 3496
3415 3497 va.va_mask = AT_ALL;
3416 3498 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3417 3499
3418 - if (vp->v_type != VDIR) {
3419 - error = ENOTDIR;
3420 - goto out;
3421 - }
3422 -
3423 3500 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3424 3501 if (error)
3425 3502 goto out;
3426 3503
3427 3504 /*
3428 3505 * Don't allow arbitrary counts for allocation
3429 3506 */
3430 - if (args->maxcount > rfs3_tsize(req))
3431 - args->maxcount = rfs3_tsize(req);
3507 + if (maxcount > rfs3_tsize(req))
3508 + maxcount = rfs3_tsize(req);
3432 3509
3433 3510 /*
3434 - * Make sure that there is room to read at least one entry
3435 - * if any are available
3511 + * struct READDIRPLUS3resok:
3512 + * dir_attributes: 1 + NFS3_SIZEOF_FATTR3
3513 + * cookieverf: 2
3514 + * entries (bool): 1
3515 + * eof: 1
3436 3516 */
3437 - args->dircount = MIN(args->dircount, args->maxcount);
3517 + size = (1 + NFS3_SIZEOF_FATTR3 + 2 + 1 + 1) * BYTES_PER_XDR_UNIT;
3438 3518
3439 - if (args->dircount < DIRENT64_RECLEN(MAXNAMELEN))
3440 - args->dircount = DIRENT64_RECLEN(MAXNAMELEN);
3519 + if (size > maxcount) {
3520 + resp->status = NFS3ERR_TOOSMALL;
3521 + goto out1;
3522 + }
3441 3523
3442 3524 /*
3443 - * This allocation relies on a minimum directory entry
3444 - * being roughly 24 bytes. Therefore, the namlen array
3445 - * will have enough space based on the maximum number of
3446 - * entries to read.
3525 + * This is simplification. The dirent64_t size is not the same as the
3526 + * size of XDR representation of entryplus3 (excluding attributes and
3527 + * handle), but the sizes are similar so we'll assume they are same.
3528 + * This assumption should not cause any harm. In worst case we will
3529 + * need to issue VOP_READDIR() once more.
3447 3530 */
3448 - namlen = kmem_alloc(args->dircount, KM_SLEEP);
3449 3531
3450 - space_left = args->dircount;
3451 - data = kmem_alloc(args->dircount, KM_SLEEP);
3452 - dp = (struct dirent64 *)data;
3532 + datasz = MIN(dircount, maxcount);
3533 +
3534 + /*
3535 + * Make sure that there is room to read at least one entry
3536 + * if any are available.
3537 + */
3538 + if (datasz < DIRENT64_RECLEN(MAXNAMELEN))
3539 + datasz = DIRENT64_RECLEN(MAXNAMELEN);
3540 +
3541 + data = kmem_alloc(datasz, KM_NOSLEEP);
3542 + if (data == NULL) {
3543 + /* The allocation failed; downsize and wait for it this time */
3544 + if (datasz > MAXBSIZE)
3545 + datasz = MAXBSIZE;
3546 + data = kmem_alloc(datasz, KM_SLEEP);
3547 + }
3548 +
3453 3549 uio.uio_iov = &iov;
3454 3550 uio.uio_iovcnt = 1;
3455 3551 uio.uio_segflg = UIO_SYSSPACE;
3456 3552 uio.uio_extflg = UIO_COPY_CACHED;
3457 3553 uio.uio_loffset = (offset_t)args->cookie;
3554 + uio.uio_resid = datasz;
3458 3555
3459 - /*
3460 - * bufsize is used to keep track of the size of the response as we
3461 - * get post op attributes and filehandles for each entry. This is
3462 - * an optimization as the server may have read more entries than will
3463 - * fit in the buffer specified by maxcount. We stop calculating
3464 - * post op attributes and filehandles once we have exceeded maxcount.
3465 - * This will minimize the effect of truncation.
3466 - *
3467 - * It is primed with:
3468 - * 1 for the status +
3469 - * 1 for the dir_attributes.attributes boolean +
3470 - * 2 for the cookie verifier
3471 - * all times BYTES_PER_XDR_UNIT to convert from XDR units
3472 - * to bytes. If there are directory attributes to be
3473 - * returned, then:
3474 - * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
3475 - * time BYTES_PER_XDR_UNIT is added to account for them.
3476 - */
3477 - bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
3478 - if (vap != NULL)
3479 - bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
3556 + ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3557 + eptr = &resp->resok.reply.entries;
3558 + entry = NULL;
3480 3559
3481 3560 getmoredents:
3482 - /*
3483 - * Here we make a check so that our read unit is not larger than
3484 - * the space left in the buffer.
3485 - */
3486 - rd_unit = MIN(rd_unit, space_left);
3487 - iov.iov_base = (char *)dp;
3488 - iov.iov_len = rd_unit;
3489 - uio.uio_resid = rd_unit;
3490 - prev_len = rd_unit;
3561 + iov.iov_base = data;
3562 + iov.iov_len = datasz;
3491 3563
3492 3564 error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
3493 -
3494 3565 if (error) {
3495 - kmem_free(data, args->dircount);
3496 - goto out;
3566 + iseof = 0;
3567 + goto done;
3497 3568 }
3498 3569
3499 - if (uio.uio_resid == prev_len && !iseof) {
3500 - if (nents == 0) {
3501 - kmem_free(data, args->dircount);
3502 - resp->status = NFS3ERR_TOOSMALL;
3503 - goto out1;
3504 - }
3570 + if (iov.iov_len == datasz)
3571 + goto done;
3505 3572
3506 - /*
3507 - * We could not get any more entries, so get the attributes
3508 - * and filehandle for the entries already obtained.
3509 - */
3510 - goto good;
3511 - }
3573 + for (dp = (dirent64_t *)data; (char *)dp - data < datasz - iov.iov_len;
3574 + dp = nextdp(dp)) {
3575 + char *name;
3576 + vnode_t *nvp;
3577 + count3 edirsize;
3578 + count3 esize;
3512 3579
3513 - /*
3514 - * We estimate the size of the response by assuming the
3515 - * entry exists and attributes and filehandle are also valid
3516 - */
3517 - for (size = prev_len - uio.uio_resid;
3518 - size > 0;
3519 - size -= dp->d_reclen, dp = nextdp(dp)) {
3520 -
3521 3580 if (dp->d_ino == 0) {
3522 - nents++;
3581 + if (entry != NULL)
3582 + entry->cookie = (cookie3)dp->d_off;
3523 3583 continue;
3524 3584 }
3525 3585
3526 - namlen[nents] = strlen(dp->d_name);
3527 - entrysize = NFS3_READDIRPLUS_ENTRY(namlen[nents]);
3586 + name = nfscmd_convname(ca, exi, dp->d_name,
3587 + NFSCMD_CONV_OUTBOUND, MAXPATHLEN + 1);
3588 + if (name == NULL) {
3589 + if (entry != NULL)
3590 + entry->cookie = (cookie3)dp->d_off;
3591 + continue;
3592 + }
3528 3593
3529 3594 /*
3530 - * We need to check to see if the number of bytes left
3531 - * to go into the buffer will actually fit into the
3532 - * buffer. This is calculated as the size of this
3533 - * entry plus:
3534 - * 1 for the true/false list indicator +
3535 - * 1 for the eof indicator
3536 - * times BYTES_PER_XDR_UNIT to convert from XDR units
3537 - * to bytes.
3538 - *
3539 - * Also check the dircount limit against the first entry read
3540 - *
3595 + * struct entryplus3:
3596 + * fileid: 2
3597 + * name (length): 1
3598 + * name (data): length (rounded up)
3599 + * cookie: 2
3541 3600 */
3542 - tofit = entrysize + (1 + 1) * BYTES_PER_XDR_UNIT;
3543 - if (bufsize + tofit > args->maxcount) {
3544 - /*
3545 - * We make a check here to see if this was the
3546 - * first entry being measured. If so, then maxcount
3547 - * was too small to begin with and so we need to
3548 - * return with NFS3ERR_TOOSMALL.
3549 - */
3550 - if (nents == 0) {
3551 - kmem_free(data, args->dircount);
3552 - resp->status = NFS3ERR_TOOSMALL;
3553 - goto out1;
3554 - }
3555 - iseof = FALSE;
3556 - goto good;
3601 + edirsize = (2 + 1 + 2) * BYTES_PER_XDR_UNIT +
3602 + RNDUP(strlen(name));
3603 +
3604 + /*
3605 + * struct entryplus3:
3606 + * attributes_follow: 1
3607 + * handle_follows: 1
3608 + * nextentry (bool): 1
3609 + */
3610 + esize = edirsize + (1 + 1 + 1) * BYTES_PER_XDR_UNIT;
3611 +
3612 + /* If the new entry does not fit, we are done */
3613 + if (edirsize > dircount - dirsize || esize > maxcount - size) {
3614 + if (name != dp->d_name)
3615 + kmem_free(name, MAXPATHLEN + 1);
3616 + iseof = 0;
3617 + error = 0;
3618 + goto done;
3557 3619 }
3558 - bufsize += entrysize;
3559 - nents++;
3560 - }
3561 3620
3562 - /*
3563 - * If there is enough room to fit at least 1 more entry including
3564 - * post op attributes and filehandle in the buffer AND that we haven't
3565 - * exceeded dircount then go back and get some more.
3566 - */
3567 - if (!iseof &&
3568 - (args->maxcount - bufsize) >= NFS3_READDIRPLUS_ENTRY(MAXNAMELEN)) {
3569 - space_left -= (prev_len - uio.uio_resid);
3570 - if (space_left >= DIRENT64_RECLEN(MAXNAMELEN))
3571 - goto getmoredents;
3621 + entry = kmem_alloc(sizeof (entryplus3), KM_SLEEP);
3572 3622
3573 - /* else, fall through */
3574 - }
3575 -good:
3576 - va.va_mask = AT_ALL;
3577 - vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3623 + entry->fileid = (fileid3)dp->d_ino;
3624 + entry->name = strdup(name);
3625 + if (name != dp->d_name)
3626 + kmem_free(name, MAXPATHLEN + 1);
3627 + entry->cookie = (cookie3)dp->d_off;
3578 3628
3579 - VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3629 + error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr,
3630 + NULL, NULL, NULL);
3631 + if (error) {
3632 + entry->name_attributes.attributes = FALSE;
3633 + entry->name_handle.handle_follows = FALSE;
3634 + } else {
3635 + struct vattr nva;
3636 + struct vattr *nvap;
3580 3637
3581 - infop = kmem_alloc(nents * sizeof (struct entryplus3_info), KM_SLEEP);
3582 - resp->resok.infop = infop;
3638 + nva.va_mask = AT_ALL;
3639 + nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL :
3640 + &nva;
3583 3641
3584 - dp = (struct dirent64 *)data;
3585 - for (i = 0; i < nents; i++) {
3642 + /* Lie about the object type for a referral */
3643 + if (nvap != NULL && vn_is_nfs_reparse(nvp, cr))
3644 + nvap->va_type = VLNK;
3586 3645
3587 - if (dp->d_ino == 0) {
3588 - infop[i].attr.attributes = FALSE;
3589 - infop[i].fh.handle_follows = FALSE;
3590 - dp = nextdp(dp);
3591 - continue;
3592 - }
3646 + if (vn_ismntpt(nvp)) {
3647 + entry->name_attributes.attributes = FALSE;
3648 + entry->name_handle.handle_follows = FALSE;
3649 + } else {
3650 + vattr_to_post_op_attr(nvap,
3651 + &entry->name_attributes);
3593 3652
3594 - infop[i].namelen = namlen[i];
3653 + error = makefh3(&entry->name_handle.handle, nvp,
3654 + exi);
3655 + if (!error)
3656 + entry->name_handle.handle_follows =
3657 + TRUE;
3658 + else
3659 + entry->name_handle.handle_follows =
3660 + FALSE;
3661 + }
3595 3662
3596 - error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr,
3597 - NULL, NULL, NULL);
3598 - if (error) {
3599 - infop[i].attr.attributes = FALSE;
3600 - infop[i].fh.handle_follows = FALSE;
3601 - dp = nextdp(dp);
3602 - continue;
3663 + VN_RELE(nvp);
3603 3664 }
3604 3665
3605 - nva.va_mask = AT_ALL;
3606 - nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL : &nva;
3666 + /*
3667 + * struct entryplus3 (optionally):
3668 + * attributes: NFS3_SIZEOF_FATTR3
3669 + * handle length: 1
3670 + * handle data: length (rounded up)
3671 + */
3672 + if (entry->name_attributes.attributes == TRUE)
3673 + esize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
3674 + if (entry->name_handle.handle_follows == TRUE)
3675 + esize += 1 * BYTES_PER_XDR_UNIT +
3676 + RNDUP(entry->name_handle.handle.fh3_length);
3607 3677
3608 - /* Lie about the object type for a referral */
3609 - if (vn_is_nfs_reparse(nvp, cr))
3610 - nvap->va_type = VLNK;
3678 + /* If the new entry does not fit, discard it */
3679 + if (esize > maxcount - size) {
3680 + strfree(entry->name);
3681 + kmem_free(entry, sizeof (entryplus3));
3682 + iseof = 0;
3683 + error = 0;
3684 + goto done;
3685 + }
3611 3686
3612 - vattr_to_post_op_attr(nvap, &infop[i].attr);
3687 + dirsize += edirsize;
3688 + size += esize;
3613 3689
3614 - error = makefh3(&infop[i].fh.handle, nvp, exi);
3615 - if (!error)
3616 - infop[i].fh.handle_follows = TRUE;
3617 - else
3618 - infop[i].fh.handle_follows = FALSE;
3690 + /* Add the entry to the linked list */
3691 + *eptr = entry;
3692 + eptr = &entry->nextentry;
3693 + }
3619 3694
3620 - VN_RELE(nvp);
3621 - dp = nextdp(dp);
3695 + if (!iseof && dirsize < dircount && size < maxcount) {
3696 + uio.uio_resid = MIN(datasz, MAXBSIZE);
3697 + goto getmoredents;
3622 3698 }
3623 3699
3624 - ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3625 - ret = nfscmd_convdirplus(ca, exi, data, nents, args->dircount, &ndata);
3626 - if (ndata == NULL)
3627 - ndata = data;
3700 +done:
3701 + *eptr = NULL;
3628 3702
3629 - if (ret > 0) {
3630 - /*
3631 - * We had to drop one or more entries in order to fit
3632 - * during the character conversion. We need to patch
3633 - * up the size and eof info.
3634 - */
3635 - if (iseof)
3636 - iseof = FALSE;
3703 + va.va_mask = AT_ALL;
3704 + vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3637 3705
3638 - ret = nfscmd_dropped_entrysize((struct dirent64 *)data,
3639 - nents, ret);
3706 + if (!iseof && resp->resok.reply.entries == NULL) {
3707 + if (error)
3708 + goto out;
3709 + resp->status = NFS3ERR_TOOSMALL;
3710 + goto out1;
3640 3711 }
3641 3712
3713 + VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3642 3714
3643 3715 #if 0 /* notyet */
3644 3716 /*
3645 3717 * Don't do this. It causes local disk writes when just
3646 3718 * reading the file and the overhead is deemed larger
3647 3719 * than the benefit.
3648 3720 */
3649 3721 /*
3650 3722 * Force modified metadata out to stable storage.
3651 3723 */
3652 3724 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3653 3725 #endif
3654 3726
3655 - kmem_free(namlen, args->dircount);
3656 -
3657 3727 resp->status = NFS3_OK;
3658 - vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
3659 3728 resp->resok.cookieverf = 0;
3660 - resp->resok.reply.entries = (entryplus3 *)ndata;
3661 - resp->resok.reply.eof = iseof;
3662 - resp->resok.size = nents;
3663 - resp->resok.count = args->dircount - ret;
3664 - resp->resok.maxcount = args->maxcount;
3729 + resp->resok.reply.eof = iseof ? TRUE : FALSE;
3665 3730
3666 - DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
3667 - cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
3668 - if (ndata != data)
3669 - kmem_free(data, args->dircount);
3731 + vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
3670 3732
3733 + DTRACE_NFSV3_5(op__readdirplus__done, struct svc_req *, req,
3734 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3735 + READDIRPLUS3res *, resp);
3671 3736
3672 3737 VN_RELE(vp);
3673 3738
3739 + if (data != NULL)
3740 + kmem_free(data, datasz);
3741 +
3674 3742 return;
3675 3743
3676 3744 out:
3677 3745 if (curthread->t_flag & T_WOULDBLOCK) {
3678 3746 curthread->t_flag &= ~T_WOULDBLOCK;
3679 3747 resp->status = NFS3ERR_JUKEBOX;
3680 3748 } else {
3681 3749 resp->status = puterrno3(error);
3682 3750 }
3683 3751 out1:
3684 - DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
3685 - cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
3752 + vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
3686 3753
3754 + DTRACE_NFSV3_5(op__readdirplus__done, struct svc_req *, req,
3755 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3756 + READDIRPLUS3res *, resp);
3757 +
3687 3758 if (vp != NULL) {
3688 3759 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3689 3760 VN_RELE(vp);
3690 3761 }
3691 3762
3692 - if (namlen != NULL)
3693 - kmem_free(namlen, args->dircount);
3694 -
3695 - vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
3763 + if (data != NULL)
3764 + kmem_free(data, datasz);
3696 3765 }
3697 3766
3698 3767 void *
3699 3768 rfs3_readdirplus_getfh(READDIRPLUS3args *args)
3700 3769 {
3701 -
3702 3770 return (&args->dir);
3703 3771 }
3704 3772
3705 3773 void
3706 3774 rfs3_readdirplus_free(READDIRPLUS3res *resp)
3707 3775 {
3708 -
3709 3776 if (resp->status == NFS3_OK) {
3710 - kmem_free(resp->resok.reply.entries, resp->resok.count);
3711 - kmem_free(resp->resok.infop,
3712 - resp->resok.size * sizeof (struct entryplus3_info));
3777 + entryplus3 *entry, *nentry;
3778 +
3779 + for (entry = resp->resok.reply.entries; entry != NULL;
3780 + entry = nentry) {
3781 + nentry = entry->nextentry;
3782 + strfree(entry->name);
3783 + kmem_free(entry, sizeof (entryplus3));
3784 + }
3713 3785 }
3714 3786 }
3715 3787
3716 3788 /* ARGSUSED */
3717 3789 void
3718 3790 rfs3_fsstat(FSSTAT3args *args, FSSTAT3res *resp, struct exportinfo *exi,
3719 3791 struct svc_req *req, cred_t *cr, bool_t ro)
3720 3792 {
3721 3793 int error;
3722 3794 vnode_t *vp;
3723 3795 struct vattr *vap;
3724 3796 struct vattr va;
3725 3797 struct statvfs64 sb;
3726 3798
3727 3799 vap = NULL;
3728 3800
3729 3801 vp = nfs3_fhtovp(&args->fsroot, exi);
3730 3802
3731 - DTRACE_NFSV3_4(op__fsstat__start, struct svc_req *, req,
3732 - cred_t *, cr, vnode_t *, vp, FSSTAT3args *, args);
3803 + DTRACE_NFSV3_5(op__fsstat__start, struct svc_req *, req,
3804 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3805 + FSSTAT3args *, args);
3733 3806
3734 3807 if (vp == NULL) {
3735 3808 error = ESTALE;
3736 3809 goto out;
3737 3810 }
3738 3811
3739 3812 if (is_system_labeled()) {
3740 3813 bslabel_t *clabel = req->rq_label;
3741 3814
3742 3815 ASSERT(clabel != NULL);
3743 3816 DTRACE_PROBE2(tx__rfs3__log__info__opfsstat__clabel, char *,
3744 3817 "got client label from request(1)", struct svc_req *, req);
3745 3818
3746 3819 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3747 3820 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3748 3821 exi)) {
3749 3822 resp->status = NFS3ERR_ACCES;
3750 3823 goto out1;
3751 3824 }
3752 3825 }
3753 3826 }
3754 3827
3755 3828 error = VFS_STATVFS(vp->v_vfsp, &sb);
3756 3829
3757 3830 va.va_mask = AT_ALL;
3758 3831 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3759 3832
3760 3833 if (error)
3761 3834 goto out;
3762 3835
3763 3836 resp->status = NFS3_OK;
3764 3837 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
3765 3838 if (sb.f_blocks != (fsblkcnt64_t)-1)
3766 3839 resp->resok.tbytes = (size3)sb.f_frsize * (size3)sb.f_blocks;
3767 3840 else
3768 3841 resp->resok.tbytes = (size3)sb.f_blocks;
3769 3842 if (sb.f_bfree != (fsblkcnt64_t)-1)
3770 3843 resp->resok.fbytes = (size3)sb.f_frsize * (size3)sb.f_bfree;
3771 3844 else
|
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
3772 3845 resp->resok.fbytes = (size3)sb.f_bfree;
3773 3846 if (sb.f_bavail != (fsblkcnt64_t)-1)
3774 3847 resp->resok.abytes = (size3)sb.f_frsize * (size3)sb.f_bavail;
3775 3848 else
3776 3849 resp->resok.abytes = (size3)sb.f_bavail;
3777 3850 resp->resok.tfiles = (size3)sb.f_files;
3778 3851 resp->resok.ffiles = (size3)sb.f_ffree;
3779 3852 resp->resok.afiles = (size3)sb.f_favail;
3780 3853 resp->resok.invarsec = 0;
3781 3854
3782 - DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
3783 - cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
3855 + DTRACE_NFSV3_5(op__fsstat__done, struct svc_req *, req,
3856 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3857 + FSSTAT3res *, resp);
3784 3858 VN_RELE(vp);
3785 3859
3786 3860 return;
3787 3861
3788 3862 out:
3789 3863 if (curthread->t_flag & T_WOULDBLOCK) {
3790 3864 curthread->t_flag &= ~T_WOULDBLOCK;
3791 3865 resp->status = NFS3ERR_JUKEBOX;
3792 3866 } else
3793 3867 resp->status = puterrno3(error);
3794 3868 out1:
3795 - DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
3796 - cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
3869 + DTRACE_NFSV3_5(op__fsstat__done, struct svc_req *, req,
3870 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3871 + FSSTAT3res *, resp);
3797 3872
3798 3873 if (vp != NULL)
3799 3874 VN_RELE(vp);
3800 3875 vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
3801 3876 }
3802 3877
3803 3878 void *
3804 3879 rfs3_fsstat_getfh(FSSTAT3args *args)
3805 3880 {
3806 -
3807 3881 return (&args->fsroot);
3808 3882 }
3809 3883
3810 3884 /* ARGSUSED */
3811 3885 void
3812 3886 rfs3_fsinfo(FSINFO3args *args, FSINFO3res *resp, struct exportinfo *exi,
3813 3887 struct svc_req *req, cred_t *cr, bool_t ro)
3814 3888 {
3815 3889 vnode_t *vp;
3816 3890 struct vattr *vap;
3817 3891 struct vattr va;
3818 3892 uint32_t xfer_size;
3819 3893 ulong_t l = 0;
3820 3894 int error;
3821 3895
3822 3896 vp = nfs3_fhtovp(&args->fsroot, exi);
3823 3897
3824 - DTRACE_NFSV3_4(op__fsinfo__start, struct svc_req *, req,
3825 - cred_t *, cr, vnode_t *, vp, FSINFO3args *, args);
3898 + DTRACE_NFSV3_5(op__fsinfo__start, struct svc_req *, req,
3899 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3900 + FSINFO3args *, args);
3826 3901
3827 3902 if (vp == NULL) {
3828 3903 if (curthread->t_flag & T_WOULDBLOCK) {
3829 3904 curthread->t_flag &= ~T_WOULDBLOCK;
3830 3905 resp->status = NFS3ERR_JUKEBOX;
3831 3906 } else
3832 3907 resp->status = NFS3ERR_STALE;
3833 3908 vattr_to_post_op_attr(NULL, &resp->resfail.obj_attributes);
3834 3909 goto out;
3835 3910 }
3836 3911
3837 3912 if (is_system_labeled()) {
3838 3913 bslabel_t *clabel = req->rq_label;
3839 3914
3840 3915 ASSERT(clabel != NULL);
3841 3916 DTRACE_PROBE2(tx__rfs3__log__info__opfsinfo__clabel, char *,
3842 3917 "got client label from request(1)", struct svc_req *, req);
3843 3918
3844 3919 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3845 3920 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3846 3921 exi)) {
3847 3922 resp->status = NFS3ERR_STALE;
3848 3923 vattr_to_post_op_attr(NULL,
3849 3924 &resp->resfail.obj_attributes);
3850 3925 goto out;
3851 3926 }
3852 3927 }
3853 3928 }
3854 3929
3855 3930 va.va_mask = AT_ALL;
3856 3931 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3857 3932
3858 3933 resp->status = NFS3_OK;
3859 3934 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
3860 3935 xfer_size = rfs3_tsize(req);
3861 3936 resp->resok.rtmax = xfer_size;
3862 3937 resp->resok.rtpref = xfer_size;
3863 3938 resp->resok.rtmult = DEV_BSIZE;
3864 3939 resp->resok.wtmax = xfer_size;
3865 3940 resp->resok.wtpref = xfer_size;
3866 3941 resp->resok.wtmult = DEV_BSIZE;
3867 3942 resp->resok.dtpref = MAXBSIZE;
3868 3943
3869 3944 /*
3870 3945 * Large file spec: want maxfilesize based on limit of
3871 3946 * underlying filesystem. We can guess 2^31-1 if need be.
3872 3947 */
3873 3948 error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
3874 3949 if (error) {
3875 3950 resp->status = puterrno3(error);
3876 3951 goto out;
3877 3952 }
3878 3953
3879 3954 /*
3880 3955 * If the underlying file system does not support _PC_FILESIZEBITS,
3881 3956 * return a reasonable default. Note that error code on VOP_PATHCONF
3882 3957 * will be 0, even if the underlying file system does not support
3883 3958 * _PC_FILESIZEBITS.
3884 3959 */
3885 3960 if (l == (ulong_t)-1) {
3886 3961 resp->resok.maxfilesize = MAXOFF32_T;
3887 3962 } else {
3888 3963 if (l >= (sizeof (uint64_t) * 8))
|
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
3889 3964 resp->resok.maxfilesize = INT64_MAX;
3890 3965 else
3891 3966 resp->resok.maxfilesize = (1LL << (l-1)) - 1;
3892 3967 }
3893 3968
3894 3969 resp->resok.time_delta.seconds = 0;
3895 3970 resp->resok.time_delta.nseconds = 1000;
3896 3971 resp->resok.properties = FSF3_LINK | FSF3_SYMLINK |
3897 3972 FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
3898 3973
3899 - DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
3900 - cred_t *, cr, vnode_t *, vp, FSINFO3res *, resp);
3974 + DTRACE_NFSV3_5(op__fsinfo__done, struct svc_req *, req,
3975 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
3976 + FSINFO3res *, resp);
3901 3977
3902 3978 VN_RELE(vp);
3903 3979
3904 3980 return;
3905 3981
3906 3982 out:
3907 - DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
3908 - cred_t *, cr, vnode_t *, NULL, FSINFO3res *, resp);
3983 + DTRACE_NFSV3_5(op__fsinfo__done, struct svc_req *, req,
3984 + cred_t *, cr, vnode_t *, NULL, struct exportinfo *, exi,
3985 + FSINFO3res *, resp);
3909 3986 if (vp != NULL)
3910 3987 VN_RELE(vp);
3911 3988 }
3912 3989
3913 3990 void *
3914 3991 rfs3_fsinfo_getfh(FSINFO3args *args)
3915 3992 {
3916 3993 return (&args->fsroot);
3917 3994 }
3918 3995
3919 3996 /* ARGSUSED */
3920 3997 void
3921 3998 rfs3_pathconf(PATHCONF3args *args, PATHCONF3res *resp, struct exportinfo *exi,
3922 3999 struct svc_req *req, cred_t *cr, bool_t ro)
3923 4000 {
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
3924 4001 int error;
3925 4002 vnode_t *vp;
3926 4003 struct vattr *vap;
3927 4004 struct vattr va;
3928 4005 ulong_t val;
3929 4006
3930 4007 vap = NULL;
3931 4008
3932 4009 vp = nfs3_fhtovp(&args->object, exi);
3933 4010
3934 - DTRACE_NFSV3_4(op__pathconf__start, struct svc_req *, req,
3935 - cred_t *, cr, vnode_t *, vp, PATHCONF3args *, args);
4011 + DTRACE_NFSV3_5(op__pathconf__start, struct svc_req *, req,
4012 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4013 + PATHCONF3args *, args);
3936 4014
3937 4015 if (vp == NULL) {
3938 4016 error = ESTALE;
3939 4017 goto out;
3940 4018 }
3941 4019
3942 4020 if (is_system_labeled()) {
3943 4021 bslabel_t *clabel = req->rq_label;
3944 4022
3945 4023 ASSERT(clabel != NULL);
3946 4024 DTRACE_PROBE2(tx__rfs3__log__info__oppathconf__clabel, char *,
3947 4025 "got client label from request(1)", struct svc_req *, req);
3948 4026
3949 4027 if (!blequal(&l_admin_low->tsl_label, clabel)) {
3950 4028 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3951 4029 exi)) {
3952 4030 resp->status = NFS3ERR_ACCES;
3953 4031 goto out1;
3954 4032 }
3955 4033 }
3956 4034 }
3957 4035
3958 4036 va.va_mask = AT_ALL;
3959 4037 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3960 4038
3961 4039 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &val, cr, NULL);
3962 4040 if (error)
3963 4041 goto out;
3964 4042 resp->resok.info.link_max = (uint32)val;
3965 4043
3966 4044 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &val, cr, NULL);
3967 4045 if (error)
3968 4046 goto out;
3969 4047 resp->resok.info.name_max = (uint32)val;
3970 4048
3971 4049 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &val, cr, NULL);
3972 4050 if (error)
3973 4051 goto out;
3974 4052 if (val == 1)
3975 4053 resp->resok.info.no_trunc = TRUE;
3976 4054 else
3977 4055 resp->resok.info.no_trunc = FALSE;
3978 4056
3979 4057 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &val, cr, NULL);
3980 4058 if (error)
|
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
3981 4059 goto out;
3982 4060 if (val == 1)
3983 4061 resp->resok.info.chown_restricted = TRUE;
3984 4062 else
3985 4063 resp->resok.info.chown_restricted = FALSE;
3986 4064
3987 4065 resp->status = NFS3_OK;
3988 4066 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
3989 4067 resp->resok.info.case_insensitive = FALSE;
3990 4068 resp->resok.info.case_preserving = TRUE;
3991 - DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
3992 - cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
4069 + DTRACE_NFSV3_5(op__pathconf__done, struct svc_req *, req,
4070 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4071 + PATHCONF3res *, resp);
3993 4072 VN_RELE(vp);
3994 4073 return;
3995 4074
3996 4075 out:
3997 4076 if (curthread->t_flag & T_WOULDBLOCK) {
3998 4077 curthread->t_flag &= ~T_WOULDBLOCK;
3999 4078 resp->status = NFS3ERR_JUKEBOX;
4000 4079 } else
4001 4080 resp->status = puterrno3(error);
4002 4081 out1:
4003 - DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
4004 - cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
4082 + DTRACE_NFSV3_5(op__pathconf__done, struct svc_req *, req,
4083 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4084 + PATHCONF3res *, resp);
4005 4085 if (vp != NULL)
4006 4086 VN_RELE(vp);
4007 4087 vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
4008 4088 }
4009 4089
4010 4090 void *
4011 4091 rfs3_pathconf_getfh(PATHCONF3args *args)
4012 4092 {
4013 -
4014 4093 return (&args->object);
4015 4094 }
4016 4095
4017 4096 void
4018 4097 rfs3_commit(COMMIT3args *args, COMMIT3res *resp, struct exportinfo *exi,
4019 4098 struct svc_req *req, cred_t *cr, bool_t ro)
4020 4099 {
4100 + nfs3_srv_t *ns;
4021 4101 int error;
4022 4102 vnode_t *vp;
4023 4103 struct vattr *bvap;
4024 4104 struct vattr bva;
4025 4105 struct vattr *avap;
4026 4106 struct vattr ava;
4027 4107
4028 4108 bvap = NULL;
4029 4109 avap = NULL;
4030 4110
4031 4111 vp = nfs3_fhtovp(&args->file, exi);
4032 4112
4033 - DTRACE_NFSV3_4(op__commit__start, struct svc_req *, req,
4034 - cred_t *, cr, vnode_t *, vp, COMMIT3args *, args);
4113 + DTRACE_NFSV3_5(op__commit__start, struct svc_req *, req,
4114 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4115 + COMMIT3args *, args);
4035 4116
4036 4117 if (vp == NULL) {
4037 4118 error = ESTALE;
4038 4119 goto out;
4039 4120 }
4040 4121
4122 + ns = zone_getspecific(rfs3_zone_key, curzone);
4041 4123 bva.va_mask = AT_ALL;
4042 4124 error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4043 4125
4044 4126 /*
4045 4127 * If we can't get the attributes, then we can't do the
4046 4128 * right access checking. So, we'll fail the request.
4047 4129 */
4048 4130 if (error)
4049 4131 goto out;
4050 4132
4051 4133 bvap = &bva;
4052 4134
4053 4135 if (rdonly(ro, vp)) {
4054 4136 resp->status = NFS3ERR_ROFS;
4055 4137 goto out1;
4056 4138 }
4057 4139
4058 4140 if (vp->v_type != VREG) {
4059 4141 resp->status = NFS3ERR_INVAL;
4060 4142 goto out1;
4061 4143 }
4062 4144
4063 4145 if (is_system_labeled()) {
4064 4146 bslabel_t *clabel = req->rq_label;
4065 4147
4066 4148 ASSERT(clabel != NULL);
4067 4149 DTRACE_PROBE2(tx__rfs3__log__info__opcommit__clabel, char *,
4068 4150 "got client label from request(1)", struct svc_req *, req);
4069 4151
4070 4152 if (!blequal(&l_admin_low->tsl_label, clabel)) {
4071 4153 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4072 4154 exi)) {
4073 4155 resp->status = NFS3ERR_ACCES;
4074 4156 goto out1;
4075 4157 }
4076 4158 }
4077 4159 }
4078 4160
4079 4161 if (crgetuid(cr) != bva.va_uid &&
4080 4162 (error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL)))
4081 4163 goto out;
4082 4164
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
4083 4165 error = VOP_FSYNC(vp, FSYNC, cr, NULL);
4084 4166
4085 4167 ava.va_mask = AT_ALL;
4086 4168 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
4087 4169
4088 4170 if (error)
4089 4171 goto out;
4090 4172
4091 4173 resp->status = NFS3_OK;
4092 4174 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
4093 - resp->resok.verf = write3verf;
4175 + resp->resok.verf = ns->write3verf;
4094 4176
4095 - DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4096 - cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4177 + DTRACE_NFSV3_5(op__commit__done, struct svc_req *, req,
4178 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4179 + COMMIT3res *, resp);
4097 4180
4098 4181 VN_RELE(vp);
4099 4182
4100 4183 return;
4101 4184
4102 4185 out:
4103 4186 if (curthread->t_flag & T_WOULDBLOCK) {
4104 4187 curthread->t_flag &= ~T_WOULDBLOCK;
4105 4188 resp->status = NFS3ERR_JUKEBOX;
4106 4189 } else
4107 4190 resp->status = puterrno3(error);
4108 4191 out1:
4109 - DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4110 - cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4192 + DTRACE_NFSV3_5(op__commit__done, struct svc_req *, req,
4193 + cred_t *, cr, vnode_t *, vp, struct exportinfo *, exi,
4194 + COMMIT3res *, resp);
4111 4195
4112 4196 if (vp != NULL)
4113 4197 VN_RELE(vp);
4114 4198 vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
4115 4199 }
4116 4200
4117 4201 void *
4118 4202 rfs3_commit_getfh(COMMIT3args *args)
4119 4203 {
4120 -
4121 4204 return (&args->file);
4122 4205 }
4123 4206
4124 4207 static int
4125 4208 sattr3_to_vattr(sattr3 *sap, struct vattr *vap)
4126 4209 {
4127 4210
4128 4211 vap->va_mask = 0;
4129 4212
4130 4213 if (sap->mode.set_it) {
4131 4214 vap->va_mode = (mode_t)sap->mode.mode;
4132 4215 vap->va_mask |= AT_MODE;
4133 4216 }
4134 4217 if (sap->uid.set_it) {
4135 4218 vap->va_uid = (uid_t)sap->uid.uid;
4136 4219 vap->va_mask |= AT_UID;
4137 4220 }
4138 4221 if (sap->gid.set_it) {
4139 4222 vap->va_gid = (gid_t)sap->gid.gid;
4140 4223 vap->va_mask |= AT_GID;
4141 4224 }
4142 4225 if (sap->size.set_it) {
4143 4226 if (sap->size.size > (size3)((u_longlong_t)-1))
4144 4227 return (EINVAL);
4145 4228 vap->va_size = sap->size.size;
4146 4229 vap->va_mask |= AT_SIZE;
4147 4230 }
4148 4231 if (sap->atime.set_it == SET_TO_CLIENT_TIME) {
4149 4232 #ifndef _LP64
4150 4233 /* check time validity */
4151 4234 if (!NFS3_TIME_OK(sap->atime.atime.seconds))
4152 4235 return (EOVERFLOW);
4153 4236 #endif
4154 4237 /*
4155 4238 * nfs protocol defines times as unsigned so don't extend sign,
4156 4239 * unless sysadmin set nfs_allow_preepoch_time.
4157 4240 */
4158 4241 NFS_TIME_T_CONVERT(vap->va_atime.tv_sec,
4159 4242 sap->atime.atime.seconds);
4160 4243 vap->va_atime.tv_nsec = (uint32_t)sap->atime.atime.nseconds;
4161 4244 vap->va_mask |= AT_ATIME;
4162 4245 } else if (sap->atime.set_it == SET_TO_SERVER_TIME) {
4163 4246 gethrestime(&vap->va_atime);
4164 4247 vap->va_mask |= AT_ATIME;
4165 4248 }
4166 4249 if (sap->mtime.set_it == SET_TO_CLIENT_TIME) {
4167 4250 #ifndef _LP64
4168 4251 /* check time validity */
4169 4252 if (!NFS3_TIME_OK(sap->mtime.mtime.seconds))
4170 4253 return (EOVERFLOW);
4171 4254 #endif
4172 4255 /*
4173 4256 * nfs protocol defines times as unsigned so don't extend sign,
4174 4257 * unless sysadmin set nfs_allow_preepoch_time.
4175 4258 */
4176 4259 NFS_TIME_T_CONVERT(vap->va_mtime.tv_sec,
4177 4260 sap->mtime.mtime.seconds);
|
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
4178 4261 vap->va_mtime.tv_nsec = (uint32_t)sap->mtime.mtime.nseconds;
4179 4262 vap->va_mask |= AT_MTIME;
4180 4263 } else if (sap->mtime.set_it == SET_TO_SERVER_TIME) {
4181 4264 gethrestime(&vap->va_mtime);
4182 4265 vap->va_mask |= AT_MTIME;
4183 4266 }
4184 4267
4185 4268 return (0);
4186 4269 }
4187 4270
4188 -static ftype3 vt_to_nf3[] = {
4271 +static const ftype3 vt_to_nf3[] = {
4189 4272 0, NF3REG, NF3DIR, NF3BLK, NF3CHR, NF3LNK, NF3FIFO, 0, 0, NF3SOCK, 0
4190 4273 };
4191 4274
4192 4275 static int
4193 4276 vattr_to_fattr3(struct vattr *vap, fattr3 *fap)
4194 4277 {
4195 4278
4196 4279 ASSERT(vap->va_type >= VNON && vap->va_type <= VBAD);
4197 4280 /* Return error if time or size overflow */
4198 4281 if (! (NFS_VAP_TIME_OK(vap) && NFS3_SIZE_OK(vap->va_size))) {
4199 4282 return (EOVERFLOW);
4200 4283 }
4201 4284 fap->type = vt_to_nf3[vap->va_type];
4202 4285 fap->mode = (mode3)(vap->va_mode & MODEMASK);
4203 4286 fap->nlink = (uint32)vap->va_nlink;
4204 4287 if (vap->va_uid == UID_NOBODY)
4205 4288 fap->uid = (uid3)NFS_UID_NOBODY;
4206 4289 else
4207 4290 fap->uid = (uid3)vap->va_uid;
4208 4291 if (vap->va_gid == GID_NOBODY)
4209 4292 fap->gid = (gid3)NFS_GID_NOBODY;
4210 4293 else
4211 4294 fap->gid = (gid3)vap->va_gid;
4212 4295 fap->size = (size3)vap->va_size;
4213 4296 fap->used = (size3)DEV_BSIZE * (size3)vap->va_nblocks;
4214 4297 fap->rdev.specdata1 = (uint32)getmajor(vap->va_rdev);
4215 4298 fap->rdev.specdata2 = (uint32)getminor(vap->va_rdev);
4216 4299 fap->fsid = (uint64)vap->va_fsid;
4217 4300 fap->fileid = (fileid3)vap->va_nodeid;
4218 4301 fap->atime.seconds = vap->va_atime.tv_sec;
4219 4302 fap->atime.nseconds = vap->va_atime.tv_nsec;
4220 4303 fap->mtime.seconds = vap->va_mtime.tv_sec;
4221 4304 fap->mtime.nseconds = vap->va_mtime.tv_nsec;
4222 4305 fap->ctime.seconds = vap->va_ctime.tv_sec;
4223 4306 fap->ctime.nseconds = vap->va_ctime.tv_nsec;
4224 4307 return (0);
4225 4308 }
4226 4309
4227 4310 static int
4228 4311 vattr_to_wcc_attr(struct vattr *vap, wcc_attr *wccap)
4229 4312 {
4230 4313
4231 4314 /* Return error if time or size overflow */
4232 4315 if (!(NFS_TIME_T_OK(vap->va_mtime.tv_sec) &&
4233 4316 NFS_TIME_T_OK(vap->va_ctime.tv_sec) &&
4234 4317 NFS3_SIZE_OK(vap->va_size))) {
4235 4318 return (EOVERFLOW);
4236 4319 }
4237 4320 wccap->size = (size3)vap->va_size;
4238 4321 wccap->mtime.seconds = vap->va_mtime.tv_sec;
4239 4322 wccap->mtime.nseconds = vap->va_mtime.tv_nsec;
4240 4323 wccap->ctime.seconds = vap->va_ctime.tv_sec;
4241 4324 wccap->ctime.nseconds = vap->va_ctime.tv_nsec;
4242 4325 return (0);
4243 4326 }
4244 4327
4245 4328 static void
4246 4329 vattr_to_pre_op_attr(struct vattr *vap, pre_op_attr *poap)
4247 4330 {
4248 4331
4249 4332 /* don't return attrs if time overflow */
4250 4333 if ((vap != NULL) && !vattr_to_wcc_attr(vap, &poap->attr)) {
4251 4334 poap->attributes = TRUE;
4252 4335 } else
4253 4336 poap->attributes = FALSE;
4254 4337 }
4255 4338
4256 4339 void
4257 4340 vattr_to_post_op_attr(struct vattr *vap, post_op_attr *poap)
4258 4341 {
4259 4342
|
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
4260 4343 /* don't return attrs if time overflow */
4261 4344 if ((vap != NULL) && !vattr_to_fattr3(vap, &poap->attr)) {
4262 4345 poap->attributes = TRUE;
4263 4346 } else
4264 4347 poap->attributes = FALSE;
4265 4348 }
4266 4349
4267 4350 static void
4268 4351 vattr_to_wcc_data(struct vattr *bvap, struct vattr *avap, wcc_data *wccp)
4269 4352 {
4270 -
4271 4353 vattr_to_pre_op_attr(bvap, &wccp->before);
4272 4354 vattr_to_post_op_attr(avap, &wccp->after);
4273 4355 }
4274 4356
4275 -void
4276 -rfs3_srvrinit(void)
4357 +static int
4358 +rdma_setup_read_data3(READ3args *args, READ3resok *rok)
4277 4359 {
4360 + struct clist *wcl;
4361 + int wlist_len;
4362 + count3 count = rok->count;
4363 +
4364 + wcl = args->wlist;
4365 + if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE)
4366 + return (FALSE);
4367 +
4368 + wcl = args->wlist;
4369 + rok->wlist_len = wlist_len;
4370 + rok->wlist = wcl;
4371 + return (TRUE);
4372 +}
4373 +
4374 +/* ARGSUSED */
4375 +static void *
4376 +rfs3_zone_init(zoneid_t zoneid)
4377 +{
4378 + nfs3_srv_t *ns;
4278 4379 struct rfs3_verf_overlay {
4279 4380 uint_t id; /* a "unique" identifier */
4280 4381 int ts; /* a unique timestamp */
4281 4382 } *verfp;
4282 4383 timestruc_t now;
4283 4384
4385 + ns = kmem_zalloc(sizeof (*ns), KM_SLEEP);
4386 +
4284 4387 /*
4285 4388 * The following algorithm attempts to find a unique verifier
4286 4389 * to be used as the write verifier returned from the server
4287 4390 * to the client. It is important that this verifier change
4288 4391 * whenever the server reboots. Of secondary importance, it
4289 4392 * is important for the verifier to be unique between two
4290 4393 * different servers.
4291 4394 *
4292 4395 * Thus, an attempt is made to use the system hostid and the
4293 4396 * current time in seconds when the nfssrv kernel module is
4294 4397 * loaded. It is assumed that an NFS server will not be able
4295 4398 * to boot and then to reboot in less than a second. If the
4296 4399 * hostid has not been set, then the current high resolution
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
4297 4400 * time is used. This will ensure different verifiers each
4298 4401 * time the server reboots and minimize the chances that two
4299 4402 * different servers will have the same verifier.
4300 4403 */
4301 4404
4302 4405 #ifndef lint
4303 4406 /*
4304 4407 * We ASSERT that this constant logic expression is
4305 4408 * always true because in the past, it wasn't.
4306 4409 */
4307 - ASSERT(sizeof (*verfp) <= sizeof (write3verf));
4410 + ASSERT(sizeof (*verfp) <= sizeof (ns->write3verf));
4308 4411 #endif
4309 4412
4310 4413 gethrestime(&now);
4311 - verfp = (struct rfs3_verf_overlay *)&write3verf;
4414 + verfp = (struct rfs3_verf_overlay *)&ns->write3verf;
4312 4415 verfp->ts = (int)now.tv_sec;
4313 4416 verfp->id = zone_get_hostid(NULL);
4314 4417
4315 4418 if (verfp->id == 0)
4316 4419 verfp->id = (uint_t)now.tv_nsec;
4317 4420
4318 - nfs3_srv_caller_id = fs_new_caller_id();
4319 -
4421 + return (ns);
4320 4422 }
4321 4423
4322 -static int
4323 -rdma_setup_read_data3(READ3args *args, READ3resok *rok)
4424 +/* ARGSUSED */
4425 +static void
4426 +rfs3_zone_fini(zoneid_t zoneid, void *data)
4324 4427 {
4325 - struct clist *wcl;
4326 - int wlist_len;
4327 - count3 count = rok->count;
4428 + nfs3_srv_t *ns = data;
4328 4429
4329 - wcl = args->wlist;
4330 - if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE) {
4331 - return (FALSE);
4332 - }
4430 + kmem_free(ns, sizeof (*ns));
4431 +}
4333 4432
4334 - wcl = args->wlist;
4335 - rok->wlist_len = wlist_len;
4336 - rok->wlist = wcl;
4337 - return (TRUE);
4433 +void
4434 +rfs3_srvrinit(void)
4435 +{
4436 + nfs3_srv_caller_id = fs_new_caller_id();
4437 + zone_key_create(&rfs3_zone_key, rfs3_zone_init, NULL, rfs3_zone_fini);
4338 4438 }
4339 4439
4340 4440 void
4341 4441 rfs3_srvrfini(void)
4342 4442 {
4343 4443 /* Nothing to do */
4344 4444 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX