mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-22 00:00:03 +03:00
Update bcachefs sources to 25de2b00dc bcachefs: Change check for invalid key types
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
619c99de4b
commit
c99a444c5c
@ -1 +1 @@
|
|||||||
84f132d5696138bb038d2dc8f1162d2fab5ac832
|
25de2b00dcca9bd801d37efd5e08c15dbf151825
|
||||||
|
@ -84,7 +84,7 @@ static void dump_one_device(struct bch_fs *c, struct bch_dev *ca, int fd,
|
|||||||
if (ret)
|
if (ret)
|
||||||
die("error %s walking btree nodes", bch2_err_str(ret));
|
die("error %s walking btree nodes", bch2_err_str(ret));
|
||||||
|
|
||||||
b = c->btree_roots[i].b;
|
b = bch2_btree_id_root(c, i)->b;
|
||||||
if (!btree_node_fake(b)) {
|
if (!btree_node_fake(b)) {
|
||||||
ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
|
ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct bio *bio_alloc_bioset(struct block_device *, unsigned,
|
struct bio *bio_alloc_bioset(struct block_device *, unsigned,
|
||||||
unsigned, gfp_t, struct bio_set *);
|
blk_opf_t, gfp_t, struct bio_set *);
|
||||||
extern void bio_put(struct bio *);
|
extern void bio_put(struct bio *);
|
||||||
|
|
||||||
int bio_add_page(struct bio *, struct page *, unsigned, unsigned);
|
int bio_add_page(struct bio *, struct page *, unsigned, unsigned);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define BIO_MAX_VECS 256U
|
#define BIO_MAX_VECS 256U
|
||||||
|
|
||||||
typedef unsigned fmode_t;
|
typedef unsigned fmode_t;
|
||||||
|
typedef __u32 __bitwise blk_opf_t;
|
||||||
|
|
||||||
struct bio;
|
struct bio;
|
||||||
struct user_namespace;
|
struct user_namespace;
|
||||||
|
@ -225,6 +225,7 @@ struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap,
|
|||||||
struct bch_inode_info *inode = to_bch_ei(dentry->d_inode);
|
struct bch_inode_info *inode = to_bch_ei(dentry->d_inode);
|
||||||
struct bch_fs *c = inode->v.i_sb->s_fs_info;
|
struct bch_fs *c = inode->v.i_sb->s_fs_info;
|
||||||
struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode);
|
struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode);
|
||||||
|
struct xattr_search_key search = X_SEARCH(acl_to_xattr_type(type), "", 0);
|
||||||
struct btree_trans trans;
|
struct btree_trans trans;
|
||||||
struct btree_iter iter = { NULL };
|
struct btree_iter iter = { NULL };
|
||||||
struct bkey_s_c_xattr xattr;
|
struct bkey_s_c_xattr xattr;
|
||||||
@ -237,9 +238,7 @@ retry:
|
|||||||
bch2_trans_begin(&trans);
|
bch2_trans_begin(&trans);
|
||||||
|
|
||||||
ret = bch2_hash_lookup(&trans, &iter, bch2_xattr_hash_desc,
|
ret = bch2_hash_lookup(&trans, &iter, bch2_xattr_hash_desc,
|
||||||
&hash, inode_inum(inode),
|
&hash, inode_inum(inode), &search, 0);
|
||||||
&X_SEARCH(acl_to_xattr_type(type), "", 0),
|
|
||||||
0);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (!bch2_err_matches(ret, ENOENT))
|
if (!bch2_err_matches(ret, ENOENT))
|
||||||
acl = ERR_PTR(ret);
|
acl = ERR_PTR(ret);
|
||||||
@ -364,6 +363,7 @@ int bch2_acl_chmod(struct btree_trans *trans, subvol_inum inum,
|
|||||||
struct posix_acl **new_acl)
|
struct posix_acl **new_acl)
|
||||||
{
|
{
|
||||||
struct bch_hash_info hash_info = bch2_hash_info_init(trans->c, inode);
|
struct bch_hash_info hash_info = bch2_hash_info_init(trans->c, inode);
|
||||||
|
struct xattr_search_key search = X_SEARCH(KEY_TYPE_XATTR_INDEX_POSIX_ACL_ACCESS, "", 0);
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
struct bkey_s_c_xattr xattr;
|
struct bkey_s_c_xattr xattr;
|
||||||
struct bkey_i_xattr *new;
|
struct bkey_i_xattr *new;
|
||||||
@ -372,9 +372,7 @@ int bch2_acl_chmod(struct btree_trans *trans, subvol_inum inum,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc,
|
ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc,
|
||||||
&hash_info, inum,
|
&hash_info, inum, &search, BTREE_ITER_INTENT);
|
||||||
&X_SEARCH(KEY_TYPE_XATTR_INDEX_POSIX_ACL_ACCESS, "", 0),
|
|
||||||
BTREE_ITER_INTENT);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return bch2_err_matches(ret, ENOENT) ? 0 : ret;
|
return bch2_err_matches(ret, ENOENT) ? 0 : ret;
|
||||||
|
|
||||||
|
@ -223,7 +223,8 @@ static unsigned bch_alloc_v1_val_u64s(const struct bch_alloc *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_alloc_v1_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_alloc_v1_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_alloc a = bkey_s_c_to_alloc(k);
|
struct bkey_s_c_alloc a = bkey_s_c_to_alloc(k);
|
||||||
|
|
||||||
@ -238,7 +239,8 @@ int bch2_alloc_v1_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_alloc_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_alloc_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_alloc_unpacked u;
|
struct bkey_alloc_unpacked u;
|
||||||
|
|
||||||
@ -251,7 +253,8 @@ int bch2_alloc_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_alloc_v3_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_alloc_v3_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_alloc_unpacked u;
|
struct bkey_alloc_unpacked u;
|
||||||
|
|
||||||
@ -282,7 +285,7 @@ int bch2_alloc_v4_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rw == WRITE &&
|
if (rw == WRITE &&
|
||||||
!(flags & BKEY_INVALID_FROM_JOURNAL) &&
|
!(flags & BKEY_INVALID_JOURNAL) &&
|
||||||
test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) {
|
test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) {
|
||||||
unsigned i, bp_len = 0;
|
unsigned i, bp_len = 0;
|
||||||
|
|
||||||
@ -605,7 +608,8 @@ static unsigned alloc_gen(struct bkey_s_c k, unsigned offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_bucket_gens_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_bucket_gens_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (bkey_val_bytes(k.k) != sizeof(struct bch_bucket_gens)) {
|
if (bkey_val_bytes(k.k) != sizeof(struct bch_bucket_gens)) {
|
||||||
prt_printf(err, "bad val size (%lu != %zu)",
|
prt_printf(err, "bad val size (%lu != %zu)",
|
||||||
@ -929,7 +933,7 @@ int bch2_trans_mark_alloc(struct btree_trans *trans,
|
|||||||
* This synthesizes deleted extents for holes, similar to BTREE_ITER_SLOTS for
|
* This synthesizes deleted extents for holes, similar to BTREE_ITER_SLOTS for
|
||||||
* extents style btrees, but works on non-extents btrees:
|
* extents style btrees, but works on non-extents btrees:
|
||||||
*/
|
*/
|
||||||
struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos end, struct bkey *hole)
|
static struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos end, struct bkey *hole)
|
||||||
{
|
{
|
||||||
struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
|
struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
|
||||||
|
|
||||||
@ -1000,7 +1004,7 @@ static bool next_bucket(struct bch_fs *c, struct bpos *bucket)
|
|||||||
return ca != NULL;
|
return ca != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_iter *iter, struct bkey *hole)
|
static struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_iter *iter, struct bkey *hole)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = iter->trans->c;
|
struct bch_fs *c = iter->trans->c;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
@ -1719,7 +1723,8 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
|
|||||||
write:
|
write:
|
||||||
ret = bch2_trans_update(trans, &iter, &a->k_i, 0) ?:
|
ret = bch2_trans_update(trans, &iter, &a->k_i, 0) ?:
|
||||||
bch2_trans_commit(trans, NULL, NULL,
|
bch2_trans_commit(trans, NULL, NULL,
|
||||||
BTREE_INSERT_USE_RESERVE|BTREE_INSERT_NOFAIL);
|
BCH_WATERMARK_btree|
|
||||||
|
BTREE_INSERT_NOFAIL);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -1827,7 +1832,8 @@ static int invalidate_one_bucket(struct btree_trans *trans,
|
|||||||
ret = bch2_trans_update(trans, &alloc_iter, &a->k_i,
|
ret = bch2_trans_update(trans, &alloc_iter, &a->k_i,
|
||||||
BTREE_TRIGGER_BUCKET_INVALIDATE) ?:
|
BTREE_TRIGGER_BUCKET_INVALIDATE) ?:
|
||||||
bch2_trans_commit(trans, NULL, NULL,
|
bch2_trans_commit(trans, NULL, NULL,
|
||||||
BTREE_INSERT_USE_RESERVE|BTREE_INSERT_NOFAIL);
|
BCH_WATERMARK_btree|
|
||||||
|
BTREE_INSERT_NOFAIL);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "super.h"
|
#include "super.h"
|
||||||
|
|
||||||
|
enum bkey_invalid_flags;
|
||||||
|
|
||||||
/* How out of date a pointer gen is allowed to be: */
|
/* How out of date a pointer gen is allowed to be: */
|
||||||
#define BUCKET_GC_GEN_MAX 96U
|
#define BUCKET_GC_GEN_MAX 96U
|
||||||
|
|
||||||
@ -147,10 +149,14 @@ struct bkey_i_alloc_v4 *bch2_alloc_to_v4_mut(struct btree_trans *, struct bkey_s
|
|||||||
|
|
||||||
int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
|
int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
|
||||||
|
|
||||||
int bch2_alloc_v1_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_alloc_v1_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
int bch2_alloc_v2_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
int bch2_alloc_v3_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_alloc_v2_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
int bch2_alloc_v4_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
|
int bch2_alloc_v3_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
|
int bch2_alloc_v4_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_alloc_v4_swab(struct bkey_s);
|
void bch2_alloc_v4_swab(struct bkey_s);
|
||||||
void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
@ -187,7 +193,8 @@ void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
|||||||
.min_val_size = 48, \
|
.min_val_size = 48, \
|
||||||
})
|
})
|
||||||
|
|
||||||
int bch2_bucket_gens_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_bucket_gens_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_bucket_gens_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_bucket_gens_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
#define bch2_bkey_ops_bucket_gens ((struct bkey_ops) { \
|
#define bch2_bkey_ops_bucket_gens ((struct bkey_ops) { \
|
||||||
|
@ -191,11 +191,12 @@ long bch2_bucket_alloc_new_fs(struct bch_dev *ca)
|
|||||||
static inline unsigned open_buckets_reserved(enum bch_watermark watermark)
|
static inline unsigned open_buckets_reserved(enum bch_watermark watermark)
|
||||||
{
|
{
|
||||||
switch (watermark) {
|
switch (watermark) {
|
||||||
|
case BCH_WATERMARK_reclaim:
|
||||||
case BCH_WATERMARK_btree:
|
case BCH_WATERMARK_btree:
|
||||||
case BCH_WATERMARK_btree_copygc:
|
case BCH_WATERMARK_btree_copygc:
|
||||||
return 0;
|
|
||||||
case BCH_WATERMARK_copygc:
|
|
||||||
return OPEN_BUCKETS_COUNT / 4;
|
return OPEN_BUCKETS_COUNT / 4;
|
||||||
|
case BCH_WATERMARK_copygc:
|
||||||
|
return OPEN_BUCKETS_COUNT / 3;
|
||||||
default:
|
default:
|
||||||
return OPEN_BUCKETS_COUNT / 2;
|
return OPEN_BUCKETS_COUNT / 2;
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,12 @@ struct bucket_alloc_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define BCH_WATERMARKS() \
|
#define BCH_WATERMARKS() \
|
||||||
x(btree_copygc) \
|
x(stripe) \
|
||||||
x(btree) \
|
|
||||||
x(copygc) \
|
|
||||||
x(normal) \
|
x(normal) \
|
||||||
x(stripe)
|
x(copygc) \
|
||||||
|
x(btree) \
|
||||||
|
x(btree_copygc) \
|
||||||
|
x(reclaim)
|
||||||
|
|
||||||
enum bch_watermark {
|
enum bch_watermark {
|
||||||
#define x(name) BCH_WATERMARK_##name,
|
#define x(name) BCH_WATERMARK_##name,
|
||||||
@ -30,6 +31,9 @@ enum bch_watermark {
|
|||||||
BCH_WATERMARK_NR,
|
BCH_WATERMARK_NR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BCH_WATERMARK_BITS 3
|
||||||
|
#define BCH_WATERMARK_MASK ~(~0 << BCH_WATERMARK_BITS)
|
||||||
|
|
||||||
#define OPEN_BUCKETS_COUNT 1024
|
#define OPEN_BUCKETS_COUNT 1024
|
||||||
|
|
||||||
#define WRITE_POINT_HASH_NR 32
|
#define WRITE_POINT_HASH_NR 32
|
||||||
|
@ -38,7 +38,8 @@ static bool extent_matches_bp(struct bch_fs *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_backpointer_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_backpointer_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
|
struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
|
||||||
struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
|
struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
|
||||||
@ -272,6 +273,7 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
|
|||||||
unsigned iter_flags)
|
unsigned iter_flags)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
|
struct btree_root *r = bch2_btree_id_root(c, bp.btree_id);
|
||||||
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
|
struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
|
|
||||||
@ -279,7 +281,7 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
|
|||||||
bp.btree_id,
|
bp.btree_id,
|
||||||
bp.pos,
|
bp.pos,
|
||||||
0,
|
0,
|
||||||
min(bp.level, c->btree_roots[bp.btree_id].level),
|
min(bp.level, r->level),
|
||||||
iter_flags);
|
iter_flags);
|
||||||
k = bch2_btree_iter_peek_slot(iter);
|
k = bch2_btree_iter_peek_slot(iter);
|
||||||
if (bkey_err(k)) {
|
if (bkey_err(k)) {
|
||||||
@ -287,8 +289,8 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
|
|||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bp.level == c->btree_roots[bp.btree_id].level + 1)
|
if (bp.level == r->level + 1)
|
||||||
k = bkey_i_to_s_c(&c->btree_roots[bp.btree_id].key);
|
k = bkey_i_to_s_c(&r->key);
|
||||||
|
|
||||||
if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp))
|
if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp))
|
||||||
return k;
|
return k;
|
||||||
@ -531,6 +533,7 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
|
|||||||
struct bpos_level *last_flushed)
|
struct bpos_level *last_flushed)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
|
struct btree_root *r = bch2_btree_id_root(c, btree_id);
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
struct btree *b;
|
struct btree *b;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
@ -539,8 +542,7 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
|
|||||||
const union bch_extent_entry *entry;
|
const union bch_extent_entry *entry;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
|
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0, r->level, 0);
|
||||||
c->btree_roots[btree_id].level, 0);
|
|
||||||
b = bch2_btree_iter_peek_node(&iter);
|
b = bch2_btree_iter_peek_node(&iter);
|
||||||
ret = PTR_ERR_OR_ZERO(b);
|
ret = PTR_ERR_OR_ZERO(b);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -589,10 +591,10 @@ static size_t btree_nodes_fit_in_ram(struct bch_fs *c)
|
|||||||
return div_u64(mem_bytes >> 1, btree_bytes(c));
|
return div_u64(mem_bytes >> 1, btree_bytes(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
|
static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
|
||||||
unsigned btree_leaf_mask,
|
unsigned btree_leaf_mask,
|
||||||
unsigned btree_interior_mask,
|
unsigned btree_interior_mask,
|
||||||
struct bbpos start, struct bbpos *end)
|
struct bbpos start, struct bbpos *end)
|
||||||
{
|
{
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
@ -640,14 +642,18 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
|
|||||||
struct bpos bucket_start,
|
struct bpos bucket_start,
|
||||||
struct bpos bucket_end)
|
struct bpos bucket_end)
|
||||||
{
|
{
|
||||||
|
struct bch_fs *c = trans->c;
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
enum btree_id btree_id;
|
enum btree_id btree_id;
|
||||||
struct bpos_level last_flushed = { UINT_MAX };
|
struct bpos_level last_flushed = { UINT_MAX };
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
for (btree_id = 0; btree_id < BTREE_ID_NR; btree_id++) {
|
for (btree_id = 0; btree_id < btree_id_nr_alive(c); btree_id++) {
|
||||||
unsigned depth = btree_type_has_ptrs(btree_id) ? 0 : 1;
|
unsigned depth = btree_type_has_ptrs(btree_id) ? 0 : 1;
|
||||||
|
|
||||||
|
if (!bch2_btree_id_root(c, btree_id)->alive)
|
||||||
|
continue;
|
||||||
|
|
||||||
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
|
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
|
||||||
depth,
|
depth,
|
||||||
BTREE_ITER_ALL_LEVELS|
|
BTREE_ITER_ALL_LEVELS|
|
||||||
@ -689,8 +695,8 @@ static struct bpos bucket_pos_to_bp_safe(const struct bch_fs *c,
|
|||||||
: bucket;
|
: bucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bch2_get_alloc_in_memory_pos(struct btree_trans *trans,
|
static int bch2_get_alloc_in_memory_pos(struct btree_trans *trans,
|
||||||
struct bpos start, struct bpos *end)
|
struct bpos start, struct bpos *end)
|
||||||
{
|
{
|
||||||
struct btree_iter alloc_iter;
|
struct btree_iter alloc_iter;
|
||||||
struct btree_iter bp_iter;
|
struct btree_iter bp_iter;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "super.h"
|
#include "super.h"
|
||||||
|
|
||||||
int bch2_backpointer_invalid(const struct bch_fs *, struct bkey_s_c k,
|
int bch2_backpointer_invalid(const struct bch_fs *, struct bkey_s_c k,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_backpointer_to_text(struct printbuf *, const struct bch_backpointer *);
|
void bch2_backpointer_to_text(struct printbuf *, const struct bch_backpointer *);
|
||||||
void bch2_backpointer_k_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_backpointer_k_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
void bch2_backpointer_swab(struct bkey_s);
|
void bch2_backpointer_swab(struct bkey_s);
|
||||||
|
@ -749,7 +749,8 @@ struct bch_fs {
|
|||||||
struct bio_set btree_bio;
|
struct bio_set btree_bio;
|
||||||
struct workqueue_struct *io_complete_wq;
|
struct workqueue_struct *io_complete_wq;
|
||||||
|
|
||||||
struct btree_root btree_roots[BTREE_ID_NR];
|
struct btree_root btree_roots_known[BTREE_ID_NR];
|
||||||
|
DARRAY(struct btree_root) btree_roots_extra;
|
||||||
struct mutex btree_root_lock;
|
struct mutex btree_root_lock;
|
||||||
|
|
||||||
struct btree_cache btree_cache;
|
struct btree_cache btree_cache;
|
||||||
|
@ -488,8 +488,9 @@ struct bch_csum {
|
|||||||
x(crc32, 1) \
|
x(crc32, 1) \
|
||||||
x(crc64, 2) \
|
x(crc64, 2) \
|
||||||
x(crc128, 3) \
|
x(crc128, 3) \
|
||||||
x(stripe_ptr, 4)
|
x(stripe_ptr, 4) \
|
||||||
#define BCH_EXTENT_ENTRY_MAX 5
|
x(rebalance, 5)
|
||||||
|
#define BCH_EXTENT_ENTRY_MAX 6
|
||||||
|
|
||||||
enum bch_extent_entry_type {
|
enum bch_extent_entry_type {
|
||||||
#define x(f, n) BCH_EXTENT_ENTRY_##f = n,
|
#define x(f, n) BCH_EXTENT_ENTRY_##f = n,
|
||||||
@ -624,6 +625,20 @@ struct bch_extent_reservation {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bch_extent_rebalance {
|
||||||
|
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||||
|
__u64 type:7,
|
||||||
|
unused:33,
|
||||||
|
compression:8,
|
||||||
|
target:16;
|
||||||
|
#elif defined (__BIG_ENDIAN_BITFIELD)
|
||||||
|
__u64 target:16,
|
||||||
|
compression:8,
|
||||||
|
unused:33,
|
||||||
|
type:7;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
union bch_extent_entry {
|
union bch_extent_entry {
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || __BITS_PER_LONG == 64
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || __BITS_PER_LONG == 64
|
||||||
unsigned long type;
|
unsigned long type;
|
||||||
@ -1356,19 +1371,19 @@ static inline bool data_type_is_hidden(enum bch_data_type type)
|
|||||||
struct bch_replicas_entry_v0 {
|
struct bch_replicas_entry_v0 {
|
||||||
__u8 data_type;
|
__u8 data_type;
|
||||||
__u8 nr_devs;
|
__u8 nr_devs;
|
||||||
__u8 devs[];
|
__u8 devs[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct bch_sb_field_replicas_v0 {
|
struct bch_sb_field_replicas_v0 {
|
||||||
struct bch_sb_field field;
|
struct bch_sb_field field;
|
||||||
struct bch_replicas_entry_v0 entries[];
|
struct bch_replicas_entry_v0 entries[0];
|
||||||
} __packed __aligned(8);
|
} __packed __aligned(8);
|
||||||
|
|
||||||
struct bch_replicas_entry {
|
struct bch_replicas_entry {
|
||||||
__u8 data_type;
|
__u8 data_type;
|
||||||
__u8 nr_devs;
|
__u8 nr_devs;
|
||||||
__u8 nr_required;
|
__u8 nr_required;
|
||||||
__u8 devs[];
|
__u8 devs[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define replicas_entry_bytes(_i) \
|
#define replicas_entry_bytes(_i) \
|
||||||
@ -1376,7 +1391,7 @@ struct bch_replicas_entry {
|
|||||||
|
|
||||||
struct bch_sb_field_replicas {
|
struct bch_sb_field_replicas {
|
||||||
struct bch_sb_field field;
|
struct bch_sb_field field;
|
||||||
struct bch_replicas_entry entries[];
|
struct bch_replicas_entry entries[0];
|
||||||
} __packed __aligned(8);
|
} __packed __aligned(8);
|
||||||
|
|
||||||
/* BCH_SB_FIELD_quota: */
|
/* BCH_SB_FIELD_quota: */
|
||||||
@ -1559,8 +1574,6 @@ struct bch_sb_field_journal_seq_blacklist {
|
|||||||
* One common version number for all on disk data structures - superblock, btree
|
* One common version number for all on disk data structures - superblock, btree
|
||||||
* nodes, journal entries
|
* nodes, journal entries
|
||||||
*/
|
*/
|
||||||
#define BCH_JSET_VERSION_OLD 2
|
|
||||||
#define BCH_BSET_VERSION_OLD 3
|
|
||||||
|
|
||||||
#define BCH_METADATA_VERSIONS() \
|
#define BCH_METADATA_VERSIONS() \
|
||||||
x(bkey_renumber, 10) \
|
x(bkey_renumber, 10) \
|
||||||
@ -2195,13 +2208,25 @@ struct btree_node {
|
|||||||
};
|
};
|
||||||
} __packed __aligned(8);
|
} __packed __aligned(8);
|
||||||
|
|
||||||
LE64_BITMASK(BTREE_NODE_ID, struct btree_node, flags, 0, 4);
|
LE64_BITMASK(BTREE_NODE_ID_LO, struct btree_node, flags, 0, 4);
|
||||||
LE64_BITMASK(BTREE_NODE_LEVEL, struct btree_node, flags, 4, 8);
|
LE64_BITMASK(BTREE_NODE_LEVEL, struct btree_node, flags, 4, 8);
|
||||||
LE64_BITMASK(BTREE_NODE_NEW_EXTENT_OVERWRITE,
|
LE64_BITMASK(BTREE_NODE_NEW_EXTENT_OVERWRITE,
|
||||||
struct btree_node, flags, 8, 9);
|
struct btree_node, flags, 8, 9);
|
||||||
/* 9-32 unused */
|
LE64_BITMASK(BTREE_NODE_ID_HI, struct btree_node, flags, 9, 25);
|
||||||
|
/* 25-32 unused */
|
||||||
LE64_BITMASK(BTREE_NODE_SEQ, struct btree_node, flags, 32, 64);
|
LE64_BITMASK(BTREE_NODE_SEQ, struct btree_node, flags, 32, 64);
|
||||||
|
|
||||||
|
static inline __u64 BTREE_NODE_ID(struct btree_node *n)
|
||||||
|
{
|
||||||
|
return BTREE_NODE_ID_LO(n) | (BTREE_NODE_ID_HI(n) << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void SET_BTREE_NODE_ID(struct btree_node *n, u64 v)
|
||||||
|
{
|
||||||
|
SET_BTREE_NODE_ID_LO(n, v);
|
||||||
|
SET_BTREE_NODE_ID_HI(n, v >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
struct btree_node_entry {
|
struct btree_node_entry {
|
||||||
struct bch_csum csum;
|
struct bch_csum csum;
|
||||||
|
|
||||||
@ -2211,7 +2236,6 @@ struct btree_node_entry {
|
|||||||
__u8 pad[22];
|
__u8 pad[22];
|
||||||
__le16 u64s;
|
__le16 u64s;
|
||||||
__u64 _data[0];
|
__u64 _data[0];
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} __packed __aligned(8);
|
} __packed __aligned(8);
|
||||||
|
@ -118,17 +118,15 @@ const struct bkey_ops bch2_bkey_ops[] = {
|
|||||||
#undef x
|
#undef x
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct bkey_ops bch2_bkey_null_ops = {
|
||||||
|
.min_val_size = U8_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k,
|
int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
const struct bkey_ops *ops;
|
const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
|
||||||
|
|
||||||
if (k.k->type >= KEY_TYPE_MAX) {
|
|
||||||
prt_printf(err, "invalid type (%u >= %u)", k.k->type, KEY_TYPE_MAX);
|
|
||||||
return -BCH_ERR_invalid_bkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
ops = &bch2_bkey_ops[k.k->type];
|
|
||||||
|
|
||||||
if (bkey_val_bytes(k.k) < ops->min_val_size) {
|
if (bkey_val_bytes(k.k) < ops->min_val_size) {
|
||||||
prt_printf(err, "bad val size (%zu < %u)",
|
prt_printf(err, "bad val size (%zu < %u)",
|
||||||
@ -136,6 +134,9 @@ int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k,
|
|||||||
return -BCH_ERR_invalid_bkey;
|
return -BCH_ERR_invalid_bkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ops->key_invalid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return ops->key_invalid(c, k, flags, err);
|
return ops->key_invalid(c, k, flags, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,14 +216,16 @@ static unsigned bch2_key_types_allowed[] = {
|
|||||||
|
|
||||||
int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
|
int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
|
||||||
enum btree_node_type type,
|
enum btree_node_type type,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (k.k->u64s < BKEY_U64s) {
|
if (k.k->u64s < BKEY_U64s) {
|
||||||
prt_printf(err, "u64s too small (%u < %zu)", k.k->u64s, BKEY_U64s);
|
prt_printf(err, "u64s too small (%u < %zu)", k.k->u64s, BKEY_U64s);
|
||||||
return -BCH_ERR_invalid_bkey;
|
return -BCH_ERR_invalid_bkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(bch2_key_types_allowed[type] & (1U << k.k->type))) {
|
if (flags & BKEY_INVALID_COMMIT &&
|
||||||
|
!(bch2_key_types_allowed[type] & (1U << k.k->type))) {
|
||||||
prt_printf(err, "invalid key type for btree %s (%s)",
|
prt_printf(err, "invalid key type for btree %s (%s)",
|
||||||
bch2_btree_ids[type], bch2_bkey_types[k.k->type]);
|
bch2_btree_ids[type], bch2_bkey_types[k.k->type]);
|
||||||
return -BCH_ERR_invalid_bkey;
|
return -BCH_ERR_invalid_bkey;
|
||||||
@ -246,24 +249,23 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != BKEY_TYPE_btree &&
|
if (type != BKEY_TYPE_btree) {
|
||||||
!btree_type_has_snapshots(type) &&
|
if (!btree_type_has_snapshots((enum btree_id) type) &&
|
||||||
k.k->p.snapshot) {
|
k.k->p.snapshot) {
|
||||||
prt_printf(err, "nonzero snapshot");
|
prt_printf(err, "nonzero snapshot");
|
||||||
return -BCH_ERR_invalid_bkey;
|
return -BCH_ERR_invalid_bkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != BKEY_TYPE_btree &&
|
if (btree_type_has_snapshots((enum btree_id) type) &&
|
||||||
btree_type_has_snapshots(type) &&
|
!k.k->p.snapshot) {
|
||||||
!k.k->p.snapshot) {
|
prt_printf(err, "snapshot == 0");
|
||||||
prt_printf(err, "snapshot == 0");
|
return -BCH_ERR_invalid_bkey;
|
||||||
return -BCH_ERR_invalid_bkey;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (type != BKEY_TYPE_btree &&
|
if (bkey_eq(k.k->p, POS_MAX)) {
|
||||||
bkey_eq(k.k->p, POS_MAX)) {
|
prt_printf(err, "key at POS_MAX");
|
||||||
prt_printf(err, "key at POS_MAX");
|
return -BCH_ERR_invalid_bkey;
|
||||||
return -BCH_ERR_invalid_bkey;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -271,7 +273,8 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
|
|||||||
|
|
||||||
int bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
|
int bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
|
||||||
enum btree_node_type type,
|
enum btree_node_type type,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
return __bch2_bkey_invalid(c, k, type, flags, err) ?:
|
return __bch2_bkey_invalid(c, k, type, flags, err) ?:
|
||||||
bch2_bkey_val_invalid(c, k, flags, err);
|
bch2_bkey_val_invalid(c, k, flags, err);
|
||||||
@ -340,14 +343,10 @@ void bch2_bkey_to_text(struct printbuf *out, const struct bkey *k)
|
|||||||
void bch2_val_to_text(struct printbuf *out, struct bch_fs *c,
|
void bch2_val_to_text(struct printbuf *out, struct bch_fs *c,
|
||||||
struct bkey_s_c k)
|
struct bkey_s_c k)
|
||||||
{
|
{
|
||||||
if (k.k->type < KEY_TYPE_MAX) {
|
const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
|
||||||
const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
|
|
||||||
|
|
||||||
if (likely(ops->val_to_text))
|
if (likely(ops->val_to_text))
|
||||||
ops->val_to_text(out, c, k);
|
ops->val_to_text(out, c, k);
|
||||||
} else {
|
|
||||||
prt_printf(out, "(invalid type %u)", k.k->type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
|
void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
|
||||||
@ -363,7 +362,7 @@ void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
|
|||||||
|
|
||||||
void bch2_bkey_swab_val(struct bkey_s k)
|
void bch2_bkey_swab_val(struct bkey_s k)
|
||||||
{
|
{
|
||||||
const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
|
const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
|
||||||
|
|
||||||
if (ops->swab)
|
if (ops->swab)
|
||||||
ops->swab(k);
|
ops->swab(k);
|
||||||
@ -371,7 +370,7 @@ void bch2_bkey_swab_val(struct bkey_s k)
|
|||||||
|
|
||||||
bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
|
bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
|
||||||
{
|
{
|
||||||
const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
|
const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
|
||||||
|
|
||||||
return ops->key_normalize
|
return ops->key_normalize
|
||||||
? ops->key_normalize(c, k)
|
? ops->key_normalize(c, k)
|
||||||
@ -380,11 +379,11 @@ bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
|
|||||||
|
|
||||||
bool bch2_bkey_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
|
bool bch2_bkey_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
|
||||||
{
|
{
|
||||||
const struct bkey_ops *ops = &bch2_bkey_ops[l.k->type];
|
const struct bkey_ops *ops = bch2_bkey_type_ops(l.k->type);
|
||||||
|
|
||||||
return bch2_bkey_maybe_mergable(l.k, r.k) &&
|
return ops->key_merge &&
|
||||||
|
bch2_bkey_maybe_mergable(l.k, r.k) &&
|
||||||
(u64) l.k->size + r.k->size <= KEY_SIZE_MAX &&
|
(u64) l.k->size + r.k->size <= KEY_SIZE_MAX &&
|
||||||
bch2_bkey_ops[l.k->type].key_merge &&
|
|
||||||
!bch2_key_merging_disabled &&
|
!bch2_key_merging_disabled &&
|
||||||
ops->key_merge(c, l, r);
|
ops->key_merge(c, l, r);
|
||||||
}
|
}
|
||||||
@ -484,7 +483,7 @@ void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
|
|||||||
u->k.p.snapshot = write
|
u->k.p.snapshot = write
|
||||||
? 0 : U32_MAX;
|
? 0 : U32_MAX;
|
||||||
} else {
|
} else {
|
||||||
u64 min_packed = f->field_offset[BKEY_FIELD_SNAPSHOT];
|
u64 min_packed = le64_to_cpu(f->field_offset[BKEY_FIELD_SNAPSHOT]);
|
||||||
u64 max_packed = min_packed +
|
u64 max_packed = min_packed +
|
||||||
~(~0ULL << f->bits_per_field[BKEY_FIELD_SNAPSHOT]);
|
~(~0ULL << f->bits_per_field[BKEY_FIELD_SNAPSHOT]);
|
||||||
|
|
||||||
@ -509,7 +508,7 @@ void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
|
|||||||
if (big_endian != CPU_BIG_ENDIAN)
|
if (big_endian != CPU_BIG_ENDIAN)
|
||||||
bch2_bkey_swab_val(u);
|
bch2_bkey_swab_val(u);
|
||||||
|
|
||||||
ops = &bch2_bkey_ops[k->type];
|
ops = bch2_bkey_type_ops(k->type);
|
||||||
|
|
||||||
if (ops->compat)
|
if (ops->compat)
|
||||||
ops->compat(btree_id, version, big_endian, write, u);
|
ops->compat(btree_id, version, big_endian, write, u);
|
||||||
|
@ -11,6 +11,13 @@ struct bkey;
|
|||||||
enum btree_node_type;
|
enum btree_node_type;
|
||||||
|
|
||||||
extern const char * const bch2_bkey_types[];
|
extern const char * const bch2_bkey_types[];
|
||||||
|
extern const struct bkey_ops bch2_bkey_null_ops;
|
||||||
|
|
||||||
|
enum bkey_invalid_flags {
|
||||||
|
BKEY_INVALID_WRITE = (1U << 0),
|
||||||
|
BKEY_INVALID_COMMIT = (1U << 1),
|
||||||
|
BKEY_INVALID_JOURNAL = (1U << 2),
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* key_invalid: checks validity of @k, returns 0 if good or -EINVAL if bad. If
|
* key_invalid: checks validity of @k, returns 0 if good or -EINVAL if bad. If
|
||||||
@ -21,7 +28,7 @@ extern const char * const bch2_bkey_types[];
|
|||||||
*/
|
*/
|
||||||
struct bkey_ops {
|
struct bkey_ops {
|
||||||
int (*key_invalid)(const struct bch_fs *c, struct bkey_s_c k,
|
int (*key_invalid)(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err);
|
enum bkey_invalid_flags flags, struct printbuf *err);
|
||||||
void (*val_to_text)(struct printbuf *, struct bch_fs *,
|
void (*val_to_text)(struct printbuf *, struct bch_fs *,
|
||||||
struct bkey_s_c);
|
struct bkey_s_c);
|
||||||
void (*swab)(struct bkey_s);
|
void (*swab)(struct bkey_s);
|
||||||
@ -41,7 +48,12 @@ struct bkey_ops {
|
|||||||
|
|
||||||
extern const struct bkey_ops bch2_bkey_ops[];
|
extern const struct bkey_ops bch2_bkey_ops[];
|
||||||
|
|
||||||
#define BKEY_INVALID_FROM_JOURNAL (1 << 1)
|
static inline const struct bkey_ops *bch2_bkey_type_ops(enum bch_bkey_type type)
|
||||||
|
{
|
||||||
|
return likely(type < KEY_TYPE_MAX)
|
||||||
|
? &bch2_bkey_ops[type]
|
||||||
|
: &bch2_bkey_null_ops;
|
||||||
|
}
|
||||||
|
|
||||||
int bch2_bkey_val_invalid(struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_bkey_val_invalid(struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
||||||
int __bch2_bkey_invalid(struct bch_fs *, struct bkey_s_c,
|
int __bch2_bkey_invalid(struct bch_fs *, struct bkey_s_c,
|
||||||
@ -75,7 +87,7 @@ static inline int bch2_mark_key(struct btree_trans *trans,
|
|||||||
struct bkey_s_c old, struct bkey_s_c new,
|
struct bkey_s_c old, struct bkey_s_c new,
|
||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
const struct bkey_ops *ops = &bch2_bkey_ops[old.k->type ?: new.k->type];
|
const struct bkey_ops *ops = bch2_bkey_type_ops(old.k->type ?: new.k->type);
|
||||||
|
|
||||||
return ops->atomic_trigger
|
return ops->atomic_trigger
|
||||||
? ops->atomic_trigger(trans, btree, level, old, new, flags)
|
? ops->atomic_trigger(trans, btree, level, old, new, flags)
|
||||||
@ -115,7 +127,7 @@ static inline int bch2_trans_mark_key(struct btree_trans *trans,
|
|||||||
struct bkey_s_c old, struct bkey_i *new,
|
struct bkey_s_c old, struct bkey_i *new,
|
||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
const struct bkey_ops *ops = &bch2_bkey_ops[old.k->type ?: new->k.type];
|
const struct bkey_ops *ops = bch2_bkey_type_ops(old.k->type ?: new->k.type);
|
||||||
|
|
||||||
return ops->trans_trigger
|
return ops->trans_trigger
|
||||||
? ops->trans_trigger(trans, btree_id, level, old, new, flags)
|
? ops->trans_trigger(trans, btree_id, level, old, new, flags)
|
||||||
|
@ -599,11 +599,10 @@ static inline unsigned bkey_mantissa(const struct bkey_packed *k,
|
|||||||
return (u16) v;
|
return (u16) v;
|
||||||
}
|
}
|
||||||
|
|
||||||
__always_inline
|
static __always_inline void make_bfloat(struct btree *b, struct bset_tree *t,
|
||||||
static inline void make_bfloat(struct btree *b, struct bset_tree *t,
|
unsigned j,
|
||||||
unsigned j,
|
struct bkey_packed *min_key,
|
||||||
struct bkey_packed *min_key,
|
struct bkey_packed *max_key)
|
||||||
struct bkey_packed *max_key)
|
|
||||||
{
|
{
|
||||||
struct bkey_float *f = bkey_float(b, t, j);
|
struct bkey_float *f = bkey_float(b, t, j);
|
||||||
struct bkey_packed *m = tree_to_bkey(b, t, j);
|
struct bkey_packed *m = tree_to_bkey(b, t, j);
|
||||||
|
@ -32,13 +32,15 @@ void bch2_recalc_btree_reserve(struct bch_fs *c)
|
|||||||
{
|
{
|
||||||
unsigned i, reserve = 16;
|
unsigned i, reserve = 16;
|
||||||
|
|
||||||
if (!c->btree_roots[0].b)
|
if (!c->btree_roots_known[0].b)
|
||||||
reserve += 8;
|
reserve += 8;
|
||||||
|
|
||||||
for (i = 0; i < BTREE_ID_NR; i++)
|
for (i = 0; i < btree_id_nr_alive(c); i++) {
|
||||||
if (c->btree_roots[i].b)
|
struct btree_root *r = bch2_btree_id_root(c, i);
|
||||||
reserve += min_t(unsigned, 1,
|
|
||||||
c->btree_roots[i].b->c.level) * 8;
|
if (r->b)
|
||||||
|
reserve += min_t(unsigned, 1, r->b->c.level) * 8;
|
||||||
|
}
|
||||||
|
|
||||||
c->btree_cache.reserve = reserve;
|
c->btree_cache.reserve = reserve;
|
||||||
}
|
}
|
||||||
@ -457,9 +459,12 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
|
|||||||
|
|
||||||
kvpfree(c->verify_ondisk, btree_bytes(c));
|
kvpfree(c->verify_ondisk, btree_bytes(c));
|
||||||
|
|
||||||
for (i = 0; i < BTREE_ID_NR; i++)
|
for (i = 0; i < btree_id_nr_alive(c); i++) {
|
||||||
if (c->btree_roots[i].b)
|
struct btree_root *r = bch2_btree_id_root(c, i);
|
||||||
list_add(&c->btree_roots[i].b->list, &bc->live);
|
|
||||||
|
if (r->b)
|
||||||
|
list_add(&r->b->list, &bc->live);
|
||||||
|
}
|
||||||
|
|
||||||
list_splice(&bc->freeable, &bc->live);
|
list_splice(&bc->freeable, &bc->live);
|
||||||
|
|
||||||
|
@ -45,7 +45,11 @@ static inline u64 btree_ptr_hash_val(const struct bkey_i *k)
|
|||||||
case KEY_TYPE_btree_ptr:
|
case KEY_TYPE_btree_ptr:
|
||||||
return *((u64 *) bkey_i_to_btree_ptr_c(k)->v.start);
|
return *((u64 *) bkey_i_to_btree_ptr_c(k)->v.start);
|
||||||
case KEY_TYPE_btree_ptr_v2:
|
case KEY_TYPE_btree_ptr_v2:
|
||||||
return bkey_i_to_btree_ptr_v2_c(k)->v.seq;
|
/*
|
||||||
|
* The cast/deref is only necessary to avoid sparse endianness
|
||||||
|
* warnings:
|
||||||
|
*/
|
||||||
|
return *((u64 *) &bkey_i_to_btree_ptr_v2_c(k)->v.seq);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -97,7 +101,27 @@ static inline unsigned btree_blocks(struct bch_fs *c)
|
|||||||
(BTREE_FOREGROUND_MERGE_THRESHOLD(c) + \
|
(BTREE_FOREGROUND_MERGE_THRESHOLD(c) + \
|
||||||
(BTREE_FOREGROUND_MERGE_THRESHOLD(c) >> 2))
|
(BTREE_FOREGROUND_MERGE_THRESHOLD(c) >> 2))
|
||||||
|
|
||||||
#define btree_node_root(_c, _b) ((_c)->btree_roots[(_b)->c.btree_id].b)
|
static inline unsigned btree_id_nr_alive(struct bch_fs *c)
|
||||||
|
{
|
||||||
|
return BTREE_ID_NR + c->btree_roots_extra.nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct btree_root *bch2_btree_id_root(struct bch_fs *c, unsigned id)
|
||||||
|
{
|
||||||
|
if (likely(id < BTREE_ID_NR)) {
|
||||||
|
return &c->btree_roots_known[id];
|
||||||
|
} else {
|
||||||
|
unsigned idx = id - BTREE_ID_NR;
|
||||||
|
|
||||||
|
EBUG_ON(idx >= c->btree_roots_extra.nr);
|
||||||
|
return &c->btree_roots_extra.data[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct btree *btree_node_root(struct bch_fs *c, struct btree *b)
|
||||||
|
{
|
||||||
|
return bch2_btree_id_root(c, b->c.btree_id)->b;
|
||||||
|
}
|
||||||
|
|
||||||
void bch2_btree_node_to_text(struct printbuf *, struct bch_fs *,
|
void bch2_btree_node_to_text(struct printbuf *, struct bch_fs *,
|
||||||
const struct btree *);
|
const struct btree *);
|
||||||
|
@ -529,8 +529,13 @@ static int bch2_repair_topology(struct bch_fs *c)
|
|||||||
|
|
||||||
bch2_trans_init(&trans, c, 0, 0);
|
bch2_trans_init(&trans, c, 0, 0);
|
||||||
|
|
||||||
for (i = 0; i < BTREE_ID_NR && !ret; i++) {
|
for (i = 0; i < btree_id_nr_alive(c)&& !ret; i++) {
|
||||||
b = c->btree_roots[i].b;
|
struct btree_root *r = bch2_btree_id_root(c, i);
|
||||||
|
|
||||||
|
if (!r->alive)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
b = r->b;
|
||||||
if (btree_node_fake(b))
|
if (btree_node_fake(b))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -883,7 +888,7 @@ static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree_id,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
mutex_lock(&c->btree_root_lock);
|
mutex_lock(&c->btree_root_lock);
|
||||||
b = c->btree_roots[btree_id].b;
|
b = bch2_btree_id_root(c, btree_id)->b;
|
||||||
if (!btree_node_fake(b)) {
|
if (!btree_node_fake(b)) {
|
||||||
struct bkey_s_c k = bkey_i_to_s_c(&b->key);
|
struct bkey_s_c k = bkey_i_to_s_c(&b->key);
|
||||||
|
|
||||||
@ -1006,7 +1011,7 @@ static int bch2_gc_btree_init(struct btree_trans *trans,
|
|||||||
struct printbuf buf = PRINTBUF;
|
struct printbuf buf = PRINTBUF;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
b = c->btree_roots[btree_id].b;
|
b = bch2_btree_id_root(c, btree_id)->b;
|
||||||
|
|
||||||
if (btree_node_fake(b))
|
if (btree_node_fake(b))
|
||||||
return 0;
|
return 0;
|
||||||
@ -1075,6 +1080,15 @@ static int bch2_gc_btrees(struct bch_fs *c, bool initial, bool metadata_only)
|
|||||||
? bch2_gc_btree_init(&trans, ids[i], metadata_only)
|
? bch2_gc_btree_init(&trans, ids[i], metadata_only)
|
||||||
: bch2_gc_btree(&trans, ids[i], initial, metadata_only);
|
: bch2_gc_btree(&trans, ids[i], initial, metadata_only);
|
||||||
|
|
||||||
|
for (i = BTREE_ID_NR; i < btree_id_nr_alive(c) && !ret; i++) {
|
||||||
|
if (!bch2_btree_id_root(c, i)->alive)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = initial
|
||||||
|
? bch2_gc_btree_init(&trans, i, metadata_only)
|
||||||
|
: bch2_gc_btree(&trans, i, initial, metadata_only);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
bch_err_fn(c, ret);
|
bch_err_fn(c, ret);
|
||||||
|
|
||||||
@ -1218,7 +1232,7 @@ static int bch2_gc_done(struct bch_fs *c,
|
|||||||
for_each_member_device(ca, c, dev) {
|
for_each_member_device(ca, c, dev) {
|
||||||
struct bch_dev_usage *dst = ca->usage_base;
|
struct bch_dev_usage *dst = ca->usage_base;
|
||||||
struct bch_dev_usage *src = (void *)
|
struct bch_dev_usage *src = (void *)
|
||||||
bch2_acc_percpu_u64s((void *) ca->usage_gc,
|
bch2_acc_percpu_u64s((u64 __percpu *) ca->usage_gc,
|
||||||
dev_usage_u64s());
|
dev_usage_u64s());
|
||||||
|
|
||||||
copy_dev_field(buckets_ec, "buckets_ec");
|
copy_dev_field(buckets_ec, "buckets_ec");
|
||||||
@ -1234,7 +1248,7 @@ static int bch2_gc_done(struct bch_fs *c,
|
|||||||
unsigned nr = fs_usage_u64s(c);
|
unsigned nr = fs_usage_u64s(c);
|
||||||
struct bch_fs_usage *dst = c->usage_base;
|
struct bch_fs_usage *dst = c->usage_base;
|
||||||
struct bch_fs_usage *src = (void *)
|
struct bch_fs_usage *src = (void *)
|
||||||
bch2_acc_percpu_u64s((void *) c->usage_gc, nr);
|
bch2_acc_percpu_u64s((u64 __percpu *) c->usage_gc, nr);
|
||||||
|
|
||||||
copy_fs_field(hidden, "hidden");
|
copy_fs_field(hidden, "hidden");
|
||||||
copy_fs_field(btree, "btree");
|
copy_fs_field(btree, "btree");
|
||||||
|
@ -517,7 +517,7 @@ static void btree_pos_to_text(struct printbuf *out, struct bch_fs *c,
|
|||||||
prt_printf(out, "%s level %u/%u\n ",
|
prt_printf(out, "%s level %u/%u\n ",
|
||||||
bch2_btree_ids[b->c.btree_id],
|
bch2_btree_ids[b->c.btree_id],
|
||||||
b->c.level,
|
b->c.level,
|
||||||
c->btree_roots[b->c.btree_id].level);
|
bch2_btree_id_root(c, b->c.btree_id)->level);
|
||||||
bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(&b->key));
|
bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(&b->key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,11 +699,9 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
|
|||||||
struct printbuf buf2 = PRINTBUF;
|
struct printbuf buf2 = PRINTBUF;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
btree_err_on((version != BCH_BSET_VERSION_OLD &&
|
btree_err_on(!bch2_version_compatible(version),
|
||||||
version < bcachefs_metadata_version_min) ||
|
|
||||||
version >= bcachefs_metadata_version_max,
|
|
||||||
BTREE_ERR_INCOMPATIBLE, c, ca, b, i,
|
BTREE_ERR_INCOMPATIBLE, c, ca, b, i,
|
||||||
"unsupported bset version");
|
"unsupported bset version %u", version);
|
||||||
|
|
||||||
if (btree_err_on(version < c->sb.version_min,
|
if (btree_err_on(version < c->sb.version_min,
|
||||||
BTREE_ERR_FIXABLE, c, NULL, b, i,
|
BTREE_ERR_FIXABLE, c, NULL, b, i,
|
||||||
@ -1283,7 +1281,7 @@ struct btree_node_read_all {
|
|||||||
unsigned nr;
|
unsigned nr;
|
||||||
void *buf[BCH_REPLICAS_MAX];
|
void *buf[BCH_REPLICAS_MAX];
|
||||||
struct bio *bio[BCH_REPLICAS_MAX];
|
struct bio *bio[BCH_REPLICAS_MAX];
|
||||||
int err[BCH_REPLICAS_MAX];
|
blk_status_t err[BCH_REPLICAS_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned btree_node_sectors_written(struct bch_fs *c, void *data)
|
static unsigned btree_node_sectors_written(struct bch_fs *c, void *data)
|
||||||
@ -1766,7 +1764,11 @@ static void btree_node_write_work(struct work_struct *work)
|
|||||||
} else {
|
} else {
|
||||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||||
bch2_btree_node_update_key_get_iter(&trans, b, &wbio->key,
|
bch2_btree_node_update_key_get_iter(&trans, b, &wbio->key,
|
||||||
!wbio->wbio.failed.nr));
|
BCH_WATERMARK_reclaim|
|
||||||
|
BTREE_INSERT_JOURNAL_RECLAIM|
|
||||||
|
BTREE_INSERT_NOFAIL|
|
||||||
|
BTREE_INSERT_NOCHECK_RW,
|
||||||
|
!wbio->wbio.failed.nr));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -1777,7 +1779,7 @@ out:
|
|||||||
err:
|
err:
|
||||||
set_btree_node_noevict(b);
|
set_btree_node_noevict(b);
|
||||||
if (!bch2_err_matches(ret, EROFS))
|
if (!bch2_err_matches(ret, EROFS))
|
||||||
bch2_fs_fatal_error(c, "fatal error writing btree node");
|
bch2_fs_fatal_error(c, "fatal error writing btree node: %s", bch2_err_str(ret));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2015,9 +2017,7 @@ do_write:
|
|||||||
BUG_ON(BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN);
|
BUG_ON(BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN);
|
||||||
BUG_ON(i->seq != b->data->keys.seq);
|
BUG_ON(i->seq != b->data->keys.seq);
|
||||||
|
|
||||||
i->version = c->sb.version < bcachefs_metadata_version_bkey_renumber
|
i->version = cpu_to_le16(c->sb.version);
|
||||||
? cpu_to_le16(BCH_BSET_VERSION_OLD)
|
|
||||||
: cpu_to_le16(c->sb.version);
|
|
||||||
SET_BSET_OFFSET(i, b->written);
|
SET_BSET_OFFSET(i, b->written);
|
||||||
SET_BSET_CSUM_TYPE(i, bch2_meta_checksum_type(c));
|
SET_BSET_CSUM_TYPE(i, bch2_meta_checksum_type(c));
|
||||||
|
|
||||||
@ -2230,7 +2230,7 @@ bool bch2_btree_flush_all_writes(struct bch_fs *c)
|
|||||||
return __bch2_btree_flush_all(c, BTREE_NODE_write_in_flight);
|
return __bch2_btree_flush_all(c, BTREE_NODE_write_in_flight);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * const bch2_btree_write_types[] = {
|
static const char * const bch2_btree_write_types[] = {
|
||||||
#define x(t, n) [n] = #t,
|
#define x(t, n) [n] = #t,
|
||||||
BCH_BTREE_WRITE_TYPES()
|
BCH_BTREE_WRITE_TYPES()
|
||||||
NULL
|
NULL
|
||||||
|
@ -178,7 +178,7 @@ static inline void compat_bformat(unsigned level, enum btree_id btree_id,
|
|||||||
|
|
||||||
f->field_offset[BKEY_FIELD_SNAPSHOT] = write
|
f->field_offset[BKEY_FIELD_SNAPSHOT] = write
|
||||||
? 0
|
? 0
|
||||||
: U32_MAX - max_packed;
|
: cpu_to_le64(U32_MAX - max_packed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ static inline void compat_btree_node(unsigned level, enum btree_id btree_id,
|
|||||||
struct btree_node *bn)
|
struct btree_node *bn)
|
||||||
{
|
{
|
||||||
if (version < bcachefs_metadata_version_inode_btree_change &&
|
if (version < bcachefs_metadata_version_inode_btree_change &&
|
||||||
btree_node_type_is_extents(btree_id) &&
|
btree_id_is_extents(btree_id) &&
|
||||||
!bpos_eq(bn->min_key, POS_MIN) &&
|
!bpos_eq(bn->min_key, POS_MIN) &&
|
||||||
write)
|
write)
|
||||||
bn->min_key = bpos_nosnap_predecessor(bn->min_key);
|
bn->min_key = bpos_nosnap_predecessor(bn->min_key);
|
||||||
@ -217,7 +217,7 @@ static inline void compat_btree_node(unsigned level, enum btree_id btree_id,
|
|||||||
bn->max_key.snapshot = U32_MAX;
|
bn->max_key.snapshot = U32_MAX;
|
||||||
|
|
||||||
if (version < bcachefs_metadata_version_inode_btree_change &&
|
if (version < bcachefs_metadata_version_inode_btree_change &&
|
||||||
btree_node_type_is_extents(btree_id) &&
|
btree_id_is_extents(btree_id) &&
|
||||||
!bpos_eq(bn->min_key, POS_MIN) &&
|
!bpos_eq(bn->min_key, POS_MIN) &&
|
||||||
!write)
|
!write)
|
||||||
bn->min_key = bpos_nosnap_successor(bn->min_key);
|
bn->min_key = bpos_nosnap_successor(bn->min_key);
|
||||||
|
@ -238,7 +238,7 @@ static void bch2_btree_path_verify(struct btree_trans *trans,
|
|||||||
for (i = 0; i < (!path->cached ? BTREE_MAX_DEPTH : 1); i++) {
|
for (i = 0; i < (!path->cached ? BTREE_MAX_DEPTH : 1); i++) {
|
||||||
if (!path->l[i].b) {
|
if (!path->l[i].b) {
|
||||||
BUG_ON(!path->cached &&
|
BUG_ON(!path->cached &&
|
||||||
c->btree_roots[path->btree_id].b->c.level > i);
|
bch2_btree_id_root(c, path->btree_id)->b->c.level > i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,8 +700,8 @@ void bch2_trans_node_add(struct btree_trans *trans, struct btree *b)
|
|||||||
|
|
||||||
if (t != BTREE_NODE_UNLOCKED) {
|
if (t != BTREE_NODE_UNLOCKED) {
|
||||||
btree_node_unlock(trans, path, b->c.level);
|
btree_node_unlock(trans, path, b->c.level);
|
||||||
six_lock_increment(&b->c.lock, t);
|
six_lock_increment(&b->c.lock, (enum six_lock_type) t);
|
||||||
mark_btree_node_locked(trans, path, b->c.level, t);
|
mark_btree_node_locked(trans, path, b->c.level, (enum six_lock_type) t);
|
||||||
}
|
}
|
||||||
|
|
||||||
bch2_btree_path_level_init(trans, path, b);
|
bch2_btree_path_level_init(trans, path, b);
|
||||||
@ -732,7 +732,7 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
|
|||||||
unsigned long trace_ip)
|
unsigned long trace_ip)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct btree *b, **rootp = &c->btree_roots[path->btree_id].b;
|
struct btree *b, **rootp = &bch2_btree_id_root(c, path->btree_id)->b;
|
||||||
enum six_lock_type lock_type;
|
enum six_lock_type lock_type;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1438,7 +1438,7 @@ void bch2_btree_path_to_text(struct printbuf *out, struct btree_path *path)
|
|||||||
prt_newline(out);
|
prt_newline(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline __cold
|
static noinline __cold
|
||||||
void __bch2_trans_paths_to_text(struct printbuf *out, struct btree_trans *trans,
|
void __bch2_trans_paths_to_text(struct printbuf *out, struct btree_trans *trans,
|
||||||
bool nosort)
|
bool nosort)
|
||||||
{
|
{
|
||||||
@ -1458,7 +1458,7 @@ void bch2_trans_paths_to_text(struct printbuf *out, struct btree_trans *trans)
|
|||||||
__bch2_trans_paths_to_text(out, trans, false);
|
__bch2_trans_paths_to_text(out, trans, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline __cold
|
static noinline __cold
|
||||||
void __bch2_dump_trans_paths_updates(struct btree_trans *trans, bool nosort)
|
void __bch2_dump_trans_paths_updates(struct btree_trans *trans, bool nosort)
|
||||||
{
|
{
|
||||||
struct printbuf buf = PRINTBUF;
|
struct printbuf buf = PRINTBUF;
|
||||||
@ -1867,9 +1867,9 @@ static inline struct bkey_i *btree_trans_peek_updates(struct btree_iter *iter)
|
|||||||
: NULL;
|
: NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bkey_i *bch2_btree_journal_peek(struct btree_trans *trans,
|
static struct bkey_i *bch2_btree_journal_peek(struct btree_trans *trans,
|
||||||
struct btree_iter *iter,
|
struct btree_iter *iter,
|
||||||
struct bpos end_pos)
|
struct bpos end_pos)
|
||||||
{
|
{
|
||||||
struct bkey_i *k;
|
struct bkey_i *k;
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ static inline void bch2_trans_verify_not_in_restart(struct btree_trans *trans)
|
|||||||
}
|
}
|
||||||
|
|
||||||
__always_inline
|
__always_inline
|
||||||
static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int err)
|
static int btree_trans_restart_nounlock(struct btree_trans *trans, int err)
|
||||||
{
|
{
|
||||||
BUG_ON(err <= 0);
|
BUG_ON(err <= 0);
|
||||||
BUG_ON(!bch2_err_matches(-err, BCH_ERR_transaction_restart));
|
BUG_ON(!bch2_err_matches(-err, BCH_ERR_transaction_restart));
|
||||||
@ -294,7 +294,7 @@ static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int er
|
|||||||
}
|
}
|
||||||
|
|
||||||
__always_inline
|
__always_inline
|
||||||
static inline int btree_trans_restart(struct btree_trans *trans, int err)
|
static int btree_trans_restart(struct btree_trans *trans, int err)
|
||||||
{
|
{
|
||||||
btree_trans_restart_nounlock(trans, err);
|
btree_trans_restart_nounlock(trans, err);
|
||||||
return -err;
|
return -err;
|
||||||
|
@ -651,9 +651,8 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
|
|||||||
bch2_trans_commit(trans, NULL, NULL,
|
bch2_trans_commit(trans, NULL, NULL,
|
||||||
BTREE_INSERT_NOCHECK_RW|
|
BTREE_INSERT_NOCHECK_RW|
|
||||||
BTREE_INSERT_NOFAIL|
|
BTREE_INSERT_NOFAIL|
|
||||||
BTREE_INSERT_USE_RESERVE|
|
|
||||||
(ck->journal.seq == journal_last_seq(j)
|
(ck->journal.seq == journal_last_seq(j)
|
||||||
? JOURNAL_WATERMARK_reserved
|
? BCH_WATERMARK_reclaim
|
||||||
: 0)|
|
: 0)|
|
||||||
commit_flags);
|
commit_flags);
|
||||||
|
|
||||||
|
@ -597,13 +597,6 @@ int __bch2_btree_path_relock(struct btree_trans *trans,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__flatten
|
|
||||||
bool bch2_btree_path_upgrade_norestart(struct btree_trans *trans,
|
|
||||||
struct btree_path *path, unsigned long trace_ip)
|
|
||||||
{
|
|
||||||
return btree_path_get_locks(trans, path, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bch2_btree_path_upgrade_noupgrade_sibs(struct btree_trans *trans,
|
bool bch2_btree_path_upgrade_noupgrade_sibs(struct btree_trans *trans,
|
||||||
struct btree_path *path,
|
struct btree_path *path,
|
||||||
unsigned new_locks_want)
|
unsigned new_locks_want)
|
||||||
|
@ -94,7 +94,7 @@ static inline void mark_btree_node_locked(struct btree_trans *trans,
|
|||||||
unsigned level,
|
unsigned level,
|
||||||
enum six_lock_type type)
|
enum six_lock_type type)
|
||||||
{
|
{
|
||||||
mark_btree_node_locked_noreset(path, level, type);
|
mark_btree_node_locked_noreset(path, level, (enum btree_node_locked_type) type);
|
||||||
#ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS
|
#ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS
|
||||||
path->l[level].lock_taken_time = local_clock();
|
path->l[level].lock_taken_time = local_clock();
|
||||||
#endif
|
#endif
|
||||||
@ -247,7 +247,7 @@ static inline bool btree_node_lock_increment(struct btree_trans *trans,
|
|||||||
trans_for_each_path(trans, path)
|
trans_for_each_path(trans, path)
|
||||||
if (&path->l[level].b->c == b &&
|
if (&path->l[level].b->c == b &&
|
||||||
btree_node_locked_type(path, level) >= want) {
|
btree_node_locked_type(path, level) >= want) {
|
||||||
six_lock_increment(&b->lock, want);
|
six_lock_increment(&b->lock, (enum six_lock_type) want);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ static inline int btree_node_lock(struct btree_trans *trans,
|
|||||||
EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx)));
|
EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx)));
|
||||||
|
|
||||||
if (likely(six_trylock_type(&b->lock, type)) ||
|
if (likely(six_trylock_type(&b->lock, type)) ||
|
||||||
btree_node_lock_increment(trans, b, level, type) ||
|
btree_node_lock_increment(trans, b, level, (enum btree_node_locked_type) type) ||
|
||||||
!(ret = btree_node_lock_nopath(trans, b, type, btree_path_ip_allocated(path)))) {
|
!(ret = btree_node_lock_nopath(trans, b, type, btree_path_ip_allocated(path)))) {
|
||||||
#ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS
|
#ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS
|
||||||
path->l[b->level].lock_taken_time = local_clock();
|
path->l[b->level].lock_taken_time = local_clock();
|
||||||
|
@ -688,6 +688,11 @@ static inline bool btree_node_type_is_extents(enum btree_node_type type)
|
|||||||
return (1U << type) & BTREE_ID_IS_EXTENTS;
|
return (1U << type) & BTREE_ID_IS_EXTENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool btree_id_is_extents(enum btree_id btree)
|
||||||
|
{
|
||||||
|
return btree_node_type_is_extents((enum btree_node_type) btree);
|
||||||
|
}
|
||||||
|
|
||||||
#define BTREE_ID_HAS_SNAPSHOTS \
|
#define BTREE_ID_HAS_SNAPSHOTS \
|
||||||
((1U << BTREE_ID_extents)| \
|
((1U << BTREE_ID_extents)| \
|
||||||
(1U << BTREE_ID_inodes)| \
|
(1U << BTREE_ID_inodes)| \
|
||||||
|
@ -23,11 +23,10 @@ void bch2_btree_insert_key_leaf(struct btree_trans *, struct btree_path *,
|
|||||||
struct bkey_i *, u64);
|
struct bkey_i *, u64);
|
||||||
|
|
||||||
enum btree_insert_flags {
|
enum btree_insert_flags {
|
||||||
/* First two bits for journal watermark: */
|
/* First bits for bch_watermark: */
|
||||||
__BTREE_INSERT_NOFAIL = 2,
|
__BTREE_INSERT_NOFAIL = BCH_WATERMARK_BITS,
|
||||||
__BTREE_INSERT_NOCHECK_RW,
|
__BTREE_INSERT_NOCHECK_RW,
|
||||||
__BTREE_INSERT_LAZY_RW,
|
__BTREE_INSERT_LAZY_RW,
|
||||||
__BTREE_INSERT_USE_RESERVE,
|
|
||||||
__BTREE_INSERT_JOURNAL_REPLAY,
|
__BTREE_INSERT_JOURNAL_REPLAY,
|
||||||
__BTREE_INSERT_JOURNAL_RECLAIM,
|
__BTREE_INSERT_JOURNAL_RECLAIM,
|
||||||
__BTREE_INSERT_NOWAIT,
|
__BTREE_INSERT_NOWAIT,
|
||||||
@ -37,26 +36,23 @@ enum btree_insert_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Don't check for -ENOSPC: */
|
/* Don't check for -ENOSPC: */
|
||||||
#define BTREE_INSERT_NOFAIL (1 << __BTREE_INSERT_NOFAIL)
|
#define BTREE_INSERT_NOFAIL BIT(__BTREE_INSERT_NOFAIL)
|
||||||
|
|
||||||
#define BTREE_INSERT_NOCHECK_RW (1 << __BTREE_INSERT_NOCHECK_RW)
|
#define BTREE_INSERT_NOCHECK_RW BIT(__BTREE_INSERT_NOCHECK_RW)
|
||||||
#define BTREE_INSERT_LAZY_RW (1 << __BTREE_INSERT_LAZY_RW)
|
#define BTREE_INSERT_LAZY_RW BIT(__BTREE_INSERT_LAZY_RW)
|
||||||
|
|
||||||
/* for copygc, or when merging btree nodes */
|
|
||||||
#define BTREE_INSERT_USE_RESERVE (1 << __BTREE_INSERT_USE_RESERVE)
|
|
||||||
|
|
||||||
/* Insert is for journal replay - don't get journal reservations: */
|
/* Insert is for journal replay - don't get journal reservations: */
|
||||||
#define BTREE_INSERT_JOURNAL_REPLAY (1 << __BTREE_INSERT_JOURNAL_REPLAY)
|
#define BTREE_INSERT_JOURNAL_REPLAY BIT(__BTREE_INSERT_JOURNAL_REPLAY)
|
||||||
|
|
||||||
/* Insert is being called from journal reclaim path: */
|
/* Insert is being called from journal reclaim path: */
|
||||||
#define BTREE_INSERT_JOURNAL_RECLAIM (1 << __BTREE_INSERT_JOURNAL_RECLAIM)
|
#define BTREE_INSERT_JOURNAL_RECLAIM BIT(__BTREE_INSERT_JOURNAL_RECLAIM)
|
||||||
|
|
||||||
/* Don't block on allocation failure (for new btree nodes: */
|
/* Don't block on allocation failure (for new btree nodes: */
|
||||||
#define BTREE_INSERT_NOWAIT (1 << __BTREE_INSERT_NOWAIT)
|
#define BTREE_INSERT_NOWAIT BIT(__BTREE_INSERT_NOWAIT)
|
||||||
#define BTREE_INSERT_GC_LOCK_HELD (1 << __BTREE_INSERT_GC_LOCK_HELD)
|
#define BTREE_INSERT_GC_LOCK_HELD BIT(__BTREE_INSERT_GC_LOCK_HELD)
|
||||||
|
|
||||||
#define BCH_HASH_SET_MUST_CREATE (1 << __BCH_HASH_SET_MUST_CREATE)
|
#define BCH_HASH_SET_MUST_CREATE BIT(__BCH_HASH_SET_MUST_CREATE)
|
||||||
#define BCH_HASH_SET_MUST_REPLACE (1 << __BCH_HASH_SET_MUST_REPLACE)
|
#define BCH_HASH_SET_MUST_REPLACE BIT(__BCH_HASH_SET_MUST_REPLACE)
|
||||||
|
|
||||||
int bch2_btree_delete_extent_at(struct btree_trans *, struct btree_iter *,
|
int bch2_btree_delete_extent_at(struct btree_trans *, struct btree_iter *,
|
||||||
unsigned, unsigned);
|
unsigned, unsigned);
|
||||||
@ -80,9 +76,10 @@ int bch2_btree_node_rewrite(struct btree_trans *, struct btree_iter *,
|
|||||||
struct btree *, unsigned);
|
struct btree *, unsigned);
|
||||||
void bch2_btree_node_rewrite_async(struct bch_fs *, struct btree *);
|
void bch2_btree_node_rewrite_async(struct bch_fs *, struct btree *);
|
||||||
int bch2_btree_node_update_key(struct btree_trans *, struct btree_iter *,
|
int bch2_btree_node_update_key(struct btree_trans *, struct btree_iter *,
|
||||||
struct btree *, struct bkey_i *, bool);
|
struct btree *, struct bkey_i *,
|
||||||
int bch2_btree_node_update_key_get_iter(struct btree_trans *,
|
unsigned, bool);
|
||||||
struct btree *, struct bkey_i *, bool);
|
int bch2_btree_node_update_key_get_iter(struct btree_trans *, struct btree *,
|
||||||
|
struct bkey_i *, unsigned, bool);
|
||||||
|
|
||||||
int __bch2_insert_snapshot_whiteouts(struct btree_trans *, enum btree_id,
|
int __bch2_insert_snapshot_whiteouts(struct btree_trans *, enum btree_id,
|
||||||
struct bpos, struct bpos);
|
struct bpos, struct bpos);
|
||||||
|
@ -246,18 +246,12 @@ static struct btree *__bch2_btree_node_alloc(struct btree_trans *trans,
|
|||||||
BKEY_PADDED_ONSTACK(k, BKEY_BTREE_PTR_VAL_U64s_MAX) tmp;
|
BKEY_PADDED_ONSTACK(k, BKEY_BTREE_PTR_VAL_U64s_MAX) tmp;
|
||||||
struct open_buckets ob = { .nr = 0 };
|
struct open_buckets ob = { .nr = 0 };
|
||||||
struct bch_devs_list devs_have = (struct bch_devs_list) { 0 };
|
struct bch_devs_list devs_have = (struct bch_devs_list) { 0 };
|
||||||
unsigned nr_reserve;
|
enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
|
||||||
enum bch_watermark alloc_reserve;
|
unsigned nr_reserve = watermark > BCH_WATERMARK_reclaim
|
||||||
|
? BTREE_NODE_RESERVE
|
||||||
|
: 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (flags & BTREE_INSERT_USE_RESERVE) {
|
|
||||||
nr_reserve = 0;
|
|
||||||
alloc_reserve = BCH_WATERMARK_btree_copygc;
|
|
||||||
} else {
|
|
||||||
nr_reserve = BTREE_NODE_RESERVE;
|
|
||||||
alloc_reserve = BCH_WATERMARK_btree;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&c->btree_reserve_cache_lock);
|
mutex_lock(&c->btree_reserve_cache_lock);
|
||||||
if (c->btree_reserve_cache_nr > nr_reserve) {
|
if (c->btree_reserve_cache_nr > nr_reserve) {
|
||||||
struct btree_alloc *a =
|
struct btree_alloc *a =
|
||||||
@ -279,7 +273,7 @@ retry:
|
|||||||
&devs_have,
|
&devs_have,
|
||||||
res->nr_replicas,
|
res->nr_replicas,
|
||||||
c->opts.metadata_replicas_required,
|
c->opts.metadata_replicas_required,
|
||||||
alloc_reserve, 0, cl, &wp);
|
watermark, 0, cl, &wp);
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
@ -647,11 +641,10 @@ static void btree_update_nodes_written(struct btree_update *as)
|
|||||||
* which may require allocations as well.
|
* which may require allocations as well.
|
||||||
*/
|
*/
|
||||||
ret = commit_do(&trans, &as->disk_res, &journal_seq,
|
ret = commit_do(&trans, &as->disk_res, &journal_seq,
|
||||||
|
BCH_WATERMARK_reclaim|
|
||||||
BTREE_INSERT_NOFAIL|
|
BTREE_INSERT_NOFAIL|
|
||||||
BTREE_INSERT_NOCHECK_RW|
|
BTREE_INSERT_NOCHECK_RW|
|
||||||
BTREE_INSERT_USE_RESERVE|
|
BTREE_INSERT_JOURNAL_RECLAIM,
|
||||||
BTREE_INSERT_JOURNAL_RECLAIM|
|
|
||||||
JOURNAL_WATERMARK_reserved,
|
|
||||||
btree_update_nodes_written_trans(&trans, as));
|
btree_update_nodes_written_trans(&trans, as));
|
||||||
bch2_trans_unlock(&trans);
|
bch2_trans_unlock(&trans);
|
||||||
|
|
||||||
@ -1049,14 +1042,24 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
|
|||||||
? BCH_DISK_RESERVATION_NOFAIL : 0;
|
? BCH_DISK_RESERVATION_NOFAIL : 0;
|
||||||
unsigned nr_nodes[2] = { 0, 0 };
|
unsigned nr_nodes[2] = { 0, 0 };
|
||||||
unsigned update_level = level;
|
unsigned update_level = level;
|
||||||
int journal_flags = flags & JOURNAL_WATERMARK_MASK;
|
enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
|
||||||
|
unsigned journal_flags = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 restart_count = trans->restart_count;
|
u32 restart_count = trans->restart_count;
|
||||||
|
|
||||||
BUG_ON(!path->should_be_locked);
|
BUG_ON(!path->should_be_locked);
|
||||||
|
|
||||||
|
if (watermark == BCH_WATERMARK_copygc)
|
||||||
|
watermark = BCH_WATERMARK_btree_copygc;
|
||||||
|
if (watermark < BCH_WATERMARK_btree)
|
||||||
|
watermark = BCH_WATERMARK_btree;
|
||||||
|
|
||||||
|
flags &= ~BCH_WATERMARK_MASK;
|
||||||
|
flags |= watermark;
|
||||||
|
|
||||||
if (flags & BTREE_INSERT_JOURNAL_RECLAIM)
|
if (flags & BTREE_INSERT_JOURNAL_RECLAIM)
|
||||||
journal_flags |= JOURNAL_RES_GET_NONBLOCK;
|
journal_flags |= JOURNAL_RES_GET_NONBLOCK;
|
||||||
|
journal_flags |= watermark;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
nr_nodes[!!update_level] += 1 + split;
|
nr_nodes[!!update_level] += 1 + split;
|
||||||
@ -1196,7 +1199,7 @@ static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b)
|
|||||||
(b->c.level < btree_node_root(c, b)->c.level ||
|
(b->c.level < btree_node_root(c, b)->c.level ||
|
||||||
!btree_node_dying(btree_node_root(c, b))));
|
!btree_node_dying(btree_node_root(c, b))));
|
||||||
|
|
||||||
btree_node_root(c, b) = b;
|
bch2_btree_id_root(c, b->c.btree_id)->b = b;
|
||||||
mutex_unlock(&c->btree_root_lock);
|
mutex_unlock(&c->btree_root_lock);
|
||||||
|
|
||||||
bch2_recalc_btree_reserve(c);
|
bch2_recalc_btree_reserve(c);
|
||||||
@ -1845,9 +1848,7 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
|
|||||||
|
|
||||||
parent = btree_node_parent(path, b);
|
parent = btree_node_parent(path, b);
|
||||||
as = bch2_btree_update_start(trans, path, level, false,
|
as = bch2_btree_update_start(trans, path, level, false,
|
||||||
BTREE_INSERT_NOFAIL|
|
BTREE_INSERT_NOFAIL|flags);
|
||||||
BTREE_INSERT_USE_RESERVE|
|
|
||||||
flags);
|
|
||||||
ret = PTR_ERR_OR_ZERO(as);
|
ret = PTR_ERR_OR_ZERO(as);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
@ -2035,7 +2036,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void async_btree_node_rewrite_work(struct work_struct *work)
|
static void async_btree_node_rewrite_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct async_btree_rewrite *a =
|
struct async_btree_rewrite *a =
|
||||||
container_of(work, struct async_btree_rewrite, work);
|
container_of(work, struct async_btree_rewrite, work);
|
||||||
@ -2127,6 +2128,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
|
|||||||
struct btree_iter *iter,
|
struct btree_iter *iter,
|
||||||
struct btree *b, struct btree *new_hash,
|
struct btree *b, struct btree *new_hash,
|
||||||
struct bkey_i *new_key,
|
struct bkey_i *new_key,
|
||||||
|
unsigned commit_flags,
|
||||||
bool skip_triggers)
|
bool skip_triggers)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
@ -2187,12 +2189,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
|
|||||||
trans->extra_journal_entries.nr += jset_u64s(new_key->k.u64s);
|
trans->extra_journal_entries.nr += jset_u64s(new_key->k.u64s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bch2_trans_commit(trans, NULL, NULL,
|
ret = bch2_trans_commit(trans, NULL, NULL, commit_flags);
|
||||||
BTREE_INSERT_NOFAIL|
|
|
||||||
BTREE_INSERT_NOCHECK_RW|
|
|
||||||
BTREE_INSERT_USE_RESERVE|
|
|
||||||
BTREE_INSERT_JOURNAL_RECLAIM|
|
|
||||||
JOURNAL_WATERMARK_reserved);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -2226,7 +2223,7 @@ err:
|
|||||||
|
|
||||||
int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *iter,
|
int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *iter,
|
||||||
struct btree *b, struct bkey_i *new_key,
|
struct btree *b, struct bkey_i *new_key,
|
||||||
bool skip_triggers)
|
unsigned commit_flags, bool skip_triggers)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct btree *new_hash = NULL;
|
struct btree *new_hash = NULL;
|
||||||
@ -2256,8 +2253,8 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
|
|||||||
}
|
}
|
||||||
|
|
||||||
path->intent_ref++;
|
path->intent_ref++;
|
||||||
ret = __bch2_btree_node_update_key(trans, iter, b, new_hash,
|
ret = __bch2_btree_node_update_key(trans, iter, b, new_hash, new_key,
|
||||||
new_key, skip_triggers);
|
commit_flags, skip_triggers);
|
||||||
--path->intent_ref;
|
--path->intent_ref;
|
||||||
|
|
||||||
if (new_hash) {
|
if (new_hash) {
|
||||||
@ -2275,7 +2272,7 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
|
|||||||
|
|
||||||
int bch2_btree_node_update_key_get_iter(struct btree_trans *trans,
|
int bch2_btree_node_update_key_get_iter(struct btree_trans *trans,
|
||||||
struct btree *b, struct bkey_i *new_key,
|
struct btree *b, struct bkey_i *new_key,
|
||||||
bool skip_triggers)
|
unsigned commit_flags, bool skip_triggers)
|
||||||
{
|
{
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
int ret;
|
int ret;
|
||||||
@ -2296,7 +2293,8 @@ int bch2_btree_node_update_key_get_iter(struct btree_trans *trans,
|
|||||||
|
|
||||||
BUG_ON(!btree_node_hashed(b));
|
BUG_ON(!btree_node_hashed(b));
|
||||||
|
|
||||||
ret = bch2_btree_node_update_key(trans, &iter, b, new_key, skip_triggers);
|
ret = bch2_btree_node_update_key(trans, &iter, b, new_key,
|
||||||
|
commit_flags, skip_triggers);
|
||||||
out:
|
out:
|
||||||
bch2_trans_iter_exit(trans, &iter);
|
bch2_trans_iter_exit(trans, &iter);
|
||||||
return ret;
|
return ret;
|
||||||
@ -2404,7 +2402,7 @@ bool bch2_btree_interior_updates_flush(struct bch_fs *c)
|
|||||||
|
|
||||||
void bch2_journal_entry_to_btree_root(struct bch_fs *c, struct jset_entry *entry)
|
void bch2_journal_entry_to_btree_root(struct bch_fs *c, struct jset_entry *entry)
|
||||||
{
|
{
|
||||||
struct btree_root *r = &c->btree_roots[entry->btree_id];
|
struct btree_root *r = bch2_btree_id_root(c, entry->btree_id);
|
||||||
|
|
||||||
mutex_lock(&c->btree_root_lock);
|
mutex_lock(&c->btree_root_lock);
|
||||||
|
|
||||||
@ -2430,15 +2428,15 @@ bch2_btree_roots_to_journal_entries(struct bch_fs *c,
|
|||||||
|
|
||||||
mutex_lock(&c->btree_root_lock);
|
mutex_lock(&c->btree_root_lock);
|
||||||
|
|
||||||
for (i = 0; i < BTREE_ID_NR; i++)
|
for (i = 0; i < btree_id_nr_alive(c); i++) {
|
||||||
if (c->btree_roots[i].alive && !test_bit(i, &have)) {
|
struct btree_root *r = bch2_btree_id_root(c, i);
|
||||||
journal_entry_set(end,
|
|
||||||
BCH_JSET_ENTRY_btree_root,
|
if (r->alive && !test_bit(i, &have)) {
|
||||||
i, c->btree_roots[i].level,
|
journal_entry_set(end, BCH_JSET_ENTRY_btree_root,
|
||||||
&c->btree_roots[i].key,
|
i, r->level, &r->key, r->key.k.u64s);
|
||||||
c->btree_roots[i].key.k.u64s);
|
|
||||||
end = vstruct_next(end);
|
end = vstruct_next(end);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&c->btree_root_lock);
|
mutex_unlock(&c->btree_root_lock);
|
||||||
|
|
||||||
@ -2452,7 +2450,7 @@ void bch2_fs_btree_interior_update_exit(struct bch_fs *c)
|
|||||||
mempool_exit(&c->btree_interior_update_pool);
|
mempool_exit(&c->btree_interior_update_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bch2_fs_btree_interior_update_init(struct bch_fs *c)
|
void bch2_fs_btree_interior_update_init_early(struct bch_fs *c)
|
||||||
{
|
{
|
||||||
mutex_init(&c->btree_reserve_cache_lock);
|
mutex_init(&c->btree_reserve_cache_lock);
|
||||||
INIT_LIST_HEAD(&c->btree_interior_update_list);
|
INIT_LIST_HEAD(&c->btree_interior_update_list);
|
||||||
@ -2462,7 +2460,10 @@ int bch2_fs_btree_interior_update_init(struct bch_fs *c)
|
|||||||
|
|
||||||
INIT_LIST_HEAD(&c->pending_node_rewrites);
|
INIT_LIST_HEAD(&c->pending_node_rewrites);
|
||||||
mutex_init(&c->pending_node_rewrites_lock);
|
mutex_init(&c->pending_node_rewrites_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bch2_fs_btree_interior_update_init(struct bch_fs *c)
|
||||||
|
{
|
||||||
c->btree_interior_update_worker =
|
c->btree_interior_update_worker =
|
||||||
alloc_workqueue("btree_update", WQ_UNBOUND|WQ_MEM_RECLAIM, 1);
|
alloc_workqueue("btree_update", WQ_UNBOUND|WQ_MEM_RECLAIM, 1);
|
||||||
if (!c->btree_interior_update_worker)
|
if (!c->btree_interior_update_worker)
|
||||||
|
@ -322,6 +322,7 @@ void bch2_do_pending_node_rewrites(struct bch_fs *);
|
|||||||
void bch2_free_pending_node_rewrites(struct bch_fs *);
|
void bch2_free_pending_node_rewrites(struct bch_fs *);
|
||||||
|
|
||||||
void bch2_fs_btree_interior_update_exit(struct bch_fs *);
|
void bch2_fs_btree_interior_update_exit(struct bch_fs *);
|
||||||
|
void bch2_fs_btree_interior_update_init_early(struct bch_fs *);
|
||||||
int bch2_fs_btree_interior_update_init(struct bch_fs *);
|
int bch2_fs_btree_interior_update_init(struct bch_fs *);
|
||||||
|
|
||||||
#endif /* _BCACHEFS_BTREE_UPDATE_INTERIOR_H */
|
#endif /* _BCACHEFS_BTREE_UPDATE_INTERIOR_H */
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
* bch2_btree_path_peek_slot() for a cached iterator might return a key in a
|
* bch2_btree_path_peek_slot() for a cached iterator might return a key in a
|
||||||
* different snapshot:
|
* different snapshot:
|
||||||
*/
|
*/
|
||||||
struct bkey_s_c bch2_btree_path_peek_slot_exact(struct btree_path *path, struct bkey *u)
|
static struct bkey_s_c bch2_btree_path_peek_slot_exact(struct btree_path *path, struct bkey *u)
|
||||||
{
|
{
|
||||||
struct bkey_s_c k = bch2_btree_path_peek_slot(path, u);
|
struct bkey_s_c k = bch2_btree_path_peek_slot(path, u);
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned flags,
|
|||||||
bch2_journal_preres_get(&trans->c->journal,
|
bch2_journal_preres_get(&trans->c->journal,
|
||||||
&trans->journal_preres,
|
&trans->journal_preres,
|
||||||
trans->journal_preres_u64s,
|
trans->journal_preres_u64s,
|
||||||
(flags & JOURNAL_WATERMARK_MASK)));
|
(flags & BCH_WATERMARK_MASK)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline int bch2_trans_journal_res_get(struct btree_trans *trans,
|
static __always_inline int bch2_trans_journal_res_get(struct btree_trans *trans,
|
||||||
@ -407,6 +407,8 @@ static int run_one_mem_trigger(struct btree_trans *trans,
|
|||||||
{
|
{
|
||||||
struct bkey_s_c old = { &i->old_k, i->old_v };
|
struct bkey_s_c old = { &i->old_k, i->old_v };
|
||||||
struct bkey_i *new = i->k;
|
struct bkey_i *new = i->k;
|
||||||
|
const struct bkey_ops *old_ops = bch2_bkey_type_ops(old.k->type);
|
||||||
|
const struct bkey_ops *new_ops = bch2_bkey_type_ops(i->k->k.type);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
verify_update_old_key(trans, i);
|
verify_update_old_key(trans, i);
|
||||||
@ -417,8 +419,7 @@ static int run_one_mem_trigger(struct btree_trans *trans,
|
|||||||
if (!btree_node_type_needs_gc(i->btree_id))
|
if (!btree_node_type_needs_gc(i->btree_id))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (bch2_bkey_ops[old.k->type].atomic_trigger ==
|
if (old_ops->atomic_trigger == new_ops->atomic_trigger) {
|
||||||
bch2_bkey_ops[i->k->k.type].atomic_trigger) {
|
|
||||||
ret = bch2_mark_key(trans, i->btree_id, i->level,
|
ret = bch2_mark_key(trans, i->btree_id, i->level,
|
||||||
old, bkey_i_to_s_c(new),
|
old, bkey_i_to_s_c(new),
|
||||||
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags);
|
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags);
|
||||||
@ -449,6 +450,8 @@ static int run_one_trans_trigger(struct btree_trans *trans, struct btree_insert_
|
|||||||
*/
|
*/
|
||||||
struct bkey old_k = i->old_k;
|
struct bkey old_k = i->old_k;
|
||||||
struct bkey_s_c old = { &old_k, i->old_v };
|
struct bkey_s_c old = { &old_k, i->old_v };
|
||||||
|
const struct bkey_ops *old_ops = bch2_bkey_type_ops(old.k->type);
|
||||||
|
const struct bkey_ops *new_ops = bch2_bkey_type_ops(i->k->k.type);
|
||||||
|
|
||||||
verify_update_old_key(trans, i);
|
verify_update_old_key(trans, i);
|
||||||
|
|
||||||
@ -458,8 +461,7 @@ static int run_one_trans_trigger(struct btree_trans *trans, struct btree_insert_
|
|||||||
|
|
||||||
if (!i->insert_trigger_run &&
|
if (!i->insert_trigger_run &&
|
||||||
!i->overwrite_trigger_run &&
|
!i->overwrite_trigger_run &&
|
||||||
bch2_bkey_ops[old.k->type].trans_trigger ==
|
old_ops->trans_trigger == new_ops->trans_trigger) {
|
||||||
bch2_bkey_ops[i->k->k.type].trans_trigger) {
|
|
||||||
i->overwrite_trigger_run = true;
|
i->overwrite_trigger_run = true;
|
||||||
i->insert_trigger_run = true;
|
i->insert_trigger_run = true;
|
||||||
return bch2_trans_mark_key(trans, i->btree_id, i->level, old, i->k,
|
return bch2_trans_mark_key(trans, i->btree_id, i->level, old, i->k,
|
||||||
@ -634,7 +636,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||||||
*/
|
*/
|
||||||
if (likely(!(flags & BTREE_INSERT_JOURNAL_REPLAY))) {
|
if (likely(!(flags & BTREE_INSERT_JOURNAL_REPLAY))) {
|
||||||
ret = bch2_trans_journal_res_get(trans,
|
ret = bch2_trans_journal_res_get(trans,
|
||||||
(flags & JOURNAL_WATERMARK_MASK)|
|
(flags & BCH_WATERMARK_MASK)|
|
||||||
JOURNAL_RES_GET_NONBLOCK);
|
JOURNAL_RES_GET_NONBLOCK);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -852,10 +854,13 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags
|
|||||||
struct printbuf buf = PRINTBUF;
|
struct printbuf buf = PRINTBUF;
|
||||||
|
|
||||||
trans_for_each_update(trans, i) {
|
trans_for_each_update(trans, i) {
|
||||||
int rw = (flags & BTREE_INSERT_JOURNAL_REPLAY) ? READ : WRITE;
|
enum bkey_invalid_flags invalid_flags = 0;
|
||||||
|
|
||||||
|
if (!(flags & BTREE_INSERT_JOURNAL_REPLAY))
|
||||||
|
invalid_flags |= BKEY_INVALID_WRITE|BKEY_INVALID_COMMIT;
|
||||||
|
|
||||||
if (unlikely(bch2_bkey_invalid(c, bkey_i_to_s_c(i->k),
|
if (unlikely(bch2_bkey_invalid(c, bkey_i_to_s_c(i->k),
|
||||||
i->bkey_type, rw, &buf)))
|
i->bkey_type, invalid_flags, &buf)))
|
||||||
return bch2_trans_commit_bkey_invalid(trans, flags, i, &buf);
|
return bch2_trans_commit_bkey_invalid(trans, flags, i, &buf);
|
||||||
btree_insert_entry_checks(trans, i);
|
btree_insert_entry_checks(trans, i);
|
||||||
}
|
}
|
||||||
@ -883,7 +888,7 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags
|
|||||||
|
|
||||||
ret = bch2_journal_preres_get(&c->journal,
|
ret = bch2_journal_preres_get(&c->journal,
|
||||||
&trans->journal_preres, trans->journal_preres_u64s,
|
&trans->journal_preres, trans->journal_preres_u64s,
|
||||||
(flags & JOURNAL_WATERMARK_MASK)|JOURNAL_RES_GET_NONBLOCK);
|
(flags & BCH_WATERMARK_MASK)|JOURNAL_RES_GET_NONBLOCK);
|
||||||
if (unlikely(ret == -BCH_ERR_journal_preres_get_blocked))
|
if (unlikely(ret == -BCH_ERR_journal_preres_get_blocked))
|
||||||
ret = bch2_trans_journal_preres_get_cold(trans, flags, trace_ip);
|
ret = bch2_trans_journal_preres_get_cold(trans, flags, trace_ip);
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
@ -950,14 +955,14 @@ int bch2_trans_commit_error(struct btree_trans *trans, unsigned flags,
|
|||||||
break;
|
break;
|
||||||
case -BCH_ERR_journal_res_get_blocked:
|
case -BCH_ERR_journal_res_get_blocked:
|
||||||
if ((flags & BTREE_INSERT_JOURNAL_RECLAIM) &&
|
if ((flags & BTREE_INSERT_JOURNAL_RECLAIM) &&
|
||||||
!(flags & JOURNAL_WATERMARK_reserved)) {
|
(flags & BCH_WATERMARK_MASK) != BCH_WATERMARK_reclaim) {
|
||||||
ret = -BCH_ERR_journal_reclaim_would_deadlock;
|
ret = -BCH_ERR_journal_reclaim_would_deadlock;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = drop_locks_do(trans,
|
ret = drop_locks_do(trans,
|
||||||
bch2_trans_journal_res_get(trans,
|
bch2_trans_journal_res_get(trans,
|
||||||
(flags & JOURNAL_WATERMARK_MASK)|
|
(flags & BCH_WATERMARK_MASK)|
|
||||||
JOURNAL_RES_GET_CHECK));
|
JOURNAL_RES_GET_CHECK));
|
||||||
break;
|
break;
|
||||||
case -BCH_ERR_btree_insert_need_journal_reclaim:
|
case -BCH_ERR_btree_insert_need_journal_reclaim:
|
||||||
@ -2044,7 +2049,7 @@ int bch2_journal_log_msg(struct bch_fs *c, const char *fmt, ...)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ret = __bch2_fs_log_msg(c, JOURNAL_WATERMARK_reserved, fmt, args);
|
ret = __bch2_fs_log_msg(c, BCH_WATERMARK_reclaim, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,9 @@ slowpath:
|
|||||||
btree_write_buffered_journal_cmp,
|
btree_write_buffered_journal_cmp,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
commit_flags &= ~BCH_WATERMARK_MASK;
|
||||||
|
commit_flags |= BCH_WATERMARK_reclaim;
|
||||||
|
|
||||||
for (i = keys; i < keys + nr; i++) {
|
for (i = keys; i < keys + nr; i++) {
|
||||||
if (!i->journal_seq)
|
if (!i->journal_seq)
|
||||||
continue;
|
continue;
|
||||||
@ -231,8 +234,7 @@ slowpath:
|
|||||||
ret = commit_do(trans, NULL, NULL,
|
ret = commit_do(trans, NULL, NULL,
|
||||||
commit_flags|
|
commit_flags|
|
||||||
BTREE_INSERT_NOFAIL|
|
BTREE_INSERT_NOFAIL|
|
||||||
BTREE_INSERT_JOURNAL_RECLAIM|
|
BTREE_INSERT_JOURNAL_RECLAIM,
|
||||||
JOURNAL_WATERMARK_reserved,
|
|
||||||
__bch2_btree_insert(trans, i->btree, &i->k, 0));
|
__bch2_btree_insert(trans, i->btree, &i->k, 0));
|
||||||
if (bch2_fs_fatal_err_on(ret, c, "%s: insert error %s", __func__, bch2_err_str(ret)))
|
if (bch2_fs_fatal_err_on(ret, c, "%s: insert error %s", __func__, bch2_err_str(ret)))
|
||||||
break;
|
break;
|
||||||
|
@ -374,7 +374,7 @@ static inline int update_replicas(struct bch_fs *c, struct bkey_s_c k,
|
|||||||
struct bch_replicas_entry *r, s64 sectors,
|
struct bch_replicas_entry *r, s64 sectors,
|
||||||
unsigned journal_seq, bool gc)
|
unsigned journal_seq, bool gc)
|
||||||
{
|
{
|
||||||
struct bch_fs_usage __percpu *fs_usage;
|
struct bch_fs_usage *fs_usage;
|
||||||
int idx, ret = 0;
|
int idx, ret = 0;
|
||||||
struct printbuf buf = PRINTBUF;
|
struct printbuf buf = PRINTBUF;
|
||||||
|
|
||||||
@ -1149,7 +1149,7 @@ int bch2_mark_inode(struct btree_trans *trans,
|
|||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct bch_fs_usage __percpu *fs_usage;
|
struct bch_fs_usage *fs_usage;
|
||||||
u64 journal_seq = trans->journal_res.seq;
|
u64 journal_seq = trans->journal_res.seq;
|
||||||
|
|
||||||
if (flags & BTREE_TRIGGER_INSERT) {
|
if (flags & BTREE_TRIGGER_INSERT) {
|
||||||
@ -1180,7 +1180,7 @@ static int __mark_reservation(struct btree_trans *trans,
|
|||||||
struct bkey_s_c k, unsigned flags)
|
struct bkey_s_c k, unsigned flags)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct bch_fs_usage __percpu *fs_usage;
|
struct bch_fs_usage *fs_usage;
|
||||||
unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
|
unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
|
||||||
s64 sectors = (s64) k.k->size;
|
s64 sectors = (s64) k.k->size;
|
||||||
|
|
||||||
|
@ -170,6 +170,7 @@ static inline u64 bch2_dev_buckets_reserved(struct bch_dev *ca, enum bch_waterma
|
|||||||
reserved += ca->nr_btree_reserve;
|
reserved += ca->nr_btree_reserve;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case BCH_WATERMARK_btree_copygc:
|
case BCH_WATERMARK_btree_copygc:
|
||||||
|
case BCH_WATERMARK_reclaim:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
/* BCH_SB_FIELD_counters */
|
/* BCH_SB_FIELD_counters */
|
||||||
|
|
||||||
const char * const bch2_counter_names[] = {
|
static const char * const bch2_counter_names[] = {
|
||||||
#define x(t, n, ...) (#t),
|
#define x(t, n, ...) (#t),
|
||||||
BCH_PERSISTENT_COUNTERS()
|
BCH_PERSISTENT_COUNTERS()
|
||||||
#undef x
|
#undef x
|
||||||
@ -27,7 +27,7 @@ static int bch2_sb_counters_validate(struct bch_sb *sb,
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void bch2_sb_counters_to_text(struct printbuf *out, struct bch_sb *sb,
|
static void bch2_sb_counters_to_text(struct printbuf *out, struct bch_sb *sb,
|
||||||
struct bch_sb_field *f)
|
struct bch_sb_field *f)
|
||||||
{
|
{
|
||||||
struct bch_sb_field_counters *ctrs = field_to_type(f, counters);
|
struct bch_sb_field_counters *ctrs = field_to_type(f, counters);
|
||||||
|
@ -381,7 +381,7 @@ void bch2_update_unwritten_extent(struct btree_trans *trans,
|
|||||||
&update->op.devs_have,
|
&update->op.devs_have,
|
||||||
update->op.nr_replicas,
|
update->op.nr_replicas,
|
||||||
update->op.nr_replicas,
|
update->op.nr_replicas,
|
||||||
update->op.alloc_reserve,
|
update->op.watermark,
|
||||||
0, &cl, &wp);
|
0, &cl, &wp);
|
||||||
if (bch2_err_matches(ret, BCH_ERR_operation_blocked)) {
|
if (bch2_err_matches(ret, BCH_ERR_operation_blocked)) {
|
||||||
bch2_trans_unlock(trans);
|
bch2_trans_unlock(trans);
|
||||||
@ -458,8 +458,7 @@ int bch2_data_update_init(struct btree_trans *trans,
|
|||||||
m->op.compression_type =
|
m->op.compression_type =
|
||||||
bch2_compression_opt_to_type[io_opts.background_compression ?:
|
bch2_compression_opt_to_type[io_opts.background_compression ?:
|
||||||
io_opts.compression];
|
io_opts.compression];
|
||||||
if (m->data_opts.btree_insert_flags & BTREE_INSERT_USE_RESERVE)
|
m->op.watermark = m->data_opts.btree_insert_flags & BCH_WATERMARK_MASK;
|
||||||
m->op.alloc_reserve = BCH_WATERMARK_copygc;
|
|
||||||
|
|
||||||
bkey_for_each_ptr(ptrs, ptr)
|
bkey_for_each_ptr(ptrs, ptr)
|
||||||
percpu_ref_get(&bch_dev_bkey_exists(c, ptr->dev)->ref);
|
percpu_ref_get(&bch_dev_bkey_exists(c, ptr->dev)->ref);
|
||||||
|
@ -85,7 +85,8 @@ const struct bch_hash_desc bch2_dirent_hash_desc = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
|
struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
|
||||||
unsigned len;
|
unsigned len;
|
||||||
@ -219,7 +220,7 @@ int bch2_dirent_read_target(struct btree_trans *trans, subvol_inum dir,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (d.v->d_type == DT_SUBVOL &&
|
if (d.v->d_type == DT_SUBVOL &&
|
||||||
d.v->d_parent_subvol != dir.subvol)
|
le32_to_cpu(d.v->d_parent_subvol) != dir.subvol)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (likely(d.v->d_type != DT_SUBVOL)) {
|
if (likely(d.v->d_type != DT_SUBVOL)) {
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
#include "str_hash.h"
|
#include "str_hash.h"
|
||||||
|
|
||||||
|
enum bkey_invalid_flags;
|
||||||
extern const struct bch_hash_desc bch2_dirent_hash_desc;
|
extern const struct bch_hash_desc bch2_dirent_hash_desc;
|
||||||
|
|
||||||
int bch2_dirent_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_dirent_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_dirent_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_dirent_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
#define bch2_bkey_ops_dirent ((struct bkey_ops) { \
|
#define bch2_bkey_ops_dirent ((struct bkey_ops) { \
|
||||||
|
@ -105,7 +105,8 @@ struct ec_bio {
|
|||||||
/* Stripes btree keys: */
|
/* Stripes btree keys: */
|
||||||
|
|
||||||
int bch2_stripe_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_stripe_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
const struct bch_stripe *s = bkey_s_c_to_stripe(k).v;
|
const struct bch_stripe *s = bkey_s_c_to_stripe(k).v;
|
||||||
|
|
||||||
@ -385,7 +386,7 @@ static void ec_block_endio(struct bio *bio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
|
static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
|
||||||
unsigned rw, unsigned idx, struct closure *cl)
|
blk_opf_t opf, unsigned idx, struct closure *cl)
|
||||||
{
|
{
|
||||||
struct bch_stripe *v = &buf->key.v;
|
struct bch_stripe *v = &buf->key.v;
|
||||||
unsigned offset = 0, bytes = buf->size << 9;
|
unsigned offset = 0, bytes = buf->size << 9;
|
||||||
@ -394,6 +395,7 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
|
|||||||
enum bch_data_type data_type = idx < buf->key.v.nr_blocks - buf->key.v.nr_redundant
|
enum bch_data_type data_type = idx < buf->key.v.nr_blocks - buf->key.v.nr_redundant
|
||||||
? BCH_DATA_user
|
? BCH_DATA_user
|
||||||
: BCH_DATA_parity;
|
: BCH_DATA_parity;
|
||||||
|
int rw = op_is_write(opf);
|
||||||
|
|
||||||
if (ptr_stale(ca, ptr)) {
|
if (ptr_stale(ca, ptr)) {
|
||||||
bch_err_ratelimited(c,
|
bch_err_ratelimited(c,
|
||||||
@ -419,7 +421,7 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
|
|||||||
|
|
||||||
ec_bio = container_of(bio_alloc_bioset(ca->disk_sb.bdev,
|
ec_bio = container_of(bio_alloc_bioset(ca->disk_sb.bdev,
|
||||||
nr_iovecs,
|
nr_iovecs,
|
||||||
rw,
|
opf,
|
||||||
GFP_KERNEL,
|
GFP_KERNEL,
|
||||||
&c->ec_bioset),
|
&c->ec_bioset),
|
||||||
struct ec_bio, bio);
|
struct ec_bio, bio);
|
||||||
@ -1380,11 +1382,12 @@ void bch2_ec_stripe_head_put(struct bch_fs *c, struct ec_stripe_head *h)
|
|||||||
mutex_unlock(&h->lock);
|
mutex_unlock(&h->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ec_stripe_head *__bch2_ec_stripe_head_get(struct btree_trans *trans,
|
static struct ec_stripe_head *
|
||||||
unsigned target,
|
__bch2_ec_stripe_head_get(struct btree_trans *trans,
|
||||||
unsigned algo,
|
unsigned target,
|
||||||
unsigned redundancy,
|
unsigned algo,
|
||||||
enum bch_watermark watermark)
|
unsigned redundancy,
|
||||||
|
enum bch_watermark watermark)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct ec_stripe_head *h;
|
struct ec_stripe_head *h;
|
||||||
@ -1570,7 +1573,7 @@ static int __bch2_ec_stripe_head_reuse(struct btree_trans *trans, struct ec_stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
BUG_ON(h->s->existing_stripe.size != h->blocksize);
|
BUG_ON(h->s->existing_stripe.size != h->blocksize);
|
||||||
BUG_ON(h->s->existing_stripe.size != h->s->existing_stripe.key.v.sectors);
|
BUG_ON(h->s->existing_stripe.size != le16_to_cpu(h->s->existing_stripe.key.v.sectors));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free buckets we initially allocated - they might conflict with
|
* Free buckets we initially allocated - they might conflict with
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
#include "buckets_types.h"
|
#include "buckets_types.h"
|
||||||
#include "extents_types.h"
|
#include "extents_types.h"
|
||||||
|
|
||||||
|
enum bkey_invalid_flags;
|
||||||
|
|
||||||
int bch2_stripe_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_stripe_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_stripe_to_text(struct printbuf *, struct bch_fs *,
|
void bch2_stripe_to_text(struct printbuf *, struct bch_fs *,
|
||||||
struct bkey_s_c);
|
struct bkey_s_c);
|
||||||
|
|
||||||
|
@ -163,7 +163,8 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
|
|||||||
/* KEY_TYPE_btree_ptr: */
|
/* KEY_TYPE_btree_ptr: */
|
||||||
|
|
||||||
int bch2_btree_ptr_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_btree_ptr_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (bkey_val_u64s(k.k) > BCH_REPLICAS_MAX) {
|
if (bkey_val_u64s(k.k) > BCH_REPLICAS_MAX) {
|
||||||
prt_printf(err, "value too big (%zu > %u)",
|
prt_printf(err, "value too big (%zu > %u)",
|
||||||
@ -181,7 +182,8 @@ void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_btree_ptr_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_btree_ptr_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (bkey_val_u64s(k.k) > BKEY_BTREE_PTR_VAL_U64s_MAX) {
|
if (bkey_val_u64s(k.k) > BKEY_BTREE_PTR_VAL_U64s_MAX) {
|
||||||
prt_printf(err, "value too big (%zu > %zu)",
|
prt_printf(err, "value too big (%zu > %zu)",
|
||||||
@ -216,7 +218,7 @@ void bch2_btree_ptr_v2_compat(enum btree_id btree_id, unsigned version,
|
|||||||
compat_bpos(0, btree_id, version, big_endian, write, &bp.v->min_key);
|
compat_bpos(0, btree_id, version, big_endian, write, &bp.v->min_key);
|
||||||
|
|
||||||
if (version < bcachefs_metadata_version_inode_btree_change &&
|
if (version < bcachefs_metadata_version_inode_btree_change &&
|
||||||
btree_node_type_is_extents(btree_id) &&
|
btree_id_is_extents(btree_id) &&
|
||||||
!bkey_eq(bp.v->min_key, POS_MIN))
|
!bkey_eq(bp.v->min_key, POS_MIN))
|
||||||
bp.v->min_key = write
|
bp.v->min_key = write
|
||||||
? bpos_nosnap_predecessor(bp.v->min_key)
|
? bpos_nosnap_predecessor(bp.v->min_key)
|
||||||
@ -371,7 +373,8 @@ bool bch2_extent_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
|
|||||||
/* KEY_TYPE_reservation: */
|
/* KEY_TYPE_reservation: */
|
||||||
|
|
||||||
int bch2_reservation_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_reservation_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_reservation r = bkey_s_c_to_reservation(k);
|
struct bkey_s_c_reservation r = bkey_s_c_to_reservation(k);
|
||||||
|
|
||||||
@ -514,7 +517,7 @@ static void bch2_extent_crc_pack(union bch_extent_crc *dst,
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case BCH_EXTENT_ENTRY_crc32:
|
case BCH_EXTENT_ENTRY_crc32:
|
||||||
set_common_fields(dst->crc32, src);
|
set_common_fields(dst->crc32, src);
|
||||||
dst->crc32.csum = *((__le32 *) &src.csum.lo);
|
memcpy(&dst->crc32.csum, &src.csum.lo, sizeof(dst->crc32.csum));
|
||||||
break;
|
break;
|
||||||
case BCH_EXTENT_ENTRY_crc64:
|
case BCH_EXTENT_ENTRY_crc64:
|
||||||
set_common_fields(dst->crc64, src);
|
set_common_fields(dst->crc64, src);
|
||||||
@ -1103,7 +1106,8 @@ static int extent_ptr_invalid(const struct bch_fs *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
|
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
|
||||||
const union bch_extent_entry *entry;
|
const union bch_extent_entry *entry;
|
||||||
@ -1202,6 +1206,8 @@ int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
have_ec = true;
|
have_ec = true;
|
||||||
break;
|
break;
|
||||||
|
case BCH_EXTENT_ENTRY_rebalance:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1260,6 +1266,8 @@ void bch2_ptr_swab(struct bkey_s k)
|
|||||||
break;
|
break;
|
||||||
case BCH_EXTENT_ENTRY_stripe_ptr:
|
case BCH_EXTENT_ENTRY_stripe_ptr:
|
||||||
break;
|
break;
|
||||||
|
case BCH_EXTENT_ENTRY_rebalance:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1310,6 +1318,8 @@ int bch2_cut_front_s(struct bpos where, struct bkey_s k)
|
|||||||
break;
|
break;
|
||||||
case BCH_EXTENT_ENTRY_stripe_ptr:
|
case BCH_EXTENT_ENTRY_stripe_ptr:
|
||||||
break;
|
break;
|
||||||
|
case BCH_EXTENT_ENTRY_rebalance:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extent_entry_is_crc(entry))
|
if (extent_entry_is_crc(entry))
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
struct bch_fs;
|
struct bch_fs;
|
||||||
struct btree_trans;
|
struct btree_trans;
|
||||||
|
enum bkey_invalid_flags;
|
||||||
|
|
||||||
/* extent entries: */
|
/* extent entries: */
|
||||||
|
|
||||||
@ -154,11 +155,7 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc)
|
|||||||
common_fields(crc->crc32),
|
common_fields(crc->crc32),
|
||||||
};
|
};
|
||||||
|
|
||||||
*((__le32 *) &ret.csum.lo) = crc->crc32.csum;
|
memcpy(&ret.csum.lo, &crc->crc32.csum, sizeof(crc->crc32.csum));
|
||||||
|
|
||||||
memcpy(&ret.csum.lo, &crc->crc32.csum,
|
|
||||||
sizeof(crc->crc32.csum));
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
case BCH_EXTENT_ENTRY_crc64: {
|
case BCH_EXTENT_ENTRY_crc64: {
|
||||||
@ -168,8 +165,8 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc)
|
|||||||
.csum.lo = (__force __le64) crc->crc64.csum_lo,
|
.csum.lo = (__force __le64) crc->crc64.csum_lo,
|
||||||
};
|
};
|
||||||
|
|
||||||
*((__le16 *) &ret.csum.hi) = crc->crc64.csum_hi;
|
u16 hi = crc->crc64.csum_hi;
|
||||||
|
memcpy(&ret.csum.hi, &hi, sizeof(hi));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
case BCH_EXTENT_ENTRY_crc128: {
|
case BCH_EXTENT_ENTRY_crc128: {
|
||||||
@ -318,6 +315,9 @@ static inline struct bkey_ptrs bch2_bkey_ptrs(struct bkey_s k)
|
|||||||
(_ptr).ec = _entry->stripe_ptr; \
|
(_ptr).ec = _entry->stripe_ptr; \
|
||||||
(_ptr).has_ec = true; \
|
(_ptr).has_ec = true; \
|
||||||
break; \
|
break; \
|
||||||
|
default: \
|
||||||
|
/* nothing */ \
|
||||||
|
break; \
|
||||||
} \
|
} \
|
||||||
out: \
|
out: \
|
||||||
_entry < (_end); \
|
_entry < (_end); \
|
||||||
@ -383,11 +383,13 @@ int bch2_bkey_pick_read_device(struct bch_fs *, struct bkey_s_c,
|
|||||||
|
|
||||||
/* KEY_TYPE_btree_ptr: */
|
/* KEY_TYPE_btree_ptr: */
|
||||||
|
|
||||||
int bch2_btree_ptr_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_btree_ptr_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *,
|
void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *,
|
||||||
struct bkey_s_c);
|
struct bkey_s_c);
|
||||||
|
|
||||||
int bch2_btree_ptr_v2_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_btree_ptr_v2_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_btree_ptr_v2_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_btree_ptr_v2_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned,
|
void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned,
|
||||||
int, struct bkey_s);
|
int, struct bkey_s);
|
||||||
@ -427,7 +429,7 @@ bool bch2_extent_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
|||||||
/* KEY_TYPE_reservation: */
|
/* KEY_TYPE_reservation: */
|
||||||
|
|
||||||
int bch2_reservation_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_reservation_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_reservation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_reservation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
bool bch2_reservation_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
bool bch2_reservation_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
||||||
|
|
||||||
|
@ -458,7 +458,7 @@ enum bch_folio_sector_state {
|
|||||||
#undef x
|
#undef x
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * const bch2_folio_sector_states[] = {
|
static const char * const bch2_folio_sector_states[] = {
|
||||||
#define x(n) #n,
|
#define x(n) #n,
|
||||||
BCH_FOLIO_SECTOR_STATE()
|
BCH_FOLIO_SECTOR_STATE()
|
||||||
#undef x
|
#undef x
|
||||||
@ -997,7 +997,7 @@ vm_fault_t bch2_page_fault(struct vm_fault *vmf)
|
|||||||
struct address_space *mapping = file->f_mapping;
|
struct address_space *mapping = file->f_mapping;
|
||||||
struct address_space *fdm = faults_disabled_mapping();
|
struct address_space *fdm = faults_disabled_mapping();
|
||||||
struct bch_inode_info *inode = file_bch_inode(file);
|
struct bch_inode_info *inode = file_bch_inode(file);
|
||||||
int ret;
|
vm_fault_t ret;
|
||||||
|
|
||||||
if (fdm == mapping)
|
if (fdm == mapping)
|
||||||
return VM_FAULT_SIGBUS;
|
return VM_FAULT_SIGBUS;
|
||||||
@ -1039,7 +1039,7 @@ vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf)
|
|||||||
struct bch2_folio_reservation res;
|
struct bch2_folio_reservation res;
|
||||||
unsigned len;
|
unsigned len;
|
||||||
loff_t isize;
|
loff_t isize;
|
||||||
int ret;
|
vm_fault_t ret;
|
||||||
|
|
||||||
bch2_folio_reservation_init(c, inode, &res);
|
bch2_folio_reservation_init(c, inode, &res);
|
||||||
|
|
||||||
|
@ -1216,7 +1216,7 @@ static int check_overlapping_extents(struct btree_trans *trans,
|
|||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (fsck_err(c, buf.buf)) {
|
if (fsck_err(c, "%s", buf.buf)) {
|
||||||
struct bkey_i *update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
|
struct bkey_i *update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
|
||||||
if ((ret = PTR_ERR_OR_ZERO(update)))
|
if ((ret = PTR_ERR_OR_ZERO(update)))
|
||||||
goto err;
|
goto err;
|
||||||
@ -1696,8 +1696,8 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (fsck_err_on(ret, c,
|
if (fsck_err_on(ret, c,
|
||||||
"dirent points to missing subvolume %llu",
|
"dirent points to missing subvolume %u",
|
||||||
le64_to_cpu(d.v->d_child_subvol))) {
|
le32_to_cpu(d.v->d_child_subvol))) {
|
||||||
ret = __remove_dirent(trans, d.k->p);
|
ret = __remove_dirent(trans, d.k->p);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -2238,7 +2238,7 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
|
|||||||
* Backpointer and directory structure checks are sufficient for
|
* Backpointer and directory structure checks are sufficient for
|
||||||
* directories, since they can't have hardlinks:
|
* directories, since they can't have hardlinks:
|
||||||
*/
|
*/
|
||||||
if (S_ISDIR(le16_to_cpu(u.bi_mode)))
|
if (S_ISDIR(u.bi_mode))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!u.bi_nlink)
|
if (!u.bi_nlink)
|
||||||
@ -2324,7 +2324,7 @@ static int check_nlinks_update_inode(struct btree_trans *trans, struct btree_ite
|
|||||||
|
|
||||||
BUG_ON(bch2_inode_unpack(k, &u));
|
BUG_ON(bch2_inode_unpack(k, &u));
|
||||||
|
|
||||||
if (S_ISDIR(le16_to_cpu(u.bi_mode)))
|
if (S_ISDIR(u.bi_mode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!u.bi_nlink)
|
if (!u.bi_nlink)
|
||||||
|
@ -432,7 +432,8 @@ static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_inode inode = bkey_s_c_to_inode(k);
|
struct bkey_s_c_inode inode = bkey_s_c_to_inode(k);
|
||||||
|
|
||||||
@ -446,7 +447,8 @@ int bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_inode_v2 inode = bkey_s_c_to_inode_v2(k);
|
struct bkey_s_c_inode_v2 inode = bkey_s_c_to_inode_v2(k);
|
||||||
|
|
||||||
@ -460,7 +462,8 @@ int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_inode_v3_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_inode_v3_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_inode_v3 inode = bkey_s_c_to_inode_v3(k);
|
struct bkey_s_c_inode_v3 inode = bkey_s_c_to_inode_v3(k);
|
||||||
|
|
||||||
@ -517,7 +520,8 @@ void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_inode_generation_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_inode_generation_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (k.k->p.inode) {
|
if (k.k->p.inode) {
|
||||||
prt_printf(err, "nonzero k.p.inode");
|
prt_printf(err, "nonzero k.p.inode");
|
||||||
|
@ -5,11 +5,15 @@
|
|||||||
#include "bkey.h"
|
#include "bkey.h"
|
||||||
#include "opts.h"
|
#include "opts.h"
|
||||||
|
|
||||||
|
enum bkey_invalid_flags;
|
||||||
extern const char * const bch2_inode_opts[];
|
extern const char * const bch2_inode_opts[];
|
||||||
|
|
||||||
int bch2_inode_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_inode_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
int bch2_inode_v2_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
int bch2_inode_v3_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_inode_v2_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
|
int bch2_inode_v3_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_inode_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_inode_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
#define bch2_bkey_ops_inode ((struct bkey_ops) { \
|
#define bch2_bkey_ops_inode ((struct bkey_ops) { \
|
||||||
@ -44,7 +48,7 @@ static inline bool bkey_is_inode(const struct bkey *k)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_inode_generation_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_inode_generation_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_inode_generation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_inode_generation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
#define bch2_bkey_ops_inode_generation ((struct bkey_ops) { \
|
#define bch2_bkey_ops_inode_generation ((struct bkey_ops) { \
|
||||||
|
@ -1696,7 +1696,7 @@ again:
|
|||||||
&op->devs_have,
|
&op->devs_have,
|
||||||
op->nr_replicas,
|
op->nr_replicas,
|
||||||
op->nr_replicas_required,
|
op->nr_replicas_required,
|
||||||
op->alloc_reserve,
|
op->watermark,
|
||||||
op->flags,
|
op->flags,
|
||||||
(op->flags & (BCH_WRITE_ALLOC_NOWAIT|
|
(op->flags & (BCH_WRITE_ALLOC_NOWAIT|
|
||||||
BCH_WRITE_ONLY_SPECIFIED_DEVS))
|
BCH_WRITE_ONLY_SPECIFIED_DEVS))
|
||||||
@ -1878,7 +1878,7 @@ err:
|
|||||||
op->end_io(op);
|
op->end_io(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * const bch2_write_flags[] = {
|
static const char * const bch2_write_flags[] = {
|
||||||
#define x(f) #f,
|
#define x(f) #f,
|
||||||
BCH_WRITE_FLAGS()
|
BCH_WRITE_FLAGS()
|
||||||
#undef x
|
#undef x
|
||||||
|
@ -59,7 +59,7 @@ enum bch_write_flags {
|
|||||||
|
|
||||||
static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op)
|
static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op)
|
||||||
{
|
{
|
||||||
return op->alloc_reserve == BCH_WATERMARK_copygc
|
return op->watermark == BCH_WATERMARK_copygc
|
||||||
? op->c->copygc_wq
|
? op->c->copygc_wq
|
||||||
: op->c->btree_update_wq;
|
: op->c->btree_update_wq;
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c,
|
|||||||
op->compression_type = bch2_compression_opt_to_type[opts.compression];
|
op->compression_type = bch2_compression_opt_to_type[opts.compression];
|
||||||
op->nr_replicas = 0;
|
op->nr_replicas = 0;
|
||||||
op->nr_replicas_required = c->opts.data_replicas_required;
|
op->nr_replicas_required = c->opts.data_replicas_required;
|
||||||
op->alloc_reserve = BCH_WATERMARK_normal;
|
op->watermark = BCH_WATERMARK_normal;
|
||||||
op->incompressible = 0;
|
op->incompressible = 0;
|
||||||
op->open_buckets.nr = 0;
|
op->open_buckets.nr = 0;
|
||||||
op->devs_have.nr = 0;
|
op->devs_have.nr = 0;
|
||||||
|
@ -119,7 +119,7 @@ struct bch_write_op {
|
|||||||
unsigned compression_type:4;
|
unsigned compression_type:4;
|
||||||
unsigned nr_replicas:4;
|
unsigned nr_replicas:4;
|
||||||
unsigned nr_replicas_required:4;
|
unsigned nr_replicas_required:4;
|
||||||
unsigned alloc_reserve:3;
|
unsigned watermark:3;
|
||||||
unsigned incompressible:1;
|
unsigned incompressible:1;
|
||||||
unsigned stripe_waited:1;
|
unsigned stripe_waited:1;
|
||||||
|
|
||||||
|
@ -19,17 +19,12 @@
|
|||||||
#include "journal_seq_blacklist.h"
|
#include "journal_seq_blacklist.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
#define x(n) #n,
|
|
||||||
static const char * const bch2_journal_watermarks[] = {
|
|
||||||
JOURNAL_WATERMARKS()
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char * const bch2_journal_errors[] = {
|
static const char * const bch2_journal_errors[] = {
|
||||||
|
#define x(n) #n,
|
||||||
JOURNAL_ERRORS()
|
JOURNAL_ERRORS()
|
||||||
|
#undef x
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
#undef x
|
|
||||||
|
|
||||||
static inline bool journal_seq_unwritten(struct journal *j, u64 seq)
|
static inline bool journal_seq_unwritten(struct journal *j, u64 seq)
|
||||||
{
|
{
|
||||||
@ -96,7 +91,7 @@ journal_error_check_stuck(struct journal *j, int error, unsigned flags)
|
|||||||
if (!(error == JOURNAL_ERR_journal_full ||
|
if (!(error == JOURNAL_ERR_journal_full ||
|
||||||
error == JOURNAL_ERR_journal_pin_full) ||
|
error == JOURNAL_ERR_journal_pin_full) ||
|
||||||
nr_unwritten_journal_entries(j) ||
|
nr_unwritten_journal_entries(j) ||
|
||||||
(flags & JOURNAL_WATERMARK_MASK) != JOURNAL_WATERMARK_reserved)
|
(flags & BCH_WATERMARK_MASK) != BCH_WATERMARK_reclaim)
|
||||||
return stuck;
|
return stuck;
|
||||||
|
|
||||||
spin_lock(&j->lock);
|
spin_lock(&j->lock);
|
||||||
@ -440,7 +435,7 @@ retry:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & JOURNAL_WATERMARK_MASK) < j->watermark) {
|
if ((flags & BCH_WATERMARK_MASK) < j->watermark) {
|
||||||
/*
|
/*
|
||||||
* Don't want to close current journal entry, just need to
|
* Don't want to close current journal entry, just need to
|
||||||
* invoke reclaim:
|
* invoke reclaim:
|
||||||
@ -1292,7 +1287,7 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
|
|||||||
prt_printf(out, "last_seq_ondisk:\t%llu\n", j->last_seq_ondisk);
|
prt_printf(out, "last_seq_ondisk:\t%llu\n", j->last_seq_ondisk);
|
||||||
prt_printf(out, "flushed_seq_ondisk:\t%llu\n", j->flushed_seq_ondisk);
|
prt_printf(out, "flushed_seq_ondisk:\t%llu\n", j->flushed_seq_ondisk);
|
||||||
prt_printf(out, "prereserved:\t\t%u/%u\n", j->prereserved.reserved, j->prereserved.remaining);
|
prt_printf(out, "prereserved:\t\t%u/%u\n", j->prereserved.reserved, j->prereserved.remaining);
|
||||||
prt_printf(out, "watermark:\t\t%s\n", bch2_journal_watermarks[j->watermark]);
|
prt_printf(out, "watermark:\t\t%s\n", bch2_watermarks[j->watermark]);
|
||||||
prt_printf(out, "each entry reserved:\t%u\n", j->entry_u64s_reserved);
|
prt_printf(out, "each entry reserved:\t%u\n", j->entry_u64s_reserved);
|
||||||
prt_printf(out, "nr flush writes:\t%llu\n", j->nr_flush_writes);
|
prt_printf(out, "nr flush writes:\t%llu\n", j->nr_flush_writes);
|
||||||
prt_printf(out, "nr noflush writes:\t%llu\n", j->nr_noflush_writes);
|
prt_printf(out, "nr noflush writes:\t%llu\n", j->nr_noflush_writes);
|
||||||
|
@ -294,9 +294,14 @@ static inline void bch2_journal_res_put(struct journal *j,
|
|||||||
int bch2_journal_res_get_slowpath(struct journal *, struct journal_res *,
|
int bch2_journal_res_get_slowpath(struct journal *, struct journal_res *,
|
||||||
unsigned);
|
unsigned);
|
||||||
|
|
||||||
/* First two bits for JOURNAL_WATERMARK: */
|
/* First bits for BCH_WATERMARK: */
|
||||||
#define JOURNAL_RES_GET_NONBLOCK (1 << 2)
|
enum journal_res_flags {
|
||||||
#define JOURNAL_RES_GET_CHECK (1 << 3)
|
__JOURNAL_RES_GET_NONBLOCK = BCH_WATERMARK_BITS,
|
||||||
|
__JOURNAL_RES_GET_CHECK,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define JOURNAL_RES_GET_NONBLOCK (1 << __JOURNAL_RES_GET_NONBLOCK)
|
||||||
|
#define JOURNAL_RES_GET_CHECK (1 << __JOURNAL_RES_GET_CHECK)
|
||||||
|
|
||||||
static inline int journal_res_get_fast(struct journal *j,
|
static inline int journal_res_get_fast(struct journal *j,
|
||||||
struct journal_res *res,
|
struct journal_res *res,
|
||||||
@ -317,7 +322,7 @@ static inline int journal_res_get_fast(struct journal *j,
|
|||||||
|
|
||||||
EBUG_ON(!journal_state_count(new, new.idx));
|
EBUG_ON(!journal_state_count(new, new.idx));
|
||||||
|
|
||||||
if ((flags & JOURNAL_WATERMARK_MASK) < j->watermark)
|
if ((flags & BCH_WATERMARK_MASK) < j->watermark)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
new.cur_entry_offset += res->u64s;
|
new.cur_entry_offset += res->u64s;
|
||||||
@ -373,17 +378,17 @@ out:
|
|||||||
static inline void journal_set_watermark(struct journal *j)
|
static inline void journal_set_watermark(struct journal *j)
|
||||||
{
|
{
|
||||||
union journal_preres_state s = READ_ONCE(j->prereserved);
|
union journal_preres_state s = READ_ONCE(j->prereserved);
|
||||||
unsigned watermark = JOURNAL_WATERMARK_any;
|
unsigned watermark = BCH_WATERMARK_stripe;
|
||||||
|
|
||||||
if (fifo_free(&j->pin) < j->pin.size / 4)
|
if (fifo_free(&j->pin) < j->pin.size / 4)
|
||||||
watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_copygc);
|
watermark = max_t(unsigned, watermark, BCH_WATERMARK_copygc);
|
||||||
if (fifo_free(&j->pin) < j->pin.size / 8)
|
if (fifo_free(&j->pin) < j->pin.size / 8)
|
||||||
watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_reserved);
|
watermark = max_t(unsigned, watermark, BCH_WATERMARK_reclaim);
|
||||||
|
|
||||||
if (s.reserved > s.remaining)
|
if (s.reserved > s.remaining)
|
||||||
watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_copygc);
|
watermark = max_t(unsigned, watermark, BCH_WATERMARK_copygc);
|
||||||
if (!s.remaining)
|
if (!s.remaining)
|
||||||
watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_reserved);
|
watermark = max_t(unsigned, watermark, BCH_WATERMARK_reclaim);
|
||||||
|
|
||||||
if (watermark == j->watermark)
|
if (watermark == j->watermark)
|
||||||
return;
|
return;
|
||||||
@ -426,13 +431,14 @@ static inline int bch2_journal_preres_get_fast(struct journal *j,
|
|||||||
int d = new_u64s - res->u64s;
|
int d = new_u64s - res->u64s;
|
||||||
union journal_preres_state old, new;
|
union journal_preres_state old, new;
|
||||||
u64 v = atomic64_read(&j->prereserved.counter);
|
u64 v = atomic64_read(&j->prereserved.counter);
|
||||||
|
enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
old.v = new.v = v;
|
old.v = new.v = v;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
if ((flags & JOURNAL_WATERMARK_reserved) ||
|
if (watermark == BCH_WATERMARK_reclaim ||
|
||||||
new.reserved + d < new.remaining) {
|
new.reserved + d < new.remaining) {
|
||||||
new.reserved += d;
|
new.reserved += d;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
@ -340,7 +340,8 @@ static int journal_entry_btree_keys_validate(struct bch_fs *c,
|
|||||||
int ret = journal_validate_key(c, jset, entry,
|
int ret = journal_validate_key(c, jset, entry,
|
||||||
entry->level,
|
entry->level,
|
||||||
entry->btree_id,
|
entry->btree_id,
|
||||||
k, version, big_endian, write|BKEY_INVALID_FROM_JOURNAL);
|
k, version, big_endian,
|
||||||
|
write|BKEY_INVALID_JOURNAL);
|
||||||
if (ret == FSCK_DELETED_KEY)
|
if (ret == FSCK_DELETED_KEY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -745,14 +746,10 @@ static int jset_validate(struct bch_fs *c,
|
|||||||
return JOURNAL_ENTRY_NONE;
|
return JOURNAL_ENTRY_NONE;
|
||||||
|
|
||||||
version = le32_to_cpu(jset->version);
|
version = le32_to_cpu(jset->version);
|
||||||
if (journal_entry_err_on((version != BCH_JSET_VERSION_OLD &&
|
if (journal_entry_err_on(!bch2_version_compatible(version), c, jset, NULL,
|
||||||
version < bcachefs_metadata_version_min) ||
|
"%s sector %llu seq %llu: incompatible journal entry version %u",
|
||||||
version >= bcachefs_metadata_version_max,
|
|
||||||
c, jset, NULL,
|
|
||||||
"%s sector %llu seq %llu: unknown journal entry version %u",
|
|
||||||
ca ? ca->name : c->name,
|
ca ? ca->name : c->name,
|
||||||
sector, le64_to_cpu(jset->seq),
|
sector, le64_to_cpu(jset->seq), version)) {
|
||||||
version)) {
|
|
||||||
/* don't try to continue: */
|
/* don't try to continue: */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -796,14 +793,10 @@ static int jset_validate_early(struct bch_fs *c,
|
|||||||
return JOURNAL_ENTRY_NONE;
|
return JOURNAL_ENTRY_NONE;
|
||||||
|
|
||||||
version = le32_to_cpu(jset->version);
|
version = le32_to_cpu(jset->version);
|
||||||
if (journal_entry_err_on((version != BCH_JSET_VERSION_OLD &&
|
if (journal_entry_err_on(!bch2_version_compatible(version), c, jset, NULL,
|
||||||
version < bcachefs_metadata_version_min) ||
|
|
||||||
version >= bcachefs_metadata_version_max,
|
|
||||||
c, jset, NULL,
|
|
||||||
"%s sector %llu seq %llu: unknown journal entry version %u",
|
"%s sector %llu seq %llu: unknown journal entry version %u",
|
||||||
ca ? ca->name : c->name,
|
ca ? ca->name : c->name,
|
||||||
sector, le64_to_cpu(jset->seq),
|
sector, le64_to_cpu(jset->seq), version)) {
|
||||||
version)) {
|
|
||||||
/* don't try to continue: */
|
/* don't try to continue: */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1505,7 +1498,7 @@ static void journal_write_done(struct closure *cl)
|
|||||||
* Must come before signaling write completion, for
|
* Must come before signaling write completion, for
|
||||||
* bch2_fs_journal_stop():
|
* bch2_fs_journal_stop():
|
||||||
*/
|
*/
|
||||||
if (j->watermark)
|
if (j->watermark != BCH_WATERMARK_stripe)
|
||||||
journal_reclaim_kick(&c->journal);
|
journal_reclaim_kick(&c->journal);
|
||||||
|
|
||||||
/* also must come before signalling write completion: */
|
/* also must come before signalling write completion: */
|
||||||
@ -1755,9 +1748,7 @@ void bch2_journal_write(struct closure *cl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
jset->magic = cpu_to_le64(jset_magic(c));
|
jset->magic = cpu_to_le64(jset_magic(c));
|
||||||
jset->version = c->sb.version < bcachefs_metadata_version_bkey_renumber
|
jset->version = cpu_to_le32(c->sb.version);
|
||||||
? cpu_to_le32(BCH_JSET_VERSION_OLD)
|
|
||||||
: cpu_to_le32(c->sb.version);
|
|
||||||
|
|
||||||
SET_JSET_BIG_ENDIAN(jset, CPU_BIG_ENDIAN);
|
SET_JSET_BIG_ENDIAN(jset, CPU_BIG_ENDIAN);
|
||||||
SET_JSET_CSUM_TYPE(jset, bch2_meta_checksum_type(c));
|
SET_JSET_CSUM_TYPE(jset, bch2_meta_checksum_type(c));
|
||||||
|
@ -361,7 +361,7 @@ void bch2_journal_pin_drop(struct journal *j,
|
|||||||
spin_unlock(&j->lock);
|
spin_unlock(&j->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum journal_pin_type journal_pin_type(journal_pin_flush_fn fn)
|
static enum journal_pin_type journal_pin_type(journal_pin_flush_fn fn)
|
||||||
{
|
{
|
||||||
if (fn == bch2_btree_node_flush0 ||
|
if (fn == bch2_btree_node_flush0 ||
|
||||||
fn == bch2_btree_node_flush1)
|
fn == bch2_btree_node_flush1)
|
||||||
@ -837,8 +837,20 @@ int bch2_journal_flush_device_pins(struct journal *j, int dev_idx)
|
|||||||
mutex_lock(&c->replicas_gc_lock);
|
mutex_lock(&c->replicas_gc_lock);
|
||||||
bch2_replicas_gc_start(c, 1 << BCH_DATA_journal);
|
bch2_replicas_gc_start(c, 1 << BCH_DATA_journal);
|
||||||
|
|
||||||
seq = 0;
|
/*
|
||||||
|
* Now that we've populated replicas_gc, write to the journal to mark
|
||||||
|
* active journal devices. This handles the case where the journal might
|
||||||
|
* be empty. Otherwise we could clear all journal replicas and
|
||||||
|
* temporarily put the fs into an unrecoverable state. Journal recovery
|
||||||
|
* expects to find devices marked for journal data on unclean mount.
|
||||||
|
*/
|
||||||
|
ret = bch2_journal_meta(&c->journal);
|
||||||
|
if (ret) {
|
||||||
|
mutex_unlock(&c->replicas_gc_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
seq = 0;
|
||||||
spin_lock(&j->lock);
|
spin_lock(&j->lock);
|
||||||
while (!ret) {
|
while (!ret) {
|
||||||
struct bch_replicas_padded replicas;
|
struct bch_replicas_padded replicas;
|
||||||
|
@ -201,16 +201,16 @@ int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca,
|
|||||||
|
|
||||||
bch2_sb_field_delete(&ca->disk_sb, BCH_SB_FIELD_journal);
|
bch2_sb_field_delete(&ca->disk_sb, BCH_SB_FIELD_journal);
|
||||||
|
|
||||||
j->d[dst].start = le64_to_cpu(buckets[0]);
|
j->d[dst].start = cpu_to_le64(buckets[0]);
|
||||||
j->d[dst].nr = le64_to_cpu(1);
|
j->d[dst].nr = cpu_to_le64(1);
|
||||||
|
|
||||||
for (i = 1; i < nr; i++) {
|
for (i = 1; i < nr; i++) {
|
||||||
if (buckets[i] == buckets[i - 1] + 1) {
|
if (buckets[i] == buckets[i - 1] + 1) {
|
||||||
le64_add_cpu(&j->d[dst].nr, 1);
|
le64_add_cpu(&j->d[dst].nr, 1);
|
||||||
} else {
|
} else {
|
||||||
dst++;
|
dst++;
|
||||||
j->d[dst].start = le64_to_cpu(buckets[i]);
|
j->d[dst].start = cpu_to_le64(buckets[i]);
|
||||||
j->d[dst].nr = le64_to_cpu(1);
|
j->d[dst].nr = cpu_to_le64(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,19 +154,6 @@ enum journal_flags {
|
|||||||
JOURNAL_NEED_FLUSH_WRITE,
|
JOURNAL_NEED_FLUSH_WRITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define JOURNAL_WATERMARKS() \
|
|
||||||
x(any) \
|
|
||||||
x(copygc) \
|
|
||||||
x(reserved)
|
|
||||||
|
|
||||||
enum journal_watermark {
|
|
||||||
#define x(n) JOURNAL_WATERMARK_##n,
|
|
||||||
JOURNAL_WATERMARKS()
|
|
||||||
#undef x
|
|
||||||
};
|
|
||||||
|
|
||||||
#define JOURNAL_WATERMARK_MASK 3
|
|
||||||
|
|
||||||
/* Reasons we may fail to get a journal reservation: */
|
/* Reasons we may fail to get a journal reservation: */
|
||||||
#define JOURNAL_ERRORS() \
|
#define JOURNAL_ERRORS() \
|
||||||
x(ok) \
|
x(ok) \
|
||||||
@ -191,7 +178,7 @@ struct journal {
|
|||||||
struct {
|
struct {
|
||||||
|
|
||||||
union journal_res_state reservations;
|
union journal_res_state reservations;
|
||||||
enum journal_watermark watermark;
|
enum bch_watermark watermark;
|
||||||
|
|
||||||
union journal_preres_state prereserved;
|
union journal_preres_state prereserved;
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
|
|
||||||
/* KEY_TYPE_lru is obsolete: */
|
/* KEY_TYPE_lru is obsolete: */
|
||||||
int bch2_lru_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_lru_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (!lru_pos_time(k.k->p)) {
|
if (!lru_pos_time(k.k->p)) {
|
||||||
prt_printf(err, "lru entry at time=0");
|
prt_printf(err, "lru entry at time=0");
|
||||||
|
@ -43,7 +43,8 @@ static inline enum bch_lru_type lru_type(struct bkey_s_c l)
|
|||||||
return BCH_LRU_read;
|
return BCH_LRU_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bch2_lru_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_lru_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_lru_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_lru_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
void bch2_lru_pos_to_text(struct printbuf *, struct bpos);
|
void bch2_lru_pos_to_text(struct printbuf *, struct bpos);
|
||||||
|
@ -141,7 +141,7 @@ retry:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, false);
|
ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, 0, false);
|
||||||
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
|
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
continue;
|
continue;
|
||||||
|
@ -632,7 +632,7 @@ int bch2_move_data(struct bch_fs *c,
|
|||||||
bch2_moving_ctxt_init(&ctxt, c, rate, stats, wp, wait_on_copygc);
|
bch2_moving_ctxt_init(&ctxt, c, rate, stats, wp, wait_on_copygc);
|
||||||
|
|
||||||
for (id = start_btree_id;
|
for (id = start_btree_id;
|
||||||
id <= min_t(unsigned, end_btree_id, BTREE_ID_NR - 1);
|
id <= min_t(unsigned, end_btree_id, btree_id_nr_alive(c) - 1);
|
||||||
id++) {
|
id++) {
|
||||||
stats->btree_id = id;
|
stats->btree_id = id;
|
||||||
|
|
||||||
@ -640,6 +640,9 @@ int bch2_move_data(struct bch_fs *c,
|
|||||||
id != BTREE_ID_reflink)
|
id != BTREE_ID_reflink)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!bch2_btree_id_root(c, id)->b)
|
||||||
|
continue;
|
||||||
|
|
||||||
ret = __bch2_move_data(&ctxt,
|
ret = __bch2_move_data(&ctxt,
|
||||||
id == start_btree_id ? start_pos : POS_MIN,
|
id == start_btree_id ? start_pos : POS_MIN,
|
||||||
id == end_btree_id ? end_pos : POS_MAX,
|
id == end_btree_id ? end_pos : POS_MAX,
|
||||||
@ -861,10 +864,13 @@ static int bch2_move_btree(struct bch_fs *c,
|
|||||||
stats->data_type = BCH_DATA_btree;
|
stats->data_type = BCH_DATA_btree;
|
||||||
|
|
||||||
for (id = start_btree_id;
|
for (id = start_btree_id;
|
||||||
id <= min_t(unsigned, end_btree_id, BTREE_ID_NR - 1);
|
id <= min_t(unsigned, end_btree_id, btree_id_nr_alive(c) - 1);
|
||||||
id++) {
|
id++) {
|
||||||
stats->btree_id = id;
|
stats->btree_id = id;
|
||||||
|
|
||||||
|
if (!bch2_btree_id_root(c, id)->b)
|
||||||
|
continue;
|
||||||
|
|
||||||
bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0,
|
bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0,
|
||||||
BTREE_ITER_PREFETCH);
|
BTREE_ITER_PREFETCH);
|
||||||
retry:
|
retry:
|
||||||
|
@ -202,7 +202,7 @@ static int bch2_copygc(struct btree_trans *trans,
|
|||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct data_update_opts data_opts = {
|
struct data_update_opts data_opts = {
|
||||||
.btree_insert_flags = BTREE_INSERT_USE_RESERVE|JOURNAL_WATERMARK_copygc,
|
.btree_insert_flags = BCH_WATERMARK_copygc,
|
||||||
};
|
};
|
||||||
move_buckets buckets = { 0 };
|
move_buckets buckets = { 0 };
|
||||||
struct move_bucket_in_flight *f;
|
struct move_bucket_in_flight *f;
|
||||||
|
@ -11,11 +11,6 @@
|
|||||||
|
|
||||||
#define x(t, n) [n] = #t,
|
#define x(t, n) [n] = #t,
|
||||||
|
|
||||||
const char * const bch2_metadata_versions[] = {
|
|
||||||
BCH_METADATA_VERSIONS()
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
const char * const bch2_error_actions[] = {
|
const char * const bch2_error_actions[] = {
|
||||||
BCH_ERROR_ACTIONS()
|
BCH_ERROR_ACTIONS()
|
||||||
NULL
|
NULL
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
#include "bcachefs_format.h"
|
#include "bcachefs_format.h"
|
||||||
|
|
||||||
extern const char * const bch2_metadata_versions[];
|
|
||||||
extern const char * const bch2_error_actions[];
|
extern const char * const bch2_error_actions[];
|
||||||
extern const char * const bch2_sb_features[];
|
extern const char * const bch2_sb_features[];
|
||||||
extern const char * const bch2_sb_compat[];
|
extern const char * const bch2_sb_compat[];
|
||||||
|
@ -60,7 +60,8 @@ const struct bch_sb_field_ops bch_sb_field_ops_quota = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int bch2_quota_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_quota_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (k.k->p.inode >= QTYP_NR) {
|
if (k.k->p.inode >= QTYP_NR) {
|
||||||
prt_printf(err, "invalid quota type (%llu >= %u)",
|
prt_printf(err, "invalid quota type (%llu >= %u)",
|
||||||
@ -480,13 +481,13 @@ static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (qdq && qdq->d_fieldmask & QC_SPC_TIMER)
|
if (qdq && qdq->d_fieldmask & QC_SPC_TIMER)
|
||||||
mq->c[Q_SPC].timer = cpu_to_le64(qdq->d_spc_timer);
|
mq->c[Q_SPC].timer = qdq->d_spc_timer;
|
||||||
if (qdq && qdq->d_fieldmask & QC_SPC_WARNS)
|
if (qdq && qdq->d_fieldmask & QC_SPC_WARNS)
|
||||||
mq->c[Q_SPC].warns = cpu_to_le64(qdq->d_spc_warns);
|
mq->c[Q_SPC].warns = qdq->d_spc_warns;
|
||||||
if (qdq && qdq->d_fieldmask & QC_INO_TIMER)
|
if (qdq && qdq->d_fieldmask & QC_INO_TIMER)
|
||||||
mq->c[Q_INO].timer = cpu_to_le64(qdq->d_ino_timer);
|
mq->c[Q_INO].timer = qdq->d_ino_timer;
|
||||||
if (qdq && qdq->d_fieldmask & QC_INO_WARNS)
|
if (qdq && qdq->d_fieldmask & QC_INO_WARNS)
|
||||||
mq->c[Q_INO].warns = cpu_to_le64(qdq->d_ino_warns);
|
mq->c[Q_INO].warns = qdq->d_ino_warns;
|
||||||
|
|
||||||
mutex_unlock(&q->lock);
|
mutex_unlock(&q->lock);
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
#include "inode.h"
|
#include "inode.h"
|
||||||
#include "quota_types.h"
|
#include "quota_types.h"
|
||||||
|
|
||||||
|
enum bkey_invalid_flags;
|
||||||
extern const struct bch_sb_field_ops bch_sb_field_ops_quota;
|
extern const struct bch_sb_field_ops bch_sb_field_ops_quota;
|
||||||
|
|
||||||
int bch2_quota_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_quota_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_quota_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_quota_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
#define bch2_bkey_ops_quota ((struct bkey_ops) { \
|
#define bch2_bkey_ops_quota ((struct bkey_ops) { \
|
||||||
|
@ -308,7 +308,7 @@ static void bch2_journal_iter_advance(struct journal_iter *iter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter)
|
static struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter)
|
||||||
{
|
{
|
||||||
struct journal_key *k = iter->keys->d + iter->idx;
|
struct journal_key *k = iter->keys->d + iter->idx;
|
||||||
|
|
||||||
@ -664,7 +664,7 @@ static int bch2_journal_replay(struct bch_fs *c, u64 start_seq, u64 end_seq)
|
|||||||
BTREE_INSERT_LAZY_RW|
|
BTREE_INSERT_LAZY_RW|
|
||||||
BTREE_INSERT_NOFAIL|
|
BTREE_INSERT_NOFAIL|
|
||||||
(!k->allocated
|
(!k->allocated
|
||||||
? BTREE_INSERT_JOURNAL_REPLAY|JOURNAL_WATERMARK_reserved
|
? BTREE_INSERT_JOURNAL_REPLAY|BCH_WATERMARK_reclaim
|
||||||
: 0),
|
: 0),
|
||||||
bch2_journal_replay_key(&trans, k));
|
bch2_journal_replay_key(&trans, k));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -702,13 +702,13 @@ static int journal_replay_entry_early(struct bch_fs *c,
|
|||||||
case BCH_JSET_ENTRY_btree_root: {
|
case BCH_JSET_ENTRY_btree_root: {
|
||||||
struct btree_root *r;
|
struct btree_root *r;
|
||||||
|
|
||||||
if (entry->btree_id >= BTREE_ID_NR) {
|
while (entry->btree_id >= c->btree_roots_extra.nr + BTREE_ID_NR) {
|
||||||
bch_err(c, "filesystem has unknown btree type %u",
|
ret = darray_push(&c->btree_roots_extra, (struct btree_root) { NULL });
|
||||||
entry->btree_id);
|
if (ret)
|
||||||
return -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = &c->btree_roots[entry->btree_id];
|
r = bch2_btree_id_root(c, entry->btree_id);
|
||||||
|
|
||||||
if (entry->u64s) {
|
if (entry->u64s) {
|
||||||
r->level = entry->level;
|
r->level = entry->level;
|
||||||
@ -980,8 +980,8 @@ static int read_btree_roots(struct bch_fs *c)
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
for (i = 0; i < BTREE_ID_NR; i++) {
|
for (i = 0; i < btree_id_nr_alive(c); i++) {
|
||||||
struct btree_root *r = &c->btree_roots[i];
|
struct btree_root *r = bch2_btree_id_root(c, i);
|
||||||
|
|
||||||
if (!r->alive)
|
if (!r->alive)
|
||||||
continue;
|
continue;
|
||||||
@ -1014,7 +1014,7 @@ static int read_btree_roots(struct bch_fs *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < BTREE_ID_NR; i++) {
|
for (i = 0; i < BTREE_ID_NR; i++) {
|
||||||
struct btree_root *r = &c->btree_roots[i];
|
struct btree_root *r = bch2_btree_id_root(c, i);
|
||||||
|
|
||||||
if (!r->b) {
|
if (!r->b) {
|
||||||
r->alive = false;
|
r->alive = false;
|
||||||
@ -1042,7 +1042,7 @@ static int bch2_fs_initialize_subvolumes(struct bch_fs *c)
|
|||||||
root_snapshot.k.p.offset = U32_MAX;
|
root_snapshot.k.p.offset = U32_MAX;
|
||||||
root_snapshot.v.flags = 0;
|
root_snapshot.v.flags = 0;
|
||||||
root_snapshot.v.parent = 0;
|
root_snapshot.v.parent = 0;
|
||||||
root_snapshot.v.subvol = BCACHEFS_ROOT_SUBVOL;
|
root_snapshot.v.subvol = cpu_to_le32(BCACHEFS_ROOT_SUBVOL);
|
||||||
root_snapshot.v.tree = cpu_to_le32(1);
|
root_snapshot.v.tree = cpu_to_le32(1);
|
||||||
SET_BCH_SNAPSHOT_SUBVOL(&root_snapshot.v, true);
|
SET_BCH_SNAPSHOT_SUBVOL(&root_snapshot.v, true);
|
||||||
|
|
||||||
@ -1146,17 +1146,22 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c->opts.nochanges) {
|
if (!c->opts.nochanges &&
|
||||||
if (c->sb.version < bcachefs_metadata_required_upgrade_below) {
|
c->sb.version < bcachefs_metadata_required_upgrade_below) {
|
||||||
bch_info(c, "version %s (%u) prior to %s (%u), upgrade and fsck required",
|
struct printbuf buf = PRINTBUF;
|
||||||
bch2_metadata_versions[c->sb.version],
|
|
||||||
c->sb.version,
|
prt_str(&buf, "version ");
|
||||||
bch2_metadata_versions[bcachefs_metadata_required_upgrade_below],
|
bch2_version_to_text(&buf, c->sb.version);
|
||||||
bcachefs_metadata_required_upgrade_below);
|
prt_str(&buf, " prior to ");
|
||||||
c->opts.version_upgrade = true;
|
bch2_version_to_text(&buf, bcachefs_metadata_required_upgrade_below);
|
||||||
c->opts.fsck = true;
|
prt_str(&buf, ", upgrade and fsck required");
|
||||||
c->opts.fix_errors = FSCK_OPT_YES;
|
|
||||||
}
|
bch_info(c, "%s", buf.buf);
|
||||||
|
printbuf_exit(&buf);
|
||||||
|
|
||||||
|
c->opts.version_upgrade = true;
|
||||||
|
c->opts.fsck = true;
|
||||||
|
c->opts.fix_errors = FSCK_OPT_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->opts.fsck && c->opts.norecovery) {
|
if (c->opts.fsck && c->opts.norecovery) {
|
||||||
@ -1463,7 +1468,7 @@ use_clean:
|
|||||||
|
|
||||||
if (!(c->sb.compat & (1ULL << BCH_COMPAT_extents_above_btree_updates_done)) ||
|
if (!(c->sb.compat & (1ULL << BCH_COMPAT_extents_above_btree_updates_done)) ||
|
||||||
!(c->sb.compat & (1ULL << BCH_COMPAT_bformat_overflow_done)) ||
|
!(c->sb.compat & (1ULL << BCH_COMPAT_bformat_overflow_done)) ||
|
||||||
le16_to_cpu(c->sb.version_min) < bcachefs_metadata_version_btree_ptr_sectors_written) {
|
c->sb.version_min < bcachefs_metadata_version_btree_ptr_sectors_written) {
|
||||||
struct bch_move_stats stats;
|
struct bch_move_stats stats;
|
||||||
|
|
||||||
bch2_move_stats_init(&stats, "recovery");
|
bch2_move_stats_init(&stats, "recovery");
|
||||||
|
@ -26,7 +26,8 @@ static inline unsigned bkey_type_to_indirect(const struct bkey *k)
|
|||||||
/* reflink pointers */
|
/* reflink pointers */
|
||||||
|
|
||||||
int bch2_reflink_p_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_reflink_p_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k);
|
struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k);
|
||||||
|
|
||||||
@ -72,7 +73,8 @@ bool bch2_reflink_p_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r
|
|||||||
/* indirect extents */
|
/* indirect extents */
|
||||||
|
|
||||||
int bch2_reflink_v_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_reflink_v_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
return bch2_bkey_ptrs_invalid(c, k, flags, err);
|
return bch2_bkey_ptrs_invalid(c, k, flags, err);
|
||||||
}
|
}
|
||||||
@ -118,7 +120,8 @@ int bch2_trans_mark_reflink_v(struct btree_trans *trans,
|
|||||||
/* indirect inline data */
|
/* indirect inline data */
|
||||||
|
|
||||||
int bch2_indirect_inline_data_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_indirect_inline_data_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
#ifndef _BCACHEFS_REFLINK_H
|
#ifndef _BCACHEFS_REFLINK_H
|
||||||
#define _BCACHEFS_REFLINK_H
|
#define _BCACHEFS_REFLINK_H
|
||||||
|
|
||||||
|
enum bkey_invalid_flags;
|
||||||
|
|
||||||
int bch2_reflink_p_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_reflink_p_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_reflink_p_to_text(struct printbuf *, struct bch_fs *,
|
void bch2_reflink_p_to_text(struct printbuf *, struct bch_fs *,
|
||||||
struct bkey_s_c);
|
struct bkey_s_c);
|
||||||
bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
||||||
@ -18,7 +20,7 @@ bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
|||||||
})
|
})
|
||||||
|
|
||||||
int bch2_reflink_v_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_reflink_v_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_reflink_v_to_text(struct printbuf *, struct bch_fs *,
|
void bch2_reflink_v_to_text(struct printbuf *, struct bch_fs *,
|
||||||
struct bkey_s_c);
|
struct bkey_s_c);
|
||||||
int bch2_trans_mark_reflink_v(struct btree_trans *, enum btree_id, unsigned,
|
int bch2_trans_mark_reflink_v(struct btree_trans *, enum btree_id, unsigned,
|
||||||
@ -34,7 +36,7 @@ int bch2_trans_mark_reflink_v(struct btree_trans *, enum btree_id, unsigned,
|
|||||||
})
|
})
|
||||||
|
|
||||||
int bch2_indirect_inline_data_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_indirect_inline_data_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_indirect_inline_data_to_text(struct printbuf *,
|
void bch2_indirect_inline_data_to_text(struct printbuf *,
|
||||||
struct bch_fs *, struct bkey_s_c);
|
struct bch_fs *, struct bkey_s_c);
|
||||||
int bch2_trans_mark_indirect_inline_data(struct btree_trans *,
|
int bch2_trans_mark_indirect_inline_data(struct btree_trans *,
|
||||||
|
@ -36,8 +36,8 @@ static void bch2_cpu_replicas_sort(struct bch_replicas_cpu *r)
|
|||||||
eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
|
eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch2_replicas_entry_v0_to_text(struct printbuf *out,
|
static void bch2_replicas_entry_v0_to_text(struct printbuf *out,
|
||||||
struct bch_replicas_entry_v0 *e)
|
struct bch_replicas_entry_v0 *e)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
@ -272,7 +272,7 @@ static void __replicas_table_update_pcpu(struct bch_fs_usage __percpu *dst_p,
|
|||||||
{
|
{
|
||||||
unsigned src_nr = sizeof(struct bch_fs_usage) / sizeof(u64) + src_r->nr;
|
unsigned src_nr = sizeof(struct bch_fs_usage) / sizeof(u64) + src_r->nr;
|
||||||
struct bch_fs_usage *dst, *src = (void *)
|
struct bch_fs_usage *dst, *src = (void *)
|
||||||
bch2_acc_percpu_u64s((void *) src_p, src_nr);
|
bch2_acc_percpu_u64s((u64 __percpu *) src_p, src_nr);
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
dst = this_cpu_ptr(dst_p);
|
dst = this_cpu_ptr(dst_p);
|
||||||
|
@ -23,7 +23,8 @@ void bch2_snapshot_tree_to_text(struct printbuf *out, struct bch_fs *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_snapshot_tree_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_snapshot_tree_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
if (bkey_gt(k.k->p, POS(0, U32_MAX)) ||
|
if (bkey_gt(k.k->p, POS(0, U32_MAX)) ||
|
||||||
bkey_lt(k.k->p, POS(0, 1))) {
|
bkey_lt(k.k->p, POS(0, 1))) {
|
||||||
@ -97,7 +98,8 @@ void bch2_snapshot_to_text(struct printbuf *out, struct bch_fs *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bch2_snapshot_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_snapshot_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bkey_s_c_snapshot s;
|
struct bkey_s_c_snapshot s;
|
||||||
u32 i, id;
|
u32 i, id;
|
||||||
@ -825,7 +827,7 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (s.v->children[0]) {
|
if (s.v->children[0]) {
|
||||||
s_t->v.root_snapshot = cpu_to_le32(s.v->children[0]);
|
s_t->v.root_snapshot = s.v->children[0];
|
||||||
} else {
|
} else {
|
||||||
s_t->k.type = KEY_TYPE_deleted;
|
s_t->k.type = KEY_TYPE_deleted;
|
||||||
set_bkey_val_u64s(&s_t->k, 0);
|
set_bkey_val_u64s(&s_t->k, 0);
|
||||||
@ -1328,7 +1330,7 @@ static int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
|
|||||||
__bch2_subvolume_delete(trans, subvolid));
|
__bch2_subvolume_delete(trans, subvolid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
|
static void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = container_of(work, struct bch_fs,
|
struct bch_fs *c = container_of(work, struct bch_fs,
|
||||||
snapshot_wait_for_pagecache_and_delete_work);
|
snapshot_wait_for_pagecache_and_delete_work);
|
||||||
@ -1366,7 +1368,7 @@ struct subvolume_unlink_hook {
|
|||||||
u32 subvol;
|
u32 subvol;
|
||||||
};
|
};
|
||||||
|
|
||||||
int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
|
static int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
|
||||||
struct btree_trans_commit_hook *_h)
|
struct btree_trans_commit_hook *_h)
|
||||||
{
|
{
|
||||||
struct subvolume_unlink_hook *h = container_of(_h, struct subvolume_unlink_hook, h);
|
struct subvolume_unlink_hook *h = container_of(_h, struct subvolume_unlink_hook, h);
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
#include "darray.h"
|
#include "darray.h"
|
||||||
#include "subvolume_types.h"
|
#include "subvolume_types.h"
|
||||||
|
|
||||||
|
enum bkey_invalid_flags;
|
||||||
|
|
||||||
void bch2_snapshot_tree_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_snapshot_tree_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
int bch2_snapshot_tree_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_snapshot_tree_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
|
|
||||||
#define bch2_bkey_ops_snapshot_tree ((struct bkey_ops) { \
|
#define bch2_bkey_ops_snapshot_tree ((struct bkey_ops) { \
|
||||||
.key_invalid = bch2_snapshot_tree_invalid, \
|
.key_invalid = bch2_snapshot_tree_invalid, \
|
||||||
@ -19,7 +21,7 @@ int bch2_snapshot_tree_lookup(struct btree_trans *, u32, struct bch_snapshot_tre
|
|||||||
|
|
||||||
void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
int bch2_snapshot_invalid(const struct bch_fs *, struct bkey_s_c,
|
int bch2_snapshot_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
unsigned, struct printbuf *);
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned,
|
int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned,
|
||||||
struct bkey_s_c, struct bkey_s_c, unsigned);
|
struct bkey_s_c, struct bkey_s_c, unsigned);
|
||||||
|
|
||||||
|
@ -23,6 +23,21 @@
|
|||||||
#include <linux/backing-dev.h>
|
#include <linux/backing-dev.h>
|
||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
|
|
||||||
|
static const char * const bch2_metadata_versions[] = {
|
||||||
|
#define x(t, n) [n] = #t,
|
||||||
|
BCH_METADATA_VERSIONS()
|
||||||
|
#undef x
|
||||||
|
};
|
||||||
|
|
||||||
|
void bch2_version_to_text(struct printbuf *out, unsigned v)
|
||||||
|
{
|
||||||
|
const char *str = v < ARRAY_SIZE(bch2_metadata_versions)
|
||||||
|
? bch2_metadata_versions[v]
|
||||||
|
: "(unknown version)";
|
||||||
|
|
||||||
|
prt_printf(out, "%u: %s", v, str);
|
||||||
|
}
|
||||||
|
|
||||||
const char * const bch2_sb_fields[] = {
|
const char * const bch2_sb_fields[] = {
|
||||||
#define x(name, nr) #name,
|
#define x(name, nr) #name,
|
||||||
BCH_SB_FIELDS()
|
BCH_SB_FIELDS()
|
||||||
@ -250,6 +265,44 @@ static int validate_sb_layout(struct bch_sb_layout *layout, struct printbuf *out
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bch2_sb_compatible(struct bch_sb *sb, struct printbuf *out)
|
||||||
|
{
|
||||||
|
u16 version = le16_to_cpu(sb->version);
|
||||||
|
u16 version_min = le16_to_cpu(sb->version_min);
|
||||||
|
|
||||||
|
if (!bch2_version_compatible(version)) {
|
||||||
|
prt_str(out, "Unsupported superblock version ");
|
||||||
|
bch2_version_to_text(out, version);
|
||||||
|
prt_str(out, " (min ");
|
||||||
|
bch2_version_to_text(out, bcachefs_metadata_version_min);
|
||||||
|
prt_str(out, ", max ");
|
||||||
|
bch2_version_to_text(out, bcachefs_metadata_version_current);
|
||||||
|
prt_str(out, ")");
|
||||||
|
return -BCH_ERR_invalid_sb_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bch2_version_compatible(version_min)) {
|
||||||
|
prt_str(out, "Unsupported superblock version_min ");
|
||||||
|
bch2_version_to_text(out, version_min);
|
||||||
|
prt_str(out, " (min ");
|
||||||
|
bch2_version_to_text(out, bcachefs_metadata_version_min);
|
||||||
|
prt_str(out, ", max ");
|
||||||
|
bch2_version_to_text(out, bcachefs_metadata_version_current);
|
||||||
|
prt_str(out, ")");
|
||||||
|
return -BCH_ERR_invalid_sb_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version_min > version) {
|
||||||
|
prt_str(out, "Bad minimum version ");
|
||||||
|
bch2_version_to_text(out, version_min);
|
||||||
|
prt_str(out, ", greater than version field ");
|
||||||
|
bch2_version_to_text(out, version);
|
||||||
|
return -BCH_ERR_invalid_sb_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
|
static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
|
||||||
int rw)
|
int rw)
|
||||||
{
|
{
|
||||||
@ -257,32 +310,12 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
|
|||||||
struct bch_sb_field *f;
|
struct bch_sb_field *f;
|
||||||
struct bch_sb_field_members *mi;
|
struct bch_sb_field_members *mi;
|
||||||
enum bch_opt_id opt_id;
|
enum bch_opt_id opt_id;
|
||||||
u32 version, version_min;
|
|
||||||
u16 block_size;
|
u16 block_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
version = le16_to_cpu(sb->version);
|
ret = bch2_sb_compatible(sb, out);
|
||||||
version_min = version >= bcachefs_metadata_version_bkey_renumber
|
if (ret)
|
||||||
? le16_to_cpu(sb->version_min)
|
return ret;
|
||||||
: version;
|
|
||||||
|
|
||||||
if (version >= bcachefs_metadata_version_max) {
|
|
||||||
prt_printf(out, "Unsupported superblock version %u (min %u, max %u)",
|
|
||||||
version, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
|
|
||||||
return -BCH_ERR_invalid_sb_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version_min < bcachefs_metadata_version_min) {
|
|
||||||
prt_printf(out, "Unsupported superblock version %u (min %u, max %u)",
|
|
||||||
version_min, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
|
|
||||||
return -BCH_ERR_invalid_sb_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version_min > version) {
|
|
||||||
prt_printf(out, "Bad minimum version %u, greater than version field %u",
|
|
||||||
version_min, version);
|
|
||||||
return -BCH_ERR_invalid_sb_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sb->features[1] ||
|
if (sb->features[1] ||
|
||||||
(le64_to_cpu(sb->features[0]) & (~0ULL << BCH_FEATURE_NR))) {
|
(le64_to_cpu(sb->features[0]) & (~0ULL << BCH_FEATURE_NR))) {
|
||||||
@ -331,7 +364,7 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
|
|||||||
if (rw == READ) {
|
if (rw == READ) {
|
||||||
/*
|
/*
|
||||||
* Been seeing a bug where these are getting inexplicably
|
* Been seeing a bug where these are getting inexplicably
|
||||||
* zeroed, so we'r now validating them, but we have to be
|
* zeroed, so we're now validating them, but we have to be
|
||||||
* careful not to preven people's filesystems from mounting:
|
* careful not to preven people's filesystems from mounting:
|
||||||
*/
|
*/
|
||||||
if (!BCH_SB_JOURNAL_FLUSH_DELAY(sb))
|
if (!BCH_SB_JOURNAL_FLUSH_DELAY(sb))
|
||||||
@ -512,7 +545,6 @@ int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca)
|
|||||||
static int read_one_super(struct bch_sb_handle *sb, u64 offset, struct printbuf *err)
|
static int read_one_super(struct bch_sb_handle *sb, u64 offset, struct printbuf *err)
|
||||||
{
|
{
|
||||||
struct bch_csum csum;
|
struct bch_csum csum;
|
||||||
u32 version, version_min;
|
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
int ret;
|
int ret;
|
||||||
reread:
|
reread:
|
||||||
@ -532,22 +564,9 @@ reread:
|
|||||||
return -BCH_ERR_invalid_sb_magic;
|
return -BCH_ERR_invalid_sb_magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
version = le16_to_cpu(sb->sb->version);
|
ret = bch2_sb_compatible(sb->sb, err);
|
||||||
version_min = version >= bcachefs_metadata_version_bkey_renumber
|
if (ret)
|
||||||
? le16_to_cpu(sb->sb->version_min)
|
return ret;
|
||||||
: version;
|
|
||||||
|
|
||||||
if (version >= bcachefs_metadata_version_max) {
|
|
||||||
prt_printf(err, "Unsupported superblock version %u (min %u, max %u)",
|
|
||||||
version, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
|
|
||||||
return -BCH_ERR_invalid_sb_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version_min < bcachefs_metadata_version_min) {
|
|
||||||
prt_printf(err, "Unsupported superblock version %u (min %u, max %u)",
|
|
||||||
version_min, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
|
|
||||||
return -BCH_ERR_invalid_sb_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes = vstruct_bytes(sb->sb);
|
bytes = vstruct_bytes(sb->sb);
|
||||||
|
|
||||||
@ -1389,21 +1408,29 @@ static const struct bch_sb_field_ops *bch2_sb_field_ops[] = {
|
|||||||
#undef x
|
#undef x
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct bch_sb_field_ops bch2_sb_field_null_ops = {
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct bch_sb_field_ops *bch2_sb_field_type_ops(unsigned type)
|
||||||
|
{
|
||||||
|
return likely(type < ARRAY_SIZE(bch2_sb_field_ops))
|
||||||
|
? bch2_sb_field_ops[type]
|
||||||
|
: &bch2_sb_field_null_ops;
|
||||||
|
}
|
||||||
|
|
||||||
static int bch2_sb_field_validate(struct bch_sb *sb, struct bch_sb_field *f,
|
static int bch2_sb_field_validate(struct bch_sb *sb, struct bch_sb_field *f,
|
||||||
struct printbuf *err)
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
unsigned type = le32_to_cpu(f->type);
|
unsigned type = le32_to_cpu(f->type);
|
||||||
struct printbuf field_err = PRINTBUF;
|
struct printbuf field_err = PRINTBUF;
|
||||||
|
const struct bch_sb_field_ops *ops = bch2_sb_field_type_ops(type);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (type >= BCH_SB_FIELD_NR)
|
ret = ops->validate ? ops->validate(sb, f, &field_err) : 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = bch2_sb_field_ops[type]->validate(sb, f, &field_err);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
prt_printf(err, "Invalid superblock section %s: %s",
|
prt_printf(err, "Invalid superblock section %s: %s",
|
||||||
bch2_sb_fields[type],
|
bch2_sb_fields[type], field_err.buf);
|
||||||
field_err.buf);
|
|
||||||
prt_newline(err);
|
prt_newline(err);
|
||||||
bch2_sb_field_to_text(err, sb, f);
|
bch2_sb_field_to_text(err, sb, f);
|
||||||
}
|
}
|
||||||
@ -1416,13 +1443,12 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
|
|||||||
struct bch_sb_field *f)
|
struct bch_sb_field *f)
|
||||||
{
|
{
|
||||||
unsigned type = le32_to_cpu(f->type);
|
unsigned type = le32_to_cpu(f->type);
|
||||||
const struct bch_sb_field_ops *ops = type < BCH_SB_FIELD_NR
|
const struct bch_sb_field_ops *ops = bch2_sb_field_type_ops(type);
|
||||||
? bch2_sb_field_ops[type] : NULL;
|
|
||||||
|
|
||||||
if (!out->nr_tabstops)
|
if (!out->nr_tabstops)
|
||||||
printbuf_tabstop_push(out, 32);
|
printbuf_tabstop_push(out, 32);
|
||||||
|
|
||||||
if (ops)
|
if (type < BCH_SB_FIELD_NR)
|
||||||
prt_printf(out, "%s", bch2_sb_fields[type]);
|
prt_printf(out, "%s", bch2_sb_fields[type]);
|
||||||
else
|
else
|
||||||
prt_printf(out, "(unknown field %u)", type);
|
prt_printf(out, "(unknown field %u)", type);
|
||||||
@ -1430,9 +1456,9 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
|
|||||||
prt_printf(out, " (size %zu):", vstruct_bytes(f));
|
prt_printf(out, " (size %zu):", vstruct_bytes(f));
|
||||||
prt_newline(out);
|
prt_newline(out);
|
||||||
|
|
||||||
if (ops && ops->to_text) {
|
if (ops->to_text) {
|
||||||
printbuf_indent_add(out, 2);
|
printbuf_indent_add(out, 2);
|
||||||
bch2_sb_field_ops[type]->to_text(out, sb, f);
|
ops->to_text(out, sb, f);
|
||||||
printbuf_indent_sub(out, 2);
|
printbuf_indent_sub(out, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1503,12 +1529,12 @@ void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb,
|
|||||||
|
|
||||||
prt_str(out, "Version:");
|
prt_str(out, "Version:");
|
||||||
prt_tab(out);
|
prt_tab(out);
|
||||||
prt_printf(out, "%s", bch2_metadata_versions[le16_to_cpu(sb->version)]);
|
bch2_version_to_text(out, le16_to_cpu(sb->version));
|
||||||
prt_newline(out);
|
prt_newline(out);
|
||||||
|
|
||||||
prt_printf(out, "Oldest version on disk:");
|
prt_printf(out, "Oldest version on disk:");
|
||||||
prt_tab(out);
|
prt_tab(out);
|
||||||
prt_printf(out, "%s", bch2_metadata_versions[le16_to_cpu(sb->version_min)]);
|
bch2_version_to_text(out, le16_to_cpu(sb->version_min));
|
||||||
prt_newline(out);
|
prt_newline(out);
|
||||||
|
|
||||||
prt_printf(out, "Created:");
|
prt_printf(out, "Created:");
|
||||||
|
@ -9,6 +9,14 @@
|
|||||||
|
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
|
static inline bool bch2_version_compatible(u16 version)
|
||||||
|
{
|
||||||
|
return version <= bcachefs_metadata_version_current &&
|
||||||
|
version >= bcachefs_metadata_version_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bch2_version_to_text(struct printbuf *, unsigned);
|
||||||
|
|
||||||
struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type);
|
struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type);
|
||||||
struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *,
|
struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *,
|
||||||
enum bch_sb_field_type, unsigned);
|
enum bch_sb_field_type, unsigned);
|
||||||
|
@ -485,6 +485,7 @@ static void __bch2_fs_free(struct bch_fs *c)
|
|||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
kfree(per_cpu_ptr(c->btree_paths_bufs, cpu)->path);
|
kfree(per_cpu_ptr(c->btree_paths_bufs, cpu)->path);
|
||||||
|
|
||||||
|
darray_exit(&c->btree_roots_extra);
|
||||||
free_percpu(c->btree_paths_bufs);
|
free_percpu(c->btree_paths_bufs);
|
||||||
free_percpu(c->pcpu);
|
free_percpu(c->pcpu);
|
||||||
mempool_exit(&c->large_bkey_pool);
|
mempool_exit(&c->large_bkey_pool);
|
||||||
@ -560,9 +561,12 @@ void __bch2_fs_stop(struct bch_fs *c)
|
|||||||
|
|
||||||
cancel_work_sync(&c->read_only_work);
|
cancel_work_sync(&c->read_only_work);
|
||||||
|
|
||||||
for (i = 0; i < c->sb.nr_devices; i++)
|
for (i = 0; i < c->sb.nr_devices; i++) {
|
||||||
if (c->devs[i])
|
struct bch_dev *ca = rcu_dereference_protected(c->devs[i], true);
|
||||||
bch2_free_super(&c->devs[i]->disk_sb);
|
|
||||||
|
if (ca)
|
||||||
|
bch2_free_super(&ca->disk_sb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch2_fs_free(struct bch_fs *c)
|
void bch2_fs_free(struct bch_fs *c)
|
||||||
@ -685,6 +689,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
|
|||||||
|
|
||||||
bch2_fs_copygc_init(c);
|
bch2_fs_copygc_init(c);
|
||||||
bch2_fs_btree_key_cache_init_early(&c->btree_key_cache);
|
bch2_fs_btree_key_cache_init_early(&c->btree_key_cache);
|
||||||
|
bch2_fs_btree_interior_update_init_early(c);
|
||||||
bch2_fs_allocator_background_init(c);
|
bch2_fs_allocator_background_init(c);
|
||||||
bch2_fs_allocator_foreground_init(c);
|
bch2_fs_allocator_foreground_init(c);
|
||||||
bch2_fs_rebalance_init(c);
|
bch2_fs_rebalance_init(c);
|
||||||
@ -751,11 +756,11 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Compat: */
|
/* Compat: */
|
||||||
if (sb->version <= bcachefs_metadata_version_inode_v2 &&
|
if (le16_to_cpu(sb->version) <= bcachefs_metadata_version_inode_v2 &&
|
||||||
!BCH_SB_JOURNAL_FLUSH_DELAY(sb))
|
!BCH_SB_JOURNAL_FLUSH_DELAY(sb))
|
||||||
SET_BCH_SB_JOURNAL_FLUSH_DELAY(sb, 1000);
|
SET_BCH_SB_JOURNAL_FLUSH_DELAY(sb, 1000);
|
||||||
|
|
||||||
if (sb->version <= bcachefs_metadata_version_inode_v2 &&
|
if (le16_to_cpu(sb->version) <= bcachefs_metadata_version_inode_v2 &&
|
||||||
!BCH_SB_JOURNAL_RECLAIM_DELAY(sb))
|
!BCH_SB_JOURNAL_RECLAIM_DELAY(sb))
|
||||||
SET_BCH_SB_JOURNAL_RECLAIM_DELAY(sb, 100);
|
SET_BCH_SB_JOURNAL_RECLAIM_DELAY(sb, 100);
|
||||||
|
|
||||||
@ -875,7 +880,8 @@ static void print_mount_opts(struct bch_fs *c)
|
|||||||
struct printbuf p = PRINTBUF;
|
struct printbuf p = PRINTBUF;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
prt_printf(&p, "mounted version=%s", bch2_metadata_versions[c->sb.version]);
|
prt_str(&p, "mounted version ");
|
||||||
|
bch2_version_to_text(&p, c->sb.version);
|
||||||
|
|
||||||
if (c->opts.read_only) {
|
if (c->opts.read_only) {
|
||||||
prt_str(&p, " opts=");
|
prt_str(&p, " opts=");
|
||||||
@ -1520,6 +1526,17 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
|
|||||||
|
|
||||||
bch2_dev_free(ca);
|
bch2_dev_free(ca);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point the device object has been removed in-core, but the
|
||||||
|
* on-disk journal might still refer to the device index via sb device
|
||||||
|
* usage entries. Recovery fails if it sees usage information for an
|
||||||
|
* invalid device. Flush journal pins to push the back of the journal
|
||||||
|
* past now invalid device index references before we update the
|
||||||
|
* superblock, but after the device object has been removed so any
|
||||||
|
* further journal writes elide usage info for the device.
|
||||||
|
*/
|
||||||
|
bch2_journal_flush_all_pins(&c->journal);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free this device's slot in the bch_member array - all pointers to
|
* Free this device's slot in the bch_member array - all pointers to
|
||||||
* this device must be gone:
|
* this device must be gone:
|
||||||
@ -1986,7 +2003,7 @@ err:
|
|||||||
BCH_DEBUG_PARAMS()
|
BCH_DEBUG_PARAMS()
|
||||||
#undef BCH_DEBUG_PARAM
|
#undef BCH_DEBUG_PARAM
|
||||||
|
|
||||||
unsigned bch2_metadata_version = bcachefs_metadata_version_current;
|
static unsigned bch2_metadata_version = bcachefs_metadata_version_current;
|
||||||
module_param_named(version, bch2_metadata_version, uint, 0400);
|
module_param_named(version, bch2_metadata_version, uint, 0400);
|
||||||
|
|
||||||
module_exit(bcachefs_exit);
|
module_exit(bcachefs_exit);
|
||||||
|
@ -202,7 +202,7 @@ read_attribute(nocow_lock_table);
|
|||||||
#ifdef BCH_WRITE_REF_DEBUG
|
#ifdef BCH_WRITE_REF_DEBUG
|
||||||
read_attribute(write_refs);
|
read_attribute(write_refs);
|
||||||
|
|
||||||
const char * const bch2_write_refs[] = {
|
static const char * const bch2_write_refs[] = {
|
||||||
#define x(n) #n,
|
#define x(n) #n,
|
||||||
BCH_WRITE_REFS()
|
BCH_WRITE_REFS()
|
||||||
#undef x
|
#undef x
|
||||||
|
@ -444,7 +444,7 @@ static int test_peek_end_extents(struct bch_fs *c, u64 nr)
|
|||||||
|
|
||||||
/* extent unit tests */
|
/* extent unit tests */
|
||||||
|
|
||||||
u64 test_version;
|
static u64 test_version;
|
||||||
|
|
||||||
static int insert_test_extent(struct bch_fs *c,
|
static int insert_test_extent(struct bch_fs *c,
|
||||||
u64 start, u64 end)
|
u64 start, u64 end)
|
||||||
|
@ -22,12 +22,13 @@ int bch2_varint_encode(u8 *out, u64 v)
|
|||||||
{
|
{
|
||||||
unsigned bits = fls64(v|1);
|
unsigned bits = fls64(v|1);
|
||||||
unsigned bytes = DIV_ROUND_UP(bits, 7);
|
unsigned bytes = DIV_ROUND_UP(bits, 7);
|
||||||
|
__le64 v_le;
|
||||||
|
|
||||||
if (likely(bytes < 9)) {
|
if (likely(bytes < 9)) {
|
||||||
v <<= bytes;
|
v <<= bytes;
|
||||||
v |= ~(~0 << (bytes - 1));
|
v |= ~(~0 << (bytes - 1));
|
||||||
v = cpu_to_le64(v);
|
v_le = cpu_to_le64(v);
|
||||||
memcpy(out, &v, bytes);
|
memcpy(out, &v_le, bytes);
|
||||||
} else {
|
} else {
|
||||||
*out++ = 255;
|
*out++ = 255;
|
||||||
bytes = 9;
|
bytes = 9;
|
||||||
@ -57,9 +58,9 @@ int bch2_varint_decode(const u8 *in, const u8 *end, u64 *out)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (likely(bytes < 9)) {
|
if (likely(bytes < 9)) {
|
||||||
v = 0;
|
__le64 v_le = 0;
|
||||||
memcpy(&v, in, bytes);
|
memcpy(&v_le, in, bytes);
|
||||||
v = le64_to_cpu(v);
|
v = le64_to_cpu(v_le);
|
||||||
v >>= bytes;
|
v >>= bytes;
|
||||||
} else {
|
} else {
|
||||||
v = get_unaligned_le64(++in);
|
v = get_unaligned_le64(++in);
|
||||||
|
@ -70,7 +70,8 @@ const struct bch_hash_desc bch2_xattr_hash_desc = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int bch2_xattr_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
int bch2_xattr_invalid(const struct bch_fs *c, struct bkey_s_c k,
|
||||||
unsigned flags, struct printbuf *err)
|
enum bkey_invalid_flags flags,
|
||||||
|
struct printbuf *err)
|
||||||
{
|
{
|
||||||
const struct xattr_handler *handler;
|
const struct xattr_handler *handler;
|
||||||
struct bkey_s_c_xattr xattr = bkey_s_c_to_xattr(k);
|
struct bkey_s_c_xattr xattr = bkey_s_c_to_xattr(k);
|
||||||
@ -135,15 +136,14 @@ static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info
|
|||||||
const char *name, void *buffer, size_t size, int type)
|
const char *name, void *buffer, size_t size, int type)
|
||||||
{
|
{
|
||||||
struct bch_hash_info hash = bch2_hash_info_init(trans->c, &inode->ei_inode);
|
struct bch_hash_info hash = bch2_hash_info_init(trans->c, &inode->ei_inode);
|
||||||
|
struct xattr_search_key search = X_SEARCH(type, name, strlen(name));
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
struct bkey_s_c_xattr xattr;
|
struct bkey_s_c_xattr xattr;
|
||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc, &hash,
|
ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc, &hash,
|
||||||
inode_inum(inode),
|
inode_inum(inode), &search, 0);
|
||||||
&X_SEARCH(type, name, strlen(name)),
|
|
||||||
0);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
extern const struct bch_hash_desc bch2_xattr_hash_desc;
|
extern const struct bch_hash_desc bch2_xattr_hash_desc;
|
||||||
|
|
||||||
int bch2_xattr_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
|
int bch2_xattr_invalid(const struct bch_fs *, struct bkey_s_c,
|
||||||
|
enum bkey_invalid_flags, struct printbuf *);
|
||||||
void bch2_xattr_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
void bch2_xattr_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
|
||||||
|
|
||||||
#define bch2_bkey_ops_xattr ((struct bkey_ops) { \
|
#define bch2_bkey_ops_xattr ((struct bkey_ops) { \
|
||||||
|
Loading…
Reference in New Issue
Block a user