From 6c3606b79a4c25946255a680f79ff2d58df66bbc Mon Sep 17 00:00:00 2001 From: Nathaniel Clark Date: Wed, 31 Oct 2012 16:56:09 -0400 Subject: [PATCH] LU-2241 symlink: fix off-by-one error when reading symlinks This fixes and off-by-one error when reading symlinks of inode size. The null character is not accounted for when checking bufferlength vs. inode data size. Also add regression test to sanity. Signed-off-by: Nathaniel Clark Change-Id: If4464cac60d57012311226113ff38b9c28926958 Reviewed-on: http://review.whamcloud.com/4415 Tested-by: Hudson Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/osd-ldiskfs/osd_io.c | 2 +- lustre/tests/sanity.sh | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lustre/osd-ldiskfs/osd_io.c b/lustre/osd-ldiskfs/osd_io.c index 0e19e80..77ece77 100644 --- a/lustre/osd-ldiskfs/osd_io.c +++ b/lustre/osd-ldiskfs/osd_io.c @@ -977,7 +977,7 @@ static ssize_t osd_read(const struct lu_env *env, struct dt_object *dt, * on-disk symlinks for ldiskfs. */ if (S_ISLNK(dt->do_lu.lo_header->loh_attr) && - (buf->lb_len <= sizeof(LDISKFS_I(inode)->i_data))) + (buf->lb_len < sizeof(LDISKFS_I(inode)->i_data))) rc = osd_ldiskfs_readlink(inode, buf->lb_buf, buf->lb_len); else rc = osd_ldiskfs_read(inode, buf->lb_buf, buf->lb_len, pos); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 7fddfe1..789f3af 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -452,13 +452,29 @@ test_17f() { } run_test 17f "symlinks: long and very long symlink name ========================" +# str_repeat(S, N) generate a string that is string S repeated N times +str_repeat() { + local s=$1 + local n=$2 + local ret='' + while [ $((n -= 1)) -ge 0 ]; do + ret=$ret$s + done + echo $ret +} + +# Long symlinks and LU-2241 test_17g() { - mkdir -p $DIR/$tdir - LONGSYMLINK="$(dd if=/dev/zero bs=4095 count=1 | tr '\0' 'x')" - ln -s $LONGSYMLINK $DIR/$tdir/$tfile - ls -l $DIR/$tdir + mkdir -p $DIR/$tdir + local TESTS="59 60 61 4094 4095" + + for i in $TESTS; do + local SYMNAME=$(str_repeat 'x' $i) + ln -s $SYMNAME $DIR/$tdir/f$i || error "failed $i-char symlink" + readlink $DIR/$tdir/f$i || error "failed $i-char readlink" + done } -run_test 17g "symlinks: really long symlink name ===============================" +run_test 17g "symlinks: really long symlink name and inode boundaries" test_17h() { #bug 17378 remote_mds_nodsh && skip "remote MDS with nodsh" && return -- 1.8.3.1