]> git.ipfire.org Git - people/ms/linux.git/blobdiff - fs/f2fs/segment.c
Merge branch 'for-6.0/dax' into libnvdimm-fixes
[people/ms/linux.git] / fs / f2fs / segment.c
index 874c1b9c41a2ae7b949cc6a257c760b925d1d235..0de21f82d7bc835c6df05e1ba8a6b8b6d7918e25 100644 (file)
@@ -190,18 +190,20 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean)
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct f2fs_inode_info *fi = F2FS_I(inode);
 
-       if (f2fs_is_atomic_file(inode)) {
-               if (clean)
-                       truncate_inode_pages_final(inode->i_mapping);
-               clear_inode_flag(fi->cow_inode, FI_ATOMIC_FILE);
-               iput(fi->cow_inode);
-               fi->cow_inode = NULL;
-               clear_inode_flag(inode, FI_ATOMIC_FILE);
+       if (!f2fs_is_atomic_file(inode))
+               return;
 
-               spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
-               sbi->atomic_files--;
-               spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
-       }
+       if (clean)
+               truncate_inode_pages_final(inode->i_mapping);
+       clear_inode_flag(fi->cow_inode, FI_COW_FILE);
+       iput(fi->cow_inode);
+       fi->cow_inode = NULL;
+       release_atomic_write_cnt(inode);
+       clear_inode_flag(inode, FI_ATOMIC_FILE);
+
+       spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
+       sbi->atomic_files--;
+       spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
 }
 
 static int __replace_atomic_write_block(struct inode *inode, pgoff_t index,
@@ -335,6 +337,11 @@ next:
        }
 
 out:
+       if (ret)
+               sbi->revoked_atomic_block += fi->atomic_write_cnt;
+       else
+               sbi->committed_atomic_block += fi->atomic_write_cnt;
+
        __complete_revoke_list(inode, &revoke_list, ret ? true : false);
 
        return ret;
@@ -728,7 +735,7 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
                                get_valid_blocks(sbi, segno, true);
 
                        f2fs_bug_on(sbi, unlikely(!valid_blocks ||
-                                       valid_blocks == BLKS_PER_SEC(sbi)));
+                                       valid_blocks == CAP_BLKS_PER_SEC(sbi)));
 
                        if (!IS_CURSEC(sbi, secno))
                                set_bit(secno, dirty_i->dirty_secmap);
@@ -764,7 +771,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
                        unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
 
                        if (!valid_blocks ||
-                                       valid_blocks == BLKS_PER_SEC(sbi)) {
+                                       valid_blocks == CAP_BLKS_PER_SEC(sbi)) {
                                clear_bit(secno, dirty_i->dirty_secmap);
                                return;
                        }
@@ -1082,7 +1089,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
        struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
        struct list_head *wait_list = (dpolicy->type == DPOLICY_FSTRIM) ?
                                        &(dcc->fstrim_list) : &(dcc->wait_list);
-       int flag = dpolicy->sync ? REQ_SYNC : 0;
+       blk_opf_t flag = dpolicy->sync ? REQ_SYNC : 0;
        block_t lstart, start, len, total_len;
        int err = 0;
 
@@ -3166,7 +3173,7 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
                        return CURSEG_COLD_DATA;
                if (file_is_hot(inode) ||
                                is_inode_flag_set(inode, FI_HOT_DATA) ||
-                               f2fs_is_atomic_file(inode))
+                               f2fs_is_cow_file(inode))
                        return CURSEG_HOT_DATA;
                return f2fs_rw_hint_to_seg_type(inode->i_write_hint);
        } else {
@@ -3433,7 +3440,8 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
                goto drop_bio;
        }
 
-       invalidate_mapping_pages(META_MAPPING(sbi),
+       if (fio->post_read)
+               invalidate_mapping_pages(META_MAPPING(sbi),
                                fio->new_blkaddr, fio->new_blkaddr);
 
        stat_inc_inplace_blocks(fio->sbi);
@@ -3616,10 +3624,16 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
 void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
                                                                block_t len)
 {
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        block_t i;
 
+       if (!f2fs_post_read_required(inode))
+               return;
+
        for (i = 0; i < len; i++)
                f2fs_wait_on_block_writeback(inode, blkaddr + i);
+
+       invalidate_mapping_pages(META_MAPPING(sbi), blkaddr, blkaddr + len - 1);
 }
 
 static int read_compacted_summaries(struct f2fs_sb_info *sbi)
