400 *exip = exi;
401
402 VN_RELE(*vpp);
403 *vpp = vp;
404 }
405
406 return (0);
407 }
408
409 /*
410 * Given mounted "dvp" and "exi", go upper mountpoint
411 * with dvp/exi correction
412 * Return 0 in success
413 */
414 int
415 rfs_climb_crossmnt(vnode_t **dvpp, struct exportinfo **exip, cred_t *cr)
416 {
417 struct exportinfo *exi;
418 vnode_t *dvp = *dvpp;
419
420 ASSERT(dvp->v_flag & VROOT);
421
422 VN_HOLD(dvp);
423 dvp = untraverse(dvp);
424 exi = nfs_vptoexi(NULL, dvp, cr, NULL, NULL, FALSE);
425 if (exi == NULL) {
426 VN_RELE(dvp);
427 return (-1);
428 }
429
430 exi_rele(*exip);
431 *exip = exi;
432 VN_RELE(*dvpp);
433 *dvpp = dvp;
434
435 return (0);
436 }
437 /*
438 * Directory lookup.
439 * Returns an fhandle and file attributes for file name in a directory.
440 */
441 /* ARGSUSED */
442 void
443 rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
444 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
445 {
446 int error;
447 vnode_t *dvp;
448 vnode_t *vp;
449 struct vattr va;
470 dr->dr_status = NFSERR_ACCES;
471 return;
472 }
473
474 /*
475 * Allow lookups from the root - the default
476 * location of the public filehandle.
477 */
478 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
479 dvp = ZONE_ROOTVP();
480 VN_HOLD(dvp);
481 } else {
482 dvp = nfs_fhtovp(fhp, exi);
483 if (dvp == NULL) {
484 dr->dr_status = NFSERR_STALE;
485 return;
486 }
487 }
488
489 exi_hold(exi);
490
491 /*
492 * Not allow lookup beyond root.
493 * If the filehandle matches a filehandle of the exi,
494 * then the ".." refers beyond the root of an exported filesystem.
495 */
496 if (strcmp(da->da_name, "..") == 0 &&
497 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
498 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
499 (dvp->v_flag & VROOT)) {
500 /*
501 * special case for ".." and 'nohide'exported root
502 */
503 if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
504 error = NFSERR_ACCES;
505 goto out;
506 }
507 } else {
508 error = NFSERR_NOENT;
509 goto out;
510 }
511 }
512
513 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
514 name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND,
515 MAXPATHLEN);
516
517 if (name == NULL) {
518 error = NFSERR_ACCES;
519 goto out;
520 }
521
522 /*
523 * If the public filehandle is used then allow
524 * a multi-component lookup, i.e. evaluate
525 * a pathname and follow symbolic links if
526 * necessary.
527 *
528 * This may result in a vnode in another filesystem
529 * which is OK as long as the filesystem is exported.
530 */
531 if (PUBLIC_FH2(fhp)) {
532 publicfh_flag = TRUE;
533
534 exi_rele(exi);
535
536 error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi,
537 &sec);
538 } else {
539 /*
540 * Do a normal single component lookup.
541 */
542 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
543 NULL, NULL, NULL);
544 }
545
546 if (name != da->da_name)
547 kmem_free(name, MAXPATHLEN);
548
549 if (error == 0 && vn_ismntpt(vp)) {
550 error = rfs_cross_mnt(&vp, &exi);
551 if (error)
552 VN_RELE(vp);
553 }
554
1301 struct rfs_async_write *trp;
1302 struct rfs_async_write *lrp;
1303 int data_written;
1304 int iovcnt;
1305 mblk_t *m;
1306 struct iovec *iovp;
1307 struct iovec *niovp;
1308 struct iovec iov[MAXCLIOVECS];
1309 int count;
1310 int rcount;
1311 uint_t off;
1312 uint_t len;
1313 struct rfs_async_write nrpsp;
1314 struct rfs_async_write_list nlpsp;
1315 ushort_t t_flag;
1316 cred_t *savecred;
1317 int in_crit = 0;
1318 caller_context_t ct;
1319 nfs_srv_t *nsrv;
1320
1321 nsrv = nfs_get_srv();
1322 if (!nsrv->write_async) {
1323 rfs_write_sync(wa, ns, exi, req, cr, ro);
1324 return;
1325 }
1326
1327 /*
1328 * Initialize status to RFSWRITE_INITVAL instead of 0, since value of 0
1329 * is considered an OK.
1330 */
1331 ns->ns_status = RFSWRITE_INITVAL;
1332
1333 nrp = &nrpsp;
1334 nrp->wa = wa;
1335 nrp->ns = ns;
1336 nrp->req = req;
1337 nrp->cr = cr;
1338 nrp->ro = ro;
1339 nrp->thread = curthread;
1340
|
400 *exip = exi;
401
402 VN_RELE(*vpp);
403 *vpp = vp;
404 }
405
406 return (0);
407 }
408
409 /*
410 * Given mounted "dvp" and "exi", go upper mountpoint
411 * with dvp/exi correction
412 * Return 0 in success
413 */
414 int
415 rfs_climb_crossmnt(vnode_t **dvpp, struct exportinfo **exip, cred_t *cr)
416 {
417 struct exportinfo *exi;
418 vnode_t *dvp = *dvpp;
419
420 ASSERT3U((*exip)->exi_zoneid, ==, curzone->zone_id);
421 ASSERT((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp));
422
423 VN_HOLD(dvp);
424 dvp = untraverse(dvp);
425 exi = nfs_vptoexi(NULL, dvp, cr, NULL, NULL, FALSE);
426 if (exi == NULL) {
427 VN_RELE(dvp);
428 return (-1);
429 }
430
431 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
432 exi_rele(*exip);
433 *exip = exi;
434 VN_RELE(*dvpp);
435 *dvpp = dvp;
436
437 return (0);
438 }
439 /*
440 * Directory lookup.
441 * Returns an fhandle and file attributes for file name in a directory.
442 */
443 /* ARGSUSED */
444 void
445 rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr,
446 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro)
447 {
448 int error;
449 vnode_t *dvp;
450 vnode_t *vp;
451 struct vattr va;
472 dr->dr_status = NFSERR_ACCES;
473 return;
474 }
475
476 /*
477 * Allow lookups from the root - the default
478 * location of the public filehandle.
479 */
480 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
481 dvp = ZONE_ROOTVP();
482 VN_HOLD(dvp);
483 } else {
484 dvp = nfs_fhtovp(fhp, exi);
485 if (dvp == NULL) {
486 dr->dr_status = NFSERR_STALE;
487 return;
488 }
489 }
490
491 exi_hold(exi);
492 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
493
494 /*
495 * Not allow lookup beyond root.
496 * If the filehandle matches a filehandle of the exi,
497 * then the ".." refers beyond the root of an exported filesystem.
498 */
499 if (strcmp(da->da_name, "..") == 0 &&
500 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) {
501 if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
502 ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp))) {
503 /*
504 * special case for ".." and 'nohide'exported root
505 */
506 if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
507 error = NFSERR_ACCES;
508 goto out;
509 }
510 } else {
511 error = NFSERR_NOENT;
512 goto out;
513 }
514 }
515
516 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
517 name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND,
518 MAXPATHLEN);
519
520 if (name == NULL) {
521 error = NFSERR_ACCES;
522 goto out;
523 }
524
525 /*
526 * If the public filehandle is used then allow
527 * a multi-component lookup, i.e. evaluate
528 * a pathname and follow symbolic links if
529 * necessary.
530 *
531 * This may result in a vnode in another filesystem
532 * which is OK as long as the filesystem is exported.
533 */
534 if (PUBLIC_FH2(fhp)) {
535 publicfh_flag = TRUE;
536
537 exi_rele(exi);
538 exi = NULL;
539
540 error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi,
541 &sec);
542 } else {
543 /*
544 * Do a normal single component lookup.
545 */
546 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
547 NULL, NULL, NULL);
548 }
549
550 if (name != da->da_name)
551 kmem_free(name, MAXPATHLEN);
552
553 if (error == 0 && vn_ismntpt(vp)) {
554 error = rfs_cross_mnt(&vp, &exi);
555 if (error)
556 VN_RELE(vp);
557 }
558
1305 struct rfs_async_write *trp;
1306 struct rfs_async_write *lrp;
1307 int data_written;
1308 int iovcnt;
1309 mblk_t *m;
1310 struct iovec *iovp;
1311 struct iovec *niovp;
1312 struct iovec iov[MAXCLIOVECS];
1313 int count;
1314 int rcount;
1315 uint_t off;
1316 uint_t len;
1317 struct rfs_async_write nrpsp;
1318 struct rfs_async_write_list nlpsp;
1319 ushort_t t_flag;
1320 cred_t *savecred;
1321 int in_crit = 0;
1322 caller_context_t ct;
1323 nfs_srv_t *nsrv;
1324
1325 ASSERT(exi == NULL || exi->exi_zoneid == curzone->zone_id);
1326 nsrv = nfs_get_srv();
1327 if (!nsrv->write_async) {
1328 rfs_write_sync(wa, ns, exi, req, cr, ro);
1329 return;
1330 }
1331
1332 /*
1333 * Initialize status to RFSWRITE_INITVAL instead of 0, since value of 0
1334 * is considered an OK.
1335 */
1336 ns->ns_status = RFSWRITE_INITVAL;
1337
1338 nrp = &nrpsp;
1339 nrp->wa = wa;
1340 nrp->ns = ns;
1341 nrp->req = req;
1342 nrp->cr = cr;
1343 nrp->ro = ro;
1344 nrp->thread = curthread;
1345
|