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 
 
 |