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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.