diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2017-02-01 16:50:27 -0900 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2017-02-06 18:30:23 -0900 |
commit | 828602e66e34296924b246fef6b3eac291434b48 (patch) | |
tree | 9309739793e4e037f0b040380339a80f1244e4fe | |
parent | 44591aeaf65183b6a023c6f1c579241982b3c8c7 (diff) |
bcachefs: assorted refactoring for fsck
-rw-r--r-- | drivers/md/bcache/dirent.c | 49 | ||||
-rw-r--r-- | drivers/md/bcache/dirent.h | 12 | ||||
-rw-r--r-- | drivers/md/bcache/fs.c | 45 | ||||
-rw-r--r-- | drivers/md/bcache/inode.c | 32 | ||||
-rw-r--r-- | drivers/md/bcache/inode.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/str_hash.h | 8 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 7 |
7 files changed, 90 insertions, 65 deletions
diff --git a/drivers/md/bcache/dirent.c b/drivers/md/bcache/dirent.c index 920ad2f7d263..d97c3b22c361 100644 --- a/drivers/md/bcache/dirent.c +++ b/drivers/md/bcache/dirent.c @@ -10,7 +10,7 @@ #include <linux/dcache.h> -static unsigned dirent_name_bytes(struct bkey_s_c_dirent d) +unsigned bch_dirent_name_bytes(struct bkey_s_c_dirent d) { unsigned len = bkey_val_bytes(d.k) - sizeof(struct bch_dirent); @@ -61,7 +61,7 @@ static u64 dirent_hash_key(const struct bch_hash_info *info, const void *key) static u64 dirent_hash_bkey(const struct bch_hash_info *info, struct bkey_s_c k) { struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k); - struct qstr name = QSTR_INIT(d.v->d_name, dirent_name_bytes(d)); + struct qstr name = QSTR_INIT(d.v->d_name, bch_dirent_name_bytes(d)); return bch_dirent_hash(info, &name); } @@ -69,7 +69,7 @@ static u64 dirent_hash_bkey(const struct bch_hash_info *info, struct bkey_s_c k) static bool dirent_cmp_key(struct bkey_s_c _l, const void *_r) { struct bkey_s_c_dirent l = bkey_s_c_to_dirent(_l); - int len = dirent_name_bytes(l); + int len = bch_dirent_name_bytes(l); const struct qstr *r = _r; return len - r->len ?: memcmp(l.v->d_name, r->name, len); @@ -79,8 +79,8 @@ static bool dirent_cmp_bkey(struct bkey_s_c _l, struct bkey_s_c _r) { struct bkey_s_c_dirent l = bkey_s_c_to_dirent(_l); struct bkey_s_c_dirent r = bkey_s_c_to_dirent(_r); - int l_len = dirent_name_bytes(l); - int r_len = dirent_name_bytes(r); + int l_len = bch_dirent_name_bytes(l); + int r_len = bch_dirent_name_bytes(r); return l_len - r_len ?: memcmp(l.v->d_name, r.v->d_name, l_len); } @@ -125,7 +125,7 @@ static void bch_dirent_to_text(struct cache_set *c, char *buf, if (size) { unsigned n = min_t(unsigned, size, - dirent_name_bytes(d)); + bch_dirent_name_bytes(d)); memcpy(buf, d.v->d_name, n); buf[size - 1] = '\0'; buf += n; @@ -167,15 +167,16 @@ static struct bkey_i_dirent *dirent_create_key(u8 type, bkey_val_bytes(&dirent->k) - (sizeof(struct bch_dirent) + name->len)); - EBUG_ON(dirent_name_bytes(dirent_i_to_s_c(dirent)) != name->len); + EBUG_ON(bch_dirent_name_bytes(dirent_i_to_s_c(dirent)) != name->len); return dirent; } -int bch_dirent_create(struct cache_set *c, struct inode *dir, u8 type, - const struct qstr *name, u64 dst_inum) +int bch_dirent_create(struct cache_set *c, u64 dir_inum, + const struct bch_hash_info *hash_info, + u8 type, const struct qstr *name, u64 dst_inum, + u64 *journal_seq, int flags) { - struct bch_inode_info *ei = to_bch_ei(dir); struct bkey_i_dirent *dirent; int ret; @@ -183,9 +184,8 @@ int bch_dirent_create(struct cache_set *c, struct inode *dir, u8 type, if (!dirent) return -ENOMEM; - ret = bch_hash_set(dirent_hash_desc, &ei->str_hash, c, - ei->vfs_inode.i_ino, &ei->journal_seq, - &dirent->k_i, BCH_HASH_SET_MUST_CREATE); + ret = bch_hash_set(dirent_hash_desc, hash_info, c, dir_inum, + journal_seq, &dirent->k_i, flags); kfree(dirent); return ret; @@ -346,26 +346,25 @@ err: return ret; } -int bch_dirent_delete(struct cache_set *c, struct inode *dir, - const struct qstr *name) +int bch_dirent_delete(struct cache_set *c, u64 dir_inum, + const struct bch_hash_info *hash_info, + const struct qstr *name, + u64 *journal_seq) { - struct bch_inode_info *ei = to_bch_ei(dir); - - return bch_hash_delete(dirent_hash_desc, &ei->str_hash, - c, ei->vfs_inode.i_ino, - &ei->journal_seq, name); + return bch_hash_delete(dirent_hash_desc, hash_info, + c, dir_inum, journal_seq, name); } -u64 bch_dirent_lookup(struct cache_set *c, struct inode *dir, +u64 bch_dirent_lookup(struct cache_set *c, u64 dir_inum, + const struct bch_hash_info *hash_info, const struct qstr *name) { - struct bch_inode_info *ei = to_bch_ei(dir); struct btree_iter iter; struct bkey_s_c k; u64 inum; - k = bch_hash_lookup(dirent_hash_desc, &ei->str_hash, c, - ei->vfs_inode.i_ino, &iter, name); + k = bch_hash_lookup(dirent_hash_desc, hash_info, c, + dir_inum, &iter, name); if (IS_ERR(k.k)) { bch_btree_iter_unlock(&iter); return 0; @@ -428,7 +427,7 @@ int bch_readdir(struct cache_set *c, struct file *file, if (k.k->p.inode > inode->i_ino) break; - len = dirent_name_bytes(dirent); + len = bch_dirent_name_bytes(dirent); pr_debug("emitting %s", dirent.v->d_name); diff --git a/drivers/md/bcache/dirent.h b/drivers/md/bcache/dirent.h index e18089ba7243..cc67d55d2f18 100644 --- a/drivers/md/bcache/dirent.h +++ b/drivers/md/bcache/dirent.h @@ -7,10 +7,13 @@ struct qstr; struct file; struct dir_context; struct cache_set; +struct bch_hash_info; -int bch_dirent_create(struct cache_set *c, struct inode *, u8, - const struct qstr *, u64); -int bch_dirent_delete(struct cache_set *c, struct inode *, const struct qstr *); +unsigned bch_dirent_name_bytes(struct bkey_s_c_dirent); +int bch_dirent_create(struct cache_set *c, u64, const struct bch_hash_info *, + u8, const struct qstr *, u64, u64 *, int); +int bch_dirent_delete(struct cache_set *, u64, const struct bch_hash_info *, + const struct qstr *, u64 *); enum bch_rename_mode { BCH_RENAME, @@ -23,8 +26,9 @@ int bch_dirent_rename(struct cache_set *, struct inode *, const struct qstr *, u64 *, enum bch_rename_mode); -u64 bch_dirent_lookup(struct cache_set *c, struct inode *, +u64 bch_dirent_lookup(struct cache_set *, u64, const struct bch_hash_info *, const struct qstr *); + int bch_empty_dir(struct cache_set *, u64); int bch_readdir(struct cache_set *, struct file *, struct dir_context *); diff --git a/drivers/md/bcache/fs.c b/drivers/md/bcache/fs.c index 1f01e48882df..884a950f1f51 100644 --- a/drivers/md/bcache/fs.c +++ b/drivers/md/bcache/fs.c @@ -26,7 +26,7 @@ static struct kmem_cache *bch_inode_cache; -static void bch_inode_init(struct bch_inode_info *, struct bkey_s_c_inode); +static void bch_vfs_inode_init(struct bch_inode_info *, struct bkey_s_c_inode); /* * I_SIZE_DIRTY requires special handling: @@ -175,7 +175,7 @@ static struct inode *bch_vfs_inode_get(struct super_block *sb, u64 inum) } ei = to_bch_ei(inode); - bch_inode_init(ei, bkey_s_c_to_inode(k)); + bch_vfs_inode_init(ei, bkey_s_c_to_inode(k)); ei->journal_seq = bch_inode_journal_seq(&c->journal, inum); @@ -193,10 +193,7 @@ static struct inode *bch_vfs_inode_create(struct cache_set *c, struct inode *inode; struct posix_acl *default_acl = NULL, *acl = NULL; struct bch_inode_info *ei; - struct bch_inode *bi; struct bkey_i_inode bkey_inode; - struct timespec ts = CURRENT_TIME; - s64 now = timespec_to_ns(&ts); int ret; inode = new_inode(parent->i_sb); @@ -213,19 +210,8 @@ static struct inode *bch_vfs_inode_create(struct cache_set *c, ei = to_bch_ei(inode); - bi = &bkey_inode_init(&bkey_inode.k_i)->v; - bi->i_uid = cpu_to_le32(i_uid_read(inode)); - bi->i_gid = cpu_to_le32(i_gid_read(inode)); - - bi->i_mode = cpu_to_le16(inode->i_mode); - bi->i_dev = cpu_to_le32(rdev); - bi->i_atime = cpu_to_le64(now); - bi->i_mtime = cpu_to_le64(now); - bi->i_ctime = cpu_to_le64(now); - bi->i_nlink = cpu_to_le32(S_ISDIR(mode) ? 2 : 1); - - get_random_bytes(&bi->i_hash_seed, sizeof(bi->i_hash_seed)); - SET_INODE_STR_HASH_TYPE(bi, c->sb.str_hash_type); + bch_inode_init(c, &bkey_inode, i_uid_read(inode), + i_gid_read(inode), inode->i_mode, rdev); ret = bch_inode_create(c, &bkey_inode.k_i, BLOCKDEV_INODE_MAX, 0, @@ -239,7 +225,7 @@ static struct inode *bch_vfs_inode_create(struct cache_set *c, goto err; } - bch_inode_init(ei, inode_i_to_s_c(&bkey_inode)); + bch_vfs_inode_init(ei, inode_i_to_s_c(&bkey_inode)); if (default_acl) { ret = bch_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); @@ -270,9 +256,13 @@ static int bch_vfs_dirent_create(struct cache_set *c, struct inode *dir, u8 type, const struct qstr *name, struct inode *dst) { + struct bch_inode_info *dir_ei = to_bch_ei(dir); int ret; - ret = bch_dirent_create(c, dir, type, name, dst->i_ino); + ret = bch_dirent_create(c, dir->i_ino, &dir_ei->str_hash, + type, name, dst->i_ino, + &dir_ei->journal_seq, + BCH_HASH_SET_MUST_CREATE); if (unlikely(ret)) return ret; @@ -317,10 +307,13 @@ static struct dentry *bch_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct cache_set *c = dir->i_sb->s_fs_info; + struct bch_inode_info *dir_ei = to_bch_ei(dir); struct inode *inode = NULL; u64 inum; - inum = bch_dirent_lookup(c, dir, &dentry->d_name); + inum = bch_dirent_lookup(c, dir->i_ino, + &dir_ei->str_hash, + &dentry->d_name); if (inum) inode = bch_vfs_inode_get(dir->i_sb, inum); @@ -374,7 +367,8 @@ static int bch_unlink(struct inode *dir, struct dentry *dentry) lockdep_assert_held(&inode->i_rwsem); - ret = bch_dirent_delete(c, dir, &dentry->d_name); + ret = bch_dirent_delete(c, dir->i_ino, &dir_ei->str_hash, + &dentry->d_name, &dir_ei->journal_seq); if (ret) return ret; @@ -1016,8 +1010,8 @@ static const struct address_space_operations bch_address_space_operations = { .error_remove_page = generic_error_remove_page, }; -static void bch_inode_init(struct bch_inode_info *ei, - struct bkey_s_c_inode bkey_inode) +static void bch_vfs_inode_init(struct bch_inode_info *ei, + struct bkey_s_c_inode bkey_inode) { struct inode *inode = &ei->vfs_inode; const struct bch_inode *bi = bkey_inode.v; @@ -1044,8 +1038,7 @@ static void bch_inode_init(struct bch_inode_info *ei, inode->i_ctime = ns_to_timespec(le64_to_cpu(bi->i_ctime)); bch_inode_flags_to_vfs(inode); - ei->str_hash.seed = le64_to_cpu(bi->i_hash_seed); - ei->str_hash.type = INODE_STR_HASH_TYPE(bi); + ei->str_hash = bch_hash_info_init(bi); inode->i_mapping->a_ops = &bch_address_space_operations; diff --git a/drivers/md/bcache/inode.c b/drivers/md/bcache/inode.c index d36de43cdfc3..200deb0e60e1 100644 --- a/drivers/md/bcache/inode.c +++ b/drivers/md/bcache/inode.c @@ -7,6 +7,8 @@ #include "io.h" #include "keylist.h" +#include <linux/random.h> + ssize_t bch_inode_status(char *buf, size_t len, const struct bkey *k) { if (k->p.offset) @@ -105,6 +107,28 @@ const struct bkey_ops bch_bkey_inode_ops = { .val_to_text = bch_inode_to_text, }; +void bch_inode_init(struct cache_set *c, struct bkey_i_inode *inode, + uid_t uid, gid_t gid, umode_t mode, dev_t rdev) +{ + struct timespec ts = CURRENT_TIME; + s64 now = timespec_to_ns(&ts); + struct bch_inode *bi; + + bi = &bkey_inode_init(&inode->k_i)->v; + bi->i_uid = cpu_to_le32(uid); + bi->i_gid = cpu_to_le32(gid); + + bi->i_mode = cpu_to_le16(mode); + bi->i_dev = cpu_to_le32(rdev); + bi->i_atime = cpu_to_le64(now); + bi->i_mtime = cpu_to_le64(now); + bi->i_ctime = cpu_to_le64(now); + bi->i_nlink = cpu_to_le32(S_ISDIR(mode) ? 2 : 1); + + get_random_bytes(&bi->i_hash_seed, sizeof(bi->i_hash_seed)); + SET_INODE_STR_HASH_TYPE(bi, c->sb.str_hash_type); +} + int bch_inode_create(struct cache_set *c, struct bkey_i *inode, u64 min, u64 max, u64 *hint) { @@ -228,15 +252,14 @@ int bch_inode_find_by_inum(struct cache_set *c, u64 inode_nr, { struct btree_iter iter; struct bkey_s_c k; - int ret = -ENOENT; for_each_btree_key_with_holes(&iter, c, BTREE_ID_INODES, POS(inode_nr, 0), k) { switch (k.k->type) { case BCH_INODE_FS: - ret = 0; bkey_reassemble(&inode->k_i, k); - break; + bch_btree_iter_unlock(&iter); + return 0; default: /* hole, not found */ break; @@ -245,9 +268,8 @@ int bch_inode_find_by_inum(struct cache_set *c, u64 inode_nr, break; } - bch_btree_iter_unlock(&iter); - return ret; + return bch_btree_iter_unlock(&iter) ?: -ENOENT; } int bch_cached_dev_inode_find_by_uuid(struct cache_set *c, uuid_le *uuid, diff --git a/drivers/md/bcache/inode.h b/drivers/md/bcache/inode.h index d8b28c78c277..fa1a4cf9cb7b 100644 --- a/drivers/md/bcache/inode.h +++ b/drivers/md/bcache/inode.h @@ -5,6 +5,8 @@ extern const struct bkey_ops bch_bkey_inode_ops; ssize_t bch_inode_status(char *, size_t, const struct bkey *); +void bch_inode_init(struct cache_set *, struct bkey_i_inode *, + uid_t, gid_t, umode_t, dev_t); int bch_inode_create(struct cache_set *, struct bkey_i *, u64, u64, u64 *); int bch_inode_truncate(struct cache_set *, u64, u64, struct extent_insert_hook *, u64 *); diff --git a/drivers/md/bcache/str_hash.h b/drivers/md/bcache/str_hash.h index 9a718a8e9eaa..a489304ce2e6 100644 --- a/drivers/md/bcache/str_hash.h +++ b/drivers/md/bcache/str_hash.h @@ -79,6 +79,14 @@ struct bch_hash_info { u8 type; }; +static inline struct bch_hash_info bch_hash_info_init(const struct bch_inode *bi) +{ + return (struct bch_hash_info) { + .seed = le64_to_cpu(bi->i_hash_seed), + .type = INODE_STR_HASH_TYPE(bi), + }; +} + struct bch_hash_desc { enum btree_id btree_id; u8 key_type; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 5f6a85e3c63a..798651ee54b1 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1433,12 +1433,9 @@ static const char *run_cache_set(struct cache_set *c) /* Wait for new btree roots to be written: */ closure_sync(&cl); - bkey_inode_init(&inode.k_i); + bch_inode_init(c, &inode, 0, 0, + S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO, 0); inode.k.p.inode = BCACHE_ROOT_INO; - inode.v.i_mode = cpu_to_le16(S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO); - inode.v.i_nlink = cpu_to_le32(2); - get_random_bytes(&inode.v.i_hash_seed, sizeof(inode.v.i_hash_seed)); - SET_INODE_STR_HASH_TYPE(&inode.v, c->sb.str_hash_type); err = "error creating root directory"; if (bch_btree_insert(c, BTREE_ID_INODES, &inode.k_i, |