int osd_ldiskfs_read(struct inode *inode, void *buf, int size, loff_t *offs);
int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
- loff_t *offs, handle_t *handle);
+ int write_NUL, loff_t *offs, handle_t *handle);
static inline
struct dentry *osd_child_dentry_by_inode(const struct lu_env *env,
}
int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
- loff_t *offs, handle_t *handle)
+ 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)) {
cfs_spin_lock(&inode->i_lock);
struct thandle *handle, struct lustre_capa *capa,
int ignore_quota)
{
- struct inode *inode = osd_dt_obj(dt)->oo_inode;
- struct osd_thandle *oh;
- ssize_t result;
+ struct inode *inode = osd_dt_obj(dt)->oo_inode;
+ struct osd_thandle *oh;
+ ssize_t result;
#ifdef HAVE_QUOTA_SUPPORT
- cfs_cap_t save = cfs_curproc_cap_pack();
+ cfs_cap_t save = cfs_curproc_cap_pack();
#endif
+ int is_link;
LASSERT(dt_object_exists(dt));
else
cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
#endif
- /* Write small symlink to inode body as we need to maintain correct
- * on-disk symlinks for ldiskfs.
- */
- if (S_ISLNK(dt->do_lu.lo_header->loh_attr) &&
- (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,
- oh->ot_handle);
+ /* 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.
+ */
+ 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, is_link, pos,
+ oh->ot_handle);
#ifdef HAVE_QUOTA_SUPPORT
cfs_curproc_cap_unpack(save);
#endif
}
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=$($LFS getstripe -M $WDIR)
+ mds_index=$((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