|
|
887953 |
From 5f2e017ce7875de1906eb319339f11c4ef321208 Mon Sep 17 00:00:00 2001
|
|
|
887953 |
From: Csaba Henk <csaba@redhat.com>
|
|
|
887953 |
Date: Mon, 22 Oct 2018 00:59:05 +0200
|
|
|
887953 |
Subject: [PATCH 529/529] fuse: SETLKW interrupt
|
|
|
887953 |
|
|
|
887953 |
Use the (f)getxattr based clearlocks interface to
|
|
|
887953 |
interrupt a pending lock request.
|
|
|
887953 |
|
|
|
887953 |
Upstream: https://review.gluster.org/21472
|
|
|
887953 |
> updates: #465
|
|
|
887953 |
> Change-Id: I4e91a4d8791fc688fed400a02de4c53487e61be2
|
|
|
887953 |
> Signed-off-by: Csaba Henk <csaba@redhat.com>
|
|
|
887953 |
|
|
|
887953 |
Change-Id: Ib436f1524cda6ade24c6970caee3dbd7d5f452d4
|
|
|
887953 |
BUG: 1595246
|
|
|
887953 |
Signed-off-by: Csaba Henk <csaba@redhat.com>
|
|
|
887953 |
Reviewed-on: https://code.engineering.redhat.com/gerrit/162552
|
|
|
887953 |
Tested-by: RHGS Build Bot <nigelb@redhat.com>
|
|
|
887953 |
Reviewed-by: Amar Tumballi Suryanarayan <amarts@redhat.com>
|
|
|
887953 |
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
|
|
|
887953 |
---
|
|
|
887953 |
tests/features/flock_interrupt.t | 33 +++++++++
|
|
|
887953 |
xlators/mount/fuse/src/fuse-bridge.c | 132 +++++++++++++++++++++++++++++++++++
|
|
|
887953 |
2 files changed, 165 insertions(+)
|
|
|
887953 |
create mode 100644 tests/features/flock_interrupt.t
|
|
|
887953 |
|
|
|
887953 |
diff --git a/tests/features/flock_interrupt.t b/tests/features/flock_interrupt.t
|
|
|
887953 |
new file mode 100644
|
|
|
887953 |
index 0000000..8603b65
|
|
|
887953 |
--- /dev/null
|
|
|
887953 |
+++ b/tests/features/flock_interrupt.t
|
|
|
887953 |
@@ -0,0 +1,33 @@
|
|
|
887953 |
+#!/bin/bash
|
|
|
887953 |
+
|
|
|
887953 |
+. $(dirname $0)/../include.rc
|
|
|
887953 |
+. $(dirname $0)/../volume.rc
|
|
|
887953 |
+
|
|
|
887953 |
+cleanup;
|
|
|
887953 |
+
|
|
|
887953 |
+## Start and create a volume
|
|
|
887953 |
+TEST glusterd;
|
|
|
887953 |
+TEST pidof glusterd;
|
|
|
887953 |
+
|
|
|
887953 |
+TEST $CLI volume create $V0 $H0:$B0/${V0}0;
|
|
|
887953 |
+
|
|
|
887953 |
+## Verify volume is is created
|
|
|
887953 |
+EXPECT "$V0" volinfo_field $V0 'Volume Name';
|
|
|
887953 |
+EXPECT 'Created' volinfo_field $V0 'Status';
|
|
|
887953 |
+
|
|
|
887953 |
+## Start volume and verify
|
|
|
887953 |
+TEST $CLI volume start $V0;
|
|
|
887953 |
+EXPECT 'Started' volinfo_field $V0 'Status';
|
|
|
887953 |
+
|
|
|
887953 |
+TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0;
|
|
|
887953 |
+TEST touch $M0/testfile;
|
|
|
887953 |
+
|
|
|
887953 |
+function flock_interrupt {
|
|
|
887953 |
+ flock $MO/testfile sleep 3 & flock -w 1 $M0/testfile true;
|
|
|
887953 |
+ echo ok;
|
|
|
887953 |
+}
|
|
|
887953 |
+
|
|
|
887953 |
+EXPECT_WITHIN 2 ok flock_interrupt;
|
|
|
887953 |
+
|
|
|
887953 |
+## Finish up
|
|
|
887953 |
+cleanup;
|
|
|
887953 |
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
|
|
|
887953 |
index 44c39e4..deaf533 100644
|
|
|
887953 |
--- a/xlators/mount/fuse/src/fuse-bridge.c
|
|
|
887953 |
+++ b/xlators/mount/fuse/src/fuse-bridge.c
|
|
|
887953 |
@@ -4346,6 +4346,18 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
887953 |
{
|
|
|
887953 |
uint32_t op = 0;
|
|
|
887953 |
fuse_state_t *state = NULL;
|
|
|
887953 |
+ int ret = 0;
|
|
|
887953 |
+
|
|
|
887953 |
+ ret = fuse_interrupt_finish_fop (frame, this, _gf_false,
|
|
|
887953 |
+ (void **)&state);
|
|
|
887953 |
+ if (state) {
|
|
|
887953 |
+ GF_FREE (state->name);
|
|
|
887953 |
+ dict_unref (state->xdata);
|
|
|
887953 |
+ GF_FREE (state);
|
|
|
887953 |
+ }
|
|
|
887953 |
+ if (ret) {
|
|
|
887953 |
+ return 0;
|
|
|
887953 |
+ }
|
|
|
887953 |
|
|
|
887953 |
state = frame->root->state;
|
|
|
887953 |
op = state->finh->opcode;
|
|
|
887953 |
@@ -4392,10 +4404,130 @@ fuse_setlk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
887953 |
return 0;
|
|
|
887953 |
}
|
|
|
887953 |
|
|
|
887953 |
+static int
|
|
|
887953 |
+fuse_setlk_interrupt_handler_cbk (call_frame_t *frame, void *cookie,
|
|
|
887953 |
+ xlator_t *this, int32_t op_ret,
|
|
|
887953 |
+ int32_t op_errno, dict_t *dict,
|
|
|
887953 |
+ dict_t *xdata)
|
|
|
887953 |
+{
|
|
|
887953 |
+ fuse_interrupt_state_t intstat = INTERRUPT_NONE;
|
|
|
887953 |
+ fuse_interrupt_record_t *fir;
|
|
|
887953 |
+ fuse_state_t *state = NULL;
|
|
|
887953 |
+ int ret = 0;
|
|
|
887953 |
+
|
|
|
887953 |
+ ret = dict_get_bin (xdata, "fuse-interrupt-record", (void **)&fir;;
|
|
|
887953 |
+ if (ret < 0) {
|
|
|
887953 |
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
|
|
|
887953 |
+ "interrupt record not found");
|
|
|
887953 |
+
|
|
|
887953 |
+ goto out;
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+ intstat = op_ret >= 0 ? INTERRUPT_HANDLED : INTERRUPT_SQUELCHED;
|
|
|
887953 |
+
|
|
|
887953 |
+ fuse_interrupt_finish_interrupt (this, fir, intstat, _gf_false,
|
|
|
887953 |
+ (void **)&state);
|
|
|
887953 |
+ if (state) {
|
|
|
887953 |
+ GF_FREE (state->name);
|
|
|
887953 |
+ dict_unref (state->xdata);
|
|
|
887953 |
+ GF_FREE (state);
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+out:
|
|
|
887953 |
+ STACK_DESTROY (frame->root);
|
|
|
887953 |
+
|
|
|
887953 |
+ return 0;
|
|
|
887953 |
+}
|
|
|
887953 |
+
|
|
|
887953 |
+static void
|
|
|
887953 |
+fuse_setlk_interrupt_handler (xlator_t *this, fuse_interrupt_record_t *fir)
|
|
|
887953 |
+{
|
|
|
887953 |
+ fuse_state_t *state = NULL;
|
|
|
887953 |
+ call_frame_t *frame = NULL;
|
|
|
887953 |
+ char *xattr_name = NULL;
|
|
|
887953 |
+ int ret = 0;
|
|
|
887953 |
+
|
|
|
887953 |
+ gf_log ("glusterfs-fuse", GF_LOG_DEBUG,
|
|
|
887953 |
+ "SETLK%s unique %" PRIu64 ": interrupt handler triggered",
|
|
|
887953 |
+ fir->fuse_in_header.opcode == FUSE_SETLK ? "" : "W",
|
|
|
887953 |
+ fir->fuse_in_header.unique);
|
|
|
887953 |
+
|
|
|
887953 |
+ state = fir->data;
|
|
|
887953 |
+
|
|
|
887953 |
+ ret = gf_asprintf (
|
|
|
887953 |
+ &xattr_name, GF_XATTR_CLRLK_CMD ".tposix.kblocked.%hd,%jd-%jd",
|
|
|
887953 |
+ state->lk_lock.l_whence, state->lk_lock.l_start,
|
|
|
887953 |
+ state->lk_lock.l_len);
|
|
|
887953 |
+ if (ret == -1) {
|
|
|
887953 |
+ xattr_name = NULL;
|
|
|
887953 |
+ goto err;
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+ frame = get_call_frame_for_req (state);
|
|
|
887953 |
+ if (!frame) {
|
|
|
887953 |
+ goto err;
|
|
|
887953 |
+ }
|
|
|
887953 |
+ frame->root->state = state;
|
|
|
887953 |
+ frame->root->op = GF_FOP_GETXATTR;
|
|
|
887953 |
+ frame->op = GF_FOP_GETXATTR;
|
|
|
887953 |
+ state->name = xattr_name;
|
|
|
887953 |
+
|
|
|
887953 |
+ STACK_WIND (frame, fuse_setlk_interrupt_handler_cbk, state->active_subvol,
|
|
|
887953 |
+ state->active_subvol->fops->fgetxattr, state->fd, xattr_name,
|
|
|
887953 |
+ state->xdata);
|
|
|
887953 |
+
|
|
|
887953 |
+ return;
|
|
|
887953 |
+
|
|
|
887953 |
+err:
|
|
|
887953 |
+ GF_FREE (xattr_name);
|
|
|
887953 |
+ fuse_interrupt_finish_interrupt (this, fir, INTERRUPT_SQUELCHED,
|
|
|
887953 |
+ _gf_false, (void **)&state);
|
|
|
887953 |
+ if (state) {
|
|
|
887953 |
+ dict_unref (state->xdata);
|
|
|
887953 |
+ GF_FREE (state);
|
|
|
887953 |
+ }
|
|
|
887953 |
+}
|
|
|
887953 |
|
|
|
887953 |
void
|
|
|
887953 |
fuse_setlk_resume (fuse_state_t *state)
|
|
|
887953 |
{
|
|
|
887953 |
+ fuse_interrupt_record_t *fir = NULL;
|
|
|
887953 |
+ fuse_state_t *state_clone = NULL;
|
|
|
887953 |
+
|
|
|
887953 |
+ fir = fuse_interrupt_record_new (state->finh, fuse_setlk_interrupt_handler);
|
|
|
887953 |
+ state_clone = gf_memdup (state, sizeof (*state));
|
|
|
887953 |
+ if (state_clone) {
|
|
|
887953 |
+ /*
|
|
|
887953 |
+ * Calling this allocator with fir casted to (char *) seems like
|
|
|
887953 |
+ * an abuse of this API, but in fact the API is stupid to assume
|
|
|
887953 |
+ * a (char *) argument (in the funcion it's casted to (void *)
|
|
|
887953 |
+ * anyway).
|
|
|
887953 |
+ */
|
|
|
887953 |
+ state_clone->xdata = dict_for_key_value (
|
|
|
887953 |
+ "fuse-interrupt-record", (char *)fir, sizeof (*fir), _gf_true);
|
|
|
887953 |
+ }
|
|
|
887953 |
+ if (!fir || !state_clone || !state_clone->xdata) {
|
|
|
887953 |
+ if (fir) {
|
|
|
887953 |
+ GF_FREE (fir);
|
|
|
887953 |
+ }
|
|
|
887953 |
+ if (state_clone) {
|
|
|
887953 |
+ GF_FREE (state_clone);
|
|
|
887953 |
+ }
|
|
|
887953 |
+ send_fuse_err (state->this, state->finh, ENOMEM);
|
|
|
887953 |
+
|
|
|
887953 |
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
|
|
|
887953 |
+ "SETLK%s unique %"PRIu64":"
|
|
|
887953 |
+ " interrupt record allocation failed",
|
|
|
887953 |
+ state->finh->opcode == FUSE_SETLK ? "" : "W",
|
|
|
887953 |
+ state->finh->unique);
|
|
|
887953 |
+ free_fuse_state (state);
|
|
|
887953 |
+
|
|
|
887953 |
+ return;
|
|
|
887953 |
+ }
|
|
|
887953 |
+ state_clone->name = NULL;
|
|
|
887953 |
+ fir->data = state_clone;
|
|
|
887953 |
+ fuse_interrupt_record_insert (state->this, fir);
|
|
|
887953 |
+
|
|
|
887953 |
gf_log ("glusterfs-fuse", GF_LOG_TRACE,
|
|
|
887953 |
"%"PRIu64": SETLK%s %p", state->finh->unique,
|
|
|
887953 |
state->finh->opcode == FUSE_SETLK ? "" : "W", state->fd);
|
|
|
887953 |
--
|
|
|
887953 |
1.8.3.1
|
|
|
887953 |
|