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