summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/dht/src
diff options
context:
space:
mode:
authorN Balachandran <nbalacha@redhat.com>2018-04-17 15:37:05 +0530
committerRaghavendra G <rgowdapp@redhat.com>2018-04-23 01:43:12 +0000
commit62437c99618551d531103023883b5cabcca20fa6 (patch)
tree71c7cef654f99cd1898d558869e9aac6a185e013 /xlators/cluster/dht/src
parentbca55ab1bfcd2889f8387ba8bcab27766e1b94ac (diff)
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 <nbalacha@redhat.com>
Diffstat (limited to 'xlators/cluster/dht/src')
-rw-r--r--xlators/cluster/dht/src/dht-rename.c65
1 files changed, 47 insertions, 18 deletions
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;