]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: Always check for transaction restarts
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 24 Jul 2021 23:50:40 +0000 (19:50 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:09 +0000 (17:09 -0400)
On transaction restart iterators won't be locked anymore - make sure
we're always checking for errors.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
14 files changed:
fs/bcachefs/acl.c
fs/bcachefs/alloc_background.c
fs/bcachefs/btree_cache.c
fs/bcachefs/btree_cache.h
fs/bcachefs/btree_iter.c
fs/bcachefs/dirent.c
fs/bcachefs/fs-common.c
fs/bcachefs/fs-io.c
fs/bcachefs/inode.c
fs/bcachefs/io.c
fs/bcachefs/move.c
fs/bcachefs/reflink.c
fs/bcachefs/str_hash.h
fs/bcachefs/xattr.c

index 1642518d32332cafc0209c55ff6827aaed15fe55..d3e2e24758ba3187d68a9303a6c6051875216ccd 100644 (file)
@@ -222,6 +222,8 @@ struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap,
        struct btree_iter *iter;
        struct bkey_s_c_xattr xattr;
        struct posix_acl *acl = NULL;
+       struct bkey_s_c k;
+       int ret;
 
        bch2_trans_init(&trans, c, 0, 0);
 retry:
@@ -240,7 +242,14 @@ retry:
                goto out;
        }
 
-       xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
+       k = bch2_btree_iter_peek_slot(iter);
+       ret = bkey_err(k);
+       if (ret) {
+               acl = ERR_PTR(ret);
+               goto out;
+       }
+
+       xattr = bkey_s_c_to_xattr(k);
        acl = bch2_acl_from_disk(xattr_val(xattr.v),
                        le16_to_cpu(xattr.v->x_val_len));
 
@@ -358,6 +367,7 @@ int bch2_acl_chmod(struct btree_trans *trans,
        struct bkey_s_c_xattr xattr;
        struct bkey_i_xattr *new;
        struct posix_acl *acl;
+       struct bkey_s_c k;
        int ret;
 
        iter = bch2_hash_lookup(trans, bch2_xattr_hash_desc,
@@ -368,7 +378,11 @@ int bch2_acl_chmod(struct btree_trans *trans,
        if (ret)
                return ret == -ENOENT ? 0 : ret;
 
-       xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
+       k = bch2_btree_iter_peek_slot(iter);
+       xattr = bkey_s_c_to_xattr(k);
+       if (ret)
+               goto err;
+
        acl = bch2_acl_from_disk(xattr_val(xattr.v),
                        le16_to_cpu(xattr.v->x_val_len));
        ret = PTR_ERR_OR_ZERO(acl);
index 26aca7d3977b8988f89470ab4c4fb7341f7a9db7..932a8176dff743fcfee9da89b28ca6a819548e1d 100644 (file)
@@ -374,7 +374,7 @@ int bch2_alloc_write(struct bch_fs *c, unsigned flags)
                                percpu_ref_put(&ca->ref);
                                goto err;
                        }
-                       bch2_btree_iter_next_slot(iter);
+                       bch2_btree_iter_advance(iter);
                }
        }
 err:
index 818b8df063da83d6bd6e49e0b0ff1ce0a2701866..252801dee0288b4d0e80388918a1d97b07e188d7 100644 (file)
@@ -973,9 +973,9 @@ out:
        return b;
 }
 
