Update bcachefs sources to 0a9f0fc68a bcachefs: Don't unconditially version_upgrade in initialize

This commit is contained in:
Kent Overstreet 2021-03-21 16:40:41 -04:00
parent d3dc47271b
commit 11098ae37a
33 changed files with 324 additions and 365 deletions

View File

@ -1 +1 @@
242d37cbd0abfa575ebf816c715e5bb9513c90a0
0a9f0fc68a3cfaaee05a0848673fdb3de3108982

View File

@ -240,12 +240,12 @@ retry:
}
xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
acl = bch2_acl_from_disk(xattr_val(xattr.v),
le16_to_cpu(xattr.v->x_val_len));
if (!IS_ERR(acl))
set_cached_acl(&inode->v, type, acl);
bch2_trans_iter_put(&trans, iter);
out:
bch2_trans_exit(&trans);
return acl;
@ -310,7 +310,7 @@ retry:
if (type == ACL_TYPE_ACCESS) {
ret = posix_acl_update_mode(&inode->v, &mode, &acl);
if (ret)
goto err;
goto btree_err;
}
hash_info = bch2_hash_info_init(c, &inode_u);
@ -327,6 +327,8 @@ retry:
&inode->ei_journal_seq,
BTREE_INSERT_NOUNLOCK);
btree_err:
bch2_trans_iter_put(&trans, inode_iter);
if (ret == -EINTR)
goto retry;
if (unlikely(ret))
@ -353,21 +355,22 @@ int bch2_acl_chmod(struct btree_trans *trans,
struct bkey_s_c_xattr xattr;
struct bkey_i_xattr *new;
struct posix_acl *acl;
int ret = 0;
int ret;
iter = bch2_hash_lookup(trans, bch2_xattr_hash_desc,
&hash_info, inode->bi_inum,
&X_SEARCH(KEY_TYPE_XATTR_INDEX_POSIX_ACL_ACCESS, "", 0),
BTREE_ITER_INTENT);
if (IS_ERR(iter))
return PTR_ERR(iter) != -ENOENT ? PTR_ERR(iter) : 0;
ret = PTR_ERR_OR_ZERO(iter);
if (ret)
return ret == -ENOENT ? 0 : ret;
xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
acl = bch2_acl_from_disk(xattr_val(xattr.v),
le16_to_cpu(xattr.v->x_val_len));
if (IS_ERR_OR_NULL(acl))
return PTR_ERR(acl);
ret = PTR_ERR_OR_ZERO(acl);
if (ret || !acl)
goto err;
ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
if (ret)
@ -384,6 +387,7 @@ int bch2_acl_chmod(struct btree_trans *trans,
*new_acl = acl;
acl = NULL;
err:
bch2_trans_iter_put(trans, iter);
kfree(acl);
return ret;
}

View File

@ -139,25 +139,6 @@ static void bch2_alloc_unpack_v1(struct bkey_alloc_unpacked *out,
#undef x
}
static void bch2_alloc_pack_v1(struct bkey_alloc_buf *dst,
const struct bkey_alloc_unpacked src)
{
struct bkey_i_alloc *a = bkey_alloc_init(&dst->k);
void *d = a->v.data;
unsigned bytes, idx = 0;
a->k.p = POS(src.dev, src.bucket);
a->v.fields = 0;
a->v.gen = src.gen;
#define x(_name, _bits) alloc_field_v1_put(a, &d, idx++, src._name);
BCH_ALLOC_FIELDS_V1()
#undef x
bytes = (void *) d - (void *) &a->v;
set_bkey_val_bytes(&a->k, bytes);
memset_u64s_tail(&a->v, 0, bytes);
}
static int bch2_alloc_unpack_v2(struct bkey_alloc_unpacked *out,
struct bkey_s_c k)
{
@ -250,10 +231,7 @@ void bch2_alloc_pack(struct bch_fs *c,
struct bkey_alloc_buf *dst,
const struct bkey_alloc_unpacked src)
{
if (c->sb.features & (1ULL << BCH_FEATURE_alloc_v2))
bch2_alloc_pack_v2(dst, src);
else
bch2_alloc_pack_v1(dst, src);
bch2_alloc_pack_v2(dst, src);
}
static unsigned bch_alloc_val_u64s(const struct bch_alloc *a)
@ -410,7 +388,6 @@ int bch2_alloc_write(struct bch_fs *c, unsigned flags)
int ret = 0;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
iter = bch2_trans_get_iter(&trans, BTREE_ID_alloc, POS_MIN,
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
@ -430,6 +407,7 @@ int bch2_alloc_write(struct bch_fs *c, unsigned flags)
}
}
err:
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
@ -959,7 +937,6 @@ static int bch2_invalidate_buckets(struct bch_fs *c, struct bch_dev *ca)
int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
iter = bch2_trans_get_iter(&trans, BTREE_ID_alloc,
POS(ca->dev_idx, 0),
BTREE_ITER_CACHED|
@ -975,6 +952,7 @@ static int bch2_invalidate_buckets(struct bch_fs *c, struct bch_dev *ca)
(!fifo_empty(&ca->free_inc)
? BTREE_INSERT_NOWAIT : 0));
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
/* If we used NOWAIT, don't return the error: */

View File

@ -597,6 +597,7 @@ struct bch_fs {
uuid_le user_uuid;
u16 version;
u16 version_min;
u16 encoded_extent_max;
u8 nr_devices;

View File

@ -1376,6 +1376,7 @@ LE64_BITMASK(BCH_SB_METADATA_TARGET, struct bch_sb, flags[3], 16, 28);
((1ULL << BCH_FEATURE_new_extent_overwrite)| \
(1ULL << BCH_FEATURE_extents_above_btree_updates)|\
(1ULL << BCH_FEATURE_btree_updates_journalled)|\
(1ULL << BCH_FEATURE_alloc_v2)|\
(1ULL << BCH_FEATURE_extents_across_btree_nodes))
#define BCH_SB_FEATURES_ALL \
@ -1383,8 +1384,7 @@ LE64_BITMASK(BCH_SB_METADATA_TARGET, struct bch_sb, flags[3], 16, 28);
(1ULL << BCH_FEATURE_new_siphash)| \
(1ULL << BCH_FEATURE_btree_ptr_v2)| \
(1ULL << BCH_FEATURE_new_varint)| \
(1ULL << BCH_FEATURE_journal_no_flush)| \
(1ULL << BCH_FEATURE_alloc_v2))
(1ULL << BCH_FEATURE_journal_no_flush))
enum bch_sb_feature {
#define x(f, n) BCH_FEATURE_##f,

View File

@ -149,7 +149,6 @@ const char *bch2_bkey_in_btree_node(struct btree *b, struct bkey_s_c k)
void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
{
const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
const char *invalid;
BUG_ON(!k.k->u64s);
@ -161,11 +160,7 @@ void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
bch2_bkey_val_to_text(&PBUF(buf), c, k);
bch2_fs_inconsistent(c, "invalid bkey %s: %s", buf, invalid);
return;
}
if (ops->key_debugcheck)
ops->key_debugcheck(c, k);
}
void bch2_bpos_to_text(struct printbuf *out, struct bpos pos)

View File

