Add an inode data_version field

The data_version field is changed every time the contents of the file
could have changed.

Signed-off-by: Zach Brown <zab@versity.com>
Reviewed-by: Mark Fasheh <mfasheh@versity.com>
This commit is contained in:
Zach Brown
2016-11-14 14:52:28 -08:00
parent 467801de73
commit f86fab1162
4 changed files with 45 additions and 1 deletions

View File

@@ -615,6 +615,11 @@ static int scoutfs_write_end(struct file *file, struct address_space *mapping,
scoutfs_ino(inode), PGA(page), (u64)pos, len, copied);
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
if (ret > 0) {
scoutfs_inode_inc_data_version(inode);
/* XXX kind of a big hammer, inode life cycle needs work */
scoutfs_update_inode_item(inode);
}
scoutfs_release_trans(sb);
return ret;
}

View File

@@ -200,6 +200,10 @@ struct scoutfs_timespec {
} __packed;
/*
* @data_version: incremented every time the contents of a file could
* have changed. It is exposed via an ioctl and is then provided as an
* argument to data functions to protect racing modification.
*
* XXX
* - otime?
* - compat flags?
@@ -211,6 +215,7 @@ struct scoutfs_inode {
__le64 size;
__le64 blocks;
__le64 link_counter;
__le64 data_version;
__le32 nlink;
__le32 uid;
__le32 gid;

View File

@@ -120,9 +120,10 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode)
inode->i_mtime.tv_nsec = le32_to_cpu(cinode->mtime.nsec);
inode->i_ctime.tv_sec = le64_to_cpu(cinode->ctime.sec);
inode->i_ctime.tv_nsec = le32_to_cpu(cinode->ctime.nsec);
ci->salt = le32_to_cpu(cinode->salt);
atomic64_set(&ci->link_counter, le64_to_cpu(cinode->link_counter));
ci->data_version = le64_to_cpu(cinode->data_version);
}
static int scoutfs_read_locked_inode(struct inode *inode)
@@ -148,6 +149,31 @@ static int scoutfs_read_locked_inode(struct inode *inode)
return ret;
}
void scoutfs_inode_inc_data_version(struct inode *inode)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
preempt_disable();
write_seqcount_begin(&si->seqcount);
si->data_version++;
write_seqcount_end(&si->seqcount);
preempt_enable();
}
u64 scoutfs_inode_get_data_version(struct inode *inode)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
unsigned int seq;
u64 vers;
do {
seq = read_seqcount_begin(&si->seqcount);
vers = si->data_version;
} while (read_seqcount_retry(&si->seqcount, seq));
return vers;
}
static int scoutfs_iget_test(struct inode *inode, void *arg)
{
struct scoutfs_inode_info *ci = SCOUTFS_I(inode);
@@ -210,6 +236,7 @@ static void store_inode(struct scoutfs_inode *cinode, struct inode *inode)
cinode->salt = cpu_to_le32(ci->salt);
cinode->link_counter = cpu_to_le64(atomic64_read(&ci->link_counter));
cinode->data_version = cpu_to_le64(ci->data_version);
}
/*
@@ -366,6 +393,8 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
ci = SCOUTFS_I(inode);
ci->ino = ino;
seqcount_init(&ci->seqcount);
ci->data_version = 0;
get_random_bytes(&ci->salt, sizeof(ci->salt));
atomic64_set(&ci->link_counter, 0);

View File

@@ -5,6 +5,9 @@ struct scoutfs_inode_info {
u64 ino;
u32 salt;
seqcount_t seqcount;
u64 data_version;
atomic64_t link_counter;
struct rw_semaphore xattr_rwsem;
@@ -33,6 +36,8 @@ void scoutfs_dirty_inode(struct inode *inode, int flags);
void scoutfs_update_inode_item(struct inode *inode);
struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
umode_t mode, dev_t rdev);
void scoutfs_inode_inc_data_version(struct inode *inode);
u64 scoutfs_inode_get_data_version(struct inode *inode);
int scoutfs_scan_orphans(struct super_block *sb);