Skip to content

Commit 8a526c4

Browse files
fdmananakdave
authored andcommitted
btrfs: allow to run delayed refs by bytes to be released instead of count
When running delayed references, through btrfs_run_delayed_refs(), we can specify how many to run, run all existing delayed references and keep running delayed references while we can find any. This is controlled with the value of the 'count' argument, where a value of 0 means to run all delayed references that exist by the time btrfs_run_delayed_refs() is called, (unsigned long)-1 means to keep running delayed references while we are able find any, and any other value to run that exact number of delayed references. Typically a specific value other than 0 or -1 is used when flushing space to try to release a certain amount of bytes for a ticket. In this case we just simply calculate how many delayed reference heads correspond to a specific amount of bytes, with calc_delayed_refs_nr(). However that only takes into account the space reserved for the reference heads themselves, and does not account for the space reserved for deleting checksums from the csum tree (see add_delayed_ref_head() and update_existing_head_ref()) in case we are going to delete a data extent. This means we may end up running more delayed references than necessary in case we process delayed references for deleting a data extent. So change the logic of btrfs_run_delayed_refs() to take a bytes argument to specify how many bytes of delayed references to run/release, using the special values of 0 to mean all existing delayed references and U64_MAX (or (u64)-1) to keep running delayed references while we can find any. This prevents running more delayed references than necessary, when we have delayed references for deleting data extents, but also makes the upcoming changes/patches simpler and it's preparatory work for them. Reviewed-by: Josef Bacik <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent da8848a commit 8a526c4

File tree

5 files changed

+43
-42
lines changed

5 files changed

+43
-42
lines changed

fs/btrfs/block-group.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3474,8 +3474,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans)
34743474
cache_save_setup(cache, trans, path);
34753475

34763476
if (!ret)
3477-
ret = btrfs_run_delayed_refs(trans,
3478-
(unsigned long) -1);
3477+
ret = btrfs_run_delayed_refs(trans, U64_MAX);
34793478

34803479
if (!ret && cache->disk_cache_state == BTRFS_DC_SETUP) {
34813480
cache->io_ctl.inode = NULL;

fs/btrfs/extent-tree.c

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,7 +1815,7 @@ static int run_and_cleanup_extent_op(struct btrfs_trans_handle *trans,
18151815
return ret ? ret : 1;
18161816
}
18171817

1818-
void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
1818+
u64 btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
18191819
struct btrfs_delayed_ref_root *delayed_refs,
18201820
struct btrfs_delayed_ref_head *head)
18211821
{
@@ -1833,10 +1833,13 @@ void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
18331833
}
18341834

18351835
btrfs_delayed_refs_rsv_release(fs_info, nr_items);
1836+
1837+
return btrfs_calc_delayed_ref_bytes(fs_info, nr_items);
18361838
}
18371839

18381840
static int cleanup_ref_head(struct btrfs_trans_handle *trans,
1839-
struct btrfs_delayed_ref_head *head)
1841+
struct btrfs_delayed_ref_head *head,
1842+
u64 *bytes_released)
18401843
{
18411844

18421845
struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -1881,7 +1884,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
18811884
}
18821885
}
18831886

1884-
btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
1887+
*bytes_released = btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
18851888

