f2fs: support an ioctl to move a range of data blocks
Subsystems (2)
Jaegeuk Kim
maintainerPATCH 1/3 f2fs: support an ioctl to move a range of data blocks
This patch implements moving a range of data blocks from source file to destination file.
--- fs/f2fs/f2fs.h | 9 ++++ fs/f2fs/file.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+)
fs/f2fs/f2fs.h +9 -0
@@ -268,6 +268,8 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,#define F2FS_IOC_GARBAGE_COLLECT _IO(F2FS_IOCTL_MAGIC, 6)#define F2FS_IOC_WRITE_CHECKPOINT _IO(F2FS_IOCTL_MAGIC, 7)#define F2FS_IOC_DEFRAGMENT _IO(F2FS_IOCTL_MAGIC, 8) +#define F2FS_IOC_MOVE_RANGE _IOWR(F2FS_IOCTL_MAGIC, 9, \ + struct f2fs_move_range)#define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY#define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY
@@ -297,6 +299,13 @@ struct f2fs_defragment {u64 len; }; +struct f2fs_move_range { +u32 dst_fd;/* destination fd */ +u64 pos_in;/* start position in src_fd */ +u64 pos_out;/* start position in dst_fd */ +u64 len;/* size to move */ +}; +/* * For INODE and NODE manager */
fs/f2fs/file.c +132 -0
156 lines not on this page · raw message
Signature · 1 line
2.8.3
Jaegeuk Kim
maintainerPATCH 2/3 f2fs: avoid data race when deciding checkpoin in f2fs_sync_file
When fs utilization is almost full, f2fs_sync_file should do checkpoint if there is not enough space for roll-forward later. (i.e. space_for_roll_forward) So, currently we have no lock for sbi->alloc_valid_block_count, resulting in race condition.
In rare case, we can get -ENOSPC when doing roll-forward which triggers
if (is_valid_blkaddr(sbi, dest, META_POR)) {
if (src == NULL_ADDR) {
err = reserve_new_block(&dn);
f2fs_bug_on(sbi, err);
...
}
...
}in do_recover_data.
So, this patch avoids that situation in advance.
--- fs/f2fs/f2fs.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
fs/f2fs/f2fs.h +11 -2
@@ -1147,24 +1147,33 @@ static inline void f2fs_i_blocks_write(struct inode *, blkcnt_t, bool);static inline bool inc_valid_block_count (struct f2fs_sb_info *sbi,struct inode *inode,blkcnt_t *count) { +blkcnt_t diff; +#ifdef CONFIG_F2FS_FAULT_INJECTION if (time_to_inject (FAULT_BLOCK ))return false;#endif +/* +* let's increase this in prior to actual block count change in order +* for f2fs_sync_file to avoid data races when deciding checkpoint. +*/ +percpu_counter_add (&sbi->alloc_valid_block_count, (*count)); +spin_lock (&sbi->stat_lock); sbi->total_valid_block_count += (block_t)(*count);if (unlikely (sbi->total_valid_block_count > sbi->user_block_count)) { - *count -= sbi->total_valid_block_count - sbi->user_block_count; + diff = sbi->total_valid_block_count - sbi->user_block_count; + *count -= diff; sbi->total_valid_block_count = sbi->user_block_count;if (!*count) {spin_unlock (&sbi->stat_lock); +percpu_counter_sub (&sbi->alloc_valid_block_count, diff);return false; } }spin_unlock (&sbi->stat_lock);f2fs_i_blocks_write (inode, *count, true); -percpu_counter_add (&sbi->alloc_valid_block_count, (*count));return true; }
Signature · 1 line
2.8.3
Jaegeuk Kim
maintainerPATCH 3/3 f2fs: handle error case with f2fs_bug_on
In reply to Jaegeuk KimIt's enough to show BUG or WARN by f2fs_bug_on for error case. Then, we don't need to remain corrupted filesystem.
--- fs/f2fs/recovery.c | 2 ++ 1 file changed, 2 insertions(+)
fs/f2fs/recovery.c +2 -0
@@ -482,6 +482,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,#endif /* We should not get -ENOSPC */ f2fs_bug_on (sbi, err); +if (err) + goto err; }/* Check the previous node page having this index */
Signature · 1 line
2.8.3