From 62437c99618551d531103023883b5cabcca20fa6 Mon Sep 17 00:00:00 2001 From: N Balachandran Date: Tue, 17 Apr 2018 15:37:05 +0530 Subject: cluster/dht: Fix dht_rename lock order Fixed dht_order_rename_lock to use the same inodelk ordering as that of the dht selfheal locks (dictionary order of lock subvolumes). Change-Id: Ia3f8353b33ea2fd3bc1ba7e8e777dda6c1d33e0d fixes: bz#1568348 Signed-off-by: N Balachandran --- xlators/cluster/dht/src/dht-rename.c | 65 ++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 18 deletions(-) (limited to 'xlators/cluster/dht/src/dht-rename.c') diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c index e61d67ca6d8..3dc042e3ce5 100644 --- a/xlators/cluster/dht/src/dht-rename.c +++ b/xlators/cluster/dht/src/dht-rename.c @@ -490,37 +490,66 @@ err: return 0; } + +/* + * If the hashed subvolumes of both source and dst are the different, + * lock in dictionary order of hashed subvol->name. This is important + * in case the parent directory is the same for both src and dst to + * prevent inodelk deadlocks when racing with a fix-layout op on the parent. + * + * If the hashed subvols are the same, use the gfid/name to determine + * the order of taking locks to prevent entrylk deadlocks when the parent + * dirs are the same. + * + */ static void dht_order_rename_lock (call_frame_t *frame, loc_t **loc, xlator_t **subvol) { - dht_local_t *local = NULL; - char src[GF_UUID_BNAME_BUF_SIZE] = {0}; - char dst[GF_UUID_BNAME_BUF_SIZE] = {0}; + int ret = 0; + dht_local_t *local = NULL; + char src[GF_UUID_BNAME_BUF_SIZE] = {0}; + char dst[GF_UUID_BNAME_BUF_SIZE] = {0}; + local = frame->local; - if (local->loc.pargfid) - uuid_utoa_r (local->loc.pargfid, src); - else if (local->loc.parent) - uuid_utoa_r (local->loc.parent->gfid, src); + if (local->src_hashed->name == local->dst_hashed->name) { + ret = 0; + } else { + ret = strcmp (local->src_hashed->name, local->dst_hashed->name); + } - strcat (src, local->loc.name); + if (ret == 0) { - if (local->loc2.pargfid) - uuid_utoa_r (local->loc2.pargfid, dst); - else if (local->loc2.parent) - uuid_utoa_r (local->loc2.parent->gfid, dst); + /* hashed subvols are the same for src and dst */ + /* Entrylks need to be ordered*/ + if (local->loc.pargfid) + uuid_utoa_r (local->loc.pargfid, src); + else if (local->loc.parent) + uuid_utoa_r (local->loc.parent->gfid, src); - strcat (dst, local->loc2.name); + strcat (src, local->loc.name); - if (strcmp(src, dst) > 0) { - local->current = &local->lock[1]; - *loc = &local->loc2; - *subvol = local->dst_hashed; - } else { + if (local->loc2.pargfid) + uuid_utoa_r (local->loc2.pargfid, dst); + else if (local->loc2.parent) + uuid_utoa_r (local->loc2.parent->gfid, dst); + + strcat (dst, local->loc2.name); + ret = strcmp (src, dst); + } + + if (ret <= 0) { + /*inodelk in dictionary order of hashed subvol names*/ + /*entrylk in dictionary order of gfid/basename */ local->current = &local->lock[0]; *loc = &local->loc; *subvol = local->src_hashed; + + } else { + local->current = &local->lock[1]; + *loc = &local->loc2; + *subvol = local->dst_hashed; } return; -- cgit