@ -26,7 +26,6 @@ struct bkey_ops {
/* Returns reason for being invalid if invalid, else NULL: */
const char * (*key_invalid)(const struct bch_fs *,
struct bkey_s_c);
void (*key_debugcheck)(struct bch_fs *, struct bkey_s_c);
void (*val_to_text)(struct printbuf *, struct bch_fs *,
struct bkey_s_c);
void (*swab)(struct bkey_s);

View File

@ -373,8 +373,6 @@ static int btree_gc_mark_node(struct bch_fs *c, struct btree *b, u8 *max_stale,
bkey_init(&prev.k->k);
while ((k = bch2_btree_node_iter_peek_unpack(&iter, b, &unpacked)).k) {
bch2_bkey_debugcheck(c, b, k);
ret = bch2_gc_mark_key(c, b->c.btree_id, b->c.level, false,
k, max_stale, initial);
if (ret)
@ -439,6 +437,8 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
bch2_trans_cond_resched(&trans);
}
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)
return ret;
@ -470,8 +470,6 @@ static int bch2_gc_btree_init_recurse(struct bch_fs *c, struct btree *b,
bkey_init(&prev.k->k);
while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) {
bch2_bkey_debugcheck(c, b, k);
BUG_ON(bkey_cmp(k.k->p, b->data->min_key) < 0);
BUG_ON(bkey_cmp(k.k->p, b->data->max_key) > 0);
@ -1470,6 +1468,7 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
struct btree *b;
bool kthread = (current->flags & PF_KTHREAD) != 0;
unsigned i;
int ret = 0;
/* Sliding window of adjacent btree nodes */
struct btree *merge[GC_MERGE_NODES];
@ -1518,8 +1517,8 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
lock_seq[0] = merge[0]->c.lock.state.seq;
if (kthread && kthread_should_stop()) {
bch2_trans_exit(&trans);
return -ESHUTDOWN;
ret = -ESHUTDOWN;
break;
}
bch2_trans_cond_resched(&trans);
@ -1534,7 +1533,9 @@ static int bch2_coalesce_btree(struct bch_fs *c, enum btree_id btree_id)
memset(merge + 1, 0,
(GC_MERGE_NODES - 1) * sizeof(merge[0]));
}
return bch2_trans_exit(&trans);
bch2_trans_iter_put(&trans, iter);
return bch2_trans_exit(&trans) ?: ret;
}
/**

View File

@ -560,6 +560,26 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
BTREE_ERR_FATAL, c, ca, b, i,
"unsupported bset version");
if (btree_err_on(version < c->sb.version_min,
BTREE_ERR_FIXABLE, c, NULL, b, i,
"bset version %u older than superblock version_min %u",
version, c->sb.version_min)) {
mutex_lock(&c->sb_lock);
c->disk_sb.sb->version_min = cpu_to_le16(version);
bch2_write_super(c);
mutex_unlock(&c->sb_lock);
}
if (btree_err_on(version > c->sb.version,
BTREE_ERR_FIXABLE, c, NULL, b, i,
"bset version %u newer than superblock version %u",
version, c->sb.version)) {
mutex_lock(&c->sb_lock);
c->disk_sb.sb->version = cpu_to_le16(version);
bch2_write_super(c);
mutex_unlock(&c->sb_lock);
}
if (btree_err_on(b->written + sectors > c->opts.btree_node_size,
BTREE_ERR_FIXABLE, c, ca, b, i,
"bset past end of btree node")) {
@ -753,6 +773,8 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
unsigned u64s;
int ret, retry_read = 0, write = READ;
b->version_ondisk = U16_MAX;
iter = mempool_alloc(&c->fill_iter, GFP_NOIO);
sort_iter_init(iter, b);
iter->size = (btree_blocks(c) + 1) * 2;
@ -832,6 +854,9 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
sectors = vstruct_sectors(bne, c->block_bits);
}
b->version_ondisk = min(b->version_ondisk,
le16_to_cpu(i->version));
ret = validate_bset(c, ca, b, i, sectors,
READ, have_retry);
if (ret)
@ -1200,6 +1225,7 @@ retry:
if (ret)
goto err;
out:
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&k, c);
bio_put(&wbio->wbio.bio);

View File

@ -9,6 +9,7 @@
#include "btree_locking.h"
#include "btree_update.h"
#include "debug.h"
#include "error.h"
#include "extents.h"
#include "journal.h"
@ -1424,7 +1425,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter)
if (btree_node_read_locked(iter, iter->level))
btree_node_unlock(iter, iter->level);
iter->pos = bkey_successor(iter->pos);
iter->pos = iter->real_pos = bkey_successor(iter->pos);
iter->level = iter->min_depth;
btree_iter_set_dirty(iter, BTREE_ITER_NEED_TRAVERSE);
@ -1496,7 +1497,7 @@ void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos new_pos)
btree_iter_set_search_pos(iter, btree_iter_search_key(iter));
}
static inline bool bch2_btree_iter_advance_pos(struct btree_iter *iter)
inline bool bch2_btree_iter_advance_pos(struct btree_iter *iter)
{
struct bpos pos = iter->k.p;
bool ret = bkey_cmp(pos, POS_MAX) != 0;
@ -1507,7 +1508,7 @@ static inline bool bch2_btree_iter_advance_pos(struct btree_iter *iter)
return ret;
}
static inline bool bch2_btree_iter_rewind_pos(struct btree_iter *iter)
inline bool bch2_btree_iter_rewind_pos(struct btree_iter *iter)
{
struct bpos pos = bkey_start_pos(&iter->k);
bool ret = bkey_cmp(pos, POS_MIN) != 0;
@ -1955,6 +1956,7 @@ int bch2_trans_iter_put(struct btree_trans *trans,
return 0;
BUG_ON(trans->iters + iter->idx != iter);
BUG_ON(!btree_iter_live(trans, iter));
ret = btree_iter_err(iter);
@ -1972,7 +1974,7 @@ int bch2_trans_iter_free(struct btree_trans *trans,
if (IS_ERR_OR_NULL(iter))
return 0;
trans->iters_touched &= ~(1ULL << iter->idx);
set_btree_iter_dontneed(trans, iter);
return bch2_trans_iter_put(trans, iter);
}
@ -2116,6 +2118,7 @@ struct btree_iter *bch2_trans_get_node_iter(struct btree_trans *trans,
for (i = 0; i < ARRAY_SIZE(iter->l); i++)
iter->l[i].b = NULL;
iter->l[iter->level].b = BTREE_ITER_NO_NODE_INIT;
iter->ip_allocated = _RET_IP_;
return iter;
}
@ -2133,7 +2136,7 @@ struct btree_iter *__bch2_trans_copy_iter(struct btree_trans *trans,
* We don't need to preserve this iter since it's cheap to copy it
* again - this will cause trans_iter_put() to free it right away:
*/
trans->iters_touched &= ~(1ULL << iter->idx);
set_btree_iter_dontneed(trans, iter);
return iter;
}
@ -2214,6 +2217,8 @@ void bch2_trans_reset(struct btree_trans *trans, unsigned flags)
(void *) &trans->fs_usage_deltas->memset_start);
}
bch2_trans_cond_resched(trans);
if (!(flags & TRANS_RESET_NOTRAVERSE))
bch2_btree_iter_traverse_all(trans);
}
@ -2273,6 +2278,19 @@ int bch2_trans_exit(struct btree_trans *trans)
bch2_trans_unlock(trans);
#ifdef CONFIG_BCACHEFS_DEBUG
if (trans->iters_live) {
struct btree_iter *iter;
bch_err(c, "btree iterators leaked!");
trans_for_each_iter(trans, iter)
if (btree_iter_live(trans, iter))
printk(KERN_ERR " btree %s allocated at %pS\n",
bch2_btree_ids[iter->btree_id],
(void *) iter->ip_allocated);
/* Be noisy about this: */
bch2_fatal_error(c);
}
mutex_lock(&trans->c->btree_trans_lock);
list_del(&trans->list);
mutex_unlock(&trans->c->btree_trans_lock);

