diff options
author | Ravishankar N <ravishankar@redhat.com> | 2017-03-21 11:02:32 +0530 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2017-03-28 18:34:48 -0400 |
commit | 0f98f5c8070904810252c6fc1df23747afa4b1d7 (patch) | |
tree | b670fd9a069a509e127c68725483a33ff85451f6 /libglusterfs | |
parent | df189a8644d7a805bb3e278f61983c5ba8619188 (diff) |
syncop: don't wake task in synctask_wake unless really needed
Problem:
In EC and AFR, we launch synctasks during self-heal.
(i) These tasks usually stackwind a FOP to all its children and call
synctask_yield() which does a swapcontext to synctask_switchto() and puts the
task in syncenv's waitq by calling __wait(task). This happends as long as the
FOP ckbs from all children haven't been received.
(ii) For each FOP cbk, we call synctask_wake() which again does a swapcontext
to synctask_switchto() which now puts the task in syncenv's runq by calling
__run(task). When the task runs and the conext switches back to the FOP path,
it puts the task in waitq because we haven't heard from all children as
explained in (i).
Thus we are unnecessarily using the swapcontext syscalls to just toggle
the task back and forth between the waitq and runq.
Fix:
Store the stackwind count in new variable 'syncbarrier->waitfor' before
winding the fop. In each cbk when we call synctask_wake(), perform an actual
wake only if the cbk count == stackwind count.
Change-Id: Id62d3b6ffed5a8c50f8b79267fb34e9470ba5ed5
BUG: 1434274
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Signed-off-by: Ashish Pandey <aspandey@redhat.com>
Reviewed-on: https://review.gluster.org/16931
Smoke: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Niels de Vos <ndevos@redhat.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r-- | libglusterfs/src/cluster-syncop.c | 7 | ||||
-rw-r--r-- | libglusterfs/src/syncop.c | 4 | ||||
-rw-r--r-- | libglusterfs/src/syncop.h | 2 |
3 files changed, 12 insertions, 1 deletions
diff --git a/libglusterfs/src/cluster-syncop.c b/libglusterfs/src/cluster-syncop.c index 98a46c85e4b..36945d69379 100644 --- a/libglusterfs/src/cluster-syncop.c +++ b/libglusterfs/src/cluster-syncop.c @@ -31,13 +31,18 @@ if (syncbarrier_init (&__local.barrier)) \ break; \ frame->local = &__local; \ + for (__i = 0; __i < numsubvols; __i++) { \ + if (on[__i]) { \ + __count++; \ + } \ + } \ + __local.barrier.waitfor = __count; \ for (__i = 0; __i < numsubvols; __i++) { \ if (!on[__i]) \ continue; \ STACK_WIND_COOKIE (frame, cluster_##fop##_cbk, \ (void *)(long) __i, subvols[__i], \ subvols[__i]->fops->fop, args); \ - __count++; \ } \ syncbarrier_wait (&__local.barrier, __count); \ syncbarrier_destroy (&__local.barrier); \ diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c index 3fa798a4342..246229f1cc2 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -1086,6 +1086,7 @@ syncbarrier_init (struct syncbarrier *barrier) pthread_cond_init (&barrier->cond, 0); barrier->count = 0; + barrier->waitfor = 0; INIT_LIST_HEAD (&barrier->waitq); return pthread_mutex_init (&barrier->guard, 0); @@ -1162,6 +1163,8 @@ __syncbarrier_wake (struct syncbarrier *barrier) } barrier->count++; + if (barrier->waitfor && (barrier->count < barrier->waitfor)) + return 0; pthread_cond_signal (&barrier->cond); if (!list_empty (&barrier->waitq)) { @@ -1169,6 +1172,7 @@ __syncbarrier_wake (struct syncbarrier *barrier) list_del_init (&task->waitq); synctask_wake (task); } + barrier->waitfor = 0; return 0; } diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index 0d0da58f4cf..a9cdee1fa00 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -138,6 +138,8 @@ struct syncbarrier { pthread_cond_t cond; /* waiting non-synctasks */ struct list_head waitq; /* waiting synctasks */ int count; /* count the number of wakes */ + int waitfor; /* no. of wakes until which task can be in + waitq before being woken up. */ }; typedef struct syncbarrier syncbarrier_t; |