Skip to content

Commit 9703d69

Browse files
Daeho JeongJaegeuk Kim
authored andcommitted
f2fs: support file pinning for zoned devices
Support file pinning with conventional storage area for zoned devices Signed-off-by: Daeho Jeong <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 4e0197f commit 9703d69

File tree

6 files changed

+154
-38
lines changed

6 files changed

+154
-38
lines changed

fs/f2fs/data.c

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3839,25 +3839,34 @@ static int f2fs_migrate_blocks(struct inode *inode, block_t start_blk,
38393839
unsigned int blkofs;
38403840
unsigned int blk_per_sec = BLKS_PER_SEC(sbi);
38413841
unsigned int secidx = start_blk / blk_per_sec;
3842-
unsigned int end_sec = secidx + blkcnt / blk_per_sec;
3842+
unsigned int end_sec;
38433843
int ret = 0;
38443844

3845+
if (!blkcnt)
3846+
return 0;
3847+
end_sec = secidx + (blkcnt - 1) / blk_per_sec;
3848+
38453849
f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
38463850
filemap_invalidate_lock(inode->i_mapping);
38473851

38483852
set_inode_flag(inode, FI_ALIGNED_WRITE);
38493853
set_inode_flag(inode, FI_OPU_WRITE);
38503854

3851-
for (; secidx < end_sec; secidx++) {
3855+
for (; secidx <= end_sec; secidx++) {
3856+
unsigned int blkofs_end = secidx == end_sec ?
3857+
(blkcnt - 1) % blk_per_sec : blk_per_sec - 1;
3858+
38523859
f2fs_down_write(&sbi->pin_sem);
38533860

3854-
f2fs_lock_op(sbi);
3855-
f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
3856-
f2fs_unlock_op(sbi);
3861+
ret = f2fs_allocate_pinning_section(sbi);
3862+
if (ret) {
3863+
f2fs_up_write(&sbi->pin_sem);
3864+
break;
3865+
}
38573866

38583867
set_inode_flag(inode, FI_SKIP_WRITES);
38593868

3860-
for (blkofs = 0; blkofs < blk_per_sec; blkofs++) {
3869+
for (blkofs = 0; blkofs <= blkofs_end; blkofs++) {
38613870
struct page *page;
38623871
unsigned int blkidx = secidx * blk_per_sec + blkofs;
38633872

@@ -3946,27 +3955,34 @@ static int check_swap_activate(struct swap_info_struct *sis,
39463955
nr_pblocks = map.m_len;
39473956

39483957
if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask ||
3949-
nr_pblocks & sec_blks_mask) {
3958+
nr_pblocks & sec_blks_mask ||
3959+
!f2fs_valid_pinned_area(sbi, pblock)) {
3960+
bool last_extent = false;
3961+
39503962
not_aligned++;
39513963

39523964
nr_pblocks = roundup(nr_pblocks, blks_per_sec);
39533965
if (cur_lblock + nr_pblocks > sis->max)
39543966
nr_pblocks -= blks_per_sec;
39553967

3968+
/* this extent is last one */
39563969
if (!nr_pblocks) {
3957-
/* this extent is last one */
3958-
nr_pblocks = map.m_len;
3959-
f2fs_warn(sbi, "Swapfile: last extent is not aligned to section");
3960-
goto next;
3970+
nr_pblocks = last_lblock - cur_lblock;
3971+
last_extent = true;
39613972
}
39623973

39633974
ret = f2fs_migrate_blocks(inode, cur_lblock,
39643975
nr_pblocks);
3965-
if (ret)
3976+
if (ret) {
3977+
if (ret == -ENOENT)
3978+
ret = -EINVAL;
39663979
goto out;
3967-
goto retry;
3980+
}
3981+
3982+
if (!last_extent)
3983+
goto retry;
39683984
}
3969-
next:
3985+
39703986
if (cur_lblock + nr_pblocks >= sis->max)
39713987
nr_pblocks = sis->max - cur_lblock;
39723988

@@ -4004,17 +4020,17 @@ static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file,
40044020
sector_t *span)
40054021
{
40064022
struct inode *inode = file_inode(file);
4023+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
40074024
int ret;
40084025

40094026
if (!S_ISREG(inode->i_mode))
40104027
return -EINVAL;
40114028

4012-
if (f2fs_readonly(F2FS_I_SB(inode)->sb))
4029+
if (f2fs_readonly(sbi->sb))
40134030
return -EROFS;
40144031

4015-
if (f2fs_lfs_mode(F2FS_I_SB(inode))) {
4016-
f2fs_err(F2FS_I_SB(inode),
4017-
"Swapfile not supported in LFS mode");
4032+
if (f2fs_lfs_mode(sbi) && !f2fs_sb_has_blkzoned(sbi)) {
4033+
f2fs_err(sbi, "Swapfile not supported in LFS mode");
40184034
return -EINVAL;
40194035
}
40204036

@@ -4027,13 +4043,17 @@ static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file,
40274043

40284044
f2fs_precache_extents(inode);
40294045

4046+
ret = filemap_fdatawrite(inode->i_mapping);
4047+
if (ret < 0)
4048+
return ret;
4049+
40304050
ret = check_swap_activate(sis, file, span);
40314051
if (ret < 0)
40324052
return ret;
40334053

40344054
stat_inc_swapfile_inode(inode);
40354055
set_inode_flag(inode, FI_PIN_FILE);
4036-
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
4056+
f2fs_update_time(sbi, REQ_TIME);
40374057
return ret;
40384058
}
40394059

fs/f2fs/f2fs.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3699,7 +3699,8 @@ void f2fs_get_new_segment(struct f2fs_sb_info *sbi,
36993699
unsigned int *newseg, bool new_sec, int dir);
37003700
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
37013701
unsigned int start, unsigned int end);
3702-
void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
3702+
int f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
3703+
int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi);
37033704
void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi);
37043705
int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);
37053706
bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
@@ -3877,6 +3878,9 @@ void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi);
38773878
block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode);
38783879
int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control);
38793880
void f2fs_build_gc_manager(struct f2fs_sb_info *sbi);
3881+
int f2fs_gc_range(struct f2fs_sb_info *sbi,
3882+
unsigned int start_seg, unsigned int end_seg,
3883+
bool dry_run, unsigned int dry_run_sections);
38803884
int f2fs_resize_fs(struct file *filp, __u64 block_count);
38813885
int __init f2fs_create_garbage_collection_cache(void);
38823886
void f2fs_destroy_garbage_collection_cache(void);
@@ -4531,6 +4535,17 @@ static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi)
45314535
return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS;
45324536
}
45334537

