From 12d206ce116298cefbd87ff46a06c2b1f9304c88 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Thu, 23 Aug 2012 22:56:59 +0800 Subject: [PATCH] LU-1540 osd: add NUL terminator for long symlink Add NUL terminator for long symlink to ldiskfs inode on-disk data. Signed-off-by: Bobi Jam Change-Id: Id7ce7829ec9b4c8eb72cf257df046a5288a5eb7b Reviewed-on: http://review.whamcloud.com/3765 Tested-by: Hudson Reviewed-by: Andreas Dilger Tested-by: Maloo --- lustre/osd-ldiskfs/osd_handler.c | 25 +++++++++++++++---- lustre/tests/sanity.sh | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 58e4771..dc443f4 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -2542,8 +2542,9 @@ static int osd_ldiskfs_writelink(struct inode *inode, char *buffer, int buflen) return 0; } -static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize, - loff_t *offs, handle_t *handle) +static int +osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize, + int write_NUL, loff_t *offs, handle_t *handle) { struct buffer_head *bh = NULL; loff_t offset = *offs; @@ -2555,6 +2556,15 @@ static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize, int boffs; int dirty_inode = 0; + if (write_NUL) { + /* + * long symlink write does not count the NUL terminator in + * bufsize, we write it, and the inode's file size does not + * count the NUL terminator as well. + */ + ((char*)buf)[bufsize] = '\0'; + ++bufsize; + } while (bufsize > 0) { if (bh != NULL) brelse(bh); @@ -2591,6 +2601,8 @@ static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize, if (bh) brelse(bh); + if (write_NUL) + --new_size; /* correct in-core and on-disk sizes */ if (new_size > i_size_read(inode)) { spin_lock(&inode->i_lock); @@ -2619,6 +2631,7 @@ static ssize_t osd_write(const struct lu_env *env, struct dt_object *dt, struct inode *inode = obj->oo_inode; struct osd_thandle *oh; ssize_t result = 0; + int is_link; #ifdef HAVE_QUOTA_SUPPORT cfs_cap_t save = cfs_curproc_cap_pack(); #endif @@ -2638,13 +2651,15 @@ static ssize_t osd_write(const struct lu_env *env, struct dt_object *dt, #endif /* Write small symlink to inode body as we need to maintain correct * on-disk symlinks for ldiskfs. + * Note: the buf->lb_buf contains a NUL terminator while buf->lb_len + * does not count it in. */ - if(S_ISLNK(obj->oo_dt.do_lu.lo_header->loh_attr) && - (buf->lb_len < sizeof (LDISKFS_I(inode)->i_data))) + is_link = S_ISLNK(dt->do_lu.lo_header->loh_attr); + if(is_link && (buf->lb_len < sizeof (LDISKFS_I(inode)->i_data))) result = osd_ldiskfs_writelink(inode, buf->lb_buf, buf->lb_len); else result = osd_ldiskfs_write_record(inode, buf->lb_buf, - buf->lb_len, pos, + buf->lb_len, is_link, pos, oh->ot_handle); #ifdef HAVE_QUOTA_SUPPORT cfs_curproc_cap_unpack(save); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 7ce344b..e5897b5 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -496,6 +496,58 @@ test_17k() { #bug 22301 } run_test 17k "symlinks: rsync with xattrs enabled =========================" +# LU-1540 +test_17m() { + local short_sym="0123456789" + local WDIR=$DIR/${tdir}m + local mds_index + local devname + local cmd + local i + local rc=0 + + mkdir -p $WDIR + long_sym=$short_sym + # create a long symlink file + for ((i = 0; i < 4; ++i)); do + long_sym=${long_sym}${long_sym} + done + + echo "create 512 short and long symlink files under $WDIR" + for ((i = 0; i < 256; ++i)); do + ln -sf ${long_sym}"a5a5" $WDIR/long-$i + ln -sf ${short_sym}"a5a5" $WDIR/short-$i + done + + echo "erase them" + rm -f $WDIR/* + sync + sleep 2 + + echo "recreate the 512 symlink files with a shorter string" + for ((i = 0; i < 512; ++i)); do + # rewrite the symlink file with a shorter string + ln -sf ${long_sym} $WDIR/long-$i + ln -sf ${short_sym} $WDIR/short-$i + done + + mds_index=1 + devname=$(mdsdevname $mds_index) + cmd="$E2FSCK -fnvd $devname" + + echo "stop and checking mds${mds_index}: $cmd" + # e2fsck should not return error + stop mds${mds_index} -f + do_facet mds${mds_index} $cmd || rc=$? + + start mds${mds_index} $devname $MDS_MOUNT_OPTS + df $MOUNT > /dev/null 2>&1 + [ $rc -ne 0 ] && error "e2fsck should not report error upon "\ + "short/long symlink MDT: rc=$rc" + return $rc +} +run_test 17m "run e2fsck against MDT which contains short/long symlink" + test_18() { touch $DIR/f ls $DIR || error -- 1.8.3.1