From 6adc3cae7f59d421a604ab14c1358c1c60e5ff9c Mon Sep 17 00:00:00 2001 From: Milind Changire Date: Tue, 15 May 2018 08:08:57 -0400 Subject: [PATCH] autobuild v3.12.2-10 Resolves: bz#1488120 bz#1565577 bz#1568297 bz#1570586 bz#1572043 Resolves: bz#1572075 bz#1575840 bz#1575877 Signed-off-by: Milind Changire --- ...bglusterfs-syncop-Add-syncop_entrylk.patch | 86 ++ ...re-the-reaction-on-failures-per-lock.patch | 346 +++++ ...don-t-trust-inode-table-for-RESOLVE_.patch | 110 ++ ...s-to-parallel-renames-to-same-destin.patch | 1201 +++++++++++++++++ ...sterfsd-brick-crash-during-get-state.patch | 47 + ...-glusterd-geo-rep-Fix-glusterd-crash.patch | 42 + 0267-geo-rep-scheduler-Fix-crash.patch | 127 ++ ...ct-is-null-logs-in-dht_discover_comp.patch | 44 + ...hoose-local-in-groups-virt-and-glust.patch | 42 + ...e-brick-crashes-at-the-time-of-inode.patch | 91 ++ ...-cli-Fix-for-gluster-volume-info-xml.patch | 52 + glusterfs.spec | 17 +- 12 files changed, 2204 insertions(+), 1 deletion(-) create mode 100644 0261-libglusterfs-syncop-Add-syncop_entrylk.patch create mode 100644 0262-cluster-dht-store-the-reaction-on-failures-per-lock.patch create mode 100644 0263-server-resolver-don-t-trust-inode-table-for-RESOLVE_.patch create mode 100644 0264-cluster-dht-fixes-to-parallel-renames-to-same-destin.patch create mode 100644 0265-Glusterfsd-brick-crash-during-get-state.patch create mode 100644 0266-glusterd-geo-rep-Fix-glusterd-crash.patch create mode 100644 0267-geo-rep-scheduler-Fix-crash.patch create mode 100644 0268-dht-Excessive-dict-is-null-logs-in-dht_discover_comp.patch create mode 100644 0269-extras-Disable-choose-local-in-groups-virt-and-glust.patch create mode 100644 0270-glusterfs-Resolve-brick-crashes-at-the-time-of-inode.patch create mode 100644 0271-cli-Fix-for-gluster-volume-info-xml.patch diff --git a/0261-libglusterfs-syncop-Add-syncop_entrylk.patch b/0261-libglusterfs-syncop-Add-syncop_entrylk.patch new file mode 100644 index 0000000..fc1271c --- /dev/null +++ b/0261-libglusterfs-syncop-Add-syncop_entrylk.patch @@ -0,0 +1,86 @@ +From 87fd48e99d6b3556aba0c4f1485b06334b8cc1cf Mon Sep 17 00:00:00 2001 +From: Raghavendra G +Date: Wed, 9 May 2018 14:57:35 +0530 +Subject: [PATCH 261/271] libglusterfs/syncop: Add syncop_entrylk + +>Change-Id: Idd86b9f0fa144c2316ab6276e2def28b696ae18a +>BUG: 1543279 +>Signed-off-by: Raghavendra G + +upstream patch: https://review.gluster.org/#/c/19556/ +BUG: 1488120 +Change-Id: I02e546bcb012545dcdaa70ea26046db05b5032f4 +Signed-off-by: Raghavendra G +Reviewed-on: https://code.engineering.redhat.com/gerrit/138169 +Tested-by: RHGS Build Bot +Reviewed-by: Nithya Balachandran +--- + libglusterfs/src/syncop.c | 37 +++++++++++++++++++++++++++++++++++++ + libglusterfs/src/syncop.h | 5 +++++ + 2 files changed, 42 insertions(+) + +diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c +index b36c88d..ac40a1d 100644 +--- a/libglusterfs/src/syncop.c ++++ b/libglusterfs/src/syncop.c +@@ -3019,6 +3019,43 @@ syncop_inodelk (xlator_t *subvol, const char *volume, loc_t *loc, int32_t cmd, + } + + int32_t ++syncop_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ++ int32_t op_ret, int32_t op_errno, dict_t *xdata) ++{ ++ struct syncargs *args = NULL; ++ ++ args = cookie; ++ args->op_ret = op_ret; ++ args->op_errno = op_errno; ++ if (xdata) ++ args->xdata = dict_ref (xdata); ++ ++ __wake (args); ++ return 0; ++} ++ ++int ++syncop_entrylk (xlator_t *subvol, const char *volume, loc_t *loc, ++ const char *basename, entrylk_cmd cmd, entrylk_type type, ++ dict_t *xdata_in, dict_t **xdata_out) ++{ ++ struct syncargs args = {0, }; ++ ++ SYNCOP (subvol, (&args), syncop_entrylk_cbk, subvol->fops->entrylk, ++ volume, loc, basename, cmd, type, xdata_in); ++ ++ if (xdata_out) ++ *xdata_out = args.xdata; ++ else if (args.xdata) ++ dict_unref (args.xdata); ++ ++ if (args.op_ret < 0) ++ return -args.op_errno; ++ ++ return args.op_ret; ++} ++ ++int32_t + syncop_xattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h +index a9cdee1..5b5ad4e 100644 +--- a/libglusterfs/src/syncop.h ++++ b/libglusterfs/src/syncop.h +@@ -562,4 +562,9 @@ syncop_setactivelk (xlator_t *subvol, loc_t *loc, + lock_migration_info_t *locklist, dict_t *xdata_in, + dict_t **xdata_out); + ++int ++syncop_entrylk (xlator_t *subvol, const char *volume, loc_t *loc, ++ const char *basename, entrylk_cmd cmd, entrylk_type type, ++ dict_t *xdata_in, dict_t **xdata_out); ++ + #endif /* _SYNCOP_H */ +-- +1.8.3.1 + diff --git a/0262-cluster-dht-store-the-reaction-on-failures-per-lock.patch b/0262-cluster-dht-store-the-reaction-on-failures-per-lock.patch new file mode 100644 index 0000000..fed7122 --- /dev/null +++ b/0262-cluster-dht-store-the-reaction-on-failures-per-lock.patch @@ -0,0 +1,346 @@ +From 2802d400934b247436edf4d9f85839ad455307ca Mon Sep 17 00:00:00 2001 +From: Raghavendra G +Date: Thu, 8 Feb 2018 13:44:38 +0530 +Subject: [PATCH 262/271] cluster/dht: store the 'reaction' on failures per + lock + +Currently its passed in dht_blocking_inode(entry)lk, which would be a +global value for all the locks passed in the argument. This would +be a limitation for cases where we want to ignore failures on only few +locks and fail for others. + +>Change-Id: I02cfbcaafb593ad8140c0e5af725c866b630fb6b +>BUG: 1543279 +>Signed-off-by: Raghavendra G + +upstream patch: https://review.gluster.org/19546/ +BUG: 1488120 +Change-Id: I2d575530d14c89f90a0ffb790810748d4e296972 +Signed-off-by: Raghavendra G +Reviewed-on: https://code.engineering.redhat.com/gerrit/138153 +Tested-by: RHGS Build Bot +Reviewed-by: Nithya Balachandran +--- + xlators/cluster/dht/src/dht-common.c | 11 ++++++----- + xlators/cluster/dht/src/dht-common.h | 16 +++++++++------- + xlators/cluster/dht/src/dht-lock.c | 27 ++++++++++++++------------- + xlators/cluster/dht/src/dht-lock.h | 9 ++++----- + xlators/cluster/dht/src/dht-rename.c | 8 +++++--- + xlators/cluster/dht/src/dht-selfheal.c | 13 ++++++++----- + 6 files changed, 46 insertions(+), 38 deletions(-) + +diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c +index a985481..5b2c897 100644 +--- a/xlators/cluster/dht/src/dht-common.c ++++ b/xlators/cluster/dht/src/dht-common.c +@@ -7248,7 +7248,8 @@ dht_mknod_lock (call_frame_t *frame, xlator_t *subvol) + goto err; + + lk_array[0] = dht_lock_new (frame->this, subvol, &local->loc, F_RDLCK, +- DHT_LAYOUT_HEAL_DOMAIN, NULL); ++ DHT_LAYOUT_HEAL_DOMAIN, NULL, ++ IGNORE_ENOENT_ESTALE); + + if (lk_array[0] == NULL) + goto err; +@@ -7256,8 +7257,7 @@ dht_mknod_lock (call_frame_t *frame, xlator_t *subvol) + local->lock[0].layout.parent_layout.locks = lk_array; + local->lock[0].layout.parent_layout.lk_count = count; + +- ret = dht_blocking_inodelk (frame, lk_array, count, +- IGNORE_ENOENT_ESTALE, dht_mknod_lock_cbk); ++ ret = dht_blocking_inodelk (frame, lk_array, count, dht_mknod_lock_cbk); + + if (ret < 0) { + local->lock[0].layout.parent_layout.locks = NULL; +@@ -8392,7 +8392,8 @@ dht_create_lock (call_frame_t *frame, xlator_t *subvol) + goto err; + + lk_array[0] = dht_lock_new (frame->this, subvol, &local->loc, F_RDLCK, +- DHT_LAYOUT_HEAL_DOMAIN, NULL); ++ DHT_LAYOUT_HEAL_DOMAIN, NULL, ++ IGNORE_ENOENT_ESTALE); + + if (lk_array[0] == NULL) + goto err; +@@ -8401,7 +8402,7 @@ dht_create_lock (call_frame_t *frame, xlator_t *subvol) + local->lock[0].layout.parent_layout.lk_count = count; + + ret = dht_blocking_inodelk (frame, lk_array, count, +- IGNORE_ENOENT_ESTALE, dht_create_lock_cbk); ++ dht_create_lock_cbk); + + if (ret < 0) { + local->lock[0].layout.parent_layout.locks = NULL; +diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h +index 9d429af..fbc1e29 100644 +--- a/xlators/cluster/dht/src/dht-common.h ++++ b/xlators/cluster/dht/src/dht-common.h +@@ -173,6 +173,7 @@ typedef enum { + } qdstatfs_action_t; + + typedef enum { ++ REACTION_INVALID, + FAIL_ON_ANY_ERROR, + IGNORE_ENOENT_ESTALE + } dht_reaction_type_t; +@@ -187,15 +188,16 @@ struct dht_skip_linkto_unlink { + }; + + typedef struct { +- xlator_t *xl; +- loc_t loc; /* contains/points to inode to lock on. */ +- short type; /* read/write lock. */ +- char *domain; /* Only locks within a single domain ++ xlator_t *xl; ++ loc_t loc; /* contains/points to inode to lock on. */ ++ short type; /* read/write lock. */ ++ char *domain; /* Only locks within a single domain + * contend with each other + */ +- char *basename; /* Required for entrylk */ +- gf_lkowner_t lk_owner; +- gf_boolean_t locked; ++ char *basename; /* Required for entrylk */ ++ gf_lkowner_t lk_owner; ++ gf_boolean_t locked; ++ dht_reaction_type_t do_on_failure; + } dht_lock_t; + + /* The lock structure represents inodelk. */ +diff --git a/xlators/cluster/dht/src/dht-lock.c b/xlators/cluster/dht/src/dht-lock.c +index 45ebeec..3e82c98 100644 +--- a/xlators/cluster/dht/src/dht-lock.c ++++ b/xlators/cluster/dht/src/dht-lock.c +@@ -191,7 +191,8 @@ out: + + dht_lock_t * + dht_lock_new (xlator_t *this, xlator_t *xl, loc_t *loc, short type, +- const char *domain, const char *basename) ++ const char *domain, const char *basename, ++ dht_reaction_type_t do_on_failure) + { + dht_conf_t *conf = NULL; + dht_lock_t *lock = NULL; +@@ -204,6 +205,7 @@ dht_lock_new (xlator_t *this, xlator_t *xl, loc_t *loc, short type, + + lock->xl = xl; + lock->type = type; ++ lock->do_on_failure = do_on_failure; + + lock->domain = gf_strdup (domain); + if (lock->domain == NULL) { +@@ -540,7 +542,7 @@ dht_blocking_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + switch (op_errno) { + case ESTALE: + case ENOENT: +- if (local->lock[0].ns.directory_ns.reaction != IGNORE_ENOENT_ESTALE) { ++ if (local->lock[0].ns.directory_ns.locks[lk_index]->do_on_failure != IGNORE_ENOENT_ESTALE) { + local->lock[0].ns.directory_ns.op_ret = -1; + local->lock[0].ns.directory_ns.op_errno = op_errno; + goto cleanup; +@@ -597,8 +599,7 @@ dht_blocking_entrylk_rec (call_frame_t *frame, int i) + + int + dht_blocking_entrylk (call_frame_t *frame, dht_lock_t **lk_array, +- int lk_count, dht_reaction_type_t reaction, +- fop_entrylk_cbk_t entrylk_cbk) ++ int lk_count, fop_entrylk_cbk_t entrylk_cbk) + { + int ret = -1; + call_frame_t *lock_frame = NULL; +@@ -621,7 +622,6 @@ dht_blocking_entrylk (call_frame_t *frame, dht_lock_t **lk_array, + dht_set_lkowner (lk_array, lk_count, &lock_frame->root->lk_owner); + + local = lock_frame->local; +- local->lock[0].ns.directory_ns.reaction = reaction; + local->main_frame = frame; + + dht_blocking_entrylk_rec (lock_frame, 0); +@@ -1029,7 +1029,8 @@ dht_blocking_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + switch (op_errno) { + case ESTALE: + case ENOENT: +- if (local->lock[0].layout.my_layout.reaction != IGNORE_ENOENT_ESTALE) { ++ if (local->lock[0].layout.my_layout.locks[lk_index]->do_on_failure ++ != IGNORE_ENOENT_ESTALE) { + gf_uuid_unparse (local->lock[0].layout.my_layout.locks[lk_index]->loc.gfid, gfid); + local->lock[0].layout.my_layout.op_ret = -1; + local->lock[0].layout.my_layout.op_errno = op_errno; +@@ -1100,8 +1101,7 @@ dht_blocking_inodelk_rec (call_frame_t *frame, int i) + + int + dht_blocking_inodelk (call_frame_t *frame, dht_lock_t **lk_array, +- int lk_count, dht_reaction_type_t reaction, +- fop_inodelk_cbk_t inodelk_cbk) ++ int lk_count, fop_inodelk_cbk_t inodelk_cbk) + { + int ret = -1; + call_frame_t *lock_frame = NULL; +@@ -1139,7 +1139,6 @@ dht_blocking_inodelk (call_frame_t *frame, dht_lock_t **lk_array, + dht_set_lkowner (lk_array, lk_count, &lock_frame->root->lk_owner); + + local = lock_frame->local; +- local->lock[0].layout.my_layout.reaction = reaction; + local->main_frame = frame; + + dht_blocking_inodelk_rec (lock_frame, 0); +@@ -1210,7 +1209,7 @@ dht_blocking_entrylk_after_inodelk (call_frame_t *frame, void *cookie, + lk_array = entrylk->locks; + count = entrylk->lk_count; + +- ret = dht_blocking_entrylk (frame, lk_array, count, FAIL_ON_ANY_ERROR, ++ ret = dht_blocking_entrylk (frame, lk_array, count, + dht_protect_namespace_cbk); + + if (ret < 0) { +@@ -1303,7 +1302,8 @@ dht_protect_namespace (call_frame_t *frame, loc_t *loc, + } + + inodelk->locks[0] = dht_lock_new (this, subvol, &parent, F_RDLCK, +- DHT_LAYOUT_HEAL_DOMAIN, NULL); ++ DHT_LAYOUT_HEAL_DOMAIN, NULL, ++ FAIL_ON_ANY_ERROR); + if (inodelk->locks[0] == NULL) { + local->op_errno = ENOMEM; + gf_msg (this->name, GF_LOG_WARNING, local->op_errno, +@@ -1330,7 +1330,8 @@ dht_protect_namespace (call_frame_t *frame, loc_t *loc, + } + + entrylk->locks[0] = dht_lock_new (this, subvol, &parent, F_WRLCK, +- DHT_ENTRY_SYNC_DOMAIN, loc->name); ++ DHT_ENTRY_SYNC_DOMAIN, loc->name, ++ FAIL_ON_ANY_ERROR); + if (entrylk->locks[0] == NULL) { + local->op_errno = ENOMEM; + gf_msg (this->name, GF_LOG_WARNING, local->op_errno, +@@ -1347,7 +1348,7 @@ dht_protect_namespace (call_frame_t *frame, loc_t *loc, + * on name in cbk. + */ + lk_array = inodelk->locks; +- ret = dht_blocking_inodelk (frame, lk_array, count, FAIL_ON_ANY_ERROR, ++ ret = dht_blocking_inodelk (frame, lk_array, count, + dht_blocking_entrylk_after_inodelk); + if (ret < 0) { + local->op_errno = EIO; +diff --git a/xlators/cluster/dht/src/dht-lock.h b/xlators/cluster/dht/src/dht-lock.h +index 0557858..f36bf3f 100644 +--- a/xlators/cluster/dht/src/dht-lock.h ++++ b/xlators/cluster/dht/src/dht-lock.h +@@ -22,7 +22,8 @@ dht_lock_count (dht_lock_t **lk_array, int lk_count); + + dht_lock_t * + dht_lock_new (xlator_t *this, xlator_t *xl, loc_t *loc, short type, +- const char *domain, const char *basename); ++ const char *domain, const char *basename, ++ dht_reaction_type_t do_on_failure); + + int32_t + dht_unlock_entrylk_wrapper (call_frame_t *, dht_elock_wrap_t *); +@@ -32,8 +33,7 @@ dht_blocking_entrylk_rec (call_frame_t *frame, int i); + + int + dht_blocking_entrylk (call_frame_t *frame, dht_lock_t **lk_array, +- int lk_count, dht_reaction_type_t reaction, +- fop_inodelk_cbk_t entrylk_cbk); ++ int lk_count, fop_inodelk_cbk_t entrylk_cbk); + + int32_t + dht_unlock_inodelk (call_frame_t *frame, dht_lock_t **lk_array, int lk_count, +@@ -70,8 +70,7 @@ dht_blocking_inodelk_rec (call_frame_t *frame, int i); + + int + dht_blocking_inodelk (call_frame_t *frame, dht_lock_t **lk_array, +- int lk_count, dht_reaction_type_t reaction, +- fop_inodelk_cbk_t inodelk_cbk); ++ int lk_count, fop_inodelk_cbk_t inodelk_cbk); + + int32_t + dht_blocking_entrylk_after_inodelk (call_frame_t *frame, void *cookie, +diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c +index 5a72c1f..3dc042e 100644 +--- a/xlators/cluster/dht/src/dht-rename.c ++++ b/xlators/cluster/dht/src/dht-rename.c +@@ -1649,14 +1649,16 @@ dht_rename_lock (call_frame_t *frame) + goto err; + + lk_array[0] = dht_lock_new (frame->this, local->src_cached, &local->loc, +- F_WRLCK, DHT_FILE_MIGRATE_DOMAIN, NULL); ++ F_WRLCK, DHT_FILE_MIGRATE_DOMAIN, NULL, ++ FAIL_ON_ANY_ERROR); + if (lk_array[0] == NULL) + goto err; + + if (local->dst_cached) { + lk_array[1] = dht_lock_new (frame->this, local->dst_cached, + &local->loc2, F_WRLCK, +- DHT_FILE_MIGRATE_DOMAIN, NULL); ++ DHT_FILE_MIGRATE_DOMAIN, NULL, ++ FAIL_ON_ANY_ERROR); + if (lk_array[1] == NULL) + goto err; + } +@@ -1665,7 +1667,7 @@ dht_rename_lock (call_frame_t *frame) + local->lock[0].layout.parent_layout.lk_count = count; + + ret = dht_blocking_inodelk (frame, lk_array, count, +- FAIL_ON_ANY_ERROR, dht_rename_lock_cbk); ++ dht_rename_lock_cbk); + if (ret < 0) { + local->lock[0].layout.parent_layout.locks = NULL; + local->lock[0].layout.parent_layout.lk_count = 0; +diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c +index 5812f12..e9b1db9 100644 +--- a/xlators/cluster/dht/src/dht-selfheal.c ++++ b/xlators/cluster/dht/src/dht-selfheal.c +@@ -588,7 +588,8 @@ dht_selfheal_layout_lock (call_frame_t *frame, dht_layout_t *layout, + conf->subvolumes[i], + &local->loc, F_WRLCK, + DHT_LAYOUT_HEAL_DOMAIN, +- NULL); ++ NULL, ++ FAIL_ON_ANY_ERROR); + if (lk_array[i] == NULL) { + gf_uuid_unparse (local->stbuf.ia_gfid, gfid); + gf_msg (THIS->name, GF_LOG_ERROR, ENOMEM, +@@ -613,7 +614,8 @@ dht_selfheal_layout_lock (call_frame_t *frame, dht_layout_t *layout, + + lk_array[0] = dht_lock_new (frame->this, local->hashed_subvol, + &local->loc, F_WRLCK, +- DHT_LAYOUT_HEAL_DOMAIN, NULL); ++ DHT_LAYOUT_HEAL_DOMAIN, NULL, ++ FAIL_ON_ANY_ERROR); + if (lk_array[0] == NULL) { + gf_uuid_unparse (local->stbuf.ia_gfid, gfid); + gf_msg (THIS->name, GF_LOG_ERROR, ENOMEM, +@@ -627,7 +629,7 @@ dht_selfheal_layout_lock (call_frame_t *frame, dht_layout_t *layout, + local->lock[0].layout.my_layout.locks = lk_array; + local->lock[0].layout.my_layout.lk_count = count; + +- ret = dht_blocking_inodelk (frame, lk_array, count, FAIL_ON_ANY_ERROR, ++ ret = dht_blocking_inodelk (frame, lk_array, count, + dht_selfheal_layout_lock_cbk); + if (ret < 0) { + local->lock[0].layout.my_layout.locks = NULL; +@@ -2783,7 +2785,8 @@ dht_update_commit_hash_for_layout (call_frame_t *frame) + lk_array[i] = dht_lock_new (frame->this, + conf->local_subvols[i], + &local->loc, F_WRLCK, +- DHT_LAYOUT_HEAL_DOMAIN, NULL); ++ DHT_LAYOUT_HEAL_DOMAIN, NULL, ++ FAIL_ON_ANY_ERROR); + if (lk_array[i] == NULL) + goto err; + } +@@ -2791,7 +2794,7 @@ dht_update_commit_hash_for_layout (call_frame_t *frame) + local->lock[0].layout.my_layout.locks = lk_array; + local->lock[0].layout.my_layout.lk_count = count; + +- ret = dht_blocking_inodelk (frame, lk_array, count, FAIL_ON_ANY_ERROR, ++ ret = dht_blocking_inodelk (frame, lk_array, count, + dht_update_commit_hash_for_layout_resume); + if (ret < 0) { + local->lock[0].layout.my_layout.locks = NULL; +-- +1.8.3.1 + diff --git a/0263-server-resolver-don-t-trust-inode-table-for-RESOLVE_.patch b/0263-server-resolver-don-t-trust-inode-table-for-RESOLVE_.patch new file mode 100644 index 0000000..abc8229 --- /dev/null +++ b/0263-server-resolver-don-t-trust-inode-table-for-RESOLVE_.patch @@ -0,0 +1,110 @@ +From 90092b0c276f599bbe415ecc3051ca12d99461b6 Mon Sep 17 00:00:00 2001 +From: Raghavendra G +Date: Sat, 17 Mar 2018 13:16:59 +0530 +Subject: [PATCH 263/271] server/resolver: don't trust inode-table for + RESOLVE_NOT + +There have been known races between fops which add a dentry (like +lookup, create, mknod etc) and fops that remove a dentry (like rename, +unlink, rmdir etc) due to which stale dentries are left out in inode +table even though the dentry doesn't exist on backend. For eg., +consider a lookup (parent/bname) and unlink (parent/bname) racing in +the following order: + +* lookup hits storage/posix and finds that dentry exists +* unlink removes the dentry on storage/posix +* unlink reaches protocol/server where the dentry (parent/bname) is + unlinked from the inode +* lookup reaches protocol/server and creates a dentry (parent/bname) + on the inode + +Now we've a stale dentry (parent/bname) associated with the inode in +itable. This situation is bad for fops like link, create etc which +invoke resolver with type RESOLVE_NOT. These fops fail with EEXIST +even though there is no such dentry on backend fs. This issue can be +solved in two ways: + +* Enable "dentry fop serializer" xlator [1]. + # gluster volume set features.sdfs on + +* Make sure resolver does a lookup on backend when it finds a dentry + in itable and validates the state of itable. + - If a dentry is not found, unlink those stale dentries from itable + and continue with fop + - If dentry is found, fail the fop with EEXIST + +This patch implements second solution as sdfs is not enabled by +default in brick xlator stack. Once sdfs is enabled by default, this +patch can be reverted. + +[1] https://github.com/gluster/glusterfs/issues/397 + +>Change-Id: Ia8bb0cf97f97cb0e72639bce8aadb0f6d3f4a34a +>updates: bz#1543279 +>BUG: 1543279 +>Signed-off-by: Raghavendra G + +upstream patch: https://review.gluster.org/19732 +BUG: 1488120 +Change-Id: I78df4f6751e5db1fc659ee15d92b76d1486455f0 +Signed-off-by: Raghavendra G +Reviewed-on: https://code.engineering.redhat.com/gerrit/138152 +Tested-by: RHGS Build Bot +Reviewed-by: Nithya Balachandran +--- + xlators/protocol/server/src/server-resolve.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/xlators/protocol/server/src/server-resolve.c b/xlators/protocol/server/src/server-resolve.c +index d0126aa..6ffb909 100644 +--- a/xlators/protocol/server/src/server-resolve.c ++++ b/xlators/protocol/server/src/server-resolve.c +@@ -58,10 +58,27 @@ resolve_gfid_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + + if (op_ret == -1) { + if (op_errno == ENOENT) { +- gf_msg_debug (this->name, 0, "%s/%s: failed to resolve" +- " (%s)", ++ gf_msg_debug (this->name, 0, ++ "%s/%s: failed to resolve (%s)", + uuid_utoa (resolve_loc->pargfid), + resolve_loc->name, strerror (op_errno)); ++ if (resolve->type == RESOLVE_NOT) { ++ do { ++ inode = inode_grep (state->itable, ++ resolve_loc->parent, ++ resolve->bname); ++ ++ if (inode) { ++ gf_msg_debug (this->name, 0, "%s/%s: " ++ "removing stale dentry", ++ uuid_utoa (resolve_loc->pargfid), ++ resolve->bname); ++ inode_unlink (inode, ++ resolve_loc->parent, ++ resolve->bname); ++ } ++ } while (inode); ++ } + } else { + gf_msg (this->name, GF_LOG_WARNING, op_errno, + PS_MSG_GFID_RESOLVE_FAILED, "%s/%s: failed to " +@@ -318,11 +335,13 @@ resolve_entry_simple (call_frame_t *frame) + + if (resolve->type == RESOLVE_NOT) { + gf_msg_debug (this->name, 0, "inode (pointer: %p gfid:%s found" +- " for path (%s) while type is RESOLVE_NOT", ++ " for path (%s) while type is RESOLVE_NOT. " ++ "Performing lookup on backend to rule out any " ++ "possible stale dentries in inode table", + inode, uuid_utoa (inode->gfid), resolve->path); + resolve->op_ret = -1; + resolve->op_errno = EEXIST; +- ret = -1; ++ ret = 1; + goto out; + } + +-- +1.8.3.1 + diff --git a/0264-cluster-dht-fixes-to-parallel-renames-to-same-destin.patch b/0264-cluster-dht-fixes-to-parallel-renames-to-same-destin.patch new file mode 100644 index 0000000..6c92c4d --- /dev/null +++ b/0264-cluster-dht-fixes-to-parallel-renames-to-same-destin.patch @@ -0,0 +1,1201 @@ +From 3b37bb9892cd89169d8b4bd308cdca2543fee08c Mon Sep 17 00:00:00 2001 +From: Raghavendra G +Date: Thu, 8 Feb 2018 17:12:41 +0530 +Subject: [PATCH 264/271] cluster/dht: fixes to parallel renames to same + destination codepath + +Test case: + # while true; do uuid="`uuidgen`"; echo "some data" > "test$uuid"; mv + "test$uuid" "test" -f || break; echo "done:$uuid"; done + + This script was run in parallel from multiple mountpoints + +Along the course of getting the above usecase working, many issues +were found: + +Issue 1: +======= +consider a case of rename (src, dst). We can encounter a situation +where, +* dst is a file present at the time of lookup +* dst is removed by the time rename fop reaches glusterfs + +In this scenario, acquring inodelk on dst fails with ESTALE resulting +in failure of rename. However, as per POSIX irrespective of whether +dst is present or not, rename should be successful. Acquiring entrylk +provides synchronization even in races like this. + +Algorithm: +1. Take inodelks on src and dst (if dst is present) on respective + cached subvols. These inodelks are done to preserve backward + compatibility with older clients, so that synchronization is + preserved when a volume is mounted by clients of different + versions. Once relevant older versions (3.10, 3.12, 3.13) reach + EOL, this code can be removed. +2. Ignore ENOENT/ESTALE errors of inodelk on dst. +3. protect namespace of src and dst. To protect namespace of a file, + take inodelk on parent on hashed subvol, then take entrylk on the + same subvol on parent with basename of file. inodelk on parent is + done to guard against changes to parent layout so that hashed + subvol won't change during rename. +4. +5. unlock all locks + +Issue 2: +======== +linkfile creation in lookup codepath can race with a rename. Imagine +the following scenario: +* lookup finds a data-file with gfid - gfid-dst - without a + corresponding linkto file on hashed-subvol. It decides to create + linkto file with gfid - gfid-dst. + - Note that some codepaths of dht-rename deletes linkto file of + dst as first step. So, a lookup racing with an in-progress + rename can easily run into this situation. +* a rename (src-path:gfid-src, dst-path:gfid-dst) renames data-file + and hence gfid of data-file changes to gfid-src with path dst-path. +* lookup proceeds and creates linkto file - dst-path - with gfid - + dst-gfid - on hashed-subvol. +* rename tries to create a linkto file dst-path with src-gfid on + hashed-subvol, but it fails with EEXIST. But EEXIST is ignored + during linkto file creation. + +Now we've ended with dst-path having different gfids - dst-gfid on +linkto file and src-gfid on data file. Future lookups on dst-path will +always fail with ESTALE, due to differing gfids. + +The fix is to synchronize linkfile creation in lookup path with rename +using the same mechanism of protecting namespace explained in solution +of Issue 1. Once locks are acquired, before proceeding with linkfile +creation, we check whether conditions for linkto file creation are +still valid. If not, we skip linkto file creation. + +Issue 3: +======== +gfid of dst-path can change by the time locks are acquired. This +means, either another rename overwrote dst-path or dst-path was +deleted and recreated by a different client. When this happens, +cached-subvol for dst can change. If rename proceeds with old-gfid and +old-cached subvol, we'll end up in inconsistent state(s) like dst-path +with different gfids on different subvols, more than one data-file +being present etc. + +Fix is to do the lookup with a new inode after protecting namespace of +dst. Post lookup, we've to compare gfids and correct local state +appropriately to be in sync with backend. + +Issue 4: +======== +During revalidate lookup, if following a linkto file doesn't lead to a +valid data-file, local->cached-subvol was not reset to NULL. This +means we would be operating on a stale state which can lead to +inconsistency. As a fix, reset it to NULL before proceeding with +lookup everywhere. + +Issue 5: +======== +Stale dentries left out in inode table on brick resulted in failures +of link fop even though the file/dentry didn't exist on backend fs. A +patch is submitted to fix this issue. Please check the dependency tree +of current patch on gerrit for details + +In short, we fix the problem by not blindly trusting the +inode-table. Instead we validate whether dentry is present by doing +lookup on backend fs. + +>Change-Id: I832e5c47d232f90c4edb1fafc512bf19bebde165 +>updates: bz#1543279 +>BUG: 1543279 +>Signed-off-by: Raghavendra G + +upstream patch: https://review.gluster.org/19547/ +Change-Id: Ief74bd920e807e88eef3f5cf33ba0bf2f0f248f6 +BUG: 1488120 +Signed-off-by: Raghavendra G +Reviewed-on: https://code.engineering.redhat.com/gerrit/138154 +Tested-by: RHGS Build Bot +Reviewed-by: Nithya Balachandran +--- + tests/bugs/distribute/bug-1543279.t | 65 ++++++ + tests/include.rc | 3 +- + xlators/cluster/dht/src/dht-common.c | 175 ++++++++++++++-- + xlators/cluster/dht/src/dht-common.h | 10 +- + xlators/cluster/dht/src/dht-helper.c | 1 + + xlators/cluster/dht/src/dht-lock.c | 29 ++- + xlators/cluster/dht/src/dht-rebalance.c | 63 +++++- + xlators/cluster/dht/src/dht-rename.c | 361 +++++++++++++++++++++++++++----- + 8 files changed, 625 insertions(+), 82 deletions(-) + create mode 100644 tests/bugs/distribute/bug-1543279.t + +diff --git a/tests/bugs/distribute/bug-1543279.t b/tests/bugs/distribute/bug-1543279.t +new file mode 100644 +index 0000000..67cc0f5 +--- /dev/null ++++ b/tests/bugs/distribute/bug-1543279.t +@@ -0,0 +1,65 @@ ++#!/bin/bash ++ ++. $(dirname $0)/../../include.rc ++. $(dirname $0)/../../volume.rc ++. $(dirname $0)/../../dht.rc ++ ++TESTS_EXPECTED_IN_LOOP=44 ++SCRIPT_TIMEOUT=600 ++ ++rename_files() { ++ MOUNT=$1 ++ ITERATIONS=$2 ++ for i in $(seq 1 $ITERATIONS); do uuid="`uuidgen`"; echo "some data" > $MOUNT/test$uuid; mv $MOUNT/test$uuid $MOUNT/test -f || return $?; done ++} ++ ++run_test_for_volume() { ++ VOLUME=$1 ++ ITERATIONS=$2 ++ TEST_IN_LOOP $CLI volume start $VOLUME ++ ++ TEST_IN_LOOP glusterfs -s $H0 --volfile-id $VOLUME $M0 ++ TEST_IN_LOOP glusterfs -s $H0 --volfile-id $VOLUME $M1 ++ TEST_IN_LOOP glusterfs -s $H0 --volfile-id $VOLUME $M2 ++ TEST_IN_LOOP glusterfs -s $H0 --volfile-id $VOLUME $M3 ++ ++ rename_files $M0 $ITERATIONS & ++ M0_RENAME_PID=$! ++ ++ rename_files $M1 $ITERATIONS & ++ M1_RENAME_PID=$! ++ ++ rename_files $M2 $ITERATIONS & ++ M2_RENAME_PID=$! ++ ++ rename_files $M3 $ITERATIONS & ++ M3_RENAME_PID=$! ++ ++ TEST_IN_LOOP wait $M0_RENAME_PID ++ TEST_IN_LOOP wait $M1_RENAME_PID ++ TEST_IN_LOOP wait $M2_RENAME_PID ++ TEST_IN_LOOP wait $M3_RENAME_PID ++ ++ TEST_IN_LOOP $CLI volume stop $VOLUME ++ TEST_IN_LOOP $CLI volume delete $VOLUME ++ umount $M0 $M1 $M2 $M3 ++} ++ ++cleanup ++ ++TEST glusterd ++TEST pidof glusterd ++ ++TEST $CLI volume create $V0 $H0:$B0/${V0}{0..8} force ++run_test_for_volume $V0 200 ++ ++TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{0..8} force ++run_test_for_volume $V0 200 ++ ++TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0..8} force ++run_test_for_volume $V0 200 ++ ++TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5} force ++run_test_for_volume $V0 200 ++ ++cleanup +diff --git a/tests/include.rc b/tests/include.rc +index 45392e0..aca4c4a 100644 +--- a/tests/include.rc ++++ b/tests/include.rc +@@ -1,6 +1,7 @@ + M0=${M0:=/mnt/glusterfs/0}; # 0th mount point for FUSE + M1=${M1:=/mnt/glusterfs/1}; # 1st mount point for FUSE + M2=${M2:=/mnt/glusterfs/2}; # 2nd mount point for FUSE ++M3=${M3:=/mnt/glusterfs/3}; # 3rd mount point for FUSE + N0=${N0:=/mnt/nfs/0}; # 0th mount point for NFS + N1=${N1:=/mnt/nfs/1}; # 1st mount point for NFS + V0=${V0:=patchy}; # volume name to use in tests +@@ -8,7 +9,7 @@ V1=${V1:=patchy1}; # volume name to use in tests + GMV0=${GMV0:=master}; # master volume name to use in geo-rep tests + GSV0=${GSV0:=slave}; # slave volume name to use in geo-rep tests + B0=${B0:=/d/backends}; # top level of brick directories +-WORKDIRS="$B0 $M0 $M1 $M2 $N0 $N1" ++WORKDIRS="$B0 $M0 $M1 $M2 $M3 $N0 $N1" + + ROOT_GFID="00000000-0000-0000-0000-000000000001" + DOT_SHARD_GFID="be318638-e8a0-4c6d-977d-7a937aa84806" +diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c +index 5b2c897..ec1628a 100644 +--- a/xlators/cluster/dht/src/dht-common.c ++++ b/xlators/cluster/dht/src/dht-common.c +@@ -1931,7 +1931,6 @@ dht_lookup_linkfile_create_cbk (call_frame_t *frame, void *cookie, + GF_VALIDATE_OR_GOTO ("dht", this, out); + GF_VALIDATE_OR_GOTO ("dht", frame->local, out); + GF_VALIDATE_OR_GOTO ("dht", this->private, out); +- GF_VALIDATE_OR_GOTO ("dht", cookie, out); + + local = frame->local; + cached_subvol = local->cached_subvol; +@@ -1939,6 +1938,9 @@ dht_lookup_linkfile_create_cbk (call_frame_t *frame, void *cookie, + + gf_uuid_unparse(local->loc.gfid, gfid); + ++ if (local->locked) ++ dht_unlock_namespace (frame, &local->lock[0]); ++ + ret = dht_layout_preset (this, local->cached_subvol, local->loc.inode); + if (ret < 0) { + gf_msg_debug (this->name, EINVAL, +@@ -1962,6 +1964,7 @@ dht_lookup_linkfile_create_cbk (call_frame_t *frame, void *cookie, + postparent, 1); + } + ++ + unwind: + gf_msg_debug (this->name, 0, + "creation of linkto on hashed subvol:%s, " +@@ -2133,6 +2136,134 @@ err: + return -1; + + } ++ ++int32_t ++dht_linkfile_create_lookup_cbk (call_frame_t *frame, void *cookie, ++ xlator_t *this, int32_t op_ret, ++ int32_t op_errno, inode_t *inode, ++ struct iatt *buf, dict_t *xdata, ++ struct iatt *postparent) ++{ ++ dht_local_t *local = NULL; ++ int call_cnt = 0, ret = 0; ++ xlator_t *subvol = NULL; ++ uuid_t gfid = {0, }; ++ char gfid_str[GF_UUID_BUF_SIZE] = {0}; ++ ++ subvol = cookie; ++ local = frame->local; ++ ++ if (subvol == local->hashed_subvol) { ++ if ((op_ret == 0) || (op_errno != ENOENT)) ++ local->dont_create_linkto = _gf_true; ++ } else { ++ if (gf_uuid_is_null (local->gfid)) ++ gf_uuid_copy (gfid, local->loc.gfid); ++ else ++ gf_uuid_copy (gfid, local->gfid); ++ ++ if ((op_ret == 0) && gf_uuid_compare (gfid, buf->ia_gfid)) { ++ gf_uuid_unparse (gfid, gfid_str); ++ gf_msg_debug (this->name, 0, ++ "gfid (%s) different on cached subvol " ++ "(%s) and looked up inode (%s), not " ++ "creating linkto", ++ uuid_utoa (buf->ia_gfid), subvol->name, ++ gfid_str); ++ local->dont_create_linkto = _gf_true; ++ } else if (op_ret == -1) { ++ local->dont_create_linkto = _gf_true; ++ } ++ } ++ ++ call_cnt = dht_frame_return (frame); ++ if (is_last_call (call_cnt)) { ++ if (local->dont_create_linkto) ++ goto no_linkto; ++ else { ++ gf_msg_debug (this->name, 0, ++ "Creating linkto file on %s(hash) to " ++ "%s on %s (gfid = %s)", ++ local->hashed_subvol->name, ++ local->loc.path, ++ local->cached_subvol->name, gfid); ++ ++ ret = dht_linkfile_create ++ (frame, dht_lookup_linkfile_create_cbk, ++ this, local->cached_subvol, ++ local->hashed_subvol, &local->loc); ++ ++ if (ret < 0) ++ goto no_linkto; ++ } ++ } ++ ++ return 0; ++ ++no_linkto: ++ gf_msg_debug (this->name, 0, ++ "skipped linkto creation (path:%s) (gfid:%s) " ++ "(hashed-subvol:%s) (cached-subvol:%s)", ++ local->loc.path, gfid_str, local->hashed_subvol->name, ++ local->cached_subvol->name); ++ ++ dht_lookup_linkfile_create_cbk (frame, NULL, this, 0, 0, ++ local->loc.inode, &local->stbuf, ++ &local->preparent, &local->postparent, ++ local->xattr); ++ return 0; ++} ++ ++ ++int32_t ++dht_call_lookup_linkfile_create (call_frame_t *frame, void *cookie, ++ xlator_t *this, int32_t op_ret, ++ int32_t op_errno, dict_t *xdata) ++{ ++ dht_local_t *local = NULL; ++ char gfid[GF_UUID_BUF_SIZE] = {0}; ++ int i = 0; ++ xlator_t *subvol = NULL; ++ ++ local = frame->local; ++ if (gf_uuid_is_null (local->gfid)) ++ gf_uuid_unparse (local->loc.gfid, gfid); ++ else ++ gf_uuid_unparse (local->gfid, gfid); ++ ++ if (op_ret < 0) { ++ gf_log (this->name, GF_LOG_WARNING, ++ "protecting namespace failed, skipping linkto " ++ "creation (path:%s)(gfid:%s)(hashed-subvol:%s)" ++ "(cached-subvol:%s)", local->loc.path, gfid, ++ local->hashed_subvol->name, local->cached_subvol->name); ++ goto err; ++ } ++ ++ local->locked = _gf_true; ++ ++ ++ local->call_cnt = 2; ++ ++ for (i = 0; i < 2; i++) { ++ subvol = (subvol == NULL) ? local->hashed_subvol ++ : local->cached_subvol; ++ ++ STACK_WIND_COOKIE (frame, dht_linkfile_create_lookup_cbk, ++ subvol, subvol, subvol->fops->lookup, ++ &local->loc, NULL); ++ } ++ ++ return 0; ++ ++err: ++ dht_lookup_linkfile_create_cbk (frame, NULL, this, 0, 0, ++ local->loc.inode, ++ &local->stbuf, &local->preparent, ++ &local->postparent, local->xattr); ++ return 0; ++} ++ + /* Rebalance is performed from cached_node to hashed_node. Initial cached_node + * contains a non-linkto file. After migration it is converted to linkto and + * then unlinked. And at hashed_subvolume, first a linkto file is present, +@@ -2176,12 +2307,12 @@ err: + int + dht_lookup_everywhere_done (call_frame_t *frame, xlator_t *this) + { +- int ret = 0; +- dht_local_t *local = NULL; +- xlator_t *hashed_subvol = NULL; +- xlator_t *cached_subvol = NULL; +- dht_layout_t *layout = NULL; +- char gfid[GF_UUID_BUF_SIZE] = {0}; ++ int ret = 0; ++ dht_local_t *local = NULL; ++ xlator_t *hashed_subvol = NULL; ++ xlator_t *cached_subvol = NULL; ++ dht_layout_t *layout = NULL; ++ char gfid[GF_UUID_BUF_SIZE] = {0}; + gf_boolean_t found_non_linkto_on_hashed = _gf_false; + + local = frame->local; +@@ -2273,8 +2404,8 @@ dht_lookup_everywhere_done (call_frame_t *frame, xlator_t *this) + "unlink on hashed is not skipped %s", + local->loc.path); + +- DHT_STACK_UNWIND (lookup, frame, -1, ENOENT, NULL, NULL, +- NULL, NULL); ++ DHT_STACK_UNWIND (lookup, frame, -1, ENOENT, ++ NULL, NULL, NULL, NULL); + } + return 0; + } +@@ -2490,14 +2621,23 @@ preset_layout: + return 0; + } + +- gf_msg_debug (this->name, 0, +- "Creating linkto file on %s(hash) to %s on %s (gfid = %s)", +- hashed_subvol->name, local->loc.path, +- cached_subvol->name, gfid); ++ if (frame->root->op != GF_FOP_RENAME) { ++ local->current = &local->lock[0]; ++ ret = dht_protect_namespace (frame, &local->loc, hashed_subvol, ++ &local->current->ns, ++ dht_call_lookup_linkfile_create); ++ } else { ++ gf_msg_debug (this->name, 0, ++ "Creating linkto file on %s(hash) to %s on %s " ++ "(gfid = %s)", ++ hashed_subvol->name, local->loc.path, ++ cached_subvol->name, gfid); + +- ret = dht_linkfile_create (frame, +- dht_lookup_linkfile_create_cbk, this, +- cached_subvol, hashed_subvol, &local->loc); ++ ret = dht_linkfile_create (frame, ++ dht_lookup_linkfile_create_cbk, this, ++ cached_subvol, hashed_subvol, ++ &local->loc); ++ } + + return ret; + +@@ -2800,6 +2940,7 @@ dht_lookup_linkfile_cbk (call_frame_t *frame, void *cookie, + removed, which can take away the namespace, and subvol is + anyways down. */ + ++ local->cached_subvol = NULL; + if (op_errno != ENOTCONN) + goto err; + else +@@ -8175,7 +8316,7 @@ out: + + int + dht_build_parent_loc (xlator_t *this, loc_t *parent, loc_t *child, +- int32_t *op_errno) ++ int32_t *op_errno) + { + inode_table_t *table = NULL; + int ret = -1; +diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h +index fbc1e29..10b7c7e 100644 +--- a/xlators/cluster/dht/src/dht-common.h ++++ b/xlators/cluster/dht/src/dht-common.h +@@ -175,7 +175,8 @@ typedef enum { + typedef enum { + REACTION_INVALID, + FAIL_ON_ANY_ERROR, +- IGNORE_ENOENT_ESTALE ++ IGNORE_ENOENT_ESTALE, ++ IGNORE_ENOENT_ESTALE_EIO, + } dht_reaction_type_t; + + struct dht_skip_linkto_unlink { +@@ -367,6 +368,10 @@ struct dht_local { + + dht_dir_transaction_t lock[2], *current; + ++ /* inodelks during filerename for backward compatibility */ ++ dht_lock_t **rename_inodelk_backward_compatible; ++ int rename_inodelk_bc_count; ++ + short lock_type; + + call_stub_t *stub; +@@ -385,6 +390,9 @@ struct dht_local { + int32_t valid; + gf_boolean_t heal_layout; + int32_t mds_heal_fresh_lookup; ++ loc_t loc2_copy; ++ gf_boolean_t locked; ++ gf_boolean_t dont_create_linkto; + }; + typedef struct dht_local dht_local_t; + +diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c +index 6e20aea..09ca966 100644 +--- a/xlators/cluster/dht/src/dht-helper.c ++++ b/xlators/cluster/dht/src/dht-helper.c +@@ -735,6 +735,7 @@ dht_local_wipe (xlator_t *this, dht_local_t *local) + + loc_wipe (&local->loc); + loc_wipe (&local->loc2); ++ loc_wipe (&local->loc2_copy); + + if (local->xattr) + dict_unref (local->xattr); +diff --git a/xlators/cluster/dht/src/dht-lock.c b/xlators/cluster/dht/src/dht-lock.c +index 3e82c98..3f389ea 100644 +--- a/xlators/cluster/dht/src/dht-lock.c ++++ b/xlators/cluster/dht/src/dht-lock.c +@@ -1015,10 +1015,11 @@ static int32_t + dht_blocking_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) + { +- int lk_index = 0; +- int i = 0; +- dht_local_t *local = NULL; +- char gfid[GF_UUID_BUF_SIZE] = {0,}; ++ int lk_index = 0; ++ int i = 0; ++ dht_local_t *local = NULL; ++ char gfid[GF_UUID_BUF_SIZE] = {0,}; ++ dht_reaction_type_t reaction = 0; + + lk_index = (long) cookie; + +@@ -1029,8 +1030,9 @@ dht_blocking_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + switch (op_errno) { + case ESTALE: + case ENOENT: +- if (local->lock[0].layout.my_layout.locks[lk_index]->do_on_failure +- != IGNORE_ENOENT_ESTALE) { ++ reaction = local->lock[0].layout.my_layout.locks[lk_index]->do_on_failure; ++ if ((reaction != IGNORE_ENOENT_ESTALE) && ++ (reaction != IGNORE_ENOENT_ESTALE_EIO)) { + gf_uuid_unparse (local->lock[0].layout.my_layout.locks[lk_index]->loc.gfid, gfid); + local->lock[0].layout.my_layout.op_ret = -1; + local->lock[0].layout.my_layout.op_errno = op_errno; +@@ -1042,6 +1044,21 @@ dht_blocking_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + goto cleanup; + } + break; ++ case EIO: ++ reaction = local->lock[0].layout.my_layout.locks[lk_index]->do_on_failure; ++ if (reaction != IGNORE_ENOENT_ESTALE_EIO) { ++ gf_uuid_unparse (local->lock[0].layout.my_layout.locks[lk_index]->loc.gfid, gfid); ++ local->lock[0].layout.my_layout.op_ret = -1; ++ local->lock[0].layout.my_layout.op_errno = op_errno; ++ gf_msg (this->name, GF_LOG_ERROR, op_errno, ++ DHT_MSG_INODELK_FAILED, ++ "inodelk failed on subvol %s. gfid:%s", ++ local->lock[0].layout.my_layout.locks[lk_index]->xl->name, ++ gfid); ++ goto cleanup; ++ } ++ break; ++ + default: + gf_uuid_unparse (local->lock[0].layout.my_layout.locks[lk_index]->loc.gfid, gfid); + local->lock[0].layout.my_layout.op_ret = -1; +diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c +index 51af11c..f03931f 100644 +--- a/xlators/cluster/dht/src/dht-rebalance.c ++++ b/xlators/cluster/dht/src/dht-rebalance.c +@@ -1470,7 +1470,9 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, + struct gf_flock flock = {0, }; + struct gf_flock plock = {0, }; + loc_t tmp_loc = {0, }; +- gf_boolean_t locked = _gf_false; ++ loc_t parent_loc = {0, }; ++ gf_boolean_t inodelk_locked = _gf_false; ++ gf_boolean_t entrylk_locked = _gf_false; + gf_boolean_t p_locked = _gf_false; + int lk_ret = -1; + gf_defrag_info_t *defrag = NULL; +@@ -1484,6 +1486,7 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, + gf_boolean_t target_changed = _gf_false; + xlator_t *new_target = NULL; + xlator_t *old_target = NULL; ++ xlator_t *hashed_subvol = NULL; + fd_t *linkto_fd = NULL; + + +@@ -1552,6 +1555,28 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, + " for file: %s", loc->path); + } + ++ ret = dht_build_parent_loc (this, &parent_loc, loc, fop_errno); ++ if (ret < 0) { ++ ret = -1; ++ gf_msg (this->name, GF_LOG_WARNING, *fop_errno, ++ DHT_MSG_MIGRATE_FILE_FAILED, ++ "%s: failed to build parent loc, which is needed to " ++ "acquire entrylk to synchronize with renames on this " ++ "path. Skipping migration", loc->path); ++ goto out; ++ } ++ ++ hashed_subvol = dht_subvol_get_hashed (this, loc); ++ if (hashed_subvol == NULL) { ++ ret = -1; ++ gf_msg (this->name, GF_LOG_WARNING, EINVAL, ++ DHT_MSG_MIGRATE_FILE_FAILED, ++ "%s: cannot find hashed subvol which is needed to " ++ "synchronize with renames on this path. " ++ "Skipping migration", loc->path); ++ goto out; ++ } ++ + flock.l_type = F_WRLCK; + + tmp_loc.inode = inode_ref (loc->inode); +@@ -1576,7 +1601,26 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, + goto out; + } + +- locked = _gf_true; ++ inodelk_locked = _gf_true; ++ ++ /* dht_rename has changed to use entrylk on hashed subvol for ++ * synchronization. So, rebalance too has to acquire an entrylk on ++ * hashed subvol. ++ */ ++ ret = syncop_entrylk (hashed_subvol, DHT_ENTRY_SYNC_DOMAIN, &parent_loc, ++ loc->name, ENTRYLK_LOCK, ENTRYLK_WRLCK, NULL, ++ NULL); ++ if (ret < 0) { ++ *fop_errno = -ret; ++ ret = -1; ++ gf_msg (this->name, GF_LOG_WARNING, *fop_errno, ++ DHT_MSG_MIGRATE_FILE_FAILED, ++ "%s: failed to acquire entrylk on subvol %s", ++ loc->path, hashed_subvol->name); ++ goto out; ++ } ++ ++ entrylk_locked = _gf_true; + + /* Phase 1 - Data migration is in progress from now on */ + ret = syncop_lookup (from, loc, &stbuf, NULL, dict, &xattr_rsp); +@@ -2231,7 +2275,7 @@ out: + } + } + +- if (locked) { ++ if (inodelk_locked) { + flock.l_type = F_UNLCK; + + lk_ret = syncop_inodelk (from, DHT_FILE_MIGRATE_DOMAIN, +@@ -2244,6 +2288,18 @@ out: + } + } + ++ if (entrylk_locked) { ++ lk_ret = syncop_entrylk (hashed_subvol, DHT_ENTRY_SYNC_DOMAIN, ++ &parent_loc, loc->name, ENTRYLK_UNLOCK, ++ ENTRYLK_UNLOCK, NULL, NULL); ++ if (lk_ret < 0) { ++ gf_msg (this->name, GF_LOG_WARNING, -lk_ret, ++ DHT_MSG_MIGRATE_FILE_FAILED, ++ "%s: failed to unlock entrylk on %s", ++ loc->path, hashed_subvol->name); ++ } ++ } ++ + if (p_locked) { + plock.l_type = F_UNLCK; + lk_ret = syncop_lk (from, src_fd, F_SETLK, &plock, NULL, NULL); +@@ -2272,6 +2328,7 @@ out: + syncop_close (linkto_fd); + + loc_wipe (&tmp_loc); ++ loc_wipe (&parent_loc); + + return ret; + } +diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c +index 3dc042e..d311ac6 100644 +--- a/xlators/cluster/dht/src/dht-rename.c ++++ b/xlators/cluster/dht/src/dht-rename.c +@@ -18,6 +18,9 @@ + #include "defaults.h" + + int dht_rename_unlock (call_frame_t *frame, xlator_t *this); ++int32_t ++dht_rename_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ++ int32_t op_ret, int32_t op_errno, dict_t *xdata); + + int + dht_rename_unlock_cbk (call_frame_t *frame, void *cookie, +@@ -44,7 +47,7 @@ dht_rename_unlock_cbk (call_frame_t *frame, void *cookie, + } + + static void +-dht_rename_unlock_src (call_frame_t *frame, xlator_t *this) ++dht_rename_dir_unlock_src (call_frame_t *frame, xlator_t *this) + { + dht_local_t *local = NULL; + +@@ -54,7 +57,7 @@ dht_rename_unlock_src (call_frame_t *frame, xlator_t *this) + } + + static void +-dht_rename_unlock_dst (call_frame_t *frame, xlator_t *this) ++dht_rename_dir_unlock_dst (call_frame_t *frame, xlator_t *this) + { + dht_local_t *local = NULL; + int op_ret = -1; +@@ -107,8 +110,8 @@ static int + dht_rename_dir_unlock (call_frame_t *frame, xlator_t *this) + { + +- dht_rename_unlock_src (frame, this); +- dht_rename_unlock_dst (frame, this); ++ dht_rename_dir_unlock_src (frame, this); ++ dht_rename_dir_unlock_dst (frame, this); + return 0; + } + int +@@ -721,12 +724,13 @@ dht_rename_unlock (call_frame_t *frame, xlator_t *this) + int op_ret = -1; + char src_gfid[GF_UUID_BUF_SIZE] = {0}; + char dst_gfid[GF_UUID_BUF_SIZE] = {0}; ++ dht_ilock_wrap_t inodelk_wrapper = {0, }; + + local = frame->local; +- op_ret = dht_unlock_inodelk (frame, +- local->lock[0].layout.parent_layout.locks, +- local->lock[0].layout.parent_layout.lk_count, +- dht_rename_unlock_cbk); ++ inodelk_wrapper.locks = local->rename_inodelk_backward_compatible; ++ inodelk_wrapper.lk_count = local->rename_inodelk_bc_count; ++ ++ op_ret = dht_unlock_inodelk_wrapper (frame, &inodelk_wrapper); + if (op_ret < 0) { + uuid_utoa_r (local->loc.inode->gfid, src_gfid); + +@@ -752,10 +756,13 @@ dht_rename_unlock (call_frame_t *frame, xlator_t *this) + "stale locks left on bricks", + local->loc.path, src_gfid, + local->loc2.path, dst_gfid); +- +- dht_rename_unlock_cbk (frame, NULL, this, 0, 0, NULL); + } + ++ dht_unlock_namespace (frame, &local->lock[0]); ++ dht_unlock_namespace (frame, &local->lock[1]); ++ ++ dht_rename_unlock_cbk (frame, NULL, this, local->op_ret, ++ local->op_errno, NULL); + return 0; + } + +@@ -1470,6 +1477,8 @@ dht_rename_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + char gfid_local[GF_UUID_BUF_SIZE] = {0}; + char gfid_server[GF_UUID_BUF_SIZE] = {0}; + int child_index = -1; ++ gf_boolean_t is_src = _gf_false; ++ loc_t *loc = NULL; + + + child_index = (long)cookie; +@@ -1477,22 +1486,98 @@ dht_rename_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + local = frame->local; + conf = this->private; + ++ is_src = (child_index == 0); ++ if (is_src) ++ loc = &local->loc; ++ else ++ loc = &local->loc2; ++ ++ if (op_ret >= 0) { ++ if (is_src) ++ local->src_cached ++ = dht_subvol_get_cached (this, ++ local->loc.inode); ++ else { ++ if (loc->inode) ++ gf_uuid_unparse (loc->inode->gfid, gfid_local); ++ ++ gf_msg_debug (this->name, 0, ++ "dst_cached before lookup: %s, " ++ "(path:%s)(gfid:%s),", ++ local->loc2.path, ++ local->dst_cached ++ ? local->dst_cached->name : ++ NULL, ++ local->dst_cached ? gfid_local : NULL); ++ ++ local->dst_cached ++ = dht_subvol_get_cached (this, ++ local->loc2_copy.inode); ++ ++ gf_uuid_unparse (stbuf->ia_gfid, gfid_local); ++ ++ gf_msg_debug (this->name, GF_LOG_WARNING, ++ "dst_cached after lookup: %s, " ++ "(path:%s)(gfid:%s)", ++ local->loc2.path, ++ local->dst_cached ++ ? local->dst_cached->name : ++ NULL, ++ local->dst_cached ? gfid_local : NULL); ++ ++ ++ if ((local->loc2.inode == NULL) ++ || gf_uuid_compare (stbuf->ia_gfid, ++ local->loc2.inode->gfid)) { ++ if (local->loc2.inode != NULL) { ++ inode_unlink (local->loc2.inode, ++ local->loc2.parent, ++ local->loc2.name); ++ inode_unref (local->loc2.inode); ++ } ++ ++ local->loc2.inode ++ = inode_link (local->loc2_copy.inode, ++ local->loc2_copy.parent, ++ local->loc2_copy.name, ++ stbuf); ++ gf_uuid_copy (local->loc2.gfid, ++ stbuf->ia_gfid); ++ } ++ } ++ } ++ + if (op_ret < 0) { +- /* The meaning of is_linkfile is overloaded here. For locking +- * to work properly both rebalance and rename should acquire +- * lock on datafile. The reason for sending this lookup is to +- * find out whether we've acquired a lock on data file. +- * Between the lookup before rename and this rename, the +- * file could be migrated by a rebalance process and now this +- * file this might be a linkto file. We verify that by sending +- * this lookup. However, if this lookup fails we cannot really +- * say whether we've acquired lock on a datafile or linkto file. +- * So, we act conservatively and _assume_ +- * that this is a linkfile and fail the rename operation. +- */ +- local->is_linkfile = _gf_true; +- local->op_errno = op_errno; +- } else if (xattr && check_is_linkfile (inode, stbuf, xattr, ++ if (is_src) { ++ /* The meaning of is_linkfile is overloaded here. For locking ++ * to work properly both rebalance and rename should acquire ++ * lock on datafile. The reason for sending this lookup is to ++ * find out whether we've acquired a lock on data file. ++ * Between the lookup before rename and this rename, the ++ * file could be migrated by a rebalance process and now this ++ * file this might be a linkto file. We verify that by sending ++ * this lookup. However, if this lookup fails we cannot really ++ * say whether we've acquired lock on a datafile or linkto file. ++ * So, we act conservatively and _assume_ ++ * that this is a linkfile and fail the rename operation. ++ */ ++ local->is_linkfile = _gf_true; ++ local->op_errno = op_errno; ++ } else { ++ if (local->dst_cached) ++ gf_msg_debug (this->name, op_errno, ++ "file %s (gfid:%s) was present " ++ "(hashed-subvol=%s, " ++ "cached-subvol=%s) before rename," ++ " but lookup failed", ++ local->loc2.path, ++ uuid_utoa (local->loc2.inode->gfid), ++ local->dst_hashed->name, ++ local->dst_cached->name); ++ if (dht_inode_missing (op_errno)) ++ local->dst_cached = NULL; ++ } ++ } else if (is_src && xattr && check_is_linkfile (inode, stbuf, xattr, + conf->link_xattr_name)) { + local->is_linkfile = _gf_true; + /* Found linkto file instead of data file, passdown ENOENT +@@ -1500,11 +1585,9 @@ dht_rename_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + local->op_errno = ENOENT; + } + +- if (!local->is_linkfile && +- gf_uuid_compare (local->lock[0].layout.parent_layout.locks[child_index]->loc.gfid, +- stbuf->ia_gfid)) { +- gf_uuid_unparse (local->lock[0].layout.parent_layout.locks[child_index]->loc.gfid, +- gfid_local); ++ if (!local->is_linkfile && (op_ret >= 0) && ++ gf_uuid_compare (loc->gfid, stbuf->ia_gfid)) { ++ gf_uuid_unparse (loc->gfid, gfid_local); + gf_uuid_unparse (stbuf->ia_gfid, gfid_server); + + gf_msg (this->name, GF_LOG_WARNING, 0, +@@ -1537,6 +1620,123 @@ fail: + return 0; + } + ++int ++dht_rename_file_lock1_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ++ int32_t op_ret, int32_t op_errno, dict_t *xdata) ++{ ++ dht_local_t *local = NULL; ++ char src_gfid[GF_UUID_BUF_SIZE] = {0}; ++ char dst_gfid[GF_UUID_BUF_SIZE] = {0}; ++ int ret = 0; ++ loc_t *loc = NULL; ++ xlator_t *subvol = NULL; ++ ++ local = frame->local; ++ ++ if (op_ret < 0) { ++ uuid_utoa_r (local->loc.inode->gfid, src_gfid); ++ ++ if (local->loc2.inode) ++ uuid_utoa_r (local->loc2.inode->gfid, dst_gfid); ++ ++ gf_msg (this->name, GF_LOG_WARNING, op_errno, ++ DHT_MSG_INODE_LK_ERROR, ++ "protecting namespace of %s failed" ++ "rename (%s:%s:%s %s:%s:%s)", ++ local->current == &local->lock[0] ? local->loc.path ++ : local->loc2.path, ++ local->loc.path, src_gfid, local->src_hashed->name, ++ local->loc2.path, dst_gfid, ++ local->dst_hashed ? local->dst_hashed->name : NULL); ++ ++ local->op_ret = -1; ++ local->op_errno = op_errno; ++ goto err; ++ } ++ ++ if (local->current == &local->lock[0]) { ++ loc = &local->loc2; ++ subvol = local->dst_hashed; ++ local->current = &local->lock[1]; ++ } else { ++ loc = &local->loc; ++ subvol = local->src_hashed; ++ local->current = &local->lock[0]; ++ } ++ ++ ret = dht_protect_namespace (frame, loc, subvol, &local->current->ns, ++ dht_rename_lock_cbk); ++ if (ret < 0) { ++ op_errno = EINVAL; ++ goto err; ++ } ++ ++ return 0; ++err: ++ /* No harm in calling an extra unlock */ ++ dht_rename_unlock (frame, this); ++ return 0; ++} ++ ++int32_t ++dht_rename_file_protect_namespace (call_frame_t *frame, void *cookie, ++ xlator_t *this, int32_t op_ret, ++ int32_t op_errno, dict_t *xdata) ++{ ++ dht_local_t *local = NULL; ++ char src_gfid[GF_UUID_BUF_SIZE] = {0}; ++ char dst_gfid[GF_UUID_BUF_SIZE] = {0}; ++ int ret = 0; ++ loc_t *loc = NULL; ++ xlator_t *subvol = NULL; ++ ++ local = frame->local; ++ ++ if (op_ret < 0) { ++ uuid_utoa_r (local->loc.inode->gfid, src_gfid); ++ ++ if (local->loc2.inode) ++ uuid_utoa_r (local->loc2.inode->gfid, dst_gfid); ++ ++ gf_msg (this->name, GF_LOG_WARNING, op_errno, ++ DHT_MSG_INODE_LK_ERROR, ++ "acquiring inodelk failed " ++ "rename (%s:%s:%s %s:%s:%s)", ++ local->loc.path, src_gfid, local->src_cached->name, ++ local->loc2.path, dst_gfid, ++ local->dst_cached ? local->dst_cached->name : NULL); ++ ++ local->op_ret = -1; ++ local->op_errno = op_errno; ++ ++ goto err; ++ } ++ ++ /* Locks on src and dst needs to ordered which otherwise might cause ++ * deadlocks when rename (src, dst) and rename (dst, src) is done from ++ * two different clients ++ */ ++ dht_order_rename_lock (frame, &loc, &subvol); ++ ++ ret = dht_protect_namespace (frame, loc, subvol, ++ &local->current->ns, ++ dht_rename_file_lock1_cbk); ++ if (ret < 0) { ++ op_errno = EINVAL; ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ /* Its fine to call unlock even when no locks are acquired, as we check ++ * for lock->locked before winding a unlock call. ++ */ ++ dht_rename_unlock (frame, this); ++ ++ return 0; ++} ++ + int32_t + dht_rename_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +@@ -1547,8 +1747,8 @@ dht_rename_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + dict_t *xattr_req = NULL; + dht_conf_t *conf = NULL; + int i = 0; +- int count = 0; +- ++ xlator_t *subvol = NULL; ++ dht_lock_t *lock = NULL; + + local = frame->local; + conf = this->private; +@@ -1561,11 +1761,13 @@ dht_rename_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + + gf_msg (this->name, GF_LOG_WARNING, op_errno, + DHT_MSG_INODE_LK_ERROR, +- "acquiring inodelk failed " ++ "protecting namespace of %s failed. " + "rename (%s:%s:%s %s:%s:%s)", +- local->loc.path, src_gfid, local->src_cached->name, ++ local->current == &local->lock[0] ? local->loc.path ++ : local->loc2.path, ++ local->loc.path, src_gfid, local->src_hashed->name, + local->loc2.path, dst_gfid, +- local->dst_cached ? local->dst_cached->name : NULL); ++ local->dst_hashed ? local->dst_hashed->name : NULL); + + local->op_ret = -1; + local->op_errno = op_errno; +@@ -1588,7 +1790,19 @@ dht_rename_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + goto done; + } + +- count = local->call_cnt = local->lock[0].layout.parent_layout.lk_count; ++ /* dst_cached might've changed. This normally happens for two reasons: ++ * 1. rebalance migrated dst ++ * 2. Another parallel rename was done overwriting dst ++ * ++ * Doing a lookup on local->loc2 when dst exists, but is associated ++ * with a different gfid will result in an ESTALE error. So, do a fresh ++ * lookup with a new inode on dst-path and handle change of dst-cached ++ * in the cbk. Also, to identify dst-cached changes we do a lookup on ++ * "this" rather than the subvol. ++ */ ++ loc_copy (&local->loc2_copy, &local->loc2); ++ inode_unref (local->loc2_copy.inode); ++ local->loc2_copy.inode = inode_new (local->loc.inode->table); + + /* Why not use local->lock.locks[?].loc for lookup post lock phase + * --------------------------------------------------------------- +@@ -1608,13 +1822,26 @@ dht_rename_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + * exists with the name that the client requested with. + * */ + +- for (i = 0; i < count; i++) { +- STACK_WIND_COOKIE (frame, dht_rename_lookup_cbk, (void *)(long)i, +- local->lock[0].layout.parent_layout.locks[i]->xl, +- local->lock[0].layout.parent_layout.locks[i]->xl->fops->lookup, +- ((gf_uuid_compare (local->loc.gfid, \ +- local->lock[0].layout.parent_layout.locks[i]->loc.gfid) == 0) ? +- &local->loc : &local->loc2), xattr_req); ++ local->call_cnt = 2; ++ for (i = 0; i < 2; i++) { ++ if (i == 0) { ++ lock = local->rename_inodelk_backward_compatible[0]; ++ if (gf_uuid_compare (local->loc.gfid, ++ lock->loc.gfid) == 0) ++ subvol = lock->xl; ++ else { ++ lock = local->rename_inodelk_backward_compatible[1]; ++ subvol = lock->xl; ++ } ++ } else { ++ subvol = this; ++ } ++ ++ STACK_WIND_COOKIE (frame, dht_rename_lookup_cbk, ++ (void *)(long)i, subvol, ++ subvol->fops->lookup, ++ (i == 0) ? &local->loc : &local->loc2_copy, ++ xattr_req); + } + + dict_unref (xattr_req); +@@ -1644,7 +1871,8 @@ dht_rename_lock (call_frame_t *frame) + if (local->dst_cached) + count++; + +- lk_array = GF_CALLOC (count, sizeof (*lk_array), gf_common_mt_pointer); ++ lk_array = GF_CALLOC (count, sizeof (*lk_array), ++ gf_common_mt_pointer); + if (lk_array == NULL) + goto err; + +@@ -1655,22 +1883,40 @@ dht_rename_lock (call_frame_t *frame) + goto err; + + if (local->dst_cached) { ++ /* dst might be removed by the time inodelk reaches bricks, ++ * which can result in ESTALE errors. POSIX imposes no ++ * restriction for dst to be present for renames to be ++ * successful. So, we'll ignore ESTALE errors. As far as ++ * synchronization on dst goes, we'll achieve the same by ++ * holding entrylk on parent directory of dst in the namespace ++ * of basename(dst). Also, there might not be quorum in cluster ++ * xlators like EC/disperse on errno, in which case they return ++ * EIO. For eg., in a disperse (4 + 2), 3 might return success ++ * and three might return ESTALE. Disperse, having no Quorum ++ * unwinds inodelk with EIO. So, ignore EIO too. ++ */ + lk_array[1] = dht_lock_new (frame->this, local->dst_cached, + &local->loc2, F_WRLCK, + DHT_FILE_MIGRATE_DOMAIN, NULL, +- FAIL_ON_ANY_ERROR); ++ IGNORE_ENOENT_ESTALE_EIO); + if (lk_array[1] == NULL) + goto err; + } + +- local->lock[0].layout.parent_layout.locks = lk_array; +- local->lock[0].layout.parent_layout.lk_count = count; ++ local->rename_inodelk_backward_compatible = lk_array; ++ local->rename_inodelk_bc_count = count; + ++ /* retaining inodelks for the sake of backward compatibility. Please ++ * make sure to remove this inodelk once all of 3.10, 3.12 and 3.13 ++ * reach EOL. Better way of getting synchronization would be to acquire ++ * entrylks on src and dst parent directories in the namespace of ++ * basenames of src and dst ++ */ + ret = dht_blocking_inodelk (frame, lk_array, count, +- dht_rename_lock_cbk); ++ dht_rename_file_protect_namespace); + if (ret < 0) { +- local->lock[0].layout.parent_layout.locks = NULL; +- local->lock[0].layout.parent_layout.lk_count = 0; ++ local->rename_inodelk_backward_compatible = NULL; ++ local->rename_inodelk_bc_count = 0; + goto err; + } + +@@ -1701,6 +1947,7 @@ dht_rename (call_frame_t *frame, xlator_t *this, + dht_local_t *local = NULL; + dht_conf_t *conf = NULL; + char gfid[GF_UUID_BUF_SIZE] = {0}; ++ char newgfid[GF_UUID_BUF_SIZE] = {0}; + + VALIDATE_OR_GOTO (frame, err); + VALIDATE_OR_GOTO (this, err); +@@ -1772,11 +2019,15 @@ dht_rename (call_frame_t *frame, xlator_t *this, + if (xdata) + local->xattr_req = dict_ref (xdata); + ++ if (newloc->inode) ++ gf_uuid_unparse(newloc->inode->gfid, newgfid); ++ + gf_msg (this->name, GF_LOG_INFO, 0, + DHT_MSG_RENAME_INFO, +- "renaming %s (hash=%s/cache=%s) => %s (hash=%s/cache=%s)", +- oldloc->path, src_hashed->name, src_cached->name, +- newloc->path, dst_hashed->name, ++ "renaming %s (%s) (hash=%s/cache=%s) => %s (%s) " ++ "(hash=%s/cache=%s) ", ++ oldloc->path, gfid, src_hashed->name, src_cached->name, ++ newloc->path, newloc->inode ? newgfid : NULL, dst_hashed->name, + dst_cached ? dst_cached->name : ""); + + if (IA_ISDIR (oldloc->inode->ia_type)) { +@@ -1784,8 +2035,10 @@ dht_rename (call_frame_t *frame, xlator_t *this, + } else { + local->op_ret = 0; + ret = dht_rename_lock (frame); +- if (ret < 0) ++ if (ret < 0) { ++ op_errno = ENOMEM; + goto err; ++ } + } + + return 0; +-- +1.8.3.1 + diff --git a/0265-Glusterfsd-brick-crash-during-get-state.patch b/0265-Glusterfsd-brick-crash-during-get-state.patch new file mode 100644 index 0000000..46d4882 --- /dev/null +++ b/0265-Glusterfsd-brick-crash-during-get-state.patch @@ -0,0 +1,47 @@ +From 9efbf3a9fb009706ca71068449a961ee0237a705 Mon Sep 17 00:00:00 2001 +From: hari gowtham +Date: Tue, 8 May 2018 11:42:33 +0530 +Subject: [PATCH 265/271] Glusterfsd: brick crash during get-state + + back-port of: https://review.gluster.org/#/c/19977/ + +The xprt's dereferencing wasn't checked before using it for the +strcmp, which caused the segfault and crashed the brick process. + +fix: Check every deferenced variable before using it. + +>Change-Id: I7f705d1c88a124e8219bb877156fadb17ecf11c3 +>fixes: bz#1575864 +>Signed-off-by: hari gowtham + +Change-Id: I7f705d1c88a124e8219bb877156fadb17ecf11c3 +BUG: 1572075 +Signed-off-by: hari gowtham +Reviewed-on: https://code.engineering.redhat.com/gerrit/138650 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + xlators/protocol/server/src/server.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c +index 6f20a06..2ba5da3 100644 +--- a/xlators/protocol/server/src/server.c ++++ b/xlators/protocol/server/src/server.c +@@ -245,8 +245,11 @@ server_priv_to_dict (xlator_t *this, dict_t *dict, char *brickname) + pthread_mutex_lock (&conf->mutex); + { + list_for_each_entry (xprt, &conf->xprt_list, list) { +- if (!strcmp (brickname, +- xprt->xl_private->bound_xl->name)) { ++ if ((xprt) && (xprt->xl_private) && ++ (xprt->xl_private->bound_xl) && ++ (xprt->xl_private->bound_xl->name) && (brickname) && ++ (!strcmp (brickname, ++ xprt->xl_private->bound_xl->name))) { + peerinfo = &xprt->peerinfo; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), +-- +1.8.3.1 + diff --git a/0266-glusterd-geo-rep-Fix-glusterd-crash.patch b/0266-glusterd-geo-rep-Fix-glusterd-crash.patch new file mode 100644 index 0000000..5442eae --- /dev/null +++ b/0266-glusterd-geo-rep-Fix-glusterd-crash.patch @@ -0,0 +1,42 @@ +From 7a2bf65414368999295993cdbbee4060ca495951 Mon Sep 17 00:00:00 2001 +From: Kotresh HR +Date: Mon, 7 May 2018 06:35:25 -0400 +Subject: [PATCH 266/271] glusterd/geo-rep: Fix glusterd crash + +Using strdump instead of gf_strdup crashes +during free if mempool is being used. +gf_free checks the magic number in the +header which will not be taken care if +strdup is used. + +Uptream reference: + > fixes: bz#1576392 + > Change-Id: Iab36496554b838a036af9d863e3f5fd07fd9780e + > Patch: https://review.gluster.org/19993 + +BUG: 1570586 +Change-Id: Iab36496554b838a036af9d863e3f5fd07fd9780e +Signed-off-by: Kotresh HR +Reviewed-on: https://code.engineering.redhat.com/gerrit/138670 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + xlators/mgmt/glusterd/src/glusterd-geo-rep.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +index dff8065..a1251ae 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c ++++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +@@ -5637,7 +5637,7 @@ glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict) + GD_MSG_GSYNCD_OP_SET_FAILED, GEOREP" is not " + "set up for %s(master) and %s(slave)", + volname, slave); +- *op_errstr = strdup (GEOREP" is not set up"); ++ *op_errstr = gf_strdup (GEOREP" is not set up"); + goto out; + } + +-- +1.8.3.1 + diff --git a/0267-geo-rep-scheduler-Fix-crash.patch b/0267-geo-rep-scheduler-Fix-crash.patch new file mode 100644 index 0000000..1f8c76b --- /dev/null +++ b/0267-geo-rep-scheduler-Fix-crash.patch @@ -0,0 +1,127 @@ +From daab3274ba03f4df0160374fa9fb5993847f3153 Mon Sep 17 00:00:00 2001 +From: Kotresh HR +Date: Wed, 9 May 2018 01:10:29 -0400 +Subject: [PATCH 267/271] geo-rep/scheduler: Fix crash + +Fix crash where session_name is referenced +before assignment. Well, this is a corner +case where the geo-rep session exists and +the status output doesn't show any rows. +This might happen when glusterd is down +or when the system is in inconsistent state +w.r.t glusterd. + +Upstream reference: + > fixes: bz#1576179 + > Change-Id: Iec1557e01b35068041b4b3c1aacee2bfa0e05873 + > Patch: https://review.gluster.org/19991 + +BUG: 1575877 +Change-Id: Iec1557e01b35068041b4b3c1aacee2bfa0e05873 +Signed-off-by: Kotresh HR +Reviewed-on: https://code.engineering.redhat.com/gerrit/138668 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + extras/geo-rep/schedule_georep.py.in | 70 ++++++++++++++++++------------------ + 1 file changed, 35 insertions(+), 35 deletions(-) + +diff --git a/extras/geo-rep/schedule_georep.py.in b/extras/geo-rep/schedule_georep.py.in +index 1887fe7..4e1a071 100644 +--- a/extras/geo-rep/schedule_georep.py.in ++++ b/extras/geo-rep/schedule_georep.py.in +@@ -297,6 +297,7 @@ def get_summary(mastervol, slave_url): + status_data = get(mastervol, slave_url) + + for session in status_data: ++ session_name = "" + summary = { + "active": 0, + "passive": 0, +@@ -339,7 +340,8 @@ def get_summary(mastervol, slave_url): + if summary["faulty"] == 0 and summary["offline"] == 0: + summary["ok"] = True + +- out.append([session_name, summary, faulty_rows, down_rows]) ++ if session_name != "": ++ out.append([session_name, summary, faulty_rows, down_rows]) + + return out + +@@ -397,41 +399,39 @@ def main(args): + # or any other error. Gluster cmd still produces XML output + # with different message + output_warning("Unable to get Geo-replication Status") +- time.sleep(1) +- continue +- +- session_name, summary, faulty_rows, down_rows = session_summary[0] +- chkpt_status = "COMPLETE" if summary["checkpoints_ok"] else \ +- "NOT COMPLETE" +- ok_status = "OK" if summary["ok"] else "NOT OK" +- +- if summary["ok"]: +- output_ok("All Checkpoints {1}, " +- "All status {2} (Turns {0:>3})".format( +- turns, chkpt_status, ok_status)) + else: +- output_warning("All Checkpoints {1}, " +- "All status {2} (Turns {0:>3})".format( +- turns, chkpt_status, ok_status)) +- +- output_warning("Geo-rep workers Faulty/Offline, " +- "Faulty: {0} Offline: {1}".format( +- repr(faulty_rows), +- repr(down_rows))) +- +- if summary["checkpoints_ok"]: +- output_ok("Stopping Geo-replication session now") +- cmd = ["@SBIN_DIR@/gluster", "volume", "geo-replication", +- args.mastervol, +- "%s::%s" % (args.slave, args.slavevol), "stop"] +- execute(cmd) +- break +- else: +- # If Checkpoint is not complete after a iteration means brick +- # was down and came online now. SETATTR on mount is not +- # recorded, So again issue touch on mount root So that +- # Stime will increase and Checkpoint will complete. +- touch_mount_root(args.mastervol) ++ session_name, summary, faulty_rows, down_rows = session_summary[0] ++ chkpt_status = "COMPLETE" if summary["checkpoints_ok"] else \ ++ "NOT COMPLETE" ++ ok_status = "OK" if summary["ok"] else "NOT OK" ++ ++ if summary["ok"]: ++ output_ok("All Checkpoints {1}, " ++ "All status {2} (Turns {0:>3})".format( ++ turns, chkpt_status, ok_status)) ++ else: ++ output_warning("All Checkpoints {1}, " ++ "All status {2} (Turns {0:>3})".format( ++ turns, chkpt_status, ok_status)) ++ ++ output_warning("Geo-rep workers Faulty/Offline, " ++ "Faulty: {0} Offline: {1}".format( ++ repr(faulty_rows), ++ repr(down_rows))) ++ ++ if summary["checkpoints_ok"]: ++ output_ok("Stopping Geo-replication session now") ++ cmd = ["@SBIN_DIR@/gluster", "volume", "geo-replication", ++ args.mastervol, ++ "%s::%s" % (args.slave, args.slavevol), "stop"] ++ execute(cmd) ++ break ++ else: ++ # If Checkpoint is not complete after a iteration means brick ++ # was down and came online now. SETATTR on mount is not ++ # recorded, So again issue touch on mount root So that ++ # Stime will increase and Checkpoint will complete. ++ touch_mount_root(args.mastervol) + + # Increment the turns and Sleep for 10 sec + turns += 1 +-- +1.8.3.1 + diff --git a/0268-dht-Excessive-dict-is-null-logs-in-dht_discover_comp.patch b/0268-dht-Excessive-dict-is-null-logs-in-dht_discover_comp.patch new file mode 100644 index 0000000..a7dccea --- /dev/null +++ b/0268-dht-Excessive-dict-is-null-logs-in-dht_discover_comp.patch @@ -0,0 +1,44 @@ +From 717fab7db9afb3d2f512fcdb7a952eb57b67e8dd Mon Sep 17 00:00:00 2001 +From: Mohit Agrawal +Date: Thu, 10 May 2018 16:54:44 +0530 +Subject: [PATCH 268/271] dht: Excessive 'dict is null' logs in + dht_discover_complete + +Problem: In Geo-Rep setup excessive "dict is null" logs in + dht_discover_complete while xattr is NULL + +Solution: To avoid the logs update a condition in dht_discover_complete + +> BUG: 1576767 +> Change-Id: Ic7aad712d9b6d69b85b76e4fdf2881adb0512237 +> fixes: bz#1576767 +> (cherry pick from commit 08dcb1c2bf02bba313d3bfc8fbc1c8ea63296321) +> (Upstream review link https://review.gluster.org/#/c/20001/) + +BUG: 1565577 +Change-Id: I1b1327eeef05fa261c814069a3bdd75653b37bd1 +Signed-off-by: Mohit Agrawal +Reviewed-on: https://code.engineering.redhat.com/gerrit/138490 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + xlators/cluster/dht/src/dht-common.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c +index ec1628a..feeaa3f 100644 +--- a/xlators/cluster/dht/src/dht-common.c ++++ b/xlators/cluster/dht/src/dht-common.c +@@ -748,7 +748,8 @@ cleanup: + done: + dht_set_fixed_dir_stat (&local->postparent); + /* Delete mds xattr at the time of STACK UNWIND */ +- GF_REMOVE_INTERNAL_XATTR (conf->mds_xattr_key, local->xattr); ++ if (local->xattr) ++ GF_REMOVE_INTERNAL_XATTR (conf->mds_xattr_key, local->xattr); + + DHT_STACK_UNWIND (lookup, main_frame, local->op_ret, local->op_errno, + local->inode, &local->stbuf, local->xattr, +-- +1.8.3.1 + diff --git a/0269-extras-Disable-choose-local-in-groups-virt-and-glust.patch b/0269-extras-Disable-choose-local-in-groups-virt-and-glust.patch new file mode 100644 index 0000000..c030969 --- /dev/null +++ b/0269-extras-Disable-choose-local-in-groups-virt-and-glust.patch @@ -0,0 +1,42 @@ +From 79b42b350da05615422443aa34b5af1909786ee5 Mon Sep 17 00:00:00 2001 +From: Krutika Dhananjay +Date: Thu, 12 Apr 2018 13:41:29 +0530 +Subject: [PATCH 269/271] extras: Disable choose-local in groups virt and + gluster-block + +> Upstream: https://review.gluster.org/19855 +> BUG: 1566386 +> Change-Id: Icba68406d86623195d59d6ee668e0850c037c63a + +Change-Id: If5575abf3c737fbfc7454d008b945530ed9b7bb3 +BUG: 1568297 +Signed-off-by: Krutika Dhananjay +Reviewed-on: https://code.engineering.redhat.com/gerrit/135960 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + extras/group-gluster-block | 1 + + extras/group-virt.example | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/extras/group-gluster-block b/extras/group-gluster-block +index e94f834..d619255 100644 +--- a/extras/group-gluster-block ++++ b/extras/group-gluster-block +@@ -16,3 +16,4 @@ features.shard=on + features.shard-block-size=64MB + user.cifs=off + server.allow-insecure=on ++cluster.choose-local=off +diff --git a/extras/group-virt.example b/extras/group-virt.example +index 403bed6..7e34b72 100644 +--- a/extras/group-virt.example ++++ b/extras/group-virt.example +@@ -12,3 +12,4 @@ cluster.shd-max-threads=8 + cluster.shd-wait-qlength=10000 + features.shard=on + user.cifs=off ++cluster.choose-local=off +-- +1.8.3.1 + diff --git a/0270-glusterfs-Resolve-brick-crashes-at-the-time-of-inode.patch b/0270-glusterfs-Resolve-brick-crashes-at-the-time-of-inode.patch new file mode 100644 index 0000000..3078a98 --- /dev/null +++ b/0270-glusterfs-Resolve-brick-crashes-at-the-time-of-inode.patch @@ -0,0 +1,91 @@ +From aad829320132fb2399e8fd8edfa573561a7c03e1 Mon Sep 17 00:00:00 2001 +From: Mohit Agrawal +Date: Sun, 13 May 2018 12:01:01 +0530 +Subject: [PATCH 270/271] glusterfs: Resolve brick crashes at the time of + inode_unref + +Problem: Sometimes brick process is getting crash at the time + of calling inode_unref in fd_destroy + +Solution: Brick process is getting crash because inode is already + free by xlator_mem_cleanup call by server_rpc_notify.To + resolve the same move code specific to call transport_unref + in last in free_state. + +> BUG: 1577574 +> Change-Id: Ia517c230d68af4e929b6b753e4c374a26c39dc1a +> fixes: bz#1577574 +> (cherry picked from commit 8e2289b1e76ac777b71897dc709d9651341bd241) +> (Upstream link for review https://review.gluster.org/#/c/20014/) + +BUG: 1575840 +Change-Id: I62df8dd6f4df545250a977897697c960adba1c4c +Signed-off-by: Mohit Agrawal +Reviewed-on: https://code.engineering.redhat.com/gerrit/138797 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + xlators/protocol/server/src/server-helpers.c | 15 +++++++++++---- + xlators/protocol/server/src/server.c | 6 +++--- + 2 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c +index c8f5382..c492ab1 100644 +--- a/xlators/protocol/server/src/server-helpers.c ++++ b/xlators/protocol/server/src/server-helpers.c +@@ -177,10 +177,6 @@ server_resolve_wipe (server_resolve_t *resolve) + void + free_state (server_state_t *state) + { +- if (state->xprt) { +- rpc_transport_unref (state->xprt); +- state->xprt = NULL; +- } + if (state->fd) { + fd_unref (state->fd); + state->fd = NULL; +@@ -223,6 +219,17 @@ free_state (server_state_t *state) + + compound_args_cleanup (state->args); + ++ /* Call rpc_trnasport_unref to avoid crashes at last after free ++ all resources because of server_rpc_notify (for transport destroy) ++ call's xlator_mem_cleanup if all xprt are destroyed that internally ++ call's inode_table_destroy. ++ */ ++ if (state->xprt) { ++ rpc_transport_unref (state->xprt); ++ state->xprt = NULL; ++ } ++ ++ + GF_FREE (state); + } + +diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c +index 2ba5da3..d40457c 100644 +--- a/xlators/protocol/server/src/server.c ++++ b/xlators/protocol/server/src/server.c +@@ -208,9 +208,6 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, + + ret = 0; + ret: +- if (state) +- free_state (state); +- + if (client) + gf_client_unref (client); + +@@ -220,6 +217,9 @@ ret: + if (new_iobref) + iobref_unref (iobref); + ++ if (state) ++ free_state (state); ++ + return ret; + } + +-- +1.8.3.1 + diff --git a/0271-cli-Fix-for-gluster-volume-info-xml.patch b/0271-cli-Fix-for-gluster-volume-info-xml.patch new file mode 100644 index 0000000..d496b29 --- /dev/null +++ b/0271-cli-Fix-for-gluster-volume-info-xml.patch @@ -0,0 +1,52 @@ +From 261a0b3feb520f7992dc026856b4b200670900ab Mon Sep 17 00:00:00 2001 +From: Sanju Rakonde +Date: Sun, 13 May 2018 21:03:12 +0530 +Subject: [PATCH 271/271] cli: Fix for gluster volume info --xml + +Problem: gluster volume info --xml is showing same uuid to all +the bricks of a tier volume. + +Solution: While iterating over hot/cold bricks of a tier volume, use +correct iterator. + +>Fixes: bz#1577627 +>Change-Id: Icf6a9c2a10b9da453abc262a57b7884d6638e3ed +>Signed-off-by: Sanju Rakonde + +upstream patch: https://review.gluster.org/#/c/20015/ + +BUG: 1572043 +Change-Id: Icf6a9c2a10b9da453abc262a57b7884d6638e3ed +Signed-off-by: Sanju Rakonde +Reviewed-on: https://code.engineering.redhat.com/gerrit/138786 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + cli/src/cli-xml-output.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c +index 29ee81b..a709ed5 100644 +--- a/cli/src/cli-xml-output.c ++++ b/cli/src/cli-xml-output.c +@@ -2942,7 +2942,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), +- "volume%d.brick%d.uuid", i, j); ++ "volume%d.brick%d.uuid", i, index); + ret = dict_get_str (dict, key, &uuid); + if (ret) + goto out; +@@ -3053,7 +3053,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), +- "volume%d.brick%d.uuid", i, j); ++ "volume%d.brick%d.uuid", i, index); + ret = dict_get_str (dict, key, &uuid); + if (ret) + goto out; +-- +1.8.3.1 + diff --git a/glusterfs.spec b/glusterfs.spec index 4359966..966ae4c 100644 --- a/glusterfs.spec +++ b/glusterfs.spec @@ -192,7 +192,7 @@ Release: 0.1%{?prereltag:.%{prereltag}}%{?dist} %else Name: glusterfs Version: 3.12.2 -Release: 9%{?dist} +Release: 10%{?dist} %endif License: GPLv2 or LGPLv3+ Group: System Environment/Base @@ -525,6 +525,17 @@ Patch0257: 0257-rpc-rearm-listener-socket-early.patch Patch0258: 0258-cluster-dht-log-error-only-if-layout-healing-is-requ.patch Patch0259: 0259-Quota-Turn-on-ssl-for-crawler-clients-if-needed.patch Patch0260: 0260-dht-Avoid-dict-log-flooding-for-internal-MDS-xattr.patch +Patch0261: 0261-libglusterfs-syncop-Add-syncop_entrylk.patch +Patch0262: 0262-cluster-dht-store-the-reaction-on-failures-per-lock.patch +Patch0263: 0263-server-resolver-don-t-trust-inode-table-for-RESOLVE_.patch +Patch0264: 0264-cluster-dht-fixes-to-parallel-renames-to-same-destin.patch +Patch0265: 0265-Glusterfsd-brick-crash-during-get-state.patch +Patch0266: 0266-glusterd-geo-rep-Fix-glusterd-crash.patch +Patch0267: 0267-geo-rep-scheduler-Fix-crash.patch +Patch0268: 0268-dht-Excessive-dict-is-null-logs-in-dht_discover_comp.patch +Patch0269: 0269-extras-Disable-choose-local-in-groups-virt-and-glust.patch +Patch0270: 0270-glusterfs-Resolve-brick-crashes-at-the-time-of-inode.patch +Patch0271: 0271-cli-Fix-for-gluster-volume-info-xml.patch %description GlusterFS is a distributed file-system capable of scaling to several @@ -2471,6 +2482,10 @@ fi %endif %changelog +* Tue May 15 2018 Milind Changire - 3.12.2-10 +- fixes bugs bz#1488120 bz#1565577 bz#1568297 bz#1570586 bz#1572043 + bz#1572075 bz#1575840 bz#1575877 + * Wed May 09 2018 Milind Changire - 3.12.2-9 - fixes bugs bz#1546717 bz#1557551 bz#1558948 bz#1561999 bz#1563804 bz#1565015 bz#1565119 bz#1565399 bz#1565577 bz#1567100 bz#1567899 bz#1568374