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;
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);
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);
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
#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);
}
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