]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/f2fs/segment.c
Merge tag 'mips_5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[linux.git] / fs / f2fs / segment.c
index 67e43b1c22e4da430b1a0a9b3756ebe7856bf0cf..8087095814819d21dc2fa056b5a776dc2527699e 100644 (file)
@@ -185,8 +185,6 @@ bool f2fs_need_SSR(struct f2fs_sb_info *sbi)
 
 void f2fs_register_inmem_page(struct inode *inode, struct page *page)
 {
-       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       struct f2fs_inode_info *fi = F2FS_I(inode);
        struct inmem_pages *new;
 
        f2fs_trace_pid(page);
@@ -200,15 +198,11 @@ void f2fs_register_inmem_page(struct inode *inode, struct page *page)
        INIT_LIST_HEAD(&new->list);
 
        /* increase reference count with clean state */
-       mutex_lock(&fi->inmem_lock);
        get_page(page);
-       list_add_tail(&new->list, &fi->inmem_pages);
-       spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
-       if (list_empty(&fi->inmem_ilist))
-               list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
-       spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
+       mutex_lock(&F2FS_I(inode)->inmem_lock);
+       list_add_tail(&new->list, &F2FS_I(inode)->inmem_pages);
        inc_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES);
-       mutex_unlock(&fi->inmem_lock);
+       mutex_unlock(&F2FS_I(inode)->inmem_lock);
 
        trace_f2fs_register_inmem_page(page, INMEM);
 }
@@ -330,19 +324,17 @@ void f2fs_drop_inmem_pages(struct inode *inode)
                mutex_lock(&fi->inmem_lock);
                __revoke_inmem_pages(inode, &fi->inmem_pages,
                                                true, false, true);
-
-               if (list_empty(&fi->inmem_pages)) {
-                       spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
-                       if (!list_empty(&fi->inmem_ilist))
-                               list_del_init(&fi->inmem_ilist);
-                       spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
-               }
                mutex_unlock(&fi->inmem_lock);
        }
 
        clear_inode_flag(inode, FI_ATOMIC_FILE);
        fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
        stat_dec_atomic_write(inode);
+
+       spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
+       if (!list_empty(&fi->inmem_ilist))
+               list_del_init(&fi->inmem_ilist);
+       spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
 }
 
 void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
@@ -471,11 +463,6 @@ int f2fs_commit_inmem_pages(struct inode *inode)
 
        mutex_lock(&fi->inmem_lock);
        err = __f2fs_commit_inmem_pages(inode);
-
-       spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
-       if (!list_empty(&fi->inmem_ilist))
-               list_del_init(&fi->inmem_ilist);
-       spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
        mutex_unlock(&fi->inmem_lock);
 
        clear_inode_flag(inode, FI_ATOMIC_COMMIT);
@@ -501,7 +488,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
        if (need && excess_cached_nats(sbi))
                f2fs_balance_fs_bg(sbi);
 
-       if (f2fs_is_checkpoint_ready(sbi))
+       if (!f2fs_is_checkpoint_ready(sbi))
                return;
 
        /*
@@ -817,9 +804,13 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
                if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
                        dirty_i->nr_dirty[t]--;
 
-               if (get_valid_blocks(sbi, segno, true) == 0)
+               if (get_valid_blocks(sbi, segno, true) == 0) {
                        clear_bit(GET_SEC_FROM_SEG(sbi, segno),
                                                dirty_i->victim_secmap);
+#ifdef CONFIG_F2FS_CHECK_FS
+                       clear_bit(segno, SIT_I(sbi)->invalid_segmap);
+#endif
+               }
        }
 }
 
@@ -2163,9 +2154,11 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
                if (!f2fs_test_and_set_bit(offset, se->discard_map))
                        sbi->discard_blks--;
 
-               /* don't overwrite by SSR to keep node chain */
-               if (IS_NODESEG(se->type) &&
-                               !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) {
+               /*
+                * SSR should never reuse block which is checkpointed
+                * or newly invalidated.
+                */
+               if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED)) {
                        if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map))
                                se->ckpt_valid_blocks++;
                }
@@ -3123,12 +3116,14 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
                f2fs_inode_chksum_set(sbi, page);
        }
 
