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