summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/afr/src/afr.h
diff options
context:
space:
mode:
authorPranith Kumar K <pkarampu@redhat.com>2013-07-03 21:28:25 +0530
committerVijay Bellur <vbellur@redhat.com>2013-07-03 21:35:30 -0700
commit0aa4248cf967b158c0cf6ce33c300ad4b3ee3249 (patch)
tree56a8e408e81bc35ef335fcc6428b8cd7b14a5210 /xlators/cluster/afr/src/afr.h
parentc2abf3a6e39c5a5832a165757483bc0ae23cdb63 (diff)
cluster/afr: Let two data-self-heals compete in new domain
Problem: At the moment data-self-heal acquires locks in following pattern. It takes full file lock then gets xattrs on files on both replicas. Decides sources/sinks based on the xattrs. Now it acquires lock from 0-128k then unlocks the full file lock. Syncs 0-128k range from source to sink now acquires lock 128k+1 till 256k then unlocks 0-128k, syncs 128k+1 till 256k block... so on finally it takes full file lock again then unlocks the final small range block. It decrements pending counts and then unlocks the full file lock. This pattern of locks is chosen to avoid more than 1 self-heal to be in progress. BUT if another self-heal tries to take a full file lock while a self-heal is already in progress it will be put in blocked queue, further inodelks from writes by the application will also be put in blocked queue because of the way locks xlator grants inodelks. So until the self-heal is complete writes are blocked. Here is the code: xlators/features/locks/src/inodelk.c - line 225 if (__blocked_lock_conflict (dom, lock) && !(__owner_has_lock (dom, lock))) { ret = -EAGAIN; if (can_block == 0) goto out; gettimeofday (&lock->blkd_time, NULL); list_add_tail (&lock->blocked_locks, &dom->blocked_inodelks); } This leads to hangs in applications. Fix: Since we want to prevent two parallel self-heals. We let them compete in a separate "domain". Lets call the domain on which the locks have been taken on in previous approach as "data-domain". In the new approach When a self-heal is triggered, it acquires a full lock in the new domain "self-heal-domain". After this it performs data-self-heal using the locks in "data-domain" as before. unlock the full file lock in "self-heal-domain" With this approach, application's writevs don't have to wait in pending queue when more than 1 self-heal is triggered. Change-Id: Id79aef3dfa888945977fb9758374ac41c320d0d5 BUG: 967717 Signed-off-by: Pranith Kumar K <pkarampu@redhat.com> Reviewed-on: http://review.gluster.org/5100 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr.h')
-rw-r--r--xlators/cluster/afr/src/afr.h4
1 files changed, 3 insertions, 1 deletions
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
index 940f84189..bca5c0f79 100644
--- a/xlators/cluster/afr/src/afr.h
+++ b/xlators/cluster/afr/src/afr.h
@@ -30,7 +30,7 @@
#define AFR_SH_READDIR_SIZE_KEY "self-heal-readdir-size"
#define AFR_LOCKEE_COUNT_MAX 3
-#define AFR_DOM_COUNT_MAX 2
+#define AFR_DOM_COUNT_MAX 3
struct _pump_private;
@@ -172,6 +172,7 @@ typedef struct _afr_private {
gf_boolean_t readdir_failover;
uint64_t sh_readdir_size;
gf_boolean_t ensure_durability;
+ char *sh_domain;
} afr_private_t;
typedef enum {
@@ -280,6 +281,7 @@ struct afr_self_heal_ {
gf_boolean_t actual_sh_started;
gf_boolean_t sync_done;
gf_boolean_t data_lock_held;
+ gf_boolean_t sh_dom_lock_held;
gf_boolean_t eof_reached;
fd_t *healing_fd;
int file_has_holes;