]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to 938f680845d1 fixup! rename and export __kern_path_locked()
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 16 Nov 2023 20:47:11 +0000 (15:47 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 16 Nov 2023 22:54:06 +0000 (17:54 -0500)
17 files changed:
.bcachefs_revision
libbcachefs/backpointers.c
libbcachefs/btree_iter.c
libbcachefs/btree_iter.h
libbcachefs/btree_locking.c
libbcachefs/btree_types.h
libbcachefs/btree_update_interior.c
libbcachefs/fs-ioctl.c
libbcachefs/fsck.c
libbcachefs/inode.c
libbcachefs/io_write.c
libbcachefs/recovery.c
libbcachefs/six.c
libbcachefs/trace.h
libbcachefs/util.c
libbcachefs/xattr.c
rust-src/bch_bindgen/src/btree.rs

index bf2104d1c09d5f763b25145d1aac31e6ec1098f8..baa146ea85a20e762eb41f0b0f999ef55e75aac3 100644 (file)
@@ -1 +1 @@
-3ca08ab51ec996180c20105489176b8c4327240c
+938f680845d1be28979e23aee972dba010c464ba
index 5025a71ad6851709957f1d27bf3e46a3b66d962b..4c8bcf23bb27194875191f0214a583b2340de3db 100644 (file)
@@ -457,25 +457,18 @@ missing:
 }
 
 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_end,
-                                       struct bpos_level *last_flushed)
+                                       struct bpos_level *last_flushed,
+                                       struct bkey_s_c k)
 {
        struct bch_fs *c = trans->c;
        struct bkey_ptrs_c ptrs;
        const union bch_extent_entry *entry;
        struct extent_ptr_decoded p;
-       struct bkey_s_c k;
        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);
        bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
                struct bpos bucket_pos;
@@ -484,7 +477,7 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
                if (p.ptr.cached)
                        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);
 
                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,
                                            struct bpos bucket_start,
                                            struct bpos bucket_end,
-                                           struct bpos_level *last_flushed)
+                                           struct bpos_level *last_flushed,
+                                           int *level)
 {
        struct bch_fs *c = trans->c;
-       struct btree_root *r = bch2_btree_id_root(c, btree_id);
        struct btree_iter iter;
        struct btree *b;
        struct bkey_s_c k;
-       struct bkey_ptrs_c ptrs;
-       struct extent_ptr_decoded p;
-       const union bch_extent_entry *entry;
        int ret;
-
-       bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0, r->level, 0);
+retry:
+       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);
        ret = PTR_ERR_OR_ZERO(b);
        if (ret)
                goto err;
 
-       BUG_ON(b != btree_node_root(c, b));
-
-       k = bkey_i_to_s_c(&b->key);
-       ptrs = bch2_bkey_ptrs_c(k);
-       bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
-               struct bpos bucket_pos;
-               struct bch_backpointer bp;
-
-               if (p.ptr.cached)
-                       continue;
+       if (b != btree_node_root(c, b)) {
+               bch2_trans_iter_exit(trans, &iter);
+               goto retry;
+       }
 
-               bch2_extent_ptr_to_bp(c, iter.btree_id, b->c.level + 1,
-                                     k, p, &bucket_pos, &bp);
+       *level = b->c.level;
 
-               ret = check_bp_exists(trans, bucket_pos, bp, k,
+       k = bkey_i_to_s_c(&b->key);
+       ret = check_extent_to_backpointers(trans, btree_id, b->c.level + 1,
                                      bucket_start, bucket_end,
-                                     last_flushed);
-               if (ret)
-                       goto err;
-       }
+                                     last_flushed, k);
 err:
        bch2_trans_iter_exit(trans, &iter);
        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 btree_iter iter;
        enum btree_id btree_id;
+       struct bkey_s_c k;
        struct bpos_level last_flushed = { UINT_MAX, POS_MIN };
        int ret = 0;
 
        for (btree_id = 0; btree_id < btree_id_nr_alive(c); btree_id++) {
-               unsigned 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;
+               int level, depth = btree_type_has_ptrs(btree_id) ? 0 : 1;
 
                ret = commit_do(trans, NULL, NULL,
                                BCH_TRANS_COMMIT_lazy_rw|
                                BCH_TRANS_COMMIT_no_enospc,
                                check_btree_root_to_backpointers(trans, btree_id,
                                                        bucket_start, bucket_end,
-                                                       &last_flushed));
+                                                       &last_flushed, &level));
                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,