@@ -4362,6 +4376,12 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
                                return err;
                        seg_info_from_raw_sit(se, &sit);
 
+                       if (se->type >= NR_PERSISTENT_LOG) {
+                               f2fs_err(sbi, "Invalid segment type: %u, segno: %u",
+                                                       se->type, start);
+                               return -EFSCORRUPTED;
+                       }
+
                        sit_valid_blocks[SE_PAGETYPE(se)] += se->valid_blocks;
 
                        if (f2fs_block_unit_discard(sbi)) {
@@ -4410,6 +4430,13 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
                        break;
                seg_info_from_raw_sit(se, &sit);
 
+               if (se->type >= NR_PERSISTENT_LOG) {
+                       f2fs_err(sbi, "Invalid segment type: %u, segno: %u",
+                                                       se->type, start);
+                       err = -EFSCORRUPTED;
+                       break;
+               }
+
                sit_valid_blocks[SE_PAGETYPE(se)] += se->valid_blocks;
 
                if (f2fs_block_unit_discard(sbi)) {
@@ -4483,7 +4510,6 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi)
        struct free_segmap_info *free_i = FREE_I(sbi);
        unsigned int segno = 0, offset = 0, secno;
        block_t valid_blocks, usable_blks_in_seg;
-       block_t blks_per_sec = BLKS_PER_SEC(sbi);
 
        while (1) {
                /* find dirty segment based on free segmap */
@@ -4512,7 +4538,7 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi)
                valid_blocks = get_valid_blocks(sbi, segno, true);
                secno = GET_SEC_FROM_SEG(sbi, segno);
 
-               if (!valid_blocks || valid_blocks == blks_per_sec)
+               if (!valid_blocks || valid_blocks == CAP_BLKS_PER_SEC(sbi))
                        continue;
                if (IS_CURSEC(sbi, secno))
                        continue;
@@ -4895,7 +4921,7 @@ static unsigned int get_zone_idx(struct f2fs_sb_info *sbi, unsigned int secno,
 static inline unsigned int f2fs_usable_zone_segs_in_sec(
                struct f2fs_sb_info *sbi, unsigned int segno)
 {
-       unsigned int dev_idx, zone_idx, unusable_segs_in_sec;
+       unsigned int dev_idx, zone_idx;
 
        dev_idx = f2fs_target_device_index(sbi, START_BLOCK(sbi, segno));
        zone_idx = get_zone_idx(sbi, GET_SEC_FROM_SEG(sbi, segno), dev_idx);
@@ -4904,18 +4930,12 @@ static inline unsigned int f2fs_usable_zone_segs_in_sec(
        if (is_conv_zone(sbi, zone_idx, dev_idx))
                return sbi->segs_per_sec;
 
-       /*
-        * If the zone_capacity_blocks array is NULL, then zone capacity
-        * is equal to the zone size for all zones
-        */
-       if (!FDEV(dev_idx).zone_capacity_blocks)
+       if (!sbi->unusable_blocks_per_sec)
                return sbi->segs_per_sec;
 
        /* Get the segment count beyond zone capacity block */
-       unusable_segs_in_sec = (sbi->blocks_per_blkz -
-                               FDEV(dev_idx).zone_capacity_blocks[zone_idx]) >>
-                               sbi->log_blocks_per_seg;
-       return sbi->segs_per_sec - unusable_segs_in_sec;
+       return sbi->segs_per_sec - (sbi->unusable_blocks_per_sec >>
+                                               sbi->log_blocks_per_seg);
 }
 
 /*
@@ -4944,12 +4964,11 @@ static inline unsigned int f2fs_usable_zone_blks_in_seg(
        if (is_conv_zone(sbi, zone_idx, dev_idx))
                return sbi->blocks_per_seg;
 
-       if (!FDEV(dev_idx).zone_capacity_blocks)
+       if (!sbi->unusable_blocks_per_sec)
                return sbi->blocks_per_seg;
 
        sec_start_blkaddr = START_BLOCK(sbi, GET_SEG_FROM_SEC(sbi, secno));
-       sec_cap_blkaddr = sec_start_blkaddr +
-                               FDEV(dev_idx).zone_capacity_blocks[zone_idx];
+       sec_cap_blkaddr = sec_start_blkaddr + CAP_BLKS_PER_SEC(sbi);
 
        /*
         * If segment starts before zone capacity and spans beyond