Print this page
2988 nfssrv: need ability to go to submounts for v3 and v2 protocols
Portions contributed by: Marcel Telka <marcel.telka@nexenta.com>
Portions contributed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Change-Id: I6fdf110cc17e789353c4442b83a46cb80643456e
*** 380,389 ****
--- 380,392 ----
struct sockaddr *ca;
char *name = NULL;
dvap = NULL;
+ if (exi != NULL)
+ exi_hold(exi);
+
/*
* Allow lookups from the root - the default
* location of the public filehandle.
*/
if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
*** 418,430 ****
--- 421,444 ----
}
fhp = &args->what.dir;
if (strcmp(args->what.name, "..") == 0 &&
EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
+ if ((exi->exi_export.ex_flags & EX_NOHIDE) &&
+ (dvp->v_flag & VROOT)) {
+ /*
+ * special case for ".." and 'nohide'exported root
+ */
+ if (rfs_climb_crossmnt(&dvp, &exi, cr) != 0) {
+ resp->status = NFS3ERR_ACCES;
+ goto out1;
+ }
+ } else {
resp->status = NFS3ERR_NOENT;
goto out1;
}
+ }
ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
name = nfscmd_convname(ca, exi, args->what.name,
NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
*** 437,450 ****
* If the public filehandle is used then allow
* a multi-component lookup
*/
if (PUBLIC_FH3(&args->what.dir)) {
publicfh_flag = TRUE;
error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
&exi, &sec);
! if (error && exi != NULL)
! exi_rele(exi); /* See comment below Re: publicfh_flag */
/*
* Since WebNFS may bypass MOUNT, we need to ensure this
* request didn't come from an unlabeled admin_low client.
*/
if (is_system_labeled() && error == 0) {
--- 451,466 ----
* If the public filehandle is used then allow
* a multi-component lookup
*/
if (PUBLIC_FH3(&args->what.dir)) {
publicfh_flag = TRUE;
+
+ exi_rele(exi);
+
error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
&exi, &sec);
!
/*
* Since WebNFS may bypass MOUNT, we need to ensure this
* request didn't come from an unlabeled admin_low client.
*/
if (is_system_labeled() && error == 0) {
*** 462,473 ****
}
tp = find_tpc(ipaddr, addr_type, B_FALSE);
if (tp == NULL || tp->tpc_tp.tp_doi !=
l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
SUN_CIPSO) {
- if (exi != NULL)
- exi_rele(exi);
VN_RELE(vp);
error = EACCES;
}
if (tp != NULL)
TPC_RELE(tp);
--- 478,487 ----
*** 478,487 ****
--- 492,507 ----
}
if (name != args->what.name)
kmem_free(name, MAXPATHLEN + 1);
+ if (error == 0 && vn_ismntpt(vp)) {
+ error = rfs_cross_mnt(&vp, &exi);
+ if (error)
+ VN_RELE(vp);
+ }
+
if (is_system_labeled() && error == 0) {
bslabel_t *clabel = req->rq_label;
ASSERT(clabel != NULL);
DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
*** 488,499 ****
"got client label from request(1)", struct svc_req *, req);
if (!blequal(&l_admin_low->tsl_label, clabel)) {
if (!do_rfs_label_check(clabel, dvp,
DOMINANCE_CHECK, exi)) {
- if (publicfh_flag && exi != NULL)
- exi_rele(exi);
VN_RELE(vp);
error = EACCES;
}
}
}
--- 508,517 ----
*** 510,536 ****
error = makefh3(&resp->resok.object, vp, exi);
if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
auth_weak = TRUE;
}
- /*
- * If publicfh_flag is true then we have called rfs_publicfh_mclookup
- * and have obtained a new exportinfo in exi which needs to be
- * released. Note that the original exportinfo pointed to by exi
- * will be released by the caller, common_dispatch.
- */
- if (publicfh_flag)
- exi_rele(exi);
-
if (error) {
VN_RELE(vp);
goto out;
}
va.va_mask = AT_ALL;
vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
VN_RELE(vp);
resp->status = NFS3_OK;
vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
--- 528,546 ----
error = makefh3(&resp->resok.object, vp, exi);
if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
auth_weak = TRUE;
}
if (error) {
VN_RELE(vp);
goto out;
}
va.va_mask = AT_ALL;
vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
+ exi_rele(exi);
VN_RELE(vp);
resp->status = NFS3_OK;
vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
*** 554,563 ****
--- 564,576 ----
curthread->t_flag &= ~T_WOULDBLOCK;
resp->status = NFS3ERR_JUKEBOX;
} else
resp->status = puterrno3(error);
out1:
+ if (exi != NULL)
+ exi_rele(exi);
+
DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
if (dvp != NULL)
VN_RELE(dvp);
*** 3607,3623 ****
--- 3620,3641 ----
/* Lie about the object type for a referral */
if (vn_is_nfs_reparse(nvp, cr))
nvap->va_type = VLNK;
+ if (vn_ismntpt(nvp)) {
+ infop[i].attr.attributes = FALSE;
+ infop[i].fh.handle_follows = FALSE;
+ } else {
vattr_to_post_op_attr(nvap, &infop[i].attr);
error = makefh3(&infop[i].fh.handle, nvp, exi);
if (!error)
infop[i].fh.handle_follows = TRUE;
else
infop[i].fh.handle_follows = FALSE;
+ }
VN_RELE(nvp);
dp = nextdp(dp);
}