summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra Bhat <raghavendra@redhat.com>2015-05-15 14:10:48 +0530
committerVenky Shankar <vshankar@redhat.com>2015-05-31 19:33:21 -0700
commit712735a0511bf23a1e04e790a59803155bbd8f65 (patch)
tree4c64d79614f8f7216135c4fdf5f01e3bc1445cd1
parent9f540b5ef116398d221bca8c180b6954acdd308b (diff)
features/bit-rot-stub: implement mknod fop
Backport of http://review.gluster.org/10790 With the absence of mknod() fop implementation in bitrot stub, further operations that trigger versioning resulted in crashes as they expect the inode context to be valid. Therefore, this patch implements mknod() following similar simantics to fops such as create(). Furthermore, bitrot stub test C program is fixed to stop lying and validate obj versions according to the versioning protocol. Change-Id: If76f252577445d1851d6c13c7e969e864e2183ef BUG: 1226139 Original-Author: Raghavendra Bhat <raghavendra@redhat.com> Signed-off-by: Venky Shankar <vshankar@redhat.com> Reviewed-on: http://review.gluster.org/10987 Tested-by: NetBSD Build System <jenkins@build.gluster.org> Tested-by: Gluster Build System <jenkins@build.gluster.com>
-rw-r--r--tests/bitrot/br-stub.c47
-rw-r--r--tests/bitrot/bug-1221914.t48
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-stub.c51
3 files changed, 131 insertions, 15 deletions
diff --git a/tests/bitrot/br-stub.c b/tests/bitrot/br-stub.c
index e164170bb83..5b862832e77 100644
--- a/tests/bitrot/br-stub.c
+++ b/tests/bitrot/br-stub.c
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <sys/xattr.h>
+#include <errno.h>
#include "bit-rot-object-version.h"
@@ -24,23 +25,26 @@ brstub_validate_version (char *bpath, unsigned long version)
xsize = sizeof (br_version_t);
xv = calloc (1, xsize);
- if (!xv)
+ if (!xv) {
+ match = -1;
goto err;
+ }
ret = getxattr (bpath, "trusted.bit-rot.version", xv, xsize);
- if (ret < 0)
+ if (ret < 0) {
+ if (errno == ENODATA)
+ match = -2;
goto err;
+ }
if (xv->ongoingversion != version) {
- match = -1;
+ match = -3;
fprintf (stderr, "ongoingversion: %lu\n", xv->ongoingversion);
}
free (xv);
- return match;
-
err:
- return -1;
+ return match;
}
int
@@ -58,8 +62,9 @@ brstub_write_validation (char *filp, char *bpath, unsigned long startversion)
close (fd1);
ret = brstub_validate_version (bpath, startversion);
- if (ret == 0)
+ if (ret != -2)
goto err;
+
/* single open (write/) check */
fd1 = open (filp, O_RDWR);
if (fd1 < 0)
@@ -76,19 +81,26 @@ brstub_write_validation (char *filp, char *bpath, unsigned long startversion)
* versioning as it would have not reached the bit-rot-stub.
*/
fsync (fd1);
- startversion++;
ret = brstub_validate_version (bpath, startversion);
- if (ret < 0)
+ if (ret != 0)
goto err;
ret = write (fd1, string, strlen (string));
if (ret <= 0)
goto err;
+ fsync (fd1); /* let it reach the disk */
ret = brstub_validate_version (bpath, startversion);
- if (ret < 0)
+ if (ret != 0)
goto err;
close (fd1);
+
+ /**
+ * Well, this is not a _real_ test per se . For this test to pass
+ * the inode should not get a forget() in the interim. Therefore,
+ * perform this test asap.
+ */
+
/* multi open (write/) check */
fd1 = open (filp, O_RDWR);
if (fd1 < 0)
@@ -101,9 +113,14 @@ brstub_write_validation (char *filp, char *bpath, unsigned long startversion)
if (ret <= 0)
goto err;
- ret = write (fd1, string, strlen (string));
+ ret = write (fd2, string, strlen (string));
if (ret <= 0)
goto err;
+
+ /* probably do a syncfs() */
+ fsync (fd1);
+ fsync (fd2);
+
close (fd1);
close (fd2);
@@ -111,7 +128,7 @@ brstub_write_validation (char *filp, char *bpath, unsigned long startversion)
* incremented once per write()/write().../close()/close() sequence
*/
ret = brstub_validate_version (bpath, startversion);
- if (ret < 0)
+ if (ret != 0)
goto err;
return 0;
@@ -134,12 +151,12 @@ brstub_new_object_validate (char *filp, char *brick)
(void) snprintf (bpath, PATH_MAX, "%s/%s", brick, fname);
printf ("Validating initial version..\n");
- ret = brstub_validate_version (bpath, 1);
- if (ret == 0)
+ ret = brstub_validate_version (bpath, 2);
+ if (ret != -2) /* version _should_ be missing */
goto err;
printf ("Validating version on modifications..\n");
- ret = brstub_write_validation (filp, bpath, 1);
+ ret = brstub_write_validation (filp, bpath, 2);
if (ret < 0)
goto err;
diff --git a/tests/bitrot/bug-1221914.t b/tests/bitrot/bug-1221914.t
new file mode 100644
index 00000000000..85715e5a83c
--- /dev/null
+++ b/tests/bitrot/bug-1221914.t
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../volume.rc
+. $(dirname $0)/../nfs.rc
+
+STUB_SOURCE=$(dirname $0)/br-stub.c
+STUB_EXEC=$(dirname $0)/br-stub
+
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+
+## Create a distribute volume (B=2)
+TEST $CLI volume create $V0 $H0:$B0/${V0}1 $H0:$B0/${V0}2;
+EXPECT "$V0" volinfo_field $V0 'Volume Name';
+EXPECT 'Created' volinfo_field $V0 'Status';
+EXPECT '2' brick_count $V0
+
+## Turn off write-behind (write-behind clubs writes together)
+TEST $CLI volume set $V0 performance.write-behind off
+
+## Start the volume
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status';
+
+## Mount the volume
+TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0;
+
+## Build stub C source
+build_tester $STUB_SOURCE -o $STUB_EXEC -I$(dirname $0)/../../xlators/features/bit-rot/src/stub
+TEST [ -e $STUB_EXEC ]
+
+## create & check version
+fname="$M0/filezero"
+$PYTHON -c "import os,stat; os.mknod('${fname}', stat.S_IFREG | stat.S_IRUSR | stat.S_IWUSR | stat.S_IROTH | stat.S_IRGRP)"
+
+backpath=$(get_backend_paths $fname)
+
+TEST $STUB_EXEC $fname $(dirname $backpath)
+
+rm -f $fname;
+
+##cleanups..
+rm -f $STUB_EXEC
+
+cleanup;
diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.c b/xlators/features/bit-rot/src/stub/bit-rot-stub.c
index 1827f48c1c9..69e326b17e1 100644
--- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c
+++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c
@@ -1647,6 +1647,10 @@ br_stub_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (ret < 0) {
ret = br_stub_init_inode_versions (this, fd, inode, version,
_gf_true);
+ if (ret) {
+ op_ret = -1;
+ op_errno = EINVAL;
+ }
} else {
ctx = (br_stub_inode_ctx_t *)(long)ctx_addr;
ret = br_stub_add_fd_to_inode (this, fd, ctx);
@@ -1679,6 +1683,52 @@ unwind:
return 0;
}
+int
+br_stub_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, inode_t *inode,
+ struct iatt *stbuf, struct iatt *preparent,
+ struct iatt *postparent, dict_t *xdata)
+{
+ int32_t ret = -1;
+ unsigned long version = BITROT_DEFAULT_CURRENT_VERSION;
+
+ if (op_ret < 0)
+ goto unwind;
+
+ ret = br_stub_init_inode_versions (this, NULL, inode, version,
+ _gf_true);
+ /**
+ * Like lookup, if init_inode_versions fail, return EINVAL
+ */
+ if (ret) {
+ op_ret = -1;
+ op_errno = EINVAL;
+ }
+
+unwind:
+ STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno,
+ inode, stbuf, preparent, postparent, xdata);
+ return 0;
+}
+
+int
+br_stub_mknod (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, mode_t mode, dev_t dev, mode_t umask, dict_t *xdata)
+{
+ GF_VALIDATE_OR_GOTO ("bit-rot-stub", this, unwind);
+ GF_VALIDATE_OR_GOTO (this->name, loc, unwind);
+ GF_VALIDATE_OR_GOTO (this->name, loc->inode, unwind);
+
+ STACK_WIND (frame, br_stub_mknod_cbk, FIRST_CHILD (this),
+ FIRST_CHILD (this)->fops->mknod,
+ loc, mode, dev, umask, xdata);
+ return 0;
+unwind:
+ STACK_UNWIND_STRICT (mknod, frame, -1, EINVAL, NULL, NULL, NULL,
+ NULL, NULL);
+ return 0;
+}
+
/** }}} */
static inline int32_t
@@ -2144,6 +2194,7 @@ struct xlator_fops fops = {
.writev = br_stub_writev,
.truncate = br_stub_truncate,
.ftruncate = br_stub_ftruncate,
+ .mknod = br_stub_mknod,
};
struct xlator_cbks cbks = {