Skip to content

Commit 521b680

Browse files
fdmananakdave
authored andcommitted
btrfs: send: keep the current inode open while processing it
Every time we send a write command, we open the inode, read some data to a buffer and then close the inode. The amount of data we read for each write command is at most 48K, returned by max_send_read_size(), and that corresponds to: BTRFS_SEND_BUF_SIZE - 16K = 48K. In practice this does not add any significant overhead, because the time elapsed between every close (iput()) and open (btrfs_iget()) is very short, so the inode is kept in the VFS's cache after the iput() and it's still there by the time we do the next btrfs_iget(). As between processing extents of the current inode we don't do anything else, it makes sense to keep the inode open after we process its first extent that needs to be sent and keep it open until we start processing the next inode. This serves to facilitate the next change, which aims to avoid having send operations trash the page cache with data extents. Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 642c5d3 commit 521b680

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

fs/btrfs/send.c

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ struct send_ctx {
131131
struct list_head name_cache_list;
132132
int name_cache_size;
133133

134+
/*
135+
* The inode we are currently processing. It's not NULL only when we
136+
* need to issue write commands for data extents from this inode.
137+
*/
138+
struct inode *cur_inode;
134139
struct file_ra_state ra;
135140

136141
/*
@@ -4868,7 +4873,6 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
48684873
{
48694874
struct btrfs_root *root = sctx->send_root;
48704875
struct btrfs_fs_info *fs_info = root->fs_info;
4871-
struct inode *inode;
48724876
struct page *page;
48734877
pgoff_t index = offset >> PAGE_SHIFT;
48744878
pgoff_t last_index;
@@ -4879,37 +4883,30 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
48794883
if (ret)
48804884
return ret;
48814885

4882-
inode = btrfs_iget(fs_info->sb, sctx->cur_ino, root);
4883-
if (IS_ERR(inode))
4884-
return PTR_ERR(inode);
4885-
48864886
last_index = (offset + len - 1) >> PAGE_SHIFT;
48874887

4888-
/* initial readahead */
4889-
memset(&sctx->ra, 0, sizeof(struct file_ra_state));
4890-
file_ra_state_init(&sctx->ra, inode->i_mapping);
4891-
48924888
while (index <= last_index) {
48934889
unsigned cur_len = min_t(unsigned, len,
48944890
PAGE_SIZE - pg_offset);
48954891

4896-
page = find_lock_page(inode->i_mapping, index);
4892+
page = find_lock_page(sctx->cur_inode->i_mapping, index);
48974893
if (!page) {
4898-
page_cache_sync_readahead(inode->i_mapping, &sctx->ra,
4899-
NULL, index, last_index + 1 - index);
4894+
page_cache_sync_readahead(sctx->cur_inode->i_mapping,
4895+
&sctx->ra, NULL, index,
4896+
last_index + 1 - index);
49004897

4901-
page = find_or_create_page(inode->i_mapping, index,
4902-
GFP_KERNEL);
4898+
page = find_or_create_page(sctx->cur_inode->i_mapping,
4899+
index, GFP_KERNEL);
49034900
if (!page) {
49044901
ret = -ENOMEM;
49054902
break;
49064903
}
49074904
}
49084905

4909-
if (PageReadahead(page)) {
4910-
page_cache_async_readahead(inode->i_mapping, &sctx->ra,
4911-
NULL, page, index, last_index + 1 - index);
4912-
}
4906+
if (PageReadahead(page))
4907+
page_cache_async_readahead(sctx->cur_inode->i_mapping,
4908+
&sctx->ra, NULL, page, index,
4909+
last_index + 1 - index);
49134910

49144911
if (!PageUptodate(page)) {
49154912
btrfs_readpage(NULL, page);
@@ -4935,7 +4932,7 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
49354932
len -= cur_len;
49364933
sctx->send_size += cur_len;
49374934
}
4938-
iput(inode);
4935+
49394936
return ret;
49404937
}
49414938

@@ -5148,6 +5145,20 @@ static int send_extent_data(struct send_ctx *sctx,
51485145
if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA)
51495146
return send_update_extent(sctx, offset, len);
51505147

5148+
if (sctx->cur_inode == NULL) {
5149+
struct btrfs_root *root = sctx->send_root;
5150+
5151+
sctx->cur_inode = btrfs_iget(root->fs_info->sb, sctx->cur_ino, root);
5152+
if (IS_ERR(sctx->cur_inode)) {
5153+
int err = PTR_ERR(sctx->cur_inode);
5154+
5155+
sctx->cur_inode = NULL;
5156+
return err;
5157+
}
5158+
memset(&sctx->ra, 0, sizeof(struct file_ra_state));
5159+
file_ra_state_init(&sctx->ra, sctx->cur_inode->i_mapping);
5160+
}
5161+
51515162
while (sent < len) {
51525163
u64 size = min(len - sent, read_size);
51535164
int ret;
@@ -6171,6 +6182,9 @@ static int changed_inode(struct send_ctx *sctx,
61716182
u64 left_gen = 0;
61726183
u64 right_gen = 0;
61736184

6185+
iput(sctx->cur_inode);
6186+
sctx->cur_inode = NULL;
6187+
61746188
sctx->cur_ino = key->objectid;
61756189
sctx->cur_inode_new_gen = 0;
61766190
sctx->cur_inode_last_extent = (u64)-1;
@@ -7657,6 +7671,8 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg)
76577671

76587672
name_cache_free(sctx);
76597673

7674+
iput(sctx->cur_inode);
7675+
76607676
kfree(sctx);
76617677
}
76627678

0 commit comments

Comments
 (0)