View File

@ -175,6 +175,8 @@ struct bkey_s_c bch2_btree_iter_prev_slot(struct btree_iter *);
struct bkey_s_c bch2_btree_iter_peek_cached(struct btree_iter *);
bool bch2_btree_iter_advance_pos(struct btree_iter *);
bool bch2_btree_iter_rewind_pos(struct btree_iter *);
void bch2_btree_iter_set_pos(struct btree_iter *, struct bpos);
/* Sort order for locking btree iterators: */
@ -298,6 +300,11 @@ static inline bool btree_iter_keep(struct btree_trans *trans, struct btree_iter
(iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT);
}
static inline void set_btree_iter_dontneed(struct btree_trans *trans, struct btree_iter *iter)
{
trans->iters_touched &= ~(1ULL << iter->idx);
}
#define TRANS_RESET_NOTRAVERSE (1 << 0)
void bch2_trans_reset(struct btree_trans *, unsigned);

View File

@ -171,23 +171,21 @@ static int btree_key_cache_fill(struct btree_trans *trans,
ck->key.pos, BTREE_ITER_SLOTS);
k = bch2_btree_iter_peek_slot(iter);
ret = bkey_err(k);
if (ret) {
bch2_trans_iter_put(trans, iter);
return ret;
}
if (ret)
goto err;
if (!bch2_btree_node_relock(ck_iter, 0)) {
bch2_trans_iter_put(trans, iter);
trace_transaction_restart_ip(trans->ip, _THIS_IP_);
return -EINTR;
ret = -EINTR;
goto err;
}
if (k.k->u64s > ck->u64s) {
new_u64s = roundup_pow_of_two(k.k->u64s);
new_k = kmalloc(new_u64s * sizeof(u64), GFP_NOFS);
if (!new_k) {
bch2_trans_iter_put(trans, iter);
return -ENOMEM;
ret = -ENOMEM;
goto err;
}
}
@ -203,9 +201,10 @@ static int btree_key_cache_fill(struct btree_trans *trans,
bch2_btree_node_unlock_write(ck_iter->l[0].b, ck_iter);
/* We're not likely to need this iterator again: */
bch2_trans_iter_free(trans, iter);
return 0;
set_btree_iter_dontneed(trans, iter);
err:
bch2_trans_iter_put(trans, iter);
return ret;
}
static int bkey_cached_check_fn(struct six_lock *lock, void *p)

View File

