diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-07-12 19:19:41 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-07-16 03:57:04 -0400 |
commit | a7085af10324dff3d4e14bf40b3a29f046a01d06 (patch) | |
tree | a7ba8a7930ecfa85c2dbf5dafb7774cdb2d1ae88 | |
parent | 39421559084438cecb4de77dc04945653debf00a (diff) |
bcachefs: Convert raw uses of bch2_btree_iter_link() to new transactions
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/fs-io.c | 84 | ||||
-rw-r--r-- | fs/bcachefs/fsck.c | 139 |
2 files changed, 130 insertions, 93 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 1a28000f20df..e4d2b39e0d82 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -390,7 +390,8 @@ static int bchfs_write_index_update(struct bch_write_op *wop) struct bchfs_write_op *op = container_of(wop, struct bchfs_write_op, op); struct keylist *keys = &op->op.insert_keys; - struct btree_iter extent_iter, inode_iter; + struct btree_trans trans; + struct btree_iter *extent_iter, *inode_iter = NULL; struct bchfs_extent_trans_hook hook; struct bkey_i *k = bch2_keylist_front(keys); s64 orig_sectors_added = op->sectors_added; @@ -398,12 +399,13 @@ static int bchfs_write_index_update(struct bch_write_op *wop) BUG_ON(k->k.p.inode != op->inode->v.i_ino); - bch2_btree_iter_init(&extent_iter, wop->c, BTREE_ID_EXTENTS, - bkey_start_pos(&bch2_keylist_front(keys)->k), - BTREE_ITER_INTENT); - bch2_btree_iter_init(&inode_iter, wop->c, BTREE_ID_INODES, - POS(extent_iter.pos.inode, 0), - BTREE_ITER_SLOTS|BTREE_ITER_INTENT); + bch2_trans_init(&trans, wop->c); + + extent_iter = bch2_trans_get_iter(&trans, + BTREE_ID_EXTENTS, + bkey_start_pos(&bch2_keylist_front(keys)->k), + BTREE_ITER_INTENT); + BUG_ON(IS_ERR(extent_iter)); hook.op = op; hook.hook.fn = bchfs_extent_update_hook; @@ -417,23 +419,28 @@ static int bchfs_write_index_update(struct bch_write_op *wop) hook.need_inode_update = true; /* optimization for fewer transaction restarts: */ - ret = bch2_btree_iter_traverse(&extent_iter); + ret = bch2_btree_iter_traverse(extent_iter); if (ret) goto err; if (hook.need_inode_update) { struct bkey_s_c inode; - if (!btree_iter_linked(&inode_iter)) - bch2_btree_iter_link(&extent_iter, &inode_iter); + if (!inode_iter) { + inode_iter = bch2_trans_get_iter(&trans, + BTREE_ID_INODES, + POS(extent_iter->pos.inode, 0), + BTREE_ITER_SLOTS|BTREE_ITER_INTENT); + BUG_ON(IS_ERR(inode_iter)); + } - inode = bch2_btree_iter_peek_slot(&inode_iter); + inode = bch2_btree_iter_peek_slot(inode_iter); if ((ret = btree_iter_err(inode))) goto err; if (WARN_ONCE(inode.k->type != BCH_INODE_FS, "inode %llu not found when updating", - extent_iter.pos.inode)) { + extent_iter->pos.inode)) { ret = -ENOENT; break; } @@ -441,7 +448,7 @@ static int bchfs_write_index_update(struct bch_write_op *wop) if (WARN_ONCE(bkey_bytes(inode.k) > sizeof(hook.inode_p), "inode %llu too big (%zu bytes, buf %zu)", - extent_iter.pos.inode, + extent_iter->pos.inode, bkey_bytes(inode.k), sizeof(hook.inode_p))) { ret = -ENOENT; @@ -453,7 +460,7 @@ static int bchfs_write_index_update(struct bch_write_op *wop) &hook.inode_u); if (WARN_ONCE(ret, "error %i unpacking inode %llu", - ret, extent_iter.pos.inode)) { + ret, extent_iter->pos.inode)) { ret = -ENOENT; break; } @@ -463,8 +470,8 @@ static int bchfs_write_index_update(struct bch_write_op *wop) BTREE_INSERT_NOFAIL| BTREE_INSERT_ATOMIC| BTREE_INSERT_USE_RESERVE, - BTREE_INSERT_ENTRY(&extent_iter, k), - BTREE_INSERT_ENTRY_EXTRA_RES(&inode_iter, + BTREE_INSERT_ENTRY(extent_iter, k), + BTREE_INSERT_ENTRY_EXTRA_RES(inode_iter, &hook.inode_p.inode.k_i, 2)); } else { ret = bch2_btree_insert_at(wop->c, &wop->res, @@ -472,10 +479,10 @@ static int bchfs_write_index_update(struct bch_write_op *wop) BTREE_INSERT_NOFAIL| BTREE_INSERT_ATOMIC| BTREE_INSERT_USE_RESERVE, - BTREE_INSERT_ENTRY(&extent_iter, k)); + BTREE_INSERT_ENTRY(extent_iter, k)); } - BUG_ON(bkey_cmp(extent_iter.pos, bkey_start_pos(&k->k))); + BUG_ON(bkey_cmp(extent_iter->pos, bkey_start_pos(&k->k))); if (WARN_ONCE(!ret != !k->k.size, "ret %i k->size %u", ret, k->k.size)) @@ -486,12 +493,11 @@ err: if (ret) break; - BUG_ON(bkey_cmp(extent_iter.pos, k->k.p) < 0); + BUG_ON(bkey_cmp(extent_iter->pos, k->k.p) < 0); bch2_keylist_pop_front(keys); } while (!bch2_keylist_empty(keys)); - bch2_btree_iter_unlock(&extent_iter); - bch2_btree_iter_unlock(&inode_iter); + bch2_trans_exit(&trans); if (op->is_dio) { struct dio_write *dio = container_of(op, struct dio_write, iop); @@ -2343,8 +2349,8 @@ static long bch2_fcollapse(struct bch_inode_info *inode, { struct bch_fs *c = inode->v.i_sb->s_fs_info; struct address_space *mapping = inode->v.i_mapping; - struct btree_iter src; - struct btree_iter dst; + struct btree_trans trans; + struct btree_iter *src, *dst; BKEY_PADDED(k) copy; struct bkey_s_c k; struct i_sectors_hook i_sectors_hook = i_sectors_hook_init(inode, 0); @@ -2354,13 +2360,17 @@ static long bch2_fcollapse(struct bch_inode_info *inode, if ((offset | len) & (block_bytes(c) - 1)) return -EINVAL; - bch2_btree_iter_init(&dst, c, BTREE_ID_EXTENTS, + bch2_trans_init(&trans, c); + + dst = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS(inode->v.i_ino, offset >> 9), BTREE_ITER_SLOTS|BTREE_ITER_INTENT); + BUG_ON(IS_ERR(dst)); + /* position will be set from dst iter's position: */ - bch2_btree_iter_init(&src, c, BTREE_ID_EXTENTS, POS_MIN, + src = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN, BTREE_ITER_SLOTS); - bch2_btree_iter_link(&src, &dst); + BUG_ON(IS_ERR(src)); /* * We need i_mutex to keep the page cache consistent with the extents @@ -2389,24 +2399,24 @@ static long bch2_fcollapse(struct bch_inode_info *inode, if (ret) goto err; - while (bkey_cmp(dst.pos, + while (bkey_cmp(dst->pos, POS(inode->v.i_ino, round_up(new_size, PAGE_SIZE) >> 9)) < 0) { struct disk_reservation disk_res; - bch2_btree_iter_set_pos(&src, - POS(dst.pos.inode, dst.pos.offset + (len >> 9))); + bch2_btree_iter_set_pos(src, + POS(dst->pos.inode, dst->pos.offset + (len >> 9))); - k = bch2_btree_iter_peek_slot(&src); + k = bch2_btree_iter_peek_slot(src); if ((ret = btree_iter_err(k))) goto btree_iter_err; bkey_reassemble(©.k, k); - bch2_cut_front(src.pos, ©.k); + bch2_cut_front(src->pos, ©.k); copy.k.k.p.offset -= len >> 9; - BUG_ON(bkey_cmp(dst.pos, bkey_start_pos(©.k.k))); + BUG_ON(bkey_cmp(dst->pos, bkey_start_pos(©.k.k))); ret = bch2_disk_reservation_get(c, &disk_res, copy.k.k.size, bch2_extent_nr_dirty_ptrs(bkey_i_to_s_c(©.k)), @@ -2417,14 +2427,13 @@ static long bch2_fcollapse(struct bch_inode_info *inode, &inode->ei_journal_seq, BTREE_INSERT_ATOMIC| BTREE_INSERT_NOFAIL, - BTREE_INSERT_ENTRY(&dst, ©.k)); + BTREE_INSERT_ENTRY(dst, ©.k)); bch2_disk_reservation_put(c, &disk_res); btree_iter_err: if (ret == -EINTR) ret = 0; if (ret) { - bch2_btree_iter_unlock(&src); - bch2_btree_iter_unlock(&dst); + bch2_trans_exit(&trans); goto err_put_sectors_dirty; } /* @@ -2432,11 +2441,10 @@ btree_iter_err: * pointers... which isn't a _super_ serious problem... */ - bch2_btree_iter_cond_resched(&src); + bch2_btree_iter_cond_resched(src); } - bch2_btree_iter_unlock(&src); - bch2_btree_iter_unlock(&dst); + bch2_trans_exit(&trans); ret = bch2_inode_truncate(c, inode->v.i_ino, round_up(new_size, block_bytes(c)) >> 9, diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index c36b32531b66..f6035cc7859a 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -126,16 +126,22 @@ static int walk_inode(struct bch_fs *c, struct inode_walker *w, u64 inum) struct hash_check { struct bch_hash_info info; - struct btree_iter chain; - struct btree_iter iter; + struct btree_trans *trans; + + /* start of current chain of hash collisions: */ + struct btree_iter *chain; + + /* next offset in current chain of hash collisions: */ u64 next; }; static void hash_check_init(const struct bch_hash_desc desc, - struct hash_check *h, struct bch_fs *c) + struct btree_trans *trans, + struct hash_check *h) { - bch2_btree_iter_init(&h->chain, c, desc.btree_id, POS_MIN, 0); - bch2_btree_iter_init(&h->iter, c, desc.btree_id, POS_MIN, 0); + h->trans = trans; + h->chain = bch2_trans_get_iter(trans, desc.btree_id, POS_MIN, 0); + h->next = -1; } static void hash_check_set_inode(struct hash_check *h, struct bch_fs *c, @@ -206,6 +212,42 @@ err: return ret; } +static int hash_check_duplicates(const struct bch_hash_desc desc, + struct hash_check *h, struct bch_fs *c, + struct btree_iter *k_iter, struct bkey_s_c k) +{ + struct btree_iter *iter; + struct bkey_s_c k2; + char buf[200]; + int ret = 0; + + if (!bkey_cmp(h->chain->pos, k_iter->pos)) + return 0; + + iter = bch2_trans_copy_iter(h->trans, h->chain); + BUG_ON(IS_ERR(iter)); + + for_each_btree_key_continue(iter, 0, k2) { + if (bkey_cmp(k2.k->p, k.k->p) >= 0) + break; + + if (fsck_err_on(k2.k->type == desc.key_type && + !desc.cmp_bkey(k, k2), c, + "duplicate hash table keys:\n%s", + (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), + buf, sizeof(buf), k), buf))) { + ret = fsck_hash_delete_at(desc, &h->info, k_iter); + if (ret) + return ret; + ret = 1; + break; + } + } +fsck_err: + bch2_trans_iter_free(h->trans, iter); + return ret; +} + static int hash_check_key(const struct bch_hash_desc desc, struct hash_check *h, struct bch_fs *c, struct btree_iter *k_iter, struct bkey_s_c k) @@ -218,13 +260,8 @@ static int hash_check_key(const struct bch_hash_desc desc, k.k->type != desc.key_type) return 0; - if (k.k->p.offset != h->next) { - if (!btree_iter_linked(&h->chain)) { - bch2_btree_iter_link(k_iter, &h->chain); - bch2_btree_iter_link(k_iter, &h->iter); - } - bch2_btree_iter_copy(&h->chain, k_iter); - } + if (k.k->p.offset != h->next) + bch2_btree_iter_copy(h->chain, k_iter); h->next = k.k->p.offset + 1; if (k.k->type != desc.key_type) @@ -232,11 +269,11 @@ static int hash_check_key(const struct bch_hash_desc desc, hashed = desc.hash_bkey(&h->info, k); - if (fsck_err_on(hashed < h->chain.pos.offset || + if (fsck_err_on(hashed < h->chain->pos.offset || hashed > k.k->p.offset, c, "hash table key at wrong offset: %llu, " "hashed to %llu chain starts at %llu\n%s", - k.k->p.offset, hashed, h->chain.pos.offset, + k.k->p.offset, hashed, h->chain->pos.offset, (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), buf, sizeof(buf), k), buf))) { ret = hash_redo_key(desc, h, c, k_iter, k, hashed); @@ -247,25 +284,7 @@ static int hash_check_key(const struct bch_hash_desc desc, return 1; } - if (!bkey_cmp(h->chain.pos, k_iter->pos)) - return 0; - - bch2_btree_iter_copy(&h->iter, &h->chain); - while (bkey_cmp(h->iter.pos, k_iter->pos) < 0) { - struct bkey_s_c k2 = bch2_btree_iter_peek(&h->iter); - - if (fsck_err_on(k2.k->type == desc.key_type && - !desc.cmp_bkey(k, k2), c, - "duplicate hash table keys:\n%s", - (bch2_bkey_val_to_text(c, bkey_type(0, desc.btree_id), - buf, sizeof(buf), k), buf))) { - ret = fsck_hash_delete_at(desc, &h->info, &h->iter); - if (ret) - return ret; - return 1; - } - bch2_btree_iter_next(&h->iter); - } + ret = hash_check_duplicates(desc, h, c, k_iter, k); fsck_err: return ret; } @@ -367,7 +386,8 @@ static int check_dirents(struct bch_fs *c) { struct inode_walker w = inode_walker_init(); struct hash_check h; - struct btree_iter iter; + struct btree_trans trans; + struct btree_iter *iter; struct bkey_s_c k; unsigned name_len; char buf[200]; @@ -375,10 +395,16 @@ static int check_dirents(struct bch_fs *c) bch_verbose(c, "checking dirents"); - hash_check_init(bch2_dirent_hash_desc, &h, c); + bch2_trans_init(&trans, c); - for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, - POS(BCACHEFS_ROOT_INO, 0), 0, k) { + BUG_ON(bch2_trans_preload_iters(&trans)); + + iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS, + POS(BCACHEFS_ROOT_INO, 0), 0); + + hash_check_init(bch2_dirent_hash_desc, &trans, &h); + + for_each_btree_key_continue(iter, 0, k) { struct bkey_s_c_dirent d; struct bch_inode_unpacked target; bool have_target; @@ -397,7 +423,7 @@ static int check_dirents(struct bch_fs *c) mode_to_type(w.inode.bi_mode), (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, buf, sizeof(buf), k), buf))) { - ret = bch2_btree_delete_at(&iter, 0); + ret = bch2_btree_delete_at(iter, 0); if (ret) goto err; continue; @@ -406,7 +432,7 @@ static int check_dirents(struct bch_fs *c) if (w.first_this_inode && w.have_inode) hash_check_set_inode(&h, c, &w.inode); - ret = hash_check_key(bch2_dirent_hash_desc, &h, c, &iter, k); + ret = hash_check_key(bch2_dirent_hash_desc, &h, c, iter, k); if (ret > 0) { ret = 0; continue; @@ -430,7 +456,7 @@ static int check_dirents(struct bch_fs *c) fsck_err_on(name_len == 2 && !memcmp(d.v->d_name, "..", 2), c, ".. dirent")) { - ret = remove_dirent(c, &iter, d); + ret = remove_dirent(c, iter, d); if (ret) goto err; continue; @@ -440,7 +466,7 @@ static int check_dirents(struct bch_fs *c) "dirent points to own directory:\n%s", (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, buf, sizeof(buf), k), buf))) { - ret = remove_dirent(c, &iter, d); + ret = remove_dirent(c, iter, d); if (ret) goto err; continue; @@ -457,7 +483,7 @@ static int check_dirents(struct bch_fs *c) "dirent points to missing inode:\n%s", (bch2_bkey_val_to_text(c, BTREE_ID_DIRENTS, buf, sizeof(buf), k), buf))) { - ret = remove_dirent(c, &iter, d); + ret = remove_dirent(c, iter, d); if (ret) goto err; continue; @@ -483,7 +509,7 @@ static int check_dirents(struct bch_fs *c) ret = bch2_btree_insert_at(c, NULL, NULL, NULL, BTREE_INSERT_NOFAIL, - BTREE_INSERT_ENTRY(&iter, &n->k_i)); + BTREE_INSERT_ENTRY(iter, &n->k_i)); kfree(n); if (ret) goto err; @@ -492,9 +518,7 @@ static int check_dirents(struct bch_fs *c) } err: fsck_err: - bch2_btree_iter_unlock(&h.chain); - bch2_btree_iter_unlock(&h.iter); - return bch2_btree_iter_unlock(&iter) ?: ret; + return bch2_trans_exit(&trans) ?: ret; } /* @@ -505,16 +529,23 @@ static int check_xattrs(struct bch_fs *c) { struct inode_walker w = inode_walker_init(); struct hash_check h; - struct btree_iter iter; + struct btree_trans trans; + struct btree_iter *iter; struct bkey_s_c k; int ret = 0; bch_verbose(c, "checking xattrs"); - hash_check_init(bch2_xattr_hash_desc, &h, c); + bch2_trans_init(&trans, c); - for_each_btree_key(&iter, c, BTREE_ID_XATTRS, - POS(BCACHEFS_ROOT_INO, 0), 0, k) { + BUG_ON(bch2_trans_preload_iters(&trans)); + + iter = bch2_trans_get_iter(&trans, BTREE_ID_XATTRS, + POS(BCACHEFS_ROOT_INO, 0), 0); + + hash_check_init(bch2_xattr_hash_desc, &trans, &h); + + for_each_btree_key_continue(iter, 0, k) { ret = walk_inode(c, &w, k.k->p.inode); if (ret) break; @@ -522,7 +553,7 @@ static int check_xattrs(struct bch_fs *c) if (fsck_err_on(!w.have_inode, c, "xattr for missing inode %llu", k.k->p.inode)) { - ret = bch2_btree_delete_at(&iter, 0); + ret = bch2_btree_delete_at(iter, 0); if (ret) goto err; continue; @@ -531,15 +562,13 @@ static int check_xattrs(struct bch_fs *c) if (w.first_this_inode && w.have_inode) hash_check_set_inode(&h, c, &w.inode); - ret = hash_check_key(bch2_xattr_hash_desc, &h, c, &iter, k); + ret = hash_check_key(bch2_xattr_hash_desc, &h, c, iter, k); if (ret) goto fsck_err; } err: fsck_err: - bch2_btree_iter_unlock(&h.chain); - bch2_btree_iter_unlock(&h.iter); - return bch2_btree_iter_unlock(&iter) ?: ret; + return bch2_trans_exit(&trans) ?: ret; } /* Get root directory, create if it doesn't exist: */ |