18861889
trace_run_delayed_ref_head(fs_info, head, 0);
18871890
btrfs_delayed_ref_unlock(head);
@@ -2002,15 +2005,22 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
20022005
* Returns -ENOMEM or -EIO on failure and will abort the transaction.
20032006
*/
20042007
static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2005-
unsigned long nr)
2008+
u64 min_bytes)
20062009
{
20072010
struct btrfs_fs_info *fs_info = trans->fs_info;
20082011
struct btrfs_delayed_ref_root *delayed_refs;
20092012
struct btrfs_delayed_ref_head *locked_ref = NULL;
20102013
int ret;
20112014
unsigned long count = 0;
2015+
unsigned long max_count = 0;
2016+
u64 bytes_processed = 0;
20122017

20132018
delayed_refs = &trans->transaction->delayed_refs;
2019+
if (min_bytes == 0) {
2020+
max_count = delayed_refs->num_heads_ready;
2021+
min_bytes = U64_MAX;
2022+
}
2023+
20142024
do {
20152025
if (!locked_ref) {
20162026
locked_ref = btrfs_obtain_ref_head(trans);
@@ -2046,11 +2056,14 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
20462056
*/
20472057
return ret;
20482058
} else if (!ret) {
2059+
u64 bytes_released = 0;
2060+
20492061
/*
20502062
* Success, perform the usual cleanup of a processed
20512063
* head
20522064
*/
2053-
ret = cleanup_ref_head(trans, locked_ref);
2065+
ret = cleanup_ref_head(trans, locked_ref, &bytes_released);
2066+
bytes_processed += bytes_released;
20542067
if (ret > 0 ) {
20552068
/* We dropped our lock, we need to loop. */
20562069
ret = 0;
@@ -2067,7 +2080,9 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
20672080

20682081
locked_ref = NULL;
20692082
cond_resched();
2070-
} while ((nr != -1 && count < nr) || locked_ref);
2083+
} while ((min_bytes != U64_MAX && bytes_processed < min_bytes) ||
2084+
(max_count > 0 && count < max_count) ||
2085+
locked_ref);
20712086

20722087
return 0;
20732088
}
@@ -2116,22 +2131,25 @@ static u64 find_middle(struct rb_root *root)
21162131
#endif
21172132

21182133
/*
2119-
* this starts processing the delayed reference count updates and
2120-
* extent insertions we have queued up so far. count can be
2121-
* 0, which means to process everything in the tree at the start
2122-
* of the run (but not newly added entries), or it can be some target
2123-
* number you'd like to process.
2134+
* Start processing the delayed reference count updates and extent insertions
2135+
* we have queued up so far.
2136+
*
2137+
* @trans: Transaction handle.
2138+
* @min_bytes: How many bytes of delayed references to process. After this
2139+
* many bytes we stop processing delayed references if there are
2140+
* any more. If 0 it means to run all existing delayed references,
2141+
* but not new ones added after running all existing ones.
2142+
* Use (u64)-1 (U64_MAX) to run all existing delayed references
2143+
* plus any new ones that are added.
21242144
*
21252145
* Returns 0 on success or if called with an aborted transaction
21262146
* Returns <0 on error and aborts the transaction
21272147
*/
2128-
int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2129-
unsigned long count)
2148+
int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, u64 min_bytes)
21302149
{
21312150
struct btrfs_fs_info *fs_info = trans->fs_info;
21322151
struct btrfs_delayed_ref_root *delayed_refs;
21332152
int ret;
2134-
int run_all = count == (unsigned long)-1;
21352153

21362154
/* We'll clean this up in btrfs_cleanup_transaction */
21372155
if (TRANS_ABORTED(trans))
@@ -2141,20 +2159,17 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
21412159
return 0;
21422160

21432161
delayed_refs = &trans->transaction->delayed_refs;
2144-
if (count == 0)
2145-
count = delayed_refs->num_heads_ready;
2146-
21472162
again:
21482163
#ifdef SCRAMBLE_DELAYED_REFS
21492164
delayed_refs->run_delayed_start = find_middle(&delayed_refs->root);
21502165
#endif
2151-
ret = __btrfs_run_delayed_refs(trans, count);
2166+
ret = __btrfs_run_delayed_refs(trans, min_bytes);
21522167
if (ret < 0) {
21532168
btrfs_abort_transaction(trans, ret);
21542169
return ret;
21552170
}
21562171

2157-
if (run_all) {
2172+
if (min_bytes == U64_MAX) {
21582173
btrfs_create_pending_block_groups(trans);
21592174

21602175
spin_lock(&delayed_refs->lock);

fs/btrfs/extent-tree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
9292
enum btrfs_inline_ref_type is_data);
9393
u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset);
9494

95-
int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, unsigned long count);
96-
void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
95+
int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, u64 min_bytes);
96+
u64 btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
9797
struct btrfs_delayed_ref_root *delayed_refs,
9898
struct btrfs_delayed_ref_head *head);
9999
int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len);

fs/btrfs/space-info.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -556,18 +556,6 @@ static inline u64 calc_reclaim_items_nr(const struct btrfs_fs_info *fs_info,
556556
return nr;
557557
}
558558

559-
static inline u64 calc_delayed_refs_nr(const struct btrfs_fs_info *fs_info,
560-
u64 to_reclaim)
561-
{
562-
const u64 bytes = btrfs_calc_delayed_ref_bytes(fs_info, 1);
563-
u64 nr;
564-
565-
nr = div64_u64(to_reclaim, bytes);
566-
if (!nr)
567-
nr = 1;
568-
return nr;
569-
}
570-
571559
#define EXTENT_SIZE_PER_ITEM SZ_256K
572560

573561
/*
@@ -749,10 +737,9 @@ static void flush_space(struct btrfs_fs_info *fs_info,
749737
break;
750738
}
751739
if (state == FLUSH_DELAYED_REFS_NR)
752-
nr = calc_delayed_refs_nr(fs_info, num_bytes);
740+
btrfs_run_delayed_refs(trans, num_bytes);
753741
else
754-
nr = 0;
755-
btrfs_run_delayed_refs(trans, nr);
742+
btrfs_run_delayed_refs(trans, 0);
756743
btrfs_end_transaction(trans);
757744
break;
758745
case ALLOC_CHUNK:

fs/btrfs/transaction.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans)
13351335
}
13361336

13371337
/* Now flush any delayed refs generated by updating all of the roots */
1338-
ret = btrfs_run_delayed_refs(trans, (unsigned long)-1);
1338+
ret = btrfs_run_delayed_refs(trans, U64_MAX);
13391339
if (ret)
13401340
return ret;
13411341

@@ -1350,7 +1350,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans)
13501350
* so we want to keep this flushing in this loop to make sure
13511351
* everything gets run.
13521352
*/
1353-
ret = btrfs_run_delayed_refs(trans, (unsigned long)-1);
1353+
ret = btrfs_run_delayed_refs(trans, U64_MAX);
13541354
if (ret)
13551355
return ret;
13561356
}
@@ -1568,7 +1568,7 @@ static int qgroup_account_snapshot(struct btrfs_trans_handle *trans,
15681568
* for now flush the delayed refs to narrow the race window where the
15691569
* qgroup counters could end up wrong.
15701570
*/
1571-
ret = btrfs_run_delayed_refs(trans, (unsigned long)-1);
1571+
ret = btrfs_run_delayed_refs(trans, U64_MAX);
15721572
if (ret) {
15731573
btrfs_abort_transaction(trans, ret);
15741574
return ret;
@@ -2404,7 +2404,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
24042404
if (ret)
24052405
goto unlock_reloc;
24062406

2407-
ret = btrfs_run_delayed_refs(trans, (unsigned long)-1);
2407+
ret = btrfs_run_delayed_refs(trans, U64_MAX);
24082408
if (ret)
24092409
goto unlock_reloc;
24102410

0 commit comments

Comments
 (0)