4538+
static inline bool f2fs_valid_pinned_area(struct f2fs_sb_info *sbi,
4539+
block_t blkaddr)
4540+
{
4541+
if (f2fs_sb_has_blkzoned(sbi)) {
4542+
int devi = f2fs_target_device_index(sbi, blkaddr);
4543+
4544+
return !bdev_is_zoned(FDEV(devi).bdev);
4545+
}
4546+
return true;
4547+
}
4548+
45344549
static inline bool f2fs_low_mem_mode(struct f2fs_sb_info *sbi)
45354550
{
45364551
return F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_LOW;

fs/f2fs/file.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,9 +1748,11 @@ static int f2fs_expand_inode_data(struct inode *inode, loff_t offset,
17481748

17491749
f2fs_down_write(&sbi->pin_sem);
17501750

1751-
f2fs_lock_op(sbi);
1752-
f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
1753-
f2fs_unlock_op(sbi);
1751+
err = f2fs_allocate_pinning_section(sbi);
1752+
if (err) {
1753+
f2fs_up_write(&sbi->pin_sem);
1754+
goto out_err;
1755+
}
17541756

17551757
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
17561758
err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_PRE_DIO);
@@ -3200,6 +3202,7 @@ int f2fs_pin_file_control(struct inode *inode, bool inc)
32003202
static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
32013203
{
32023204
struct inode *inode = file_inode(filp);
3205+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
32033206
__u32 pin;
32043207
int ret = 0;
32053208

@@ -3209,7 +3212,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
32093212
if (!S_ISREG(inode->i_mode))
32103213
return -EINVAL;
32113214

3212-
if (f2fs_readonly(F2FS_I_SB(inode)->sb))
3215+
if (f2fs_readonly(sbi->sb))
32133216
return -EROFS;
32143217

32153218
ret = mnt_want_write_file(filp);
@@ -3222,9 +3225,18 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
32223225
clear_inode_flag(inode, FI_PIN_FILE);
32233226
f2fs_i_gc_failures_write(inode, 0);
32243227
goto done;
3228+
} else if (f2fs_is_pinned_file(inode)) {
3229+
goto done;
32253230
}
32263231

3227-
if (f2fs_should_update_outplace(inode, NULL)) {
3232+
if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
3233+
ret = -EFBIG;
3234+
goto out;
3235+
}
3236+
3237+
/* Let's allow file pinning on zoned device. */
3238+
if (!f2fs_sb_has_blkzoned(sbi) &&
3239+
f2fs_should_update_outplace(inode, NULL)) {
32283240
ret = -EINVAL;
32293241
goto out;
32303242
}
@@ -3246,7 +3258,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
32463258
set_inode_flag(inode, FI_PIN_FILE);
32473259
ret = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
32483260
done:
3249-
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
3261+
f2fs_update_time(sbi, REQ_TIME);
32503262
out:
32513263
inode_unlock(inode);
32523264
mnt_drop_write_file(filp);

fs/f2fs/gc.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,22 +1974,28 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
19741974
init_atgc_management(sbi);
19751975
}
19761976

1977-
static int f2fs_gc_range(struct f2fs_sb_info *sbi,
1978-
unsigned int start_seg, unsigned int end_seg, bool dry_run)
1977+
int f2fs_gc_range(struct f2fs_sb_info *sbi,
1978+
unsigned int start_seg, unsigned int end_seg,
1979+
bool dry_run, unsigned int dry_run_sections)
19791980
{
19801981
unsigned int segno;
1982+
unsigned int gc_secs = dry_run_sections;
19811983

19821984
for (segno = start_seg; segno <= end_seg; segno += SEGS_PER_SEC(sbi)) {
19831985
struct gc_inode_list gc_list = {
19841986
.ilist = LIST_HEAD_INIT(gc_list.ilist),
19851987
.iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
19861988
};
19871989

1988-
do_garbage_collect(sbi, segno, &gc_list, FG_GC, true);
1990+
do_garbage_collect(sbi, segno, &gc_list, FG_GC,
1991+
dry_run_sections == 0);
19891992
put_gc_inode(&gc_list);
19901993

19911994
if (!dry_run && get_valid_blocks(sbi, segno, true))
19921995
return -EAGAIN;
1996+
if (dry_run && dry_run_sections &&
1997+
!get_valid_blocks(sbi, segno, true) && --gc_secs == 0)
1998+
break;
19931999

19942000
if (fatal_signal_pending(current))
19952001
return -ERESTARTSYS;
@@ -2027,7 +2033,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
20272033
f2fs_allocate_segment_for_resize(sbi, type, start, end);
20282034

20292035
/* do GC to move out valid blocks in the range */
2030-
err = f2fs_gc_range(sbi, start, end, dry_run);
2036+
err = f2fs_gc_range(sbi, start, end, dry_run, 0);
20312037
if (err || dry_run)
20322038
goto out;
20332039

0 commit comments

Comments
 (0)