Merge tag 'ftracetest-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[firefly-linux-kernel-4.4.55.git] / fs / f2fs / checkpoint.c
index ec3b7a5381fa3fca2165aa9bcdb7402c0eace5bc..dd10a031c0523700cadee8346d254685f45fe9db 100644 (file)
@@ -72,7 +72,22 @@ out:
        return page;
 }
 
-static inline int get_max_meta_blks(struct f2fs_sb_info *sbi, int type)
+struct page *get_meta_page_ra(struct f2fs_sb_info *sbi, pgoff_t index)
+{
+       bool readahead = false;
+       struct page *page;
+
+       page = find_get_page(META_MAPPING(sbi), index);
+       if (!page || (page && !PageUptodate(page)))
+               readahead = true;
+       f2fs_put_page(page, 0);
+
+       if (readahead)
+               ra_meta_pages(sbi, index, MAX_BIO_BLOCKS(sbi), META_POR);
+       return get_meta_page(sbi, index);
+}
+
+static inline block_t get_max_meta_blks(struct f2fs_sb_info *sbi, int type)
 {
        switch (type) {
        case META_NAT:
@@ -82,6 +97,8 @@ static inline int get_max_meta_blks(struct f2fs_sb_info *sbi, int type)
        case META_SSA:
        case META_CP:
                return 0;
+       case META_POR:
+               return MAX_BLKADDR(sbi);
        default:
                BUG();
        }
@@ -90,12 +107,12 @@ static inline int get_max_meta_blks(struct f2fs_sb_info *sbi, int type)
 /*
  * Readahead CP/NAT/SIT/SSA pages
  */
-int ra_meta_pages(struct f2fs_sb_info *sbi, int start, int nrpages, int type)
+int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, int type)
 {
        block_t prev_blk_addr = 0;
        struct page *page;
-       int blkno = start;
-       int max_blks = get_max_meta_blks(sbi, type);
+       block_t blkno = start;
+       block_t max_blks = get_max_meta_blks(sbi, type);
 
        struct f2fs_io_info fio = {
                .type = META,
@@ -125,7 +142,11 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, int start, int nrpages, int type)
                        break;
                case META_SSA:
                case META_CP:
-                       /* get ssa/cp block addr */
+               case META_POR:
+                       if (unlikely(blkno >= max_blks))
+                               goto out;
+                       if (unlikely(blkno < SEG0_BLKADDR(sbi)))
+                               goto out;
                        blk_addr = blkno;
                        break;
                default:
@@ -151,8 +172,7 @@ out:
 static int f2fs_write_meta_page(struct page *page,
                                struct writeback_control *wbc)
 {
-       struct inode *inode = page->mapping->host;
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_sb_info *sbi = F2FS_P_SB(page);
 
        trace_f2fs_writepage(page, META);
 
@@ -177,7 +197,7 @@ redirty_out:
 static int f2fs_write_meta_pages(struct address_space *mapping,
                                struct writeback_control *wbc)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+       struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
        long diff, written;
 
        trace_f2fs_writepages(mapping->host, wbc, META);
@@ -259,15 +279,12 @@ continue_unlock:
 
 static int f2fs_set_meta_page_dirty(struct page *page)
 {
-       struct address_space *mapping = page->mapping;
-       struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
-
        trace_f2fs_set_page_dirty(page, META);
 
        SetPageUptodate(page);
        if (!PageDirty(page)) {
                __set_page_dirty_nobuffers(page);
-               inc_page_count(sbi, F2FS_DIRTY_META);
+               inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
                return 1;
        }
        return 0;
@@ -378,7 +395,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
 void release_orphan_inode(struct f2fs_sb_info *sbi)
 {
        spin_lock(&sbi->ino_lock[ORPHAN_INO]);
-       f2fs_bug_on(sbi->n_orphans == 0);
+       f2fs_bug_on(sbi, sbi->n_orphans == 0);
        sbi->n_orphans--;
        spin_unlock(&sbi->ino_lock[ORPHAN_INO]);
 }
@@ -398,7 +415,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
 static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
 {
        struct inode *inode = f2fs_iget(sbi->sb, ino);
-       f2fs_bug_on(IS_ERR(inode));
+       f2fs_bug_on(sbi, IS_ERR(inode));
        clear_nlink(inode);
 
        /* truncate all the data during iput */
@@ -459,7 +476,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
        list_for_each_entry(orphan, head, list) {
                if (!page) {
                        page = find_get_page(META_MAPPING(sbi), start_blk++);
-                       f2fs_bug_on(!page);
+                       f2fs_bug_on(sbi, !page);
                        orphan_blk =
                                (struct f2fs_orphan_block *)page_address(page);
                        memset(orphan_blk, 0, sizeof(*orphan_blk));
@@ -619,7 +636,7 @@ fail_no_cp:
 
 static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 
        if (is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR))
                return -EEXIST;
@@ -631,32 +648,38 @@ static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
        return 0;
 }
 
-void set_dirty_dir_page(struct inode *inode, struct page *page)
+void update_dirty_page(struct inode *inode, struct page *page)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct dir_inode_entry *new;
        int ret = 0;
 
-       if (!S_ISDIR(inode->i_mode))
+       if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode))
                return;
 
+       if (!S_ISDIR(inode->i_mode)) {
+               inode_inc_dirty_pages(inode);
+               goto out;
+       }
+
        new = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
        new->inode = inode;
        INIT_LIST_HEAD(&new->list);
 
        spin_lock(&sbi->dir_inode_lock);
        ret = __add_dirty_inode(inode, new);
-       inode_inc_dirty_dents(inode);
-       SetPagePrivate(page);
+       inode_inc_dirty_pages(inode);
        spin_unlock(&sbi->dir_inode_lock);
 
        if (ret)
                kmem_cache_free(inode_entry_slab, new);
+out:
+       SetPagePrivate(page);
 }
 
 void add_dirty_dir_inode(struct inode *inode)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct dir_inode_entry *new =
                        f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
        int ret = 0;
@@ -674,14 +697,14 @@ void add_dirty_dir_inode(struct inode *inode)
 
 void remove_dirty_dir_inode(struct inode *inode)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct dir_inode_entry *entry;
 
        if (!S_ISDIR(inode->i_mode))
                return;
 
        spin_lock(&sbi->dir_inode_lock);
-       if (get_dirty_dents(inode) ||
+       if (get_dirty_pages(inode) ||
                        !is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) {
                spin_unlock(&sbi->dir_inode_lock);
                return;
@@ -802,11 +825,12 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
        finish_wait(&sbi->cp_wait, &wait);
 }
 
-static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
+static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 {
        struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
        struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
-       nid_t last_nid = 0;
+       struct f2fs_nm_info *nm_i = NM_I(sbi);
+       nid_t last_nid = nm_i->next_scan_nid;
        block_t start_blk;
        struct page *cp_page;
        unsigned int data_sum_blocks, orphan_blocks;
@@ -869,7 +893,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
                        orphan_blocks);
 
-       if (is_umount) {
+       if (cpc->reason == CP_UMOUNT) {
                set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
                ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS+
                                cp_payload_blks + data_sum_blocks +
@@ -886,6 +910,9 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        else
                clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
 
+       if (sbi->need_fsck)
+               set_ckpt_flags(ckpt, CP_FSCK_FLAG);
+
        /* update SIT/NAT bitmap */
        get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
        get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
@@ -920,7 +947,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 
        write_data_summaries(sbi, start_blk);
        start_blk += data_sum_blocks;
-       if (is_umount) {
+       if (cpc->reason == CP_UMOUNT) {
                write_node_summaries(sbi, start_blk);
                start_blk += NR_CURSEG_NODE_TYPE;
        }
@@ -960,23 +987,23 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 /*
  * We guarantee that this checkpoint procedure will not fail.
  */
-void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
+void write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 {
        struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
        unsigned long long ckpt_ver;
 
-       trace_f2fs_write_checkpoint(sbi->sb, is_umount, "start block_ops");
+       trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops");
 
        mutex_lock(&sbi->cp_mutex);
 
-       if (!sbi->s_dirty)
+       if (!sbi->s_dirty && cpc->reason != CP_DISCARD)
                goto out;
        if (unlikely(f2fs_cp_error(sbi)))
                goto out;
        if (block_operations(sbi))
                goto out;
 
-       trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops");
+       trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops");
 
        f2fs_submit_merged_bio(sbi, DATA, WRITE);
        f2fs_submit_merged_bio(sbi, NODE, WRITE);
@@ -992,16 +1019,16 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 
        /* write cached NAT/SIT entries to NAT/SIT area */
        flush_nat_entries(sbi);
-       flush_sit_entries(sbi);
+       flush_sit_entries(sbi, cpc);
 
        /* unlock all the fs_lock[] in do_checkpoint() */
-       do_checkpoint(sbi, is_umount);
+       do_checkpoint(sbi, cpc);
 
        unblock_operations(sbi);
        stat_inc_cp_count(sbi->stat_info);
 out:
        mutex_unlock(&sbi->cp_mutex);
-       trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint");
+       trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint");
 }
 
 void init_ino_entry_info(struct f2fs_sb_info *sbi)