diff options
-rw-r--r-- | fs/nfsd/export.c | 15 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 32 | ||||
-rw-r--r-- | include/linux/nfsd/export.h | 3 |
3 files changed, 23 insertions, 27 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 5149dabde555..84f5e5cb0863 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -1240,18 +1240,15 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) | |||
1240 | * use exp_get_by_name() or exp_find(). | 1240 | * use exp_get_by_name() or exp_find(). |
1241 | */ | 1241 | */ |
1242 | struct svc_export * | 1242 | struct svc_export * |
1243 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt, | 1243 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) |
1244 | struct dentry *dentry) | ||
1245 | { | 1244 | { |
1246 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); | 1245 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); |
1247 | struct path path = {.mnt = mnt, .dentry = dentry}; | ||
1248 | 1246 | ||
1249 | if (rqstp->rq_client == NULL) | 1247 | if (rqstp->rq_client == NULL) |
1250 | goto gss; | 1248 | goto gss; |
1251 | 1249 | ||
1252 | /* First try the auth_unix client: */ | 1250 | /* First try the auth_unix client: */ |
1253 | exp = exp_get_by_name(rqstp->rq_client, &path, | 1251 | exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle); |
1254 | &rqstp->rq_chandle); | ||
1255 | if (PTR_ERR(exp) == -ENOENT) | 1252 | if (PTR_ERR(exp) == -ENOENT) |
1256 | goto gss; | 1253 | goto gss; |
1257 | if (IS_ERR(exp)) | 1254 | if (IS_ERR(exp)) |
@@ -1263,8 +1260,7 @@ gss: | |||
1263 | /* Otherwise, try falling back on gss client */ | 1260 | /* Otherwise, try falling back on gss client */ |
1264 | if (rqstp->rq_gssclient == NULL) | 1261 | if (rqstp->rq_gssclient == NULL) |
1265 | return exp; | 1262 | return exp; |
1266 | gssexp = exp_get_by_name(rqstp->rq_gssclient, &path, | 1263 | gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle); |
1267 | &rqstp->rq_chandle); | ||
1268 | if (PTR_ERR(gssexp) == -ENOENT) | 1264 | if (PTR_ERR(gssexp) == -ENOENT) |
1269 | return exp; | 1265 | return exp; |
1270 | if (!IS_ERR(exp)) | 1266 | if (!IS_ERR(exp)) |
@@ -1307,9 +1303,10 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt, | |||
1307 | struct dentry *dentry) | 1303 | struct dentry *dentry) |
1308 | { | 1304 | { |
1309 | struct svc_export *exp; | 1305 | struct svc_export *exp; |
1306 | struct path path = {.mnt = mnt, .dentry = dentry}; | ||
1310 | 1307 | ||
1311 | dget(dentry); | 1308 | dget(dentry); |
1312 | exp = rqst_exp_get_by_name(rqstp, mnt, dentry); | 1309 | exp = rqst_exp_get_by_name(rqstp, &path); |
1313 | 1310 | ||
1314 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) { | 1311 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) { |
1315 | struct dentry *parent; | 1312 | struct dentry *parent; |
@@ -1317,7 +1314,7 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt, | |||
1317 | parent = dget_parent(dentry); | 1314 | parent = dget_parent(dentry); |
1318 | dput(dentry); | 1315 | dput(dentry); |
1319 | dentry = parent; | 1316 | dentry = parent; |
1320 | exp = rqst_exp_get_by_name(rqstp, mnt, dentry); | 1317 | exp = rqst_exp_get_by_name(rqstp, &path); |
1321 | } | 1318 | } |
1322 | dput(dentry); | 1319 | dput(dentry); |
1323 | return exp; | 1320 | return exp; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index bd584bcf1d9f..d84c4eaa526b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -101,36 +101,36 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, | |||
101 | { | 101 | { |
102 | struct svc_export *exp = *expp, *exp2 = NULL; | 102 | struct svc_export *exp = *expp, *exp2 = NULL; |
103 | struct dentry *dentry = *dpp; | 103 | struct dentry *dentry = *dpp; |
104 | struct vfsmount *mnt = mntget(exp->ex_path.mnt); | 104 | struct path path = {.mnt = mntget(exp->ex_path.mnt), |
105 | struct dentry *mounts = dget(dentry); | 105 | .dentry = dget(dentry)}; |
106 | int err = 0; | 106 | int err = 0; |
107 | 107 | ||
108 | while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts)); | 108 | while (follow_down(&path.mnt, &path.dentry) && |
109 | d_mountpoint(path.dentry)) | ||
110 | ; | ||
109 | 111 | ||
110 | exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts); | 112 | exp2 = rqst_exp_get_by_name(rqstp, &path); |
111 | if (IS_ERR(exp2)) { | 113 | if (IS_ERR(exp2)) { |
112 | if (PTR_ERR(exp2) != -ENOENT) | 114 | if (PTR_ERR(exp2) != -ENOENT) |
113 | err = PTR_ERR(exp2); | 115 | err = PTR_ERR(exp2); |
114 | dput(mounts); | 116 | path_put(&path); |
115 | mntput(mnt); | ||
116 | goto out; | 117 | goto out; |
117 | } | 118 | } |
118 | if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) { | 119 | if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) { |
119 | /* successfully crossed mount point */ | 120 | /* successfully crossed mount point */ |
120 | /* | 121 | /* |
121 | * This is subtle: dentry is *not* under mnt at this point. | 122 | * This is subtle: path.dentry is *not* on path.mnt |
122 | * The only reason we are safe is that original mnt is pinned | 123 | * at this point. The only reason we are safe is that |
123 | * down by exp, so we should dput before putting exp. | 124 | * original mnt is pinned down by exp, so we should |
125 | * put path *before* putting exp | ||
124 | */ | 126 | */ |
125 | dput(dentry); | 127 | *dpp = path.dentry; |
126 | *dpp = mounts; | 128 | path.dentry = dentry; |
127 | exp_put(exp); | ||
128 | *expp = exp2; | 129 | *expp = exp2; |
129 | } else { | 130 | exp2 = exp; |
130 | exp_put(exp2); | ||
131 | dput(mounts); | ||
132 | } | 131 | } |
133 | mntput(mnt); | 132 | path_put(&path); |
133 | exp_put(exp2); | ||
134 | out: | 134 | out: |
135 | return err; | 135 | return err; |
136 | } | 136 | } |
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index bcd0201589f8..98f6fd584d53 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h | |||
@@ -125,8 +125,7 @@ void nfsd_export_flush(void); | |||
125 | void exp_readlock(void); | 125 | void exp_readlock(void); |
126 | void exp_readunlock(void); | 126 | void exp_readunlock(void); |
127 | struct svc_export * rqst_exp_get_by_name(struct svc_rqst *, | 127 | struct svc_export * rqst_exp_get_by_name(struct svc_rqst *, |
128 | struct vfsmount *, | 128 | struct path *); |
129 | struct dentry *); | ||
130 | struct svc_export * rqst_exp_parent(struct svc_rqst *, | 129 | struct svc_export * rqst_exp_parent(struct svc_rqst *, |
131 | struct vfsmount *mnt, | 130 | struct vfsmount *mnt, |
132 | struct dentry *dentry); | 131 | struct dentry *dentry); |