From 7cda6661979dfec1614575a9729b84cbf49e6b25 Mon Sep 17 00:00:00 2001 From: Shehjar Tikoo Date: Mon, 31 May 2010 22:43:53 +0000 Subject: nfs3: Special-case the lookup for parent dir of root 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 Signed-off-by: Anand V. Avati BUG: 942 (NFS crashes as a vmware ESX data store) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=942 --- xlators/nfs/server/src/nfs3.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'xlators/nfs') diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index f09ed95d9da..fda6d6413bf 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -895,7 +895,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, @@ -926,18 +934,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); -- cgit