ocfs2: Find proper end cpos for a leaf refcount block.
ocfs2 refcount tree is stored as an extent tree while the leaf ocfs2_refcount_rec points to a refcount block. The following step can trip a kernel panic. mkfs.ocfs2 -b 512 -C 1M --fs-features=refcount $DEVICE mount -t ocfs2 $DEVICE $MNT_DIR FILE_NAME=$RANDOM FILE_NAME_1=$RANDOM FILE_REF="${FILE_NAME}_ref" FILE_REF_1="${FILE_NAME}_ref_1" for((i=0;i<305;i++)) do # /mnt/1048576 is a file with 1048576 sizes. cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME_1 done for((i=0;i<3;i++)) do cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME done for((i=0;i<2;i++)) do cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME_1 done cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME for((i=0;i<11;i++)) do cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME cat /mnt/1048576 >> $MNT_DIR/$FILE_NAME_1 done reflink $MNT_DIR/$FILE_NAME $MNT_DIR/$FILE_REF # write_f is a program which will write some bytes to a file at offset. # write_f -f file_name -l offset -w write_bytes. ./write_f -f $MNT_DIR/$FILE_REF -l $[310*1048576] -w 4096 ./write_f -f $MNT_DIR/$FILE_REF -l $[306*1048576] -w 4096 ./write_f -f $MNT_DIR/$FILE_REF -l $[311*1048576] -w 4096 ./write_f -f $MNT_DIR/$FILE_NAME -l $[310*1048576] -w 4096 ./write_f -f $MNT_DIR/$FILE_NAME -l $[311*1048576] -w 4096 reflink $MNT_DIR/$FILE_NAME $MNT_DIR/$FILE_REF_1 ./write_f -f $MNT_DIR/$FILE_NAME -l $[311*1048576] -w 4096 #kernel panic here. The reason is that if the ocfs2_extent_rec is the last record in a leaf extent block, the old solution fails to find the suitable end cpos. So this patch try to walk through the b-tree, find the next sub root and get the c_pos the next sub-tree starts from. btw, I have runned tristan's test case against the patched kernel for several days and this type of kernel panic never happens again. Signed-off-by: Tao Ma <tao.ma@oracle.com> Signed-off-by: Joel Becker <joel.becker@oracle.com>
This commit is contained in:
@@ -1765,9 +1765,9 @@ set_and_inc:
|
||||
*
|
||||
* The array index of the subtree root is passed back.
|
||||
*/
|
||||
static int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
|
||||
struct ocfs2_path *left,
|
||||
struct ocfs2_path *right)
|
||||
int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
|
||||
struct ocfs2_path *left,
|
||||
struct ocfs2_path *right)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -2872,8 +2872,8 @@ out:
|
||||
* This looks similar, but is subtly different to
|
||||
* ocfs2_find_cpos_for_left_leaf().
|
||||
*/
|
||||
static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
|
||||
struct ocfs2_path *path, u32 *cpos)
|
||||
int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
|
||||
struct ocfs2_path *path, u32 *cpos)
|
||||
{
|
||||
int i, j, ret = 0;
|
||||
u64 blkno;
|
||||
|
Reference in New Issue
Block a user