diff options
author | shishir gowda <sgowda@redhat.com> | 2013-02-25 10:02:15 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2013-03-04 02:42:00 -0800 |
commit | f6a9f19be0e1afe7850842997b88182133d3464e (patch) | |
tree | af4abe593e97b4117c13d6c8f477aa440ff38089 | |
parent | ea0b1c66bf61c12491bb4f2b7313df2a4d66ed6a (diff) |
cluster/distribute: Preserve file size during rebalance migration
If holes are encountered, then we do not write these to the dst,
which sometimes causes file size to be lesser than src. Data is not
corrupted, as when non-zero reads are received, we do write that data.
Calling a truncrate to give file size to prevent it from being
truncated to less than src in case the file end has holes.
Thanks to Brian Foster for providing the test case
BUG: 915554
Change-Id: I7e1e0c475118b073c3ebb87e93220c1ec22e8b7d
Signed-off-by: shishir gowda <sgowda@redhat.com>
Reviewed-on: http://review.gluster.org/4609
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rwxr-xr-x | tests/bugs/bug-915554.t | 75 | ||||
-rw-r--r-- | tests/dht.rc | 13 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-rebalance.c | 6 |
3 files changed, 94 insertions, 0 deletions
diff --git a/tests/bugs/bug-915554.t b/tests/bugs/bug-915554.t new file mode 100755 index 000000000..a811c18f6 --- /dev/null +++ b/tests/bugs/bug-915554.t @@ -0,0 +1,75 @@ +#!/bin/bash +# +# Bug <915554> +# +# This test checks for a condition where a rebalance migrates a file and does +# not preserve the original file size. This can occur due to hole preservation +# logic in the file migration code. If a file size is aligned to a disk sector +# boundary (512b) and the tail portion of the file is zero-filled, the file +# may end up truncated to the end of the last data region in the file. +# +### + +. $(dirname $0)/../include.rc +. $(dirname $0)/../dht.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd + +BRICK_COUNT=3 +# create, start and mount a two brick DHT volume +TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1 $H0:$B0/${V0}2 +TEST $CLI volume start $V0 + +TEST glusterfs --attribute-timeout=0 --entry-timeout=0 --gid-timeout=-1 -s $H0 --volfile-id $V0 $M0; + +i=1 +# Write some data to a file and extend such that the file is sparse to a sector +# aligned boundary. +echo test > $M0/$i +TEST truncate --size=1m $M0/$i + +# cache the original size +SIZE1=`stat -c %s $M0/$i` + +# rename till file gets a linkfile + +while [ $i -ne 0 ] +do + test=`mv $M0/$i $M0/$(( $i+1 )) 2>/dev/null` + if [ $? -ne 0 ] + then + echo "rename failed" + break + fi + let i++ + file_has_linkfile $i + has_link=$? + if [ $has_link -eq 2 ] + then + break; + fi +done + +# start a rebalance (force option to overide checks) to trigger migration of +# file + +TEST $CLI volume rebalance $V0 start force + +# check if rebalance has completed for upto 15 secs + +EXPECT_WITHIN 15 "0" rebalance_completed + +# validate the file size after the migration +SIZE2=`stat -c %s $M0/$i` + +TEST [ $SIZE1 -eq $SIZE2 ] + +TEST rm -f $M0/$i +TEST umount $M0 +TEST $CLI volume stop $V0 +TEST $CLI volume delete $V0 + +cleanup; diff --git a/tests/dht.rc b/tests/dht.rc index 1c811a63c..ee92a47bd 100644 --- a/tests/dht.rc +++ b/tests/dht.rc @@ -70,3 +70,16 @@ function get_hashed_brick() return $hashed } + + +function rebalance_completed() +{ + val=1 + test=`gluster volume rebalance $V0 status |grep localhost|grep -v "in progress" 2>&1` + if [ $? -eq 0 ] + then + val=0 + fi + + echo $val +} diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c index bc5252ee9..cc3691cc2 100644 --- a/xlators/cluster/dht/src/dht-rebalance.c +++ b/xlators/cluster/dht/src/dht-rebalance.c @@ -300,6 +300,12 @@ __dht_rebalance_create_dst_file (xlator_t *to, xlator_t *from, loc_t *loc, struc goto out; } + ret = syncop_ftruncate (to, fd, stbuf->ia_size); + if (ret < 0) + gf_log (this->name, GF_LOG_ERROR, + "ftruncate failed for %s on %s (%s)", + loc->path, to->name, strerror (errno)); + ret = syncop_fsetattr (to, fd, stbuf, (GF_SET_ATTR_UID | GF_SET_ATTR_GID), NULL, NULL); |