diff options
| author | Csaba Henk <csaba@gluster.com> | 2009-09-23 10:34:38 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2009-09-23 09:19:29 -0700 | 
| commit | a484a0c47ef6468c1615aa78795880e71347f709 (patch) | |
| tree | a16ec602af03258c9b36cfa7cbcab40b939a7162 | |
| parent | 270a473ddaa076af5b3c8c455c7642932dabb479 (diff) | |
fuse: emit a flush from release if we didn't get an adjacent FLUSH message from the kernel
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 223 (flush not sent)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=223
| -rw-r--r-- | booster/src/booster-fd.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/fd.h | 1 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 55 | 
3 files changed, 52 insertions, 5 deletions
diff --git a/booster/src/booster-fd.h b/booster/src/booster-fd.h index 43592e825..0ccc28121 100644 --- a/booster/src/booster-fd.h +++ b/booster/src/booster-fd.h @@ -33,6 +33,7 @@ struct _fd {          pid_t             pid;  	int32_t           flags;          int32_t           refcount; +        uint64_t          flush_unique;          struct list_head  inode_list;          struct _inode    *inode;          struct _dict     *ctx; diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h index 298b1b347..66dc0ed9e 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -46,6 +46,7 @@ struct _fd {          pid_t             pid;  	int32_t           flags;          int32_t           refcount; +        uint64_t          flush_unique;          struct list_head  inode_list;          struct _inode    *inode;          struct _dict     *ctx; diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 9d358984b..e2f0a916d 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -1587,6 +1587,8 @@ fuse_flush (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)          state = state_from_req (req);          fd = FI_TO_FD (fi);          state->fd = fd; +        if (fd) +                fd->flush_unique = req_callid (req);          gf_log ("glusterfs-fuse", GF_LOG_TRACE,                  "%"PRId64": FLUSH %p", req_callid (req), fd); @@ -1602,18 +1604,61 @@ static void  fuse_release (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)  {          fuse_state_t *state = NULL; +        fd_t            *fd = NULL; +        int        do_flush = 0;          state = state_from_req (req); -        state->fd = FI_TO_FD (fi); +        fd = FI_TO_FD (fi); +        state->fd = fd; +#ifdef  GF_LINUX_HOST_OS +        /* This is an ugly Linux specific hack, relying on subtle +         * implementation details. +         * +         * The self-heal algorithm of replicate relies on being +         * notified by means of a flush fop whenever a consumer +         * of a file is done with that file. If this happens +         * from userspace by means of close(2) or process termination, +         * the kernel sends us a FLUSH message which we can handle with +         * the flush fop (nb. this mechanism itself is Linux specific!!). +         * +         * However, if it happens from a kernel context, we get no FLUSH, +         * just the final RELEASE when all references to the file are gone. +         * We try to guess that this is the case by checking if the last FLUSH +         * on the file was just the previous message. If not, we conjecture +         * that this release is from a kernel context and call the flush fop +         * here. +         * +         * Note #1: we check the above condition by means of looking at +         * the "unique" values of the FUSE messages, relying on which is +         * a big fat NO NO NO in any sane code. +         * +         * Note #2: there is no guarantee against false positives (in theory +         * it's possible that the scheduler arranges an unrelated FUSE message +         * in between FLUSH and RELEASE, although it seems to be unlikely), but +         * extra flushes are not a problem. +         * +         * Note #3: cf. Bug #223. +         */ + +        if (fd && fd->flush_unique + 1 != req_callid (req)) +                do_flush = 1; +#endif          gf_log ("glusterfs-fuse", GF_LOG_TRACE, -                "%"PRId64": RELEASE %p", req_callid (req), state->fd); +                "%"PRId64": RELEASE %p%s", req_callid (req), fd, +                do_flush ? " (FLUSH implied)" : ""); -        fd_unref (state->fd); +        if (do_flush) { +                FUSE_FOP (state, fuse_err_cbk, GF_FOP_FLUSH, flush, fd); +                fd_unref (fd); +        } else { +                fd_unref (fd); -        fuse_reply_err (req, 0); +                fuse_reply_err (req, 0); + +                free_state (state); +        } -        free_state (state);          return;  }  | 
