Whamcloud - gitweb
LU-2241 symlink: fix off-by-one error when reading symlinks
authorNathaniel Clark <nathaniel.l.clark@intel.com>
Wed, 31 Oct 2012 20:56:09 +0000 (16:56 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 6 Nov 2012 16:17:03 +0000 (11:17 -0500)
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 <nathaniel.l.clark@intel.com>
Change-Id: If4464cac60d57012311226113ff38b9c28926958
Reviewed-on: http://review.whamcloud.com/4415
Tested-by: Hudson
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/osd-ldiskfs/osd_io.c
lustre/tests/sanity.sh

index 0e19e80..77ece77 100644 (file)
@@ -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);
index 7fddfe1..789f3af 100644 (file)
@@ -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