mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-22 00:00:03 +03:00
Update bcachefs sources to 938f680845d1 fixup! rename and export __kern_path_locked()
This commit is contained in:
parent
9776f9f362
commit
689b4dd4f0
@ -1 +1 @@
|
|||||||
3ca08ab51ec996180c20105489176b8c4327240c
|
938f680845d1be28979e23aee972dba010c464ba
|
||||||
|
@ -457,25 +457,18 @@ missing:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int check_extent_to_backpointers(struct btree_trans *trans,
|
static int check_extent_to_backpointers(struct btree_trans *trans,
|
||||||
struct btree_iter *iter,
|
enum btree_id btree, unsigned level,
|
||||||
struct bpos bucket_start,
|
struct bpos bucket_start,
|
||||||
struct bpos bucket_end,
|
struct bpos bucket_end,
|
||||||
struct bpos_level *last_flushed)
|
struct bpos_level *last_flushed,
|
||||||
|
struct bkey_s_c k)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct bkey_ptrs_c ptrs;
|
struct bkey_ptrs_c ptrs;
|
||||||
const union bch_extent_entry *entry;
|
const union bch_extent_entry *entry;
|
||||||
struct extent_ptr_decoded p;
|
struct extent_ptr_decoded p;
|
||||||
struct bkey_s_c k;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k = bch2_btree_iter_peek_all_levels(iter);
|
|
||||||
ret = bkey_err(k);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
if (!k.k)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ptrs = bch2_bkey_ptrs_c(k);
|
ptrs = bch2_bkey_ptrs_c(k);
|
||||||
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
||||||
struct bpos bucket_pos;
|
struct bpos bucket_pos;
|
||||||
@ -484,7 +477,7 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
|
|||||||
if (p.ptr.cached)
|
if (p.ptr.cached)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bch2_extent_ptr_to_bp(c, iter->btree_id, iter->path->level,
|
bch2_extent_ptr_to_bp(c, btree, level,
|
||||||
k, p, &bucket_pos, &bp);
|
k, p, &bucket_pos, &bp);
|
||||||
|
|
||||||
ret = check_bp_exists(trans, bucket_pos, bp, k,
|
ret = check_bp_exists(trans, bucket_pos, bp, k,
|
||||||
@ -501,44 +494,33 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
|
|||||||
enum btree_id btree_id,
|
enum btree_id btree_id,
|
||||||
struct bpos bucket_start,
|
struct bpos bucket_start,
|
||||||
struct bpos bucket_end,
|
struct bpos bucket_end,
|
||||||
struct bpos_level *last_flushed)
|
struct bpos_level *last_flushed,
|
||||||
|
int *level)
|
||||||
{
|
{
|
||||||
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;
|
||||||
struct bkey_ptrs_c ptrs;
|
|
||||||
struct extent_ptr_decoded p;
|
|
||||||
const union bch_extent_entry *entry;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
retry:
|
||||||
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0, r->level, 0);
|
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN,
|
||||||
|
0, bch2_btree_id_root(c, btree_id)->b->c.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)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
BUG_ON(b != btree_node_root(c, b));
|
if (b != btree_node_root(c, b)) {
|
||||||
|
bch2_trans_iter_exit(trans, &iter);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
*level = b->c.level;
|
||||||
|
|
||||||
k = bkey_i_to_s_c(&b->key);
|
k = bkey_i_to_s_c(&b->key);
|
||||||
ptrs = bch2_bkey_ptrs_c(k);
|
ret = check_extent_to_backpointers(trans, btree_id, b->c.level + 1,
|
||||||
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
|
||||||
struct bpos bucket_pos;
|
|
||||||
struct bch_backpointer bp;
|
|
||||||
|
|
||||||
if (p.ptr.cached)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bch2_extent_ptr_to_bp(c, iter.btree_id, b->c.level + 1,
|
|
||||||
k, p, &bucket_pos, &bp);
|
|
||||||
|
|
||||||
ret = check_bp_exists(trans, bucket_pos, bp, k,
|
|
||||||
bucket_start, bucket_end,
|
bucket_start, bucket_end,
|
||||||
last_flushed);
|
last_flushed, k);
|
||||||
if (ret)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
err:
|
err:
|
||||||
bch2_trans_iter_exit(trans, &iter);
|
bch2_trans_iter_exit(trans, &iter);
|
||||||
return ret;
|
return ret;
|
||||||
@ -616,43 +598,49 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
|
|||||||
struct bch_fs *c = trans->c;
|
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 bkey_s_c k;
|
||||||
struct bpos_level last_flushed = { UINT_MAX, POS_MIN };
|
struct bpos_level last_flushed = { UINT_MAX, POS_MIN };
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
for (btree_id = 0; btree_id < btree_id_nr_alive(c); 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;
|
int level, depth = btree_type_has_ptrs(btree_id) ? 0 : 1;
|
||||||
|
|
||||||
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
|
|
||||||
depth,
|
|
||||||
BTREE_ITER_ALL_LEVELS|
|
|
||||||
BTREE_ITER_PREFETCH);
|
|
||||||
|
|
||||||
do {
|
|
||||||
ret = commit_do(trans, NULL, NULL,
|
|
||||||
BCH_TRANS_COMMIT_lazy_rw|
|
|
||||||
BCH_TRANS_COMMIT_no_enospc,
|
|
||||||
check_extent_to_backpointers(trans, &iter,
|
|
||||||
bucket_start, bucket_end,
|
|
||||||
&last_flushed));
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
} while (!bch2_btree_iter_advance(&iter));
|
|
||||||
|
|
||||||
bch2_trans_iter_exit(trans, &iter);
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ret = commit_do(trans, NULL, NULL,
|
ret = commit_do(trans, NULL, NULL,
|
||||||
BCH_TRANS_COMMIT_lazy_rw|
|
BCH_TRANS_COMMIT_lazy_rw|
|
||||||
BCH_TRANS_COMMIT_no_enospc,
|
BCH_TRANS_COMMIT_no_enospc,
|
||||||
check_btree_root_to_backpointers(trans, btree_id,
|
check_btree_root_to_backpointers(trans, btree_id,
|
||||||
bucket_start, bucket_end,
|
bucket_start, bucket_end,
|
||||||
&last_flushed));
|
&last_flushed, &level));
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
return ret;
|
||||||
|
|
||||||
|
while (level >= depth) {
|
||||||
|
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
|
||||||
|
level,
|
||||||
|
BTREE_ITER_PREFETCH);
|
||||||
|
for_each_btree_key_continue(trans, iter, BTREE_ITER_PREFETCH, k, ret) {
|
||||||
|
ret = commit_do(trans, NULL, NULL,
|
||||||
|
BCH_TRANS_COMMIT_lazy_rw|
|
||||||
|
BCH_TRANS_COMMIT_no_enospc,
|
||||||
|
check_extent_to_backpointers(trans, btree_id, level,
|
||||||
|
bucket_start, bucket_end,
|
||||||
|
&last_flushed, k));
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (bpos_eq(iter.pos, SPOS_MAX))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bch2_trans_iter_exit(trans, &iter);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
--level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bpos bucket_pos_to_bp_safe(const struct bch_fs *c,
|
static struct bpos bucket_pos_to_bp_safe(const struct bch_fs *c,
|
||||||
|
@ -1797,23 +1797,15 @@ err:
|
|||||||
|
|
||||||
inline bool bch2_btree_iter_advance(struct btree_iter *iter)
|
inline bool bch2_btree_iter_advance(struct btree_iter *iter)
|
||||||
{
|
{
|
||||||
if (likely(!(iter->flags & BTREE_ITER_ALL_LEVELS))) {
|
struct bpos pos = iter->k.p;
|
||||||
struct bpos pos = iter->k.p;
|
bool ret = !(iter->flags & BTREE_ITER_ALL_SNAPSHOTS
|
||||||
bool ret = !(iter->flags & BTREE_ITER_ALL_SNAPSHOTS
|
? bpos_eq(pos, SPOS_MAX)
|
||||||
? bpos_eq(pos, SPOS_MAX)
|
: bkey_eq(pos, SPOS_MAX));
|
||||||
: bkey_eq(pos, SPOS_MAX));
|
|
||||||
|
|
||||||
if (ret && !(iter->flags & BTREE_ITER_IS_EXTENTS))
|
if (ret && !(iter->flags & BTREE_ITER_IS_EXTENTS))
|
||||||
pos = bkey_successor(iter, pos);
|
pos = bkey_successor(iter, pos);
|
||||||
bch2_btree_iter_set_pos(iter, pos);
|
bch2_btree_iter_set_pos(iter, pos);
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
|
||||||
if (!btree_path_node(iter->path, iter->path->level))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
iter->advanced = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool bch2_btree_iter_rewind(struct btree_iter *iter)
|
inline bool bch2_btree_iter_rewind(struct btree_iter *iter)
|
||||||
@ -2064,7 +2056,6 @@ struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *iter, struct bpos e
|
|||||||
struct bpos iter_pos;
|
struct bpos iter_pos;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
EBUG_ON(iter->flags & BTREE_ITER_ALL_LEVELS);
|
|
||||||
EBUG_ON((iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) && bkey_eq(end, POS_MAX));
|
EBUG_ON((iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) && bkey_eq(end, POS_MAX));
|
||||||
|
|
||||||
if (iter->update_path) {
|
if (iter->update_path) {
|
||||||
@ -2190,103 +2181,6 @@ end:
|
|||||||
goto out_no_locked;
|
goto out_no_locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* bch2_btree_iter_peek_all_levels() - returns the first key greater than or
|
|
||||||
* equal to iterator's current position, returning keys from every level of the
|
|
||||||
* btree. For keys at different levels of the btree that compare equal, the key
|
|
||||||
* from the lower level (leaf) is returned first.
|
|
||||||
* @iter: iterator to peek from
|
|
||||||
*
|
|
||||||
* Returns: key if found, or an error extractable with bkey_err().
|
|
||||||
*/
|
|
||||||
struct bkey_s_c bch2_btree_iter_peek_all_levels(struct btree_iter *iter)
|
|
||||||
{
|
|
||||||
struct btree_trans *trans = iter->trans;
|
|
||||||
struct bkey_s_c k;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
EBUG_ON(iter->path->cached);
|
|
||||||
bch2_btree_iter_verify(iter);
|
|
||||||
BUG_ON(iter->path->level < iter->min_depth);
|
|
||||||
BUG_ON(!(iter->flags & BTREE_ITER_ALL_SNAPSHOTS));
|
|
||||||
EBUG_ON(!(iter->flags & BTREE_ITER_ALL_LEVELS));
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
iter->path = bch2_btree_path_set_pos(trans, iter->path, iter->pos,
|
|
||||||
iter->flags & BTREE_ITER_INTENT,
|
|
||||||
btree_iter_ip_allocated(iter));
|
|
||||||
|
|
||||||
ret = bch2_btree_path_traverse(trans, iter->path, iter->flags);
|
|
||||||
if (unlikely(ret)) {
|
|
||||||
/* ensure that iter->k is consistent with iter->pos: */
|
|
||||||
bch2_btree_iter_set_pos(iter, iter->pos);
|
|
||||||
k = bkey_s_c_err(ret);
|
|
||||||
goto out_no_locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Already at end? */
|
|
||||||
if (!btree_path_node(iter->path, iter->path->level)) {
|
|
||||||
k = bkey_s_c_null;
|
|
||||||
goto out_no_locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
k = btree_path_level_peek_all(trans->c,
|
|
||||||
&iter->path->l[iter->path->level], &iter->k);
|
|
||||||
|
|
||||||
/* Check if we should go up to the parent node: */
|
|
||||||
if (!k.k ||
|
|
||||||
(iter->advanced &&
|
|
||||||
bpos_eq(path_l(iter->path)->b->key.k.p, iter->pos))) {
|
|
||||||
iter->pos = path_l(iter->path)->b->key.k.p;
|
|
||||||
btree_path_set_level_up(trans, iter->path);
|
|
||||||
iter->advanced = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if we should go back down to a leaf:
|
|
||||||
* If we're not in a leaf node, we only return the current key
|
|
||||||
* if it exactly matches iter->pos - otherwise we first have to
|
|
||||||
* go back to the leaf:
|
|
||||||
*/
|
|
||||||
if (iter->path->level != iter->min_depth &&
|
|
||||||
(iter->advanced ||
|
|
||||||
!k.k ||
|
|
||||||
!bpos_eq(iter->pos, k.k->p))) {
|
|
||||||
btree_path_set_level_down(trans, iter->path, iter->min_depth);
|
|
||||||
iter->pos = bpos_successor(iter->pos);
|
|
||||||
iter->advanced = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we should go to the next key: */
|
|
||||||
if (iter->path->level == iter->min_depth &&
|
|
||||||
iter->advanced &&
|
|
||||||
k.k &&
|
|
||||||
bpos_eq(iter->pos, k.k->p)) {
|
|
||||||
iter->pos = bpos_successor(iter->pos);
|
|
||||||
iter->advanced = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iter->advanced &&
|
|
||||||
iter->path->level == iter->min_depth &&
|
|
||||||
!bpos_eq(k.k->p, iter->pos))
|
|
||||||
iter->advanced = false;
|
|
||||||
|
|
||||||
BUG_ON(iter->advanced);
|
|
||||||
BUG_ON(!k.k);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iter->pos = k.k->p;
|
|
||||||
btree_path_set_should_be_locked(iter->path);
|
|
||||||
out_no_locked:
|
|
||||||
bch2_btree_iter_verify(iter);
|
|
||||||
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bch2_btree_iter_next() - returns first key greater than iterator's current
|
* bch2_btree_iter_next() - returns first key greater than iterator's current
|
||||||
* position
|
* position
|
||||||
@ -2453,7 +2347,6 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
|
|||||||
|
|
||||||
bch2_btree_iter_verify(iter);
|
bch2_btree_iter_verify(iter);
|
||||||
bch2_btree_iter_verify_entry_exit(iter);
|
bch2_btree_iter_verify_entry_exit(iter);
|
||||||
EBUG_ON(iter->flags & BTREE_ITER_ALL_LEVELS);
|
|
||||||
EBUG_ON(iter->path->level && (iter->flags & BTREE_ITER_WITH_KEY_CACHE));
|
EBUG_ON(iter->path->level && (iter->flags & BTREE_ITER_WITH_KEY_CACHE));
|
||||||
|
|
||||||
/* extents can't span inode numbers: */
|
/* extents can't span inode numbers: */
|
||||||
|
@ -348,8 +348,6 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *);
|
|||||||
struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *, struct bpos);
|
struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *, struct bpos);
|
||||||
struct bkey_s_c bch2_btree_iter_next(struct btree_iter *);
|
struct bkey_s_c bch2_btree_iter_next(struct btree_iter *);
|
||||||
|
|
||||||
struct bkey_s_c bch2_btree_iter_peek_all_levels(struct btree_iter *);
|
|
||||||
|
|
||||||
static inline struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
|
static inline struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
|
||||||
{
|
{
|
||||||
return bch2_btree_iter_peek_upto(iter, SPOS_MAX);
|
return bch2_btree_iter_peek_upto(iter, SPOS_MAX);
|
||||||
@ -408,9 +406,6 @@ static inline unsigned __bch2_btree_iter_flags(struct btree_trans *trans,
|
|||||||
unsigned btree_id,
|
unsigned btree_id,
|
||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
if (flags & BTREE_ITER_ALL_LEVELS)
|
|
||||||
flags |= BTREE_ITER_ALL_SNAPSHOTS|__BTREE_ITER_ALL_SNAPSHOTS;
|
|
||||||
|
|
||||||
if (!(flags & (BTREE_ITER_ALL_SNAPSHOTS|BTREE_ITER_NOT_EXTENTS)) &&
|
if (!(flags & (BTREE_ITER_ALL_SNAPSHOTS|BTREE_ITER_NOT_EXTENTS)) &&
|
||||||
btree_id_is_extents(btree_id))
|
btree_id_is_extents(btree_id))
|
||||||
flags |= BTREE_ITER_IS_EXTENTS;
|
flags |= BTREE_ITER_IS_EXTENTS;
|
||||||
@ -606,8 +601,6 @@ u32 bch2_trans_begin(struct btree_trans *);
|
|||||||
static inline struct bkey_s_c bch2_btree_iter_peek_prev_type(struct btree_iter *iter,
|
static inline struct bkey_s_c bch2_btree_iter_peek_prev_type(struct btree_iter *iter,
|
||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
BUG_ON(flags & BTREE_ITER_ALL_LEVELS);
|
|
||||||
|
|
||||||
return flags & BTREE_ITER_SLOTS ? bch2_btree_iter_peek_slot(iter) :
|
return flags & BTREE_ITER_SLOTS ? bch2_btree_iter_peek_slot(iter) :
|
||||||
bch2_btree_iter_peek_prev(iter);
|
bch2_btree_iter_peek_prev(iter);
|
||||||
}
|
}
|
||||||
@ -615,8 +608,7 @@ static inline struct bkey_s_c bch2_btree_iter_peek_prev_type(struct btree_iter *
|
|||||||
static inline struct bkey_s_c bch2_btree_iter_peek_type(struct btree_iter *iter,
|
static inline struct bkey_s_c bch2_btree_iter_peek_type(struct btree_iter *iter,
|
||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
return flags & BTREE_ITER_ALL_LEVELS ? bch2_btree_iter_peek_all_levels(iter) :
|
return flags & BTREE_ITER_SLOTS ? bch2_btree_iter_peek_slot(iter) :
|
||||||
flags & BTREE_ITER_SLOTS ? bch2_btree_iter_peek_slot(iter) :
|
|
||||||
bch2_btree_iter_peek(iter);
|
bch2_btree_iter_peek(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +664,7 @@ void __bch2_btree_path_downgrade(struct btree_trans *trans,
|
|||||||
struct btree_path *path,
|
struct btree_path *path,
|
||||||
unsigned new_locks_want)
|
unsigned new_locks_want)
|
||||||
{
|
{
|
||||||
unsigned l;
|
unsigned l, old_locks_want = path->locks_want;
|
||||||
|
|
||||||
if (trans->restarted)
|
if (trans->restarted)
|
||||||
return;
|
return;
|
||||||
@ -689,7 +689,7 @@ void __bch2_btree_path_downgrade(struct btree_trans *trans,
|
|||||||
bch2_btree_path_verify_locks(path);
|
bch2_btree_path_verify_locks(path);
|
||||||
|
|
||||||
path->downgrade_seq++;
|
path->downgrade_seq++;
|
||||||
trace_path_downgrade(trans, _RET_IP_, path);
|
trace_path_downgrade(trans, _RET_IP_, path, old_locks_want);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Btree transaction locking: */
|
/* Btree transaction locking: */
|
||||||
|
@ -195,33 +195,32 @@ struct btree_node_iter {
|
|||||||
* Iterate over all possible positions, synthesizing deleted keys for holes:
|
* Iterate over all possible positions, synthesizing deleted keys for holes:
|
||||||
*/
|
*/
|
||||||
static const __maybe_unused u16 BTREE_ITER_SLOTS = 1 << 0;
|
static const __maybe_unused u16 BTREE_ITER_SLOTS = 1 << 0;
|
||||||
static const __maybe_unused u16 BTREE_ITER_ALL_LEVELS = 1 << 1;
|
|
||||||
/*
|
/*
|
||||||
* Indicates that intent locks should be taken on leaf nodes, because we expect
|
* Indicates that intent locks should be taken on leaf nodes, because we expect
|
||||||
* to be doing updates:
|
* to be doing updates:
|
||||||
*/
|
*/
|
||||||
static const __maybe_unused u16 BTREE_ITER_INTENT = 1 << 2;
|
static const __maybe_unused u16 BTREE_ITER_INTENT = 1 << 1;
|
||||||
/*
|
/*
|
||||||
* Causes the btree iterator code to prefetch additional btree nodes from disk:
|
* Causes the btree iterator code to prefetch additional btree nodes from disk:
|
||||||
*/
|
*/
|
||||||
static const __maybe_unused u16 BTREE_ITER_PREFETCH = 1 << 3;
|
static const __maybe_unused u16 BTREE_ITER_PREFETCH = 1 << 2;
|
||||||
/*
|
/*
|
||||||
* Used in bch2_btree_iter_traverse(), to indicate whether we're searching for
|
* Used in bch2_btree_iter_traverse(), to indicate whether we're searching for
|
||||||
* @pos or the first key strictly greater than @pos
|
* @pos or the first key strictly greater than @pos
|
||||||
*/
|
*/
|
||||||
static const __maybe_unused u16 BTREE_ITER_IS_EXTENTS = 1 << 4;
|
static const __maybe_unused u16 BTREE_ITER_IS_EXTENTS = 1 << 3;
|
||||||
static const __maybe_unused u16 BTREE_ITER_NOT_EXTENTS = 1 << 5;
|
static const __maybe_unused u16 BTREE_ITER_NOT_EXTENTS = 1 << 4;
|
||||||
static const __maybe_unused u16 BTREE_ITER_CACHED = 1 << 6;
|
static const __maybe_unused u16 BTREE_ITER_CACHED = 1 << 5;
|
||||||
static const __maybe_unused u16 BTREE_ITER_WITH_KEY_CACHE = 1 << 7;
|
static const __maybe_unused u16 BTREE_ITER_WITH_KEY_CACHE = 1 << 6;
|
||||||
static const __maybe_unused u16 BTREE_ITER_WITH_UPDATES = 1 << 8;
|
static const __maybe_unused u16 BTREE_ITER_WITH_UPDATES = 1 << 7;
|
||||||
static const __maybe_unused u16 BTREE_ITER_WITH_JOURNAL = 1 << 9;
|
static const __maybe_unused u16 BTREE_ITER_WITH_JOURNAL = 1 << 8;
|
||||||
static const __maybe_unused u16 __BTREE_ITER_ALL_SNAPSHOTS = 1 << 10;
|
static const __maybe_unused u16 __BTREE_ITER_ALL_SNAPSHOTS = 1 << 9;
|
||||||
static const __maybe_unused u16 BTREE_ITER_ALL_SNAPSHOTS = 1 << 11;
|
static const __maybe_unused u16 BTREE_ITER_ALL_SNAPSHOTS = 1 << 10;
|
||||||
static const __maybe_unused u16 BTREE_ITER_FILTER_SNAPSHOTS = 1 << 12;
|
static const __maybe_unused u16 BTREE_ITER_FILTER_SNAPSHOTS = 1 << 11;
|
||||||
static const __maybe_unused u16 BTREE_ITER_NOPRESERVE = 1 << 13;
|
static const __maybe_unused u16 BTREE_ITER_NOPRESERVE = 1 << 12;
|
||||||
static const __maybe_unused u16 BTREE_ITER_CACHED_NOFILL = 1 << 14;
|
static const __maybe_unused u16 BTREE_ITER_CACHED_NOFILL = 1 << 13;
|
||||||
static const __maybe_unused u16 BTREE_ITER_KEY_CACHE_FILL = 1 << 15;
|
static const __maybe_unused u16 BTREE_ITER_KEY_CACHE_FILL = 1 << 14;
|
||||||
#define __BTREE_ITER_FLAGS_END 16
|
#define __BTREE_ITER_FLAGS_END 15
|
||||||
|
|
||||||
enum btree_path_uptodate {
|
enum btree_path_uptodate {
|
||||||
BTREE_ITER_UPTODATE = 0,
|
BTREE_ITER_UPTODATE = 0,
|
||||||
|
@ -1054,7 +1054,6 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
|
|||||||
unsigned nr_nodes[2] = { 0, 0 };
|
unsigned nr_nodes[2] = { 0, 0 };
|
||||||
unsigned update_level = level;
|
unsigned update_level = level;
|
||||||
enum bch_watermark watermark = flags & BCH_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;
|
||||||
|
|
||||||
@ -1068,10 +1067,6 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
|
|||||||
flags &= ~BCH_WATERMARK_MASK;
|
flags &= ~BCH_WATERMARK_MASK;
|
||||||
flags |= watermark;
|
flags |= watermark;
|
||||||
|
|
||||||
if (flags & BCH_TRANS_COMMIT_journal_reclaim)
|
|
||||||
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;
|
||||||
update_level++;
|
update_level++;
|
||||||
|
@ -453,33 +453,35 @@ static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
|
|||||||
static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
|
static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
|
||||||
struct bch_ioctl_subvolume arg)
|
struct bch_ioctl_subvolume arg)
|
||||||
{
|
{
|
||||||
|
struct filename *name;
|
||||||
struct path path;
|
struct path path;
|
||||||
struct inode *dir;
|
struct inode *dir;
|
||||||
|
struct dentry *victim;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (arg.flags)
|
if (arg.flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = user_path_at(arg.dirfd,
|
name = getname((const char __user *)(unsigned long)arg.dst_ptr);
|
||||||
(const char __user *)(unsigned long)arg.dst_ptr,
|
victim = filename_path_locked(arg.dirfd, name, &path);
|
||||||
LOOKUP_FOLLOW, &path);
|
putname(name);
|
||||||
if (ret)
|
if (IS_ERR(victim))
|
||||||
return ret;
|
return PTR_ERR(victim);
|
||||||
|
|
||||||
if (path.dentry->d_sb->s_fs_info != c) {
|
if (victim->d_sb->s_fs_info != c) {
|
||||||
ret = -EXDEV;
|
ret = -EXDEV;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = path.dentry->d_parent->d_inode;
|
dir = d_inode(path.dentry);
|
||||||
|
ret = __bch2_unlink(dir, victim, true);
|
||||||
ret = __bch2_unlink(dir, path.dentry, true);
|
if (!ret) {
|
||||||
if (ret)
|
fsnotify_rmdir(dir, victim);
|
||||||
goto err;
|
d_delete(victim);
|
||||||
|
}
|
||||||
fsnotify_rmdir(dir, path.dentry);
|
inode_unlock(dir);
|
||||||
d_delete(path.dentry);
|
|
||||||
err:
|
err:
|
||||||
|
dput(victim);
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1023,25 +1023,6 @@ static bool dirent_points_to_inode(struct bkey_s_c_dirent d,
|
|||||||
: le64_to_cpu(d.v->d_inum) == inode->bi_inum;
|
: le64_to_cpu(d.v->d_inum) == inode->bi_inum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int inode_backpointer_exists(struct btree_trans *trans,
|
|
||||||
struct bch_inode_unpacked *inode,
|
|
||||||
u32 snapshot)
|
|
||||||
{
|
|
||||||
struct btree_iter iter;
|
|
||||||
struct bkey_s_c_dirent d;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
d = dirent_get_by_pos(trans, &iter,
|
|
||||||
SPOS(inode->bi_dir, inode->bi_dir_offset, snapshot));
|
|
||||||
ret = bkey_err(d);
|
|
||||||
if (ret)
|
|
||||||
return bch2_err_matches(ret, ENOENT) ? 0 : ret;
|
|
||||||
|
|
||||||
ret = dirent_points_to_inode(d, inode);
|
|
||||||
bch2_trans_iter_exit(trans, &iter);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w)
|
static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
@ -1553,8 +1534,8 @@ static int check_dirent_target(struct btree_trans *trans,
|
|||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct bkey_i_dirent *n;
|
struct bkey_i_dirent *n;
|
||||||
bool backpointer_exists = true;
|
|
||||||
struct printbuf buf = PRINTBUF;
|
struct printbuf buf = PRINTBUF;
|
||||||
|
struct btree_iter bp_iter = { NULL };
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!target->bi_dir &&
|
if (!target->bi_dir &&
|
||||||
@ -1568,25 +1549,37 @@ static int check_dirent_target(struct btree_trans *trans,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!inode_points_to_dirent(target, d)) {
|
if (!inode_points_to_dirent(target, d)) {
|
||||||
ret = inode_backpointer_exists(trans, target, d.k->p.snapshot);
|
struct bkey_s_c_dirent bp_dirent = dirent_get_by_pos(trans, &bp_iter,
|
||||||
if (ret < 0)
|
SPOS(target->bi_dir, target->bi_dir_offset, target_snapshot));
|
||||||
|
ret = bkey_err(bp_dirent);
|
||||||
|
if (ret && !bch2_err_matches(ret, ENOENT))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
backpointer_exists = ret;
|
bool backpointer_exists = !ret;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
bch2_bkey_val_to_text(&buf, c, d.s_c);
|
||||||
|
prt_newline(&buf);
|
||||||
|
if (backpointer_exists)
|
||||||
|
bch2_bkey_val_to_text(&buf, c, bp_dirent.s_c);
|
||||||
|
|
||||||
if (fsck_err_on(S_ISDIR(target->bi_mode) && backpointer_exists,
|
if (fsck_err_on(S_ISDIR(target->bi_mode) && backpointer_exists,
|
||||||
c, inode_dir_multiple_links,
|
c, inode_dir_multiple_links,
|
||||||
"directory %llu with multiple links",
|
"directory %llu:%u with multiple links\n%s",
|
||||||
target->bi_inum)) {
|
target->bi_inum, target_snapshot, buf.buf)) {
|
||||||
ret = __remove_dirent(trans, d.k->p);
|
ret = __remove_dirent(trans, d.k->p);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hardlinked file with nlink 0:
|
||||||
|
* We're just adjusting nlink here so check_nlinks() will pick
|
||||||
|
* it up, it ignores inodes with nlink 0
|
||||||
|
*/
|
||||||
if (fsck_err_on(backpointer_exists && !target->bi_nlink,
|
if (fsck_err_on(backpointer_exists && !target->bi_nlink,
|
||||||
c, inode_multiple_links_but_nlink_0,
|
c, inode_multiple_links_but_nlink_0,
|
||||||
"inode %llu type %s has multiple links but i_nlink 0",
|
"inode %llu:%u type %s has multiple links but i_nlink 0\n%s",
|
||||||
target->bi_inum, bch2_d_types[d.v->d_type])) {
|
target->bi_inum, target_snapshot, bch2_d_types[d.v->d_type], buf.buf)) {
|
||||||
target->bi_nlink++;
|
target->bi_nlink++;
|
||||||
target->bi_flags &= ~BCH_INODE_unlinked;
|
target->bi_flags &= ~BCH_INODE_unlinked;
|
||||||
|
|
||||||
@ -1660,6 +1653,7 @@ static int check_dirent_target(struct btree_trans *trans,
|
|||||||
out:
|
out:
|
||||||
err:
|
err:
|
||||||
fsck_err:
|
fsck_err:
|
||||||
|
bch2_trans_iter_exit(trans, &bp_iter);
|
||||||
printbuf_exit(&buf);
|
printbuf_exit(&buf);
|
||||||
bch_err_fn(c, ret);
|
bch_err_fn(c, ret);
|
||||||
return ret;
|
return ret;
|
||||||
@ -2220,7 +2214,7 @@ static int nlink_cmp(const void *_l, const void *_r)
|
|||||||
const struct nlink *l = _l;
|
const struct nlink *l = _l;
|
||||||
const struct nlink *r = _r;
|
const struct nlink *r = _r;
|
||||||
|
|
||||||
return cmp_int(l->inum, r->inum) ?: cmp_int(l->snapshot, r->snapshot);
|
return cmp_int(l->inum, r->inum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inc_link(struct bch_fs *c, struct snapshots_seen *s,
|
static void inc_link(struct bch_fs *c, struct snapshots_seen *s,
|
||||||
@ -2401,7 +2395,7 @@ static int check_nlinks_update_hardlinks(struct bch_fs *c,
|
|||||||
NULL, NULL, BCH_TRANS_COMMIT_lazy_rw|BCH_TRANS_COMMIT_no_enospc,
|
NULL, NULL, BCH_TRANS_COMMIT_lazy_rw|BCH_TRANS_COMMIT_no_enospc,
|
||||||
check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end)));
|
check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end)));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bch_err(c, "error in fsck: btree error %i while walking inodes", ret);
|
bch_err(c, "error in fsck walking inodes: %s", bch2_err_str(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1124,10 +1124,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans,
|
|||||||
inode.bi_flags &= ~BCH_INODE_unlinked;
|
inode.bi_flags &= ~BCH_INODE_unlinked;
|
||||||
|
|
||||||
ret = bch2_inode_write_flags(trans, &inode_iter, &inode,
|
ret = bch2_inode_write_flags(trans, &inode_iter, &inode,
|
||||||
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?:
|
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
|
||||||
bch2_trans_commit(trans, NULL, NULL,
|
|
||||||
BCH_TRANS_COMMIT_no_enospc|
|
|
||||||
BCH_TRANS_COMMIT_lazy_rw);
|
|
||||||
bch_err_msg(c, ret, "clearing inode unlinked flag");
|
bch_err_msg(c, ret, "clearing inode unlinked flag");
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@ -1172,8 +1169,10 @@ again:
|
|||||||
*/
|
*/
|
||||||
for_each_btree_key(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
|
for_each_btree_key(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
|
||||||
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
|
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
|
||||||
ret = lockrestart_do(trans, may_delete_deleted_inode(trans, &iter, k.k->p,
|
ret = commit_do(trans, NULL, NULL,
|
||||||
&need_another_pass));
|
BCH_TRANS_COMMIT_no_enospc|
|
||||||
|
BCH_TRANS_COMMIT_lazy_rw,
|
||||||
|
may_delete_deleted_inode(trans, &iter, k.k->p, &need_another_pass));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -795,7 +795,7 @@ static int bch2_write_decrypt(struct bch_write_op *op)
|
|||||||
* checksum:
|
* checksum:
|
||||||
*/
|
*/
|
||||||
csum = bch2_checksum_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
|
csum = bch2_checksum_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
|
||||||
if (bch2_crc_cmp(op->crc.csum, csum))
|
if (bch2_crc_cmp(op->crc.csum, csum) && !c->opts.no_data_io)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
|
ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
|
||||||
|
@ -161,8 +161,8 @@ static int bch2_journal_replay(struct bch_fs *c)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* First, attempt to replay keys in sorted order. This is more
|
* First, attempt to replay keys in sorted order. This is more
|
||||||
* efficient, but some might fail if that would cause a journal
|
* efficient - better locality of btree access - but some might fail if
|
||||||
* deadlock.
|
* that would cause a journal deadlock.
|
||||||
*/
|
*/
|
||||||
for (size_t i = 0; i < keys->nr; i++) {
|
for (size_t i = 0; i < keys->nr; i++) {
|
||||||
cond_resched();
|
cond_resched();
|
||||||
@ -211,6 +211,10 @@ static int bch2_journal_replay(struct bch_fs *c)
|
|||||||
BUG_ON(!k->overwritten);
|
BUG_ON(!k->overwritten);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to put our btree_trans before calling flush_all_pins(), since
|
||||||
|
* that will use a btree_trans internally
|
||||||
|
*/
|
||||||
bch2_trans_put(trans);
|
bch2_trans_put(trans);
|
||||||
trans = NULL;
|
trans = NULL;
|
||||||
|
|
||||||
@ -874,6 +878,8 @@ use_clean:
|
|||||||
test_bit(BCH_FS_ERRORS_FIXED, &c->flags) &&
|
test_bit(BCH_FS_ERRORS_FIXED, &c->flags) &&
|
||||||
!test_bit(BCH_FS_ERRORS_NOT_FIXED, &c->flags) &&
|
!test_bit(BCH_FS_ERRORS_NOT_FIXED, &c->flags) &&
|
||||||
!test_bit(BCH_FS_ERROR, &c->flags)) {
|
!test_bit(BCH_FS_ERROR, &c->flags)) {
|
||||||
|
bch2_flush_fsck_errs(c);
|
||||||
|
|
||||||
bch_info(c, "Fixed errors, running fsck a second time to verify fs is clean");
|
bch_info(c, "Fixed errors, running fsck a second time to verify fs is clean");
|
||||||
clear_bit(BCH_FS_ERRORS_FIXED, &c->flags);
|
clear_bit(BCH_FS_ERRORS_FIXED, &c->flags);
|
||||||
|
|
||||||
|
@ -163,8 +163,11 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type,
|
|||||||
this_cpu_sub(*lock->readers, !ret);
|
this_cpu_sub(*lock->readers, !ret);
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
|
|
||||||
if (!ret && (old & SIX_LOCK_WAITING_write))
|
if (!ret) {
|
||||||
ret = -1 - SIX_LOCK_write;
|
smp_mb();
|
||||||
|
if (atomic_read(&lock->state) & SIX_LOCK_WAITING_write)
|
||||||
|
ret = -1 - SIX_LOCK_write;
|
||||||
|
}
|
||||||
} else if (type == SIX_LOCK_write && lock->readers) {
|
} else if (type == SIX_LOCK_write && lock->readers) {
|
||||||
if (try) {
|
if (try) {
|
||||||
atomic_add(SIX_LOCK_HELD_write, &lock->state);
|
atomic_add(SIX_LOCK_HELD_write, &lock->state);
|
||||||
|
@ -1252,22 +1252,37 @@ TRACE_EVENT(trans_restart_key_cache_key_realloced,
|
|||||||
TRACE_EVENT(path_downgrade,
|
TRACE_EVENT(path_downgrade,
|
||||||
TP_PROTO(struct btree_trans *trans,
|
TP_PROTO(struct btree_trans *trans,
|
||||||
unsigned long caller_ip,
|
unsigned long caller_ip,
|
||||||
struct btree_path *path),
|
struct btree_path *path,
|
||||||
TP_ARGS(trans, caller_ip, path),
|
unsigned old_locks_want),
|
||||||
|
TP_ARGS(trans, caller_ip, path, old_locks_want),
|
||||||
|
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
__array(char, trans_fn, 32 )
|
__array(char, trans_fn, 32 )
|
||||||
__field(unsigned long, caller_ip )
|
__field(unsigned long, caller_ip )
|
||||||
|
__field(unsigned, old_locks_want )
|
||||||
|
__field(unsigned, new_locks_want )
|
||||||
|
__field(unsigned, btree )
|
||||||
|
TRACE_BPOS_entries(pos)
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
strscpy(__entry->trans_fn, trans->fn, sizeof(__entry->trans_fn));
|
strscpy(__entry->trans_fn, trans->fn, sizeof(__entry->trans_fn));
|
||||||
__entry->caller_ip = caller_ip;
|
__entry->caller_ip = caller_ip;
|
||||||
|
__entry->old_locks_want = old_locks_want;
|
||||||
|
__entry->new_locks_want = path->locks_want;
|
||||||
|
__entry->btree = path->btree_id;
|
||||||
|
TRACE_BPOS_assign(pos, path->pos);
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_printk("%s %pS",
|
TP_printk("%s %pS locks_want %u -> %u %s %llu:%llu:%u",
|
||||||
__entry->trans_fn,
|
__entry->trans_fn,
|
||||||
(void *) __entry->caller_ip)
|
(void *) __entry->caller_ip,
|
||||||
|
__entry->old_locks_want,
|
||||||
|
__entry->new_locks_want,
|
||||||
|
bch2_btree_id_str(__entry->btree),
|
||||||
|
__entry->pos_inode,
|
||||||
|
__entry->pos_offset,
|
||||||
|
__entry->pos_snapshot)
|
||||||
);
|
);
|
||||||
|
|
||||||
DEFINE_EVENT(transaction_event, trans_restart_write_buffer_flush,
|
DEFINE_EVENT(transaction_event, trans_restart_write_buffer_flush,
|
||||||
|
@ -322,6 +322,7 @@ void bch2_prt_datetime(struct printbuf *out, time64_t sec)
|
|||||||
time_t t = sec;
|
time_t t = sec;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
ctime_r(&t, buf);
|
ctime_r(&t, buf);
|
||||||
|
strim(buf);
|
||||||
prt_str(out, buf);
|
prt_str(out, buf);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -552,6 +552,14 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
|
|||||||
s.v = v + 1;
|
s.v = v + 1;
|
||||||
s.defined = true;
|
s.defined = true;
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* Check if this option was set on the parent - if so, switched
|
||||||
|
* back to inheriting from the parent:
|
||||||
|
*
|
||||||
|
* rename() also has to deal with keeping inherited options up
|
||||||
|
* to date - see bch2_reinherit_attrs()
|
||||||
|
*/
|
||||||
|
spin_lock(&dentry->d_lock);
|
||||||
if (!IS_ROOT(dentry)) {
|
if (!IS_ROOT(dentry)) {
|
||||||
struct bch_inode_info *dir =
|
struct bch_inode_info *dir =
|
||||||
to_bch_ei(d_inode(dentry->d_parent));
|
to_bch_ei(d_inode(dentry->d_parent));
|
||||||
@ -560,6 +568,7 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
|
|||||||
} else {
|
} else {
|
||||||
s.v = 0;
|
s.v = 0;
|
||||||
}
|
}
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
|
|
||||||
s.defined = false;
|
s.defined = false;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ impl<'f> Drop for BtreeTrans<'f> {
|
|||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct BtreeIterFlags: u16 {
|
pub struct BtreeIterFlags: u16 {
|
||||||
const SLOTS = c::BTREE_ITER_SLOTS as u16;
|
const SLOTS = c::BTREE_ITER_SLOTS as u16;
|
||||||
const ALL_LEVELS = c::BTREE_ITER_ALL_LEVELS as u16;
|
|
||||||
const INTENT = c::BTREE_ITER_INTENT as u16;
|
const INTENT = c::BTREE_ITER_INTENT as u16;
|
||||||
const PREFETCH = c::BTREE_ITER_PREFETCH as u16;
|
const PREFETCH = c::BTREE_ITER_PREFETCH as u16;
|
||||||
const IS_EXTENTS = c::BTREE_ITER_IS_EXTENTS as u16;
|
const IS_EXTENTS = c::BTREE_ITER_IS_EXTENTS as u16;
|
||||||
|
Loading…
Reference in New Issue
Block a user