summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 = {