From 4c6b063463ae48b3509ff8e66cd391f8637a86af Mon Sep 17 00:00:00 2001 From: Csaba Henk Date: Tue, 21 Aug 2018 12:44:54 +0200 Subject: fuse: diagnostic FLUSH interrupt We add dummy interrupt handling for the FLUSH fuse message. It can be enabled by the "--fuse-flush-handle-interrupt" hidden command line option, or "-ofuse-flush-handle-interrupt=yes" mount option. It serves no other than diagnostic & demonstational purposes -- to exercise the interrupt handling framework a bit and to give an usage example. Documentation is also provided that showcases interrupt handling via FLUSH. Change-Id: I522f1e798501d06b74ac3592a5f73c1ab0590c60 updates: #465 Signed-off-by: Csaba Henk --- xlators/mount/fuse/src/fuse-bridge.c | 60 ++++++++++++++++++++++++++++- xlators/mount/fuse/src/fuse-bridge.h | 4 +- xlators/mount/fuse/utils/mount.glusterfs.in | 7 ++++ 3 files changed, 69 insertions(+), 2 deletions(-) (limited to 'xlators/mount/fuse') diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index e4e894e6c9b..48b8d9df480 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -1828,6 +1828,21 @@ fuse_err_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, return 0; } +static int +fuse_flush_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + fuse_private_t *priv = this->private; + + if (priv->flush_handle_interrupt) { + if (fuse_interrupt_finish_fop(frame, this, _gf_false, NULL)) { + return 0; + } + } + + return fuse_err_cbk(frame, cookie, this, op_ret, op_errno, xdata); +} + static int fuse_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, @@ -3044,7 +3059,19 @@ fuse_lseek(xlator_t *this, fuse_in_header_t *finh, void *msg, void fuse_flush_resume(fuse_state_t *state) { - FUSE_FOP(state, fuse_err_cbk, GF_FOP_FLUSH, flush, state->fd, state->xdata); + FUSE_FOP(state, fuse_flush_cbk, GF_FOP_FLUSH, flush, state->fd, + state->xdata); +} + +static void +fuse_flush_interrupt_handler(xlator_t *this, fuse_interrupt_record_t *fir) +{ + gf_log("glusterfs-fuse", GF_LOG_DEBUG, + "FLUSH unique %" PRIu64 ": interrupt handler triggered", + fir->fuse_in_header.unique); + + fuse_interrupt_finish_interrupt(this, fir, INTERRUPT_HANDLED, _gf_false, + NULL); } static void @@ -3052,6 +3079,7 @@ fuse_flush(xlator_t *this, fuse_in_header_t *finh, void *msg, struct iobuf *iobuf) { struct fuse_flush_in *ffi = msg; + fuse_private_t *priv = NULL; fuse_state_t *state = NULL; fd_t *fd = NULL; @@ -3060,6 +3088,26 @@ fuse_flush(xlator_t *this, fuse_in_header_t *finh, void *msg, fd = FH_TO_FD(ffi->fh); state->fd = fd; + priv = this->private; + if (priv->flush_handle_interrupt) { + fuse_interrupt_record_t *fir = NULL; + + fir = fuse_interrupt_record_new(finh, fuse_flush_interrupt_handler); + if (!fir) { + send_fuse_err(this, finh, ENOMEM); + + gf_log("glusterfs-fuse", GF_LOG_ERROR, + "FLUSH unique %" PRIu64 + ":" + " interrupt record allocation failed", + finh->unique); + free_fuse_state(state); + + return; + } + fuse_interrupt_record_insert(this, fir); + } + fuse_resolve_fd_init(state, &state->resolve, fd); state->lk_owner = ffi->lock_owner; @@ -6301,6 +6349,9 @@ init(xlator_t *this_xl) GF_OPTION_INIT("attr-times-granularity", priv->attr_times_granularity, int32, cleanup_exit); + GF_OPTION_INIT("flush-handle-interrupt", priv->flush_handle_interrupt, bool, + cleanup_exit); + /* user has set only background-qlen, not congestion-threshold, use the fuse kernel driver formula to set congestion. ie, 75% */ if (dict_get(this_xl->options, "background-qlen") && @@ -6608,5 +6659,12 @@ struct volume_options options[] = { .max = 1000000000, .description = "Supported granularity of file attribute times.", }, + { + .key = {"flush-handle-interrupt"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "false", + .description = + "Handle iterrupts in FLUSH handler (for testing purposes).", + }, {.key = {NULL}}, }; diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index b391af76bac..b997d9e0cbb 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -161,6 +161,8 @@ struct fuse_private { /* Interrupt subscription */ struct list_head interrupt_list; pthread_mutex_t interrupt_mutex; + + gf_boolean_t flush_handle_interrupt; }; typedef struct fuse_private fuse_private_t; @@ -194,7 +196,7 @@ typedef struct fuse_interrupt_record fuse_interrupt_record_t; typedef void (*fuse_interrupt_handler_t)(xlator_t *this, fuse_interrupt_record_t *); struct fuse_interrupt_record { - struct fuse_in_header fuse_in_header; + fuse_in_header_t fuse_in_header; void *data; gf_boolean_t hit; fuse_interrupt_state_t interrupt_state; diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in index 40172fc421d..4a95cd80b87 100755 --- a/xlators/mount/fuse/utils/mount.glusterfs.in +++ b/xlators/mount/fuse/utils/mount.glusterfs.in @@ -281,6 +281,10 @@ start_glusterfs () cmd_line=$(echo "$cmd_line --dump-fuse=$dump_fuse"); fi + if [ -n "$fuse_flush_handle_interrupt" ]; then + cmd_line=$(echo "$cmd_line --fuse-flush-handle-interrupt=$fuse_flush_handle_interrupt"); + fi + if [ -n "$process_name" ]; then cmd_line=$(echo "$cmd_line --process-name fuse.$process_name"); else @@ -541,6 +545,9 @@ with_options() "dump-fuse") dump_fuse=$value ;; + "fuse-flush-handle-interrupt") + fuse_flush_handle_interrupt=$value + ;; "context"|"fscontext"|"defcontext"|"rootcontext") # standard SElinux mount options to pass to the kernel [ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts," -- cgit