Skip to content

Commit bc83b4d

Browse files
committed
Merge tag 'bcachefs-2024-09-09' of git://evilpiepirate.org/bcachefs
Pull bcachefs fixes from Kent Overstreet: - fix ca->io_ref usage; analagous to previous patch doing that for main discard path - cond_resched() in __journal_keys_sort(), cutting down on "hung task" warnings when journal is big - rest of basic BCH_SB_MEMBER_INVALID support - and the critical one: don't delete open files in online fsck, this was causing the "dirent points to inode that doesn't point back" inconsistencies some users were seeing * tag 'bcachefs-2024-09-09' of git://evilpiepirate.org/bcachefs: bcachefs: Don't delete open files in online fsck bcachefs: fix btree_key_cache sysfs knob bcachefs: More BCH_SB_MEMBER_INVALID support bcachefs: Simplify bch2_bkey_drop_ptrs() bcachefs: Add a cond_resched() to __journal_keys_sort() bcachefs: Fix ca->io_ref usage
2 parents fb92a1f + 1600514 commit bc83b4d

File tree

11 files changed

+79
-52
lines changed

11 files changed

+79
-52
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,8 +1968,8 @@ static void bch2_do_discards_fast_work(struct work_struct *work)
19681968
break;
19691969
}
19701970

1971-
bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast);
19721971
percpu_ref_put(&ca->io_ref);
1972+
bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast);
19731973
}
19741974

19751975
static void bch2_discard_one_bucket_fast(struct bch_dev *ca, u64 bucket)
@@ -1979,18 +1979,18 @@ static void bch2_discard_one_bucket_fast(struct bch_dev *ca, u64 bucket)
19791979
if (discard_in_flight_add(ca, bucket, false))
19801980
return;
19811981

1982-
if (!bch2_dev_get_ioref(c, ca->dev_idx, WRITE))
1982+
if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_discard_fast))
19831983
return;
19841984

1985-
if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_discard_fast))
1986-
goto put_ioref;
1985+
if (!bch2_dev_get_ioref(c, ca->dev_idx, WRITE))
1986+
goto put_ref;
19871987

19881988
if (queue_work(c->write_ref_wq, &ca->discard_fast_work))
19891989
return;
19901990

1991-
bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast);
1992-
put_ioref:
19931991
percpu_ref_put(&ca->io_ref);
1992+
put_ref:
1993+
bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast);
19941994
}
19951995

19961996
static int invalidate_one_bucket(struct btree_trans *trans,
@@ -2132,26 +2132,26 @@ static void bch2_do_invalidates_work(struct work_struct *work)
21322132
bch2_trans_iter_exit(trans, &iter);
21332133
err:
21342134
bch2_trans_put(trans);
2135-
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
21362135
percpu_ref_put(&ca->io_ref);
2136+
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
21372137
}
21382138

21392139
void bch2_dev_do_invalidates(struct bch_dev *ca)
21402140
{
21412141
struct bch_fs *c = ca->fs;
21422142

2143-
if (!bch2_dev_get_ioref(c, ca->dev_idx, WRITE))
2143+
if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_invalidate))
21442144
return;
21452145

2146-
if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_invalidate))
2147-
goto put_ioref;
2146+
if (!bch2_dev_get_ioref(c, ca->dev_idx, WRITE))
2147+
goto put_ref;
21482148

21492149
if (queue_work(c->write_ref_wq, &ca->invalidate_work))
21502150
return;
21512151

2152-
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
2153-
put_ioref:
21542152
percpu_ref_put(&ca->io_ref);
2153+
put_ref:
2154+
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
21552155
}
21562156

21572157
void bch2_do_invalidates(struct bch_fs *c)

