d1681e
From 59fafc2b918846cc59daac107981211fa1568335 Mon Sep 17 00:00:00 2001
d1681e
From: Susant Palai <spalai@redhat.com>
d1681e
Date: Mon, 6 Aug 2018 15:02:58 +0530
d1681e
Subject: [PATCH 350/351] cluster/dht: fix inode ref management in
d1681e
 dht_heal_path
d1681e
d1681e
In dht_heal_path, the inodes are created & looked up from top to down.
d1681e
d1681e
If the path is "a/b/c", then lookup will be done on a, then b and so
d1681e
on. Here is a rough snippet of the function "dht_heal_path".
d1681e
d1681e
<snippet>
d1681e
if (bname) {						ref_count
d1681e
	- loc.inode = create/grep inode    		  1
d1681e
	- syncop_lookup (loc.inode)
d1681e
	- linked_inode = inode_link (loc.inode)		  2
d1681e
	/*clean up current loc*/
d1681e
	- loc_wipe(&loc)				  1
d1681e
	/*set up parent and bname for next child */
d1681e
	- loc.parent = inode
d1681e
	- bname = next_child_name
d1681e
}
d1681e
out:
d1681e
	- inode_ref (linked_inode)			  2
d1681e
	- loc_wipe (&loc) 				  1
d1681e
</snippet>
d1681e
d1681e
The problem with the above code is if _bname_ is empty ie the chain lookup is
d1681e
done, then for the next iteration we populate loc.parent anyway. Now that
d1681e
bname is empty, the loc_wipe is done in the _out_ section as well. Since, the
d1681e
loc.parent was set to the previous inode, we lose a ref unwantedly. Now a
d1681e
dht_local_wipe as part of the DHT_STACK_UNWIND takes away the last ref leading
d1681e
to inode_destroy.
d1681e
d1681e
This problenm is observed currently with nfs-ganesha with the nameless lookup.
d1681e
Post the inode_purge, gfapi does not get the new inode to link and hence, it links
d1681e
the inode it sent in the lookup fop, which does not have any dht related context
d1681e
(layout) leading to "invalid argument error" in lookup path done parallely with tar
d1681e
operation.
d1681e
d1681e
test done in the following way:
d1681e
 - create two nfs client connected with two different nfs servers.
d1681e
 - run untar on one client and run lookup continuously on the other.
d1681e
 - Prior to this patch, invalid arguement was seen which is fixed with
d1681e
   the current patch.
d1681e
d1681e
> Change-Id: Ifb90c178a2f3c16604068c7da8fa562b877f5c61
d1681e
> fixes: bz#1610256
d1681e
> Signed-off-by: Susant Palai <spalai@redhat.com>
d1681e
(backport of https://review.gluster.org/#/c/glusterfs/+/20643/)
d1681e
d1681e
Fixes: bz#1569657
d1681e
Change-Id: I94329f2d148c31fe85a8753256e7aaf1d4d337ac
d1681e
BUG: 1569657
d1681e
Signed-off-by: Susant Palai <spalai@redhat.com>
d1681e
Reviewed-on: https://code.engineering.redhat.com/gerrit/146966
d1681e
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d1681e
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d1681e
---
d1681e
 xlators/cluster/dht/src/dht-helper.c | 9 +++++++--
d1681e
 1 file changed, 7 insertions(+), 2 deletions(-)
d1681e
d1681e
diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c
d1681e
index 09ca966..d35d7e8 100644
d1681e
--- a/xlators/cluster/dht/src/dht-helper.c
d1681e
+++ b/xlators/cluster/dht/src/dht-helper.c
d1681e
@@ -1974,12 +1974,16 @@ dht_heal_path (xlator_t *this, char *path, inode_table_t *itable)
d1681e
                 } else {
d1681e
                         /*
d1681e
                          * Inode is already populated in the inode table.
d1681e
-                         * Which means we already looked up the inde and
d1681e
+                         * Which means we already looked up the inode and
d1681e
                          * linked with a dentry. So that we will skip
d1681e
                          * lookup on this entry, and proceed to next.
d1681e
                          */
d1681e
+                        linked_inode = loc.inode;
d1681e
                         bname = strtok_r (NULL, "/",  &save_ptr);
d1681e
                         inode_unref (loc.parent);
d1681e
+                        if (!bname) {
d1681e
+                                goto out;
d1681e
+                        }
d1681e
                         loc.parent = loc.inode;
d1681e
                         gf_uuid_copy (loc.pargfid, loc.inode->gfid);
d1681e
                         loc.inode = NULL;
d1681e
@@ -2005,9 +2009,10 @@ dht_heal_path (xlator_t *this, char *path, inode_table_t *itable)
d1681e
                 loc_wipe (&loc;;
d1681e
                 gf_uuid_copy (loc.pargfid, linked_inode->gfid);
d1681e
                 loc.inode = NULL;
d1681e
-                loc.parent = linked_inode;
d1681e
 
d1681e
                 bname = strtok_r (NULL, "/",  &save_ptr);
d1681e
+                if (bname)
d1681e
+                        loc.parent = linked_inode;
d1681e
         }
d1681e
 out:
d1681e
         inode_ref (linked_inode);
d1681e
-- 
d1681e
1.8.3.1
d1681e