Btrfs: Drop dirty roots created by log replay immediately when
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / file.c
index 85841c53880571fec4852364725e91b5a6eaef07..1e8c024c69c37b9f61c454fbf329fb32c4129a84 100644 (file)
@@ -244,16 +244,17 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
 
                        split->start = start + len;
                        split->len = em->start + em->len - (start + len);
-                       split->orig_start = em->orig_start;
                        split->bdev = em->bdev;
                        split->flags = flags;
 
                        if (compressed) {
                                split->block_len = em->block_len;
                                split->block_start = em->block_start;
+                               split->orig_start = em->orig_start;
                        } else {
                                split->block_len = split->len;
                                split->block_start = em->block_start + diff;
+                               split->orig_start = split->start;
                        }
 
                        ret = add_extent_mapping(em_tree, split);
@@ -435,7 +436,7 @@ next_slot:
                        goto out;
                }
                if (recow) {
-                       search_start = key.offset;
+                       search_start = max(key.offset, start);
                        continue;
                }
                if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
@@ -745,6 +746,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
        u64 other_end;
        u64 split = start;
        u64 locked_end = end;
+       u64 orig_parent;
        int extent_type;
        int split_end = 1;
        int ret;
@@ -889,6 +891,12 @@ again:
        }
 
        btrfs_mark_buffer_dirty(leaf);
+
+       orig_parent = leaf->start;
+       ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes,
+                                  orig_parent, root->root_key.objectid,
+                                  trans->transid, inode->i_ino);
+       BUG_ON(ret);
        btrfs_release_path(root, path);
 
        key.offset = start;
@@ -909,10 +917,13 @@ again:
        btrfs_set_file_extent_encryption(leaf, fi, 0);
        btrfs_set_file_extent_other_encoding(leaf, fi, 0);
 
-       ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes,
-                                  leaf->start, root->root_key.objectid,
-                                  trans->transid, inode->i_ino);
-       BUG_ON(ret);
+       if (orig_parent != leaf->start) {
+               ret = btrfs_update_extent_ref(trans, root, bytenr,
+                                             orig_parent, leaf->start,
+                                             root->root_key.objectid,
+                                             trans->transid, inode->i_ino);
+               BUG_ON(ret);
+       }
 done:
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(root, path);