-void bch2_btree_node_prefetch(struct bch_fs *c, struct btree_iter *iter,
-                             const struct bkey_i *k,
-                             enum btree_id btree_id, unsigned level)
+int bch2_btree_node_prefetch(struct bch_fs *c, struct btree_iter *iter,
+                            const struct bkey_i *k,
+                            enum btree_id btree_id, unsigned level)
 {
        struct btree_cache *bc = &c->btree_cache;
        struct btree *b;
@@ -985,9 +985,10 @@ void bch2_btree_node_prefetch(struct bch_fs *c, struct btree_iter *iter,
 
        b = btree_cache_find(bc, k);
        if (b)
-               return;
+               return 0;
 
-       bch2_btree_node_fill(c, iter, k, btree_id, level, SIX_LOCK_read, false);
+       b = bch2_btree_node_fill(c, iter, k, btree_id, level, SIX_LOCK_read, false);
+       return PTR_ERR_OR_ZERO(b);
 }
 
 void bch2_btree_node_evict(struct bch_fs *c, const struct bkey_i *k)
index 6e9f08597d946e420dfa570417f0bf005f690043..eb57dc3c70b754ba2214565fa76dd73a2fde17f7 100644 (file)
@@ -27,8 +27,8 @@ struct btree *bch2_btree_node_get(struct btree_trans *, struct btree_iter *,
 struct btree *bch2_btree_node_get_noiter(struct bch_fs *, const struct bkey_i *,
                                         enum btree_id, unsigned, bool);
 
-void bch2_btree_node_prefetch(struct bch_fs *, struct btree_iter *,
-                             const struct bkey_i *, enum btree_id, unsigned);
+int bch2_btree_node_prefetch(struct bch_fs *, struct btree_iter *,
+                            const struct bkey_i *, enum btree_id, unsigned);
 
 void bch2_btree_node_evict(struct bch_fs *, const struct bkey_i *);
 
index 2a649166c042c9464c74ad6a114dbbd3c7df3a6b..89de6a8a8a9e3790f471bd0d944391dbaa03bd35 100644 (file)
@@ -1142,7 +1142,7 @@ static inline int btree_iter_lock_root(struct btree_iter *iter,
 }
 
 noinline
-static void btree_iter_prefetch(struct btree_iter *iter)
+static int btree_iter_prefetch(struct btree_iter *iter)
 {
        struct bch_fs *c = iter->trans->c;
        struct btree_iter_level *l = &iter->l[iter->level];
@@ -1153,10 +1153,11 @@ static void btree_iter_prefetch(struct btree_iter *iter)
                ? (iter->level > 1 ? 0 :  2)
                : (iter->level > 1 ? 1 : 16);
        bool was_locked = btree_node_locked(iter, iter->level);
+       int ret = 0;
 
        bch2_bkey_buf_init(&tmp);
 
-       while (nr) {
+       while (nr && !ret) {
                if (!bch2_btree_node_relock(iter, iter->level))
                        break;
 
@@ -1166,14 +1167,15 @@ static void btree_iter_prefetch(struct btree_iter *iter)
                        break;
 
                bch2_bkey_buf_unpack(&tmp, c, l->b, k);
-               bch2_btree_node_prefetch(c, iter, tmp.k, iter->btree_id,
-                                        iter->level - 1);
+               ret = bch2_btree_node_prefetch(c, iter, tmp.k, iter->btree_id,
+                                              iter->level - 1);
        }
 
        if (!was_locked)
                btree_node_unlock(iter, iter->level);
 
        bch2_bkey_buf_exit(&tmp, c);
+       return ret;
 }
 
 static noinline void btree_node_mem_ptr_set(struct btree_iter *iter,
@@ -1228,7 +1230,7 @@ static __always_inline int btree_iter_down(struct btree_iter *iter,
                btree_node_mem_ptr_set(iter, level + 1, b);
 
        if (iter->flags & BTREE_ITER_PREFETCH)
-               btree_iter_prefetch(iter);
+               ret = btree_iter_prefetch(iter);
 
        if (btree_node_read_locked(iter, level + 1))
                btree_node_unlock(iter, level + 1);
index a95165b8eddf97fa352a1ae577b6337b21d6402e..02b29681f695e09c30dcf8d3cc50fbff1c938ce9 100644 (file)
@@ -210,6 +210,9 @@ int bch2_dirent_rename(struct btree_trans *trans,
                goto out;
 
        old_dst = bch2_btree_iter_peek_slot(dst_iter);
+       ret = bkey_err(old_dst);
+       if (ret)
+               goto out;
 
        if (mode != BCH_RENAME)
                *dst_inum = le64_to_cpu(bkey_s_c_to_dirent(old_dst).v->d_inum);
@@ -225,6 +228,10 @@ int bch2_dirent_rename(struct btree_trans *trans,
                goto out;
 
        old_src = bch2_btree_iter_peek_slot(src_iter);
+       ret = bkey_err(old_src);
+       if (ret)
+               goto out;
+
        *src_inum = le64_to_cpu(bkey_s_c_to_dirent(old_src).v->d_inum);
 
        /* Create new dst key: */
@@ -329,20 +336,25 @@ u64 bch2_dirent_lookup(struct bch_fs *c, u64 dir_inum,
        struct btree_iter *iter;
        struct bkey_s_c k;
        u64 inum = 0;
+       int ret = 0;
 
        bch2_trans_init(&trans, c, 0, 0);
 
        iter = __bch2_dirent_lookup_trans(&trans, dir_inum,
                                          hash_info, name, 0);
-       if (IS_ERR(iter)) {
-               BUG_ON(PTR_ERR(iter) == -EINTR);
+       ret = PTR_ERR_OR_ZERO(iter);
+       if (ret)
                goto out;
-       }
 
        k = bch2_btree_iter_peek_slot(iter);
+       ret = bkey_err(k);
+       if (ret)
+               goto out;
+
        inum = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum);
        bch2_trans_iter_put(&trans, iter);
 out:
+       BUG_ON(ret == -EINTR);
        bch2_trans_exit(&trans);
        return inum;
 }
index 60c54438074e711ba2f9fcc1a34279dbe79a0ad8..2189a11ccad8d42e89a3749f7b19836d76f9a053 100644 (file)
@@ -168,6 +168,10 @@ int bch2_unlink_trans(struct btree_trans *trans,
                goto err;
 
        k = bch2_btree_iter_peek_slot(dirent_iter);
+       ret = bkey_err(k);
+       if (ret)
+               goto err;
+
        inum = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum);
 
        inode_iter = bch2_inode_peek(trans, inode_u, inum, BTREE_ITER_INTENT);
index 4af8cd018e3aafe4be4e6c3fb9de24618484add8..1a06f77101ab8b2139a4d6d7a4ebbae528e60634 100644 (file)
@@ -2668,13 +2668,13 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
                /* already reserved */
                if (k.k->type == KEY_TYPE_reservation &&
                    bkey_s_c_to_reservation(k).v->nr_replicas >= replicas) {
-                       bch2_btree_iter_next_slot(iter);
+                       bch2_btree_iter_advance(iter);
                        continue;
                }
 
                if (bkey_extent_is_data(k.k) &&
                    !(mode & FALLOC_FL_ZERO_RANGE)) {
-                       bch2_btree_iter_next_slot(iter);
+                       bch2_btree_iter_advance(iter);
                        continue;
                }
 
index 8c6627907431db1913f85413046febc60f2073b2..102bd3c9d30fca21d10dc3c8cab8b7edd0611b1e 100644 (file)
@@ -519,7 +519,7 @@ again:
                if (k.k->p.snapshot == snapshot &&
                    k.k->type != KEY_TYPE_inode &&
                    !bch2_btree_key_cache_find(c, BTREE_ID_inodes, SPOS(0, pos, snapshot))) {
-                       bch2_btree_iter_next(iter);
+                       bch2_btree_iter_advance(iter);
                        continue;
                }
 
index f80b3ce4c7d77f6bd63655bc40eb99c8f475b7f6..5ff8fea80fbaf2fb77be6a4c661955d7f426972a 100644 (file)
@@ -245,8 +245,12 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
                         * writing to, because i_size could be up to one block
                         * less:
                         */
-                       if (!bkey_cmp(old.k->p, new->k.p))
+                       if (!bkey_cmp(old.k->p, new->k.p)) {
                                old = bch2_btree_iter_next(iter);
+                               ret = bkey_err(old);
+                               if (ret)
+                                       break;
+                       }
 
                        if (old.k && !bkey_err(old) &&
                            old.k->p.inode == extent_iter->pos.inode &&
index 3069f32efddddf3f707309f728071908a256fa55..7dea6637ae58ecc058174a031ca2830580350892 100644 (file)
@@ -190,7 +190,7 @@ nomatch:
                }
                atomic_long_inc(&c->extent_migrate_raced);
                trace_move_race(&new->k);
-               bch2_btree_iter_next_slot(iter);
+               bch2_btree_iter_advance(iter);
                goto next;
        }
 out:
index ebf391245470f2b2e49a528ade8c1715791f861d..8b168246ca38555ac0fcd26e06b8d8743404dcf4 100644 (file)
@@ -192,8 +192,9 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end)
                        return k;
        }
 
-       bch2_btree_iter_set_pos(iter, end);
-       return bkey_s_c_null;
+       if (bkey_cmp(iter->pos, end) >= 0)
+               bch2_btree_iter_set_pos(iter, end);
+       return ret ? bkey_s_c_err(ret) : bkey_s_c_null;
 }
 
 s64 bch2_remap_range(struct bch_fs *c,
index 2ff8e5bd2744b8839a1448a93055182ffc7f9478..23602349419161d7e7bd422f931a81dad44ba4e4 100644 (file)
@@ -209,7 +209,7 @@ int bch2_hash_needs_whiteout(struct btree_trans *trans,
 
        iter = bch2_trans_copy_iter(trans, start);
 
-       bch2_btree_iter_next_slot(iter);
+       bch2_btree_iter_advance(iter);
 
        for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k, ret) {
                if (k.k->type != desc.key_type &&
index d7160e8cdc070e2ad382371fb424b467721dbf51..bf4164f987435f7b1775e26d0bacb9af2140c357 100644 (file)
@@ -124,6 +124,7 @@ static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info
        struct bch_hash_info hash = bch2_hash_info_init(trans->c, &inode->ei_inode);
        struct btree_iter *iter;
        struct bkey_s_c_xattr xattr;
+       struct bkey_s_c k;
        int ret;
 
        iter = bch2_hash_lookup(trans, bch2_xattr_hash_desc, &hash,
@@ -134,7 +135,12 @@ static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info
        if (ret)
                goto err;
 
-       xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
+       k = bch2_btree_iter_peek_slot(iter);
+       ret = bkey_err(k);
+       if (ret)
+               goto err;
+
+       xattr = bkey_s_c_to_xattr(k);
        ret = le16_to_cpu(xattr.v->x_val_len);
        if (buffer) {
                if (ret > size)