diff options
| author | Csaba Henk <csaba@redhat.com> | 2020-07-15 20:33:07 +0200 | 
|---|---|---|
| committer | Amar Tumballi <amar@kadalu.io> | 2020-07-24 04:35:42 +0000 | 
| commit | c6205023f3992d165e18d78bbeedbb2eb1cc5beb (patch) | |
| tree | dd86e78b383a935f61426f753a4e24a4d7c4f26b | |
| parent | 716aeb0ebbfd046e55de4b0f758a4a5eaf7d4e4c (diff) | |
fuse: fix waiting for interrupt handler
With 'sync' strategy, a fop's cbk waits for
the interrupt handler to finish by making a
call to fuse_interrupt_finish_fop() with
sync = true.
The wait is implemented by monitoring an
interrupt_state struct member via a condition
variable. However, due to broken code logic,
the pthread_cond_wait() call is never reached.
This change introduces a new member to the
fuse_interrupt_state_t enum (the type of
aforementioned struct member),
FUSE_INTERRUPT_WAITING_HANDLER, which is then
used for indicating the state of waiting for
the interrupt handler.
Change-Id: I72ab06c37f45ff8f212a6a632bac1f647af05cbd
Updates: #1374
Signed-off-by: Csaba Henk <csaba@redhat.com>
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 28 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 1 | 
2 files changed, 22 insertions, 7 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index dcafd67b0d6..91eaf9cf6f6 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -833,18 +833,22 @@ fuse_interrupt_finish_fop(call_frame_t *frame, xlator_t *this,          {              intstat_orig = fir->interrupt_state;              if (fir->interrupt_state == INTERRUPT_NONE) { -                fir->interrupt_state = INTERRUPT_SQUELCHED;                  if (sync) { -                    while (fir->interrupt_state == INTERRUPT_NONE) { +                    fir->interrupt_state = INTERRUPT_WAITING_HANDLER; +                    while (fir->interrupt_state != INTERRUPT_SQUELCHED) {                          pthread_cond_wait(&fir->handler_cond,                                            &fir->handler_mutex);                      } -                } +                } else +                    fir->interrupt_state = INTERRUPT_SQUELCHED;              }          }          pthread_mutex_unlock(&fir->handler_mutex);      } +    GF_ASSERT(intstat_orig == INTERRUPT_NONE || +              intstat_orig == INTERRUPT_HANDLED || +              intstat_orig == INTERRUPT_SQUELCHED);      gf_log("glusterfs-fuse", GF_LOG_DEBUG, "intstat_orig=%d", intstat_orig);      /* @@ -894,19 +898,29 @@ fuse_interrupt_finish_interrupt(xlator_t *this, fuse_interrupt_record_t *fir,      };      fuse_interrupt_state_t intstat_orig = INTERRUPT_NONE; +    GF_ASSERT(intstat == INTERRUPT_HANDLED || intstat == INTERRUPT_SQUELCHED); +      pthread_mutex_lock(&fir->handler_mutex);      {          intstat_orig = fir->interrupt_state; -        if (fir->interrupt_state == INTERRUPT_NONE) { -            fir->interrupt_state = intstat; -            if (sync) { +        switch (intstat_orig) { +            case INTERRUPT_NONE: +                fir->interrupt_state = intstat; +                break; +            case INTERRUPT_WAITING_HANDLER: +                fir->interrupt_state = INTERRUPT_SQUELCHED;                  pthread_cond_signal(&fir->handler_cond); -            } +                break; +            default: +                break;          }          finh = fir->fuse_in_header;      }      pthread_mutex_unlock(&fir->handler_mutex); +    GF_ASSERT(intstat_orig == INTERRUPT_NONE || +              (sync && intstat_orig == INTERRUPT_WAITING_HANDLER) || +              (!sync && intstat_orig == INTERRUPT_SQUELCHED));      gf_log("glusterfs-fuse", GF_LOG_DEBUG, "intstat_orig=%d", intstat_orig);      /* diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index 1890e409826..4cb94c23cad 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -244,6 +244,7 @@ enum fuse_interrupt_state {      INTERRUPT_NONE,      INTERRUPT_SQUELCHED,      INTERRUPT_HANDLED, +    INTERRUPT_WAITING_HANDLER,  };  typedef enum fuse_interrupt_state fuse_interrupt_state_t;  struct fuse_interrupt_record;  | 
