From: Chao Yu <[email protected]>

[ Upstream commit 91803392c732c43b5cf440e885ea89be7f5fecef ]

During f2fs_write_checkpoint(), once we failed in
f2fs_flush_nat_entries() or do_checkpoint(), metadata of filesystem
such as prefree bitmap, nat/sit version bitmap won't be recovered,
it may cause f2fs image to be inconsistent, let's just set CP error
flag to avoid further updates until we figure out a scheme to rollback
all metadatas in such condition.

Reported-by: Yangtao Li <[email protected]>
Signed-off-by: Yangtao Li <[email protected]>
Signed-off-by: Chao Yu <[email protected]>
Signed-off-by: Jaegeuk Kim <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
 fs/f2fs/checkpoint.c | 12 +++++++++---
 fs/f2fs/f2fs.h       |  2 +-
 fs/f2fs/segment.c    | 15 +++++++++++++--
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index b39bf416d511..4e1f6860ee95 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -1620,8 +1620,11 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, 
struct cp_control *cpc)
 
        /* write cached NAT/SIT entries to NAT/SIT area */
        err = f2fs_flush_nat_entries(sbi, cpc);
-       if (err)
+       if (err) {
+               f2fs_err(sbi, "f2fs_flush_nat_entries failed err:%d, stop 
checkpoint", err);
+               f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
                goto stop;
+       }
 
        f2fs_flush_sit_entries(sbi, cpc);
 
@@ -1629,10 +1632,13 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, 
struct cp_control *cpc)
        f2fs_save_inmem_curseg(sbi);
 
        err = do_checkpoint(sbi, cpc);
-       if (err)
+       if (err) {
+               f2fs_err(sbi, "do_checkpoint failed err:%d, stop checkpoint", 
err);
+               f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
                f2fs_release_discard_addrs(sbi);
-       else
+       } else {
                f2fs_clear_prefree_segments(sbi, cpc);
+       }
 
        f2fs_restore_inmem_curseg(sbi);
 stop:
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 2d7799bd30b1..95eef965bbce 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -514,7 +514,7 @@ enum {
                                         */
 };
 
-#define DEFAULT_RETRY_IO_COUNT 8       /* maximum retry read IO count */
+#define DEFAULT_RETRY_IO_COUNT 8       /* maximum retry read IO or flush count 
*/
 
 /* congestion wait timeout value, default: 20ms */
 #define        DEFAULT_IO_TIMEOUT      (msecs_to_jiffies(20))
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 730f028e8f49..0b2013709f8e 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -767,11 +767,22 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
                return 0;
 
        for (i = 1; i < sbi->s_ndevs; i++) {
+               int count = DEFAULT_RETRY_IO_COUNT;
+
                if (!f2fs_test_bit(i, (char *)&sbi->dirty_device))
                        continue;
-               ret = __submit_flush_wait(sbi, FDEV(i).bdev);
-               if (ret)
+
+               do {
+                       ret = __submit_flush_wait(sbi, FDEV(i).bdev);
+                       if (ret)
+                               congestion_wait(BLK_RW_ASYNC,
+                                               DEFAULT_IO_TIMEOUT);
+               } while (ret && --count);
+
+               if (ret) {
+                       f2fs_stop_checkpoint(sbi, false);
                        break;
+               }
 
                spin_lock(&sbi->dev_lock);
                f2fs_clear_bit(i, (char *)&sbi->dirty_device);
-- 
2.30.2



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to