Btrfs: fix recursive auto-defrag
authorLi Zefan <lizf@cn.fujitsu.com>
Mon, 10 Oct 2011 19:43:34 +0000 (15:43 -0400)
committerChris Mason <chris.mason@oracle.com>
Mon, 10 Oct 2011 19:43:34 +0000 (15:43 -0400)
Follow those steps:

  # mount -o autodefrag /dev/sda7 /mnt
  # dd if=/dev/urandom of=/mnt/tmp bs=200K count=1
  # sync
  # dd if=/dev/urandom of=/mnt/tmp bs=8K count=1 conv=notrunc

and then it'll go into a loop: writeback -> defrag -> writeback ...

It's because writeback writes [8K, 200K] and then writes [0, 8K].

I tried to make writeback know if the pages are dirtied by defrag,
but the patch was a bit intrusive. Here I simply set writeback_index
when we defrag a file.

Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/ioctl.c

index 6f89bcc4e5554cbf497e149043ab0e02202e8164..df40b7c5f06bec231a83e63710a4011d1cbd63d0 100644 (file)
@@ -1055,6 +1055,13 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
        if (!max_to_defrag)
                max_to_defrag = last_index - 1;
 
+       /*
+        * make writeback starts from i, so the defrag range can be
+        * written sequentially.
+        */
+       if (i < inode->i_mapping->writeback_index)
+               inode->i_mapping->writeback_index = i;
+
        while (i <= last_index && defrag_count < max_to_defrag) {
                /*
                 * make sure we stop running if someone unmounts