]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/btrfs/ordered-data.c
btrfs: make btrfs_inode_resume_unlocked_dio take btrfs_inode
[mirror_ubuntu-artful-kernel.git] / fs / btrfs / ordered-data.c
index 041c3326d1091d3553d8f9111f9f77c4cdea0c05..9a46878ba60fa973562139f32629810b476ed453 100644 (file)
@@ -432,7 +432,7 @@ out:
 }
 
 /* Needs to either be called under a log transaction or the log_mutex */
-void btrfs_get_logged_extents(struct inode *inode,
+void btrfs_get_logged_extents(struct btrfs_inode *inode,
                              struct list_head *logged_list,
                              const loff_t start,
                              const loff_t end)
@@ -442,7 +442,7 @@ void btrfs_get_logged_extents(struct inode *inode,
        struct rb_node *n;
        struct rb_node *prev;
 
-       tree = &BTRFS_I(inode)->ordered_tree;
+       tree = &inode->ordered_tree;
        spin_lock_irq(&tree->lock);
        n = __tree_search(&tree->tree, end, &prev);
        if (!n)
@@ -879,15 +879,14 @@ out:
 /* Since the DIO code tries to lock a wide area we need to look for any ordered
  * extents that exist in the range, rather than just the start of the range.
  */
-struct btrfs_ordered_extent *btrfs_lookup_ordered_range(struct inode *inode,
-                                                       u64 file_offset,
-                                                       u64 len)
+struct btrfs_ordered_extent *btrfs_lookup_ordered_range(
+               struct btrfs_inode *inode, u64 file_offset, u64 len)
 {
        struct btrfs_ordered_inode_tree *tree;
        struct rb_node *node;
        struct btrfs_ordered_extent *entry = NULL;
 
-       tree = &BTRFS_I(inode)->ordered_tree;
+       tree = &inode->ordered_tree;
        spin_lock_irq(&tree->lock);
        node = tree_search(tree, file_offset);
        if (!node) {
@@ -923,7 +922,7 @@ bool btrfs_have_ordered_extents_in_range(struct inode *inode,
 {
        struct btrfs_ordered_extent *oe;
 
-       oe = btrfs_lookup_ordered_range(inode, file_offset, len);
+       oe = btrfs_lookup_ordered_range(BTRFS_I(inode), file_offset, len);
        if (oe) {
                btrfs_put_ordered_extent(oe);
                return true;
@@ -984,8 +983,18 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
        }
        disk_i_size = BTRFS_I(inode)->disk_i_size;
 
-       /* truncate file */
-       if (disk_i_size > i_size) {
+       /*
+        * truncate file.
+        * If ordered is not NULL, then this is called from endio and
+        * disk_i_size will be updated by either truncate itself or any
+        * in-flight IOs which are inside the disk_i_size.
+        *
+        * Because btrfs_setsize() may set i_size with disk_i_size if truncate
+        * fails somehow, we need to make sure we have a precise disk_i_size by
+        * updating it as usual.
+        *
+        */
+       if (!ordered && disk_i_size > i_size) {
                BTRFS_I(inode)->disk_i_size = orig_offset;
                ret = 0;
                goto out;
@@ -1032,25 +1041,22 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
                /* We treat this entry as if it doesn't exist */
                if (test_bit(BTRFS_ORDERED_UPDATED_ISIZE, &test->flags))
                        continue;
-               if (test->file_offset + test->len <= disk_i_size)
+
+               if (entry_end(test) <= disk_i_size)
                        break;
                if (test->file_offset >= i_size)
                        break;
-               if (entry_end(test) > disk_i_size) {
-                       /*
-                        * we don't update disk_i_size now, so record this
-                        * undealt i_size. Or we will not know the real
-                        * i_size.
-                        */
-                       if (test->outstanding_isize < offset)
-                               test->outstanding_isize = offset;
-                       if (ordered &&
-                           ordered->outstanding_isize >
-                           test->outstanding_isize)
-                               test->outstanding_isize =
-                                               ordered->outstanding_isize;
-                       goto out;
-               }
+
+               /*
+                * We don't update disk_i_size now, so record this undealt
+                * i_size. Or we will not know the real i_size.
+                */
+               if (test->outstanding_isize < offset)
+                       test->outstanding_isize = offset;
+               if (ordered &&
+                   ordered->outstanding_isize > test->outstanding_isize)
+                       test->outstanding_isize = ordered->outstanding_isize;
+               goto out;
        }
        new_i_size = min_t(u64, offset, i_size);