scoutfs: add atomic online/offline blocks calls

Add functions that atomically change and query the online and offline
block counts as a pair.  They're semantically linked and we shouldn't
present counts that don't match if they're in the process of being
updated.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-06-29 14:42:06 -07:00
committed by Zach Brown
parent 4ceb123473
commit 036577890f
5 changed files with 44 additions and 25 deletions
+1
View File
@@ -30,6 +30,7 @@
EXPAND_COUNTER(corrupt_dirent_backref_name_len) \
EXPAND_COUNTER(corrupt_dirent_name_len) \
EXPAND_COUNTER(corrupt_dirent_readdir_name_len) \
EXPAND_COUNTER(corrupt_inode_block_counts) \
EXPAND_COUNTER(corrupt_symlink_inode_size) \
EXPAND_COUNTER(corrupt_symlink_missing_item) \
EXPAND_COUNTER(corrupt_symlink_not_null_term) \
+1
View File
@@ -658,6 +658,7 @@ enum {
SC_SYMLINK_NOT_NULL_TERM,
SC_BTREE_BLOCK_LEVEL,
SC_BTREE_NO_CHILD_REF,
SC_INODE_BLOCK_COUNTS,
SC_NR_SOURCES,
};
+39 -23
View File
@@ -500,32 +500,32 @@ void scoutfs_inode_inc_data_version(struct inode *inode)
preempt_enable();
}
static void add_seq_value(struct scoutfs_inode_info *si, u64 *si_u64, u64 val)
{
preempt_disable();
write_seqcount_begin(&si->seqcount);
*si_u64 += val;
write_seqcount_end(&si->seqcount);
preempt_enable();
}
void scoutfs_inode_add_online_blocks(struct inode *inode, u64 val)
void scoutfs_inode_add_onoff(struct inode *inode, s64 on, s64 off)
{
struct scoutfs_inode_info *si;
if (inode) {
if (inode && (on || off)) {
si = SCOUTFS_I(inode);
add_seq_value(si, &SCOUTFS_I(inode)->online_blocks, val);
}
}
preempt_disable();
write_seqcount_begin(&si->seqcount);
void scoutfs_inode_add_offline_blocks(struct inode *inode, u64 val)
{
struct scoutfs_inode_info *si;
/* inode and extents out of sync, bad callers */
if (((s64)si->online_blocks + on < 0) ||
((s64)si->offline_blocks + off < 0)) {
scoutfs_corruption(inode->i_sb, SC_INODE_BLOCK_COUNTS,
corrupt_inode_block_counts,
"ino %llu size %llu online %llu + %lld offline %llu + %lld",
scoutfs_ino(inode), i_size_read(inode),
si->online_blocks, on, si->offline_blocks, off);
}
if (inode) {
si = SCOUTFS_I(inode);
add_seq_value(si, &SCOUTFS_I(inode)->offline_blocks, val);
si->online_blocks += on;
si->offline_blocks += off;
/* XXX not sure if this is right */
inode->i_blocks += (on + off) * SCOUTFS_BLOCK_SECTORS;
write_seqcount_end(&si->seqcount);
preempt_enable();
}
}
@@ -577,6 +577,19 @@ u64 scoutfs_inode_offline_blocks(struct inode *inode)
return read_seqcount_u64(inode, &si->offline_blocks);
}
void scoutfs_inode_get_onoff(struct inode *inode, s64 *on, s64 *off)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
unsigned int seq;
do {
seq = read_seqcount_begin(&si->seqcount);
*on = SCOUTFS_I(inode)->online_blocks;
*off = SCOUTFS_I(inode)->offline_blocks;
} while (read_seqcount_retry(&si->seqcount, seq));
}
static int scoutfs_iget_test(struct inode *inode, void *arg)
{
struct scoutfs_inode_info *ci = SCOUTFS_I(inode);
@@ -644,6 +657,10 @@ out:
static void store_inode(struct scoutfs_inode *cinode, struct inode *inode)
{
struct scoutfs_inode_info *ci = SCOUTFS_I(inode);
u64 online_blocks;
u64 offline_blocks;
scoutfs_inode_get_onoff(inode, &online_blocks, &offline_blocks);
cinode->size = cpu_to_le64(i_size_read(inode));
cinode->nlink = cpu_to_le32(inode->i_nlink);
@@ -661,9 +678,8 @@ static void store_inode(struct scoutfs_inode *cinode, struct inode *inode)
cinode->meta_seq = cpu_to_le64(scoutfs_inode_meta_seq(inode));
cinode->data_seq = cpu_to_le64(scoutfs_inode_data_seq(inode));
cinode->data_version = cpu_to_le64(scoutfs_inode_data_version(inode));
cinode->online_blocks = cpu_to_le64(scoutfs_inode_online_blocks(inode));
cinode->offline_blocks =
cpu_to_le64(scoutfs_inode_offline_blocks(inode));
cinode->online_blocks = cpu_to_le64(online_blocks);
cinode->offline_blocks = cpu_to_le64(offline_blocks);
cinode->next_readdir_pos = cpu_to_le64(ci->next_readdir_pos);
cinode->next_xattr_id = cpu_to_le64(ci->next_xattr_id);
cinode->flags = cpu_to_le32(ci->flags);
+2
View File
@@ -102,11 +102,13 @@ void scoutfs_inode_set_data_seq(struct inode *inode);
void scoutfs_inode_inc_data_version(struct inode *inode);
void scoutfs_inode_add_online_blocks(struct inode *inode, u64 val);
void scoutfs_inode_add_offline_blocks(struct inode *inode, u64 val);
void scoutfs_inode_add_onoff(struct inode *inode, s64 on, s64 off);
u64 scoutfs_inode_meta_seq(struct inode *inode);
u64 scoutfs_inode_data_seq(struct inode *inode);
u64 scoutfs_inode_data_version(struct inode *inode);
u64 scoutfs_inode_online_blocks(struct inode *inode);
u64 scoutfs_inode_offline_blocks(struct inode *inode);
void scoutfs_inode_get_onoff(struct inode *inode, s64 *on, s64 *off);
int scoutfs_complete_truncate(struct inode *inode, struct scoutfs_lock *lock);
int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
+1 -2
View File
@@ -464,8 +464,7 @@ static long scoutfs_ioc_stat_more(struct file *file, unsigned long arg)
stm.meta_seq = scoutfs_inode_meta_seq(inode);
stm.data_seq = scoutfs_inode_data_seq(inode);
stm.data_version = scoutfs_inode_data_version(inode);
stm.online_blocks = scoutfs_inode_online_blocks(inode);
stm.offline_blocks = scoutfs_inode_offline_blocks(inode);
scoutfs_inode_get_onoff(inode, &stm.online_blocks, &stm.offline_blocks);
if (copy_to_user((void __user *)arg, &stm, stm.valid_bytes))
return -EFAULT;