mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Update bcachefs sources to 718df3f7c2 bcachefs: Fix restart handling in for_each_btree_key()
This commit is contained in:
parent
41d10332bd
commit
a2b0239593
@ -1 +1 @@
|
|||||||
4dd9a5a488857137ce6eecadddd9304440fb03e9
|
718df3f7c266f8385fa8bef9ce4c5e9266aa8970
|
||||||
|
@ -1037,8 +1037,6 @@ LE64_BITMASK(BCH_MEMBER_DATA_ALLOWED, struct bch_member, flags[0], 15, 20)
|
|||||||
LE64_BITMASK(BCH_MEMBER_GROUP, struct bch_member, flags[0], 20, 28)
|
LE64_BITMASK(BCH_MEMBER_GROUP, struct bch_member, flags[0], 20, 28)
|
||||||
LE64_BITMASK(BCH_MEMBER_DURABILITY, struct bch_member, flags[0], 28, 30)
|
LE64_BITMASK(BCH_MEMBER_DURABILITY, struct bch_member, flags[0], 28, 30)
|
||||||
|
|
||||||
#define BCH_TIER_MAX 4U
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
LE64_BITMASK(BCH_MEMBER_NR_READ_ERRORS, struct bch_member, flags[1], 0, 20);
|
LE64_BITMASK(BCH_MEMBER_NR_READ_ERRORS, struct bch_member, flags[1], 0, 20);
|
||||||
LE64_BITMASK(BCH_MEMBER_NR_WRITE_ERRORS,struct bch_member, flags[1], 20, 40);
|
LE64_BITMASK(BCH_MEMBER_NR_WRITE_ERRORS,struct bch_member, flags[1], 20, 40);
|
||||||
|
@ -1508,19 +1508,11 @@ static int __btree_path_traverse_all(struct btree_trans *, int, unsigned long);
|
|||||||
int __must_check bch2_btree_path_traverse(struct btree_trans *trans,
|
int __must_check bch2_btree_path_traverse(struct btree_trans *trans,
|
||||||
struct btree_path *path, unsigned flags)
|
struct btree_path *path, unsigned flags)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (path->uptodate < BTREE_ITER_NEED_RELOCK)
|
if (path->uptodate < BTREE_ITER_NEED_RELOCK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = bch2_trans_cond_resched(trans) ?:
|
return bch2_trans_cond_resched(trans) ?:
|
||||||
btree_path_traverse_one(trans, path, flags, _RET_IP_);
|
btree_path_traverse_one(trans, path, flags, _RET_IP_);
|
||||||
if (unlikely(ret) && hweight64(trans->paths_allocated) == 1) {
|
|
||||||
ret = __btree_path_traverse_all(trans, ret, _RET_IP_);
|
|
||||||
BUG_ON(ret == -EINTR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void btree_path_copy(struct btree_trans *trans, struct btree_path *dst,
|
static void btree_path_copy(struct btree_trans *trans, struct btree_path *dst,
|
||||||
@ -1928,10 +1920,6 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter)
|
|||||||
if (!btree_path_node(path, path->level))
|
if (!btree_path_node(path, path->level))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = bch2_trans_cond_resched(trans);
|
|
||||||
if (ret)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
btree_node_unlock(path, path->level);
|
btree_node_unlock(path, path->level);
|
||||||
path->l[path->level].b = BTREE_ITER_NO_NODE_UP;
|
path->l[path->level].b = BTREE_ITER_NO_NODE_UP;
|
||||||
path->level++;
|
path->level++;
|
||||||
|
@ -258,57 +258,6 @@ static inline int bch2_trans_cond_resched(struct btree_trans *trans)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __for_each_btree_node(_trans, _iter, _btree_id, _start, \
|
|
||||||
_locks_want, _depth, _flags, _b, _ret) \
|
|
||||||
for (bch2_trans_node_iter_init((_trans), &(_iter), (_btree_id), \
|
|
||||||
_start, _locks_want, _depth, _flags), \
|
|
||||||
_b = bch2_btree_iter_peek_node(&(_iter)); \
|
|
||||||
!((_ret) = PTR_ERR_OR_ZERO(_b)) && (_b); \
|
|
||||||
(_b) = bch2_btree_iter_next_node(&(_iter)))
|
|
||||||
|
|
||||||
#define for_each_btree_node(_trans, _iter, _btree_id, _start, \
|
|
||||||
_flags, _b, _ret) \
|
|
||||||
__for_each_btree_node(_trans, _iter, _btree_id, _start, \
|
|
||||||
0, 0, _flags, _b, _ret)
|
|
||||||
|
|
||||||
static inline struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter,
|
|
||||||
unsigned flags)
|
|
||||||
{
|
|
||||||
return flags & BTREE_ITER_SLOTS
|
|
||||||
? bch2_btree_iter_peek_slot(iter)
|
|
||||||
: bch2_btree_iter_peek(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct bkey_s_c __bch2_btree_iter_next(struct btree_iter *iter,
|
|
||||||
unsigned flags)
|
|
||||||
{
|
|
||||||
return flags & BTREE_ITER_SLOTS
|
|
||||||
? bch2_btree_iter_next_slot(iter)
|
|
||||||
: bch2_btree_iter_next(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int bkey_err(struct bkey_s_c k)
|
|
||||||
{
|
|
||||||
return PTR_ERR_OR_ZERO(k.k);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define for_each_btree_key(_trans, _iter, _btree_id, \
|
|
||||||
_start, _flags, _k, _ret) \
|
|
||||||
for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \
|
|
||||||
(_start), (_flags)), \
|
|
||||||
(_k) = __bch2_btree_iter_peek(&(_iter), _flags); \
|
|
||||||
!((_ret) = bkey_err(_k)) && (_k).k; \
|
|
||||||
(_k) = __bch2_btree_iter_next(&(_iter), _flags))
|
|
||||||
|
|
||||||
#define for_each_btree_key_continue(_iter, _flags, _k, _ret) \
|
|
||||||
for ((_k) = __bch2_btree_iter_peek(&(_iter), _flags); \
|
|
||||||
!((_ret) = bkey_err(_k)) && (_k).k; \
|
|
||||||
(_k) = __bch2_btree_iter_next(&(_iter), _flags))
|
|
||||||
|
|
||||||
/* new multiple iterator interface: */
|
|
||||||
|
|
||||||
void bch2_dump_trans_paths_updates(struct btree_trans *);
|
|
||||||
|
|
||||||
void bch2_trans_iter_exit(struct btree_trans *, struct btree_iter *);
|
void bch2_trans_iter_exit(struct btree_trans *, struct btree_iter *);
|
||||||
void bch2_trans_iter_init(struct btree_trans *, struct btree_iter *,
|
void bch2_trans_iter_init(struct btree_trans *, struct btree_iter *,
|
||||||
unsigned, struct bpos, unsigned);
|
unsigned, struct bpos, unsigned);
|
||||||
@ -324,6 +273,89 @@ static inline void set_btree_iter_dontneed(struct btree_iter *iter)
|
|||||||
|
|
||||||
void *bch2_trans_kmalloc(struct btree_trans *, size_t);
|
void *bch2_trans_kmalloc(struct btree_trans *, size_t);
|
||||||
void bch2_trans_begin(struct btree_trans *);
|
void bch2_trans_begin(struct btree_trans *);
|
||||||
|
|
||||||
|
static inline struct btree *
|
||||||
|
__btree_iter_peek_node_and_restart(struct btree_trans *trans, struct btree_iter *iter)
|
||||||
|
{
|
||||||
|
struct btree *b;
|
||||||
|
|
||||||
|
while (b = bch2_btree_iter_peek_node(iter),
|
||||||
|
PTR_ERR_OR_ZERO(b) == -EINTR)
|
||||||
|
bch2_trans_begin(trans);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __for_each_btree_node(_trans, _iter, _btree_id, _start, \
|
||||||
|
_locks_want, _depth, _flags, _b, _ret) \
|
||||||
|
for (bch2_trans_node_iter_init((_trans), &(_iter), (_btree_id), \
|
||||||
|
_start, _locks_want, _depth, _flags); \
|
||||||
|
(_b) = __btree_iter_peek_node_and_restart((_trans), &(_iter)),\
|
||||||
|
!((_ret) = PTR_ERR_OR_ZERO(_b)) && (_b); \
|
||||||
|
(_b) = bch2_btree_iter_next_node(&(_iter)))
|
||||||
|
|
||||||
|
#define for_each_btree_node(_trans, _iter, _btree_id, _start, \
|
||||||
|
_flags, _b, _ret) \
|
||||||
|
__for_each_btree_node(_trans, _iter, _btree_id, _start, \
|
||||||
|
0, 0, _flags, _b, _ret)
|
||||||
|
|
||||||
|
static inline int bkey_err(struct bkey_s_c k)
|
||||||
|
{
|
||||||
|
return PTR_ERR_OR_ZERO(k.k);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter,
|
||||||
|
unsigned flags)
|
||||||
|
{
|
||||||
|
return flags & BTREE_ITER_SLOTS
|
||||||
|
? bch2_btree_iter_peek_slot(iter)
|
||||||
|
: bch2_btree_iter_peek(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct bkey_s_c
|
||||||
|
__bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
|
||||||
|
struct btree_iter *iter, unsigned flags)
|
||||||
|
{
|
||||||
|
struct bkey_s_c k;
|
||||||
|
|
||||||
|
while (k = __bch2_btree_iter_peek(iter, flags),
|
||||||
|
bkey_err(k) == -EINTR)
|
||||||
|
bch2_trans_begin(trans);
|
||||||
|
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define for_each_btree_key(_trans, _iter, _btree_id, \
|
||||||
|
_start, _flags, _k, _ret) \
|
||||||
|
for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \
|
||||||
|
(_start), (_flags)); \
|
||||||
|
(_k) = __bch2_btree_iter_peek_and_restart((_trans), &(_iter), _flags),\
|
||||||
|
!((_ret) = bkey_err(_k)) && (_k).k; \
|
||||||
|
bch2_btree_iter_advance(&(_iter)))
|
||||||
|
|
||||||
|
#define for_each_btree_key_norestart(_trans, _iter, _btree_id, \
|
||||||
|
_start, _flags, _k, _ret) \
|
||||||
|
for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \
|
||||||
|
(_start), (_flags)); \
|
||||||
|
(_k) = __bch2_btree_iter_peek(&(_iter), _flags), \
|
||||||
|
!((_ret) = bkey_err(_k)) && (_k).k; \
|
||||||
|
bch2_btree_iter_advance(&(_iter)))
|
||||||
|
|
||||||
|
#define for_each_btree_key_continue(_trans, _iter, _flags, _k, _ret) \
|
||||||
|
for (; \
|
||||||
|
(_k) = __bch2_btree_iter_peek_and_restart((_trans), &(_iter), _flags),\
|
||||||
|
!((_ret) = bkey_err(_k)) && (_k).k; \
|
||||||
|
bch2_btree_iter_advance(&(_iter)))
|
||||||
|
|
||||||
|
#define for_each_btree_key_continue_norestart(_iter, _flags, _k, _ret) \
|
||||||
|
for (; \
|
||||||
|
(_k) = __bch2_btree_iter_peek(&(_iter), _flags), \
|
||||||
|
!((_ret) = bkey_err(_k)) && (_k).k; \
|
||||||
|
bch2_btree_iter_advance(&(_iter)))
|
||||||
|
|
||||||
|
/* new multiple iterator interface: */
|
||||||
|
|
||||||
|
void bch2_dump_trans_paths_updates(struct btree_trans *);
|
||||||
void bch2_trans_init(struct btree_trans *, struct bch_fs *, unsigned, size_t);
|
void bch2_trans_init(struct btree_trans *, struct bch_fs *, unsigned, size_t);
|
||||||
void bch2_trans_exit(struct btree_trans *);
|
void bch2_trans_exit(struct btree_trans *);
|
||||||
|
|
||||||
|
@ -1210,7 +1210,7 @@ static int need_whiteout_for_snapshot(struct btree_trans *trans,
|
|||||||
|
|
||||||
pos.snapshot++;
|
pos.snapshot++;
|
||||||
|
|
||||||
for_each_btree_key(trans, iter, btree_id, pos,
|
for_each_btree_key_norestart(trans, iter, btree_id, pos,
|
||||||
BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
|
BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
|
||||||
if (bkey_cmp(k.k->p, pos))
|
if (bkey_cmp(k.k->p, pos))
|
||||||
break;
|
break;
|
||||||
|
@ -432,7 +432,7 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for_each_btree_key(trans, iter, BTREE_ID_dirents,
|
for_each_btree_key_norestart(trans, iter, BTREE_ID_dirents,
|
||||||
SPOS(dir.inum, 0, snapshot), 0, k, ret) {
|
SPOS(dir.inum, 0, snapshot), 0, k, ret) {
|
||||||
if (k.k->p.inode > dir.inum)
|
if (k.k->p.inode > dir.inum)
|
||||||
break;
|
break;
|
||||||
@ -464,7 +464,7 @@ retry:
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for_each_btree_key(&trans, iter, BTREE_ID_dirents,
|
for_each_btree_key_norestart(&trans, iter, BTREE_ID_dirents,
|
||||||
SPOS(inum.inum, ctx->pos, snapshot), 0, k, ret) {
|
SPOS(inum.inum, ctx->pos, snapshot), 0, k, ret) {
|
||||||
if (k.k->p.inode > inum.inum)
|
if (k.k->p.inode > inum.inum)
|
||||||
break;
|
break;
|
||||||
|
@ -61,7 +61,7 @@ static int count_iters_for_insert(struct btree_trans *trans,
|
|||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
struct bkey_s_c r_k;
|
struct bkey_s_c r_k;
|
||||||
|
|
||||||
for_each_btree_key(trans, iter,
|
for_each_btree_key_norestart(trans, iter,
|
||||||
BTREE_ID_reflink, POS(0, idx + offset),
|
BTREE_ID_reflink, POS(0, idx + offset),
|
||||||
BTREE_ITER_SLOTS, r_k, ret2) {
|
BTREE_ITER_SLOTS, r_k, ret2) {
|
||||||
if (bkey_cmp(bkey_start_pos(r_k.k),
|
if (bkey_cmp(bkey_start_pos(r_k.k),
|
||||||
@ -120,7 +120,7 @@ int bch2_extent_atomic_end(struct btree_trans *trans,
|
|||||||
|
|
||||||
bch2_trans_copy_iter(©, iter);
|
bch2_trans_copy_iter(©, iter);
|
||||||
|
|
||||||
for_each_btree_key_continue(copy, 0, k, ret) {
|
for_each_btree_key_continue_norestart(copy, 0, k, ret) {
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
|
|
||||||
if (bkey_cmp(bkey_start_pos(k.k), *end) >= 0)
|
if (bkey_cmp(bkey_start_pos(k.k), *end) >= 0)
|
||||||
|
@ -1838,7 +1838,7 @@ retry:
|
|||||||
if (err)
|
if (err)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for_each_btree_key(&trans, iter, BTREE_ID_extents,
|
for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents,
|
||||||
SPOS(inum.inum, offset, snapshot),
|
SPOS(inum.inum, offset, snapshot),
|
||||||
BTREE_ITER_SLOTS, k, err) {
|
BTREE_ITER_SLOTS, k, err) {
|
||||||
if (bkey_cmp(bkey_start_pos(k.k), POS(inum.inum, end)) >= 0)
|
if (bkey_cmp(bkey_start_pos(k.k), POS(inum.inum, end)) >= 0)
|
||||||
@ -2213,7 +2213,7 @@ retry:
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for_each_btree_key(&trans, iter, BTREE_ID_extents, start, 0, k, ret) {
|
for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents, start, 0, k, ret) {
|
||||||
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
|
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3118,7 +3118,7 @@ retry:
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for_each_btree_key(&trans, iter, BTREE_ID_extents,
|
for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents,
|
||||||
SPOS(inode->v.i_ino, offset >> 9, snapshot), 0, k, ret) {
|
SPOS(inode->v.i_ino, offset >> 9, snapshot), 0, k, ret) {
|
||||||
if (k.k->p.inode != inode->v.i_ino) {
|
if (k.k->p.inode != inode->v.i_ino) {
|
||||||
break;
|
break;
|
||||||
@ -3225,7 +3225,7 @@ retry:
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for_each_btree_key(&trans, iter, BTREE_ID_extents,
|
for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents,
|
||||||
SPOS(inode->v.i_ino, offset >> 9, snapshot),
|
SPOS(inode->v.i_ino, offset >> 9, snapshot),
|
||||||
BTREE_ITER_SLOTS, k, ret) {
|
BTREE_ITER_SLOTS, k, ret) {
|
||||||
if (k.k->p.inode != inode->v.i_ino) {
|
if (k.k->p.inode != inode->v.i_ino) {
|
||||||
|
@ -422,6 +422,7 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
|
|||||||
struct bch_ioctl_subvolume arg)
|
struct bch_ioctl_subvolume arg)
|
||||||
{
|
{
|
||||||
struct path path;
|
struct path path;
|
||||||
|
struct inode *dir;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (arg.flags)
|
if (arg.flags)
|
||||||
@ -438,7 +439,13 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
|
|||||||
return -EXDEV;
|
return -EXDEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = __bch2_unlink(path.dentry->d_parent->d_inode, path.dentry, 1);
|
dir = path.dentry->d_parent->d_inode;
|
||||||
|
|
||||||
|
ret = __bch2_unlink(dir, path.dentry, 1);
|
||||||
|
if (!ret) {
|
||||||
|
fsnotify_rmdir(dir, path.dentry);
|
||||||
|
d_delete(path.dentry);
|
||||||
|
}
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1357,10 +1357,10 @@ static int check_dirent_target(struct btree_trans *trans,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fsck_err_on(!backpointer_exists, c,
|
if (fsck_err_on(!backpointer_exists, c,
|
||||||
"inode %llu has wrong backpointer:\n"
|
"inode %llu:%u has wrong backpointer:\n"
|
||||||
"got %llu:%llu\n"
|
"got %llu:%llu\n"
|
||||||
"should be %llu:%llu",
|
"should be %llu:%llu",
|
||||||
target->bi_inum,
|
target->bi_inum, target_snapshot,
|
||||||
target->bi_dir,
|
target->bi_dir,
|
||||||
target->bi_dir_offset,
|
target->bi_dir_offset,
|
||||||
d.k->p.inode,
|
d.k->p.inode,
|
||||||
@ -1730,10 +1730,23 @@ struct pathbuf {
|
|||||||
|
|
||||||
struct pathbuf_entry {
|
struct pathbuf_entry {
|
||||||
u64 inum;
|
u64 inum;
|
||||||
|
u32 snapshot;
|
||||||
} *entries;
|
} *entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int path_down(struct pathbuf *p, u64 inum)
|
static bool path_is_dup(struct pathbuf *p, u64 inum, u32 snapshot)
|
||||||
|
{
|
||||||
|
struct pathbuf_entry *i;
|
||||||
|
|
||||||
|
for (i = p->entries; i < p->entries + p->nr; i++)
|
||||||
|
if (i->inum == inum &&
|
||||||
|
i->snapshot == snapshot)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int path_down(struct pathbuf *p, u64 inum, u32 snapshot)
|
||||||
{
|
{
|
||||||
if (p->nr == p->size) {
|
if (p->nr == p->size) {
|
||||||
size_t new_size = max_t(size_t, 256UL, p->size * 2);
|
size_t new_size = max_t(size_t, 256UL, p->size * 2);
|
||||||
@ -1749,18 +1762,23 @@ static int path_down(struct pathbuf *p, u64 inum)
|
|||||||
};
|
};
|
||||||
|
|
||||||
p->entries[p->nr++] = (struct pathbuf_entry) {
|
p->entries[p->nr++] = (struct pathbuf_entry) {
|
||||||
.inum = inum,
|
.inum = inum,
|
||||||
|
.snapshot = snapshot,
|
||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that a given inode is reachable from the root:
|
||||||
|
*
|
||||||
|
* XXX: we should also be verifying that inodes are in the right subvolumes
|
||||||
|
*/
|
||||||
static int check_path(struct btree_trans *trans,
|
static int check_path(struct btree_trans *trans,
|
||||||
struct pathbuf *p,
|
struct pathbuf *p,
|
||||||
struct bch_inode_unpacked *inode,
|
struct bch_inode_unpacked *inode,
|
||||||
u32 snapshot)
|
u32 snapshot)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
size_t i;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
snapshot = snapshot_t(c, snapshot)->equiv;
|
snapshot = snapshot_t(c, snapshot)->equiv;
|
||||||
@ -1768,17 +1786,19 @@ static int check_path(struct btree_trans *trans,
|
|||||||
|
|
||||||
while (!(inode->bi_inum == BCACHEFS_ROOT_INO &&
|
while (!(inode->bi_inum == BCACHEFS_ROOT_INO &&
|
||||||
inode->bi_subvol == BCACHEFS_ROOT_SUBVOL)) {
|
inode->bi_subvol == BCACHEFS_ROOT_SUBVOL)) {
|
||||||
|
u32 parent_snapshot = snapshot;
|
||||||
|
|
||||||
if (inode->bi_parent_subvol) {
|
if (inode->bi_parent_subvol) {
|
||||||
u64 inum;
|
u64 inum;
|
||||||
|
|
||||||
ret = subvol_lookup(trans, inode->bi_parent_subvol,
|
ret = subvol_lookup(trans, inode->bi_parent_subvol,
|
||||||
&snapshot, &inum);
|
&parent_snapshot, &inum);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = lockrestart_do(trans,
|
ret = lockrestart_do(trans,
|
||||||
inode_backpointer_exists(trans, inode, snapshot));
|
inode_backpointer_exists(trans, inode, parent_snapshot));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1797,17 +1817,31 @@ static int check_path(struct btree_trans *trans,
|
|||||||
if (!S_ISDIR(inode->bi_mode))
|
if (!S_ISDIR(inode->bi_mode))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = path_down(p, inode->bi_inum);
|
ret = path_down(p, inode->bi_inum, snapshot);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
bch_err(c, "memory allocation failure");
|
bch_err(c, "memory allocation failure");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < p->nr; i++) {
|
snapshot = parent_snapshot;
|
||||||
if (inode->bi_dir != p->entries[i].inum)
|
|
||||||
continue;
|
ret = lookup_inode(trans, inode->bi_dir, inode, &snapshot);
|
||||||
|
if (ret) {
|
||||||
|
/* Should have been caught in dirents pass */
|
||||||
|
bch_err(c, "error looking up parent directory: %i", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_is_dup(p, inode->bi_inum, snapshot)) {
|
||||||
|
struct pathbuf_entry *i;
|
||||||
|
|
||||||
/* XXX print path */
|
/* XXX print path */
|
||||||
|
bch_err(c, "directory structure loop");
|
||||||
|
|
||||||
|
for (i = p->entries; i < p->entries + p->nr; i++)
|
||||||
|
pr_err("%llu:%u", i->inum, i->snapshot);
|
||||||
|
pr_err("%llu:%u", inode->bi_inum, snapshot);
|
||||||
|
|
||||||
if (!fsck_err(c, "directory structure loop"))
|
if (!fsck_err(c, "directory structure loop"))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1819,14 +1853,6 @@ static int check_path(struct btree_trans *trans,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = reattach_inode(trans, inode, snapshot);
|
ret = reattach_inode(trans, inode, snapshot);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = lookup_inode(trans, inode->bi_dir, inode, &snapshot);
|
|
||||||
if (ret) {
|
|
||||||
/* Should have been caught in dirents pass */
|
|
||||||
bch_err(c, "error looking up parent directory: %i", ret);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fsck_err:
|
fsck_err:
|
||||||
|
@ -206,7 +206,7 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
|
|||||||
|
|
||||||
bch2_trans_copy_iter(&iter, extent_iter);
|
bch2_trans_copy_iter(&iter, extent_iter);
|
||||||
|
|
||||||
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, old, ret) {
|
for_each_btree_key_continue_norestart(iter, BTREE_ITER_SLOTS, old, ret) {
|
||||||
s64 sectors = min(new->k.p.offset, old.k->p.offset) -
|
s64 sectors = min(new->k.p.offset, old.k->p.offset) -
|
||||||
max(bkey_start_offset(&new->k),
|
max(bkey_start_offset(&new->k),
|
||||||
bkey_start_offset(old.k));
|
bkey_start_offset(old.k));
|
||||||
@ -966,7 +966,6 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
|
|||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto err;
|
goto err;
|
||||||
case PREP_ENCODED_CHECKSUM_ERR:
|
case PREP_ENCODED_CHECKSUM_ERR:
|
||||||
BUG();
|
|
||||||
goto csum_err;
|
goto csum_err;
|
||||||
case PREP_ENCODED_DO_WRITE:
|
case PREP_ENCODED_DO_WRITE:
|
||||||
/* XXX look for bug here */
|
/* XXX look for bug here */
|
||||||
|
@ -131,7 +131,7 @@ static int bch2_make_extent_indirect(struct btree_trans *trans,
|
|||||||
if (orig->k.type == KEY_TYPE_inline_data)
|
if (orig->k.type == KEY_TYPE_inline_data)
|
||||||
bch2_check_set_feature(c, BCH_FEATURE_reflink_inline_data);
|
bch2_check_set_feature(c, BCH_FEATURE_reflink_inline_data);
|
||||||
|
|
||||||
for_each_btree_key(trans, reflink_iter, BTREE_ID_reflink,
|
for_each_btree_key_norestart(trans, reflink_iter, BTREE_ID_reflink,
|
||||||
POS(0, c->reflink_hint),
|
POS(0, c->reflink_hint),
|
||||||
BTREE_ITER_INTENT|BTREE_ITER_SLOTS, k, ret) {
|
BTREE_ITER_INTENT|BTREE_ITER_SLOTS, k, ret) {
|
||||||
if (reflink_iter.pos.inode) {
|
if (reflink_iter.pos.inode) {
|
||||||
@ -194,7 +194,7 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end)
|
|||||||
struct bkey_s_c k;
|
struct bkey_s_c k;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
for_each_btree_key_continue(*iter, 0, k, ret) {
|
for_each_btree_key_continue_norestart(*iter, 0, k, ret) {
|
||||||
if (bkey_cmp(iter->pos, end) >= 0)
|
if (bkey_cmp(iter->pos, end) >= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1010,6 +1010,9 @@ bool bch2_have_enough_devs(struct bch_fs *c, struct bch_devs_mask devs,
|
|||||||
unsigned i, nr_online = 0, nr_failed = 0, dflags = 0;
|
unsigned i, nr_online = 0, nr_failed = 0, dflags = 0;
|
||||||
bool metadata = e->data_type < BCH_DATA_user;
|
bool metadata = e->data_type < BCH_DATA_user;
|
||||||
|
|
||||||
|
if (e->data_type == BCH_DATA_cached)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < e->nr_devs; i++) {
|
for (i = 0; i < e->nr_devs; i++) {
|
||||||
struct bch_dev *ca = bch_dev_bkey_exists(c, e->devs[i]);
|
struct bch_dev *ca = bch_dev_bkey_exists(c, e->devs[i]);
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ bch2_hash_lookup(struct btree_trans *trans,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for_each_btree_key(trans, *iter, desc.btree_id,
|
for_each_btree_key_norestart(trans, *iter, desc.btree_id,
|
||||||
SPOS(inum.inum, desc.hash_key(info, key), snapshot),
|
SPOS(inum.inum, desc.hash_key(info, key), snapshot),
|
||||||
BTREE_ITER_SLOTS|flags, k, ret) {
|
BTREE_ITER_SLOTS|flags, k, ret) {
|
||||||
if (iter->pos.inode != inum.inum)
|
if (iter->pos.inode != inum.inum)
|
||||||
@ -192,7 +192,7 @@ bch2_hash_hole(struct btree_trans *trans,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for_each_btree_key(trans, *iter, desc.btree_id,
|
for_each_btree_key_norestart(trans, *iter, desc.btree_id,
|
||||||
SPOS(inum.inum, desc.hash_key(info, key), snapshot),
|
SPOS(inum.inum, desc.hash_key(info, key), snapshot),
|
||||||
BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
|
BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
|
||||||
if (iter->pos.inode != inum.inum)
|
if (iter->pos.inode != inum.inum)
|
||||||
@ -220,7 +220,7 @@ int bch2_hash_needs_whiteout(struct btree_trans *trans,
|
|||||||
|
|
||||||
bch2_btree_iter_advance(&iter);
|
bch2_btree_iter_advance(&iter);
|
||||||
|
|
||||||
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k, ret) {
|
for_each_btree_key_continue_norestart(iter, BTREE_ITER_SLOTS, k, ret) {
|
||||||
if (k.k->type != desc.key_type &&
|
if (k.k->type != desc.key_type &&
|
||||||
k.k->type != KEY_TYPE_hash_whiteout)
|
k.k->type != KEY_TYPE_hash_whiteout)
|
||||||
break;
|
break;
|
||||||
@ -253,7 +253,7 @@ int bch2_hash_set(struct btree_trans *trans,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for_each_btree_key(trans, iter, desc.btree_id,
|
for_each_btree_key_norestart(trans, iter, desc.btree_id,
|
||||||
SPOS(inum.inum,
|
SPOS(inum.inum,
|
||||||
desc.hash_bkey(info, bkey_i_to_s_c(insert)),
|
desc.hash_bkey(info, bkey_i_to_s_c(insert)),
|
||||||
snapshot),
|
snapshot),
|
||||||
|
@ -295,7 +295,7 @@ retry:
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for_each_btree_key(&trans, iter, BTREE_ID_xattrs,
|
for_each_btree_key_norestart(&trans, iter, BTREE_ID_xattrs,
|
||||||
SPOS(inum, offset, snapshot), 0, k, ret) {
|
SPOS(inum, offset, snapshot), 0, k, ret) {
|
||||||
BUG_ON(k.k->p.inode < inum);
|
BUG_ON(k.k->p.inode < inum);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user