cb8e9e
From d4e4e3326d03a8c051ec3bea865dd669f3ea3566 Mon Sep 17 00:00:00 2001
cb8e9e
From: Raghavendra Bhat <raghavendra@redhat.com>
cb8e9e
Date: Tue, 21 Jul 2015 15:13:28 +0530
cb8e9e
Subject: [PATCH 282/304] features/bit-rot-stub: handle REOPEN_WAIT on forgotten inodes
cb8e9e
cb8e9e
        Upstream review: http://review.gluster.org/11729
cb8e9e
cb8e9e
> Change-Id: Ia8706ec9b66d78c4e33e7b7faf69f0d113ba68a4
cb8e9e
> BUG: 1245981
cb8e9e
> Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com>
cb8e9e
> Reviewed-on: http://review.gluster.org/11729
cb8e9e
> Tested-by: Gluster Build System <jenkins@build.gluster.com>
cb8e9e
> Tested-by: NetBSD Build System <jenkins@build.gluster.org>
cb8e9e
> Reviewed-by: Venky Shankar <vshankar@redhat.com>
cb8e9e
> Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com>
cb8e9e
cb8e9e
Change-Id: I9de4b597e8ecd36afb98a553fb1101f8b9baff0b
cb8e9e
BUG: 1245165
cb8e9e
Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com>
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/55759
cb8e9e
---
cb8e9e
 tests/bugs/bitrot/bug-1245981.t                  |   55 ++++++++++++++++++++++
cb8e9e
 xlators/features/bit-rot/src/stub/bit-rot-stub.c |   44 +++++++++++++++++-
cb8e9e
 2 files changed, 98 insertions(+), 1 deletions(-)
cb8e9e
 create mode 100644 tests/bugs/bitrot/bug-1245981.t
cb8e9e
cb8e9e
diff --git a/tests/bugs/bitrot/bug-1245981.t b/tests/bugs/bitrot/bug-1245981.t
cb8e9e
new file mode 100644
cb8e9e
index 0000000..2bed4d9
cb8e9e
--- /dev/null
cb8e9e
+++ b/tests/bugs/bitrot/bug-1245981.t
cb8e9e
@@ -0,0 +1,55 @@
cb8e9e
+#!/bin/bash
cb8e9e
+
cb8e9e
+## Test case for bitrot
cb8e9e
+## Tunable object signing waiting time value for bitrot.
cb8e9e
+
cb8e9e
+. $(dirname $0)/../../include.rc
cb8e9e
+. $(dirname $0)/../../volume.rc
cb8e9e
+. $(dirname $0)/../../cluster.rc
cb8e9e
+
cb8e9e
+SLEEP_TIME=5
cb8e9e
+
cb8e9e
+cleanup;
cb8e9e
+## Start glusterd
cb8e9e
+TEST glusterd;
cb8e9e
+TEST pidof glusterd;
cb8e9e
+
cb8e9e
+## Lets create and start the volume
cb8e9e
+TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1
cb8e9e
+TEST $CLI volume start $V0
cb8e9e
+TEST $CLI volume set $V0 network.inode-lru-limit 1
cb8e9e
+## Enable bitrot on volume $V0
cb8e9e
+TEST $CLI volume bitrot $V0 enable
cb8e9e
+
cb8e9e
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count
cb8e9e
+
cb8e9e
+# wait a bit for oneshot crawler to finish
cb8e9e
+sleep 2;
cb8e9e
+
cb8e9e
+## Set object expiry time value
cb8e9e
+TEST $CLI volume bitrot $V0 signing-time $SLEEP_TIME
cb8e9e
+
cb8e9e
+## Mount the volume
cb8e9e
+TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0;
cb8e9e
+
cb8e9e
+# create and check object signature
cb8e9e
+fname="$M0/filezero"
cb8e9e
+echo "ZZZ" > $fname
cb8e9e
+echo "123" > $M0/new_file;
cb8e9e
+
cb8e9e
+touch $M0/1
cb8e9e
+touch $M0/2
cb8e9e
+touch $M0/3
cb8e9e
+touch $M0/4
cb8e9e
+touch $M0/5
cb8e9e
+
cb8e9e
+# wait till the object is signed
cb8e9e
+sleep `expr $SLEEP_TIME \* 2`
cb8e9e
+
cb8e9e
+backpath=$(get_backend_paths $fname)
cb8e9e
+TEST getfattr -m . -n trusted.bit-rot.signature $backpath
cb8e9e
+
cb8e9e
+backpath=$(get_backend_paths $M0/new_file)
cb8e9e
+TEST getfattr -m . -n trusted.bit-rot.signature $backpath
cb8e9e
+
cb8e9e
+cleanup;
cb8e9e
diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.c b/xlators/features/bit-rot/src/stub/bit-rot-stub.c
cb8e9e
index 41c8359..3b3d4d1 100644
cb8e9e
--- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c
cb8e9e
+++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c
cb8e9e
@@ -851,6 +851,40 @@ br_stub_fsetxattr_resume (call_frame_t *frame, void *cookie, xlator_t *this,
cb8e9e
         return 0;
cb8e9e
 }
