summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-08-06 03:02:18 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-09-25 06:00:44 -0800
commit5c0dc2453210037dc913e2e1f99db823fbb85099 (patch)
tree9f4ce5748f889066cf0939fb29d74a9b27295c92
parent0faa1ccc5ff4a29ac3cd0d561d9ceec5cbbe3e61 (diff)
bcachefs: inode optional fields
-rw-r--r--drivers/md/bcache/fs-gc.c12
-rw-r--r--drivers/md/bcache/fs.c7
-rw-r--r--drivers/md/bcache/inode.c37
-rw-r--r--drivers/md/bcache/inode.h21
-rw-r--r--include/uapi/linux/bcache.h30
5 files changed, 96 insertions, 11 deletions
diff --git a/drivers/md/bcache/fs-gc.c b/drivers/md/bcache/fs-gc.c
index 53c7ec0283a9..329791198697 100644
--- a/drivers/md/bcache/fs-gc.c
+++ b/drivers/md/bcache/fs-gc.c
@@ -212,7 +212,7 @@ static int bch_gc_do_inode(struct cache_set *c, struct btree_iter *iter,
if (i_nlink != real_i_nlink||
i_flags & BCH_INODE_I_SECTORS_DIRTY ||
i_flags & BCH_INODE_I_SIZE_DIRTY) {
- struct bkey_i_inode update;
+ struct bkey_inode_buf update;
bkey_reassemble(&update.k_i, inode.s_c);
update.v.i_nlink = cpu_to_le32(real_i_nlink);
@@ -338,7 +338,7 @@ int bch_gc_inode_nlinks(struct cache_set *c)
static inline bool next_inode(struct cache_set *c, u64 inum,
u64 *cur_inum,
- struct bkey_i_inode *inode,
+ struct bch_inode *inode,
struct bch_inode **bi,
u64 *i_size, u16 *i_mode)
{
@@ -346,9 +346,9 @@ static inline bool next_inode(struct cache_set *c, u64 inum,
return false;
if (!bch_inode_find_by_inum(c, inum, inode)) {
- *i_mode = le16_to_cpu(inode->v.i_mode);
- *i_size = le64_to_cpu(inode->v.i_size);
- *bi = &inode->v;
+ *i_mode = le16_to_cpu(inode->i_mode);
+ *i_size = le64_to_cpu(inode->i_size);
+ *bi = inode;
} else {
*bi = NULL;
}
@@ -367,7 +367,7 @@ void bch_fsck(struct cache_set *c)
{
struct btree_iter iter;
struct bkey_s_c k;
- struct bkey_i_inode inode;
+ struct bch_inode inode;
struct bch_inode *bi = NULL;
struct bkey_s_c_dirent d;
u64 i_size = 0;
diff --git a/drivers/md/bcache/fs.c b/drivers/md/bcache/fs.c
index 9415e3fc12b3..21fa1107b571 100644
--- a/drivers/md/bcache/fs.c
+++ b/drivers/md/bcache/fs.c
@@ -62,7 +62,7 @@ int __must_check __bch_write_inode(struct cache_set *c,
{
struct btree_iter iter;
struct inode *inode = &ei->vfs_inode;
- struct bkey_i_inode new_inode;
+ struct bkey_inode_buf new_inode;
struct bch_inode *bi;
u64 inum = inode->i_ino;
int ret;
@@ -1019,6 +1019,7 @@ static void bch_inode_init(struct bch_inode_info *ei,
{
struct inode *inode = &ei->vfs_inode;
const struct bch_inode *bi = bkey_inode.v;
+ struct inode_opt_fields f = bch_inode_opt_fields_get(bi);
pr_debug("init inode %llu with mode %o",
bkey_inode.k->p.inode, bi->i_mode);
@@ -1045,6 +1046,10 @@ static void bch_inode_init(struct bch_inode_info *ei,
ei->str_hash.seed = le64_to_cpu(bi->i_hash_seed);
ei->str_hash.type = INODE_STR_HASH_TYPE(bi);
+ inode->i_generation = f.i_generation
+ ? le64_to_cpu(f.i_generation->v)
+ : 0;
+
inode->i_mapping->a_ops = &bch_address_space_operations;
switch (inode->i_mode & S_IFMT) {
diff --git a/drivers/md/bcache/inode.c b/drivers/md/bcache/inode.c
index 7cbe9b5dc757..c138c5424c1d 100644
--- a/drivers/md/bcache/inode.c
+++ b/drivers/md/bcache/inode.c
@@ -221,7 +221,7 @@ int bch_inode_update(struct cache_set *c, struct bkey_i *inode,
}
int bch_inode_find_by_inum(struct cache_set *c, u64 inode_nr,
- struct bkey_i_inode *inode)
+ struct bch_inode *inode)
{
struct btree_iter iter;
struct bkey_s_c k;
@@ -232,7 +232,7 @@ int bch_inode_find_by_inum(struct cache_set *c, u64 inode_nr,
switch (k.k->type) {
case BCH_INODE_FS:
ret = 0;
- bkey_reassemble(&inode->k_i, k);
+ *inode = *bkey_s_c_to_inode(k).v;
break;
default:
/* hole, not found */
@@ -278,3 +278,36 @@ int bch_cached_dev_inode_find_by_uuid(struct cache_set *c, uuid_le *uuid,
bch_btree_iter_unlock(&iter);
return -ENOENT;
}
+
+struct inode_opt_fields bch_inode_opt_fields_get(const struct bch_inode *inode)
+{
+ size_t offset = sizeof(struct bch_inode);
+ struct inode_opt_fields ret;
+
+#define walk_field(_field, _field_size) \
+ do { \
+ if (le32_to_cpu(inode->i_flags) & \
+ (1 << __BCH_INODE_##_field)) { \
+ struct bch_inode_##_field *field = \
+ (void *) inode + offset; \
+ size_t size = _field_size; \
+ \
+ ret._field = field; \
+ \
+ EBUG_ON(size & 7); \
+ offset += size; \
+ } else { \
+ ret._field = NULL; \
+ } \
+ } while (0)
+
+#define walk_constant_size_field(_field) \
+ walk_field(_field, sizeof(*field))
+
+ walk_constant_size_field(i_generation);
+ walk_constant_size_field(long_times);
+#undef walk_field
+#undef walk_constant_size_field
+
+ return ret;
+}
diff --git a/drivers/md/bcache/inode.h b/drivers/md/bcache/inode.h
index a89064a37861..49849e31a0fa 100644
--- a/drivers/md/bcache/inode.h
+++ b/drivers/md/bcache/inode.h
@@ -10,10 +10,29 @@ 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 *);
int bch_inode_rm(struct cache_set *, u64);
+
int bch_inode_update(struct cache_set *, struct bkey_i *, u64 *);
-int bch_inode_find_by_inum(struct cache_set *, u64, struct bkey_i_inode *);
+int bch_inode_find_by_inum(struct cache_set *, u64, struct bch_inode *);
int bch_cached_dev_inode_find_by_uuid(struct cache_set *, uuid_le *,
struct bkey_i_inode_blockdev *);
+struct inode_opt_fields {
+ const struct bch_inode_i_generation *i_generation;
+ const struct bch_inode_long_times *long_times;
+};
+
+/*
+ * This is just to provide a buffer that has enough space for an inode with all
+ * optional fields - it is not to be used for accessing the optional fields:
+ */
+struct bkey_inode_buf {
+ struct bkey_i k_i;
+ struct bch_inode v;
+ struct bch_inode_i_generation __i_generation;
+ struct bch_inode_long_times __long_times;
+};
+
+struct inode_opt_fields bch_inode_opt_fields_get(const struct bch_inode *);
+
#endif
diff --git a/include/uapi/linux/bcache.h b/include/uapi/linux/bcache.h
index caa048f82020..7aa2874438f8 100644
--- a/include/uapi/linux/bcache.h
+++ b/include/uapi/linux/bcache.h
@@ -508,7 +508,7 @@ struct bch_inode {
__le32 i_dev;
__le64 i_hash_seed;
-} __attribute__((packed));
+} __attribute__((packed, aligned(8)));
BKEY_VAL_TYPE(inode, BCH_INODE_FS);
enum {
@@ -527,6 +527,10 @@ enum {
/* not implemented yet: */
__BCH_INODE_HAS_XATTRS = 7, /* has xattrs in xattr btree */
+
+ /* These flags indicate whether optional fields are present: */
+ __BCH_INODE_i_generation= 8,
+ __BCH_INODE_long_times = 9,
};
LE32_BITMASK(INODE_STR_HASH_TYPE, struct bch_inode, i_flags, 28, 32);
@@ -540,6 +544,29 @@ LE32_BITMASK(INODE_STR_HASH_TYPE, struct bch_inode, i_flags, 28, 32);
#define BCH_INODE_I_SECTORS_DIRTY (1 << __BCH_INODE_I_SECTORS_DIRTY)
#define BCH_INODE_HAS_XATTRS (1 << __BCH_INODE_HAS_XATTRS)
+/*
+ * Inode optional fields:
+ *
+ * This is the order that fields are present in:
+ * New fields must be added at the end so that old kernels can read newer
+ * inodes:
+ */
+enum bch_inode_opt_fieldnrs {
+ BCH_INODE_FIELDNR_i_generation,
+ BCH_INODE_FIELDNR_long_times,
+};
+
+struct bch_inode_i_generation {
+ __le64 v;
+} __attribute__((packed, aligned(8)));
+
+struct bch_inode_long_times {
+ __le32 i_atime_high;
+ __le32 i_ctime_high;
+ __le32 i_mtime_high;
+ __le32 pad;
+} __attribute__((packed, aligned(8)));
+
struct bch_inode_blockdev {
struct bch_val v;
@@ -557,6 +584,7 @@ BKEY_VAL_TYPE(inode_blockdev, BCH_INODE_BLOCKDEV);
/* Thin provisioned volume, or cache for another block device? */
LE64_BITMASK(CACHED_DEV, struct bch_inode_blockdev, i_flags, 0, 1)
+
/* Dirents */
/*