diff options
| author | Soumya Koduri <skoduri@redhat.com> | 2020-04-06 12:36:44 +0530 | 
|---|---|---|
| committer | Kaleb KEITHLEY <kkeithle@redhat.com> | 2020-04-07 11:48:42 +0000 | 
| commit | 55914f968d907ed747774da15285b42653afda61 (patch) | |
| tree | 01ea01d1c6bd8456db49f4fe02c549284666e14a /api/src/glfs.c | |
| parent | e1ad1483e0e82d70fcc32311b7842bc9a77c04aa (diff) | |
gfapi: Suspend synctasks instead of blocking them
There are certain conditions which blocks the current
execution thread (like waiting on mutex lock or condition
variable or I/O response). In such cases, if it is a
synctask thread, we should suspend the task instead
of blocking it (like done in SYNCOP using synctask_yield)
This is to avoid deadlock like the one mentioned below -
1) synctaskA sets fs->migration_in_progress to 1 and
   does I/O (LOOKUP)
2) Other synctask threads wait for fs->migration_in_progress
  to be reset to 0 by synctaskA and hence blocked
3) but synctaskA cannot resume as all synctask threads are blocked
   on (2).
Note: this same approach is already used by few other components
like syncbarrier etc.
Change-Id: If90f870d663bb242c702a5b86ac52eeda67c6f0d
Fixes: #1146
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
Diffstat (limited to 'api/src/glfs.c')
| -rw-r--r-- | api/src/glfs.c | 9 | 
1 files changed, 9 insertions, 0 deletions
diff --git a/api/src/glfs.c b/api/src/glfs.c index 5f683451c21..93e0938b815 100644 --- a/api/src/glfs.c +++ b/api/src/glfs.c @@ -737,6 +737,7 @@ glfs_new_fs(const char *volname)      INIT_LIST_HEAD(&fs->openfds);      INIT_LIST_HEAD(&fs->upcall_list); +    INIT_LIST_HEAD(&fs->waitq);      PTHREAD_MUTEX_INIT(&fs->mutex, NULL, fs->pthread_flags, GLFS_INIT_MUTEX,                         err); @@ -1240,6 +1241,7 @@ pub_glfs_fini(struct glfs *fs)      call_pool_t *call_pool = NULL;      int fs_init = 0;      int err = -1; +    struct synctask *waittask = NULL;      DECLARE_OLD_THIS; @@ -1261,6 +1263,13 @@ pub_glfs_fini(struct glfs *fs)      call_pool = fs->ctx->pool; +    /* Wake up any suspended synctasks */ +    while (!list_empty(&fs->waitq)) { +        waittask = list_entry(fs->waitq.next, struct synctask, waitq); +        list_del_init(&waittask->waitq); +        synctask_wake(waittask); +    } +      while (countdown--) {          /* give some time for background frames to finish */          pthread_mutex_lock(&fs->mutex);  | 
