diff options
author | Filipe Manana <fdmanana@suse.com> | 2014-11-13 20:00:35 +0300 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-11-21 22:59:56 +0300 |
commit | 0870295b2371673b3563735825ad559409d8cedc (patch) | |
tree | 11c07b99c363a2b4fccf42fc78fd5cf907200bfc /fs/btrfs/ordered-data.c | |
parent | 5ab5e44a36164f0366a98b47289c868d8fbcb256 (diff) | |
download | linux-0870295b2371673b3563735825ad559409d8cedc.tar.xz |
Btrfs: collect only the necessary ordered extents on ranged fsync
Instead of collecting all ordered extents from the inode's ordered tree
and then wait for all of them to complete, just collect the ones that
overlap the fsync range.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 9c28eb4da4dd..534544e08f76 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -432,21 +432,31 @@ out: /* Needs to either be called under a log transaction or the log_mutex */ void btrfs_get_logged_extents(struct inode *inode, - struct list_head *logged_list) + struct list_head *logged_list, + const loff_t start, + const loff_t end) { struct btrfs_ordered_inode_tree *tree; struct btrfs_ordered_extent *ordered; struct rb_node *n; + struct rb_node *prev; tree = &BTRFS_I(inode)->ordered_tree; spin_lock_irq(&tree->lock); - for (n = rb_first(&tree->tree); n; n = rb_next(n)) { + n = __tree_search(&tree->tree, end, &prev); + if (!n) + n = prev; + for (; n; n = rb_prev(n)) { ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); + if (ordered->file_offset > end) + continue; + if (entry_end(ordered) <= start) + break; if (!list_empty(&ordered->log_list)) continue; if (test_bit(BTRFS_ORDERED_LOGGED, &ordered->flags)) continue; - list_add_tail(&ordered->log_list, logged_list); + list_add(&ordered->log_list, logged_list); atomic_inc(&ordered->refs); } spin_unlock_irq(&tree->lock); |