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;