Patchwork [BUG:942,2/6] nfs3: Special-case the lookup for parent dir of root

login
register
Submitter Shehjar Tikoo
Date 2010-06-01 04:13:53
Message ID <1275365637-30417-2-git-send-email-shehjart@gluster.com>
Download mbox | patch
Permalink /patch/3355/
State Accepted
Delegated to: Anand Avati
Headers show

Comments

Shehjar Tikoo - 2010-06-01 04:13:53
From: Shehjar Tikoo <shehjart@gluster.com>

When a lookup request comes in for (rootfh, ".."), we need to handle
it in a way that returns the attributes and handle of the root dir.
Not doing so crashes nfsx because the inode table is not able to
find a inode for the root's parent. This inode was being referenced in
nfs3_lookup_parentdir_resume when filling a loc for the lookup fop.

For the record, such a lookup request is sent by vmkernel.

Signed-off-by: Shehjar Tikoo <shehjart@gluster.com>
---
 xlators/nfs/server/src/nfs3.c |   38 +++++++++++++++++++++++++++++++-------
 1 files changed, 31 insertions(+), 7 deletions(-)

Patch

diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index d48d002..f3cf8b0 100644
--- a/xlators/nfs/server/src/nfs3.c
+++ b/xlators/nfs/server/src/nfs3.c
@@ -894,7 +894,15 @@  nfs3svc_lookup_parentdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
                 goto xmit_res;
         }
 
-        nfs3_fh_build_parent_fh (&cs->fh, buf, &newfh);
+        /* If the buf inode shows that this is a root dir's buf, then the file
+         * handle needs to be specially crafted, in all other cases, we'll just
+         * create the handle normally using the buffer of the parent dir.
+         */
+        if (buf->ia_ino != 1)
+                nfs3_fh_build_parent_fh (&cs->fh, buf, &newfh);
+        else
+                newfh = nfs3_fh_build_root_fh (cs->nfs3state->exportslist,
+                                               cs->vol, *buf);
 
 xmit_res:
         nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "LOOKUP", status,
@@ -925,18 +933,34 @@  nfs3_lookup_parentdir_resume (void *carg)
         /* At this point now, the loc in cs is for the directory file handle
          * sent by the client. This loc needs to be transformed into a loc that
          * represents the parent dir of cs->resolvedloc.inode.
+         *
+         * EXCEPT in the case where the .. is a parent of the root directory.
+         * In this case we'll be returning the file handle and attributes of the
+         * root itself.
          */
         nfs_request_user_init (&nfu, cs->req);
 
         /* Save the file handle from the LOOKUP request. We'll use this to
-         * build the file handle of the parent directory.
+         * build the file handle of the parent directory in case the parent is
+         * not root dir.
          */
         cs->fh = cs->resolvefh;
-        parent = inode_ref (cs->resolvedloc.parent);
-        nfs_loc_wipe (&cs->resolvedloc);
-        ret = nfs_inode_loc_fill (parent, &cs->resolvedloc);
-        if (ret < 0)
-                goto errtostat;
+
+        /* If fh is that of the root, the resolvedloc will already contain
+         * the loc for root. After that, we'll send lookup for the root dir
+         * itself since we cannot send the lookup on the parent of root.
+         *
+         * For all other cases, we'll send the lookup on the parent of the
+         * given directory file handle.
+         */
+        if (!nfs3_fh_is_root_fh (&cs->fh)) {
+                parent = inode_ref (cs->resolvedloc.parent);
+                nfs_loc_wipe (&cs->resolvedloc);
+                ret = nfs_inode_loc_fill (parent, &cs->resolvedloc);
+
+                if (ret < 0)
+                        goto errtostat;
+        }
 
         ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
                           nfs3svc_lookup_parentdir_cbk, cs);