Merge branch 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[linux-2.6-block.git] / fs / f2fs / checkpoint.c
index 0955312e5ca042fe45f88e0c10714d79f3fb8778..3891600499939895600bfc9aed37c6f2b5e1d53d 100644 (file)
 static struct kmem_cache *ino_entry_slab;
 struct kmem_cache *inode_entry_slab;
 
+void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io)
+{
+       set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+       sbi->sb->s_flags |= MS_RDONLY;
+       if (!end_io)
+               f2fs_flush_merged_bios(sbi);
+}
+
 /*
  * We guarantee no failure on the returned page.
  */
@@ -34,7 +42,7 @@ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
        struct address_space *mapping = META_MAPPING(sbi);
        struct page *page = NULL;
 repeat:
-       page = grab_cache_page(mapping, index);
+       page = f2fs_grab_cache_page(mapping, index, false);
        if (!page) {
                cond_resched();
                goto repeat;
@@ -64,7 +72,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
        if (unlikely(!is_meta))
                fio.rw &= ~REQ_META;
 repeat:
-       page = grab_cache_page(mapping, index);
+       page = f2fs_grab_cache_page(mapping, index, false);
        if (!page) {
                cond_resched();
                goto repeat;
@@ -91,7 +99,7 @@ repeat:
         * meta page.
         */
        if (unlikely(!PageUptodate(page)))
-               f2fs_stop_checkpoint(sbi);
+               f2fs_stop_checkpoint(sbi, false);
 out:
        return page;
 }
@@ -186,7 +194,8 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
                        BUG();
                }
 
-               page = grab_cache_page(META_MAPPING(sbi), fio.new_blkaddr);
+               page = f2fs_grab_cache_page(META_MAPPING(sbi),
+                                               fio.new_blkaddr, false);
                if (!page)
                        continue;
                if (PageUptodate(page)) {
@@ -211,7 +220,7 @@ void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index)
        bool readahead = false;
 
        page = find_get_page(META_MAPPING(sbi), index);
-       if (!page || (page && !PageUptodate(page)))
+       if (!page || !PageUptodate(page))
                readahead = true;
        f2fs_put_page(page, 0);
 
@@ -448,12 +457,12 @@ bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
        return e ? true : false;
 }
 
-void release_ino_entry(struct f2fs_sb_info *sbi)
+void release_ino_entry(struct f2fs_sb_info *sbi, bool all)
 {
        struct ino_entry *e, *tmp;
        int i;
 
-       for (i = APPEND_INO; i <= UPDATE_INO; i++) {
+       for (i = all ? ORPHAN_INO: APPEND_INO; i <= UPDATE_INO; i++) {
                struct inode_management *im = &sbi->im[i];
 
                spin_lock(&im->ino_lock);
@@ -473,6 +482,13 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
        int err = 0;
 
        spin_lock(&im->ino_lock);
+
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+       if (time_to_inject(FAULT_ORPHAN)) {
+               spin_unlock(&im->ino_lock);
+               return -ENOSPC;
+       }
+#endif
        if (unlikely(im->ino_num >= sbi->max_orphans))
                err = -ENOSPC;
        else
@@ -777,43 +793,32 @@ void update_dirty_page(struct inode *inode, struct page *page)
                        !S_ISLNK(inode->i_mode))
                return;
 
-       spin_lock(&sbi->inode_lock[type]);
-       __add_dirty_inode(inode, type);
-       inode_inc_dirty_pages(inode);
-       spin_unlock(&sbi->inode_lock[type]);
+       if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH)) {
+               spin_lock(&sbi->inode_lock[type]);
+               __add_dirty_inode(inode, type);
+               spin_unlock(&sbi->inode_lock[type]);
+       }
 
+       inode_inc_dirty_pages(inode);
        SetPagePrivate(page);
        f2fs_trace_pid(page);
 }
 
-void add_dirty_dir_inode(struct inode *inode)
-{
-       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-
-       spin_lock(&sbi->inode_lock[DIR_INODE]);
-       __add_dirty_inode(inode, DIR_INODE);
-       spin_unlock(&sbi->inode_lock[DIR_INODE]);
-}
-
 void remove_dirty_inode(struct inode *inode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       struct f2fs_inode_info *fi = F2FS_I(inode);
        enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE;
 
        if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
                        !S_ISLNK(inode->i_mode))
                return;
 
+       if (type == FILE_INODE && !test_opt(sbi, DATA_FLUSH))
+               return;
+
        spin_lock(&sbi->inode_lock[type]);
        __remove_dirty_inode(inode, type);
        spin_unlock(&sbi->inode_lock[type]);
-
-       /* Only from the recovery routine */
-       if (is_inode_flag_set(fi, FI_DELAY_IPUT)) {
-               clear_inode_flag(fi, FI_DELAY_IPUT);
-               iput(inode);
-       }
 }
 
 int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
@@ -892,7 +897,7 @@ retry_flush_nodes:
 
        if (get_pages(sbi, F2FS_DIRTY_NODES)) {
                up_write(&sbi->node_write);
-               err = sync_node_pages(sbi, 0, &wbc);
+               err = sync_node_pages(sbi, &wbc);
                if (err) {
                        f2fs_unlock_all(sbi);
                        goto out;
@@ -917,7 +922,7 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
        for (;;) {
                prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);
 
-               if (!get_pages(sbi, F2FS_WRITEBACK))
+               if (!atomic_read(&sbi->nr_wb_bios))
                        break;
 
                io_schedule_timeout(5*HZ);
@@ -1082,7 +1087,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 
        /* update user_block_counts */
        sbi->last_valid_block_count = sbi->total_valid_block_count;
-       sbi->alloc_valid_block_count = 0;
+       percpu_counter_set(&sbi->alloc_valid_block_count, 0);
 
        /* Here, we only have one bio having CP pack */
        sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
@@ -1098,7 +1103,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
                invalidate_mapping_pages(META_MAPPING(sbi), discard_blk,
                                                                discard_blk);
 
-       release_ino_entry(sbi);
+       release_ino_entry(sbi, false);
 
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;