summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenky Shankar <vshankar@redhat.com>2015-06-04 10:07:38 +0530
committerRaghavendra Bhat <raghavendra@redhat.com>2015-06-16 02:22:21 -0700
commit8e81dccfce17db2d388de95b0b009478cc7d0d4d (patch)
treeb75b93bb4ae24e6fa6faac33fa8d9b416d8ef61e
parent1ac3d28d8dde6360550c80a10d8add572937be16 (diff)
features/bitrot: fix fd leak in truncate (stub)
The need to perform object versioning in the truncate() code path required an fd to reuse existing versioning infrastructure that's used by fd based operations (such as writev(), ftruncate(), etc..). This tempted the use of anonymous fd which was never ever unref()'d after use resulting in fd and/or memory leak depending on the code path taken. Versioning resulted in a dangling file descriptor left open in the filesystem effecting the signing process of a given object (no release() would be trigerred, hence no signing would be performed). On the other hand, cases where the object need not be versioned, the anonymous fd in still ref()'d resulting in memory leak (NOTE: there's no "dangling" file descriptor in this case). Change-Id: I29c3d2af9bbc5cd4b8ddf38954080e3c7a44ba61 BUG: 1227996 Signed-off-by: Venky Shankar <vshankar@redhat.com> Reviewed-on: http://review.gluster.org/11077 Tested-by: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
-rw-r--r--tests/bugs/bitrot/bug-1227996.t58
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-stub.c11
2 files changed, 66 insertions, 3 deletions
diff --git a/tests/bugs/bitrot/bug-1227996.t b/tests/bugs/bitrot/bug-1227996.t
new file mode 100644
index 0000000..47ebc42
--- /dev/null
+++ b/tests/bugs/bitrot/bug-1227996.t
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+## Test case for bitrot
+## Tunable object signing waiting time value for bitrot.
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+. $(dirname $0)/../../cluster.rc
+
+SLEEP_TIME=3
+
+cleanup;
+## Start glusterd
+TEST glusterd;
+TEST pidof glusterd;
+
+## Lets create and start the volume
+TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1
+TEST $CLI volume start $V0
+
+## Enable bitrot on volume $V0
+TEST $CLI volume bitrot $V0 enable
+
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count
+
+# wait a bit for oneshot crawler to finish
+sleep $SLEEP_TIME
+
+## Set object expiry time value
+TEST $CLI volume bitrot $V0 signing-time $SLEEP_TIME
+
+## Mount the volume
+TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0;
+
+# create and check object signature
+fname="$M0/filezero"
+echo "ZZZ" > $fname
+
+# wait till the object is signed
+sleep `expr $SLEEP_TIME \* 2`
+
+backpath=$(get_backend_paths $fname)
+TEST getfattr -m . -n trusted.bit-rot.signature $backpath
+
+## for now just remove the signature xattr to test for signing
+## upon truncate()
+TEST setfattr -x trusted.bit-rot.signature $backpath
+
+## overwrite the file (truncate(), write())
+echo "XYX" > $fname
+
+# wait till the object is signed
+sleep `expr $SLEEP_TIME \* 2`
+
+# test for new signature
+TEST getfattr -m . -n trusted.bit-rot.signature $backpath
+
+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 2f2e16d..5238f43 100644
--- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c
+++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c
@@ -1548,6 +1548,9 @@ int32_t
br_stub_truncate_resume (call_frame_t *frame, xlator_t *this, loc_t *loc,
off_t offset, dict_t *xdata)
{
+ br_stub_local_t *local = frame->local;
+
+ fd_unref (local->u.context.fd);
STACK_WIND (frame, br_stub_ftruncate_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->truncate, loc, offset, xdata);
return 0;
@@ -1596,14 +1599,14 @@ br_stub_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc,
ret = br_stub_need_versioning (this, fd, &inc_version, &modified, &ctx);
if (ret)
- goto unwind;
+ goto cleanup_fd;
if (!inc_version && modified)
goto wind;
ret = br_stub_versioning_prep (frame, this, fd, ctx);
if (ret)
- goto unwind;
+ goto cleanup_fd;
local = frame->local;
if (!inc_version) {
@@ -1627,12 +1630,14 @@ br_stub_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc,
wind:
STACK_WIND (frame, cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->truncate, loc, offset, xdata);
+ fd_unref (fd);
return 0;
cleanup_local:
br_stub_cleanup_local (local);
br_stub_dealloc_local (local);
-
+ cleanup_fd:
+ fd_unref (fd);
unwind:
frame->local = NULL;
STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, NULL, NULL,