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 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 = {  | 