index 104172f6822b3e26ed5acd8b64df79e9f5971f01..3128695062d9345b8e94b442db77e93c25897e0e 100644 (file)
@@ -1797,23 +1797,15 @@ err:
 
 inline bool bch2_btree_iter_advance(struct btree_iter *iter)
 {
-       if (likely(!(iter->flags & BTREE_ITER_ALL_LEVELS))) {
-               struct bpos pos = iter->k.p;
-               bool ret = !(iter->flags & BTREE_ITER_ALL_SNAPSHOTS
-                            ? bpos_eq(pos, SPOS_MAX)
-                            : bkey_eq(pos, SPOS_MAX));
-
-               if (ret && !(iter->flags & BTREE_ITER_IS_EXTENTS))
-                       pos = bkey_successor(iter, pos);
-               bch2_btree_iter_set_pos(iter, pos);
-               return ret;
-       } else {
-               if (!btree_path_node(iter->path, iter->path->level))
-                       return true;
+       struct bpos pos = iter->k.p;
+       bool ret = !(iter->flags & BTREE_ITER_ALL_SNAPSHOTS
+                    ? bpos_eq(pos, SPOS_MAX)
+                    : bkey_eq(pos, SPOS_MAX));
 
-               iter->advanced = true;
-               return false;
-       }
+       if (ret && !(iter->flags & BTREE_ITER_IS_EXTENTS))
+               pos = bkey_successor(iter, pos);
+       bch2_btree_iter_set_pos(iter, pos);
+       return ret;
 }
 
 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;
        int ret;
 