@ -76,6 +76,7 @@ struct btree {
u16 written;
u8 nsets;
u8 nr_key_bits;
u16 version_ondisk;
struct bkey_format format;

View File

@ -282,6 +282,7 @@ static struct btree *bch2_btree_node_alloc(struct btree_update *as, unsigned lev
bch2_bset_init_first(b, &b->data->keys);
b->c.level = level;
b->c.btree_id = as->btree_id;
b->version_ondisk = c->sb.version;
memset(&b->nr, 0, sizeof(b->nr));
b->data->magic = cpu_to_le64(bset_magic(c));

View File

@ -754,7 +754,7 @@ static int extent_handle_overwrites(struct btree_trans *trans,
enum btree_id btree_id,
struct bpos start, struct bpos end)
{
struct btree_iter *iter = NULL, *update_iter;
struct btree_iter *iter, *update_iter;
struct bkey_i *update;
struct bkey_s_c k;
int ret = 0;
@ -767,8 +767,6 @@ static int extent_handle_overwrites(struct btree_trans *trans,
break;
if (bkey_cmp(bkey_start_pos(k.k), start) < 0) {
update_iter = bch2_trans_copy_iter(trans, iter);
update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
if ((ret = PTR_ERR_OR_ZERO(update)))
goto err;
@ -776,6 +774,7 @@ static int extent_handle_overwrites(struct btree_trans *trans,
bkey_reassemble(update, k);
bch2_cut_back(start, update);
update_iter = bch2_trans_copy_iter(trans, iter);
update_iter->flags &= ~BTREE_ITER_IS_EXTENTS;
bch2_btree_iter_set_pos(update_iter, update->k.p);
ret = bch2_trans_update2(trans, update_iter, update);
@ -785,8 +784,6 @@ static int extent_handle_overwrites(struct btree_trans *trans,
}
if (bkey_cmp(k.k->p, end) > 0) {
update_iter = bch2_trans_copy_iter(trans, iter);
update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
if ((ret = PTR_ERR_OR_ZERO(update)))
goto err;
@ -794,6 +791,7 @@ static int extent_handle_overwrites(struct btree_trans *trans,
bkey_reassemble(update, k);
bch2_cut_front(end, update);
update_iter = bch2_trans_copy_iter(trans, iter);
update_iter->flags &= ~BTREE_ITER_IS_EXTENTS;
bch2_btree_iter_set_pos(update_iter, update->k.p);
ret = bch2_trans_update2(trans, update_iter, update);
@ -801,8 +799,6 @@ static int extent_handle_overwrites(struct btree_trans *trans,
if (ret)
goto err;
} else {
update_iter = bch2_trans_copy_iter(trans, iter);
update = bch2_trans_kmalloc(trans, sizeof(struct bkey));
if ((ret = PTR_ERR_OR_ZERO(update)))
goto err;
@ -812,6 +808,7 @@ static int extent_handle_overwrites(struct btree_trans *trans,
update->k.type = KEY_TYPE_deleted;
update->k.size = 0;
update_iter = bch2_trans_copy_iter(trans, iter);
update_iter->flags &= ~BTREE_ITER_IS_EXTENTS;
bch2_btree_iter_set_pos(update_iter, update->k.p);
ret = bch2_trans_update2(trans, update_iter, update);
@ -823,8 +820,7 @@ static int extent_handle_overwrites(struct btree_trans *trans,
k = bch2_btree_iter_next_with_updates(iter);
}
err:
if (!IS_ERR_OR_NULL(iter))
bch2_trans_iter_put(trans, iter);
bch2_trans_iter_put(trans, iter);
return ret;
}

View File

@ -1481,6 +1481,10 @@ static struct btree_iter *trans_get_update(struct btree_trans *trans,
bkey_cmp(pos, i->k->k.p) < 0
: !bkey_cmp(pos, i->iter->pos))) {
*k = bkey_i_to_s_c(i->k);
/* ugly hack.. */
BUG_ON(btree_iter_live(trans, i->iter));
trans->iters_live |= 1ULL << i->iter->idx;
return i->iter;
}

View File

@ -242,6 +242,8 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
if (!i->size)
break;
}
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return err < 0 ? err : i->ret;
@ -294,6 +296,8 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
if (!i->size)
break;
}
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return err < 0 ? err : i->ret;

View File

@ -321,6 +321,7 @@ u64 bch2_dirent_lookup(struct bch_fs *c, u64 dir_inum,
k = bch2_btree_iter_peek_slot(iter);
inum = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum);
bch2_trans_iter_put(&trans, iter);
out:
bch2_trans_exit(&trans);
return inum;
@ -379,6 +380,8 @@ int bch2_readdir(struct bch_fs *c, u64 inum, struct dir_context *ctx)
break;
ctx->pos = dirent.k->p.offset + 1;
}
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
return ret;

View File

@ -1663,12 +1663,13 @@ int bch2_ec_mem_alloc(struct bch_fs *c, bool gc)
int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
iter = bch2_trans_get_iter(&trans, BTREE_ID_stripes, POS(0, U64_MAX), 0);
k = bch2_btree_iter_prev(iter);
if (!IS_ERR_OR_NULL(k.k))
idx = k.k->p.offset + 1;
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans);
if (ret)
return ret;

View File

@ -164,46 +164,6 @@ const char *bch2_btree_ptr_invalid(const struct bch_fs *c, struct bkey_s_c k)
return bch2_bkey_ptrs_invalid(c, k);
}
void bch2_btree_ptr_debugcheck(struct bch_fs *c, struct bkey_s_c k)
{
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const struct bch_extent_ptr *ptr;
const char *err;
char buf[160];
struct bucket_mark mark;
struct bch_dev *ca;
if (!test_bit(BCH_FS_INITIAL_GC_DONE, &c->flags))
return;
if (!percpu_down_read_trylock(&c->mark_lock))
return;
bkey_for_each_ptr(ptrs, ptr) {
ca = bch_dev_bkey_exists(c, ptr->dev);
mark = ptr_bucket_mark(ca, ptr);
err = "stale";
if (gen_after(mark.gen, ptr->gen))
goto err;
err = "inconsistent";
if (mark.data_type != BCH_DATA_btree ||
mark.dirty_sectors < c->opts.btree_node_size)
goto err;
}
out:
percpu_up_read(&c->mark_lock);
return;
err:
bch2_fs_inconsistent(c, "%s btree pointer %s: bucket %zi gen %i mark %08x",
err, (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf),
PTR_BUCKET_NR(ca, ptr),
mark.gen, (unsigned) mark.v.counter);
goto out;
}
void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c,
struct bkey_s_c k)
{
@ -247,49 +207,6 @@ const char *bch2_extent_invalid(const struct bch_fs *c, struct bkey_s_c k)
return bch2_bkey_ptrs_invalid(c, k);
}
void bch2_extent_debugcheck(struct bch_fs *c, struct bkey_s_c k)
{
struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
const union bch_extent_entry *entry;
struct extent_ptr_decoded p;
char buf[160];
if (!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags) ||
!test_bit(BCH_FS_INITIAL_GC_DONE, &c->flags))
return;
if (!percpu_down_read_trylock(&c->mark_lock))
return;
extent_for_each_ptr_decode(e, p, entry) {
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
struct bucket_mark mark = ptr_bucket_mark(ca, &p.ptr);
unsigned stale = gen_after(mark.gen, p.ptr.gen);
unsigned disk_sectors = ptr_disk_sectors(p);
unsigned mark_sectors = p.ptr.cached
? mark.cached_sectors
: mark.dirty_sectors;
bch2_fs_inconsistent_on(stale && !p.ptr.cached, c,
"stale dirty pointer (ptr gen %u bucket %u",
p.ptr.gen, mark.gen);
bch2_fs_inconsistent_on(stale > 96, c,
"key too stale: %i", stale);
bch2_fs_inconsistent_on(!stale &&
(mark.data_type != BCH_DATA_user ||
mark_sectors < disk_sectors), c,
"extent pointer not marked: %s:\n"
"type %u sectors %u < %u",
(bch2_bkey_val_to_text(&PBUF(buf), c, e.s_c), buf),
mark.data_type,
mark_sectors, disk_sectors);
}
percpu_up_read(&c->mark_lock);
}
void bch2_extent_to_text(struct printbuf *out, struct bch_fs *c,
struct bkey_s_c k)
{
@ -688,6 +605,8 @@ bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size,
break;
}
}
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
@ -1265,7 +1184,7 @@ int bch2_cut_back_s(struct bpos where, struct bkey_s k)
len = where.offset - bkey_start_offset(k.k);
k.k->p = where;
k.k->p.offset = where.offset;
k.k->size = len;
if (!len) {

View File

@ -368,7 +368,6 @@ int bch2_bkey_pick_read_device(struct bch_fs *, struct bkey_s_c,
/* KEY_TYPE_btree_ptr: */
const char *bch2_btree_ptr_invalid(const struct bch_fs *, struct bkey_s_c);
void bch2_btree_ptr_debugcheck(struct bch_fs *, struct bkey_s_c);
void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *,
struct bkey_s_c);
@ -379,14 +378,12 @@ void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned,
#define bch2_bkey_ops_btree_ptr (struct bkey_ops) { \
.key_invalid = bch2_btree_ptr_invalid, \
.key_debugcheck = bch2_btree_ptr_debugcheck, \
.val_to_text = bch2_btree_ptr_to_text, \
.swab = bch2_ptr_swab, \
}
#define bch2_bkey_ops_btree_ptr_v2 (struct bkey_ops) { \
.key_invalid = bch2_btree_ptr_invalid, \
.key_debugcheck = bch2_btree_ptr_debugcheck, \
.val_to_text = bch2_btree_ptr_v2_to_text, \
.swab = bch2_ptr_swab, \
.compat = bch2_btree_ptr_v2_compat, \
@ -395,14 +392,12 @@ void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned,
/* KEY_TYPE_extent: */
const char *bch2_extent_invalid(const struct bch_fs *, struct bkey_s_c);
void bch2_extent_debugcheck(struct bch_fs *, struct bkey_s_c);
void bch2_extent_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
enum merge_result bch2_extent_merge(struct bch_fs *,
struct bkey_s, struct bkey_s);
#define bch2_bkey_ops_extent (struct bkey_ops) { \
.key_invalid = bch2_extent_invalid, \
.key_debugcheck = bch2_extent_debugcheck, \
.val_to_text = bch2_extent_to_text, \
.swab = bch2_ptr_swab, \
.key_normalize = bch2_extent_normalize, \

View File

