summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2017-02-01 16:50:27 -0900
committerKent Overstreet <kent.overstreet@gmail.com>2017-02-06 18:30:23 -0900
commit828602e66e34296924b246fef6b3eac291434b48 (patch)
tree9309739793e4e037f0b040380339a80f1244e4fe
parent44591aeaf65183b6a023c6f1c579241982b3c8c7 (diff)
bcachefs: assorted refactoring for fsck
-rw-r--r--drivers/md/bcache/dirent.c49
-rw-r--r--drivers/md/bcache/dirent.h12
-rw-r--r--drivers/md/bcache/fs.c45
-rw-r--r--drivers/md/bcache/inode.c32
-rw-r--r--drivers/md/bcache/inode.h2
-rw-r--r--drivers/md/bcache/str_hash.h8
-rw-r--r--drivers/md/bcache/super.c7
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,