diff options
| -rw-r--r-- | tests/bitrot/bug-1294786.t | 43 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/stub/bit-rot-stub.c | 104 | 
2 files changed, 133 insertions, 14 deletions
diff --git a/tests/bitrot/bug-1294786.t b/tests/bitrot/bug-1294786.t index 2bfae36fd86..4911c1dd6c2 100644 --- a/tests/bitrot/bug-1294786.t +++ b/tests/bitrot/bug-1294786.t @@ -13,7 +13,11 @@ function get_bitd_count_2 {  }  function get_node_uuid { -        getfattr -n trusted.glusterfs.node-uuid --only-values $M0/FILE 2>/dev/null +        getfattr -n trusted.glusterfs.node-uuid --only-values $M0/FILE1 2>/dev/null +} + +function get_quarantine_count { +        ls -l "$B1/.glusterfs/quanrantine" | wc -l  }  cleanup; @@ -41,15 +45,26 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count_1  EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count_2  #Create sample file -TEST `echo "1234" > $M0/FILE` +TEST `echo "1234" > $M0/FILE1` +TEST `echo "5678" > $M0/FILE2` +gfid1=$(getfattr -n glusterfs.gfid.string --only-values $M0/FILE1) +gfid2=$(getfattr -n glusterfs.gfid.string --only-values $M0/FILE2)  EXPECT "$uuid1" get_node_uuid;  #Corrupt file from back-end -TEST stat $B1/FILE -echo "Corrupted data" >> $B1/FILE +TEST stat $B1/FILE1 +TEST stat $B1/FILE2 +echo "Corrupted data" >> $B1/FILE1 +echo "Corrupted data" >> $B1/FILE2  #Manually set bad-file xattr since we can't wait for an hour for scrubber. -TEST setfattr -n trusted.bit-rot.bad-file -v 0x3100 $B1/FILE +TEST setfattr -n trusted.bit-rot.bad-file -v 0x3100 $B1/FILE1 +TEST setfattr -n trusted.bit-rot.bad-file -v 0x3100 $B1/FILE2 +TEST touch "$B1/.glusterfs/quanrantine/$gfid1" +TEST chmod 000 "$B1/.glusterfs/quanrantine/$gfid1" +TEST touch "$B1/.glusterfs/quanrantine/$gfid2" +TEST chmod 000 "$B1/.glusterfs/quanrantine/$gfid2" +EXPECT "4" get_quarantine_count;  TEST $CLI_1 volume stop $V0  TEST $CLI_1 volume start $V0 @@ -61,8 +76,24 @@ EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1  EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count_1  EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count_2  #Trigger lookup so that bitrot xlator marks file as bad in its inode context. -TEST stat $M0/FILE +TEST stat $M0/FILE1 +TEST stat $M0/FILE2  EXPECT "$uuid2" get_node_uuid; +#BUG 1308961 +#Remove bad files from  mount, it should be removed from quarantine directory. +TEST rm -f $M0/FILE1 +TEST ! stat "$B1/.glusterfs/quanrantine/$gfid1" + +#BUG 1308961 +#Set network.inode-lru-limit to 5 and exceed the limit by creating 10 other files. +#The bad entry from quarantine directory should not be removed. +TEST $CLI_1 volume set $V0 network.inode-lru-limit 5 +for i in {1..10} +do +     echo "1234" > $M0/file_$i +done +TEST stat "$B1/.glusterfs/quanrantine/$gfid2" +  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 1ec9d459845..ce2d22256c8 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c @@ -2844,19 +2844,46 @@ unwind:  /** {{{ */ -/* forget() */ +/* unlink() */  int -br_stub_forget (xlator_t *this, inode_t *inode) +br_stub_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, struct iatt *preparent, +                   struct iatt *postparent, dict_t *xdata)  { -        uint64_t ctx_addr = 0; -        br_stub_inode_ctx_t *ctx = NULL; +        br_stub_local_t     *local    = NULL; +        inode_t             *inode    = NULL; +        uint64_t             ctx_addr = 0; +        br_stub_inode_ctx_t *ctx      = NULL; +        int32_t              ret      = -1; -        inode_ctx_del (inode, this, &ctx_addr); -        if (!ctx_addr) -                return 0; +        if (op_ret < 0) +                goto unwind; -        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; +        local = frame->local; +        frame->local = NULL; + +        inode = local->u.context.inode; + +        ret = br_stub_get_inode_ctx (this, inode, &ctx_addr); +        if (ret) { +                /** +                 * If the inode is bad AND context is not there, then there +                 * is a possibility of the gfid of the object being listed +                 * in the quarantine directory and will be shown in the +                 * bad objects list. So continuing with the fop with a +                 * warning log. The entry from the quarantine directory +                 * has to be removed manually. Its not a good idea to fail +                 * the fop, as the object has already been deleted. +                 */ +                gf_msg (this->name, GF_LOG_WARNING, 0, +                        BRS_MSG_GET_INODE_CONTEXT_FAILED, +                        "failed to get the context for the inode %s", +                        uuid_utoa (inode->gfid)); +                goto unwind; +        } + +        ctx = (br_stub_inode_ctx_t *)(long)ctx_addr;          LOCK (&inode->lock);          { @@ -2871,6 +2898,66 @@ br_stub_forget (xlator_t *this, inode_t *inode)          }          UNLOCK (&inode->lock); +unwind: +        STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent, +                             postparent, xdata); +        br_stub_cleanup_local (local); +        br_stub_dealloc_local (local); +        return 0; +} + +int +br_stub_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int flag, +                dict_t *xdata) +{ +        br_stub_local_t *local = NULL; +        int32_t          op_ret = -1; +        int32_t          op_errno = 0; + +        local = br_stub_alloc_local (this); +        if (!local) { +                op_ret = -1; +                op_errno = ENOMEM; +                gf_msg (this->name, GF_LOG_ERROR, ENOMEM, BRS_MSG_NO_MEMORY, +                        "failed to allocate memory for local (path: %s, gfid: %s)", +                        loc->path, uuid_utoa (loc->inode->gfid)); +                goto unwind; +        } + +        br_stub_fill_local (local, NULL, NULL, loc->inode, +                            loc->inode->gfid, +                            BR_STUB_NO_VERSIONING, 0); + +        frame->local = local; + +        STACK_WIND (frame, br_stub_unlink_cbk, FIRST_CHILD (this), +                    FIRST_CHILD (this)->fops->unlink, loc, flag, xdata); +        return 0; + +unwind: +        STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, NULL, NULL, NULL); +        return 0; +} + + +/** }}} */ + +/** {{{ */ + +/* forget() */ + +int +br_stub_forget (xlator_t *this, inode_t *inode) +{ +        uint64_t ctx_addr = 0; +        br_stub_inode_ctx_t *ctx = NULL; + +        inode_ctx_del (inode, this, &ctx_addr); +        if (!ctx_addr) +                return 0; + +        ctx = (br_stub_inode_ctx_t *) (long) ctx_addr; +          GF_FREE (ctx);          return 0; @@ -3136,6 +3223,7 @@ struct xlator_fops fops = {          .setxattr  = br_stub_setxattr,          .opendir   = br_stub_opendir,          .readdir   = br_stub_readdir, +        .unlink    = br_stub_unlink,  };  struct xlator_cbks cbks = {  | 
