exportfs: Add a function to return the raw output from fh_to_dentry()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 30 Nov 2020 22:03:17 +0000 (17:03 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Wed, 9 Dec 2020 14:39:38 +0000 (09:39 -0500)
In order to allow nfsd to accept return values that are not
acceptable to overlayfs and others, add a new function.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/exportfs/expfs.c
include/linux/exportfs.h

index 2dd55b1..0106eba 100644 (file)
@@ -417,9 +417,11 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
 }
 EXPORT_SYMBOL_GPL(exportfs_encode_fh);
 
-struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
-               int fh_len, int fileid_type,
-               int (*acceptable)(void *, struct dentry *), void *context)
+struct dentry *
+exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len,
+                      int fileid_type,
+                      int (*acceptable)(void *, struct dentry *),
+                      void *context)
 {
        const struct export_operations *nop = mnt->mnt_sb->s_export_op;
        struct dentry *result, *alias;
@@ -432,10 +434,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
        if (!nop || !nop->fh_to_dentry)
                return ERR_PTR(-ESTALE);
        result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
-       if (PTR_ERR(result) == -ENOMEM)
-               return ERR_CAST(result);
        if (IS_ERR_OR_NULL(result))
-               return ERR_PTR(-ESTALE);
+               return result;
 
        /*
         * If no acceptance criteria was specified by caller, a disconnected
@@ -561,10 +561,26 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
 
  err_result:
        dput(result);
-       if (err != -ENOMEM)
-               err = -ESTALE;
        return ERR_PTR(err);
 }
+EXPORT_SYMBOL_GPL(exportfs_decode_fh_raw);
+
+struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
+                                 int fh_len, int fileid_type,
+                                 int (*acceptable)(void *, struct dentry *),
+                                 void *context)
+{
+       struct dentry *ret;
+
+       ret = exportfs_decode_fh_raw(mnt, fid, fh_len, fileid_type,
+                                    acceptable, context);
+       if (IS_ERR_OR_NULL(ret)) {
+               if (ret == ERR_PTR(-ENOMEM))
+                       return ret;
+               return ERR_PTR(-ESTALE);
+       }
+       return ret;
+}
 EXPORT_SYMBOL_GPL(exportfs_decode_fh);
 
 MODULE_LICENSE("GPL");
index d829403..846df3c 100644 (file)
@@ -223,6 +223,11 @@ extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
                                    int *max_len, struct inode *parent);
 extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
        int *max_len, int connectable);
+extern struct dentry *exportfs_decode_fh_raw(struct vfsmount *mnt,
+                                            struct fid *fid, int fh_len,
+                                            int fileid_type,
+                                            int (*acceptable)(void *, struct dentry *),
+                                            void *context);
 extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
        int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *),
        void *context);