aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2016-08-03 20:19:06 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-10-06 09:07:44 -0400
commit09bb8bfffd29c3dffb72bc2c69a062dfb1ae624c (patch)
tree44c4f7a56072f73b85088225a408a91bdb33b567
parent7d22fc11c7edeeac6f1c3f1ae0edcef4de08c6e0 (diff)
exportfs: be careful to only return expected errors.
When nfsd calls fh_to_dentry, it expect ESTALE or ENOMEM as errors. In particular it can be tempting to return ENOENT, but this is not handled well by nfsd. Rather than requiring strict adherence to error code code filesystems, treat all unexpected error codes the same as ESTALE. This is safest. Signed-off-by: NeilBrown <neilb@suse.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/exportfs/expfs.c10
-rw-r--r--include/linux/exportfs.h13
2 files changed, 13 insertions, 10 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 207ba8d627ca..a4b531be9168 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -428,10 +428,10 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
428 if (!nop || !nop->fh_to_dentry) 428 if (!nop || !nop->fh_to_dentry)
429 return ERR_PTR(-ESTALE); 429 return ERR_PTR(-ESTALE);
430 result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); 430 result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
431 if (!result) 431 if (PTR_ERR(result) == -ENOMEM)
432 result = ERR_PTR(-ESTALE); 432 return ERR_CAST(result);
433 if (IS_ERR(result)) 433 if (IS_ERR_OR_NULL(result))
434 return result; 434 return ERR_PTR(-ESTALE);
435 435
436 if (d_is_dir(result)) { 436 if (d_is_dir(result)) {
437 /* 437 /*
@@ -541,6 +541,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
541 541
542 err_result: 542 err_result:
543 dput(result); 543 dput(result);
544 if (err != -ENOMEM)
545 err = -ESTALE;
544 return ERR_PTR(err); 546 return ERR_PTR(err);
545} 547}
546EXPORT_SYMBOL_GPL(exportfs_decode_fh); 548EXPORT_SYMBOL_GPL(exportfs_decode_fh);
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index b03c0625fa6e..5ab958cdc50b 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -157,12 +157,13 @@ struct fid {
157 * @fh_to_dentry is given a &struct super_block (@sb) and a file handle 157 * @fh_to_dentry is given a &struct super_block (@sb) and a file handle
158 * fragment (@fh, @fh_len). It should return a &struct dentry which refers 158 * fragment (@fh, @fh_len). It should return a &struct dentry which refers
159 * to the same file that the file handle fragment refers to. If it cannot, 159 * to the same file that the file handle fragment refers to. If it cannot,
160 * it should return a %NULL pointer if the file was found but no acceptable 160 * it should return a %NULL pointer if the file cannot be found, or an
161 * &dentries were available, or an %ERR_PTR error code indicating why it 161 * %ERR_PTR error code of %ENOMEM if a memory allocation failure occurred.
162 * couldn't be found (e.g. %ENOENT or %ENOMEM). Any suitable dentry can be 162 * Any other error code is treated like %NULL, and will cause an %ESTALE error
163 * returned including, if necessary, a new dentry created with d_alloc_root. 163 * for callers of exportfs_decode_fh().
164 * The caller can then find any other extant dentries by following the 164 * Any suitable dentry can be returned including, if necessary, a new dentry
165 * d_alias links. 165 * created with d_alloc_root. The caller can then find any other extant
166 * dentries by following the d_alias links.
166 * 167 *
167 * fh_to_parent: 168 * fh_to_parent:
168 * Same as @fh_to_dentry, except that it returns a pointer to the parent 169 * Same as @fh_to_dentry, except that it returns a pointer to the parent