staging/lustre: proper support of NFS anonymous dentries
authorDmitry Eremin <dmitry.eremin@intel.com>
Mon, 15 Feb 2016 00:13:52 +0000 (19:13 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 26 Feb 2016 06:12:26 +0000 (22:12 -0800)
NFS can ask to encode dentries that are not connected to the root.
The fix check for parent is NULL and encode a file handle accordingly.

Reviewed-on: http://review.whamcloud.com/8347
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4231
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Jian Yu <jian.yu@intel.com>
Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com>
Signed-off-by: Oleg Drokin <green@linuxhacker.ru>
Acked-by: Jeff Layton <jlayton@poochiereds.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/llite/llite_nfs.c
include/linux/exportfs.h

index 2484412157941552f2452b5fcd78439464da1d82..74a88685e9dd36f855fd7ffedec1b09584ecab73 100644 (file)
@@ -142,10 +142,11 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
        struct inode  *inode;
        struct dentry *result;
 
-       CDEBUG(D_INFO, "Get dentry for fid: "DFID"\n", PFID(fid));
        if (!fid_is_sane(fid))
                return ERR_PTR(-ESTALE);
 
+       CDEBUG(D_INFO, "Get dentry for fid: " DFID "\n", PFID(fid));
+
        inode = search_inode_for_lustre(sb, fid);
        if (IS_ERR(inode))
                return ERR_CAST(inode);
@@ -161,7 +162,7 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
         * We have to find the parent to tell MDS how to init lov objects.
         */
        if (S_ISREG(inode->i_mode) && !ll_i2info(inode)->lli_has_smd &&
-           parent != NULL) {
+           parent && !fid_is_zero(parent)) {
                struct ll_inode_info *lli = ll_i2info(inode);
 
                spin_lock(&lli->lli_lock);
@@ -175,8 +176,6 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
        return result;
 }
 
-#define LUSTRE_NFS_FID   0x97
-
 /**
  * \a connectable - is nfsd will connect himself or this should be done
  *               at lustre
@@ -189,20 +188,25 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
 static int ll_encode_fh(struct inode *inode, __u32 *fh, int *plen,
                        struct inode *parent)
 {
+       int fileid_len = sizeof(struct lustre_nfs_fid) / 4;
        struct lustre_nfs_fid *nfs_fid = (void *)fh;
 
        CDEBUG(D_INFO, "encoding for (%lu,"DFID") maxlen=%d minlen=%d\n",
-             inode->i_ino, PFID(ll_inode2fid(inode)), *plen,
-             (int)sizeof(struct lustre_nfs_fid));
+             inode->i_ino, PFID(ll_inode2fid(inode)), *plen, fileid_len);
 
-       if (*plen < sizeof(struct lustre_nfs_fid) / 4)
-               return 255;
+       if (*plen < fileid_len) {
+               *plen = fileid_len;
+               return FILEID_INVALID;
+       }
 
        nfs_fid->lnf_child = *ll_inode2fid(inode);
-       nfs_fid->lnf_parent = *ll_inode2fid(parent);
-       *plen = sizeof(struct lustre_nfs_fid) / 4;
+       if (parent)
+               nfs_fid->lnf_parent = *ll_inode2fid(parent);
+       else
+               fid_zero(&nfs_fid->lnf_parent);
+       *plen = fileid_len;
 
-       return LUSTRE_NFS_FID;
+       return FILEID_LUSTRE;
 }
 
 static int ll_nfs_get_name_filldir(struct dir_context *ctx, const char *name,
@@ -261,7 +265,7 @@ static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid,
 {
        struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
 
-       if (fh_type != LUSTRE_NFS_FID)
+       if (fh_type != FILEID_LUSTRE)
                return ERR_PTR(-EPROTO);
 
        return ll_iget_for_nfs(sb, &nfs_fid->lnf_child, &nfs_fid->lnf_parent);
@@ -272,7 +276,7 @@ static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid,
 {
        struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;
 
-       if (fh_type != LUSTRE_NFS_FID)
+       if (fh_type != FILEID_LUSTRE)
                return ERR_PTR(-EPROTO);
 
        return ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL);
index fa05e04c5531ce7ae8195abcb0b03b7343e40037..d8414502edb4db8e19a5e94c544b38d6cec746f3 100644 (file)
@@ -96,6 +96,12 @@ enum fid_type {
         */
        FILEID_FAT_WITH_PARENT = 0x72,
 
+       /*
+        * 128 bit child FID (struct lu_fid)
+        * 128 bit parent FID (struct lu_fid)
+        */
+       FILEID_LUSTRE = 0x97,
+
        /*
         * Filesystems must not use 0xff file ID.
         */