@ -883,7 +883,6 @@ void bch2_readahead(struct readahead_control *ractl)
BUG_ON(ret);
bch2_trans_init(&trans, c, 0, 0);
iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, POS_MIN,
BTREE_ITER_SLOTS);
@ -912,6 +911,7 @@ void bch2_readahead(struct readahead_control *ractl)
bch2_pagecache_add_put(&inode->ei_pagecache_lock);
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
kfree(readpages_iter.pages);
}
@ -935,6 +935,7 @@ static void __bchfs_readpage(struct bch_fs *c, struct bch_read_bio *rbio,
bchfs_read(&trans, iter, rbio, inum, NULL);
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
}
@ -2143,6 +2144,7 @@ static inline int range_has_data(struct bch_fs *c,
break;
}
}
bch2_trans_iter_put(&trans, iter);
return bch2_trans_exit(&trans) ?: ret;
}
@ -2312,6 +2314,7 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
bch2_trans_init(&trans, c, 0, 0);
iter = bch2_inode_peek(&trans, &inode_u, inode->v.i_ino, 0);
ret = PTR_ERR_OR_ZERO(iter);
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
if (ret)
@ -2445,14 +2448,11 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
struct btree_iter *src, *dst, *del;
loff_t shift, new_size;
u64 src_start;
int ret;
int ret = 0;
if ((offset | len) & (block_bytes(c) - 1))
return -EINVAL;
bch2_bkey_buf_init(&copy);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256);
/*
* We need i_mutex to keep the page cache consistent with the extents
* btree, and the btree consistent with i_size - we don't need outside
@ -2508,13 +2508,15 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
goto err;
}
bch2_bkey_buf_init(&copy);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256);
src = bch2_trans_get_iter(&trans, BTREE_ID_extents,
POS(inode->v.i_ino, src_start >> 9),
BTREE_ITER_INTENT);
dst = bch2_trans_copy_iter(&trans, src);
del = bch2_trans_copy_iter(&trans, src);
while (1) {
while (ret == 0 || ret == -EINTR) {
struct disk_reservation disk_res =
bch2_disk_reservation_init(c, 0);
struct bkey_i delete;
@ -2528,7 +2530,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
? bch2_btree_iter_peek_prev(src)
: bch2_btree_iter_peek(src);
if ((ret = bkey_err(k)))
goto bkey_err;
continue;
if (!k.k || k.k->p.inode != inode->v.i_ino)
break;
@ -2548,7 +2550,7 @@ reassemble:
ret = bch2_extent_atomic_end(dst, copy.k, &atomic_end);
if (ret)
goto bkey_err;
continue;
if (bkey_cmp(atomic_end, copy.k->k.p)) {
if (insert) {
@ -2591,18 +2593,18 @@ reassemble:
&inode->ei_journal_seq,
BTREE_INSERT_NOFAIL);
bch2_disk_reservation_put(c, &disk_res);
bkey_err:
if (!ret)
bch2_btree_iter_set_pos(src, next_pos);
if (ret == -EINTR)
ret = 0;
if (ret)
goto err;
bch2_trans_cond_resched(&trans);
}
bch2_trans_unlock(&trans);
bch2_trans_iter_put(&trans, del);
bch2_trans_iter_put(&trans, dst);
bch2_trans_iter_put(&trans, src);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&copy, c);
if (ret)
goto err;
if (!insert) {
i_size_write(&inode->v, new_size);
@ -2612,8 +2614,6 @@ bkey_err:
mutex_unlock(&inode->ei_update_lock);
}
err:
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&copy, c);
bch2_pagecache_block_put(&inode->ei_pagecache_lock);
inode_unlock(&inode->v);
return ret;
@ -2668,7 +2668,7 @@ static long bchfs_fallocate(struct bch_inode_info *inode, int mode,
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
end_pos = POS(inode->v.i_ino, block_end >> 9);
while (bkey_cmp(iter->pos, end_pos) < 0) {
while (!ret && bkey_cmp(iter->pos, end_pos) < 0) {
s64 i_sectors_delta = 0;
struct disk_reservation disk_res = { 0 };
struct quota_res quota_res = { 0 };
@ -2732,9 +2732,11 @@ bkey_err:
bch2_disk_reservation_put(c, &disk_res);
if (ret == -EINTR)
ret = 0;
if (ret)
goto err;
}
bch2_trans_iter_put(&trans, iter);
if (ret)
goto err;
/*
* Do we need to extend the file?
@ -2756,6 +2758,7 @@ bkey_err:
ret = PTR_ERR_OR_ZERO(inode_iter);
} while (ret == -EINTR);
bch2_trans_iter_put(&trans, inode_iter);
bch2_trans_unlock(&trans);
if (ret)
@ -3003,6 +3006,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
} else if (k.k->p.offset >> 9 > isize)
break;
}
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)
@ -3106,6 +3110,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
offset = max(offset, bkey_start_offset(k.k) << 9);
}
}
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)

View File

@ -725,6 +725,8 @@ retry:
BTREE_INSERT_NOUNLOCK|
BTREE_INSERT_NOFAIL);
btree_err:
bch2_trans_iter_put(&trans, inode_iter);
if (ret == -EINTR)
goto retry;
if (unlikely(ret))
@ -948,6 +950,7 @@ retry:
ret = bch2_fill_extent(c, info, bkey_i_to_s_c(prev.k),
FIEMAP_EXTENT_LAST);
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
bch2_bkey_buf_exit(&cur, c);
bch2_bkey_buf_exit(&prev, c);

View File

@ -319,7 +319,7 @@ static int hash_check_key(struct btree_trans *trans,
bch_err(c, "hash_redo_key err %i", ret);
return ret;
}
return 1;
return -EINTR;
}
ret = hash_check_duplicates(trans, desc, h, k_iter, k);
@ -413,18 +413,10 @@ err_redo:
goto err;
}
static int bch2_inode_truncate(struct bch_fs *c, u64 inode_nr, u64 new_size)
{
return bch2_btree_delete_range(c, BTREE_ID_extents,
POS(inode_nr, round_up(new_size, block_bytes(c)) >> 9),
POS(inode_nr + 1, 0), NULL);
}
static int bch2_fix_overlapping_extent(struct btree_trans *trans,
struct btree_iter *iter,
static int fix_overlapping_extent(struct btree_trans *trans,
struct bkey_s_c k, struct bpos cut_at)
{
struct btree_iter *u_iter;
struct btree_iter *iter;
struct bkey_i *u;
int ret;
@ -436,22 +428,24 @@ static int bch2_fix_overlapping_extent(struct btree_trans *trans,
bkey_reassemble(u, k);
bch2_cut_front(cut_at, u);
u_iter = bch2_trans_copy_iter(trans, iter);
/*
* We don't want to go through the
* extent_handle_overwrites path:
* We don't want to go through the extent_handle_overwrites path:
*
* XXX: this is going to screw up disk accounting, extent triggers
* assume things about extent overwrites - we should be running the
* triggers manually here
*/
u_iter->flags &= ~BTREE_ITER_IS_EXTENTS;
bch2_btree_iter_set_pos(u_iter, u->k.p);
iter = bch2_trans_get_iter(trans, BTREE_ID_extents, u->k.p,
BTREE_ITER_INTENT|BTREE_ITER_NOT_EXTENTS);
/*
* XXX: this is going to leave disk space
* accounting slightly wrong
*/
ret = bch2_trans_update(trans, u_iter, u, 0);
bch2_trans_iter_put(trans, u_iter);
return ret;
BUG_ON(iter->flags & BTREE_ITER_IS_EXTENTS);
bch2_trans_update(trans, iter, u, BTREE_TRIGGER_NORUN);
bch2_trans_iter_put(trans, iter);
return bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW);
}
/*
@ -466,7 +460,7 @@ static int check_extents(struct bch_fs *c)
struct btree_iter *iter;
struct bkey_s_c k;
struct bkey_buf prev;
u64 i_sectors;
u64 i_sectors = 0;
int ret = 0;
bch2_bkey_buf_init(&prev);
@ -479,97 +473,86 @@ static int check_extents(struct bch_fs *c)
POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_INTENT);
retry:
for_each_btree_key_continue(iter, 0, k, ret) {
/*
* due to retry errors we might see the same extent twice:
*/
if (bkey_cmp(prev.k->k.p, k.k->p) &&
bkey_cmp(prev.k->k.p, bkey_start_pos(k.k)) > 0) {
while ((k = bch2_btree_iter_peek(iter)).k &&
!(ret = bkey_err(k))) {
if (w.have_inode &&
w.cur_inum != k.k->p.inode &&
!(w.inode.bi_flags & BCH_INODE_I_SECTORS_DIRTY) &&
fsck_err_on(w.inode.bi_sectors != i_sectors, c,
"inode %llu has incorrect i_sectors: got %llu, should be %llu",
w.inode.bi_inum,
w.inode.bi_sectors, i_sectors)) {
struct btree_iter *inode_iter =
bch2_trans_get_iter(&trans, BTREE_ID_inodes,
POS(0, w.cur_inum),
BTREE_ITER_INTENT);
w.inode.bi_sectors = i_sectors;
ret = __bch2_trans_do(&trans, NULL, NULL,
BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW,
bch2_inode_write(&trans, inode_iter, &w.inode));
bch2_trans_iter_put(&trans, inode_iter);
if (ret)
break;
}
if (bkey_cmp(prev.k->k.p, bkey_start_pos(k.k)) > 0) {
char buf1[200];
char buf2[200];
bch2_bkey_val_to_text(&PBUF(buf1), c, bkey_i_to_s_c(prev.k));
bch2_bkey_val_to_text(&PBUF(buf2), c, k);
if (fsck_err(c, "overlapping extents:\n%s\n%s", buf1, buf2)) {
ret = __bch2_trans_do(&trans, NULL, NULL,
BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW,
bch2_fix_overlapping_extent(&trans,
iter, k, prev.k->k.p));
if (ret)
goto err;
}
if (fsck_err(c, "overlapping extents:\n%s\n%s", buf1, buf2))
return fix_overlapping_extent(&trans, k, prev.k->k.p) ?: -EINTR;
}
bch2_bkey_buf_reassemble(&prev, c, k);
ret = walk_inode(&trans, &w, k.k->p.inode);
if (ret)
break;
if (w.first_this_inode)
i_sectors = 0;
if (fsck_err_on(!w.have_inode, c,
"extent type %u for missing inode %llu",
k.k->type, k.k->p.inode) ||
"extent type %u for missing inode %llu",
k.k->type, k.k->p.inode) ||
fsck_err_on(w.have_inode &&
!S_ISREG(w.inode.bi_mode) && !S_ISLNK(w.inode.bi_mode), c,
"extent type %u for non regular file, inode %llu mode %o",
k.k->type, k.k->p.inode, w.inode.bi_mode)) {
bch2_trans_unlock(&trans);
ret = bch2_inode_truncate(c, k.k->p.inode, 0);
if (ret)
goto err;
continue;
}
if (fsck_err_on(w.first_this_inode &&
w.have_inode &&
!(w.inode.bi_flags & BCH_INODE_I_SECTORS_DIRTY) &&
w.inode.bi_sectors !=
(i_sectors = bch2_count_inode_sectors(&trans, w.cur_inum)),
c, "inode %llu has incorrect i_sectors: got %llu, should be %llu",
w.inode.bi_inum,
w.inode.bi_sectors, i_sectors)) {
struct bkey_inode_buf p;
w.inode.bi_sectors = i_sectors;
bch2_trans_unlock(&trans);
bch2_inode_pack(c, &p, &w.inode);
ret = bch2_btree_insert(c, BTREE_ID_inodes,
&p.inode.k_i, NULL, NULL,
BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW);
if (ret) {
bch_err(c, "error in fsck: error %i updating inode", ret);
goto err;
}
/* revalidate iterator: */
k = bch2_btree_iter_peek(iter);
!S_ISREG(w.inode.bi_mode) && !S_ISLNK(w.inode.bi_mode), c,
"extent type %u for non regular file, inode %llu mode %o",
k.k->type, k.k->p.inode, w.inode.bi_mode)) {
bch2_fs_lazy_rw(c);
return bch2_btree_delete_range_trans(&trans, BTREE_ID_extents,
POS(k.k->p.inode, 0),
POS(k.k->p.inode, U64_MAX),
NULL) ?: -EINTR;
}
if (fsck_err_on(w.have_inode &&
!(w.inode.bi_flags & BCH_INODE_I_SIZE_DIRTY) &&
k.k->type != KEY_TYPE_reservation &&
k.k->p.offset > round_up(w.inode.bi_size, block_bytes(c)) >> 9, c,
"extent type %u offset %llu past end of inode %llu, i_size %llu",
k.k->type, k.k->p.offset, k.k->p.inode, w.inode.bi_size)) {
bch2_trans_unlock(&trans);
ret = bch2_inode_truncate(c, k.k->p.inode,
w.inode.bi_size);
if (ret)
goto err;
continue;
!(w.inode.bi_flags & BCH_INODE_I_SIZE_DIRTY) &&
k.k->type != KEY_TYPE_reservation &&
k.k->p.offset > round_up(w.inode.bi_size, block_bytes(c)) >> 9, c,
"extent type %u offset %llu past end of inode %llu, i_size %llu",
k.k->type, k.k->p.offset, k.k->p.inode, w.inode.bi_size)) {
bch2_fs_lazy_rw(c);
return bch2_btree_delete_range_trans(&trans, BTREE_ID_extents,
POS(k.k->p.inode, round_up(w.inode.bi_size, block_bytes(c))),
POS(k.k->p.inode, U64_MAX),
NULL) ?: -EINTR;
}
if (bkey_extent_is_allocation(k.k))
i_sectors += k.k->size;
bch2_bkey_buf_reassemble(&prev, c, k);
bch2_btree_iter_advance_pos(iter);
}
err:
fsck_err:
if (ret == -EINTR)
goto retry;
bch2_trans_iter_put(&trans, iter);
bch2_bkey_buf_exit(&prev, c);
return bch2_trans_exit(&trans) ?: ret;
}
@ -599,7 +582,8 @@ static int check_dirents(struct bch_fs *c)
iter = bch2_trans_get_iter(&trans, BTREE_ID_dirents,
POS(BCACHEFS_ROOT_INO, 0), 0);
retry:
for_each_btree_key_continue(iter, 0, k, ret) {
while ((k = bch2_btree_iter_peek(iter)).k &&
!(ret = bkey_err(k))) {
struct bkey_s_c_dirent d;
struct bch_inode_unpacked target;
bool have_target;
@ -718,6 +702,8 @@ retry:
goto err;
}
bch2_btree_iter_advance_pos(iter);
}
hash_stop_chain(&trans, &h);
@ -726,6 +712,8 @@ fsck_err:
if (ret == -EINTR)
goto retry;
bch2_trans_iter_put(&trans, h.chain);
bch2_trans_iter_put(&trans, iter);
return bch2_trans_exit(&trans) ?: ret;
}
@ -751,7 +739,8 @@ static int check_xattrs(struct bch_fs *c)
iter = bch2_trans_get_iter(&trans, BTREE_ID_xattrs,
POS(BCACHEFS_ROOT_INO, 0), 0);
retry:
for_each_btree_key_continue(iter, 0, k, ret) {
while ((k = bch2_btree_iter_peek(iter)).k &&
!(ret = bkey_err(k))) {
ret = walk_inode(&trans, &w, k.k->p.inode);
if (ret)
break;
@ -761,7 +750,7 @@ retry:
k.k->p.inode)) {
ret = bch2_btree_delete_at(&trans, iter, 0);
if (ret)
goto err;
break;
continue;
}
@ -771,12 +760,16 @@ retry:
ret = hash_check_key(&trans, bch2_xattr_hash_desc,
&h, iter, k);
if (ret)
goto fsck_err;
break;
bch2_btree_iter_advance_pos(iter);
}
err:
fsck_err:
if (ret == -EINTR)
goto retry;
bch2_trans_iter_put(&trans, h.chain);
bch2_trans_iter_put(&trans, iter);
return bch2_trans_exit(&trans) ?: ret;
}
@ -1127,6 +1120,8 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
bch2_trans_cond_resched(&trans);
}
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)
bch_err(c, "error in fsck: btree error %i while walking dirents", ret);
@ -1279,8 +1274,10 @@ static int check_inode(struct btree_trans *trans,
* XXX: need to truncate partial blocks too here - or ideally
* just switch units to bytes and that issue goes away
*/
ret = bch2_inode_truncate(c, u.bi_inum, u.bi_size);
ret = bch2_btree_delete_range_trans(trans, BTREE_ID_extents,
POS(u.bi_inum, round_up(u.bi_size, block_bytes(c))),
POS(u.bi_inum, U64_MAX),
NULL);
if (ret) {
bch_err(c, "error in fsck: error %i truncating inode", ret);
return ret;
@ -1392,10 +1389,11 @@ peek_nlinks: link = genradix_iter_peek(&nlinks_iter, links);
if (nlinks_pos == iter->pos.offset)
genradix_iter_advance(&nlinks_iter, links);
bch2_btree_iter_next(iter);
bch2_btree_iter_advance_pos(iter);
bch2_trans_cond_resched(&trans);
}
fsck_err:
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
if (ret2)
@ -1487,11 +1485,12 @@ int bch2_fsck_walk_inodes_only(struct bch_fs *c)
BCH_INODE_I_SECTORS_DIRTY|
BCH_INODE_UNLINKED)) {
ret = check_inode(&trans, NULL, iter, inode, NULL);
BUG_ON(ret == -EINTR);
if (ret)
break;
}
}
bch2_trans_iter_put(&trans, iter);
BUG_ON(ret == -EINTR);
return bch2_trans_exit(&trans) ?: ret;

