]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/ioctl.c
Merge branch 'fixes' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
[karo-tx-linux.git] / fs / btrfs / ioctl.c
index 0770c91586ca694e1f9c142fb653cf02c02dd686..0adf5422fce9d4b9fc62c2bbf319429b38aaec7c 100644 (file)
@@ -1030,6 +1030,7 @@ static int should_defrag_range(struct inode *inode, u64 start, u32 thresh,
        struct extent_map *em;
        int ret = 1;
        bool next_mergeable = true;
+       bool prev_mergeable = true;
 
        /*
         * make sure that once we start defragging an extent, we keep on
@@ -1050,13 +1051,16 @@ static int should_defrag_range(struct inode *inode, u64 start, u32 thresh,
                goto out;
        }
 
+       if (!*defrag_end)
+               prev_mergeable = false;
+
        next_mergeable = defrag_check_next_extent(inode, em);
        /*
         * we hit a real extent, if it is big or the next extent is not a
         * real extent, don't bother defragging it
         */
        if (!compress && (*last_len == 0 || *last_len >= thresh) &&
-           (em->len >= thresh || !next_mergeable))
+           (em->len >= thresh || (!next_mergeable && !prev_mergeable)))
                ret = 0;
 out:
        /*
@@ -1933,6 +1937,7 @@ static noinline int copy_to_sk(struct btrfs_root *root,
        u64 found_transid;
        struct extent_buffer *leaf;
        struct btrfs_ioctl_search_header sh;
+       struct btrfs_key test;
        unsigned long item_off;
        unsigned long item_len;
        int nritems;
@@ -2016,12 +2021,17 @@ static noinline int copy_to_sk(struct btrfs_root *root,
        }
 advance_key:
        ret = 0;
-       if (key->offset < (u64)-1 && key->offset < sk->max_offset)
+       test.objectid = sk->max_objectid;
+       test.type = sk->max_type;
+       test.offset = sk->max_offset;
+       if (btrfs_comp_cpu_keys(key, &test) >= 0)
+               ret = 1;
+       else if (key->offset < (u64)-1)
                key->offset++;
-       else if (key->type < (u8)-1 && key->type < sk->max_type) {
+       else if (key->type < (u8)-1) {
                key->offset = 0;
                key->type++;
-       } else if (key->objectid < (u64)-1 && key->objectid < sk->max_objectid) {
+       } else if (key->objectid < (u64)-1) {
                key->offset = 0;
                key->type = 0;
                key->objectid++;
@@ -2842,8 +2852,7 @@ static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2)
                swap(inode1, inode2);
 
        mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT);
-       if (inode1 != inode2)
-               mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
+       mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
 }
 
 static void btrfs_double_extent_unlock(struct inode *inode1, u64 loff1,
@@ -2861,8 +2870,7 @@ static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
                swap(loff1, loff2);
        }
        lock_extent_range(inode1, loff1, len);
-       if (inode1 != inode2)
-               lock_extent_range(inode2, loff2, len);
+       lock_extent_range(inode2, loff2, len);
 }
 
 struct cmp_pages {
@@ -3787,13 +3795,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                goto out_fput;
 
        if (!same_inode) {
-               if (inode < src) {
-                       mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
-                       mutex_lock_nested(&src->i_mutex, I_MUTEX_CHILD);
-               } else {
-                       mutex_lock_nested(&src->i_mutex, I_MUTEX_PARENT);
-                       mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
-               }
+               btrfs_double_inode_lock(src, inode);
        } else {
                mutex_lock(&src->i_mutex);
        }
@@ -3843,8 +3845,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
 
                lock_extent_range(src, lock_start, lock_len);
        } else {
-               lock_extent_range(src, off, len);
-               lock_extent_range(inode, destoff, len);
+               btrfs_double_extent_lock(src, off, inode, destoff, len);
        }
 
        ret = btrfs_clone(src, inode, off, olen, len, destoff, 0);
@@ -3855,9 +3856,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
 
                unlock_extent(&BTRFS_I(src)->io_tree, lock_start, lock_end);
        } else {
-               unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1);
-               unlock_extent(&BTRFS_I(inode)->io_tree, destoff,
-                             destoff + len - 1);
+               btrfs_double_extent_unlock(src, off, inode, destoff, len);
        }
        /*
         * Truncate page cache pages so that future reads will see the cloned
@@ -3866,17 +3865,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
        truncate_inode_pages_range(&inode->i_data, destoff,
                                   PAGE_CACHE_ALIGN(destoff + len) - 1);
 out_unlock:
-       if (!same_inode) {
-               if (inode < src) {
-                       mutex_unlock(&src->i_mutex);
-                       mutex_unlock(&inode->i_mutex);
-               } else {
-                       mutex_unlock(&inode->i_mutex);
-                       mutex_unlock(&src->i_mutex);
-               }
-       } else {
+       if (!same_inode)
+               btrfs_double_inode_unlock(src, inode);
+       else
                mutex_unlock(&src->i_mutex);
-       }
 out_fput:
        fdput(src_file);
 out_drop_write: