Skip to content

Commit a98048e

Browse files
fdmananakdave
authored andcommitted
btrfs: simplify obtaining a delayed ref head
Instead of doing it in two steps outside of delayed-ref.c, leaking low level details such as locking, move the logic entirely to delayed-ref.c under btrfs_select_ref_head(), reducing code and making things simpler for the caller. Reviewed-by: Boris Burkov <boris@bur.io> Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 7ef3604 commit a98048e

3 files changed

Lines changed: 23 additions & 41 deletions

File tree

fs/btrfs/delayed-ref.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,8 @@ static struct btrfs_delayed_ref_head *find_ref_head(
431431
return NULL;
432432
}
433433

434-
bool btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs,
435-
struct btrfs_delayed_ref_head *head)
434+
static bool btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs,
435+
struct btrfs_delayed_ref_head *head)
436436
{
437437
lockdep_assert_held(&delayed_refs->lock);
438438
if (mutex_trylock(&head->mutex))
@@ -561,25 +561,30 @@ struct btrfs_delayed_ref_head *btrfs_select_ref_head(
561561
struct btrfs_delayed_ref_root *delayed_refs)
562562
{
563563
struct btrfs_delayed_ref_head *head;
564+
bool locked;
564565

565-
lockdep_assert_held(&delayed_refs->lock);
566+
spin_lock(&delayed_refs->lock);
566567
again:
567568
head = find_ref_head(delayed_refs, delayed_refs->run_delayed_start,
568569
true);
569570
if (!head && delayed_refs->run_delayed_start != 0) {
570571
delayed_refs->run_delayed_start = 0;
571572
head = find_first_ref_head(delayed_refs);
572573
}
573-
if (!head)
574+
if (!head) {
575+
spin_unlock(&delayed_refs->lock);
574576
return NULL;
577+
}
575578

576579
while (head->processing) {
577580
struct rb_node *node;
578581

579582
node = rb_next(&head->href_node);
580583
if (!node) {
581-
if (delayed_refs->run_delayed_start == 0)
584+
if (delayed_refs->run_delayed_start == 0) {
585+
spin_unlock(&delayed_refs->lock);
582586
return NULL;
587+
}
583588
delayed_refs->run_delayed_start = 0;
584589
goto again;
585590
}
@@ -592,6 +597,18 @@ struct btrfs_delayed_ref_head *btrfs_select_ref_head(
592597
delayed_refs->num_heads_ready--;
593598
delayed_refs->run_delayed_start = head->bytenr +
594599
head->num_bytes;
600+
601+
locked = btrfs_delayed_ref_lock(delayed_refs, head);
602+
spin_unlock(&delayed_refs->lock);
603+
604+
/*
605+
* We may have dropped the spin lock to get the head mutex lock, and
606+
* that might have given someone else time to free the head. If that's
607+
* true, it has been removed from our list and we can move on.
608+
*/
609+
if (!locked)
610+
return ERR_PTR(-EAGAIN);
611+
595612
return head;
596613
}
597614

fs/btrfs/delayed-ref.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,6 @@ void btrfs_merge_delayed_refs(struct btrfs_fs_info *fs_info,
369369
struct btrfs_delayed_ref_head *
370370
btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs,
371371
u64 bytenr);
372-
bool btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs,
373-
struct btrfs_delayed_ref_head *head);
374372
static inline void btrfs_delayed_ref_unlock(struct btrfs_delayed_ref_head *head)
375373
{
376374
mutex_unlock(&head->mutex);

fs/btrfs/extent-tree.c

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,39 +1953,6 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
19531953
return ret;
19541954
}
19551955

1956-
static struct btrfs_delayed_ref_head *btrfs_obtain_ref_head(
1957-
struct btrfs_trans_handle *trans)
1958-
{
1959-
struct btrfs_delayed_ref_root *delayed_refs =
1960-
&trans->transaction->delayed_refs;
1961-
struct btrfs_delayed_ref_head *head = NULL;
1962-
bool locked;
1963-
1964-
spin_lock(&delayed_refs->lock);
1965-
head = btrfs_select_ref_head(delayed_refs);
1966-
if (!head) {
1967-
spin_unlock(&delayed_refs->lock);
1968-
return head;
1969-
}
1970-
1971-
/*
1972-
* Grab the lock that says we are going to process all the refs for
1973-
* this head
1974-
*/
1975-
locked = btrfs_delayed_ref_lock(delayed_refs, head);
1976-
spin_unlock(&delayed_refs->lock);
1977-
1978-
/*
1979-
* We may have dropped the spin lock to get the head mutex lock, and
1980-
* that might have given someone else time to free the head. If that's
1981-
* true, it has been removed from our list and we can move on.
1982-
*/
1983-
if (!locked)
1984-
head = ERR_PTR(-EAGAIN);
1985-
1986-
return head;
1987-
}
1988-
19891956
static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
19901957
struct btrfs_delayed_ref_head *locked_ref,
19911958
u64 *bytes_released)
@@ -2092,7 +2059,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
20922059

20932060
do {
20942061
if (!locked_ref) {
2095-
locked_ref = btrfs_obtain_ref_head(trans);
2062+
locked_ref = btrfs_select_ref_head(delayed_refs);
20962063
if (IS_ERR_OR_NULL(locked_ref)) {
20972064
if (PTR_ERR(locked_ref) == -EAGAIN) {
20982065
continue;

0 commit comments

Comments
 (0)