scoutfs: add tracking of online and offline blocks

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-02-02 09:51:20 -08:00
committed by Zach Brown
parent f52dc28322
commit c1311783d5
7 changed files with 93 additions and 12 deletions

View File

@@ -603,9 +603,13 @@ out:
* This is the low level extent item manipulation code. We hold and
* release the transaction so the caller doesn't have to deal with
* partial progress.
*
* If the inode is provided then we update its tracking of the online
* and offline blocks. If it's not provided then the inode is being
* destroyed and we don't have to keep it updated.
*/
int scoutfs_data_truncate_items(struct super_block *sb, u64 ino, u64 iblock,
u64 last, bool offline,
int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
u64 ino, u64 iblock, u64 last, bool offline,
struct scoutfs_lock *lock)
{
struct scoutfs_key_buf last_key;
@@ -687,12 +691,17 @@ int scoutfs_data_truncate_items(struct super_block *sb, u64 ino, u64 iblock,
break;
map->blknos[i] = 0;
scoutfs_inode_add_online_blocks(inode, -1);
}
if (offline && !test_bit(i, map->offline))
if (offline && !test_bit(i, map->offline)) {
set_bit(i, map->offline);
else if (!offline && test_bit(i, map->offline))
scoutfs_inode_add_offline_blocks(inode, 1);
} else if (!offline && test_bit(i, map->offline)) {
clear_bit(i, map->offline);
scoutfs_inode_add_offline_blocks(inode, -1);
}
modified = true;
}
@@ -905,7 +914,8 @@ out:
* a new segment. Lots of concurrent allocations can interleave at
* segment granularity.
*/
static int find_alloc_block(struct super_block *sb, struct block_mapping *map,
static int find_alloc_block(struct super_block *sb, struct inode *inode,
struct block_mapping *map,
struct scoutfs_key_buf *map_key,
unsigned map_ind, bool map_exists,
struct scoutfs_lock *data_lock)
@@ -973,8 +983,10 @@ static int find_alloc_block(struct super_block *sb, struct block_mapping *map,
goto out;
/* update the mapping */
clear_bit(map_ind, map->offline);
if (test_and_clear_bit(map_ind, map->offline))
scoutfs_inode_add_offline_blocks(inode, -1);
map->blknos[map_ind] = blkno;
scoutfs_inode_add_online_blocks(inode, 1);
bytes = encode_mapping(map);
scoutfs_kvec_init(val, map->encoded, bytes);
@@ -1049,7 +1061,7 @@ static int scoutfs_get_block(struct inode *inode, sector_t iblock,
* and try again if we've already done a bulk alloc in
* our transaction.
*/
ret = find_alloc_block(sb, map, &key, ind, exists, lock);
ret = find_alloc_block(sb, inode, map, &key, ind, exists, lock);
if (ret)
goto out;
set_buffer_new(bh);

View File

@@ -4,8 +4,8 @@
extern const struct address_space_operations scoutfs_file_aops;
extern const struct file_operations scoutfs_file_fops;
int scoutfs_data_truncate_items(struct super_block *sb, u64 ino, u64 iblock,
u64 last, bool offline,
int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
u64 ino, u64 iblock, u64 last, bool offline,
struct scoutfs_lock *lock);
int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len);

View File

@@ -449,6 +449,12 @@ struct scoutfs_timespec {
* have changed. It is exposed via an ioctl and is then provided as an
* argument to data functions to protect racing modification.
*
* @online_blocks: The number of fixed 4k blocks currently allocated and
* storing data in the volume.
*
* @offline_blocks: The number of fixed 4k blocks that could be made
* online by staging.
*
* XXX
* - otime?
* - compat flags?
@@ -462,6 +468,8 @@ struct scoutfs_inode {
__le64 meta_seq;
__le64 data_seq;
__le64 data_version;
__le64 online_blocks;
__le64 offline_blocks;
__le64 next_readdir_pos;
__le32 nlink;
__le32 uid;

View File

@@ -231,6 +231,8 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode)
ci->meta_seq = le64_to_cpu(cinode->meta_seq);
ci->data_seq = le64_to_cpu(cinode->data_seq);
ci->data_version = le64_to_cpu(cinode->data_version);
ci->online_blocks = le64_to_cpu(cinode->online_blocks);
ci->offline_blocks = le64_to_cpu(cinode->offline_blocks);
ci->next_readdir_pos = le64_to_cpu(cinode->next_readdir_pos);
ci->flags = le32_to_cpu(cinode->flags);
@@ -380,8 +382,9 @@ int scoutfs_complete_truncate(struct inode *inode, struct scoutfs_lock *lock)
return 0;
start = (i_size_read(inode) + SCOUTFS_BLOCK_SIZE - 1) >> SCOUTFS_BLOCK_SHIFT;
ret = scoutfs_data_truncate_items(inode->i_sb, scoutfs_ino(inode),
start, ~0ULL, false, lock);
ret = scoutfs_data_truncate_items(inode->i_sb, inode,
scoutfs_ino(inode), start, ~0ULL,
false, lock);
err = clear_truncate_flag(inode, lock);
return ret ? ret : err;
@@ -493,6 +496,35 @@ 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)
{
struct scoutfs_inode_info *si;
if (inode) {
si = SCOUTFS_I(inode);
add_seq_value(si, &SCOUTFS_I(inode)->online_blocks, val);
}
}
void scoutfs_inode_add_offline_blocks(struct inode *inode, u64 val)
{
struct scoutfs_inode_info *si;
if (inode) {
si = SCOUTFS_I(inode);
add_seq_value(si, &SCOUTFS_I(inode)->offline_blocks, val);
}
}
static u64 read_seqcount_u64(struct inode *inode, u64 *val)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
@@ -528,6 +560,19 @@ u64 scoutfs_inode_data_version(struct inode *inode)
return read_seqcount_u64(inode, &si->data_version);
}
u64 scoutfs_inode_online_blocks(struct inode *inode)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
return read_seqcount_u64(inode, &si->online_blocks);
}
u64 scoutfs_inode_offline_blocks(struct inode *inode)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
return read_seqcount_u64(inode, &si->offline_blocks);
}
static int scoutfs_iget_test(struct inode *inode, void *arg)
{
struct scoutfs_inode_info *ci = SCOUTFS_I(inode);
@@ -612,6 +657,9 @@ 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->next_readdir_pos = cpu_to_le64(ci->next_readdir_pos);
cinode->flags = cpu_to_le32(ci->flags);
}
@@ -1270,6 +1318,8 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
ci = SCOUTFS_I(inode);
ci->ino = ino;
ci->data_version = 0;
ci->online_blocks = 0;
ci->offline_blocks = 0;
ci->next_readdir_pos = SCOUTFS_DIRENT_FIRST_POS;
ci->have_item = false;
atomic64_set(&ci->last_refreshed, lock->refresh_gen);