cb8e9e
 
cb8e9e
+/**
cb8e9e
+ * Handles object reopens. Object reopens can be of 3 types. 2 are from
cb8e9e
+ * oneshot crawler and 1 from the regular signer.
cb8e9e
+ * ONESHOT CRAWLER:
cb8e9e
+ * For those objects which were created before bitrot was enabled. oneshow
cb8e9e
+ * crawler crawls the namespace and signs all the objects. It has to do
cb8e9e
+ * the versioning before making bit-rot-stub send a sign notification.
cb8e9e
+ * So it sends fsetxattr with BR_OBJECT_REOPEN as the value. And bit-rot-stub
cb8e9e
+ * upon getting BR_OBJECT_REOPEN value checks if the version has to be
cb8e9e
+ * increased or not. By default the version will be increased. But if the
cb8e9e
+ * object is modified before BR_OBJECT_REOPEN from oneshot crawler, then
cb8e9e
+ * versioning need not be done. In that case simply a success is returned.
cb8e9e
+ * SIGNER:
cb8e9e
+ * Signer wait for 2 minutes upon getting the notification from bit-rot-stub
cb8e9e
+ * and then it sends a dummy write (in reality a fsetxattr) call, to change
cb8e9e
+ * the state of the inode from REOPEN_WAIT to SIGN_QUICK. The funny part here
cb8e9e
+ * is though the inode's state is REOPEN_WAIT, the call sent by signer is
cb8e9e
+ * BR_OBJECT_RESIGN. Once the state is changed to SIGN_QUICK, then yet another
cb8e9e
+ * notification is sent upon release (RESIGN would have happened via fsetxattr,
cb8e9e
+ * so a fd is needed) and the object is signed truly this time.
cb8e9e
+ * There is a challenge in the above RESIGN method by signer. After sending
cb8e9e
+ * the 1st notification, the inode could be forgotten before RESIGN request
cb8e9e
+ * is received. In that case, the inode's context (the newly looked up inode)
cb8e9e
+ * would not indicate the inode as being modified (it would be in the default
cb8e9e
+ * state) and because of this, a SIGN_QUICK notification to truly sign the
cb8e9e
+ * object would not be sent. So, this is how its handled.
cb8e9e
+ * if (request == RESIGN) {
cb8e9e
+ *    if (inode->sign_info == NORMAL) {
cb8e9e
+ *        mark_inode_non_dirty;
cb8e9e
+ *        mark_inode_modified;
cb8e9e
+ *    }
cb8e9e
+ *    GOBACK (means unwind without doing versioning)
cb8e9e
+ * }
cb8e9e
+ */
cb8e9e
 static void
cb8e9e
 br_stub_handle_object_reopen (call_frame_t *frame,
cb8e9e
                               xlator_t *this, fd_t *fd, uint32_t val)
cb8e9e
@@ -863,6 +897,7 @@ br_stub_handle_object_reopen (call_frame_t *frame,
cb8e9e
         gf_boolean_t         modified    = _gf_false;
cb8e9e
         br_stub_inode_ctx_t *ctx         = NULL;
cb8e9e
         br_stub_local_t     *local       = NULL;
cb8e9e
+        gf_boolean_t         goback      = _gf_true;
cb8e9e
 
cb8e9e
         ret = br_stub_need_versioning (this, fd, &inc_version, &modified, &ctx;;
cb8e9e
         if (ret)
cb8e9e
@@ -870,11 +905,18 @@ br_stub_handle_object_reopen (call_frame_t *frame,
cb8e9e
 
cb8e9e
         LOCK (&fd->inode->lock);
cb8e9e
         {
cb8e9e
+                if ((val == BR_OBJECT_REOPEN) && inc_version)
cb8e9e
+                        goback = _gf_false;
cb8e9e
+                if (val == BR_OBJECT_RESIGN &&
cb8e9e
+                    ctx->info_sign == BR_SIGN_NORMAL) {
cb8e9e
+                        __br_stub_mark_inode_synced (ctx);
cb8e9e
+                        __br_stub_set_inode_modified (ctx);
cb8e9e
+                }
cb8e9e
                 (void) __br_stub_inode_sign_state (ctx, GF_FOP_FSETXATTR, fd);
cb8e9e
         }
cb8e9e
         UNLOCK (&fd->inode->lock);
cb8e9e
 
cb8e9e
-        if ((val == BR_OBJECT_RESIGN) || !inc_version) {
cb8e9e
+        if (goback) {
cb8e9e
                 op_ret = op_errno = 0;
cb8e9e
                 goto unwind;
cb8e9e
         }
cb8e9e
-- 
cb8e9e
1.7.1
cb8e9e