From: Li Zefan <lizf@cn.fujitsu.com>
To: Chris Mason <chris.mason@oracle.com>
Cc: "linux-btrfs@vger.kernel.org" <linux-btrfs@vger.kernel.org>,
Martin Steigerwald <Martin@lichtvoll.de>
Subject: [PATCH 2/3] Btrfs: speed up fstrim
Date: Thu, 29 Dec 2011 17:49:58 +0800 [thread overview]
Message-ID: <4EFC37C6.40307@cn.fujitsu.com> (raw)
In-Reply-To: <4EFC378D.7090606@cn.fujitsu.com>
By remembering which areas has been trimmed, we can speed up
fstrim significantly.
# fstrim -v /mnt/
/mnt/: 152772608 bytes were trimmed
# fstrim -v /mnt/
/mnt/: 0 bytes were trimmed
No bytes has to be trimmed for the second run.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
---
fs/btrfs/extent-tree.c | 29 ++++++++++++++++++-----------
fs/btrfs/free-space-cache.c | 38 ++++++++++++++++++++++++++++++++------
fs/btrfs/free-space-cache.h | 7 ++++---
fs/btrfs/inode-map.c | 16 +++++++++-------
4 files changed, 63 insertions(+), 27 deletions(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f5fbe57..e743395 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -319,7 +319,7 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
size = extent_start - start;
total_added += size;
ret = btrfs_add_free_space(block_group, start,
- size);
+ size, false);
BUG_ON(ret);
start = extent_end + 1;
} else {
@@ -330,7 +330,7 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
if (start < end) {
size = end - start;
total_added += size;
- ret = btrfs_add_free_space(block_group, start, size);
+ ret = btrfs_add_free_space(block_group, start, size, false);
BUG_ON(ret);
}
@@ -4631,7 +4631,7 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
if (start < cache->last_byte_to_unpin) {
len = min(len, cache->last_byte_to_unpin - start);
- btrfs_add_free_space(cache, start, len);
+ btrfs_add_free_space(cache, start, len, false);
}
start += len;
@@ -4987,7 +4987,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
- btrfs_add_free_space(cache, buf->start, buf->len);
+ btrfs_add_free_space(cache, buf->start, buf->len, false);
btrfs_update_reserved_bytes(cache, buf->len, RESERVE_FREE);
}
out:
@@ -5427,14 +5427,16 @@ checks:
search_start = stripe_align(root, offset);
/* move on to the next group */
if (search_start + num_bytes >= search_end) {
- btrfs_add_free_space(used_block_group, offset, num_bytes);
+ btrfs_add_free_space(used_block_group, offset,
+ num_bytes, false);
goto loop;
}
/* move on to the next group */
if (search_start + num_bytes >
used_block_group->key.objectid + used_block_group->key.offset) {
- btrfs_add_free_space(used_block_group, offset, num_bytes);
+ btrfs_add_free_space(used_block_group, offset,
+ num_bytes, false);
goto loop;
}
@@ -5443,13 +5445,14 @@ checks:
if (offset < search_start)
btrfs_add_free_space(used_block_group, offset,
- search_start - offset);
+ search_start - offset, false);
BUG_ON(offset > search_start);
ret = btrfs_update_reserved_bytes(used_block_group, num_bytes,
alloc_type);
if (ret == -EAGAIN) {
- btrfs_add_free_space(used_block_group, offset, num_bytes);
+ btrfs_add_free_space(used_block_group, offset,
+ num_bytes, false);
goto loop;
}
@@ -5459,7 +5462,7 @@ checks:
if (offset < search_start)
btrfs_add_free_space(used_block_group, offset,
- search_start - offset);
+ search_start - offset, false);
BUG_ON(offset > search_start);
if (used_block_group != block_group)
btrfs_put_block_group(used_block_group);
@@ -5668,6 +5671,7 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
{
struct btrfs_block_group_cache *cache;
int ret = 0;
+ bool trimmed = false;
cache = btrfs_lookup_block_group(root->fs_info, start);
if (!cache) {
@@ -5676,13 +5680,16 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
return -ENOSPC;
}
- if (btrfs_test_opt(root, DISCARD))
+ if (btrfs_test_opt(root, DISCARD)) {
ret = btrfs_discard_extent(root, start, len, NULL);
+ if (!ret)
+ trimmed = true;
+ }
if (pin)
pin_down_extent(root, cache, start, len, 1);
else {
- btrfs_add_free_space(cache, start, len);
+ btrfs_add_free_space(cache, start, len, trimmed);
btrfs_update_reserved_bytes(cache, len, RESERVE_FREE);
}
btrfs_put_block_group(cache);
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 044c0ec..cba2a94 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -1567,7 +1567,7 @@ again:
static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info, u64 offset,
- u64 bytes)
+ u64 bytes, bool trimmed)
{
u64 bytes_to_set = 0;
u64 end;
@@ -1578,6 +1578,9 @@ static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl,
bitmap_set_bits(ctl, info, offset, bytes_to_set);
+ if (info->trimmed && !trimmed)
+ info->trimmed = false;
+
return bytes_to_set;
}
@@ -1631,9 +1634,11 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl,
int added = 0;
u64 bytes, offset, bytes_added;
int ret;
+ bool trimmed;
bytes = info->bytes;
offset = info->offset;
+ trimmed = info->trimmed;
if (!ctl->op->use_bitmap(ctl, info))
return 0;
@@ -1669,7 +1674,8 @@ again:
if (entry->offset == offset_to_bitmap(ctl, offset)) {
bytes_added = add_bytes_to_bitmap(ctl, entry,
- offset, bytes);
+ offset, bytes,
+ trimmed);
bytes -= bytes_added;
offset += bytes_added;
}
@@ -1688,7 +1694,8 @@ no_cluster_bitmap:
goto new_bitmap;
}
- bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes);
+ bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes,
+ trimmed);
bytes -= bytes_added;
offset += bytes_added;
added = 0;
@@ -1721,6 +1728,7 @@ new_bitmap:
/* allocate the bitmap */
info->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
+ info->trimmed = trimmed;
spin_lock(&ctl->tree_lock);
if (!info->bitmap) {
ret = -ENOMEM;
@@ -1766,6 +1774,8 @@ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
else
__unlink_free_space(ctl, right_info);
info->bytes += right_info->bytes;
+ if (!right_info->trimmed)
+ info->trimmed = false;
kmem_cache_free(btrfs_free_space_cachep, right_info);
merged = true;
}
@@ -1778,6 +1788,8 @@ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
__unlink_free_space(ctl, left_info);
info->offset = left_info->offset;
info->bytes += left_info->bytes;
+ if (!left_info->trimmed)
+ info->trimmed = false;
kmem_cache_free(btrfs_free_space_cachep, left_info);
merged = true;
}
@@ -1786,7 +1798,7 @@ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
}
int __btrfs_add_free_space(struct btrfs_free_space_ctl *ctl,
- u64 offset, u64 bytes)
+ u64 offset, u64 bytes, bool trimmed)
{
struct btrfs_free_space *info;
int ret = 0;
@@ -1797,6 +1809,7 @@ int __btrfs_add_free_space(struct btrfs_free_space_ctl *ctl,
info->offset = offset;
info->bytes = bytes;
+ info->trimmed = trimmed;
spin_lock(&ctl->tree_lock);
@@ -1940,7 +1953,7 @@ again:
* anything before the hole
*/
ret = btrfs_add_free_space(block_group, old_start,
- offset - old_start);
+ offset - old_start, false);
WARN_ON(ret);
goto out;
}
@@ -2620,6 +2633,13 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
}
if (entry->bitmap) {
+ if (entry->trimmed) {
+ start = entry->offset + BITS_PER_BITMAP *
+ block_group->sectorsize;
+ spin_unlock(&ctl->tree_lock);
+ continue;
+ }
+
ret = search_bitmap(ctl, entry, &start, &bytes);
if (!ret) {
if (start >= end) {
@@ -2638,6 +2658,12 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
continue;
}
} else {
+ if (entry->trimmed) {
+ start = entry->offset + entry->bytes;
+ spin_unlock(&ctl->tree_lock);
+ continue;
+ }
+
start = entry->offset;
bytes = min(entry->bytes, end - start);
unlink_free_space(ctl, entry);
@@ -2666,7 +2692,7 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
bytes,
&actually_trimmed);
- btrfs_add_free_space(block_group, start, bytes);
+ btrfs_add_free_space(block_group, start, bytes, true);
if (update) {
spin_lock(&space_info->lock);
spin_lock(&block_group->lock);
diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h
index 8f2613f..befc682 100644
--- a/fs/btrfs/free-space-cache.h
+++ b/fs/btrfs/free-space-cache.h
@@ -25,6 +25,7 @@ struct btrfs_free_space {
u64 bytes;
unsigned long *bitmap;
struct list_head list;
+ bool trimmed;
};
struct btrfs_free_space_ctl {
@@ -78,13 +79,13 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,
void btrfs_init_free_space_ctl(struct btrfs_block_group_cache *block_group);
int __btrfs_add_free_space(struct btrfs_free_space_ctl *ctl,
- u64 bytenr, u64 size);
+ u64 bytenr, u64 size, bool trimmed);
static inline int
btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
- u64 bytenr, u64 size)
+ u64 bytenr, u64 size, bool trimmed)
{
return __btrfs_add_free_space(block_group->free_space_ctl,
- bytenr, size);
+ bytenr, size, trimmed);
}
int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
u64 bytenr, u64 size);
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index f8962a9..05d73a4 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -107,7 +107,7 @@ again:
if (last != (u64)-1 && last + 1 != key.objectid) {
__btrfs_add_free_space(ctl, last + 1,
- key.objectid - last - 1);
+ key.objectid - last - 1, false);
wake_up(&root->cache_wait);
}
@@ -118,7 +118,8 @@ next:
if (last < root->highest_objectid - 1) {
__btrfs_add_free_space(ctl, last + 1,
- root->highest_objectid - last - 1);
+ root->highest_objectid - last - 1,
+ false);
}
spin_lock(&root->cache_lock);
@@ -173,7 +174,8 @@ static void start_caching(struct btrfs_root *root)
ret = btrfs_find_free_objectid(root, &objectid);
if (!ret && objectid <= BTRFS_LAST_FREE_OBJECTID) {
__btrfs_add_free_space(ctl, objectid,
- BTRFS_LAST_FREE_OBJECTID - objectid + 1);
+ BTRFS_LAST_FREE_OBJECTID - objectid + 1,
+ false);
}
tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n",
@@ -215,7 +217,7 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
again:
if (root->cached == BTRFS_CACHE_FINISHED) {
- __btrfs_add_free_space(ctl, objectid, 1);
+ __btrfs_add_free_space(ctl, objectid, 1, false);
} else {
/*
* If we are in the process of caching free ino chunks,
@@ -238,9 +240,9 @@ again:
if (objectid <= root->cache_progress ||
objectid > root->highest_objectid)
- __btrfs_add_free_space(ctl, objectid, 1);
+ __btrfs_add_free_space(ctl, objectid, 1, false);
else
- __btrfs_add_free_space(pinned, objectid, 1);
+ __btrfs_add_free_space(pinned, objectid, 1, false);
mutex_unlock(&root->fs_commit_mutex);
}
@@ -280,7 +282,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
else
count = info->bytes;
- __btrfs_add_free_space(ctl, info->offset, count);
+ __btrfs_add_free_space(ctl, info->offset, count, false);
free:
rb_erase(&info->offset_index, rbroot);
kfree(info);
-- 1.7.3.1
next prev parent reply other threads:[~2011-12-29 9:49 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-29 9:49 [RFC][PATCH 0/3] Btrfs: speed up fstrim Li Zefan
2011-12-29 9:49 ` [PATCH 1/3][URGENT] Btrfs: allow future use of type field of struct btrfs_free_space_entry Li Zefan
2011-12-29 9:49 ` Li Zefan [this message]
2011-12-29 9:50 ` [PATCH 3/3] Btrfs: save trimmed flag onto disk Li Zefan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4EFC37C6.40307@cn.fujitsu.com \
--to=lizf@cn.fujitsu.com \
--cc=Martin@lichtvoll.de \
--cc=chris.mason@oracle.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).