View File

@ -620,6 +620,7 @@ retry:
ret = bch2_trans_commit(&trans, NULL, NULL,
BTREE_INSERT_NOFAIL);
bch2_trans_iter_put(&trans, iter);
err:
if (ret == -EINTR)
goto retry;

View File

@ -404,6 +404,8 @@ int bch2_fpunch(struct bch_fs *c, u64 inum, u64 start, u64 end,
ret = bch2_fpunch_at(&trans, iter, POS(inum, end),
journal_seq, i_sectors_delta);
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
if (ret == -EINTR)
@ -450,6 +452,7 @@ int bch2_write_index_default(struct bch_write_op *op)
bch2_keylist_pop_front(keys);
} while (!bch2_keylist_empty(keys));
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
@ -1667,6 +1670,7 @@ retry:
goto err;
out:
bch2_rbio_done(rbio);
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
return;
@ -2260,7 +2264,7 @@ retry:
k = bch2_btree_iter_peek_slot(iter);
ret = bkey_err(k);
if (ret)
goto err;
break;
offset_into_extent = iter->pos.offset -
bkey_start_offset(k.k);
@ -2271,7 +2275,7 @@ retry:
ret = bch2_read_indirect_extent(&trans, &data_btree,
&offset_into_extent, &sk);
if (ret)
goto err;
break;
k = bkey_i_to_s_c(sk.k);
@ -2296,12 +2300,8 @@ retry:
ret = __bch2_read_extent(&trans, rbio, bvec_iter, iter->pos,
data_btree, k,
offset_into_extent, failed, flags);
switch (ret) {
case READ_RETRY:
goto retry;
case READ_ERR:
goto err;
};
if (ret)
break;
if (flags & BCH_READ_LAST_FRAGMENT)
break;
@ -2309,19 +2309,19 @@ retry:
swap(bvec_iter.bi_size, bytes);
bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
}
out:
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
return;
err:
if (ret == -EINTR)
bch2_trans_iter_put(&trans, iter);
if (ret == -EINTR || ret == READ_RETRY || ret == READ_RETRY_AVOID)
goto retry;
bch_err_inum_ratelimited(c, inode,
"read error %i from btree lookup", ret);
rbio->bio.bi_status = BLK_STS_IOERR;
bch2_rbio_done(rbio);
goto out;
if (ret) {
bch_err_inum_ratelimited(c, inode,
"read error %i from btree lookup", ret);
rbio->bio.bi_status = BLK_STS_IOERR;
bch2_rbio_done(rbio);
}
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
}
void bch2_fs_io_exit(struct bch_fs *c)

