]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
ocfs2: Fix the update of name_offset when removing xattrs
authorTao Ma <tao.ma@oracle.com>
Fri, 19 Mar 2010 07:04:23 +0000 (15:04 +0800)
committerJoel Becker <joel.becker@oracle.com>
Fri, 19 Mar 2010 21:53:51 +0000 (14:53 -0700)
When replacing a xattr's value, in some case we wipe its name/value
first and then re-add it. The wipe is done by
ocfs2_xa_block_wipe_namevalue() when the xattr is in the inode or
block. We currently adjust name_offset for all the entries which have
(offset < name_offset). This does not adjust the entrie we're replacing.
Since we are replacing the entry, we don't adjust the total entry count.
When we calculate a new namevalue location, we trust the entries
now-wrong offset in ocfs2_xa_get_free_start().  The solution is to
also adjust the name_offset for the replaced entry, allowing
ocfs2_xa_get_free_start() to calculate the new namevalue location
correctly.

The following script can trigger a kernel panic easily.

echo 'y'|mkfs.ocfs2 --fs-features=local,xattr -b 4K $DEVICE
mount -t ocfs2 $DEVICE $MNT_DIR
FILE=$MNT_DIR/$RANDOM
for((i=0;i<76;i++))
do
string_76="a$string_76"
done
string_78="aa$string_76"
string_82="aaaa$string_78"

touch $FILE
setfattr -n 'user.test1234567890' -v $string_76 $FILE
setfattr -n 'user.test1234567890' -v $string_78 $FILE
setfattr -n 'user.test1234567890' -v $string_82 $FILE

Signed-off-by: Tao Ma <tao.ma@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
fs/ocfs2/xattr.c

index d1b0d386f6d1c43c58b8e0016530f7830ea6eddf..82c2a0b53eb4f0d812e23a97c9be19f2bbf46f40 100644 (file)
@@ -1622,7 +1622,7 @@ static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc)
        /* Now tell xh->xh_entries about it */
        for (i = 0; i < count; i++) {
                offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
-               if (offset < namevalue_offset)
+               if (offset <= namevalue_offset)
                        le16_add_cpu(&xh->xh_entries[i].xe_name_offset,
                                     namevalue_size);
        }