From 032a3dbb5d4ea63ec6c2ceb39c067ea6424b5792 Mon Sep 17 00:00:00 2001 From: V3n3RiX Date: Mon, 20 Jan 2020 19:28:42 +0000 Subject: gentoo resync : 20.01.2020 --- .../files/glusterfs-6.7-fix-rebalance-crash.patch | 185 +++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 sys-cluster/glusterfs/files/glusterfs-6.7-fix-rebalance-crash.patch (limited to 'sys-cluster/glusterfs/files/glusterfs-6.7-fix-rebalance-crash.patch') diff --git a/sys-cluster/glusterfs/files/glusterfs-6.7-fix-rebalance-crash.patch b/sys-cluster/glusterfs/files/glusterfs-6.7-fix-rebalance-crash.patch new file mode 100644 index 000000000000..e5a31623a32f --- /dev/null +++ b/sys-cluster/glusterfs/files/glusterfs-6.7-fix-rebalance-crash.patch @@ -0,0 +1,185 @@ +From ff1eae7f882b8f12380e0c35a9a73b672583cd4c Mon Sep 17 00:00:00 2001 +From: N Balachandran +Date: Tue, 01 Oct 2019 17:37:15 +0530 +Subject: [PATCH] cluster/dht: Correct fd processing loop + +The fd processing loops in the +dht_migration_complete_check_task and the +dht_rebalance_inprogress_task functions were unsafe +and could cause an open to be sent on an already freed +fd. This has been fixed. + +> Change-Id: I0a3c7d2fba314089e03dfd704f9dceb134749540 +> Fixes: bz#1757399 +> Signed-off-by: N Balachandran +> (cherry picked from commit 9b15867070b0cc241ab165886292ecffc3bc0aed) + +Change-Id: I0a3c7d2fba314089e03dfd704f9dceb134749540 +Fixes: bz#1786983 +Signed-off-by: Mohit Agrawal +--- + +diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c +index acad493..4f7370d 100644 +--- a/xlators/cluster/dht/src/dht-helper.c ++++ b/xlators/cluster/dht/src/dht-helper.c +@@ -1290,6 +1290,7 @@ + fd_t *tmp = NULL; + uint64_t tmp_miginfo = 0; + dht_migrate_info_t *miginfo = NULL; ++ gf_boolean_t skip_open = _gf_false; + int open_failed = 0; + + this = THIS; +@@ -1428,24 +1429,34 @@ + * the loop will cause the destruction of the fd. So we need to + * iterate the list safely because iter_fd cannot be trusted. + */ +- list_for_each_entry_safe(iter_fd, tmp, &inode->fd_list, inode_list) +- { +- if (fd_is_anonymous(iter_fd)) +- continue; +- +- if (dht_fd_open_on_dst(this, iter_fd, dst_node)) +- continue; +- ++ iter_fd = list_entry((&inode->fd_list)->next, typeof(*iter_fd), inode_list); ++ while (&iter_fd->inode_list != (&inode->fd_list)) { ++ if (fd_is_anonymous(iter_fd) || ++ (dht_fd_open_on_dst(this, iter_fd, dst_node))) { ++ if (!tmp) { ++ iter_fd = list_entry(iter_fd->inode_list.next, typeof(*iter_fd), ++ inode_list); ++ continue; ++ } ++ skip_open = _gf_true; ++ } + /* We need to release the inode->lock before calling + * syncop_open() to avoid possible deadlocks. However this + * can cause the iter_fd to be released by other threads. + * To avoid this, we take a reference before releasing the + * lock. + */ +- __fd_ref(iter_fd); ++ fd_ref(iter_fd); + + UNLOCK(&inode->lock); + ++ if (tmp) { ++ fd_unref(tmp); ++ tmp = NULL; ++ } ++ if (skip_open) ++ goto next; ++ + /* flags for open are stripped down to allow following the + * new location of the file, otherwise we can get EEXIST or + * truncate the file again as rebalance is moving the data */ +@@ -1467,9 +1478,11 @@ + dht_fd_ctx_set(this, iter_fd, dst_node); + } + +- fd_unref(iter_fd); +- ++ next: + LOCK(&inode->lock); ++ skip_open = _gf_false; ++ tmp = iter_fd; ++ iter_fd = list_entry(tmp->inode_list.next, typeof(*tmp), inode_list); + } + + SYNCTASK_SETID(frame->root->uid, frame->root->gid); +@@ -1482,6 +1495,10 @@ + + unlock: + UNLOCK(&inode->lock); ++ if (tmp) { ++ fd_unref(tmp); ++ tmp = NULL; ++ } + + out: + if (dict) { +@@ -1563,6 +1580,7 @@ + int open_failed = 0; + uint64_t tmp_miginfo = 0; + dht_migrate_info_t *miginfo = NULL; ++ gf_boolean_t skip_open = _gf_false; + + this = THIS; + frame = data; +@@ -1683,24 +1701,40 @@ + * the loop will cause the destruction of the fd. So we need to + * iterate the list safely because iter_fd cannot be trusted. + */ +- list_for_each_entry_safe(iter_fd, tmp, &inode->fd_list, inode_list) +- { +- if (fd_is_anonymous(iter_fd)) +- continue; +- +- if (dht_fd_open_on_dst(this, iter_fd, dst_node)) +- continue; +- ++ iter_fd = list_entry((&inode->fd_list)->next, typeof(*iter_fd), inode_list); ++ while (&iter_fd->inode_list != (&inode->fd_list)) { + /* We need to release the inode->lock before calling + * syncop_open() to avoid possible deadlocks. However this + * can cause the iter_fd to be released by other threads. + * To avoid this, we take a reference before releasing the + * lock. + */ +- __fd_ref(iter_fd); + ++ if (fd_is_anonymous(iter_fd) || ++ (dht_fd_open_on_dst(this, iter_fd, dst_node))) { ++ if (!tmp) { ++ iter_fd = list_entry(iter_fd->inode_list.next, typeof(*iter_fd), ++ inode_list); ++ continue; ++ } ++ skip_open = _gf_true; ++ } ++ ++ /* Yes, this is ugly but there isn't a cleaner way to do this ++ * the fd_ref is an atomic increment so not too bad. We want to ++ * reduce the number of inode locks and unlocks. ++ */ ++ ++ fd_ref(iter_fd); + UNLOCK(&inode->lock); + ++ if (tmp) { ++ fd_unref(tmp); ++ tmp = NULL; ++ } ++ if (skip_open) ++ goto next; ++ + /* flags for open are stripped down to allow following the + * new location of the file, otherwise we can get EEXIST or + * truncate the file again as rebalance is moving the data */ +@@ -1721,9 +1755,11 @@ + dht_fd_ctx_set(this, iter_fd, dst_node); + } + +- fd_unref(iter_fd); +- ++ next: + LOCK(&inode->lock); ++ skip_open = _gf_false; ++ tmp = iter_fd; ++ iter_fd = list_entry(tmp->inode_list.next, typeof(*tmp), inode_list); + } + + SYNCTASK_SETID(frame->root->uid, frame->root->gid); +@@ -1731,6 +1767,10 @@ + unlock: + UNLOCK(&inode->lock); + ++ if (tmp) { ++ fd_unref(tmp); ++ tmp = NULL; ++ } + if (open_failed) { + ret = -1; + goto out; -- cgit v1.2.3