diff options
-rw-r--r-- | tests/bitrot/br-stub.c | 47 | ||||
-rw-r--r-- | tests/bitrot/bug-1221914.t | 48 | ||||
-rw-r--r-- | xlators/features/bit-rot/src/stub/bit-rot-stub.c | 51 |
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 b9a527681ab..d48a3f751f3 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c @@ -1642,6 +1642,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); @@ -1674,6 +1678,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 @@ -2139,6 +2189,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 = { |