Skip to content

Commit 284ae18

Browse files
koverstreetKent Overstreet
authored andcommitted
bcachefs: Add subvolume to ei_inode_info
Filesystem operations generally operate within a subvolume: at the start of every btree transaction we'll be looking up (and locking) the subvolume to get the current snapshot ID, which we then use for our other btree lookups in BTREE_ITER_FILTER_SNAPSHOTS mode. But inodes don't record what subvolume they're in - they can't, because if they did we'd have to update every single inode within a subvolume when taking a snapshot in order to keep that field up to date. So it needs to be tracked in memory, based on how we got to that inode. Hence this patch adds a subvolume field to ei_inode_info, and switches to iget5() so we can index by it in the inode hash table. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 81ed9ce commit 284ae18

File tree

3 files changed

+76
-27
lines changed

3 files changed

+76
-27
lines changed

fs/bcachefs/fs-ioctl.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ static int bch2_ioc_reinherit_attrs(struct bch_fs *c,
192192
char *kname = NULL;
193193
struct qstr qstr;
194194
int ret = 0;
195-
u64 inum;
195+
subvol_inum inum = { .subvol = 1 };
196196

197197
kname = kmalloc(BCH_NAME_MAX + 1, GFP_KERNEL);
198198
if (!kname)
@@ -206,9 +206,9 @@ static int bch2_ioc_reinherit_attrs(struct bch_fs *c,
206206
qstr.name = kname;
207207

208208
ret = -ENOENT;
209-
inum = bch2_dirent_lookup(c, src->v.i_ino, &hash,
209+
inum.inum = bch2_dirent_lookup(c, src->v.i_ino, &hash,
210210
&qstr);
211-
if (!inum)
211+
if (!inum.inum)
212212
goto err1;
213213

214214
vinode = bch2_vfs_inode_get(c, inum);

fs/bcachefs/fs.c

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
static struct kmem_cache *bch2_inode_cache;
3939

40-
static void bch2_vfs_inode_init(struct bch_fs *,
40+
static void bch2_vfs_inode_init(struct bch_fs *, subvol_inum,
4141
struct bch_inode_info *,
4242
struct bch_inode_unpacked *);
4343

@@ -209,40 +209,68 @@ int bch2_fs_quota_transfer(struct bch_fs *c,
209209
return ret;
210210
}
211211

212-
struct inode *bch2_vfs_inode_get(struct bch_fs *c, u64 inum)
212+
static int bch2_iget5_test(struct inode *vinode, void *p)
213+
{
214+
struct bch_inode_info *inode = to_bch_ei(vinode);
215+
subvol_inum *inum = p;
216+
217+
return inode->ei_subvol == inum->subvol &&
218+
inode->ei_inode.bi_inum == inum->inum;
219+
}
220+
221+
static int bch2_iget5_set(struct inode *vinode, void *p)
222+
{
223+
struct bch_inode_info *inode = to_bch_ei(vinode);
224+
subvol_inum *inum = p;
225+
226+
inode->v.i_ino = inum->inum;
227+
inode->ei_subvol = inum->subvol;
228+
inode->ei_inode.bi_inum = inum->inum;
229+
return 0;
230+
}
231+
232+
static unsigned bch2_inode_hash(subvol_inum inum)
233+
{
234+
return jhash_3words(inum.subvol, inum.inum >> 32, inum.inum, JHASH_INITVAL);
235+
}
236+
237+
struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum)
213238
{
214239
struct bch_inode_unpacked inode_u;
215240
struct bch_inode_info *inode;
216241
int ret;
217242

218-
inode = to_bch_ei(iget_locked(c->vfs_sb, inum));
243+
/*
244+
* debug assert, to be removed when we start creating
245+
* subvolumes/snapshots:
246+
*/
247+
BUG_ON(inum.subvol != BCACHEFS_ROOT_SUBVOL);
248+
249+
inode = to_bch_ei(iget5_locked(c->vfs_sb,
250+
bch2_inode_hash(inum),
251+
bch2_iget5_test,
252+
bch2_iget5_set,
253+
&inum));
219254
if (unlikely(!inode))
220255
return ERR_PTR(-ENOMEM);
221256
if (!(inode->v.i_state & I_NEW))
222257
return &inode->v;
223258

224-
ret = bch2_inode_find_by_inum(c, inum, &inode_u);
259+
ret = bch2_inode_find_by_inum(c, inum.inum, &inode_u);
225260
if (ret) {
226261
iget_failed(&inode->v);
227262
return ERR_PTR(ret);
228263
}
229264

230-
bch2_vfs_inode_init(c, inode, &inode_u);
265+
bch2_vfs_inode_init(c, inum, inode, &inode_u);
231266

232-
inode->ei_journal_seq = bch2_inode_journal_seq(&c->journal, inum);
267+
inode->ei_journal_seq = bch2_inode_journal_seq(&c->journal, inum.inum);
233268

234269
unlock_new_inode(&inode->v);
235270

236271
return &inode->v;
237272
}
238273

239-
static int inum_test(struct inode *inode, void *p)
240-
{
241-
unsigned long *ino = p;
242-
243-
return *ino == inode->i_ino;
244-
}
245-
246274
static struct bch_inode_info *
247275
__bch2_create(struct mnt_idmap *idmap,
248276
struct bch_inode_info *dir, struct dentry *dentry,
@@ -254,6 +282,7 @@ __bch2_create(struct mnt_idmap *idmap,
254282
struct bch_inode_info *inode, *old;
255283
struct bch_inode_unpacked inode_u;
256284
struct posix_acl *default_acl = NULL, *acl = NULL;
285+
subvol_inum inum;
257286
u64 journal_seq = 0;
258287
int ret;
259288

@@ -310,7 +339,10 @@ __bch2_create(struct mnt_idmap *idmap,
310339
mutex_unlock(&dir->ei_update_lock);
311340
}
312341

313-
bch2_vfs_inode_init(c, inode, &inode_u);
342+
inum.subvol = inode_u.bi_subvol ?: dir->ei_subvol;
343+
inum.inum = inode_u.bi_inum;
344+
345+
bch2_vfs_inode_init(c, inum, inode, &inode_u);
314346
journal_seq_copy(c, inode, journal_seq);
315347

316348
set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl);
@@ -323,8 +355,12 @@ __bch2_create(struct mnt_idmap *idmap,
323355
*/
324356

325357
inode->v.i_state |= I_CREATING;
326-
old = to_bch_ei(inode_insert5(&inode->v, inode->v.i_ino,
327-
inum_test, NULL, &inode->v.i_ino));
358+
359+
old = to_bch_ei(inode_insert5(&inode->v,
360+
bch2_inode_hash(inum),
361+
bch2_iget5_test,
362+
bch2_iget5_set,
363+
&inum));
328364
BUG_ON(!old);
329365

330366
if (unlikely(old != inode)) {
@@ -370,12 +406,12 @@ static struct dentry *bch2_lookup(struct inode *vdir, struct dentry *dentry,
370406
struct bch_inode_info *dir = to_bch_ei(vdir);
371407
struct bch_hash_info hash = bch2_hash_info_init(c, &dir->ei_inode);
372408
struct inode *vinode = NULL;
373-
u64 inum;
409+
subvol_inum inum = { .subvol = 1 };
374410

375-
inum = bch2_dirent_lookup(c, dir->v.i_ino, &hash,
411+
inum.inum = bch2_dirent_lookup(c, dir->v.i_ino, &hash,
376412
&dentry->d_name);
377413

378-
if (inum)
414+
if (inum.inum)
379415
vinode = bch2_vfs_inode_get(c, inum);
380416

381417
return d_splice_alias(vinode, dentry);
@@ -1098,6 +1134,7 @@ static const struct address_space_operations bch_address_space_operations = {
10981134
.error_remove_page = generic_error_remove_page,
10991135
};
11001136

1137+
#if 0
11011138
static struct inode *bch2_nfs_get_inode(struct super_block *sb,
11021139
u64 ino, u32 generation)
11031140
{
@@ -1131,14 +1168,15 @@ static struct dentry *bch2_fh_to_parent(struct super_block *sb, struct fid *fid,
11311168
return generic_fh_to_parent(sb, fid, fh_len, fh_type,
11321169
bch2_nfs_get_inode);
11331170
}
1171+
#endif
11341172

11351173
static const struct export_operations bch_export_ops = {
1136-
.fh_to_dentry = bch2_fh_to_dentry,
1137-
.fh_to_parent = bch2_fh_to_parent,
1174+
//.fh_to_dentry = bch2_fh_to_dentry,
1175+
//.fh_to_parent = bch2_fh_to_parent,
11381176
//.get_parent = bch2_get_parent,
11391177
};
11401178

1141-
static void bch2_vfs_inode_init(struct bch_fs *c,
1179+
static void bch2_vfs_inode_init(struct bch_fs *c, subvol_inum inum,
11421180
struct bch_inode_info *inode,
11431181
struct bch_inode_unpacked *bi)
11441182
{
@@ -1154,6 +1192,7 @@ static void bch2_vfs_inode_init(struct bch_fs *c,
11541192
inode->ei_journal_seq = 0;
11551193
inode->ei_quota_reserved = 0;
11561194
inode->ei_qid = bch_qid(bi);
1195+
inode->ei_subvol = inum.subvol;
11571196

11581197
inode->v.i_mapping->a_ops = &bch_address_space_operations;
11591198

@@ -1595,7 +1634,7 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type,
15951634
sb->s_flags |= SB_POSIXACL;
15961635
#endif
15971636

1598-
vinode = bch2_vfs_inode_get(c, BCACHEFS_ROOT_INO);
1637+
vinode = bch2_vfs_inode_get(c, BCACHEFS_ROOT_SUBVOL_INUM);
15991638
if (IS_ERR(vinode)) {
16001639
bch_err(c, "error mounting: error getting root inode %i",
16011640
(int) PTR_ERR(vinode));

fs/bcachefs/fs.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,20 @@ struct bch_inode_info {
4444
struct mutex ei_quota_lock;
4545
struct bch_qid ei_qid;
4646

47+
u32 ei_subvol;
48+
4749
/* copy of inode in btree: */
4850
struct bch_inode_unpacked ei_inode;
4951
};
5052

53+
static inline subvol_inum inode_inum(struct bch_inode_info *inode)
54+
{
55+
return (subvol_inum) {
56+
.subvol = inode->ei_subvol,
57+
.inum = inode->ei_inode.bi_inum,
58+
};
59+
}
60+
5161
/*
5262
* Set if we've gotten a btree error for this inode, and thus the vfs inode and
5363
* btree inode may be inconsistent:
@@ -153,7 +163,7 @@ static inline int bch2_set_projid(struct bch_fs *c,
153163
KEY_TYPE_QUOTA_PREALLOC);
154164
}
155165

156-
struct inode *bch2_vfs_inode_get(struct bch_fs *, u64);
166+
struct inode *bch2_vfs_inode_get(struct bch_fs *, subvol_inum);
157167

158168
/* returns 0 if we want to do the update, or error is passed up */
159169
typedef int (*inode_set_fn)(struct bch_inode_info *,

0 commit comments

Comments
 (0)