mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-09 21:22:36 +00:00
scoutfs: add tracking of online and offline blocks
Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, \
|
||||
|
||||
Reference in New Issue
Block a user