Merge tag 'f2fs-for-v5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeu...
[sfrench/cifs-2.6.git] / fs / f2fs / f2fs.h
index bacf5c2a8850b832e1fc73ae501fea8fd3d976e6..06b89a9862ab2bb42bea7a067a455d497fc73e51 100644 (file)
@@ -210,7 +210,14 @@ enum {
        META_SSA,
        META_MAX,
        META_POR,
-       DATA_GENERIC,
+       DATA_GENERIC,           /* check range only */
+       DATA_GENERIC_ENHANCE,   /* strong check on range and segment bitmap */
+       DATA_GENERIC_ENHANCE_READ,      /*
+                                        * strong check on range and segment
+                                        * bitmap but no warning due to race
+                                        * condition of read on truncated area
+                                        * by extent_cache
+                                        */
        META_GENERIC,
 };
 
@@ -1041,7 +1048,7 @@ struct f2fs_io_info {
        bool submitted;         /* indicate IO submission */
        int need_lock;          /* indicate we need to lock cp_rwsem */
        bool in_list;           /* indicate fio is in io_list */
-       bool is_meta;           /* indicate borrow meta inode mapping or not */
+       bool is_por;            /* indicate IO is from recovery or not */
        bool retry;             /* need to reallocate block address */
        enum iostat_type io_type;       /* io type */
        struct writeback_control *io_wbc; /* writeback control */
@@ -1068,8 +1075,8 @@ struct f2fs_dev_info {
        block_t start_blk;
        block_t end_blk;
 #ifdef CONFIG_BLK_DEV_ZONED
-       unsigned int nr_blkz;                   /* Total number of zones */
-       u8 *blkz_type;                          /* Array of zones type */
+       unsigned int nr_blkz;           /* Total number of zones */
+       unsigned long *blkz_seq;        /* Bitmap indicating sequential zones */
 #endif
 };
 
@@ -1366,6 +1373,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.
  */
@@ -1777,6 +1795,7 @@ enospc:
        return -ENOSPC;
 }
 
+void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...);
 static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
                                                struct inode *inode,
                                                block_t count)
@@ -1785,13 +1804,21 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
 
        spin_lock(&sbi->stat_lock);
        f2fs_bug_on(sbi, sbi->total_valid_block_count < (block_t) count);
-       f2fs_bug_on(sbi, inode->i_blocks < sectors);
        sbi->total_valid_block_count -= (block_t)count;
        if (sbi->reserved_blocks &&
                sbi->current_reserved_blocks < sbi->reserved_blocks)
                sbi->current_reserved_blocks = min(sbi->reserved_blocks,
                                        sbi->current_reserved_blocks + count);
        spin_unlock(&sbi->stat_lock);
+       if (unlikely(inode->i_blocks < sectors)) {
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "Inconsistent i_blocks, ino:%lu, iblocks:%llu, sectors:%llu",
+                       inode->i_ino,
+                       (unsigned long long)inode->i_blocks,
+                       (unsigned long long)sectors);
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               return;
+       }
        f2fs_i_blocks_write(inode, count, false, true);
 }
 
@@ -1889,7 +1916,11 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
        if (is_set_ckpt_flags(sbi, CP_LARGE_NAT_BITMAP_FLAG)) {
                offset = (flag == SIT_BITMAP) ?
                        le32_to_cpu(ckpt->nat_ver_bitmap_bytesize) : 0;
-               return &ckpt->sit_nat_version_bitmap + offset;
+               /*
+                * if large_nat_bitmap feature is enabled, leave checksum
+                * protection for all nat/sit bitmaps.
+                */
+               return &ckpt->sit_nat_version_bitmap + offset + sizeof(__le32);
        }
 
        if (__cp_payload(sbi) > 0) {
@@ -2008,7 +2039,6 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
 
        f2fs_bug_on(sbi, !sbi->total_valid_block_count);
        f2fs_bug_on(sbi, !sbi->total_valid_node_count);
-       f2fs_bug_on(sbi, !is_inode && !inode->i_blocks);
 
        sbi->total_valid_node_count--;
        sbi->total_valid_block_count--;
@@ -2018,10 +2048,19 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
 
        spin_unlock(&sbi->stat_lock);
 
-       if (is_inode)
+       if (is_inode) {
                dquot_free_inode(inode);
-       else
+       } else {
+               if (unlikely(inode->i_blocks == 0)) {
+                       f2fs_msg(sbi->sb, KERN_WARNING,
+                               "Inconsistent i_blocks, ino:%lu, iblocks:%llu",
+                               inode->i_ino,
+                               (unsigned long long)inode->i_blocks);
+                       set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       return;
+               }
                f2fs_i_blocks_write(inode, 1, false, true);
+       }
 }
 
 static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