View File

@@ -21,6 +21,8 @@ struct scoutfs_inode_info {
u64 meta_seq;
u64 data_seq;
u64 data_version;
u64 online_blocks;
u64 offline_blocks;
u32 flags;
/*
@@ -97,9 +99,13 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
void scoutfs_inode_set_meta_seq(struct inode *inode);
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);
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);
int scoutfs_complete_truncate(struct inode *inode, struct scoutfs_lock *lock);
int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,

View File

@@ -378,7 +378,8 @@ static long scoutfs_ioc_release(struct file *file, unsigned long arg)
end_inc = ((args.block + args.count) << SCOUTFS_BLOCK_SHIFT) - 1;
truncate_inode_pages_range(&inode->i_data, start, end_inc);
ret = scoutfs_data_truncate_items(sb, scoutfs_ino(inode), args.block,
ret = scoutfs_data_truncate_items(sb, inode, scoutfs_ino(inode),
args.block,
args.block + args.count - 1, true,
lock);
out:
@@ -522,6 +523,8 @@ 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);
if (copy_to_user((void __user *)arg, &stm, stm.valid_bytes))
return -EFAULT;

View File

@@ -178,6 +178,8 @@ struct scoutfs_ioctl_stat_more {
__u64 meta_seq;
__u64 data_seq;
__u64 data_version;
__u64 online_blocks;
__u64 offline_blocks;
} __packed;
#define SCOUTFS_IOC_STAT_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 7, \