From ea2b01434e34311c39cd09b5ff8d7693ad5deba8 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 2 Aug 2021 13:13:37 -0700 Subject: [PATCH] Add support for i_version This adds i_version to our inode and maintains it as we allocate, load, modify, and store inodes. We set the flag in the superblock so in-kernel users can use i_version to see changes in our inodes. Signed-off-by: Zach Brown --- kmod/src/data.c | 4 ++++ kmod/src/dir.c | 16 ++++++++++++++++ kmod/src/format.h | 7 +------ kmod/src/inode.c | 5 +++++ kmod/src/super.c | 1 + utils/src/print.c | 3 ++- 6 files changed, 29 insertions(+), 7 deletions(-) diff --git a/kmod/src/data.c b/kmod/src/data.c index acce243a..aae6f601 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -830,6 +830,7 @@ static int scoutfs_write_end(struct file *file, struct address_space *mapping, scoutfs_inode_inc_data_version(inode); } + inode_inc_iversion(inode); scoutfs_update_inode_item(inode, wbd->lock, &wbd->ind_locks); scoutfs_inode_queue_writeback(inode); } @@ -1033,6 +1034,7 @@ long scoutfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) end = offset + len; if (end > i_size_read(inode)) { i_size_write(inode, end); + inode_inc_iversion(inode); scoutfs_inode_inc_data_version(inode); } } @@ -1366,10 +1368,12 @@ int scoutfs_data_move_blocks(struct inode *from, u64 from_off, cur_time = CURRENT_TIME; if (!is_stage) { to->i_ctime = to->i_mtime = cur_time; + inode_inc_iversion(to); scoutfs_inode_inc_data_version(to); scoutfs_inode_set_data_seq(to); } from->i_ctime = from->i_mtime = cur_time; + inode_inc_iversion(from); scoutfs_inode_inc_data_version(from); scoutfs_inode_set_data_seq(from); diff --git a/kmod/src/dir.c b/kmod/src/dir.c index 4cbb2e0b..dc95c360 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -836,6 +836,8 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dir->i_mtime = dir->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = dir->i_mtime; si->crtime = inode->i_mtime; + inode_inc_iversion(dir); + inode_inc_iversion(inode); if (S_ISDIR(mode)) { inc_nlink(inode); @@ -961,6 +963,8 @@ retry: dir->i_mtime = dir->i_ctime = CURRENT_TIME; inode->i_ctime = dir->i_mtime; inc_nlink(inode); + inode_inc_iversion(dir); + inode_inc_iversion(inode); scoutfs_update_inode_item(inode, inode_lock, &ind_locks); scoutfs_update_inode_item(dir, dir_lock, &ind_locks); @@ -1058,6 +1062,8 @@ retry: dir->i_ctime = ts; dir->i_mtime = ts; i_size_write(dir, i_size_read(dir) - dentry->d_name.len); + inode_inc_iversion(dir); + inode_inc_iversion(inode); inode->i_ctime = ts; drop_nlink(inode); @@ -1295,10 +1301,12 @@ static int scoutfs_symlink(struct inode *dir, struct dentry *dentry, i_size_write(dir, i_size_read(dir) + dentry->d_name.len); dir->i_mtime = dir->i_ctime = CURRENT_TIME; + inode_inc_iversion(dir); inode->i_ctime = dir->i_mtime; si->crtime = inode->i_ctime; i_size_write(inode, name_len); + inode_inc_iversion(inode); scoutfs_update_inode_item(inode, inode_lock, &ind_locks); scoutfs_update_inode_item(dir, dir_lock, &ind_locks); @@ -1779,6 +1787,13 @@ retry: if (new_inode) old_inode->i_ctime = now; + inode_inc_iversion(old_dir); + inode_inc_iversion(old_inode); + if (new_dir != old_dir) + inode_inc_iversion(new_dir); + if (new_inode) + inode_inc_iversion(new_inode); + scoutfs_update_inode_item(old_dir, old_dir_lock, &ind_locks); scoutfs_update_inode_item(old_inode, old_inode_lock, &ind_locks); if (new_dir != old_dir) @@ -1888,6 +1903,7 @@ static int scoutfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mod insert_inode_hash(inode); ihold(inode); /* need to update inode modifications in d_tmpfile */ d_tmpfile(dentry, inode); + inode_inc_iversion(inode); scoutfs_update_inode_item(inode, inode_lock, &ind_locks); scoutfs_update_inode_item(dir, dir_lock, &ind_locks); diff --git a/kmod/src/format.h b/kmod/src/format.h index 196cd4fb..cb26ed15 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -823,12 +823,6 @@ struct scoutfs_super_block { * * @offline_blocks: The number of fixed 4k blocks that could be made * online by staging. - * - * XXX - * - compat flags? - * - version? - * - generation? - * - be more careful with rdev? */ struct scoutfs_inode { __le64 size; @@ -839,6 +833,7 @@ struct scoutfs_inode { __le64 offline_blocks; __le64 next_readdir_pos; __le64 next_xattr_id; + __le64 version; __le32 nlink; __le32 uid; __le32 gid; diff --git a/kmod/src/inode.c b/kmod/src/inode.c index ebd2622c..0cb61a89 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -212,6 +212,7 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode) struct scoutfs_inode_info *si = SCOUTFS_I(inode); i_size_write(inode, le64_to_cpu(cinode->size)); + inode->i_version = le64_to_cpu(cinode->version); set_nlink(inode, le32_to_cpu(cinode->nlink)); i_uid_write(inode, le32_to_cpu(cinode->uid)); i_gid_write(inode, le32_to_cpu(cinode->gid)); @@ -346,6 +347,7 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock, if (truncate) si->flags |= SCOUTFS_INO_FLAG_TRUNCATE; scoutfs_inode_set_data_seq(inode); + inode_inc_iversion(inode); scoutfs_update_inode_item(inode, lock, &ind_locks); scoutfs_release_trans(sb); @@ -481,6 +483,7 @@ retry: goto out; setattr_copy(inode, attr); + inode_inc_iversion(inode); scoutfs_update_inode_item(inode, lock, &ind_locks); scoutfs_release_trans(sb); @@ -686,6 +689,7 @@ struct inode *scoutfs_iget(struct super_block *sb, u64 ino, int lkf) /* XXX ensure refresh, instead clear in drop_inode? */ si = SCOUTFS_I(inode); atomic64_set(&si->last_refreshed, 0); + inode->i_version = 0; ret = scoutfs_inode_refresh(inode, lock, 0); if (ret == 0) @@ -713,6 +717,7 @@ static void store_inode(struct scoutfs_inode *cinode, struct inode *inode) scoutfs_inode_get_onoff(inode, &online_blocks, &offline_blocks); cinode->size = cpu_to_le64(i_size_read(inode)); + cinode->version = cpu_to_le64(inode->i_version); cinode->nlink = cpu_to_le32(inode->i_nlink); cinode->uid = cpu_to_le32(i_uid_read(inode)); cinode->gid = cpu_to_le32(i_gid_read(inode)); diff --git a/kmod/src/super.c b/kmod/src/super.c index f9fcc133..b6c1ea88 100644 --- a/kmod/src/super.c +++ b/kmod/src/super.c @@ -545,6 +545,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_op = &scoutfs_super_ops; sb->s_export_op = &scoutfs_export_ops; + sb->s_flags |= MS_I_VERSION; /* btree blocks use long lived bh->b_data refs */ mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS); diff --git a/utils/src/print.c b/utils/src/print.c index a7688cc4..b8717048 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -47,13 +47,14 @@ static void print_inode(struct scoutfs_key *key, void *val, int val_len) { struct scoutfs_inode *inode = val; - printf(" inode: ino %llu size %llu nlink %u\n" + printf(" inode: ino %llu size %llu version %llu nlink %u\n" " uid %u gid %u mode 0%o rdev 0x%x flags 0x%x\n" " next_readdir_pos %llu meta_seq %llu data_seq %llu data_version %llu\n" " atime %llu.%08u ctime %llu.%08u\n" " mtime %llu.%08u\n", le64_to_cpu(key->ski_ino), le64_to_cpu(inode->size), + le64_to_cpu(inode->version), le32_to_cpu(inode->nlink), le32_to_cpu(inode->uid), le32_to_cpu(inode->gid), le32_to_cpu(inode->mode), le32_to_cpu(inode->rdev),