Print this page
Send nfs_export_t to untraverse()
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
+++ new/usr/src/uts/common/fs/nfs/nfs4_srv_attr.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 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Copyright 2018 Nexenta Systems, Inc.
29 29 */
30 30
31 31 #include <sys/systm.h>
32 32 #include <sys/cmn_err.h>
33 33 #include <nfs/nfs.h>
34 34 #include <nfs/export.h>
35 35 #include <nfs/nfs4.h>
36 36 #include <sys/ddi.h>
37 37 #include <sys/door.h>
38 38 #include <sys/sdt.h>
39 39 #include <nfs/nfssys.h>
40 40
41 41 void rfs4_init_compound_state(struct compound_state *);
42 42
43 43 bitmap4 rfs4_supported_attrs;
44 44 int MSG_PRT_DEBUG = FALSE;
45 45
46 46 /* If building with DEBUG enabled, enable mandattr tunable by default */
47 47 #ifdef DEBUG
48 48 #ifndef RFS4_SUPPORT_MANDATTR_ONLY
49 49 #define RFS4_SUPPORT_MANDATTR_ONLY
50 50 #endif
51 51 #endif
52 52
53 53 /*
54 54 * If building with mandattr only code, disable it by default.
55 55 * To enable, set rfs4_mandattr_only in /etc/system and reboot.
56 56 * When building without mandattr ifdef, the compiler should
57 57 * optimize away the the comparisons because RFS4_MANDATTR_ONLY
58 58 * is defined to be 0.
59 59 */
60 60 #ifdef RFS4_SUPPORT_MANDATTR_ONLY
61 61 #define NFS4_LAST_MANDATTR FATTR4_RDATTR_ERROR
62 62 #define RFS4_MANDATTR_ONLY rfs4_mandattr_only
63 63 int rfs4_mandattr_only = 0;
64 64 #else
65 65 #define RFS4_MANDATTR_ONLY 0
66 66 #endif
67 67
68 68
69 69 static void rfs4_ntov_init(void);
70 70 static int rfs4_fattr4_supported_attrs();
71 71 static int rfs4_fattr4_type();
72 72 static int rfs4_fattr4_fh_expire_type();
73 73 static int rfs4_fattr4_change();
74 74 static int rfs4_fattr4_size();
75 75 static int rfs4_fattr4_link_support();
76 76 static int rfs4_fattr4_symlink_support();
77 77 static int rfs4_fattr4_named_attr();
78 78 static int rfs4_fattr4_fsid();
79 79 static int rfs4_fattr4_unique_handles();
80 80 static int rfs4_fattr4_lease_time();
81 81 static int rfs4_fattr4_rdattr_error();
82 82 static int rfs4_fattr4_acl();
83 83 static int rfs4_fattr4_aclsupport();
84 84 static int rfs4_fattr4_archive();
85 85 static int rfs4_fattr4_cansettime();
86 86 static int rfs4_fattr4_case_insensitive();
87 87 static int rfs4_fattr4_case_preserving();
88 88 static int rfs4_fattr4_chown_restricted();
89 89 static int rfs4_fattr4_filehandle();
90 90 static int rfs4_fattr4_fileid();
91 91 static int rfs4_fattr4_files_avail();
92 92 static int rfs4_fattr4_files_free();
93 93 static int rfs4_fattr4_files_total();
94 94 static int rfs4_fattr4_fs_locations();
95 95 static int rfs4_fattr4_hidden();
96 96 static int rfs4_fattr4_homogeneous();
97 97 static int rfs4_fattr4_maxfilesize();
98 98 static int rfs4_fattr4_maxlink();
99 99 static int rfs4_fattr4_maxname();
100 100 static int rfs4_fattr4_maxread();
101 101 static int rfs4_fattr4_maxwrite();
102 102 static int rfs4_fattr4_mimetype();
103 103 static int rfs4_fattr4_mode();
104 104 static int rfs4_fattr4_no_trunc();
105 105 static int rfs4_fattr4_numlinks();
106 106 static int rfs4_fattr4_owner();
107 107 static int rfs4_fattr4_owner_group();
108 108 static int rfs4_fattr4_quota_avail_hard();
109 109 static int rfs4_fattr4_quota_avail_soft();
110 110 static int rfs4_fattr4_quota_used();
111 111 static int rfs4_fattr4_rawdev();
112 112 static int rfs4_fattr4_space_avail();
113 113 static int rfs4_fattr4_space_free();
114 114 static int rfs4_fattr4_space_total();
115 115 static int rfs4_fattr4_space_used();
116 116 static int rfs4_fattr4_system();
117 117 static int rfs4_fattr4_time_access();
118 118 static int rfs4_fattr4_time_access_set();
119 119 static int rfs4_fattr4_time_backup();
120 120 static int rfs4_fattr4_time_create();
121 121 static int rfs4_fattr4_time_delta();
122 122 static int rfs4_fattr4_time_metadata();
123 123 static int rfs4_fattr4_time_modify();
124 124 static int rfs4_fattr4_time_modify_set();
125 125
126 126 /*
127 127 * Initialize the supported attributes
128 128 */
129 129 void
130 130 rfs4_attr_init()
131 131 {
132 132 int i;
133 133 struct nfs4_svgetit_arg sarg;
134 134 struct compound_state cs;
135 135 struct statvfs64 sb;
136 136
137 137 rfs4_init_compound_state(&cs);
138 138 /*
139 139 * This is global state checking, called once. We might be in
140 140 * non-global-zone context here (say a modload happens from a zone
141 141 * process) so in this case, we want the global-zone root vnode.
142 142 */
143 143 cs.vp = rootvp;
144 144 cs.fh.nfs_fh4_val = NULL;
145 145 cs.cr = kcred;
146 146
147 147 /*
148 148 * Get all the supported attributes
149 149 */
150 150 sarg.op = NFS4ATTR_SUPPORTED;
151 151 sarg.cs = &cs;
152 152 sarg.vap->va_mask = AT_ALL;
153 153 sarg.sbp = &sb;
154 154 sarg.flag = 0;
155 155 sarg.rdattr_error = NFS4_OK;
156 156 sarg.rdattr_error_req = FALSE;
157 157 sarg.is_referral = B_FALSE;
158 158
159 159 rfs4_ntov_init();
160 160
161 161 rfs4_supported_attrs = 0;
162 162 for (i = 0; i < NFS4_MAXNUM_ATTRS; i++) {
163 163 #ifdef RFS4_SUPPORT_MANDATTR_ONLY
164 164 if (rfs4_mandattr_only == TRUE && i > NFS4_LAST_MANDATTR)
165 165 continue;
166 166 #endif
167 167 if ((*nfs4_ntov_map[i].sv_getit)(NFS4ATTR_SUPPORTED,
168 168 &sarg, NULL) == 0) {
169 169 rfs4_supported_attrs |= nfs4_ntov_map[i].fbit;
170 170 }
171 171 }
172 172 }
173 173
174 174 /*
175 175 * The following rfs4_fattr4_* functions convert between the fattr4
176 176 * arguments/attributes and the system (e.g. vattr) values. The following
177 177 * commands are currently in use:
178 178 *
179 179 * NFS4ATTR_SUPPORTED: checks if the attribute in question is supported:
180 180 * sarg.op = SUPPORTED - all supported attrs
181 181 * sarg.op = GETIT - only supported readable attrs
182 182 * sarg.op = SETIT - only supported writable attrs
183 183 *
184 184 * NFS4ATTR_GETIT: getattr type conversion - convert system values
185 185 * (e.g. vattr struct) to fattr4 type values to be returned to the
186 186 * user - usually in response to nfsv4 getattr request.
187 187 *
188 188 * NFS4ATTR_SETIT: convert fattr4 type values to system values to use by
189 189 * setattr. Allows only read/write and write attributes,
190 190 * even if not supported by the filesystem. Note that ufs only allows setattr
191 191 * of owner/group, mode, size, atime/mtime.
192 192 *
193 193 * NFS4ATTR_VERIT: convert fattr4 type values to system values to use by
194 194 * verify/nverify. Implemented to allow
195 195 * almost everything that can be returned by getattr into known structs
196 196 * (like vfsstat64 or vattr_t), that is, both read only and read/write attrs.
197 197 * The function will return -1 if it found that the arguments don't match.
198 198 * This applies to system-wide values that don't require a VOP_GETATTR
199 199 * or other further checks to verify. It will return no error if they
200 200 * either match or were retrieved successfully for later checking.
201 201 *
202 202 * NFS4ATTR_FREEIT: free up any space allocated by either of the above.
203 203 * The sargp->op should be either NFS4ATTR_GETIT or NFS4ATTR_SETIT
204 204 * to indicate which op was used to allocate the space.
205 205 *
206 206 * XXX Note: these functions are currently used by the server only. A
207 207 * XXX different method of conversion is used on the client side.
208 208 * XXX Eventually combining the two (possibly by adding NFS4ATTR_CLNT_GETIT
209 209 * XXX and SETIT) may be a cleaner approach.
210 210 */
211 211
212 212 /*
213 213 * Mandatory attributes
214 214 */
215 215
216 216 /* ARGSUSED */
217 217 static int
218 218 rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
219 219 union nfs4_attr_u *na)
220 220 {
221 221 int error = 0;
222 222
223 223 switch (cmd) {
224 224 case NFS4ATTR_SUPPORTED:
225 225 if (sarg->op == NFS4ATTR_SETIT)
226 226 error = EINVAL;
227 227 break; /* this attr is supported */
228 228 case NFS4ATTR_GETIT:
229 229 na->supported_attrs = rfs4_supported_attrs;
230 230 break;
231 231 case NFS4ATTR_SETIT:
232 232 /*
233 233 * read-only attr
234 234 */
235 235 error = EINVAL;
236 236 break;
237 237 case NFS4ATTR_VERIT:
238 238 /*
239 239 * Compare the input bitmap to the server's bitmap
240 240 */
241 241 if (na->supported_attrs != rfs4_supported_attrs) {
242 242 error = -1; /* no match */
243 243 }
244 244 break;
245 245 case NFS4ATTR_FREEIT:
246 246 break;
247 247 }
248 248 return (error);
249 249 }
250 250
251 251 /*
252 252 * Translate vnode vtype to nfsv4_ftype.
253 253 */
254 254 static nfs_ftype4 vt_to_nf4[] = {
255 255 0, NF4REG, NF4DIR, NF4BLK, NF4CHR, NF4LNK, NF4FIFO, 0, 0, NF4SOCK, 0
256 256 };
257 257
258 258 /* ARGSUSED */
259 259 static int
260 260 rfs4_fattr4_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
261 261 union nfs4_attr_u *na)
262 262 {
263 263 int error = 0;
264 264
265 265 switch (cmd) {
266 266 case NFS4ATTR_SUPPORTED:
267 267 if (sarg->op == NFS4ATTR_SETIT)
268 268 error = EINVAL;
269 269 break; /* this attr is supported */
270 270 case NFS4ATTR_GETIT:
271 271 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_TYPE)) {
272 272 error = -1; /* may be okay if rdattr_error */
273 273 break;
274 274 }
275 275 ASSERT(sarg->vap->va_mask & AT_TYPE);
276 276
277 277 /*
278 278 * if xattr flag not set, use v4_to_nf4 mapping;
279 279 * otherwise verify xattr flag is in sync with va_type
280 280 * and set xattr types.
281 281 */
282 282 if (! (sarg->xattr & (FH4_NAMEDATTR | FH4_ATTRDIR)))
283 283 na->type = vt_to_nf4[sarg->vap->va_type];
284 284 else {
285 285 /*
286 286 * FH4 flag was set. Dir type maps to attrdir,
287 287 * and all other types map to namedattr.
288 288 */
289 289 if (sarg->vap->va_type == VDIR)
290 290 na->type = NF4ATTRDIR;
291 291 else
292 292 na->type = NF4NAMEDATTR;
293 293 }
294 294 break;
295 295 case NFS4ATTR_SETIT:
296 296 /*
297 297 * read-only attr
298 298 */
299 299 error = EINVAL;
300 300 break;
301 301 case NFS4ATTR_VERIT:
302 302 /*
303 303 * Compare the input type to the object type on server
304 304 */
305 305 ASSERT(sarg->vap->va_mask & AT_TYPE);
306 306 if (sarg->vap->va_type != nf4_to_vt[na->type])
307 307 error = -1; /* no match */
308 308 break;
309 309 case NFS4ATTR_FREEIT:
310 310 break;
311 311 }
312 312 return (error);
313 313 }
314 314
315 315 /* ARGSUSED */
316 316 static int
317 317 fattr4_get_fh_expire_type(struct exportinfo *exi, uint32_t *fh_expire_typep)
318 318 {
319 319 #ifdef VOLATILE_FH_TEST
320 320 int ex_flags;
321 321
322 322 if (exi == NULL)
323 323 return (ESTALE);
324 324 ex_flags = exi->exi_export.ex_flags;
325 325 if ((ex_flags & (EX_VOLFH | EX_VOLRNM | EX_VOLMIG | EX_NOEXPOPEN))
326 326 == 0) {
327 327 *fh_expire_typep = FH4_PERSISTENT;
328 328 return (0);
329 329 }
330 330 *fh_expire_typep = 0;
331 331
332 332 if (ex_flags & EX_NOEXPOPEN) {
333 333 /* file handles should not expire with open - not used */
334 334 *fh_expire_typep = FH4_NOEXPIRE_WITH_OPEN;
335 335 }
336 336 if (ex_flags & EX_VOLFH) {
337 337 /*
338 338 * file handles may expire any time - on share here.
339 339 * If volatile any, no need to check other flags.
340 340 */
341 341 *fh_expire_typep |= FH4_VOLATILE_ANY;
342 342 return (0);
343 343 }
344 344 if (ex_flags & EX_VOLRNM) {
345 345 /* file handles may expire on rename */
346 346 *fh_expire_typep |= FH4_VOL_RENAME;
347 347 }
348 348 if (ex_flags & EX_VOLMIG) {
349 349 /* file handles may expire on migration - not used */
350 350 *fh_expire_typep |= FH4_VOL_MIGRATION;
351 351 }
352 352 #else /* not VOLATILE_FH_TEST */
353 353 *fh_expire_typep = FH4_PERSISTENT;
354 354 #endif /* VOLATILE_FH_TEST */
355 355
356 356 return (0);
357 357 }
358 358
359 359 /*
360 360 * At this point the only volatile filehandles we allow (for test purposes
361 361 * only) are either fh's that expire when the filesystem is shared (reshared),
362 362 * fh's that expire on a rename and persistent ones.
363 363 */
364 364 /* ARGSUSED */
365 365 static int
366 366 rfs4_fattr4_fh_expire_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
367 367 union nfs4_attr_u *na)
368 368 {
369 369 uint32_t fh_expire_type;
370 370 int error = 0;
371 371
372 372 switch (cmd) {
373 373 case NFS4ATTR_SUPPORTED:
374 374 if (sarg->op == NFS4ATTR_SETIT)
375 375 error = EINVAL;
376 376 break; /* this attr is supported */
377 377 case NFS4ATTR_GETIT:
378 378 error = fattr4_get_fh_expire_type(sarg->cs->exi,
379 379 &na->fh_expire_type);
380 380 break;
381 381 case NFS4ATTR_SETIT:
382 382 /*
383 383 * read-only attr
384 384 */
385 385 error = EINVAL;
386 386 break;
387 387 case NFS4ATTR_VERIT:
388 388 error = fattr4_get_fh_expire_type(sarg->cs->exi,
389 389 &fh_expire_type);
390 390 if (!error && (na->fh_expire_type != fh_expire_type))
391 391 error = -1; /* no match */
392 392 break;
393 393 case NFS4ATTR_FREEIT:
394 394 break;
395 395 }
396 396 return (error);
397 397 }
398 398
399 399 static int
400 400 fattr4_get_change(struct nfs4_svgetit_arg *sarg, fattr4_change *changep)
401 401 {
402 402 vattr_t vap2[1], *vap = sarg->vap;
403 403 struct compound_state *cs = sarg->cs;
404 404 vnode_t *vp = cs->vp;
405 405 nfsstat4 status;
406 406 timespec_t vis_change;
407 407
408 408 if ((vap->va_mask & AT_CTIME) == 0) {
409 409 if (sarg->rdattr_error && (vp == NULL)) {
410 410 return (-1); /* may be okay if rdattr_error */
411 411 }
412 412 ASSERT(vp != NULL);
413 413 vap = vap2;
414 414 vap->va_mask = AT_CTIME;
415 415 status = rfs4_vop_getattr(vp, vap, 0, cs->cr);
416 416 if (status != NFS4_OK)
417 417 return (geterrno4(status));
418 418 }
419 419 NFS4_SET_FATTR4_CHANGE(*changep, vap->va_ctime);
420 420
421 421 if (nfs_visible_change(cs->exi, vp, &vis_change)) {
422 422 fattr4_change visch;
423 423 NFS4_SET_FATTR4_CHANGE(visch, vis_change);
424 424 if (visch > *changep)
425 425 *changep = visch;
426 426 }
427 427
428 428 return (0);
429 429 }
430 430
431 431 /* ARGSUSED */
432 432 static int
433 433 rfs4_fattr4_change(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
434 434 union nfs4_attr_u *na)
435 435 {
436 436 int error = 0;
437 437 fattr4_change change;
438 438 uint_t mask;
439 439 vattr_t *vap = sarg->vap;
440 440
441 441 switch (cmd) {
442 442 case NFS4ATTR_SUPPORTED:
443 443 if (sarg->op == NFS4ATTR_SETIT)
444 444 error = EINVAL;
445 445 break; /* this attr is supported */
446 446 case NFS4ATTR_GETIT:
447 447 error = fattr4_get_change(sarg, &na->change);
448 448 break;
449 449 case NFS4ATTR_SETIT:
450 450 /*
451 451 * read-only attr
452 452 */
453 453 error = EINVAL;
454 454 break;
455 455 case NFS4ATTR_VERIT:
456 456 mask = vap->va_mask;
457 457 vap->va_mask &= ~AT_CTIME; /* force a VOP_GETATTR */
458 458 error = fattr4_get_change(sarg, &change);
459 459 vap->va_mask = mask;
460 460 if (!error && (na->change != change))
461 461 error = -1;
462 462 break;
463 463 case NFS4ATTR_FREEIT:
464 464 break;
465 465 }
466 466 return (error);
467 467 }
468 468
469 469 /* ARGSUSED */
470 470 static int
471 471 rfs4_fattr4_size(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
472 472 union nfs4_attr_u *na)
473 473 {
474 474 int error = 0;
475 475
476 476 switch (cmd) {
477 477 case NFS4ATTR_SUPPORTED:
478 478 break; /* this attr is supported */
479 479 case NFS4ATTR_GETIT:
480 480 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_SIZE)) {
481 481 error = -1; /* may be okay if rdattr_error */
482 482 break;
483 483 }
484 484 ASSERT(sarg->vap->va_mask & AT_SIZE);
485 485 na->size = sarg->vap->va_size;
486 486 break;
487 487 case NFS4ATTR_SETIT:
488 488 ASSERT(sarg->vap->va_mask & AT_SIZE);
489 489 sarg->vap->va_size = na->size;
490 490 break;
491 491 case NFS4ATTR_VERIT:
492 492 ASSERT(sarg->vap->va_mask & AT_SIZE);
493 493 if (sarg->vap->va_size != na->size)
494 494 error = -1; /* no match */
495 495 break;
496 496 case NFS4ATTR_FREEIT:
497 497 break;
498 498 }
499 499 return (error);
500 500 }
501 501
502 502 /*
503 503 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
504 504 * hard links.
505 505 */
506 506 /* ARGSUSED */
507 507 static int
508 508 rfs4_fattr4_link_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
509 509 union nfs4_attr_u *na)
510 510 {
511 511 int error = 0;
512 512
513 513 switch (cmd) {
514 514 case NFS4ATTR_SUPPORTED:
515 515 if (sarg->op == NFS4ATTR_SETIT)
516 516 error = EINVAL;
517 517 break; /* this attr is supported */
518 518 case NFS4ATTR_GETIT:
519 519 na->link_support = TRUE;
520 520 break;
521 521 case NFS4ATTR_SETIT:
522 522 /*
523 523 * read-only attr
524 524 */
525 525 error = EINVAL;
526 526 break;
527 527 case NFS4ATTR_VERIT:
528 528 if (!na->link_support)
529 529 error = -1; /* no match */
530 530 break;
531 531 case NFS4ATTR_FREEIT:
532 532 break;
533 533 }
534 534 return (error);
535 535 }
536 536
537 537 /*
538 538 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
539 539 * sym links.
540 540 */
541 541 /* ARGSUSED */
542 542 static int
543 543 rfs4_fattr4_symlink_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
544 544 union nfs4_attr_u *na)
545 545 {
546 546 int error = 0;
547 547
548 548 switch (cmd) {
549 549 case NFS4ATTR_SUPPORTED:
550 550 if (sarg->op == NFS4ATTR_SETIT)
551 551 error = EINVAL;
552 552 break; /* this attr is supported */
553 553 case NFS4ATTR_GETIT:
554 554 na->symlink_support = TRUE;
555 555 break;
556 556 case NFS4ATTR_SETIT:
557 557 /*
558 558 * read-only attr
559 559 */
560 560 error = EINVAL;
561 561 break;
562 562 case NFS4ATTR_VERIT:
563 563 if (!na->symlink_support)
564 564 error = -1; /* no match */
565 565 break;
566 566 case NFS4ATTR_FREEIT:
567 567 break;
568 568 }
569 569 return (error);
570 570 }
571 571
572 572 /* ARGSUSED */
573 573 static int
574 574 rfs4_fattr4_named_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
575 575 union nfs4_attr_u *na)
576 576 {
577 577 int error = 0;
578 578 ulong_t val;
579 579
580 580 switch (cmd) {
581 581 case NFS4ATTR_SUPPORTED:
582 582 if (sarg->op == NFS4ATTR_SETIT)
583 583 error = EINVAL;
584 584 break; /* this attr is supported */
585 585 case NFS4ATTR_GETIT:
586 586 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
587 587 error = -1; /* may be okay if rdattr_error */
588 588 break;
589 589 }
590 590 ASSERT(sarg->cs->vp != NULL);
591 591
592 592 /*
593 593 * Solaris xattr model requires that VFS_XATTR is set
594 594 * in file systems enabled for generic xattr. If VFS_XATTR
595 595 * not set, no need to call pathconf for _PC_XATTR_EXISTS..
596 596 *
597 597 * However the VFS_XATTR flag doesn't indicate sysattr support
598 598 * so always check for sysattrs and then only do the
599 599 * _PC_XATTR_EXISTS pathconf if needed.
600 600 */
601 601
602 602 val = 0;
603 603 error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
604 604 &val, sarg->cs->cr, NULL);
605 605 if ((error || val == 0) &&
606 606 sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
607 607 error = VOP_PATHCONF(sarg->cs->vp,
608 608 _PC_XATTR_EXISTS, &val, sarg->cs->cr, NULL);
609 609 if (error)
610 610 break;
611 611 }
612 612 na->named_attr = (val ? TRUE : FALSE);
613 613 break;
614 614 case NFS4ATTR_SETIT:
615 615 /*
616 616 * read-only attr
617 617 */
618 618 error = EINVAL;
619 619 break;
620 620 case NFS4ATTR_VERIT:
621 621 ASSERT(sarg->cs->vp != NULL);
622 622 if (sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
623 623 error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
624 624 &val, sarg->cs->cr, NULL);
625 625 if (error || val == 0)
626 626 error = VOP_PATHCONF(sarg->cs->vp,
627 627 _PC_XATTR_EXISTS, &val,
628 628 sarg->cs->cr, NULL);
629 629 if (error)
630 630 break;
631 631 } else
632 632 val = 0;
633 633 if (na->named_attr != (val ? TRUE : FALSE))
634 634 error = -1; /* no match */
635 635 break;
636 636 case NFS4ATTR_FREEIT:
637 637 break;
638 638 }
639 639 return (error);
640 640 }
641 641
642 642 /* ARGSUSED */
643 643 static int
644 644 rfs4_fattr4_fsid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
645 645 union nfs4_attr_u *na)
646 646 {
647 647 int error = 0;
648 648 int *pmaj = (int *)&na->fsid.major;
649 649
650 650 /*
651 651 * fsid_t is 64bits so it fits completely in fattr4_fsid.major.
652 652 * fattr4_fsid.minor is always set to 0 since it isn't needed (yet).
653 653 */
654 654 switch (cmd) {
655 655 case NFS4ATTR_SUPPORTED:
656 656 if (sarg->op == NFS4ATTR_SETIT)
657 657 error = EINVAL;
658 658 break; /* this attr is supported */
659 659 case NFS4ATTR_GETIT:
660 660 if (sarg->is_referral) {
661 661 na->fsid.major = 1;
662 662 na->fsid.minor = 0;
663 663 } else if (sarg->cs->exi->exi_volatile_dev) {
664 664 pmaj[0] = sarg->cs->exi->exi_fsid.val[0];
665 665 pmaj[1] = sarg->cs->exi->exi_fsid.val[1];
666 666 na->fsid.minor = 0;
667 667 } else {
668 668 na->fsid.major = getmajor(sarg->vap->va_fsid);
669 669 na->fsid.minor = getminor(sarg->vap->va_fsid);
670 670 }
671 671 break;
672 672 case NFS4ATTR_SETIT:
673 673 error = EINVAL;
674 674 break;
675 675 case NFS4ATTR_VERIT:
676 676 if (sarg->is_referral) {
677 677 if (na->fsid.major != 1 ||
678 678 na->fsid.minor != 0)
679 679 error = -1;
680 680 } else if (sarg->cs->exi->exi_volatile_dev) {
681 681 if (pmaj[0] != sarg->cs->exi->exi_fsid.val[0] ||
682 682 pmaj[1] != sarg->cs->exi->exi_fsid.val[1] ||
683 683 na->fsid.minor != 0)
684 684 error = -1;
685 685 } else {
686 686 if (na->fsid.major != getmajor(sarg->vap->va_fsid) ||
687 687 na->fsid.minor != getminor(sarg->vap->va_fsid))
688 688 error = -1;
689 689 }
690 690 break;
691 691 case NFS4ATTR_FREEIT:
692 692 break;
693 693 }
694 694 return (error);
695 695 }
696 696
697 697 /* ARGSUSED */
698 698 static int
699 699 rfs4_fattr4_unique_handles(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
700 700 union nfs4_attr_u *na)
701 701 {
702 702 /*
703 703 * XXX
704 704 * For now, we can't support this. Problem of /export, beinging
705 705 * a file system, /export/a and /export/b shared separately,
706 706 * and /export/a/l and /export/b/l are ahrd links of each other.
707 707 */
708 708 int error = 0;
709 709
710 710 switch (cmd) {
711 711 case NFS4ATTR_SUPPORTED:
712 712 if (sarg->op == NFS4ATTR_SETIT)
713 713 error = EINVAL;
714 714 break; /* this attr is supported */
715 715 case NFS4ATTR_GETIT:
716 716 na->unique_handles = FALSE;
717 717 break;
718 718 case NFS4ATTR_SETIT:
719 719 /*
720 720 * read-only attr
721 721 */
722 722 error = EINVAL;
723 723 break;
724 724 case NFS4ATTR_VERIT:
725 725 if (na->unique_handles)
726 726 error = -1; /* no match */
727 727 break;
728 728 case NFS4ATTR_FREEIT:
729 729 break;
730 730 }
731 731 return (error);
732 732 }
733 733
734 734 /* ARGSUSED */
735 735 static int
736 736 rfs4_fattr4_lease_time(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
737 737 union nfs4_attr_u *na)
738 738 {
739 739 int error = 0;
740 740
741 741 switch (cmd) {
742 742 case NFS4ATTR_SUPPORTED:
743 743 if (sarg->op == NFS4ATTR_SETIT)
744 744 error = EINVAL;
745 745 break; /* this attr is supported */
746 746 case NFS4ATTR_GETIT:
747 747 na->lease_time = rfs4_lease_time;
748 748 break;
749 749 case NFS4ATTR_SETIT:
750 750 /*
751 751 * read-only attr
752 752 */
753 753 error = EINVAL;
754 754 break;
755 755 case NFS4ATTR_VERIT:
756 756 if (na->lease_time != rfs4_lease_time)
757 757 error = -1; /* no match */
758 758 break;
759 759 case NFS4ATTR_FREEIT:
760 760 break;
761 761 }
762 762 return (error);
763 763 }
764 764
765 765 /* ARGSUSED */
766 766 static int
767 767 rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
768 768 union nfs4_attr_u *na)
769 769 {
770 770 int error = 0;
771 771
772 772 switch (cmd) {
773 773 case NFS4ATTR_SUPPORTED:
774 774 if ((sarg->op == NFS4ATTR_SETIT) ||
775 775 (sarg->op == NFS4ATTR_VERIT))
776 776 error = EINVAL;
777 777 break; /* this attr is supported */
778 778 case NFS4ATTR_GETIT:
779 779 ASSERT(sarg->rdattr_error_req);
780 780 na->rdattr_error = sarg->rdattr_error;
781 781 break;
782 782 case NFS4ATTR_SETIT:
783 783 case NFS4ATTR_VERIT:
784 784 /*
785 785 * read-only attr
786 786 */
787 787 error = EINVAL;
788 788 break;
789 789 case NFS4ATTR_FREEIT:
790 790 break;
791 791 }
792 792 return (error);
793 793 }
794 794
795 795 /*
796 796 * Server side compare of a filehandle from the wire to a native
797 797 * server filehandle.
798 798 */
799 799 static int
800 800 rfs4fhcmp(nfs_fh4 *wirefh, nfs_fh4 *srvfh)
801 801 {
802 802 nfs_fh4_fmt_t fh;
803 803
804 804 ASSERT(IS_P2ALIGNED(wirefh->nfs_fh4_val, sizeof (uint32_t)));
805 805
806 806 bzero(&fh, sizeof (nfs_fh4_fmt_t));
807 807 if (!xdr_inline_decode_nfs_fh4((uint32_t *)wirefh->nfs_fh4_val, &fh,
808 808 wirefh->nfs_fh4_len))
809 809 return (1);
810 810
811 811 return (bcmp(srvfh->nfs_fh4_val, &fh, srvfh->nfs_fh4_len));
812 812 }
813 813
814 814 /* ARGSUSED */
815 815 static int
816 816 rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
817 817 union nfs4_attr_u *na)
818 818 {
819 819 nfs_fh4 *fh;
820 820
821 821 switch (cmd) {
822 822 case NFS4ATTR_SUPPORTED:
823 823 if (sarg->op == NFS4ATTR_SETIT)
824 824 return (EINVAL);
825 825 return (0); /* this attr is supported */
826 826 case NFS4ATTR_GETIT:
827 827 /*
828 828 * If sarg->cs->fh is all zeros then should makefh a new
829 829 * one, otherwise, copy that one over.
830 830 */
831 831 fh = &sarg->cs->fh;
832 832 if (sarg->cs->fh.nfs_fh4_len == 0) {
833 833 if (sarg->rdattr_error && (sarg->cs->vp == NULL))
834 834 return (-1); /* okay if rdattr_error */
835 835 ASSERT(sarg->cs->vp != NULL);
836 836 na->filehandle.nfs_fh4_val =
837 837 kmem_alloc(NFS_FH4_LEN, KM_SLEEP);
838 838 return (makefh4(&na->filehandle, sarg->cs->vp,
839 839 sarg->cs->exi));
840 840 }
841 841 na->filehandle.nfs_fh4_val =
842 842 kmem_alloc(fh->nfs_fh4_len, KM_SLEEP);
843 843 nfs_fh4_copy(fh, &na->filehandle);
844 844 return (0);
845 845 case NFS4ATTR_SETIT:
846 846 /*
847 847 * read-only attr
848 848 */
849 849 return (EINVAL);
850 850 case NFS4ATTR_VERIT:
851 851 /*
852 852 * A verify of a filehandle will have the client sending
853 853 * the raw format which needs to be compared to the
854 854 * native format.
855 855 */
856 856 if (rfs4fhcmp(&na->filehandle, &sarg->cs->fh) == 1)
857 857 return (-1); /* no match */
858 858 return (0);
859 859 case NFS4ATTR_FREEIT:
860 860 if (sarg->op != NFS4ATTR_GETIT)
861 861 return (0);
862 862 if (na->filehandle.nfs_fh4_val == NULL)
863 863 return (0);
864 864 kmem_free(na->filehandle.nfs_fh4_val,
865 865 na->filehandle.nfs_fh4_len);
866 866 na->filehandle.nfs_fh4_val = NULL;
867 867 na->filehandle.nfs_fh4_len = 0;
868 868 return (0);
869 869 }
870 870 return (0);
871 871 }
872 872
873 873 /*
874 874 * Recommended attributes
875 875 */
876 876
877 877 /* ARGSUSED */
878 878 static int
879 879 rfs4_fattr4_acl(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
880 880 union nfs4_attr_u *na)
881 881 {
882 882 int error = 0;
883 883 vsecattr_t vs_native, vs_ace4;
884 884 ulong_t whichacl;
885 885 nfsstat4 status;
886 886 vattr_t va, *vap = sarg->vap;
887 887 vnode_t *vp = sarg->cs->vp;
888 888
889 889 if (RFS4_MANDATTR_ONLY)
890 890 return (ENOTSUP);
891 891
892 892 switch (cmd) {
893 893 case NFS4ATTR_SUPPORTED:
894 894 break;
895 895
896 896 case NFS4ATTR_VERIT:
897 897 case NFS4ATTR_GETIT:
898 898 if (sarg->rdattr_error && (vp == NULL)) {
899 899 return (-1);
900 900 }
901 901 ASSERT(vp != NULL);
902 902 bzero(&vs_native, sizeof (vs_native));
903 903
904 904 /* see which ACLs fs supports */
905 905 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
906 906 sarg->cs->cr, NULL);
907 907 if (error != 0) {
908 908 /*
909 909 * If we got an error, then the filesystem
910 910 * likely does not understand the _PC_ACL_ENABLED
911 911 * pathconf. In this case, we fall back to trying
912 912 * POSIX-draft (aka UFS-style) ACLs, since that's
913 913 * the behavior used by earlier version of NFS.
914 914 */
915 915 error = 0;
916 916 whichacl = _ACL_ACLENT_ENABLED;
917 917 }
918 918
919 919 if (!(whichacl & (_ACL_ACE_ENABLED | _ACL_ACLENT_ENABLED))) {
920 920 /*
921 921 * If the file system supports neither ACE nor
922 922 * ACLENT ACLs we will fall back to UFS-style ACLs
923 923 * like we did above if there was an error upon
924 924 * calling VOP_PATHCONF.
925 925 *
926 926 * ACE and ACLENT type ACLs are the only interfaces
927 927 * supported thus far. If any other bits are set on
928 928 * 'whichacl' upon return from VOP_PATHCONF, we will
929 929 * ignore them.
930 930 */
931 931 whichacl = _ACL_ACLENT_ENABLED;
932 932 }
933 933
934 934 if (whichacl & _ACL_ACE_ENABLED)
935 935 vs_native.vsa_mask = VSA_ACE | VSA_ACECNT;
936 936 else if (whichacl & _ACL_ACLENT_ENABLED)
937 937 vs_native.vsa_mask = VSA_ACL | VSA_ACLCNT |
938 938 VSA_DFACL | VSA_DFACLCNT;
939 939
940 940 if (error != 0)
941 941 break;
942 942
943 943 /* get the ACL, and translate it into nfsace4 style */
944 944 error = VOP_GETSECATTR(vp, &vs_native,
945 945 0, sarg->cs->cr, NULL);
946 946 if (error != 0)
947 947 break;
948 948 if (whichacl & _ACL_ACE_ENABLED) {
949 949 error = vs_acet_to_ace4(&vs_native, &vs_ace4, TRUE);
950 950 vs_acet_destroy(&vs_native);
951 951 } else {
952 952 error = vs_aent_to_ace4(&vs_native, &vs_ace4,
953 953 vp->v_type == VDIR, TRUE);
954 954 vs_aent_destroy(&vs_native);
955 955 }
956 956 if (error != 0)
957 957 break;
958 958
959 959 if (cmd == NFS4ATTR_GETIT) {
960 960 na->acl.fattr4_acl_len = vs_ace4.vsa_aclcnt;
961 961 /* see case NFS4ATTR_FREEIT for this being freed */
962 962 na->acl.fattr4_acl_val = vs_ace4.vsa_aclentp;
963 963 } else {
964 964 if (na->acl.fattr4_acl_len != vs_ace4.vsa_aclcnt)
965 965 error = -1; /* no match */
966 966 else if (ln_ace4_cmp(na->acl.fattr4_acl_val,
967 967 vs_ace4.vsa_aclentp,
968 968 vs_ace4.vsa_aclcnt) != 0)
969 969 error = -1; /* no match */
970 970 }
971 971
972 972 break;
973 973
974 974 case NFS4ATTR_SETIT:
975 975 if (sarg->rdattr_error && (vp == NULL)) {
976 976 return (-1);
977 977 }
978 978 ASSERT(vp != NULL);
979 979
980 980 /* prepare vs_ace4 from fattr4 data */
981 981 bzero(&vs_ace4, sizeof (vs_ace4));
982 982 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
983 983 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
984 984 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
985 985 vs_ace4.vsa_aclentsz = vs_ace4.vsa_aclcnt * sizeof (ace_t);
986 986 /* make sure we have correct owner/group */
987 987 if ((vap->va_mask & (AT_UID | AT_GID)) !=
988 988 (AT_UID | AT_GID)) {
989 989 vap = &va;
990 990 vap->va_mask = AT_UID | AT_GID;
991 991 status = rfs4_vop_getattr(vp,
992 992 vap, 0, sarg->cs->cr);
993 993 if (status != NFS4_OK)
994 994 return (geterrno4(status));
995 995 }
996 996
997 997 /* see which ACLs the fs supports */
998 998 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
999 999 sarg->cs->cr, NULL);
1000 1000 if (error != 0) {
1001 1001 /*
1002 1002 * If we got an error, then the filesystem
1003 1003 * likely does not understand the _PC_ACL_ENABLED
1004 1004 * pathconf. In this case, we fall back to trying
1005 1005 * POSIX-draft (aka UFS-style) ACLs, since that's
1006 1006 * the behavior used by earlier version of NFS.
1007 1007 */
1008 1008 error = 0;
1009 1009 whichacl = _ACL_ACLENT_ENABLED;
1010 1010 }
1011 1011
1012 1012 if (!(whichacl & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED))) {
1013 1013 /*
1014 1014 * If the file system supports neither ACE nor
1015 1015 * ACLENT ACLs we will fall back to UFS-style ACLs
1016 1016 * like we did above if there was an error upon
1017 1017 * calling VOP_PATHCONF.
1018 1018 *
1019 1019 * ACE and ACLENT type ACLs are the only interfaces
1020 1020 * supported thus far. If any other bits are set on
1021 1021 * 'whichacl' upon return from VOP_PATHCONF, we will
1022 1022 * ignore them.
1023 1023 */
1024 1024 whichacl = _ACL_ACLENT_ENABLED;
1025 1025 }
1026 1026
1027 1027 if (whichacl & _ACL_ACE_ENABLED) {
1028 1028 error = vs_ace4_to_acet(&vs_ace4, &vs_native,
1029 1029 vap->va_uid, vap->va_gid, TRUE);
1030 1030 if (error != 0)
1031 1031 break;
1032 1032 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
1033 1033 error = VOP_SETSECATTR(vp, &vs_native,
1034 1034 0, sarg->cs->cr, NULL);
1035 1035 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
1036 1036 vs_acet_destroy(&vs_native);
1037 1037 } else if (whichacl & _ACL_ACLENT_ENABLED) {
1038 1038 error = vs_ace4_to_aent(&vs_ace4, &vs_native,
1039 1039 vap->va_uid, vap->va_gid, vp->v_type == VDIR, TRUE);
1040 1040 if (error != 0)
1041 1041 break;
1042 1042 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
1043 1043 error = VOP_SETSECATTR(vp, &vs_native,
1044 1044 0, sarg->cs->cr, NULL);
1045 1045 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
1046 1046 vs_aent_destroy(&vs_native);
1047 1047 }
1048 1048 break;
1049 1049
1050 1050 case NFS4ATTR_FREEIT:
1051 1051 if (sarg->op == NFS4ATTR_GETIT) {
1052 1052 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
1053 1053 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
1054 1054 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
1055 1055 vs_ace4_destroy(&vs_ace4);
1056 1056 }
1057 1057 break;
1058 1058 }
1059 1059
1060 1060 return (error);
1061 1061 }
1062 1062
1063 1063 /* ARGSUSED */
1064 1064 static int
1065 1065 rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1066 1066 union nfs4_attr_u *na)
1067 1067 {
1068 1068 int error = 0;
1069 1069
1070 1070 if (RFS4_MANDATTR_ONLY)
1071 1071 return (ENOTSUP);
1072 1072
1073 1073 switch (cmd) {
1074 1074 case NFS4ATTR_SUPPORTED:
1075 1075 if (sarg->op == NFS4ATTR_SETIT)
1076 1076 error = EINVAL;
1077 1077 break; /* supported */
1078 1078 case NFS4ATTR_GETIT:
1079 1079 na->aclsupport = ACL4_SUPPORT_ALLOW_ACL |
1080 1080 ACL4_SUPPORT_DENY_ACL;
1081 1081 break;
1082 1082 case NFS4ATTR_SETIT:
1083 1083 error = EINVAL;
1084 1084 break;
1085 1085 case NFS4ATTR_VERIT:
1086 1086 if (na->aclsupport != (ACL4_SUPPORT_ALLOW_ACL |
1087 1087 ACL4_SUPPORT_DENY_ACL))
1088 1088 error = -1; /* no match */
1089 1089 break;
1090 1090 }
1091 1091
1092 1092 return (error);
1093 1093 }
1094 1094
1095 1095 /* ARGSUSED */
1096 1096 static int
1097 1097 rfs4_fattr4_archive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1098 1098 union nfs4_attr_u *na)
1099 1099 {
1100 1100 return (ENOTSUP);
1101 1101 }
1102 1102
1103 1103 /* ARGSUSED */
1104 1104 static int
1105 1105 rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1106 1106 union nfs4_attr_u *na)
1107 1107 {
1108 1108 int error = 0;
1109 1109
1110 1110 if (RFS4_MANDATTR_ONLY)
1111 1111 return (ENOTSUP);
1112 1112
1113 1113 switch (cmd) {
1114 1114 case NFS4ATTR_SUPPORTED:
1115 1115 if (sarg->op == NFS4ATTR_SETIT)
1116 1116 error = EINVAL;
1117 1117 break; /* this attr is supported */
1118 1118 case NFS4ATTR_GETIT:
1119 1119 na->cansettime = TRUE;
1120 1120 break;
1121 1121 case NFS4ATTR_SETIT:
1122 1122 /*
1123 1123 * read-only attr
1124 1124 */
1125 1125 error = EINVAL;
1126 1126 break;
1127 1127 case NFS4ATTR_VERIT:
1128 1128 if (!na->cansettime)
1129 1129 error = -1; /* no match */
1130 1130 break;
1131 1131 case NFS4ATTR_FREEIT:
1132 1132 break;
1133 1133 }
1134 1134 return (error);
1135 1135 }
1136 1136
1137 1137 /*
1138 1138 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
1139 1139 * case insensitive.
1140 1140 */
1141 1141 /* ARGSUSED */
1142 1142 static int
1143 1143 rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1144 1144 union nfs4_attr_u *na)
1145 1145 {
1146 1146 int error = 0;
1147 1147
1148 1148 if (RFS4_MANDATTR_ONLY)
1149 1149 return (ENOTSUP);
1150 1150
1151 1151 switch (cmd) {
1152 1152 case NFS4ATTR_SUPPORTED:
1153 1153 if (sarg->op == NFS4ATTR_SETIT)
1154 1154 error = EINVAL;
1155 1155 break; /* this attr is supported */
1156 1156 case NFS4ATTR_GETIT:
1157 1157 na->case_insensitive = FALSE;
1158 1158 break;
1159 1159 case NFS4ATTR_SETIT:
1160 1160 /*
1161 1161 * read-only attr
1162 1162 */
1163 1163 error = EINVAL;
1164 1164 break;
1165 1165 case NFS4ATTR_VERIT:
1166 1166 if (!na->case_insensitive)
1167 1167 error = -1; /* no match */
1168 1168 break;
1169 1169 case NFS4ATTR_FREEIT:
1170 1170 break;
1171 1171 }
1172 1172 return (error);
1173 1173 }
1174 1174
1175 1175 /* ARGSUSED */
1176 1176 static int
1177 1177 rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1178 1178 union nfs4_attr_u *na)
1179 1179 {
1180 1180 int error = 0;
1181 1181
1182 1182 if (RFS4_MANDATTR_ONLY)
1183 1183 return (ENOTSUP);
1184 1184
1185 1185 switch (cmd) {
1186 1186 case NFS4ATTR_SUPPORTED:
1187 1187 if (sarg->op == NFS4ATTR_SETIT)
1188 1188 error = EINVAL;
1189 1189 break; /* this attr is supported */
1190 1190 case NFS4ATTR_GETIT:
1191 1191 na->case_preserving = TRUE;
1192 1192 break;
1193 1193 case NFS4ATTR_SETIT:
1194 1194 /*
1195 1195 * read-only attr
1196 1196 */
1197 1197 error = EINVAL;
1198 1198 break;
1199 1199 case NFS4ATTR_VERIT:
1200 1200 if (!na->case_preserving)
1201 1201 error = -1; /* no match */
1202 1202 break;
1203 1203 case NFS4ATTR_FREEIT:
1204 1204 break;
1205 1205 }
1206 1206 return (error);
1207 1207 }
1208 1208
1209 1209 /* fattr4_chown_restricted should reall be fattr4_chown_allowed */
1210 1210 /* ARGSUSED */
1211 1211 static int
1212 1212 rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1213 1213 union nfs4_attr_u *na)
1214 1214 {
1215 1215 int error = 0;
1216 1216 ulong_t val;
1217 1217
1218 1218 if (RFS4_MANDATTR_ONLY)
1219 1219 return (ENOTSUP);
1220 1220
1221 1221 switch (cmd) {
1222 1222 case NFS4ATTR_SUPPORTED:
1223 1223 if (sarg->op == NFS4ATTR_SETIT)
1224 1224 error = EINVAL;
1225 1225 break; /* this attr is supported */
1226 1226 case NFS4ATTR_GETIT:
1227 1227 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1228 1228 error = -1; /* may be okay if rdattr_error */
1229 1229 break;
1230 1230 }
1231 1231 ASSERT(sarg->cs->vp != NULL);
1232 1232 error = VOP_PATHCONF(sarg->cs->vp,
1233 1233 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
1234 1234 if (error)
1235 1235 break;
1236 1236
1237 1237 na->chown_restricted = (val == 1);
1238 1238 break;
1239 1239 case NFS4ATTR_SETIT:
1240 1240 /*
1241 1241 * read-only attr
1242 1242 */
1243 1243 error = EINVAL;
1244 1244 break;
1245 1245 case NFS4ATTR_VERIT:
1246 1246 ASSERT(sarg->cs->vp != NULL);
1247 1247 error = VOP_PATHCONF(sarg->cs->vp,
1248 1248 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
1249 1249 if (error)
1250 1250 break;
1251 1251 if (na->chown_restricted != (val == 1))
1252 1252 error = -1; /* no match */
1253 1253 break;
1254 1254 case NFS4ATTR_FREEIT:
1255 1255 break;
1256 1256 }
1257 1257 return (error);
1258 1258 }
1259 1259
1260 1260 /* ARGSUSED */
1261 1261 static int
1262 1262 rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1263 1263 union nfs4_attr_u *na)
1264 1264 {
1265 1265 int error = 0;
1266 1266
1267 1267 if (RFS4_MANDATTR_ONLY)
1268 1268 return (ENOTSUP);
1269 1269
1270 1270 switch (cmd) {
1271 1271 case NFS4ATTR_SUPPORTED:
1272 1272 if (sarg->op == NFS4ATTR_SETIT)
1273 1273 error = EINVAL;
1274 1274 break; /* this attr is supported */
1275 1275 case NFS4ATTR_GETIT:
1276 1276 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NODEID)) {
1277 1277 error = -1; /* may be okay if rdattr_error */
1278 1278 break;
1279 1279 }
1280 1280 ASSERT(sarg->vap->va_mask & AT_NODEID);
1281 1281 na->fileid = sarg->vap->va_nodeid;
1282 1282 break;
1283 1283 case NFS4ATTR_SETIT:
1284 1284 /*
1285 1285 * read-only attr
1286 1286 */
1287 1287 error = EINVAL;
1288 1288 break;
1289 1289 case NFS4ATTR_VERIT:
1290 1290 ASSERT(sarg->vap->va_mask & AT_NODEID);
1291 1291 if (sarg->vap->va_nodeid != na->fileid)
1292 1292 error = -1; /* no match */
1293 1293 break;
1294 1294 case NFS4ATTR_FREEIT:
1295 1295 break;
1296 1296 }
1297 1297 return (error);
1298 1298 }
1299 1299
1300 1300 /* ARGSUSED */
1301 1301 static int
1302 1302 rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg)
1303 1303 {
1304 1304 int error = 0;
1305 1305 vattr_t *vap, va;
1306 1306 vnode_t *stubvp = NULL, *vp;
1307 1307
1308 1308 vp = sarg->cs->vp;
1309 1309 sarg->mntdfid_set = FALSE;
1310 1310
1311 1311 /*
1312 1312 * VROOT object or zone's root, must untraverse.
|
↓ open down ↓ |
1312 lines elided |
↑ open up ↑ |
1313 1313 *
1314 1314 * NOTE: Not doing reality checks on curzone vs. compound
1315 1315 * state vnode because it will mismatch once at initialization
1316 1316 * if a non-global-zone triggers the module load, BUT in that case
1317 1317 * the vp is literally "/" which has VROOT set.
1318 1318 */
1319 1319 if ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp)) {
1320 1320
1321 1321 /* extra hold for vp since untraverse might rele */
1322 1322 VN_HOLD(vp);
1323 - stubvp = untraverse(vp);
1323 + stubvp = untraverse(nfs_get_export(), vp);
1324 1324
1325 1325 /*
1326 1326 * If vp/stubvp are same, we must be at system-or-zone
1327 1327 * root because untraverse returned same vp
1328 1328 * for a VROOT object. sarg->vap was setup
1329 1329 * before we got here, so there's no need to do
1330 1330 * another getattr -- just use the one in sarg.
1331 1331 */
1332 1332 if (VN_CMP(vp, stubvp)) {
1333 1333 ASSERT(VN_IS_CURZONEROOT(vp));
1334 1334 vap = sarg->vap;
1335 1335 } else {
1336 1336 va.va_mask = AT_NODEID;
1337 1337 vap = &va;
1338 1338 error = rfs4_vop_getattr(stubvp, vap, 0, sarg->cs->cr);
1339 1339 }
1340 1340
1341 1341 /*
1342 1342 * Done with stub, time to rele. If vp and stubvp
1343 1343 * were the same, then we need to rele either vp or
1344 1344 * stubvp. If they weren't the same, then untraverse()
1345 1345 * already took case of the extra hold on vp, and only
1346 1346 * the stub needs to be rele'd. Both cases are handled
1347 1347 * by unconditionally rele'ing the stub.
1348 1348 */
1349 1349 VN_RELE(stubvp);
1350 1350 } else
1351 1351 vap = sarg->vap;
1352 1352
1353 1353 /*
1354 1354 * At this point, vap should contain "correct" AT_NODEID --
1355 1355 * (for V_ROOT case, nodeid of stub, for non-VROOT case,
1356 1356 * nodeid of vp). If error or AT_NODEID not available, then
1357 1357 * make the obligatory (yet mysterious) rdattr_error
1358 1358 * check that is so common in the attr code.
1359 1359 */
1360 1360 if (!error && (vap->va_mask & AT_NODEID)) {
1361 1361 sarg->mounted_on_fileid = vap->va_nodeid;
1362 1362 sarg->mntdfid_set = TRUE;
1363 1363 } else if (sarg->rdattr_error)
1364 1364 error = -1;
1365 1365
1366 1366 /*
1367 1367 * error describes these cases:
1368 1368 * 0 : success
1369 1369 * -1: failure due to previous attr processing error (rddir only).
1370 1370 * * : new attr failure (if rddir, caller will set rdattr_error)
1371 1371 */
1372 1372 return (error);
1373 1373 }
1374 1374
1375 1375 /* ARGSUSED */
1376 1376 static int
1377 1377 rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd,
1378 1378 struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na)
1379 1379 {
1380 1380 int error = 0;
1381 1381
1382 1382 if (RFS4_MANDATTR_ONLY)
1383 1383 return (ENOTSUP);
1384 1384
1385 1385 switch (cmd) {
1386 1386 case NFS4ATTR_SUPPORTED:
1387 1387 if (sarg->op == NFS4ATTR_SETIT)
1388 1388 error = EINVAL;
1389 1389 break; /* this attr is supported */
1390 1390 case NFS4ATTR_GETIT:
1391 1391 case NFS4ATTR_VERIT:
1392 1392 if (!sarg->mntdfid_set)
1393 1393 error = rfs4_get_mntdfileid(cmd, sarg);
1394 1394
1395 1395 if (!error && sarg->mntdfid_set) {
1396 1396 if (cmd == NFS4ATTR_GETIT)
1397 1397 na->mounted_on_fileid = sarg->mounted_on_fileid;
1398 1398 else
1399 1399 if (na->mounted_on_fileid !=
1400 1400 sarg->mounted_on_fileid)
1401 1401 error = -1;
1402 1402 }
1403 1403 break;
1404 1404 case NFS4ATTR_SETIT:
1405 1405 /* read-only attr */
1406 1406 error = EINVAL;
1407 1407 break;
1408 1408 case NFS4ATTR_FREEIT:
1409 1409 break;
1410 1410 }
1411 1411 return (error);
1412 1412 }
1413 1413
1414 1414 /* ARGSUSED */
1415 1415 static int
1416 1416 rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1417 1417 union nfs4_attr_u *na)
1418 1418 {
1419 1419 int error = 0;
1420 1420
1421 1421 if (RFS4_MANDATTR_ONLY)
1422 1422 return (ENOTSUP);
1423 1423
1424 1424 switch (cmd) {
1425 1425 case NFS4ATTR_SUPPORTED:
1426 1426 if (sarg->op == NFS4ATTR_SETIT)
1427 1427 error = EINVAL;
1428 1428 break; /* this attr is supported */
1429 1429 case NFS4ATTR_GETIT:
1430 1430 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1431 1431 error = -1; /* may be okay if rdattr_error */
1432 1432 break;
1433 1433 }
1434 1434 ASSERT(sarg->sbp != NULL);
1435 1435 na->files_avail = sarg->sbp->f_favail;
1436 1436 break;
1437 1437 case NFS4ATTR_SETIT:
1438 1438 /*
1439 1439 * read-only attr
1440 1440 */
1441 1441 error = EINVAL;
1442 1442 break;
1443 1443 case NFS4ATTR_VERIT:
1444 1444 ASSERT(sarg->sbp != NULL);
1445 1445 if (sarg->sbp->f_favail != na->files_avail)
1446 1446 error = -1; /* no match */
1447 1447 break;
1448 1448 case NFS4ATTR_FREEIT:
1449 1449 break;
1450 1450 }
1451 1451 return (error);
1452 1452 }
1453 1453
1454 1454 /* ARGSUSED */
1455 1455 static int
1456 1456 rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1457 1457 union nfs4_attr_u *na)
1458 1458 {
1459 1459 int error = 0;
1460 1460
1461 1461 if (RFS4_MANDATTR_ONLY)
1462 1462 return (ENOTSUP);
1463 1463
1464 1464 switch (cmd) {
1465 1465 case NFS4ATTR_SUPPORTED:
1466 1466 if (sarg->op == NFS4ATTR_SETIT)
1467 1467 error = EINVAL;
1468 1468 break; /* this attr is supported */
1469 1469 case NFS4ATTR_GETIT:
1470 1470 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1471 1471 error = -1; /* may be okay if rdattr_error */
1472 1472 break;
1473 1473 }
1474 1474 ASSERT(sarg->sbp != NULL);
1475 1475 na->files_free = sarg->sbp->f_ffree;
1476 1476 break;
1477 1477 case NFS4ATTR_SETIT:
1478 1478 /*
1479 1479 * read-only attr
1480 1480 */
1481 1481 error = EINVAL;
1482 1482 break;
1483 1483 case NFS4ATTR_VERIT:
1484 1484 ASSERT(sarg->sbp != NULL);
1485 1485 if (sarg->sbp->f_ffree != na->files_free)
1486 1486 error = -1; /* no match */
1487 1487 break;
1488 1488 case NFS4ATTR_FREEIT:
1489 1489 break;
1490 1490 }
1491 1491 return (error);
1492 1492 }
1493 1493
1494 1494 /* ARGSUSED */
1495 1495 static int
1496 1496 rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1497 1497 union nfs4_attr_u *na)
1498 1498 {
1499 1499 int error = 0;
1500 1500
1501 1501 if (RFS4_MANDATTR_ONLY)
1502 1502 return (ENOTSUP);
1503 1503
1504 1504 switch (cmd) {
1505 1505 case NFS4ATTR_SUPPORTED:
1506 1506 if (sarg->op == NFS4ATTR_SETIT)
1507 1507 error = EINVAL;
1508 1508 break; /* this attr is supported */
1509 1509 case NFS4ATTR_GETIT:
1510 1510 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1511 1511 error = -1; /* may be okay if rdattr_error */
1512 1512 break;
1513 1513 }
1514 1514 ASSERT(sarg->sbp != NULL);
1515 1515 na->files_total = sarg->sbp->f_files;
1516 1516 break;
1517 1517 case NFS4ATTR_SETIT:
1518 1518 /*
1519 1519 * read-only attr
1520 1520 */
1521 1521 error = EINVAL;
1522 1522 break;
1523 1523 case NFS4ATTR_VERIT:
1524 1524 ASSERT(sarg->sbp != NULL);
1525 1525 if (sarg->sbp->f_files != na->files_total)
1526 1526 error = -1; /* no match */
1527 1527 break;
1528 1528 case NFS4ATTR_FREEIT:
1529 1529 break;
1530 1530 }
1531 1531 return (error);
1532 1532 }
1533 1533
1534 1534 static void
1535 1535 rfs4_free_pathname4(pathname4 *pn4)
1536 1536 {
1537 1537 int i, len;
1538 1538 utf8string *utf8s;
1539 1539
1540 1540 if (pn4 == NULL || (len = pn4->pathname4_len) == 0 ||
1541 1541 (utf8s = pn4->pathname4_val) == NULL)
1542 1542 return;
1543 1543
1544 1544 for (i = 0; i < len; i++, utf8s++) {
1545 1545 if (utf8s->utf8string_val == NULL ||
1546 1546 utf8s->utf8string_len == 0)
1547 1547 continue;
1548 1548
1549 1549 kmem_free(utf8s->utf8string_val, utf8s->utf8string_len);
1550 1550 utf8s->utf8string_val = NULL;
1551 1551 }
1552 1552
1553 1553 kmem_free(pn4->pathname4_val,
1554 1554 sizeof (utf8string) * pn4->pathname4_len);
1555 1555 pn4->pathname4_val = 0;
1556 1556 }
1557 1557
1558 1558 static void
1559 1559 rfs4_free_fs_location4(fs_location4 *fsl4)
1560 1560 {
1561 1561 if (fsl4 == NULL)
1562 1562 return;
1563 1563
1564 1564 rfs4_free_pathname4((pathname4 *)&fsl4->server_len);
1565 1565 rfs4_free_pathname4(&fsl4->rootpath);
1566 1566 }
1567 1567
1568 1568 void
1569 1569 rfs4_free_fs_locations4(fs_locations4 *fsls4)
1570 1570 {
1571 1571 int i, len;
1572 1572 fs_location4 *fsl4;
1573 1573
1574 1574 if (fsls4 == NULL)
1575 1575 return;
1576 1576
1577 1577 /* free fs_root */
1578 1578 rfs4_free_pathname4(&fsls4->fs_root);
1579 1579
1580 1580 if ((len = fsls4->locations_len) == 0 ||
1581 1581 (fsl4 = fsls4->locations_val) == NULL)
1582 1582 return;
1583 1583
1584 1584 /* free fs_location4 */
1585 1585 for (i = 0; i < len; i++) {
1586 1586 rfs4_free_fs_location4(fsl4);
1587 1587 fsl4++;
1588 1588 }
1589 1589
1590 1590 kmem_free(fsls4->locations_val, sizeof (fs_location4) * len);
1591 1591 fsls4->locations_val = NULL;
1592 1592 }
1593 1593
1594 1594 /* ARGSUSED */
1595 1595 static int
1596 1596 rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1597 1597 union nfs4_attr_u *na)
1598 1598 {
1599 1599 int error = 0;
1600 1600 fs_locations4 *fsl;
1601 1601
1602 1602 if (RFS4_MANDATTR_ONLY)
1603 1603 return (ENOTSUP);
1604 1604
1605 1605 switch (cmd) {
1606 1606 case NFS4ATTR_SUPPORTED:
1607 1607 if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
1608 1608 error = EINVAL;
1609 1609 break; /* this attr is supported */
1610 1610
1611 1611 case NFS4ATTR_GETIT:
1612 1612 fsl = fetch_referral(sarg->cs->vp, sarg->cs->cr);
1613 1613 if (fsl == NULL)
1614 1614 (void) memset(&(na->fs_locations), 0,
1615 1615 sizeof (fs_locations4));
1616 1616 else {
1617 1617 na->fs_locations = *fsl;
1618 1618 kmem_free(fsl, sizeof (fs_locations4));
1619 1619 }
1620 1620 global_svstat_ptr[4][NFS_REFERRALS].value.ui64++;
1621 1621 break;
1622 1622
1623 1623 case NFS4ATTR_FREEIT:
1624 1624 if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
1625 1625 error = EINVAL;
1626 1626 rfs4_free_fs_locations4(&na->fs_locations);
1627 1627 break;
1628 1628
1629 1629 case NFS4ATTR_SETIT:
1630 1630 case NFS4ATTR_VERIT:
1631 1631 /*
1632 1632 * read-only attr
1633 1633 */
1634 1634 error = EINVAL;
1635 1635 break;
1636 1636 }
1637 1637 return (error);
1638 1638 }
1639 1639
1640 1640 /* ARGSUSED */
1641 1641 static int
1642 1642 rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1643 1643 union nfs4_attr_u *na)
1644 1644 {
1645 1645 return (ENOTSUP);
1646 1646 }
1647 1647
1648 1648 /* ARGSUSED */
1649 1649 static int
1650 1650 rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1651 1651 union nfs4_attr_u *na)
1652 1652 {
1653 1653 int error = 0;
1654 1654
1655 1655 if (RFS4_MANDATTR_ONLY)
1656 1656 return (ENOTSUP);
1657 1657
1658 1658 switch (cmd) {
1659 1659 case NFS4ATTR_SUPPORTED:
1660 1660 if (sarg->op == NFS4ATTR_SETIT)
1661 1661 error = EINVAL;
1662 1662 break; /* this attr is supported */
1663 1663 case NFS4ATTR_GETIT:
1664 1664 na->homogeneous = TRUE; /* XXX - need a VOP extension */
1665 1665 break;
1666 1666 case NFS4ATTR_SETIT:
1667 1667 /*
1668 1668 * read-only attr
1669 1669 */
1670 1670 error = EINVAL;
1671 1671 break;
1672 1672 case NFS4ATTR_VERIT:
1673 1673 if (!na->homogeneous)
1674 1674 error = -1; /* no match */
1675 1675 break;
1676 1676 case NFS4ATTR_FREEIT:
1677 1677 break;
1678 1678 }
1679 1679 return (error);
1680 1680 }
1681 1681
1682 1682 /* ARGSUSED */
1683 1683 static int
1684 1684 rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1685 1685 union nfs4_attr_u *na)
1686 1686 {
1687 1687 int error = 0;
1688 1688 ulong_t val;
1689 1689 fattr4_maxfilesize maxfilesize;
1690 1690
1691 1691 if (RFS4_MANDATTR_ONLY)
1692 1692 return (ENOTSUP);
1693 1693
1694 1694 switch (cmd) {
1695 1695 case NFS4ATTR_SUPPORTED:
1696 1696 if (sarg->op == NFS4ATTR_SETIT)
1697 1697 error = EINVAL;
1698 1698 break; /* this attr is supported */
1699 1699 case NFS4ATTR_GETIT:
1700 1700 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1701 1701 error = -1; /* may be okay if rdattr_error */
1702 1702 break;
1703 1703 }
1704 1704 ASSERT(sarg->cs->vp != NULL);
1705 1705 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
1706 1706 sarg->cs->cr, NULL);
1707 1707 if (error)
1708 1708 break;
1709 1709
1710 1710 /*
1711 1711 * If the underlying file system does not support
1712 1712 * _PC_FILESIZEBITS, return a reasonable default. Note that
1713 1713 * error code on VOP_PATHCONF will be 0, even if the underlying
1714 1714 * file system does not support _PC_FILESIZEBITS.
1715 1715 */
1716 1716 if (val == (ulong_t)-1) {
1717 1717 na->maxfilesize = MAXOFF32_T;
1718 1718 } else {
1719 1719 if (val >= (sizeof (uint64_t) * 8))
1720 1720 na->maxfilesize = INT64_MAX;
1721 1721 else
1722 1722 na->maxfilesize = ((1LL << (val - 1)) - 1);
1723 1723 }
1724 1724 break;
1725 1725 case NFS4ATTR_SETIT:
1726 1726 /*
1727 1727 * read-only attr
1728 1728 */
1729 1729 error = EINVAL;
1730 1730 break;
1731 1731 case NFS4ATTR_VERIT:
1732 1732 ASSERT(sarg->cs->vp != NULL);
1733 1733 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
1734 1734 sarg->cs->cr, NULL);
1735 1735 if (error)
1736 1736 break;
1737 1737 /*
1738 1738 * If the underlying file system does not support
1739 1739 * _PC_FILESIZEBITS, return a reasonable default. Note that
1740 1740 * error code on VOP_PATHCONF will be 0, even if the underlying
1741 1741 * file system does not support _PC_FILESIZEBITS.
1742 1742 */
1743 1743 if (val == (ulong_t)-1) {
1744 1744 maxfilesize = MAXOFF32_T;
1745 1745 } else {
1746 1746 if (val >= (sizeof (uint64_t) * 8))
1747 1747 maxfilesize = INT64_MAX;
1748 1748 else
1749 1749 maxfilesize = ((1LL << (val - 1)) - 1);
1750 1750 }
1751 1751 if (na->maxfilesize != maxfilesize)
1752 1752 error = -1; /* no match */
1753 1753 break;
1754 1754 case NFS4ATTR_FREEIT:
1755 1755 break;
1756 1756 }
1757 1757 return (error);
1758 1758 }
1759 1759
1760 1760 /* ARGSUSED */
1761 1761 static int
1762 1762 rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1763 1763 union nfs4_attr_u *na)
1764 1764 {
1765 1765 int error = 0;
1766 1766 ulong_t val;
1767 1767
1768 1768 if (RFS4_MANDATTR_ONLY)
1769 1769 return (ENOTSUP);
1770 1770
1771 1771 switch (cmd) {
1772 1772 case NFS4ATTR_SUPPORTED:
1773 1773 if (sarg->op == NFS4ATTR_SETIT)
1774 1774 error = EINVAL;
1775 1775 break; /* this attr is supported */
1776 1776 case NFS4ATTR_GETIT:
1777 1777 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1778 1778 error = -1; /* may be okay if rdattr_error */
1779 1779 break;
1780 1780 }
1781 1781 ASSERT(sarg->cs->vp != NULL);
1782 1782 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
1783 1783 sarg->cs->cr, NULL);
1784 1784 if (error == 0) {
1785 1785 na->maxlink = val;
1786 1786 }
1787 1787 break;
1788 1788 case NFS4ATTR_SETIT:
1789 1789 /*
1790 1790 * read-only attr
1791 1791 */
1792 1792 error = EINVAL;
1793 1793 break;
1794 1794 case NFS4ATTR_VERIT:
1795 1795 ASSERT(sarg->cs->vp != NULL);
1796 1796 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
1797 1797 sarg->cs->cr, NULL);
1798 1798 if (!error && (na->maxlink != (uint32_t)val))
1799 1799 error = -1; /* no match */
1800 1800 break;
1801 1801 case NFS4ATTR_FREEIT:
1802 1802 break;
1803 1803 }
1804 1804 return (error);
1805 1805 }
1806 1806
1807 1807 /* ARGSUSED */
1808 1808 static int
1809 1809 rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1810 1810 union nfs4_attr_u *na)
1811 1811 {
1812 1812 int error = 0;
1813 1813 ulong_t val;
1814 1814
1815 1815 if (RFS4_MANDATTR_ONLY)
1816 1816 return (ENOTSUP);
1817 1817
1818 1818 switch (cmd) {
1819 1819 case NFS4ATTR_SUPPORTED:
1820 1820 if (sarg->op == NFS4ATTR_SETIT)
1821 1821 error = EINVAL;
1822 1822 break; /* this attr is supported */
1823 1823 case NFS4ATTR_GETIT:
1824 1824 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1825 1825 error = -1; /* may be okay if rdattr_error */
1826 1826 break;
1827 1827 }
1828 1828 ASSERT(sarg->cs->vp != NULL);
1829 1829 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
1830 1830 sarg->cs->cr, NULL);
1831 1831 if (error == 0) {
1832 1832 na->maxname = val;
1833 1833 }
1834 1834 break;
1835 1835 case NFS4ATTR_SETIT:
1836 1836 /*
1837 1837 * read-only attr
1838 1838 */
1839 1839 error = EINVAL;
1840 1840 break;
1841 1841 case NFS4ATTR_VERIT:
1842 1842 ASSERT(sarg->cs->vp != NULL);
1843 1843 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
1844 1844 sarg->cs->cr, NULL);
1845 1845 if (!error && (na->maxname != val))
1846 1846 error = -1; /* no match */
1847 1847 break;
1848 1848 case NFS4ATTR_FREEIT:
1849 1849 break;
1850 1850 }
1851 1851 return (error);
1852 1852 }
1853 1853
1854 1854 /* ARGSUSED */
1855 1855 static int
1856 1856 rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1857 1857 union nfs4_attr_u *na)
1858 1858 {
1859 1859 int error = 0;
1860 1860
1861 1861 if (RFS4_MANDATTR_ONLY)
1862 1862 return (ENOTSUP);
1863 1863
1864 1864 switch (cmd) {
1865 1865 case NFS4ATTR_SUPPORTED:
1866 1866 if (sarg->op == NFS4ATTR_SETIT)
1867 1867 error = EINVAL;
1868 1868 break; /* this attr is supported */
1869 1869 case NFS4ATTR_GETIT:
1870 1870 na->maxread = rfs4_tsize(sarg->cs->req);
1871 1871 break;
1872 1872 case NFS4ATTR_SETIT:
1873 1873 /*
1874 1874 * read-only attr
1875 1875 */
1876 1876 error = EINVAL;
1877 1877 break;
1878 1878 case NFS4ATTR_VERIT:
1879 1879 if (na->maxread != rfs4_tsize(sarg->cs->req))
1880 1880 error = -1; /* no match */
1881 1881 break;
1882 1882 case NFS4ATTR_FREEIT:
1883 1883 break;
1884 1884 }
1885 1885 return (error);
1886 1886 }
1887 1887
1888 1888 /* ARGSUSED */
1889 1889 static int
1890 1890 rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1891 1891 union nfs4_attr_u *na)
1892 1892 {
1893 1893 int error = 0;
1894 1894
1895 1895 if (RFS4_MANDATTR_ONLY)
1896 1896 return (ENOTSUP);
1897 1897
1898 1898 switch (cmd) {
1899 1899 case NFS4ATTR_SUPPORTED:
1900 1900 if (sarg->op == NFS4ATTR_SETIT)
1901 1901 error = EINVAL;
1902 1902 break; /* this attr is supported */
1903 1903 case NFS4ATTR_GETIT:
1904 1904 na->maxwrite = rfs4_tsize(sarg->cs->req);
1905 1905 break;
1906 1906 case NFS4ATTR_SETIT:
1907 1907 /*
1908 1908 * read-only attr
1909 1909 */
1910 1910 error = EINVAL;
1911 1911 break;
1912 1912 case NFS4ATTR_VERIT:
1913 1913 if (na->maxwrite != rfs4_tsize(sarg->cs->req))
1914 1914 error = -1; /* no match */
1915 1915 break;
1916 1916 case NFS4ATTR_FREEIT:
1917 1917 break;
1918 1918 }
1919 1919 return (error);
1920 1920 }
1921 1921
1922 1922 /* ARGSUSED */
1923 1923 static int
1924 1924 rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1925 1925 union nfs4_attr_u *na)
1926 1926 {
1927 1927 return (ENOTSUP);
1928 1928 }
1929 1929
1930 1930 /* ARGSUSED */
1931 1931 static int
1932 1932 rfs4_fattr4_mode(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1933 1933 union nfs4_attr_u *na)
1934 1934 {
1935 1935 int error = 0;
1936 1936
1937 1937 if (RFS4_MANDATTR_ONLY)
1938 1938 return (ENOTSUP);
1939 1939
1940 1940 switch (cmd) {
1941 1941 case NFS4ATTR_SUPPORTED:
1942 1942 break; /* this attr is supported */
1943 1943 case NFS4ATTR_GETIT:
1944 1944 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MODE)) {
1945 1945 error = -1; /* may be okay if rdattr_error */
1946 1946 break;
1947 1947 }
1948 1948 ASSERT(sarg->vap->va_mask & AT_MODE);
1949 1949 na->mode = sarg->vap->va_mode;
1950 1950 break;
1951 1951 case NFS4ATTR_SETIT:
1952 1952 ASSERT(sarg->vap->va_mask & AT_MODE);
1953 1953 sarg->vap->va_mode = na->mode;
1954 1954 /*
1955 1955 * If the filesystem is exported with nosuid, then mask off
1956 1956 * the setuid and setgid bits.
1957 1957 */
1958 1958 if (sarg->cs->vp->v_type == VREG &&
1959 1959 (sarg->cs->exi->exi_export.ex_flags & EX_NOSUID))
1960 1960 sarg->vap->va_mode &= ~(VSUID | VSGID);
1961 1961 break;
1962 1962 case NFS4ATTR_VERIT:
1963 1963 ASSERT(sarg->vap->va_mask & AT_MODE);
1964 1964 if (sarg->vap->va_mode != na->mode)
1965 1965 error = -1; /* no match */
1966 1966 break;
1967 1967 case NFS4ATTR_FREEIT:
1968 1968 break;
1969 1969 }
1970 1970 return (error);
1971 1971 }
1972 1972
1973 1973 /* ARGSUSED */
1974 1974 static int
1975 1975 rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1976 1976 union nfs4_attr_u *na)
1977 1977 {
1978 1978 int error = 0;
1979 1979
1980 1980 if (RFS4_MANDATTR_ONLY)
1981 1981 return (ENOTSUP);
1982 1982
1983 1983 switch (cmd) {
1984 1984 case NFS4ATTR_SUPPORTED:
1985 1985 if (sarg->op == NFS4ATTR_SETIT)
1986 1986 error = EINVAL;
1987 1987 break; /* this attr is supported */
1988 1988 case NFS4ATTR_GETIT:
1989 1989 na->no_trunc = TRUE;
1990 1990 break;
1991 1991 case NFS4ATTR_SETIT:
1992 1992 /*
1993 1993 * read-only attr
1994 1994 */
1995 1995 error = EINVAL;
1996 1996 break;
1997 1997 case NFS4ATTR_VERIT:
1998 1998 if (!na->no_trunc)
1999 1999 error = -1; /* no match */
2000 2000 break;
2001 2001 case NFS4ATTR_FREEIT:
2002 2002 break;
2003 2003 }
2004 2004 return (error);
2005 2005 }
2006 2006
2007 2007 /* ARGSUSED */
2008 2008 static int
2009 2009 rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2010 2010 union nfs4_attr_u *na)
2011 2011 {
2012 2012 int error = 0;
2013 2013
2014 2014 if (RFS4_MANDATTR_ONLY)
2015 2015 return (ENOTSUP);
2016 2016
2017 2017 switch (cmd) {
2018 2018 case NFS4ATTR_SUPPORTED:
2019 2019 if (sarg->op == NFS4ATTR_SETIT)
2020 2020 error = EINVAL;
2021 2021 break; /* this attr is supported */
2022 2022 case NFS4ATTR_GETIT:
2023 2023 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NLINK)) {
2024 2024 error = -1; /* may be okay if rdattr_error */
2025 2025 break;
2026 2026 }
2027 2027 ASSERT(sarg->vap->va_mask & AT_NLINK);
2028 2028 na->numlinks = sarg->vap->va_nlink;
2029 2029 break;
2030 2030 case NFS4ATTR_SETIT:
2031 2031 /*
2032 2032 * read-only attr
2033 2033 */
2034 2034 error = EINVAL;
2035 2035 break;
2036 2036 case NFS4ATTR_VERIT:
2037 2037 ASSERT(sarg->vap->va_mask & AT_NLINK);
2038 2038 if (sarg->vap->va_nlink != na->numlinks)
2039 2039 error = -1; /* no match */
2040 2040 break;
2041 2041 case NFS4ATTR_FREEIT:
2042 2042 break;
2043 2043 }
2044 2044 return (error);
2045 2045 }
2046 2046
2047 2047 /* ARGSUSED */
2048 2048 static int
2049 2049 rfs4_fattr4_owner(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2050 2050 union nfs4_attr_u *na)
2051 2051 {
2052 2052 int error = 0;
2053 2053 uid_t uid;
2054 2054
2055 2055 if (RFS4_MANDATTR_ONLY)
2056 2056 return (ENOTSUP);
2057 2057
2058 2058 switch (cmd) {
2059 2059 case NFS4ATTR_SUPPORTED:
2060 2060 break; /* this attr is supported */
2061 2061 case NFS4ATTR_GETIT:
2062 2062 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_UID)) {
2063 2063 error = -1; /* may be okay if rdattr_error */
2064 2064 break;
2065 2065 }
2066 2066 ASSERT(sarg->vap->va_mask & AT_UID);
2067 2067
2068 2068 /*
2069 2069 * There are well defined polices for what happens on server-
2070 2070 * side GETATTR when uid to attribute string conversion cannot
2071 2071 * occur. Please refer to nfs4_idmap.c for details.
2072 2072 */
2073 2073 error = nfs_idmap_uid_str(sarg->vap->va_uid, &na->owner, TRUE);
2074 2074 switch (error) {
2075 2075 case ECONNREFUSED:
2076 2076 error = NFS4ERR_DELAY;
2077 2077 break;
2078 2078 default:
2079 2079 break;
2080 2080 }
2081 2081 break;
2082 2082
2083 2083 case NFS4ATTR_SETIT:
2084 2084 ASSERT(sarg->vap->va_mask & AT_UID);
2085 2085
2086 2086 /*
2087 2087 * There are well defined policies for what happens on server-
2088 2088 * side SETATTR of 'owner' when a "user@domain" mapping cannot
2089 2089 * occur. Please refer to nfs4_idmap.c for details.
2090 2090 *
2091 2091 * Any other errors, such as the mapping not being found by
2092 2092 * nfsmapid(1m), and interrupted clnt_call, etc, will result
2093 2093 * in NFS4ERR_BADOWNER.
2094 2094 *
2095 2095 * XXX need to return consistent errors, perhaps all
2096 2096 * server side attribute routines should return NFS4ERR*.
2097 2097 */
2098 2098 error = nfs_idmap_str_uid(&na->owner, &sarg->vap->va_uid, TRUE);
2099 2099 switch (error) {
2100 2100 case NFS4_OK:
2101 2101 case ENOTSUP:
2102 2102 /*
2103 2103 * Ignore warning that we are the
2104 2104 * nfsmapid (can't happen on srv)
2105 2105 */
2106 2106 error = 0;
2107 2107 MSG_PRT_DEBUG = FALSE;
2108 2108 break;
2109 2109
2110 2110 case ECOMM:
2111 2111 case ECONNREFUSED:
2112 2112 if (!MSG_PRT_DEBUG) {
2113 2113 /*
2114 2114 * printed just once per daemon death,
2115 2115 * inform the user and then stay silent
2116 2116 */
2117 2117 cmn_err(CE_WARN, "!Unable to contact "
2118 2118 "nfsmapid");
2119 2119 MSG_PRT_DEBUG = TRUE;
2120 2120 }
2121 2121 error = NFS4ERR_DELAY;
2122 2122 break;
2123 2123
2124 2124 case EINVAL:
2125 2125 error = NFS4ERR_INVAL;
2126 2126 break;
2127 2127
2128 2128 default:
2129 2129 error = NFS4ERR_BADOWNER;
2130 2130 break;
2131 2131 }
2132 2132 break;
2133 2133
2134 2134 case NFS4ATTR_VERIT:
2135 2135 ASSERT(sarg->vap->va_mask & AT_UID);
2136 2136 error = nfs_idmap_str_uid(&na->owner, &uid, TRUE);
2137 2137 /*
2138 2138 * Ignore warning that we are the nfsmapid (can't happen on srv)
2139 2139 */
2140 2140 if (error == ENOTSUP)
2141 2141 error = 0;
2142 2142 if (error)
2143 2143 error = -1; /* no match */
2144 2144 else if (sarg->vap->va_uid != uid)
2145 2145 error = -1; /* no match */
2146 2146 break;
2147 2147 case NFS4ATTR_FREEIT:
2148 2148 if (sarg->op == NFS4ATTR_GETIT) {
2149 2149 if (na->owner.utf8string_val) {
2150 2150 UTF8STRING_FREE(na->owner)
2151 2151 bzero(&na->owner, sizeof (na->owner));
2152 2152 }
2153 2153 }
2154 2154 break;
2155 2155 }
2156 2156 return (error);
2157 2157 }
2158 2158
2159 2159 /* ARGSUSED */
2160 2160 static int
2161 2161 rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2162 2162 union nfs4_attr_u *na)
2163 2163 {
2164 2164 int error = 0;
2165 2165 gid_t gid;
2166 2166
2167 2167 if (RFS4_MANDATTR_ONLY)
2168 2168 return (ENOTSUP);
2169 2169
2170 2170 switch (cmd) {
2171 2171 case NFS4ATTR_SUPPORTED:
2172 2172 break; /* this attr is supported */
2173 2173 case NFS4ATTR_GETIT:
2174 2174 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_GID)) {
2175 2175 error = -1; /* may be okay if rdattr_error */
2176 2176 break;
2177 2177 }
2178 2178 ASSERT(sarg->vap->va_mask & AT_GID);
2179 2179
2180 2180 /*
2181 2181 * There are well defined polices for what happens on server-
2182 2182 * side GETATTR when gid to attribute string conversion cannot
2183 2183 * occur. Please refer to nfs4_idmap.c for details.
2184 2184 */
2185 2185 error = nfs_idmap_gid_str(sarg->vap->va_gid, &na->owner_group,
2186 2186 TRUE);
2187 2187 switch (error) {
2188 2188 case ECONNREFUSED:
2189 2189 error = NFS4ERR_DELAY;
2190 2190 break;
2191 2191 default:
2192 2192 break;
2193 2193 }
2194 2194 break;
2195 2195
2196 2196 case NFS4ATTR_SETIT:
2197 2197 ASSERT(sarg->vap->va_mask & AT_GID);
2198 2198
2199 2199 /*
2200 2200 * There are well defined policies for what happens on server-
2201 2201 * side SETATTR of 'owner_group' when a "group@domain" mapping
2202 2202 * cannot occur. Please refer to nfs4_idmap.c for details.
2203 2203 *
2204 2204 * Any other errors, such as the mapping not being found by
2205 2205 * nfsmapid(1m), and interrupted clnt_call, etc, will result
2206 2206 * in NFS4ERR_BADOWNER.
2207 2207 *
2208 2208 * XXX need to return consistent errors, perhaps all
2209 2209 * server side attribute routines should return NFS4ERR*.
2210 2210 */
2211 2211 error = nfs_idmap_str_gid(&na->owner_group, &sarg->vap->va_gid,
2212 2212 TRUE);
2213 2213 switch (error) {
2214 2214 case NFS4_OK:
2215 2215 case ENOTSUP:
2216 2216 /*
2217 2217 * Ignore warning that we are the
2218 2218 * nfsmapid (can't happen on srv)
2219 2219 */
2220 2220 error = 0;
2221 2221 MSG_PRT_DEBUG = FALSE;
2222 2222 break;
2223 2223
2224 2224 case ECOMM:
2225 2225 case ECONNREFUSED:
2226 2226 if (!MSG_PRT_DEBUG) {
2227 2227 /*
2228 2228 * printed just once per daemon death,
2229 2229 * inform the user and then stay silent
2230 2230 */
2231 2231 cmn_err(CE_WARN, "!Unable to contact "
2232 2232 "nfsmapid");
2233 2233 MSG_PRT_DEBUG = TRUE;
2234 2234 }
2235 2235 error = NFS4ERR_DELAY;
2236 2236 break;
2237 2237
2238 2238 case EINVAL:
2239 2239 error = NFS4ERR_INVAL;
2240 2240 break;
2241 2241
2242 2242 default:
2243 2243 error = NFS4ERR_BADOWNER;
2244 2244 break;
2245 2245 }
2246 2246 break;
2247 2247
2248 2248 case NFS4ATTR_VERIT:
2249 2249 ASSERT(sarg->vap->va_mask & AT_GID);
2250 2250 error = nfs_idmap_str_gid(&na->owner_group, &gid, TRUE);
2251 2251 /*
2252 2252 * Ignore warning that we are the nfsmapid (can't happen on srv)
2253 2253 */
2254 2254 if (error == ENOTSUP)
2255 2255 error = 0;
2256 2256 if (error)
2257 2257 error = -1; /* no match */
2258 2258 else if (sarg->vap->va_gid != gid)
2259 2259 error = -1; /* no match */
2260 2260 break;
2261 2261 case NFS4ATTR_FREEIT:
2262 2262 if (sarg->op == NFS4ATTR_GETIT) {
2263 2263 if (na->owner_group.utf8string_val) {
2264 2264 UTF8STRING_FREE(na->owner_group)
2265 2265 bzero(&na->owner_group,
2266 2266 sizeof (na->owner_group));
2267 2267 }
2268 2268 }
2269 2269 break;
2270 2270 }
2271 2271 return (error);
2272 2272 }
2273 2273
2274 2274 /* XXX - quota attributes should be supportable on Solaris 2 */
2275 2275 /* ARGSUSED */
2276 2276 static int
2277 2277 rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2278 2278 union nfs4_attr_u *na)
2279 2279 {
2280 2280 return (ENOTSUP);
2281 2281 }
2282 2282
2283 2283 /* ARGSUSED */
2284 2284 static int
2285 2285 rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2286 2286 union nfs4_attr_u *na)
2287 2287 {
2288 2288 return (ENOTSUP);
2289 2289 }
2290 2290
2291 2291 /* ARGSUSED */
2292 2292 static int
2293 2293 rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2294 2294 union nfs4_attr_u *na)
2295 2295 {
2296 2296 return (ENOTSUP);
2297 2297 }
2298 2298
2299 2299 /* ARGSUSED */
2300 2300 static int
2301 2301 rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2302 2302 union nfs4_attr_u *na)
2303 2303 {
2304 2304 int error = 0;
2305 2305
2306 2306 if (RFS4_MANDATTR_ONLY)
2307 2307 return (ENOTSUP);
2308 2308
2309 2309 switch (cmd) {
2310 2310 case NFS4ATTR_SUPPORTED:
2311 2311 if (sarg->op == NFS4ATTR_SETIT)
2312 2312 error = EINVAL;
2313 2313 break; /* this attr is supported */
2314 2314 case NFS4ATTR_GETIT:
2315 2315 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_RDEV)) {
2316 2316 error = -1; /* may be okay if rdattr_error */
2317 2317 break;
2318 2318 }
2319 2319 ASSERT(sarg->vap->va_mask & AT_RDEV);
2320 2320 na->rawdev.specdata1 = (uint32)getmajor(sarg->vap->va_rdev);
2321 2321 na->rawdev.specdata2 = (uint32)getminor(sarg->vap->va_rdev);
2322 2322 break;
2323 2323 case NFS4ATTR_SETIT:
2324 2324 /*
2325 2325 * read-only attr
2326 2326 */
2327 2327 error = EINVAL;
2328 2328 break;
2329 2329 case NFS4ATTR_VERIT:
2330 2330 ASSERT(sarg->vap->va_mask & AT_RDEV);
2331 2331 if ((na->rawdev.specdata1 !=
2332 2332 (uint32)getmajor(sarg->vap->va_rdev)) ||
2333 2333 (na->rawdev.specdata2 !=
2334 2334 (uint32)getminor(sarg->vap->va_rdev)))
2335 2335 error = -1; /* no match */
2336 2336 break;
2337 2337 case NFS4ATTR_FREEIT:
2338 2338 break;
2339 2339 }
2340 2340 return (error);
2341 2341 }
2342 2342
2343 2343 /* ARGSUSED */
2344 2344 static int
2345 2345 rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2346 2346 union nfs4_attr_u *na)
2347 2347 {
2348 2348 int error = 0;
2349 2349
2350 2350 if (RFS4_MANDATTR_ONLY)
2351 2351 return (ENOTSUP);
2352 2352
2353 2353 switch (cmd) {
2354 2354 case NFS4ATTR_SUPPORTED:
2355 2355 if (sarg->op == NFS4ATTR_SETIT)
2356 2356 error = EINVAL;
2357 2357 break; /* this attr is supported */
2358 2358 case NFS4ATTR_GETIT:
2359 2359 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
2360 2360 error = -1; /* may be okay if rdattr_error */
2361 2361 break;
2362 2362 }
2363 2363 ASSERT(sarg->sbp != NULL);
2364 2364 if (sarg->sbp->f_bavail != (fsblkcnt64_t)-1) {
2365 2365 na->space_avail =
2366 2366 (fattr4_space_avail) sarg->sbp->f_frsize *
2367 2367 (fattr4_space_avail) sarg->sbp->f_bavail;
2368 2368 } else {
2369 2369 na->space_avail =
2370 2370 (fattr4_space_avail) sarg->sbp->f_bavail;
2371 2371 }
2372 2372 break;
2373 2373 case NFS4ATTR_SETIT:
2374 2374 /*
2375 2375 * read-only attr
2376 2376 */
2377 2377 error = EINVAL;
2378 2378 break;
2379 2379 case NFS4ATTR_VERIT:
2380 2380 ASSERT(sarg->sbp != NULL);
2381 2381 if (sarg->sbp->f_bavail != na->space_avail)
2382 2382 error = -1; /* no match */
2383 2383 break;
2384 2384 case NFS4ATTR_FREEIT:
2385 2385 break;
2386 2386 }
2387 2387 return (error);
2388 2388 }
2389 2389
2390 2390 /* ARGSUSED */
2391 2391 static int
2392 2392 rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2393 2393 union nfs4_attr_u *na)
2394 2394 {
2395 2395 int error = 0;
2396 2396
2397 2397 if (RFS4_MANDATTR_ONLY)
2398 2398 return (ENOTSUP);
2399 2399
2400 2400 switch (cmd) {
2401 2401 case NFS4ATTR_SUPPORTED:
2402 2402 if (sarg->op == NFS4ATTR_SETIT)
2403 2403 error = EINVAL;
2404 2404 break; /* this attr is supported */
2405 2405 case NFS4ATTR_GETIT:
2406 2406 if (sarg->rdattr_error && (sarg->sbp == NULL)) {
2407 2407 error = -1; /* may be okay if rdattr_error */
2408 2408 break;
2409 2409 }
2410 2410 ASSERT(sarg->sbp != NULL);
2411 2411 if (sarg->sbp->f_bfree != (fsblkcnt64_t)-1) {
2412 2412 na->space_free =
2413 2413 (fattr4_space_free) sarg->sbp->f_frsize *
2414 2414 (fattr4_space_free) sarg->sbp->f_bfree;
2415 2415 } else {
2416 2416 na->space_free =
2417 2417 (fattr4_space_free) sarg->sbp->f_bfree;
2418 2418 }
2419 2419 break;
2420 2420 case NFS4ATTR_SETIT:
2421 2421 /*
2422 2422 * read-only attr
2423 2423 */
2424 2424 error = EINVAL;
2425 2425 break;
2426 2426 case NFS4ATTR_VERIT:
2427 2427 ASSERT(sarg->sbp != NULL);
2428 2428 if (sarg->sbp->f_bfree != na->space_free)
2429 2429 error = -1; /* no match */
2430 2430 break;
2431 2431 case NFS4ATTR_FREEIT:
2432 2432 break;
2433 2433 }
2434 2434 return (error);
2435 2435 }
2436 2436
2437 2437 /* ARGSUSED */
2438 2438 static int
2439 2439 rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2440 2440 union nfs4_attr_u *na)
2441 2441 {
2442 2442 int error = 0;
2443 2443
2444 2444 if (RFS4_MANDATTR_ONLY)
2445 2445 return (ENOTSUP);
2446 2446
2447 2447 switch (cmd) {
2448 2448 case NFS4ATTR_SUPPORTED:
2449 2449 if (sarg->op == NFS4ATTR_SETIT)
2450 2450 error = EINVAL;
2451 2451 break; /* this attr is supported */
2452 2452 case NFS4ATTR_GETIT:
2453 2453 if (sarg->rdattr_error_req && (sarg->sbp == NULL)) {
2454 2454 error = -1; /* may be okay if rdattr_error */
2455 2455 break;
2456 2456 }
2457 2457 ASSERT(sarg->sbp != NULL);
2458 2458 if (sarg->sbp->f_blocks != (fsblkcnt64_t)-1) {
2459 2459 na->space_total =
2460 2460 (fattr4_space_total) sarg->sbp->f_frsize *
2461 2461 (fattr4_space_total) sarg->sbp->f_blocks;
2462 2462 } else {
2463 2463 na->space_total =
2464 2464 (fattr4_space_total) sarg->sbp->f_blocks;
2465 2465 }
2466 2466 break;
2467 2467 case NFS4ATTR_SETIT:
2468 2468 /*
2469 2469 * read-only attr
2470 2470 */
2471 2471 error = EINVAL;
2472 2472 break;
2473 2473 case NFS4ATTR_VERIT:
2474 2474 ASSERT(sarg->sbp != NULL);
2475 2475 if (sarg->sbp->f_blocks != na->space_total)
2476 2476 error = -1; /* no match */
2477 2477 break;
2478 2478 case NFS4ATTR_FREEIT:
2479 2479 break;
2480 2480 }
2481 2481 return (error);
2482 2482 }
2483 2483
2484 2484 /* ARGSUSED */
2485 2485 static int
2486 2486 rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2487 2487 union nfs4_attr_u *na)
2488 2488 {
2489 2489 int error = 0;
2490 2490
2491 2491 if (RFS4_MANDATTR_ONLY)
2492 2492 return (ENOTSUP);
2493 2493
2494 2494 switch (cmd) {
2495 2495 case NFS4ATTR_SUPPORTED:
2496 2496 if (sarg->op == NFS4ATTR_SETIT)
2497 2497 error = EINVAL;
2498 2498 break; /* this attr is supported */
2499 2499 case NFS4ATTR_GETIT:
2500 2500 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NBLOCKS)) {
2501 2501 error = -1; /* may be okay if rdattr_error */
2502 2502 break;
2503 2503 }
2504 2504 ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
2505 2505 na->space_used = (fattr4_space_used) DEV_BSIZE *
2506 2506 (fattr4_space_used) sarg->vap->va_nblocks;
2507 2507 break;
2508 2508 case NFS4ATTR_SETIT:
2509 2509 /*
2510 2510 * read-only attr
2511 2511 */
2512 2512 error = EINVAL;
2513 2513 break;
2514 2514 case NFS4ATTR_VERIT:
2515 2515 ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
2516 2516 if (sarg->vap->va_nblocks != na->space_used)
2517 2517 error = -1; /* no match */
2518 2518 break;
2519 2519 case NFS4ATTR_FREEIT:
2520 2520 break;
2521 2521 }
2522 2522 return (error);
2523 2523 }
2524 2524
2525 2525 /* ARGSUSED */
2526 2526 static int
2527 2527 rfs4_fattr4_system(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2528 2528 union nfs4_attr_u *na)
2529 2529 {
2530 2530 return (ENOTSUP);
2531 2531 }
2532 2532
2533 2533 /* ARGSUSED */
2534 2534 static int
2535 2535 rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2536 2536 union nfs4_attr_u *na)
2537 2537 {
2538 2538 int error = 0;
2539 2539 timestruc_t atime;
2540 2540
2541 2541 if (RFS4_MANDATTR_ONLY)
2542 2542 return (ENOTSUP);
2543 2543
2544 2544 switch (cmd) {
2545 2545 case NFS4ATTR_SUPPORTED:
2546 2546 if (sarg->op == NFS4ATTR_SETIT)
2547 2547 error = EINVAL;
2548 2548 break; /* this attr is supported */
2549 2549 case NFS4ATTR_GETIT:
2550 2550 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_ATIME)) {
2551 2551 error = -1; /* may be okay if rdattr_error */
2552 2552 break;
2553 2553 }
2554 2554 ASSERT(sarg->vap->va_mask & AT_ATIME);
2555 2555 error = nfs4_time_vton(&sarg->vap->va_atime, &na->time_access);
2556 2556 break;
2557 2557 case NFS4ATTR_SETIT:
2558 2558 /*
2559 2559 * read-only attr
2560 2560 */
2561 2561 error = EINVAL;
2562 2562 break;
2563 2563 case NFS4ATTR_VERIT:
2564 2564 ASSERT(sarg->vap->va_mask & AT_ATIME);
2565 2565 error = nfs4_time_ntov(&na->time_access, &atime);
2566 2566 if (error)
2567 2567 break;
2568 2568 if (bcmp(&atime, &sarg->vap->va_atime, sizeof (atime)))
2569 2569 error = -1; /* no match */
2570 2570 break;
2571 2571 case NFS4ATTR_FREEIT:
2572 2572 break;
2573 2573 }
2574 2574 return (error);
2575 2575 }
2576 2576
2577 2577 /*
2578 2578 * XXX - need to support the setting of access time
2579 2579 */
2580 2580 /* ARGSUSED */
2581 2581 static int
2582 2582 rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2583 2583 union nfs4_attr_u *na)
2584 2584 {
2585 2585 int error = 0;
2586 2586 settime4 *ta;
2587 2587
2588 2588 if (RFS4_MANDATTR_ONLY)
2589 2589 return (ENOTSUP);
2590 2590
2591 2591 switch (cmd) {
2592 2592 case NFS4ATTR_SUPPORTED:
2593 2593 if ((sarg->op == NFS4ATTR_GETIT) ||
2594 2594 (sarg->op == NFS4ATTR_VERIT))
2595 2595 error = EINVAL;
2596 2596 break; /* this attr is supported */
2597 2597 case NFS4ATTR_GETIT:
2598 2598 case NFS4ATTR_VERIT:
2599 2599 /*
2600 2600 * write only attr
2601 2601 */
2602 2602 error = EINVAL;
2603 2603 break;
2604 2604 case NFS4ATTR_SETIT:
2605 2605 ASSERT(sarg->vap->va_mask & AT_ATIME);
2606 2606 /*
2607 2607 * Set access time (by server or by client)
2608 2608 */
2609 2609 ta = &na->time_access_set;
2610 2610 if (ta->set_it == SET_TO_CLIENT_TIME4) {
2611 2611 error = nfs4_time_ntov(&ta->time, &sarg->vap->va_atime);
2612 2612 } else if (ta->set_it == SET_TO_SERVER_TIME4) {
2613 2613 gethrestime(&sarg->vap->va_atime);
2614 2614 } else {
2615 2615 error = EINVAL;
2616 2616 }
2617 2617 break;
2618 2618 case NFS4ATTR_FREEIT:
2619 2619 break;
2620 2620 }
2621 2621 return (error);
2622 2622 }
2623 2623
2624 2624 /* ARGSUSED */
2625 2625 static int
2626 2626 rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2627 2627 union nfs4_attr_u *na)
2628 2628 {
2629 2629 return (ENOTSUP);
2630 2630 }
2631 2631
2632 2632 /* ARGSUSED */
2633 2633 static int
2634 2634 rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2635 2635 union nfs4_attr_u *na)
2636 2636 {
2637 2637 return (ENOTSUP);
2638 2638 }
2639 2639
2640 2640 /* ARGSUSED */
2641 2641 static int
2642 2642 rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2643 2643 union nfs4_attr_u *na)
2644 2644 {
2645 2645 int error = 0;
2646 2646
2647 2647 if (RFS4_MANDATTR_ONLY)
2648 2648 return (ENOTSUP);
2649 2649
2650 2650 switch (cmd) {
2651 2651 case NFS4ATTR_SUPPORTED:
2652 2652 if (sarg->op == NFS4ATTR_SETIT)
2653 2653 error = EINVAL;
2654 2654 break; /* this attr is supported */
2655 2655 case NFS4ATTR_GETIT:
2656 2656 na->time_delta.seconds = 0;
2657 2657 na->time_delta.nseconds = 1000;
2658 2658 break;
2659 2659 case NFS4ATTR_SETIT:
2660 2660 /*
2661 2661 * write only attr
2662 2662 */
2663 2663 error = EINVAL;
2664 2664 break;
2665 2665 case NFS4ATTR_VERIT:
2666 2666 if ((na->time_delta.seconds != 0) ||
2667 2667 (na->time_delta.nseconds != 1000))
2668 2668 error = -1; /* no match */
2669 2669 break;
2670 2670 case NFS4ATTR_FREEIT:
2671 2671 break;
2672 2672 }
2673 2673 return (error);
2674 2674 }
2675 2675
2676 2676 /* ARGSUSED */
2677 2677 static int
2678 2678 rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2679 2679 union nfs4_attr_u *na)
2680 2680 {
2681 2681 int error = 0;
2682 2682 timestruc_t ctime;
2683 2683
2684 2684 if (RFS4_MANDATTR_ONLY)
2685 2685 return (ENOTSUP);
2686 2686
2687 2687 switch (cmd) {
2688 2688 case NFS4ATTR_SUPPORTED:
2689 2689 if (sarg->op == NFS4ATTR_SETIT)
2690 2690 error = EINVAL;
2691 2691 break; /* this attr is supported */
2692 2692 case NFS4ATTR_GETIT:
2693 2693 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_CTIME)) {
2694 2694 error = -1; /* may be okay if rdattr_error */
2695 2695 break;
2696 2696 }
2697 2697 ASSERT(sarg->vap->va_mask & AT_CTIME);
2698 2698 error = nfs4_time_vton(&sarg->vap->va_ctime,
2699 2699 &na->time_metadata);
2700 2700 break;
2701 2701 case NFS4ATTR_SETIT:
2702 2702 /*
2703 2703 * read-only attr
2704 2704 */
2705 2705 error = EINVAL;
2706 2706 break;
2707 2707 case NFS4ATTR_VERIT:
2708 2708 ASSERT(sarg->vap->va_mask & AT_CTIME);
2709 2709 error = nfs4_time_ntov(&na->time_metadata, &ctime);
2710 2710 if (error)
2711 2711 break;
2712 2712 if (bcmp(&ctime, &sarg->vap->va_ctime, sizeof (ctime)))
2713 2713 error = -1; /* no match */
2714 2714 break;
2715 2715 case NFS4ATTR_FREEIT:
2716 2716 break;
2717 2717 }
2718 2718 return (error);
2719 2719 }
2720 2720
2721 2721 /* ARGSUSED */
2722 2722 static int
2723 2723 rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2724 2724 union nfs4_attr_u *na)
2725 2725 {
2726 2726 int error = 0;
2727 2727 timestruc_t mtime;
2728 2728
2729 2729 if (RFS4_MANDATTR_ONLY)
2730 2730 return (ENOTSUP);
2731 2731
2732 2732 switch (cmd) {
2733 2733 case NFS4ATTR_SUPPORTED:
2734 2734 if (sarg->op == NFS4ATTR_SETIT)
2735 2735 error = EINVAL;
2736 2736 break; /* this attr is supported */
2737 2737 case NFS4ATTR_GETIT:
2738 2738 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MTIME)) {
2739 2739 error = -1; /* may be okay if rdattr_error */
2740 2740 break;
2741 2741 }
2742 2742 ASSERT(sarg->vap->va_mask & AT_MTIME);
2743 2743 error = nfs4_time_vton(&sarg->vap->va_mtime, &na->time_modify);
2744 2744 break;
2745 2745 case NFS4ATTR_SETIT:
2746 2746 /*
2747 2747 * read-only attr
2748 2748 */
2749 2749 error = EINVAL;
2750 2750 break;
2751 2751 case NFS4ATTR_VERIT:
2752 2752 ASSERT(sarg->vap->va_mask & AT_MTIME);
2753 2753 error = nfs4_time_ntov(&na->time_modify, &mtime);
2754 2754 if (error)
2755 2755 break;
2756 2756 if (bcmp(&mtime, &sarg->vap->va_mtime, sizeof (mtime)))
2757 2757 error = -1; /* no match */
2758 2758 break;
2759 2759 case NFS4ATTR_FREEIT:
2760 2760 break;
2761 2761 }
2762 2762 return (error);
2763 2763 }
2764 2764
2765 2765 /*
2766 2766 * XXX - need to add support for setting modify time
2767 2767 */
2768 2768 /* ARGSUSED */
2769 2769 static int
2770 2770 rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2771 2771 union nfs4_attr_u *na)
2772 2772 {
2773 2773 int error = 0;
2774 2774 settime4 *tm;
2775 2775
2776 2776 if (RFS4_MANDATTR_ONLY)
2777 2777 return (ENOTSUP);
2778 2778
2779 2779 switch (cmd) {
2780 2780 case NFS4ATTR_SUPPORTED:
2781 2781 if ((sarg->op == NFS4ATTR_GETIT) ||
2782 2782 (sarg->op == NFS4ATTR_VERIT))
2783 2783 error = EINVAL;
2784 2784 break; /* this attr is supported */
2785 2785 case NFS4ATTR_GETIT:
2786 2786 case NFS4ATTR_VERIT:
2787 2787 /*
2788 2788 * write only attr
2789 2789 */
2790 2790 error = EINVAL;
2791 2791 break;
2792 2792 case NFS4ATTR_SETIT:
2793 2793 ASSERT(sarg->vap->va_mask & AT_MTIME);
2794 2794 /*
2795 2795 * Set modify time (by server or by client)
2796 2796 */
2797 2797 tm = &na->time_modify_set;
2798 2798 if (tm->set_it == SET_TO_CLIENT_TIME4) {
2799 2799 error = nfs4_time_ntov(&tm->time, &sarg->vap->va_mtime);
2800 2800 sarg->flag = ATTR_UTIME;
2801 2801 } else if (tm->set_it == SET_TO_SERVER_TIME4) {
2802 2802 gethrestime(&sarg->vap->va_mtime);
2803 2803 } else {
2804 2804 error = EINVAL;
2805 2805 }
2806 2806 break;
2807 2807 case NFS4ATTR_FREEIT:
2808 2808 break;
2809 2809 }
2810 2810 return (error);
2811 2811 }
2812 2812
2813 2813
2814 2814 static void
2815 2815 rfs4_ntov_init(void)
2816 2816 {
2817 2817 /* index must be same as corresponding FATTR4_* define */
2818 2818 nfs4_ntov_map[0].sv_getit = rfs4_fattr4_supported_attrs;
2819 2819 nfs4_ntov_map[1].sv_getit = rfs4_fattr4_type;
2820 2820 nfs4_ntov_map[2].sv_getit = rfs4_fattr4_fh_expire_type;
2821 2821 nfs4_ntov_map[3].sv_getit = rfs4_fattr4_change;
2822 2822 nfs4_ntov_map[4].sv_getit = rfs4_fattr4_size;
2823 2823 nfs4_ntov_map[5].sv_getit = rfs4_fattr4_link_support;
2824 2824 nfs4_ntov_map[6].sv_getit = rfs4_fattr4_symlink_support;
2825 2825 nfs4_ntov_map[7].sv_getit = rfs4_fattr4_named_attr;
2826 2826 nfs4_ntov_map[8].sv_getit = rfs4_fattr4_fsid;
2827 2827 nfs4_ntov_map[9].sv_getit = rfs4_fattr4_unique_handles;
2828 2828 nfs4_ntov_map[10].sv_getit = rfs4_fattr4_lease_time;
2829 2829 nfs4_ntov_map[11].sv_getit = rfs4_fattr4_rdattr_error;
2830 2830 nfs4_ntov_map[12].sv_getit = rfs4_fattr4_acl;
2831 2831 nfs4_ntov_map[13].sv_getit = rfs4_fattr4_aclsupport;
2832 2832 nfs4_ntov_map[14].sv_getit = rfs4_fattr4_archive;
2833 2833 nfs4_ntov_map[15].sv_getit = rfs4_fattr4_cansettime;
2834 2834 nfs4_ntov_map[16].sv_getit = rfs4_fattr4_case_insensitive;
2835 2835 nfs4_ntov_map[17].sv_getit = rfs4_fattr4_case_preserving;
2836 2836 nfs4_ntov_map[18].sv_getit = rfs4_fattr4_chown_restricted;
2837 2837 nfs4_ntov_map[19].sv_getit = rfs4_fattr4_filehandle;
2838 2838 nfs4_ntov_map[20].sv_getit = rfs4_fattr4_fileid;
2839 2839 nfs4_ntov_map[21].sv_getit = rfs4_fattr4_files_avail;
2840 2840 nfs4_ntov_map[22].sv_getit = rfs4_fattr4_files_free;
2841 2841 nfs4_ntov_map[23].sv_getit = rfs4_fattr4_files_total;
2842 2842 nfs4_ntov_map[24].sv_getit = rfs4_fattr4_fs_locations;
2843 2843 nfs4_ntov_map[25].sv_getit = rfs4_fattr4_hidden;
2844 2844 nfs4_ntov_map[26].sv_getit = rfs4_fattr4_homogeneous;
2845 2845 nfs4_ntov_map[27].sv_getit = rfs4_fattr4_maxfilesize;
2846 2846 nfs4_ntov_map[28].sv_getit = rfs4_fattr4_maxlink;
2847 2847 nfs4_ntov_map[29].sv_getit = rfs4_fattr4_maxname;
2848 2848 nfs4_ntov_map[30].sv_getit = rfs4_fattr4_maxread;
2849 2849 nfs4_ntov_map[31].sv_getit = rfs4_fattr4_maxwrite;
2850 2850 nfs4_ntov_map[32].sv_getit = rfs4_fattr4_mimetype;
2851 2851 nfs4_ntov_map[33].sv_getit = rfs4_fattr4_mode;
2852 2852 nfs4_ntov_map[34].sv_getit = rfs4_fattr4_no_trunc;
2853 2853 nfs4_ntov_map[35].sv_getit = rfs4_fattr4_numlinks;
2854 2854 nfs4_ntov_map[36].sv_getit = rfs4_fattr4_owner;
2855 2855 nfs4_ntov_map[37].sv_getit = rfs4_fattr4_owner_group;
2856 2856 nfs4_ntov_map[38].sv_getit = rfs4_fattr4_quota_avail_hard;
2857 2857 nfs4_ntov_map[39].sv_getit = rfs4_fattr4_quota_avail_soft;
2858 2858 nfs4_ntov_map[40].sv_getit = rfs4_fattr4_quota_used;
2859 2859 nfs4_ntov_map[41].sv_getit = rfs4_fattr4_rawdev;
2860 2860 nfs4_ntov_map[42].sv_getit = rfs4_fattr4_space_avail;
2861 2861 nfs4_ntov_map[43].sv_getit = rfs4_fattr4_space_free;
2862 2862 nfs4_ntov_map[44].sv_getit = rfs4_fattr4_space_total;
2863 2863 nfs4_ntov_map[45].sv_getit = rfs4_fattr4_space_used;
2864 2864 nfs4_ntov_map[46].sv_getit = rfs4_fattr4_system;
2865 2865 nfs4_ntov_map[47].sv_getit = rfs4_fattr4_time_access;
2866 2866 nfs4_ntov_map[48].sv_getit = rfs4_fattr4_time_access_set;
2867 2867 nfs4_ntov_map[49].sv_getit = rfs4_fattr4_time_backup;
2868 2868 nfs4_ntov_map[50].sv_getit = rfs4_fattr4_time_create;
2869 2869 nfs4_ntov_map[51].sv_getit = rfs4_fattr4_time_delta;
2870 2870 nfs4_ntov_map[52].sv_getit = rfs4_fattr4_time_metadata;
2871 2871 nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify;
2872 2872 nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set;
2873 2873 nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid;
2874 2874 }
|
↓ open down ↓ |
1541 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX