From 2fbc135a48aa9fe25346114e6dca2c6805e6c3b2 Mon Sep 17 00:00:00 2001 From: "Bryant G. Duffy-Ly" Date: Fri, 7 Jan 2022 08:03:43 -0600 Subject: [PATCH] Initial support for different inode sizes We're about to increase the inode size and increment the format version. Inode reading and writing has to handle different valid inode sizes as allowed by the format version. This is the initial skeletal work that later patches which really increase the inode size will further refine to add the specific known sizes and format versions. Signed-off-by: Bryant G. Duffy-Ly [zab@versity.com: reworded description, reworked to use _within] Signed-off-by: Zach Brown --- kmod/src/inode.c | 58 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 9d22f52a..83225ced 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -281,6 +281,30 @@ void scoutfs_inode_init_key(struct scoutfs_key *key, u64 ino) }; } +/* Returns the max inode size given format version */ +static int max_inode_fmt_ver_bytes(struct super_block *sb) +{ + return sizeof(struct scoutfs_inode); +} + +/* + * Read an inode item into the caller's buffer and return the size that + * we read. Returns errors if the inode size is unsupported or doesn't + * make sense for the format version. + */ +static int lookup_inode_item(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_inode *sinode, struct scoutfs_lock *lock) +{ + int inode_bytes = max_inode_fmt_ver_bytes(sb); + int ret; + + ret = scoutfs_item_lookup_within(sb, key, sinode, sizeof(struct scoutfs_inode), lock); + if (ret >= 0 && ret != inode_bytes) + return -EIO; + + return ret; +} + /* * Refresh the vfs inode fields if the lock indicates that the current * contents could be stale. @@ -316,13 +340,13 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock) mutex_lock(&si->item_mutex); if (atomic64_read(&si->last_refreshed) < refresh_gen) { - ret = scoutfs_item_lookup_exact(sb, &key, &sinode, - sizeof(sinode), lock); - if (ret == 0) { - load_inode(inode, &sinode); + ret = lookup_inode_item(sb, &key, &sinode, lock); + if (ret > 0) { + load_inode(inode, &sinode, ret); atomic64_set(&si->last_refreshed, refresh_gen); scoutfs_lock_add_coverage(sb, lock, &si->ino_lock_cov); si->drop_invalidated = false; + ret = 0; } } else { ret = 0; @@ -828,13 +852,15 @@ int scoutfs_dirty_inode_item(struct inode *inode, struct scoutfs_lock *lock) struct super_block *sb = inode->i_sb; struct scoutfs_inode sinode; struct scoutfs_key key; + int inode_bytes; int ret; - store_inode(&sinode, inode); + inode_bytes = max_inode_fmt_ver_bytes(sb); + store_inode(&sinode, inode, inode_bytes); scoutfs_inode_init_key(&key, scoutfs_ino(inode)); - ret = scoutfs_item_update(sb, &key, &sinode, sizeof(sinode), lock); + ret = scoutfs_item_update(sb, &key, &sinode, inode_bytes, lock); if (!ret) trace_scoutfs_dirty_inode(inode); return ret; @@ -1035,8 +1061,9 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock, struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; const u64 ino = scoutfs_ino(inode); - struct scoutfs_key key; struct scoutfs_inode sinode; + struct scoutfs_key key; + int inode_bytes; int ret; int err; @@ -1045,15 +1072,17 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock, /* set the meta version once per trans for any inode updates */ scoutfs_inode_set_meta_seq(inode); + inode_bytes = max_inode_fmt_ver_bytes(sb); + /* only race with other inode field stores once */ - store_inode(&sinode, inode); + store_inode(&sinode, inode, inode_bytes); ret = update_indices(sb, si, ino, inode->i_mode, &sinode, lock_list); BUG_ON(ret); scoutfs_inode_init_key(&key, ino); - err = scoutfs_item_update(sb, &key, &sinode, sizeof(sinode), lock); + err = scoutfs_item_update(sb, &key, &sinode, inode_bytes, lock); if (err) { scoutfs_err(sb, "inode %llu update err %d", ino, err); BUG_ON(err); @@ -1421,9 +1450,10 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d u64 ino, struct scoutfs_lock *lock, struct inode **inode_ret) { struct scoutfs_inode_info *si; - struct scoutfs_key key; struct scoutfs_inode sinode; + struct scoutfs_key key; struct inode *inode; + int inode_bytes; int ret; inode = new_inode(sb); @@ -1455,14 +1485,16 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d inode->i_rdev = rdev; set_inode_ops(inode); - store_inode(&sinode, inode); + inode_bytes = max_inode_fmt_ver_bytes(sb); + + store_inode(&sinode, inode, inode_bytes); scoutfs_inode_init_key(&key, scoutfs_ino(inode)); ret = scoutfs_omap_set(sb, ino); if (ret < 0) goto out; - ret = scoutfs_item_create(sb, &key, &sinode, sizeof(sinode), lock); + ret = scoutfs_item_create(sb, &key, &sinode, inode_bytes, lock); if (ret < 0) scoutfs_omap_clear(sb, ino); out: @@ -1712,7 +1744,7 @@ static int try_delete_inode_items(struct super_block *sb, u64 ino) } scoutfs_inode_init_key(&key, ino); - ret = scoutfs_item_lookup_exact(sb, &key, &sinode, sizeof(sinode), lock); + ret = lookup_inode_item(sb, &key, &sinode, lock); if (ret < 0) { if (ret == -ENOENT) ret = 0;