@@ -2545,7 +2584,14 @@ static inline int f2fs_has_inline_xattr(struct inode *inode)
 
 static inline unsigned int addrs_per_inode(struct inode *inode)
 {
-       return CUR_ADDRS_PER_INODE(inode) - get_inline_xattr_addrs(inode);
+       unsigned int addrs = CUR_ADDRS_PER_INODE(inode) -
+                               get_inline_xattr_addrs(inode);
+       return ALIGN_DOWN(addrs, 1);
+}
+
+static inline unsigned int addrs_per_block(struct inode *inode)
+{
+       return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, 1);
 }
 
 static inline void *inline_xattr_addr(struct inode *inode, struct page *page)
@@ -2558,7 +2604,9 @@ static inline void *inline_xattr_addr(struct inode *inode, struct page *page)
 
 static inline int inline_xattr_size(struct inode *inode)
 {
-       return get_inline_xattr_addrs(inode) * sizeof(__le32);
+       if (f2fs_has_inline_xattr(inode))
+               return get_inline_xattr_addrs(inode) * sizeof(__le32);
+       return 0;
 }
 
 static inline int f2fs_has_inline_data(struct inode *inode)
@@ -2800,12 +2848,10 @@ static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
 
 #define __is_large_section(sbi)                ((sbi)->segs_per_sec > 1)
 
-#define __is_meta_io(fio) (PAGE_TYPE_OF_BIO((fio)->type) == META &&    \
-                               (!is_read_io((fio)->op) || (fio)->is_meta))
+#define __is_meta_io(fio) (PAGE_TYPE_OF_BIO((fio)->type) == META)
 
 bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
                                        block_t blkaddr, int type);
-void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...);
 static inline void verify_blkaddr(struct f2fs_sb_info *sbi,
                                        block_t blkaddr, int type)
 {
@@ -2824,15 +2870,6 @@ static inline bool __is_valid_data_blkaddr(block_t blkaddr)
        return true;
 }
 
-static inline bool is_valid_data_blkaddr(struct f2fs_sb_info *sbi,
-                                               block_t blkaddr)
-{
-       if (!__is_valid_data_blkaddr(blkaddr))
-               return false;
-       verify_blkaddr(sbi, blkaddr, DATA_GENERIC);
-       return true;
-}
-
 static inline void f2fs_set_page_private(struct page *page,
                                                unsigned long data)
 {
@@ -3530,16 +3567,12 @@ F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND);
 F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM);
 
 #ifdef CONFIG_BLK_DEV_ZONED
-static inline int get_blkz_type(struct f2fs_sb_info *sbi,
-                       struct block_device *bdev, block_t blkaddr)
+static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
+                                   block_t blkaddr)
 {
        unsigned int zno = blkaddr >> sbi->log_blocks_per_blkz;
-       int i;
 
-       for (i = 0; i < sbi->s_ndevs; i++)
-               if (FDEV(i).bdev == bdev)
-                       return FDEV(i).blkz_type[zno];
-       return -EINVAL;
+       return test_bit(zno, FDEV(devi).blkz_seq);
 }
 #endif
 
@@ -3548,9 +3581,23 @@ static inline bool f2fs_hw_should_discard(struct f2fs_sb_info *sbi)
        return f2fs_sb_has_blkzoned(sbi);
 }
 
+static inline bool f2fs_bdev_support_discard(struct block_device *bdev)
+{
+       return blk_queue_discard(bdev_get_queue(bdev)) ||
+              bdev_is_zoned(bdev);
+}
+
 static inline bool f2fs_hw_support_discard(struct f2fs_sb_info *sbi)
 {
-       return blk_queue_discard(bdev_get_queue(sbi->sb->s_bdev));
+       int i;
+
+       if (!f2fs_is_multi_device(sbi))
+               return f2fs_bdev_support_discard(sbi->sb->s_bdev);
+
+       for (i = 0; i < sbi->s_ndevs; i++)
+               if (f2fs_bdev_support_discard(FDEV(i).bdev))
+                       return true;
+       return false;
 }
 
 static inline bool f2fs_realtime_discard_enable(struct f2fs_sb_info *sbi)
@@ -3559,6 +3606,20 @@ static inline bool f2fs_realtime_discard_enable(struct f2fs_sb_info *sbi)
                                        f2fs_hw_should_discard(sbi);
 }
 
+static inline bool f2fs_hw_is_readonly(struct f2fs_sb_info *sbi)
+{
+       int i;
+
+       if (!f2fs_is_multi_device(sbi))
+               return bdev_read_only(sbi->sb->s_bdev);
+
+       for (i = 0; i < sbi->s_ndevs; i++)
+               if (bdev_read_only(FDEV(i).bdev))
+                       return true;
+       return false;
+}
+
+
 static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)
 {
        clear_opt(sbi, ADAPTIVE);
@@ -3614,7 +3675,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
@@ -3651,4 +3712,4 @@ static inline bool is_journalled_quota(struct f2fs_sb_info *sbi)
        return false;
 }
 
-#endif
+#endif /* _LINUX_F2FS_H */