-       EBUG_ON(iter->flags & BTREE_ITER_ALL_LEVELS);
        EBUG_ON((iter->flags & BTREE_ITER_FILTER_SNAPSHOTS) && bkey_eq(end, POS_MAX));
 
        if (iter->update_path) {
@@ -2190,103 +2181,6 @@ end:
        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
  * 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_entry_exit(iter);
-       EBUG_ON(iter->flags & BTREE_ITER_ALL_LEVELS);
        EBUG_ON(iter->path->level && (iter->flags & BTREE_ITER_WITH_KEY_CACHE));
 
        /* extents can't span inode numbers: */
index 85e7cb52f6b6c41b95c7dc3496a9340c9f2b38d0..e5b989a8eb98ab330eeacadd6b8c24d72f440599 100644 (file)
@@ -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_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)
 {
        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 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)) &&
            btree_id_is_extents(btree_id))
                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,
                                                             unsigned flags)
 {
-       BUG_ON(flags & BTREE_ITER_ALL_LEVELS);
-
        return  flags & BTREE_ITER_SLOTS      ? bch2_btree_iter_peek_slot(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,
                                                        unsigned flags)
 {
-       return  flags & BTREE_ITER_ALL_LEVELS ? bch2_btree_iter_peek_all_levels(iter) :
-               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(iter);
 }
 
index c4266835b8646f45adf9eb1a5f116bac12470fe1..59c57c585a4c37716ecc50fbfdc0968eb62655d7 100644 (file)
@@ -664,7 +664,7 @@ void __bch2_btree_path_downgrade(struct btree_trans *trans,
                                 struct btree_path *path,
                                 unsigned new_locks_want)
 {
-       unsigned l;
+       unsigned l, old_locks_want = path->locks_want;
 
        if (trans->restarted)
                return;
@@ -689,7 +689,7 @@ void __bch2_btree_path_downgrade(struct btree_trans *trans,
        bch2_btree_path_verify_locks(path);
 
        path->downgrade_seq++;
-       trace_path_downgrade(trans, _RET_IP_, path);
+       trace_path_downgrade(trans, _RET_IP_, path, old_locks_want);
 }
 
 /* Btree transaction locking: */
index a3f24cd0043dbbf19783063db9cc45205ab53b79..e58575ad104542bf1d5f5f111a5bf1ee10255ba0 100644 (file)
@@ -195,33 +195,32 @@ struct btree_node_iter {
  * 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_ALL_LEVELS          = 1 << 1;
 /*
  * Indicates that intent locks should be taken on leaf nodes, because we expect
  * 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:
  */
-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
  * @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_NOT_EXTENTS         = 1 << 5;
-static const __maybe_unused u16 BTREE_ITER_CACHED              = 1 << 6;
-static const __maybe_unused u16 BTREE_ITER_WITH_KEY_CACHE      = 1 << 7;
-static const __maybe_unused u16 BTREE_ITER_WITH_UPDATES                = 1 << 8;
-static const __maybe_unused u16 BTREE_ITER_WITH_JOURNAL                = 1 << 9;
-static const __maybe_unused u16 __BTREE_ITER_ALL_SNAPSHOTS     = 1 << 10;
-static const __maybe_unused u16 BTREE_ITER_ALL_SNAPSHOTS       = 1 << 11;
-static const __maybe_unused u16 BTREE_ITER_FILTER_SNAPSHOTS    = 1 << 12;
-static const __maybe_unused u16 BTREE_ITER_NOPRESERVE          = 1 << 13;
-static const __maybe_unused u16 BTREE_ITER_CACHED_NOFILL       = 1 << 14;
-static const __maybe_unused u16 BTREE_ITER_KEY_CACHE_FILL      = 1 << 15;
-#define __BTREE_ITER_FLAGS_END                                        16
+static const __maybe_unused u16 BTREE_ITER_IS_EXTENTS          = 1 << 3;
+static const __maybe_unused u16 BTREE_ITER_NOT_EXTENTS         = 1 << 4;
+static const __maybe_unused u16 BTREE_ITER_CACHED              = 1 << 5;
+static const __maybe_unused u16 BTREE_ITER_WITH_KEY_CACHE      = 1 << 6;
+static const __maybe_unused u16 BTREE_ITER_WITH_UPDATES                = 1 << 7;
+static const __maybe_unused u16 BTREE_ITER_WITH_JOURNAL                = 1 << 8;
+static const __maybe_unused u16 __BTREE_ITER_ALL_SNAPSHOTS     = 1 << 9;
+static const __maybe_unused u16 BTREE_ITER_ALL_SNAPSHOTS       = 1 << 10;
+static const __maybe_unused u16 BTREE_ITER_FILTER_SNAPSHOTS    = 1 << 11;
+static const __maybe_unused u16 BTREE_ITER_NOPRESERVE          = 1 << 12;
+static const __maybe_unused u16 BTREE_ITER_CACHED_NOFILL       = 1 << 13;
+static const __maybe_unused u16 BTREE_ITER_KEY_CACHE_FILL      = 1 << 14;
+#define __BTREE_ITER_FLAGS_END                                        15
 
 enum btree_path_uptodate {
        BTREE_ITER_UPTODATE             = 0,
index 9affcb22d9cb7025453cfd528f13738ff9514879..18e5a75142e9a5e95b68661965342e8b923e140e 100644 (file)
@@ -1054,7 +1054,6 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
        unsigned nr_nodes[2] = { 0, 0 };
        unsigned update_level = level;
        enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
-       unsigned journal_flags = 0;
        int ret = 0;
        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 |= watermark;
 
-       if (flags & BCH_TRANS_COMMIT_journal_reclaim)
-               journal_flags |= JOURNAL_RES_GET_NONBLOCK;
-       journal_flags |= watermark;
-
        while (1) {
                nr_nodes[!!update_level] += 1 + split;
                update_level++;
index 5a39bcb597a33d42826a16a98da394de3fe23660..d7c1b05aa438568c4b7becceb00e20853ad87d3f 100644 (file)
@@ -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,
                                struct bch_ioctl_subvolume arg)
 {
+       struct filename *name;
        struct path path;
        struct inode *dir;
+       struct dentry *victim;
        int ret = 0;
 
        if (arg.flags)
                return -EINVAL;
 
-       ret = user_path_at(arg.dirfd,
-                       (const char __user *)(unsigned long)arg.dst_ptr,
-                       LOOKUP_FOLLOW, &path);
-       if (ret)
-               return ret;
+       name = getname((const char __user *)(unsigned long)arg.dst_ptr);
+       victim = filename_path_locked(arg.dirfd, name, &path);
+       putname(name);
+       if (IS_ERR(victim))
+               return PTR_ERR(victim);
 
-       if (path.dentry->d_sb->s_fs_info != c) {
+       if (victim->d_sb->s_fs_info != c) {
                ret = -EXDEV;
                goto err;
        }
 
-       dir = path.dentry->d_parent->d_inode;
-
-       ret = __bch2_unlink(dir, path.dentry, true);
-       if (ret)
-               goto err;
-
-       fsnotify_rmdir(dir, path.dentry);
-       d_delete(path.dentry);
+       dir = d_inode(path.dentry);
+       ret = __bch2_unlink(dir, victim, true);
+       if (!ret) {
+               fsnotify_rmdir(dir, victim);
+               d_delete(victim);
+       }
+       inode_unlock(dir);
 err:
+       dput(victim);
        path_put(&path);
        return ret;
 }
index 127310d310fb9ca2bf4a550b72cf8eb031b3548b..cc90279fdf4ee85c8d6db9f8108ce188c9fd19aa 100644 (file)
@@ -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;
 }
 
-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)
 {
        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 bkey_i_dirent *n;
-       bool backpointer_exists = true;
        struct printbuf buf = PRINTBUF;
+       struct btree_iter bp_iter = { NULL };
        int ret = 0;
 
        if (!target->bi_dir &&
@@ -1568,25 +1549,37 @@ static int check_dirent_target(struct btree_trans *trans,
        }
 
        if (!inode_points_to_dirent(target, d)) {
-               ret = inode_backpointer_exists(trans, target, d.k->p.snapshot);
-               if (ret < 0)
+               struct bkey_s_c_dirent bp_dirent = dirent_get_by_pos(trans, &bp_iter,
+                                     SPOS(target->bi_dir, target->bi_dir_offset, target_snapshot));
+               ret = bkey_err(bp_dirent);
+               if (ret && !bch2_err_matches(ret, ENOENT))
                        goto err;
 
-               backpointer_exists = ret;
+               bool backpointer_exists = !ret;
                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,
                                c, inode_dir_multiple_links,
-                               "directory %llu with multiple links",
-                               target->bi_inum)) {
+                               "directory %llu:%u with multiple links\n%s",
+                               target->bi_inum, target_snapshot, buf.buf)) {
                        ret = __remove_dirent(trans, d.k->p);
                        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,
                                c, inode_multiple_links_but_nlink_0,
-                               "inode %llu type %s has multiple links but i_nlink 0",
-                               target->bi_inum, bch2_d_types[d.v->d_type])) {
+                               "inode %llu:%u type %s has multiple links but i_nlink 0\n%s",
+                               target->bi_inum, target_snapshot, bch2_d_types[d.v->d_type], buf.buf)) {
                        target->bi_nlink++;
                        target->bi_flags &= ~BCH_INODE_unlinked;
 
@@ -1660,6 +1653,7 @@ static int check_dirent_target(struct btree_trans *trans,
 out:
 err:
 fsck_err:
+       bch2_trans_iter_exit(trans, &bp_iter);
        printbuf_exit(&buf);
        bch_err_fn(c, 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 *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,
@@ -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,
                        check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end)));
        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;
        }
 
