* [PATCH] Btrfs: do not zero the page if it's in a hole
@ 2012-10-15 11:03 Li Dongyang
2012-10-15 11:03 ` [PATCH] Btrfs: try harder when we merge holes Li Dongyang
0 siblings, 1 reply; 2+ messages in thread
From: Li Dongyang @ 2012-10-15 11:03 UTC (permalink / raw)
To: linux-btrfs
Don't bother zeroing the page if it's already a hole under there.
We can save one allocation from this.
Signed-off-by: Li Dongyang <Jerry87905@gmail.com>
---
fs/btrfs/inode.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 85a1e50..017052e 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3481,6 +3481,7 @@ int btrfs_truncate_page(struct inode *inode, loff_t from, loff_t len,
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct btrfs_ordered_extent *ordered;
struct extent_state *cached_state = NULL;
+ struct extent_map *em = NULL;
char *kaddr;
u32 blocksize = root->sectorsize;
pgoff_t index = from >> PAGE_CACHE_SHIFT;
@@ -3538,6 +3539,20 @@ again:
goto again;
}
+ em = btrfs_get_extent_fiemap(inode, NULL, 0, page_start,
+ PAGE_CACHE_SIZE, 0);
+ if (!IS_ERR_OR_NULL(em) && em->block_start == EXTENT_MAP_HOLE) {
+ u64 em_end = extent_map_end(em);
+ if (em->start <= page_start &&
+ em_end >= page_start + PAGE_CACHE_SIZE) {
+ btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
+ unlock_extent_cached(io_tree, page_start, page_end,
+ &cached_state, GFP_NOFS);
+ ret = 0;
+ goto out_unlock;
+ }
+ }
+
clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, page_end,
EXTENT_DIRTY | EXTENT_DELALLOC |
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
@@ -3574,6 +3589,8 @@ out_unlock:
unlock_page(page);
page_cache_release(page);
out:
+ if (em)
+ free_extent_map(em);
return ret;
}
--
1.7.12.3
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH] Btrfs: try harder when we merge holes
2012-10-15 11:03 [PATCH] Btrfs: do not zero the page if it's in a hole Li Dongyang
@ 2012-10-15 11:03 ` Li Dongyang
0 siblings, 0 replies; 2+ messages in thread
From: Li Dongyang @ 2012-10-15 11:03 UTC (permalink / raw)
To: linux-btrfs
We should look at path->slots[0] rather than path->slots[0]+1 while trying to
merge with the hole behind us.
Also this patch will delete the the latter one if we can merge with both front
and back, leaving one hole covers all three.
Signed-off-by: Li Dongyang <Jerry87905@gmail.com>
---
fs/btrfs/file.c | 133 ++++++++++++++++++++++++++++++++------------------------
1 file changed, 76 insertions(+), 57 deletions(-)
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 9ab1bed..d41805a 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1663,89 +1663,108 @@ static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma)
return 0;
}
-static int hole_mergeable(struct inode *inode, struct extent_buffer *leaf,
- int slot, u64 start, u64 end)
-{
- struct btrfs_file_extent_item *fi;
- struct btrfs_key key;
-
- if (slot < 0 || slot >= btrfs_header_nritems(leaf))
- return 0;
-
- btrfs_item_key_to_cpu(leaf, &key, slot);
- if (key.objectid != btrfs_ino(inode) ||
- key.type != BTRFS_EXTENT_DATA_KEY)
- return 0;
-
- fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
-
- if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG)
- return 0;
-
- if (btrfs_file_extent_disk_bytenr(leaf, fi))
- return 0;
-
- if (key.offset == end)
- return 1;
- if (key.offset + btrfs_file_extent_num_bytes(leaf, fi) == start)
- return 1;
- return 0;
-}
-
-static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode,
- struct btrfs_path *path, u64 offset, u64 end)
+static int merge_holes(struct btrfs_trans_handle *trans, struct inode *inode,
+ struct btrfs_path *path, u64 offset, u64 end)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
struct extent_buffer *leaf;
- struct btrfs_file_extent_item *fi;
- struct extent_map *hole_em;
- struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
+ struct btrfs_file_extent_item *back_fi, *front_fi;
struct btrfs_key key;
int ret;
+ bool front_mergeable = false;
+ bool back_mergeable = false;
key.objectid = btrfs_ino(inode);
key.type = BTRFS_EXTENT_DATA_KEY;
key.offset = offset;
-
ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
if (ret < 0)
return ret;
BUG_ON(!ret);
leaf = path->nodes[0];
- if (hole_mergeable(inode, leaf, path->slots[0]-1, offset, end)) {
- u64 num_bytes;
+ if (path->slots[0] != 0) {
+ btrfs_item_key_to_cpu(leaf, &key, path->slots[0]-1);
+ if (key.objectid == btrfs_ino(inode) &&
+ key.type == BTRFS_EXTENT_DATA_KEY) {
+ front_fi = btrfs_item_ptr(leaf, path->slots[0]-1,
+ struct btrfs_file_extent_item);
+ if (btrfs_file_extent_type(leaf, front_fi) ==
+ BTRFS_FILE_EXTENT_REG &&
+ btrfs_file_extent_disk_bytenr(leaf,
+ front_fi) == 0 &&
+ key.offset +
+ btrfs_file_extent_num_bytes(leaf, front_fi) ==
+ offset) {
+ front_mergeable = true;
+ }
+ }
+ }
- path->slots[0]--;
- fi = btrfs_item_ptr(leaf, path->slots[0],
- struct btrfs_file_extent_item);
- num_bytes = btrfs_file_extent_num_bytes(leaf, fi) +
- end - offset;
- btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
- btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
- btrfs_set_file_extent_offset(leaf, fi, 0);
- btrfs_mark_buffer_dirty(leaf);
- goto out;
+ btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+ if (key.objectid == btrfs_ino(inode) &&
+ key.type == BTRFS_EXTENT_DATA_KEY) {
+ back_fi = btrfs_item_ptr(leaf, path->slots[0],
+ struct btrfs_file_extent_item);
+ if (btrfs_file_extent_type(leaf, back_fi) ==
+ BTRFS_FILE_EXTENT_REG &&
+ btrfs_file_extent_disk_bytenr(leaf, back_fi) == 0 &&
+ key.offset == end) {
+ back_mergeable = true;
+ }
}
- if (hole_mergeable(inode, leaf, path->slots[0]+1, offset, end)) {
+ if (front_mergeable) {
+ u64 num_bytes = 0;
+
+ if (back_mergeable) {
+ num_bytes = btrfs_file_extent_num_bytes(leaf, back_fi);
+
+ ret = btrfs_del_item(trans, root, path);
+ if (ret)
+ goto out;
+ }
+
+ num_bytes += btrfs_file_extent_num_bytes(leaf, front_fi) +
+ end - offset;
+ btrfs_set_file_extent_num_bytes(leaf, front_fi, num_bytes);
+ btrfs_set_file_extent_ram_bytes(leaf, front_fi, num_bytes);
+ btrfs_set_file_extent_offset(leaf, front_fi, 0);
+ btrfs_mark_buffer_dirty(leaf);
+ ret = 0;
+ } else if (back_mergeable) {
u64 num_bytes;
- path->slots[0]++;
key.offset = offset;
btrfs_set_item_key_safe(trans, root, path, &key);
- fi = btrfs_item_ptr(leaf, path->slots[0],
- struct btrfs_file_extent_item);
- num_bytes = btrfs_file_extent_num_bytes(leaf, fi) + end -
- offset;
- btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
- btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
- btrfs_set_file_extent_offset(leaf, fi, 0);
+ num_bytes = btrfs_file_extent_num_bytes(leaf, back_fi) +
+ end - offset;
+ btrfs_set_file_extent_num_bytes(leaf, back_fi, num_bytes);
+ btrfs_set_file_extent_ram_bytes(leaf, back_fi, num_bytes);
+ btrfs_set_file_extent_offset(leaf, back_fi, 0);
btrfs_mark_buffer_dirty(leaf);
- goto out;
+ ret = 0;
}
+
+out:
btrfs_release_path(path);
+ return ret;
+}
+
+static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode,
+ struct btrfs_path *path, u64 offset, u64 end)
+{
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct extent_map *hole_em;
+ struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
+ int ret;
+
+ ret = merge_holes(trans, inode, path, offset, end);
+ if (ret < 0)
+ return ret;
+ if (!ret)
+ goto out;
ret = btrfs_insert_file_extent(trans, root, btrfs_ino(inode), offset,
0, 0, end - offset, 0, end - offset,
--
1.7.12.3
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-10-15 11:02 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-15 11:03 [PATCH] Btrfs: do not zero the page if it's in a hole Li Dongyang
2012-10-15 11:03 ` [PATCH] Btrfs: try harder when we merge holes Li Dongyang
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).