unsigned r_level)
{
return cmp_int(l->btree_id, r_btree_id) ?:
- cmp_int(l->cached, r_cached) ?:
+ cmp_int((int) l->cached, (int) r_cached) ?:
bpos_cmp(l->pos, r_pos) ?:
-cmp_int(l->level, r_level);
}
return ret;
}
+void bch2_assert_pos_locked(struct btree_trans *trans, enum btree_id id,
+ struct bpos pos, bool key_cache)
+{
+ struct btree_path *path;
+ unsigned idx;
+ char buf[100];
+
+ trans_for_each_path_inorder(trans, path, idx) {
+ int cmp = cmp_int(path->btree_id, id) ?:
+ cmp_int(path->cached, key_cache);
+
+ if (cmp > 0)
+ break;
+ if (cmp < 0)
+ continue;
+
+ if (!(path->nodes_locked & 1) ||
+ !path->should_be_locked)
+ continue;
+
+ if (!key_cache) {
+ if (bkey_cmp(pos, path->l[0].b->data->min_key) >= 0 &&
+ bkey_cmp(pos, path->l[0].b->key.k.p) <= 0)
+ return;
+ } else {
+ if (!bkey_cmp(pos, path->pos))
+ return;
+ }
+ }
+
+ bch2_dump_trans_paths_updates(trans);
+ panic("not locked: %s %s%s\n",
+ bch2_btree_ids[id],
+ (bch2_bpos_to_text(&PBUF(buf), pos), buf),
+ key_cache ? " cached" : "");
+}
+
#else
static inline void bch2_btree_path_verify_level(struct btree_trans *trans,
btree_trans_sort_paths(trans);
trans_for_each_path_inorder(trans, path, idx)
- printk(KERN_ERR "path: idx %u ref %u:%u%s btree %s pos %s %pS\n",
+ printk(KERN_ERR "path: idx %u ref %u:%u%s%s btree %s pos %s locks %u %pS\n",
path->idx, path->ref, path->intent_ref,
- path->preserve ? " preserve" : "",
+ path->should_be_locked ? " S" : "",
+ path->preserve ? " P" : "",
bch2_btree_ids[path->btree_id],
(bch2_bpos_to_text(&PBUF(buf1), path->pos), buf1),
+ path->nodes_locked,
#ifdef CONFIG_BCACHEFS_DEBUG
(void *) path->ip_allocated
#else
static struct kmem_cache *bch2_inode_cache;
-static void bch2_vfs_inode_init(struct bch_fs *, subvol_inum,
+static void bch2_vfs_inode_init(struct btree_trans *, subvol_inum,
struct bch_inode_info *,
struct bch_inode_unpacked *);
__pagecache_lock_get(lock, -1);
}
-void bch2_inode_update_after_write(struct bch_fs *c,
+void bch2_inode_update_after_write(struct btree_trans *trans,
struct bch_inode_info *inode,
struct bch_inode_unpacked *bi,
unsigned fields)
{
+ struct bch_fs *c = trans->c;
+
+ BUG_ON(bi->bi_inum != inode->v.i_ino);
+
+ bch2_assert_pos_locked(trans, BTREE_ID_inodes,
+ POS(0, bi->bi_inum),
+ 0 && c->opts.inodes_use_key_cache);
+
set_nlink(&inode->v, bch2_inode_nlink_get(bi));
i_uid_write(&inode->v, bi->bi_uid);
i_gid_write(&inode->v, bi->bi_gid);
int ret;
bch2_trans_init(&trans, c, 0, 512);
+ trans.ip = _RET_IP_;
retry:
bch2_trans_begin(&trans);
* this is important for inode updates via bchfs_write_index_update
*/
if (!ret)
- bch2_inode_update_after_write(c, inode, &inode_u, fields);
+ bch2_inode_update_after_write(&trans, inode, &inode_u, fields);
bch2_trans_iter_exit(&trans, &iter);
{
struct bch_inode_unpacked inode_u;
struct bch_inode_info *inode;
+ struct btree_trans trans;
int ret;
inode = to_bch_ei(iget5_locked(c->vfs_sb,
if (!(inode->v.i_state & I_NEW))
return &inode->v;
- ret = bch2_inode_find_by_inum(c, inum, &inode_u);
+ bch2_trans_init(&trans, c, 8, 0);
+ ret = lockrestart_do(&trans,
+ bch2_inode_find_by_inum_trans(&trans, inum, &inode_u));
+
+ if (!ret)
+ bch2_vfs_inode_init(&trans, inum, inode, &inode_u);
+ bch2_trans_exit(&trans);
+
if (ret) {
iget_failed(&inode->v);
return ERR_PTR(ret);
}
- bch2_vfs_inode_init(c, inum, inode, &inode_u);
-
unlock_new_inode(&inode->v);
return &inode->v;
}
if (!(flags & BCH_CREATE_TMPFILE)) {
- bch2_inode_update_after_write(c, dir, &dir_u,
+ bch2_inode_update_after_write(&trans, dir, &dir_u,
ATTR_MTIME|ATTR_CTIME);
mutex_unlock(&dir->ei_update_lock);
}
inum.subvol = inode_u.bi_subvol ?: dir->ei_subvol;
inum.inum = inode_u.bi_inum;
- bch2_vfs_inode_init(c, inum, inode, &inode_u);
+ bch2_iget5_set(&inode->v, &inum);
+ bch2_vfs_inode_init(&trans, inum, inode, &inode_u);
set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl);
set_cached_acl(&inode->v, ACL_TYPE_DEFAULT, default_acl);
&dentry->d_name));
if (likely(!ret)) {
- BUG_ON(inode_u.bi_inum != inode->v.i_ino);
-
- bch2_inode_update_after_write(c, dir, &dir_u,
+ bch2_inode_update_after_write(&trans, dir, &dir_u,
ATTR_MTIME|ATTR_CTIME);
- bch2_inode_update_after_write(c, inode, &inode_u, ATTR_CTIME);
+ bch2_inode_update_after_write(&trans, inode, &inode_u, ATTR_CTIME);
}
bch2_trans_exit(&trans);
deleting_snapshot));
if (likely(!ret)) {
- BUG_ON(inode_u.bi_inum != inode->v.i_ino);
-
- bch2_inode_update_after_write(c, dir, &dir_u,
+ bch2_inode_update_after_write(&trans, dir, &dir_u,
ATTR_MTIME|ATTR_CTIME);
- bch2_inode_update_after_write(c, inode, &inode_u,
+ bch2_inode_update_after_write(&trans, inode, &inode_u,
ATTR_MTIME);
}
BUG_ON(dst_inode &&
dst_inode->v.i_ino != dst_inode_u.bi_inum);
- bch2_inode_update_after_write(c, src_dir, &src_dir_u,
+ bch2_inode_update_after_write(&trans, src_dir, &src_dir_u,
ATTR_MTIME|ATTR_CTIME);
if (src_dir != dst_dir)
- bch2_inode_update_after_write(c, dst_dir, &dst_dir_u,
+ bch2_inode_update_after_write(&trans, dst_dir, &dst_dir_u,
ATTR_MTIME|ATTR_CTIME);
- bch2_inode_update_after_write(c, src_inode, &src_inode_u,
+ bch2_inode_update_after_write(&trans, src_inode, &src_inode_u,
ATTR_CTIME);
if (dst_inode)
- bch2_inode_update_after_write(c, dst_inode, &dst_inode_u,
+ bch2_inode_update_after_write(&trans, dst_inode, &dst_inode_u,
ATTR_CTIME);
err:
bch2_trans_exit(&trans);
if (unlikely(ret))
goto err_trans;
- bch2_inode_update_after_write(c, inode, &inode_u, attr->ia_valid);
+ bch2_inode_update_after_write(&trans, inode, &inode_u, attr->ia_valid);
if (acl)
set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl);
//.get_parent = bch2_get_parent,
};
-static void bch2_vfs_inode_init(struct bch_fs *c, subvol_inum inum,
+static void bch2_vfs_inode_init(struct btree_trans *trans, subvol_inum inum,
struct bch_inode_info *inode,
struct bch_inode_unpacked *bi)
{
- bch2_inode_update_after_write(c, inode, bi, ~0);
+ bch2_inode_update_after_write(trans, inode, bi, ~0);
inode->v.i_blocks = bi->bi_sectors;
inode->v.i_ino = bi->bi_inum;