index 1baf8b7fdccb9e77f61a8784dce4657f85cd58f2..b9d6dbf3a54b26bacc211b3d4779fddc68460af6 100644 (file)
@@ -1124,10 +1124,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans,
                inode.bi_flags &= ~BCH_INODE_unlinked;
 
                ret = bch2_inode_write_flags(trans, &inode_iter, &inode,
-                                            BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?:
-                       bch2_trans_commit(trans, NULL, NULL,
-                                         BCH_TRANS_COMMIT_no_enospc|
-                                         BCH_TRANS_COMMIT_lazy_rw);
+                                            BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
                bch_err_msg(c, ret, "clearing inode unlinked flag");
                if (ret)
                        goto out;
@@ -1172,8 +1169,10 @@ again:
         */
        for_each_btree_key(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
                           BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
-               ret = lockrestart_do(trans, may_delete_deleted_inode(trans, &iter, k.k->p,
-                                                                    &need_another_pass));
+               ret = commit_do(trans, NULL, NULL,
+                               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)
                        break;
 
index 97f7a4b7fdecaaf048839d7e989ae84bc93edf52..75376f040e4b4e29d6abe94a9352d5413e0972a5 100644 (file)
@@ -795,7 +795,7 @@ static int bch2_write_decrypt(struct bch_write_op *op)
         * checksum:
         */
        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;
 
        ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
index 130274b195e21621c391ad89d965440cf077816c..83fc121ff3c44d3012a1d5770536549cbc479971 100644 (file)
@@ -161,8 +161,8 @@ static int bch2_journal_replay(struct bch_fs *c)
 
        /*
         * First, attempt to replay keys in sorted order. This is more
-        * efficient, but some might fail if that would cause a journal
-        * deadlock.
+        * efficient - better locality of btree access -  but some might fail if
+        * that would cause a journal deadlock.
         */
        for (size_t i = 0; i < keys->nr; i++) {
                cond_resched();
@@ -211,6 +211,10 @@ static int bch2_journal_replay(struct bch_fs *c)
                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);
        trans = NULL;
 
@@ -874,6 +878,8 @@ use_clean:
            test_bit(BCH_FS_ERRORS_FIXED, &c->flags) &&
            !test_bit(BCH_FS_ERRORS_NOT_FIXED, &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");
                clear_bit(BCH_FS_ERRORS_FIXED, &c->flags);
 
index d22826cabee07d022194c93d31fe5e19055faaef..f37d5ad2c6ffdd458a841796a18d940d26762a41 100644 (file)
@@ -163,8 +163,11 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type,
                this_cpu_sub(*lock->readers, !ret);
                preempt_enable();
 
-               if (!ret && (old & SIX_LOCK_WAITING_write))
-                       ret = -1 - SIX_LOCK_write;
+               if (!ret) {
+                       smp_mb();
+                       if (atomic_read(&lock->state) & SIX_LOCK_WAITING_write)
+                               ret = -1 - SIX_LOCK_write;
+               }
        } else if (type == SIX_LOCK_write && lock->readers) {
                if (try) {
                        atomic_add(SIX_LOCK_HELD_write, &lock->state);
index 7857671159b491235a0bcdfe19f9b34a316a0126..09a530325dd05e43d18f7e81a3d64a3fbd95c6ea 100644 (file)
@@ -1252,22 +1252,37 @@ TRACE_EVENT(trans_restart_key_cache_key_realloced,
 TRACE_EVENT(path_downgrade,
        TP_PROTO(struct btree_trans *trans,
                 unsigned long caller_ip,
-                struct btree_path *path),
-       TP_ARGS(trans, caller_ip, path),
+                struct btree_path *path,
+                unsigned old_locks_want),
+       TP_ARGS(trans, caller_ip, path, old_locks_want),
 
        TP_STRUCT__entry(
                __array(char,                   trans_fn, 32    )
                __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(
                strscpy(__entry->trans_fn, trans->fn, sizeof(__entry->trans_fn));
                __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,
-                 (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,
index 2ff9cdfb006c920172e7727e5f9c406ee218fd99..c3303b02e5de42629f0baab36d81d63bfc5a4a68 100644 (file)
@@ -322,6 +322,7 @@ void bch2_prt_datetime(struct printbuf *out, time64_t sec)
        time_t t = sec;
        char buf[64];
        ctime_r(&t, buf);
+       strim(buf);
        prt_str(out, buf);
 }
 #else
index a39ff0c296ecfb2a000edd6aace20bdbb8db20ea..79d982674c180307f5d5a4da42fabaa480878573 100644 (file)
@@ -552,6 +552,14 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
                s.v = v + 1;
                s.defined = true;
        } 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)) {
                        struct bch_inode_info *dir =
                                to_bch_ei(d_inode(dentry->d_parent));
@@ -560,6 +568,7 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
                } else {
                        s.v = 0;
                }
+               spin_unlock(&dentry->d_lock);
 
                s.defined = false;
        }
index f738a46689766681f67a12de7ee5d23b3838da2e..c8203a421815cec65ed33ead22a6849e3853c563 100644 (file)
@@ -32,7 +32,6 @@ impl<'f> Drop for BtreeTrans<'f> {
 bitflags! {
     pub struct BtreeIterFlags: 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 PREFETCH = c::BTREE_ITER_PREFETCH as u16;
         const IS_EXTENTS = c::BTREE_ITER_IS_EXTENTS as u16;