View File

@ -1234,6 +1234,9 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
&c->rw_devs[BCH_DATA_journal]) {
struct journal_device *ja = &ca->journal;
if (!test_bit(ca->dev_idx, c->rw_devs[BCH_DATA_journal].d))
continue;
if (!ja->nr)
continue;

View File

@ -196,6 +196,7 @@ nomatch:
goto next;
}
out:
bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&_insert, c);
bch2_bkey_buf_exit(&_new, c);
@ -642,6 +643,8 @@ next_nondata:
bch2_trans_cond_resched(&trans);
}
out:
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
bch2_bkey_buf_exit(&sk, c);
@ -728,7 +731,7 @@ static int bch2_move_btree(struct bch_fs *c,
for_each_btree_node(&trans, iter, id,
id == start_btree_id ? start_pos : POS_MIN,
BTREE_ITER_PREFETCH, b) {
if (kthread && (ret = kthread_should_stop()))
if (kthread && kthread_should_stop())
goto out;
if ((cmp_int(id, end_btree_id) ?:
@ -837,13 +840,15 @@ static enum data_cmd rewrite_old_nodes_pred(struct bch_fs *c, void *arg,
struct bch_io_opts *io_opts,
struct data_opts *data_opts)
{
if (!btree_node_need_rewrite(b))
return DATA_SKIP;
if (b->version_ondisk != c->sb.version ||
btree_node_need_rewrite(b)) {
data_opts->target = 0;
data_opts->nr_replicas = 1;
data_opts->btree_insert_flags = 0;
return DATA_REWRITE;
}
data_opts->target = 0;
data_opts->nr_replicas = 1;
data_opts->btree_insert_flags = 0;
return DATA_REWRITE;
return DATA_SKIP;
}
int bch2_data_job(struct bch_fs *c,
@ -895,11 +900,17 @@ int bch2_data_job(struct bch_fs *c,
ret = bch2_replicas_gc2(c) ?: ret;
break;
case BCH_DATA_OP_REWRITE_OLD_NODES:
ret = bch2_move_btree(c,
op.start_btree, op.start_pos,
op.end_btree, op.end_pos,
rewrite_old_nodes_pred, &op, stats) ?: ret;
if (!ret) {
mutex_lock(&c->sb_lock);
c->disk_sb.sb->version_min = c->disk_sb.sb->version;
bch2_write_super(c);
mutex_unlock(&c->sb_lock);
}
break;
default:
ret = -EINVAL;

View File

@ -990,11 +990,17 @@ int bch2_fs_recovery(struct bch_fs *c)
goto err;
}
if (!c->sb.clean &&
!(c->sb.features & (1ULL << BCH_FEATURE_extents_above_btree_updates))) {
bch_err(c, "filesystem needs recovery from older version; run fsck from older bcachefs-tools to fix");
ret = -EINVAL;
goto err;
}
if (!(c->sb.features & (1ULL << BCH_FEATURE_alloc_v2))) {
bch_info(c, "alloc_v2 feature bit not set, fsck required");
c->opts.fsck = true;
c->opts.fix_errors = FSCK_OPT_YES;
c->disk_sb.sb->features[0] |= 1ULL << BCH_FEATURE_alloc_v2;
}
if (!c->replicas.entries ||
@ -1060,13 +1066,6 @@ use_clean:
blacklist_seq = journal_seq = le64_to_cpu(clean->journal_seq) + 1;
}
if (!c->sb.clean &&
!(c->sb.features & (1ULL << BCH_FEATURE_extents_above_btree_updates))) {
bch_err(c, "filesystem needs recovery from older version; run fsck from older bcachefs-tools to fix");
ret = -EINVAL;
goto err;
}
if (c->opts.reconstruct_alloc) {
c->sb.compat &= ~(1ULL << BCH_COMPAT_FEAT_ALLOC_INFO);
drop_alloc_keys(&c->journal_keys);
@ -1209,15 +1208,6 @@ use_clean:
}
mutex_lock(&c->sb_lock);
if (c->opts.version_upgrade) {
if (c->sb.version < bcachefs_metadata_version_new_versioning)
c->disk_sb.sb->version_min =
le16_to_cpu(bcachefs_metadata_version_min);
c->disk_sb.sb->version = le16_to_cpu(bcachefs_metadata_version_current);
c->disk_sb.sb->features[0] |= BCH_SB_FEATURES_ALL;
write_sb = true;
}
if (!test_bit(BCH_FS_ERROR, &c->flags)) {
c->disk_sb.sb->compat[0] |= 1ULL << BCH_COMPAT_FEAT_ALLOC_INFO;
write_sb = true;
@ -1274,15 +1264,6 @@ int bch2_fs_initialize(struct bch_fs *c)
bch2_mark_dev_superblock(c, ca, 0);
mutex_unlock(&c->sb_lock);
mutex_lock(&c->sb_lock);
c->disk_sb.sb->version = c->disk_sb.sb->version_min =
le16_to_cpu(bcachefs_metadata_version_current);
c->disk_sb.sb->features[0] |= 1ULL << BCH_FEATURE_atomic_nlink;
c->disk_sb.sb->features[0] |= BCH_SB_FEATURES_ALL;
bch2_write_super(c);
mutex_unlock(&c->sb_lock);
set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);

View File

@ -223,20 +223,18 @@ s64 bch2_remap_range(struct bch_fs *c,
dst_iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, dst_start,
BTREE_ITER_INTENT);
while (1) {
while (ret == 0 || ret == -EINTR) {
bch2_trans_begin(&trans);
trans.mem_top = 0;
if (fatal_signal_pending(current)) {
ret = -EINTR;
goto err;
break;
}
src_k = get_next_src(src_iter, src_end);
ret = bkey_err(src_k);
if (ret)
goto btree_err;
continue;
src_done = bpos_min(src_iter->pos, src_end).offset -
src_start.offset;
@ -245,8 +243,6 @@ s64 bch2_remap_range(struct bch_fs *c,
if (bkey_cmp(dst_iter->pos, dst_want) < 0) {
ret = bch2_fpunch_at(&trans, dst_iter, dst_want,
journal_seq, i_sectors_delta);
if (ret)
goto btree_err;
continue;
}
@ -265,7 +261,7 @@ s64 bch2_remap_range(struct bch_fs *c,
ret = bch2_make_extent_indirect(&trans, src_iter,
new_src.k);
if (ret)
goto btree_err;
continue;
BUG_ON(src_k.k->type != KEY_TYPE_reflink_p);
}
@ -294,20 +290,16 @@ s64 bch2_remap_range(struct bch_fs *c,
NULL, journal_seq,
new_i_size, i_sectors_delta);
if (ret)
goto btree_err;
continue;
dst_done = dst_iter->pos.offset - dst_start.offset;
src_want = POS(src_start.inode, src_start.offset + dst_done);
bch2_btree_iter_set_pos(src_iter, src_want);
btree_err:
if (ret == -EINTR)
ret = 0;
if (ret)
goto err;
}
bch2_trans_iter_put(&trans, dst_iter);
bch2_trans_iter_put(&trans, src_iter);
BUG_ON(bkey_cmp(dst_iter->pos, dst_end));
err:
BUG_ON(!ret && bkey_cmp(dst_iter->pos, dst_end));
BUG_ON(bkey_cmp(dst_iter->pos, dst_end) > 0);
dst_done = dst_iter->pos.offset - dst_start.offset;
@ -329,6 +321,8 @@ err:
ret2 = bch2_inode_write(&trans, inode_iter, &inode_u) ?:
bch2_trans_commit(&trans, NULL, journal_seq, 0);
}
bch2_trans_iter_put(&trans, inode_iter);
} while (ret2 == -EINTR);
ret = bch2_trans_exit(&trans) ?: ret;

View File

@ -362,6 +362,7 @@ static void bch2_sb_update(struct bch_fs *c)
c->sb.uuid = src->uuid;
c->sb.user_uuid = src->user_uuid;
c->sb.version = le16_to_cpu(src->version);
c->sb.version_min = le16_to_cpu(src->version_min);
c->sb.nr_devices = src->nr_devices;
c->sb.clean = BCH_SB_CLEAN(src);
c->sb.encryption_type = BCH_SB_ENCRYPTION_TYPE(src);
@ -964,6 +965,11 @@ int bch2_fs_mark_dirty(struct bch_fs *c)
*/
mutex_lock(&c->sb_lock);
if (c->opts.version_upgrade) {
c->disk_sb.sb->version = le16_to_cpu(bcachefs_metadata_version_current);
c->disk_sb.sb->features[0] |= BCH_SB_FEATURES_ALL;
}
SET_BCH_SB_CLEAN(c->disk_sb.sb, false);
c->disk_sb.sb->features[0] |= BCH_SB_FEATURES_ALWAYS;
ret = bch2_write_super(c);

View File

@ -396,6 +396,8 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early)
(!early || c->opts.read_only)))
return -EROFS;
bch_info(c, "going read-write");
ret = bch2_fs_mark_dirty(c);
if (ret)
goto err;

View File

@ -133,12 +133,9 @@ int bch2_xattr_get(struct bch_fs *c, struct bch_inode_info *inode,
inode->v.i_ino,
&X_SEARCH(type, name, strlen(name)),
0);
if (IS_ERR(iter)) {
bch2_trans_exit(&trans);
BUG_ON(PTR_ERR(iter) == -EINTR);
return PTR_ERR(iter) == -ENOENT ? -ENODATA : PTR_ERR(iter);
}
ret = PTR_ERR_OR_ZERO(iter);
if (ret)
goto err;
xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
ret = le16_to_cpu(xattr.v->x_val_len);
@ -148,9 +145,12 @@ int bch2_xattr_get(struct bch_fs *c, struct bch_inode_info *inode,
else
memcpy(buffer, xattr_val(xattr.v), ret);
}
bch2_trans_iter_put(&trans, iter);
err:
bch2_trans_exit(&trans);
return ret;
BUG_ON(ret == -EINTR);
return ret == -ENOENT ? -ENODATA : ret;
}
int bch2_xattr_set(struct btree_trans *trans, u64 inum,
@ -294,6 +294,8 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
if (ret)
break;
}
bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)