FAILED: patch "[PATCH] f2fs: Fix use of number of devices" failed to apply to 4.19-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0916878da355650d7e77104a7ac0fa1784eca852 Mon Sep 17 00:00:00 2001
From: Damien Le Moal <[email protected]>
Date: Sat, 16 Mar 2019 09:13:06 +0900
Subject: [PATCH] f2fs: Fix use of number of devices
For a single device mount using a zoned block device, the zone information for the device is stored in the sbi->devs single entry array and sbi->s_ndevs is set to 1. This differs from a single device mount using a regular block device which does not allocate sbi->devs and sets sbi->s_ndevs to 0.
However, sbi->s_devs == 0 condition is used throughout the code to differentiate a single device mount from a multi-device mount where sbi->s_ndevs is always larger than 1. This results in problems with single zoned block device volumes as these are treated as multi-device mounts but do not have the start_blk and end_blk information set. One of the problem observed is skipping of zone discard issuing resulting in write commands being issued to full zones or unaligned to a zone write pointer.
Fix this problem by simply treating the cases sbi->s_ndevs == 0 (single regular block device mount) and sbi->s_ndevs == 1 (single zoned block device mount) in the same manner. This is done by introducing the helper function f2fs_is_multi_device() and using this helper in place of direct tests of sbi->s_ndevs value, improving code readability.
fs/f2fs/data.c +11 -6
@@ -220,12 +220,14 @@ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,struct block_device *bdev = sbi->sb->s_bdev;int i; -for (i =0 ; i < sbi->s_ndevs; i++) { -if (FDEV (i).start_blk <= blk_addr && -FDEV (i).end_blk >= blk_addr) { - blk_addr -=FDEV (i).start_blk; - bdev =FDEV (i).bdev; -break ; +if (f2fs_is_multi_device (sbi)) { +for (i =0 ; i < sbi->s_ndevs; i++) { +if (FDEV (i).start_blk <= blk_addr && +FDEV (i).end_blk >= blk_addr) { + blk_addr -=FDEV (i).start_blk; + bdev =FDEV (i).bdev; +break ; + } } }if (bio) {
@@ -239,6 +241,9 @@ int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr) {int i; +if (!f2fs_is_multi_device (sbi)) +return 0 ; +for (i =0 ; i < sbi->s_ndevs; i++)if (FDEV (i).start_blk <= blkaddr &&FDEV (i).end_blk >= blkaddr)return i;
fs/f2fs/f2fs.h +12 -1
@@ -1366,6 +1366,17 @@ static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) }#endif +/* +* Test if the mounted volume is a multi-device volume. +* - For a single regular disk volume, sbi->s_ndevs is 0. +* - For a single zoned disk volume, sbi->s_ndevs is 1. +* - For a multi-device volume, sbi->s_ndevs is always 2 or more. +*/ +static inline bool f2fs_is_multi_device (struct f2fs_sb_info *sbi) +{ +return sbi->s_ndevs >1 ; +} +/* For write statistics. Suppose sector size is 512 bytes, * and the return value is in kbytes. s is of struct f2fs_sb_info. */
@@ -3615,7 +3626,7 @@ static inline bool f2fs_force_buffered_io(struct inode *inode,if (f2fs_post_read_required (inode))return true; -if (sbi->s_ndevs) +if (f2fs_is_multi_device (sbi))return true;/* * for blkzoned device, fallback direct IO to buffered IO, so
fs/f2fs/file.c +1 -1
@@ -2573,7 +2573,7 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg) sizeof(range)))return -EFAULT ; -if (sbi->s_ndevs <=1 || sbi->s_ndevs -1 <= range.dev_num || +if (!f2fs_is_multi_device (sbi) || sbi->s_ndevs -1 <= range.dev_num ||__is_large_section (sbi)) { f2fs_msg(sbi->sb, KERN_WARNING, "Can't flush %u in %d for segs_per_sec %u != 1\n",
fs/f2fs/gc.c +1 -1
@@ -1346,7 +1346,7 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi) sbi->gc_pin_file_threshold =DEF_GC_FAILED_PINNED_FILES ;/* give warm/cold data area from slower device */ -if (sbi->s_ndevs && !__is_large_section (sbi)) +if (f2fs_is_multi_device (sbi) && !__is_large_section (sbi))SIT_I (sbi)->last_victim[ALLOC_NEXT ] =GET_SEGNO (sbi,FDEV (0 ).end_blk) +1 ; }
fs/f2fs/segment.c +7 -6
@@ -580,7 +580,7 @@ static int submit_flush_wait(struct f2fs_sb_info *sbi, nid_t ino)int ret =0 ;int i; -if (!sbi->s_ndevs) +if (!f2fs_is_multi_device (sbi))return __submit_flush_wait (sbi, sbi->sb->s_bdev);for (i =0 ; i < sbi->s_ndevs; i++) {
@@ -648,7 +648,8 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino)return ret; } -if (atomic_inc_return (&fcc->queued_flush) ==1 || sbi->s_ndevs >1 ) { +if (atomic_inc_return (&fcc->queued_flush) ==1 || +f2fs_is_multi_device (sbi)) { ret =submit_flush_wait (sbi, ino);atomic_dec (&fcc->queued_flush);
@@ -754,7 +755,7 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi) {int ret =0 , i; -if (!sbi->s_ndevs) +if (!f2fs_is_multi_device (sbi))return 0 ;for (i =1 ; i < sbi->s_ndevs; i++) {
@@ -1369,7 +1370,7 @@ static int __queue_discard_cmd(struct f2fs_sb_info *sbi,trace_f2fs_queue_discard (bdev, blkstart, blklen); -if (sbi->s_ndevs) { +if (f2fs_is_multi_device (sbi)) {int devi =f2fs_target_device_index (sbi, blkstart); blkstart -=FDEV (devi).start_blk;
@@ -1732,7 +1733,7 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,block_t lblkstart = blkstart;int devi =0 ; -if (sbi->s_ndevs) { +if (f2fs_is_multi_device (sbi)) { devi =f2fs_target_device_index (sbi, blkstart); blkstart -=FDEV (devi).start_blk; }
@@ -3089,7 +3090,7 @@ static void update_device_state(struct f2fs_io_info *fio)struct f2fs_sb_info *sbi = fio->sbi;unsigned int devidx; -if (!sbi->s_ndevs) +if (!f2fs_is_multi_device (sbi))return ; devidx =f2fs_target_device_index (sbi, fio->new_blkaddr);