diff options
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r-- | fs/nfsd/export.c | 78 |
1 files changed, 32 insertions, 46 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 5839b229cd0e..8b1f8efb4690 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -847,9 +847,8 @@ exp_get_fsid_key(svc_client *clp, int fsid) | |||
847 | return exp_find_key(clp, FSID_NUM, fsidv, NULL); | 847 | return exp_find_key(clp, FSID_NUM, fsidv, NULL); |
848 | } | 848 | } |
849 | 849 | ||
850 | static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt, | 850 | static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, |
851 | struct dentry *dentry, | 851 | struct cache_req *reqp) |
852 | struct cache_req *reqp) | ||
853 | { | 852 | { |
854 | struct svc_export *exp, key; | 853 | struct svc_export *exp, key; |
855 | int err; | 854 | int err; |
@@ -858,8 +857,7 @@ static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt, | |||
858 | return ERR_PTR(-ENOENT); | 857 | return ERR_PTR(-ENOENT); |
859 | 858 | ||
860 | key.ex_client = clp; | 859 | key.ex_client = clp; |
861 | key.ex_path.mnt = mnt; | 860 | key.ex_path = *path; |
862 | key.ex_path.dentry = dentry; | ||
863 | 861 | ||
864 | exp = svc_export_lookup(&key); | 862 | exp = svc_export_lookup(&key); |
865 | if (exp == NULL) | 863 | if (exp == NULL) |
@@ -873,24 +871,19 @@ static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt, | |||
873 | /* | 871 | /* |
874 | * Find the export entry for a given dentry. | 872 | * Find the export entry for a given dentry. |
875 | */ | 873 | */ |
876 | static struct svc_export *exp_parent(svc_client *clp, struct vfsmount *mnt, | 874 | static struct svc_export *exp_parent(svc_client *clp, struct path *path) |
877 | struct dentry *dentry, | ||
878 | struct cache_req *reqp) | ||
879 | { | 875 | { |
880 | svc_export *exp; | 876 | struct dentry *saved = dget(path->dentry); |
881 | 877 | svc_export *exp = exp_get_by_name(clp, path, NULL); | |
882 | dget(dentry); | 878 | |
883 | exp = exp_get_by_name(clp, mnt, dentry, reqp); | 879 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { |
884 | 880 | struct dentry *parent = dget_parent(path->dentry); | |
885 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) { | 881 | dput(path->dentry); |
886 | struct dentry *parent; | 882 | path->dentry = parent; |
887 | 883 | exp = exp_get_by_name(clp, path, NULL); | |
888 | parent = dget_parent(dentry); | ||
889 | dput(dentry); | ||
890 | dentry = parent; | ||
891 | exp = exp_get_by_name(clp, mnt, dentry, reqp); | ||
892 | } | 884 | } |
893 | dput(dentry); | 885 | dput(path->dentry); |
886 | path->dentry = saved; | ||
894 | return exp; | 887 | return exp; |
895 | } | 888 | } |
896 | 889 | ||
@@ -1018,7 +1011,7 @@ exp_export(struct nfsctl_export *nxp) | |||
1018 | goto out_put_clp; | 1011 | goto out_put_clp; |
1019 | err = -EINVAL; | 1012 | err = -EINVAL; |
1020 | 1013 | ||
1021 | exp = exp_get_by_name(clp, path.mnt, path.dentry, NULL); | 1014 | exp = exp_get_by_name(clp, &path, NULL); |
1022 | 1015 | ||
1023 | memset(&new, 0, sizeof(new)); | 1016 | memset(&new, 0, sizeof(new)); |
1024 | 1017 | ||
@@ -1135,7 +1128,7 @@ exp_unexport(struct nfsctl_export *nxp) | |||
1135 | goto out_domain; | 1128 | goto out_domain; |
1136 | 1129 | ||
1137 | err = -EINVAL; | 1130 | err = -EINVAL; |
1138 | exp = exp_get_by_name(dom, path.mnt, path.dentry, NULL); | 1131 | exp = exp_get_by_name(dom, &path, NULL); |
1139 | path_put(&path); | 1132 | path_put(&path); |
1140 | if (IS_ERR(exp)) | 1133 | if (IS_ERR(exp)) |
1141 | goto out_domain; | 1134 | goto out_domain; |
@@ -1177,7 +1170,7 @@ exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) | |||
1177 | dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", | 1170 | dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", |
1178 | name, path.dentry, clp->name, | 1171 | name, path.dentry, clp->name, |
1179 | inode->i_sb->s_id, inode->i_ino); | 1172 | inode->i_sb->s_id, inode->i_ino); |
1180 | exp = exp_parent(clp, path.mnt, path.dentry, NULL); | 1173 | exp = exp_parent(clp, &path); |
1181 | if (IS_ERR(exp)) { | 1174 | if (IS_ERR(exp)) { |
1182 | err = PTR_ERR(exp); | 1175 | err = PTR_ERR(exp); |
1183 | goto out; | 1176 | goto out; |
@@ -1207,7 +1200,7 @@ static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, | |||
1207 | if (IS_ERR(ek)) | 1200 | if (IS_ERR(ek)) |
1208 | return ERR_CAST(ek); | 1201 | return ERR_CAST(ek); |
1209 | 1202 | ||
1210 | exp = exp_get_by_name(clp, ek->ek_path.mnt, ek->ek_path.dentry, reqp); | 1203 | exp = exp_get_by_name(clp, &ek->ek_path, reqp); |
1211 | cache_put(&ek->h, &svc_expkey_cache); | 1204 | cache_put(&ek->h, &svc_expkey_cache); |
1212 | 1205 | ||
1213 | if (IS_ERR(exp)) | 1206 | if (IS_ERR(exp)) |
@@ -1247,8 +1240,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) | |||
1247 | * use exp_get_by_name() or exp_find(). | 1240 | * use exp_get_by_name() or exp_find(). |
1248 | */ | 1241 | */ |
1249 | struct svc_export * | 1242 | struct svc_export * |
1250 | 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) |
1251 | struct dentry *dentry) | ||
1252 | { | 1244 | { |
1253 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); | 1245 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); |
1254 | 1246 | ||
@@ -1256,8 +1248,7 @@ rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt, | |||
1256 | goto gss; | 1248 | goto gss; |
1257 | 1249 | ||
1258 | /* First try the auth_unix client: */ | 1250 | /* First try the auth_unix client: */ |
1259 | exp = exp_get_by_name(rqstp->rq_client, mnt, dentry, | 1251 | exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle); |
1260 | &rqstp->rq_chandle); | ||
1261 | if (PTR_ERR(exp) == -ENOENT) | 1252 | if (PTR_ERR(exp) == -ENOENT) |
1262 | goto gss; | 1253 | goto gss; |
1263 | if (IS_ERR(exp)) | 1254 | if (IS_ERR(exp)) |
@@ -1269,8 +1260,7 @@ gss: | |||
1269 | /* Otherwise, try falling back on gss client */ | 1260 | /* Otherwise, try falling back on gss client */ |
1270 | if (rqstp->rq_gssclient == NULL) | 1261 | if (rqstp->rq_gssclient == NULL) |
1271 | return exp; | 1262 | return exp; |
1272 | gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry, | 1263 | gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle); |
1273 | &rqstp->rq_chandle); | ||
1274 | if (PTR_ERR(gssexp) == -ENOENT) | 1264 | if (PTR_ERR(gssexp) == -ENOENT) |
1275 | return exp; | 1265 | return exp; |
1276 | if (!IS_ERR(exp)) | 1266 | if (!IS_ERR(exp)) |
@@ -1309,23 +1299,19 @@ gss: | |||
1309 | } | 1299 | } |
1310 | 1300 | ||
1311 | struct svc_export * | 1301 | struct svc_export * |
1312 | rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt, | 1302 | rqst_exp_parent(struct svc_rqst *rqstp, struct path *path) |
1313 | struct dentry *dentry) | ||
1314 | { | 1303 | { |
1315 | struct svc_export *exp; | 1304 | struct dentry *saved = dget(path->dentry); |
1316 | 1305 | struct svc_export *exp = rqst_exp_get_by_name(rqstp, path); | |
1317 | dget(dentry); | 1306 | |
1318 | exp = rqst_exp_get_by_name(rqstp, mnt, dentry); | 1307 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { |
1319 | 1308 | struct dentry *parent = dget_parent(path->dentry); | |
1320 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) { | 1309 | dput(path->dentry); |
1321 | struct dentry *parent; | 1310 | path->dentry = parent; |
1322 | 1311 | exp = rqst_exp_get_by_name(rqstp, path); | |
1323 | parent = dget_parent(dentry); | ||
1324 | dput(dentry); | ||
1325 | dentry = parent; | ||
1326 | exp = rqst_exp_get_by_name(rqstp, mnt, dentry); | ||
1327 | } | 1312 | } |
1328 | dput(dentry); | 1313 | dput(path->dentry); |
1314 | path->dentry = saved; | ||
1329 | return exp; | 1315 | return exp; |
1330 | } | 1316 | } |
1331 | 1317 | ||