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