Merge branch 'btrfs-3.0' of git://github.com/chrismason/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Oct 2011 06:20:40 +0000 (18:20 +1200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Oct 2011 06:20:40 +0000 (18:20 +1200)
* 'btrfs-3.0' of git://github.com/chrismason/linux:
  Btrfs: make sure not to defrag extents past i_size
  Btrfs: fix recursive auto-defrag

1  2 
fs/btrfs/ioctl.c

diff --combined fs/btrfs/ioctl.c
index 538f65a79ec5694eb16bd80567238eb320de0703,efc4e4a85a6988b69bdf7094feacfb00a6ebac11..dae5dfe41ba59fdd820006b96ff4ed2803d51887
@@@ -323,7 -323,7 +323,7 @@@ static noinline int create_subvol(struc
        struct btrfs_inode_item *inode_item;
        struct extent_buffer *leaf;
        struct btrfs_root *new_root;
 -      struct dentry *parent = dget_parent(dentry);
 +      struct dentry *parent = dentry->d_parent;
        struct inode *dir;
        int ret;
        int err;
        u64 index = 0;
  
        ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
 -      if (ret) {
 -              dput(parent);
 +      if (ret)
                return ret;
 -      }
  
        dir = parent->d_inode;
  
         * 2 - dir items
         */
        trans = btrfs_start_transaction(root, 6);
 -      if (IS_ERR(trans)) {
 -              dput(parent);
 +      if (IS_ERR(trans))
                return PTR_ERR(trans);
 -      }
  
        leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
                                      0, objectid, NULL, 0, 0, 0);
  
        d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
  fail:
 -      dput(parent);
        if (async_transid) {
                *async_transid = trans->transid;
                err = btrfs_commit_transaction_async(trans, root, 1);
@@@ -451,6 -456,7 +451,6 @@@ static int create_snapshot(struct btrfs
                           bool readonly)
  {
        struct inode *inode;
 -      struct dentry *parent;
        struct btrfs_pending_snapshot *pending_snapshot;
        struct btrfs_trans_handle *trans;
        int ret;
        if (ret)
                goto fail;
  
 -      parent = dget_parent(dentry);
 -      inode = btrfs_lookup_dentry(parent->d_inode, dentry);
 -      dput(parent);
 +      inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
        if (IS_ERR(inode)) {
                ret = PTR_ERR(inode);
                goto fail;
@@@ -1047,7 -1055,16 +1047,16 @@@ int btrfs_defrag_file(struct inode *ino
        if (!max_to_defrag)
                max_to_defrag = last_index - 1;
  
-       while (i <= last_index && defrag_count < max_to_defrag) {
+       /*
+        * 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 &&
+              (i < (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+               PAGE_CACHE_SHIFT)) {
                /*
                 * make sure we stop running if someone unmounts
                 * the FS