+       if (F2FS_IO_ALIGNED(sbi))
+               fio->retry = false;
+
        if (add_list) {
                struct f2fs_bio_info *io;
 
                INIT_LIST_HEAD(&fio->list);
                fio->in_list = true;
-               fio->retry = false;
                io = sbi->write_io[fio->type] + fio->temp;
                spin_lock(&io->io_lock);
                list_add_tail(&fio->list, &io->io_list);
@@ -3943,8 +3938,8 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
        struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
        struct sit_info *sit_i;
        unsigned int sit_segs, start;
-       char *src_bitmap;
-       unsigned int bitmap_size;
+       char *src_bitmap, *bitmap;
+       unsigned int bitmap_size, main_bitmap_size, sit_bitmap_size;
 
        /* allocate memory for SIT information */
        sit_i = f2fs_kzalloc(sbi, sizeof(struct sit_info), GFP_KERNEL);
@@ -3960,33 +3955,37 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
        if (!sit_i->sentries)
                return -ENOMEM;
 
-       bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
-       sit_i->dirty_sentries_bitmap = f2fs_kvzalloc(sbi, bitmap_size,
+       main_bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
+       sit_i->dirty_sentries_bitmap = f2fs_kvzalloc(sbi, main_bitmap_size,
                                                                GFP_KERNEL);
        if (!sit_i->dirty_sentries_bitmap)
                return -ENOMEM;
 
+#ifdef CONFIG_F2FS_CHECK_FS
+       bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * 4;
+#else
+       bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * 3;
+#endif
+       sit_i->bitmap = f2fs_kvzalloc(sbi, bitmap_size, GFP_KERNEL);
+       if (!sit_i->bitmap)
+               return -ENOMEM;
+
+       bitmap = sit_i->bitmap;
+
        for (start = 0; start < MAIN_SEGS(sbi); start++) {
-               sit_i->sentries[start].cur_valid_map
-                       = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
-               sit_i->sentries[start].ckpt_valid_map
-                       = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
-               if (!sit_i->sentries[start].cur_valid_map ||
-                               !sit_i->sentries[start].ckpt_valid_map)
-                       return -ENOMEM;
+               sit_i->sentries[start].cur_valid_map = bitmap;
+               bitmap += SIT_VBLOCK_MAP_SIZE;
+
+               sit_i->sentries[start].ckpt_valid_map = bitmap;
+               bitmap += SIT_VBLOCK_MAP_SIZE;
 
 #ifdef CONFIG_F2FS_CHECK_FS
-               sit_i->sentries[start].cur_valid_map_mir
-                       = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
-               if (!sit_i->sentries[start].cur_valid_map_mir)
-                       return -ENOMEM;
+               sit_i->sentries[start].cur_valid_map_mir = bitmap;
+               bitmap += SIT_VBLOCK_MAP_SIZE;
 #endif
 
-               sit_i->sentries[start].discard_map
-                       = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE,
-                                                       GFP_KERNEL);
-               if (!sit_i->sentries[start].discard_map)
-                       return -ENOMEM;
+               sit_i->sentries[start].discard_map = bitmap;
+               bitmap += SIT_VBLOCK_MAP_SIZE;
        }
 
        sit_i->tmp_map = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
@@ -4006,17 +4005,23 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
        sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1;
 
        /* setup SIT bitmap from ckeckpoint pack */
-       bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
+       sit_bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
        src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
 
-       sit_i->sit_bitmap = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL);
+       sit_i->sit_bitmap = kmemdup(src_bitmap, sit_bitmap_size, GFP_KERNEL);
        if (!sit_i->sit_bitmap)
                return -ENOMEM;
 
 #ifdef CONFIG_F2FS_CHECK_FS
-       sit_i->sit_bitmap_mir = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL);
+       sit_i->sit_bitmap_mir = kmemdup(src_bitmap,
+                                       sit_bitmap_size, GFP_KERNEL);
        if (!sit_i->sit_bitmap_mir)
                return -ENOMEM;
+
+       sit_i->invalid_segmap = f2fs_kvzalloc(sbi,
+                                       main_bitmap_size, GFP_KERNEL);
+       if (!sit_i->invalid_segmap)
+               return -ENOMEM;
 #endif
 
        /* init SIT information */
@@ -4025,7 +4030,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
        sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr);
        sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg;
        sit_i->written_valid_blocks = 0;
-       sit_i->bitmap_size = bitmap_size;
+       sit_i->bitmap_size = sit_bitmap_size;
        sit_i->dirty_sentries = 0;
        sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
        sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time);
@@ -4492,21 +4497,12 @@ static void destroy_free_segmap(struct f2fs_sb_info *sbi)
 static void destroy_sit_info(struct f2fs_sb_info *sbi)
 {
        struct sit_info *sit_i = SIT_I(sbi);
-       unsigned int start;
 
        if (!sit_i)
                return;
 
-       if (sit_i->sentries) {
-               for (start = 0; start < MAIN_SEGS(sbi); start++) {
-                       kvfree(sit_i->sentries[start].cur_valid_map);
-#ifdef CONFIG_F2FS_CHECK_FS
-                       kvfree(sit_i->sentries[start].cur_valid_map_mir);
-#endif
-                       kvfree(sit_i->sentries[start].ckpt_valid_map);
-                       kvfree(sit_i->sentries[start].discard_map);
-               }
-       }
+       if (sit_i->sentries)
+               kvfree(sit_i->bitmap);
        kvfree(sit_i->tmp_map);
 
        kvfree(sit_i->sentries);
@@ -4517,6 +4513,7 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi)
        kvfree(sit_i->sit_bitmap);
 #ifdef CONFIG_F2FS_CHECK_FS
        kvfree(sit_i->sit_bitmap_mir);
+       kvfree(sit_i->invalid_segmap);
 #endif
        kvfree(sit_i);
 }