fs/bcachefs/btree_journal_iter.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@ static void __journal_keys_sort(struct journal_keys *keys)
530530
{
531531
sort(keys->data, keys->nr, sizeof(keys->data[0]), journal_sort_key_cmp, NULL);
532532

533+
cond_resched();
534+
533535
struct journal_key *dst = keys->data;
534536

535537
darray_for_each(*keys, src) {

fs/bcachefs/buckets.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,13 @@ static int bch2_check_fix_ptr(struct btree_trans *trans,
100100

101101
struct bch_dev *ca = bch2_dev_tryget(c, p.ptr.dev);
102102
if (!ca) {
103-
if (fsck_err(trans, ptr_to_invalid_device,
104-
"pointer to missing device %u\n"
105-
"while marking %s",
106-
p.ptr.dev,
107-
(printbuf_reset(&buf),
108-
bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
103+
if (fsck_err_on(p.ptr.dev != BCH_SB_MEMBER_INVALID,
104+
trans, ptr_to_invalid_device,
105+
"pointer to missing device %u\n"
106+
"while marking %s",
107+
p.ptr.dev,
108+
(printbuf_reset(&buf),
109+
bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
109110
*do_update = true;
110111
return 0;
111112
}
@@ -562,7 +563,7 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
562563
struct bch_fs *c = trans->c;
563564
struct bch_dev *ca = bch2_dev_tryget(c, p.ptr.dev);
564565
if (unlikely(!ca)) {
565-
if (insert)
566+
if (insert && p.ptr.dev != BCH_SB_MEMBER_INVALID)
566567
ret = -EIO;
567568
goto err;
568569
}

fs/bcachefs/ec.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ static inline bool __bch2_ptr_matches_stripe(const struct bch_extent_ptr *stripe
9797
const struct bch_extent_ptr *data_ptr,
9898
unsigned sectors)
9999
{
100-
return data_ptr->dev == stripe_ptr->dev &&
100+
return (data_ptr->dev == stripe_ptr->dev ||
101+
data_ptr->dev == BCH_SB_MEMBER_INVALID ||
102+
stripe_ptr->dev == BCH_SB_MEMBER_INVALID) &&
101103
data_ptr->gen == stripe_ptr->gen &&
102104
data_ptr->offset >= stripe_ptr->offset &&
103105
data_ptr->offset < stripe_ptr->offset + sectors;

fs/bcachefs/extents.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -781,14 +781,17 @@ static union bch_extent_entry *extent_entry_prev(struct bkey_ptrs ptrs,
781781
/*
782782
* Returns pointer to the next entry after the one being dropped:
783783
*/
784-
union bch_extent_entry *bch2_bkey_drop_ptr_noerror(struct bkey_s k,
785-
struct bch_extent_ptr *ptr)
784+
void bch2_bkey_drop_ptr_noerror(struct bkey_s k, struct bch_extent_ptr *ptr)
786785
{
787786
struct bkey_ptrs ptrs = bch2_bkey_ptrs(k);
788787
union bch_extent_entry *entry = to_entry(ptr), *next;
789-
union bch_extent_entry *ret = entry;
790788
bool drop_crc = true;
791789

790+
if (k.k->type == KEY_TYPE_stripe) {
791+
ptr->dev = BCH_SB_MEMBER_INVALID;
792+
return;
793+
}
794+
792795
EBUG_ON(ptr < &ptrs.start->ptr ||
793796
ptr >= &ptrs.end->ptr);
794797
EBUG_ON(ptr->type != 1 << BCH_EXTENT_ENTRY_ptr);
@@ -811,21 +814,16 @@ union bch_extent_entry *bch2_bkey_drop_ptr_noerror(struct bkey_s k,
811814
break;
812815

813816
if ((extent_entry_is_crc(entry) && drop_crc) ||
814-
extent_entry_is_stripe_ptr(entry)) {
815-
ret = (void *) ret - extent_entry_bytes(entry);
817+
extent_entry_is_stripe_ptr(entry))
816818
extent_entry_drop(k, entry);
817-
}
818819
}
819-
820-
return ret;
821820
}
822821

823-
union bch_extent_entry *bch2_bkey_drop_ptr(struct bkey_s k,
824-
struct bch_extent_ptr *ptr)
822+
void bch2_bkey_drop_ptr(struct bkey_s k, struct bch_extent_ptr *ptr)
825823
{
826824
bool have_dirty = bch2_bkey_dirty_devs(k.s_c).nr;
827-
union bch_extent_entry *ret =
828-
bch2_bkey_drop_ptr_noerror(k, ptr);
825+
826+
bch2_bkey_drop_ptr_noerror(k, ptr);
829827

830828
/*
831829
* If we deleted all the dirty pointers and there's still cached
@@ -837,14 +835,10 @@ union bch_extent_entry *bch2_bkey_drop_ptr(struct bkey_s k,
837835
!bch2_bkey_dirty_devs(k.s_c).nr) {
838836
k.k->type = KEY_TYPE_error;
839837
set_bkey_val_u64s(k.k, 0);
840-
ret = NULL;
841838
} else if (!bch2_bkey_nr_ptrs(k.s_c)) {
842839
k.k->type = KEY_TYPE_deleted;
843840
set_bkey_val_u64s(k.k, 0);
844-
ret = NULL;
845841
}
846-
847-
return ret;
848842
}
849843

850844
void bch2_bkey_drop_device(struct bkey_s k, unsigned dev)

fs/bcachefs/extents.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -649,26 +649,21 @@ static inline void bch2_bkey_append_ptr(struct bkey_i *k, struct bch_extent_ptr
649649

650650
void bch2_extent_ptr_decoded_append(struct bkey_i *,
651651
struct extent_ptr_decoded *);
652-
union bch_extent_entry *bch2_bkey_drop_ptr_noerror(struct bkey_s,
653-
struct bch_extent_ptr *);
654-
union bch_extent_entry *bch2_bkey_drop_ptr(struct bkey_s,
655-
struct bch_extent_ptr *);
652+
void bch2_bkey_drop_ptr_noerror(struct bkey_s, struct bch_extent_ptr *);
653+
void bch2_bkey_drop_ptr(struct bkey_s, struct bch_extent_ptr *);
656654

657655
#define bch2_bkey_drop_ptrs(_k, _ptr, _cond) \
658656
do { \
659-
struct bkey_ptrs _ptrs = bch2_bkey_ptrs(_k); \
657+
__label__ _again; \
658+
struct bkey_ptrs _ptrs; \
659+
_again: \
660+
_ptrs = bch2_bkey_ptrs(_k); \
660661
\
661-
struct bch_extent_ptr *_ptr = &_ptrs.start->ptr; \
662-
\
663-
while ((_ptr = bkey_ptr_next(_ptrs, _ptr))) { \
662+
bkey_for_each_ptr(_ptrs, _ptr) \
664663
if (_cond) { \
665-
_ptr = (void *) bch2_bkey_drop_ptr(_k, _ptr); \
666-
_ptrs = bch2_bkey_ptrs(_k); \
667-
continue; \
664+
bch2_bkey_drop_ptr(_k, _ptr); \
665+
goto _again; \
668666
} \
669-
\
670-
(_ptr)++; \
671-
} \
672667
} while (0)
673668

674669
bool bch2_bkey_matches_ptr(struct bch_fs *, struct bkey_s_c,

fs/bcachefs/fs.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ static unsigned bch2_inode_hash(subvol_inum inum)
177177
return jhash_3words(inum.subvol, inum.inum >> 32, inum.inum, JHASH_INITVAL);
178178
}
179179

180+
struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
181+
{
182+
return to_bch_ei(ilookup5_nowait(c->vfs_sb,
183+
bch2_inode_hash(inum),
184+
bch2_iget5_test,
185+
&inum));
186+
}
187+
180188
static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_inode_info *inode)
181189
{
182190
subvol_inum inum = inode_inum(inode);

fs/bcachefs/fs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ static inline subvol_inum inode_inum(struct bch_inode_info *inode)
5656
};
5757
}
5858

59+
struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *, subvol_inum);
60+
5961
/*
6062
* Set if we've gotten a btree error for this inode, and thus the vfs inode and
6163
* btree inode may be inconsistent:
@@ -194,6 +196,11 @@ int bch2_vfs_init(void);
194196

195197
#define bch2_inode_update_after_write(_trans, _inode, _inode_u, _fields) ({ do {} while (0); })
196198

199+
static inline struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
200+
{
201+
return NULL;
202+
}
203+
197204
static inline void bch2_evict_subvolume_inodes(struct bch_fs *c,
198205
snapshot_id_list *s) {}
199206
static inline void bch2_vfs_exit(void) {}

fs/bcachefs/fsck.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "darray.h"
99
#include "dirent.h"
1010
#include "error.h"
11+
#include "fs.h"
1112
#include "fs-common.h"
1213
#include "fsck.h"
1314
#include "inode.h"
@@ -962,6 +963,22 @@ static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c i
962963
return ret;
963964
}
964965

966+
static bool bch2_inode_open(struct bch_fs *c, struct bpos p)
967+
{
968+
subvol_inum inum = {
969+
.subvol = snapshot_t(c, p.snapshot)->subvol,
970+
.inum = p.offset,
971+
};
972+
973+
/* snapshot tree corruption, can't safely delete */
974+
if (!inum.subvol) {
975+
bch_err_ratelimited(c, "%s(): snapshot %u has no subvol", __func__, p.snapshot);
976+
return true;
977+
}
978+
979+
return __bch2_inode_hash_find(c, inum) != NULL;
980+
}
981+
965982
static int check_inode(struct btree_trans *trans,
966983
struct btree_iter *iter,
967984
struct bkey_s_c k,
@@ -1040,6 +1057,7 @@ static int check_inode(struct btree_trans *trans,
10401057
}
10411058

10421059
if (u.bi_flags & BCH_INODE_unlinked &&
1060+
!bch2_inode_open(c, k.k->p) &&
10431061
(!c->sb.clean ||
10441062
fsck_err(trans, inode_unlinked_but_clean,
10451063
"filesystem marked clean, but inode %llu unlinked",

fs/bcachefs/replicas.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ bool bch2_have_enough_devs(struct bch_fs *c, struct bch_devs_mask devs,
796796
nr_online += test_bit(e->devs[i], devs.d);
797797

798798
struct bch_dev *ca = bch2_dev_rcu(c, e->devs[i]);
799-
nr_failed += ca && ca->mi.state == BCH_MEMBER_STATE_failed;
799+
nr_failed += !ca || ca->mi.state == BCH_MEMBER_STATE_failed;
800800
}
801801
rcu_read_unlock();
802802

0 commit comments

Comments
 (0)