diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index ac225a79376c..4537a8f5cb9a 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -1229,6 +1229,10 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | |||
1229 | } | 1229 | } |
1230 | 1230 | ||
1231 | /* | 1231 | /* |
1232 | * Uses rq_client and rq_gssclient to find an export; uses rq_client (an | ||
1233 | * auth_unix client) if it's available and has secinfo information; | ||
1234 | * otherwise, will try to use rq_gssclient. | ||
1235 | * | ||
1232 | * Called from functions that handle requests; functions that do work on | 1236 | * Called from functions that handle requests; functions that do work on |
1233 | * behalf of mountd are passed a single client name to use, and should | 1237 | * behalf of mountd are passed a single client name to use, and should |
1234 | * use exp_get_by_name() or exp_find(). | 1238 | * use exp_get_by_name() or exp_find(). |
@@ -1237,29 +1241,83 @@ struct svc_export * | |||
1237 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt, | 1241 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt, |
1238 | struct dentry *dentry) | 1242 | struct dentry *dentry) |
1239 | { | 1243 | { |
1240 | struct auth_domain *clp; | 1244 | struct svc_export *gssexp, *exp = NULL; |
1245 | |||
1246 | if (rqstp->rq_client == NULL) | ||
1247 | goto gss; | ||
1241 | 1248 | ||
1242 | clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; | 1249 | /* First try the auth_unix client: */ |
1243 | return exp_get_by_name(clp, mnt, dentry, &rqstp->rq_chandle); | 1250 | exp = exp_get_by_name(rqstp->rq_client, mnt, dentry, |
1251 | &rqstp->rq_chandle); | ||
1252 | if (PTR_ERR(exp) == -ENOENT) | ||
1253 | goto gss; | ||
1254 | if (IS_ERR(exp)) | ||
1255 | return exp; | ||
1256 | /* If it has secinfo, assume there are no gss/... clients */ | ||
1257 | if (exp->ex_nflavors > 0) | ||
1258 | return exp; | ||
1259 | gss: | ||
1260 | /* Otherwise, try falling back on gss client */ | ||
1261 | if (rqstp->rq_gssclient == NULL) | ||
1262 | return exp; | ||
1263 | gssexp = exp_get_by_name(rqstp->rq_gssclient, mnt, dentry, | ||
1264 | &rqstp->rq_chandle); | ||
1265 | if (PTR_ERR(gssexp) == -ENOENT) | ||
1266 | return exp; | ||
1267 | if (exp && !IS_ERR(exp)) | ||
1268 | exp_put(exp); | ||
1269 | return gssexp; | ||
1244 | } | 1270 | } |
1245 | 1271 | ||
1246 | struct svc_export * | 1272 | struct svc_export * |
1247 | rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) | 1273 | rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) |
1248 | { | 1274 | { |
1249 | struct auth_domain *clp; | 1275 | struct svc_export *gssexp, *exp = NULL; |
1276 | |||
1277 | if (rqstp->rq_client == NULL) | ||
1278 | goto gss; | ||
1250 | 1279 | ||
1251 | clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; | 1280 | /* First try the auth_unix client: */ |
1252 | return exp_find(clp, fsid_type, fsidv, &rqstp->rq_chandle); | 1281 | exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle); |
1282 | if (PTR_ERR(exp) == -ENOENT) | ||
1283 | goto gss; | ||
1284 | if (IS_ERR(exp)) | ||
1285 | return exp; | ||
1286 | /* If it has secinfo, assume there are no gss/... clients */ | ||
1287 | if (exp->ex_nflavors > 0) | ||
1288 | return exp; | ||
1289 | gss: | ||
1290 | /* Otherwise, try falling back on gss client */ | ||
1291 | if (rqstp->rq_gssclient == NULL) | ||
1292 | return exp; | ||
1293 | gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv, | ||
1294 | &rqstp->rq_chandle); | ||
1295 | if (PTR_ERR(gssexp) == -ENOENT) | ||
1296 | return exp; | ||
1297 | if (exp && !IS_ERR(exp)) | ||
1298 | exp_put(exp); | ||
1299 | return gssexp; | ||
1253 | } | 1300 | } |
1254 | 1301 | ||
1255 | struct svc_export * | 1302 | struct svc_export * |
1256 | rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt, | 1303 | rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt, |
1257 | struct dentry *dentry) | 1304 | struct dentry *dentry) |
1258 | { | 1305 | { |
1259 | struct auth_domain *clp; | 1306 | struct svc_export *exp; |
1260 | 1307 | ||
1261 | clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; | 1308 | dget(dentry); |
1262 | return exp_parent(rqstp->rq_client, mnt, dentry, &rqstp->rq_chandle); | 1309 | exp = rqst_exp_get_by_name(rqstp, mnt, dentry); |
1310 | |||
1311 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) { | ||
1312 | struct dentry *parent; | ||
1313 | |||
1314 | parent = dget_parent(dentry); | ||
1315 | dput(dentry); | ||
1316 | dentry = parent; | ||
1317 | exp = rqst_exp_get_by_name(rqstp, mnt, dentry); | ||
1318 | } | ||
1319 | dput(dentry); | ||
1320 | return exp; | ||
1263 | } | 1321 | } |
1264 | 1322 | ||
1265 | /* | 1323 | /* |