f2fs: use meta_inode cache to improve roll-forward speed
[linux-3.10.git] / fs / f2fs / f2fs.h
index 90ed0ba..9941b83 100644 (file)
 #include <linux/sched.h>
 
 #ifdef CONFIG_F2FS_CHECK_FS
-#define f2fs_bug_on(condition) BUG_ON(condition)
+#define f2fs_bug_on(sbi, condition)    BUG_ON(condition)
 #define f2fs_down_write(x, y)  down_write_nest_lock(x, y)
 #else
-#define f2fs_bug_on(condition)
+#define f2fs_bug_on(sbi, condition)                                    \
+       do {                                                            \
+               if (unlikely(condition)) {                              \
+                       WARN_ON(1);                                     \
+                       sbi->need_fsck = true;                          \
+               }                                                       \
+       } while (0)
 #define f2fs_down_write(x, y)  down_write(x)
 #endif
 
@@ -100,7 +106,8 @@ enum {
        META_CP,
        META_NAT,
        META_SIT,
-       META_SSA
+       META_SSA,
+       META_POR,
 };
 
 /* for the list of ino */
@@ -158,6 +165,15 @@ static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
        return before;
 }
 
+static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,
+                                                               int type)
+{
+       if (type == NAT_JOURNAL)
+               return nats_in_cursum(sum) + size <= NAT_JOURNAL_ENTRIES;
+
+       return sits_in_cursum(sum) + size <= SIT_JOURNAL_ENTRIES;
+}
+
 /*
  * ioctl commands
  */
@@ -227,7 +243,7 @@ struct f2fs_inode_info {
        /* Use below internally in f2fs*/
        unsigned long flags;            /* use to pass per-file flags */
        struct rw_semaphore i_sem;      /* protect fi info */
-       atomic_t dirty_dents;           /* # of dirty dentry pages */
+       atomic_t dirty_pages;           /* # of dirty pages */
        f2fs_hash_t chash;              /* hash value of given file name */
        unsigned int clevel;            /* maximum level of given file name */
        nid_t i_xattr_nid;              /* node id that contains xattrs */
@@ -337,18 +353,16 @@ enum {
 };
 
 struct flush_cmd {
-       struct flush_cmd *next;
        struct completion wait;
+       struct llist_node llnode;
        int ret;
 };
 
 struct flush_cmd_control {
        struct task_struct *f2fs_issue_flush;   /* flush thread */
        wait_queue_head_t flush_wait_queue;     /* waiting queue for wake-up */
-       struct flush_cmd *issue_list;           /* list for command issue */
-       struct flush_cmd *dispatch_list;        /* list for command dispatch */
-       spinlock_t issue_lock;                  /* for issue list lock */
-       struct flush_cmd *issue_tail;           /* list tail of issue list */
+       struct llist_head issue_list;           /* list for command issue */
+       struct llist_node *dispatch_list;       /* list for command dispatch */
 };
 
 struct f2fs_sm_info {
@@ -374,8 +388,11 @@ struct f2fs_sm_info {
        int nr_discards;                        /* # of discards in the list */
        int max_discards;                       /* max. discards to be issued */
 
+       struct list_head sit_entry_set; /* sit entry set list */
+
        unsigned int ipu_policy;        /* in-place-update policy */
        unsigned int min_ipu_util;      /* in-place-update threshold */
+       unsigned int min_fsync_blocks;  /* threshold for fsync */
 
        /* for flush command control */
        struct flush_cmd_control *cmd_control_info;
@@ -444,6 +461,7 @@ struct f2fs_sb_info {
        struct buffer_head *raw_super_buf;      /* buffer head of raw sb */
        struct f2fs_super_block *raw_super;     /* raw super block pointer */
        int s_dirty;                            /* dirty flag for checkpoint */
+       bool need_fsck;                         /* need fsck.f2fs to fix */
 
        /* for node-related operations */
        struct f2fs_nm_info *nm_info;           /* node manager */
@@ -462,7 +480,7 @@ struct f2fs_sb_info {
        struct inode *meta_inode;               /* cache meta blocks */
        struct mutex cp_mutex;                  /* checkpoint procedure lock */
        struct rw_semaphore cp_rwsem;           /* blocking FS operations */
-       struct mutex node_write;                /* locking node writes */
+       struct rw_semaphore node_write;         /* locking node writes */
        struct mutex writepages;                /* mutex for writepages() */
        bool por_doing;                         /* recovery is doing or not */
        wait_queue_head_t cp_wait;
@@ -555,6 +573,21 @@ static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb)
        return sb->s_fs_info;
 }
 
+static inline struct f2fs_sb_info *F2FS_I_SB(struct inode *inode)
+{
+       return F2FS_SB(inode->i_sb);
+}
+
+static inline struct f2fs_sb_info *F2FS_M_SB(struct address_space *mapping)
+{
+       return F2FS_I_SB(mapping->host);
+}
+
+static inline struct f2fs_sb_info *F2FS_P_SB(struct page *page)
+{
+       return F2FS_M_SB(page->mapping);
+}
+
 static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
 {
        return (struct f2fs_super_block *)(sbi->raw_super);
@@ -695,6 +728,7 @@ static inline int f2fs_handle_error(struct f2fs_sb_info *sbi)
        if (test_opt(sbi, ERRORS_PANIC))
                BUG();
        if (test_opt(sbi, ERRORS_RECOVER))
+               sbi->need_fsck = true;
                return 1;
        return 0;
 }
@@ -755,10 +789,11 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
        F2FS_SET_SB_DIRT(sbi);
 }
 
-static inline void inode_inc_dirty_dents(struct inode *inode)
+static inline void inode_inc_dirty_pages(struct inode *inode)
 {
-       inc_page_count(F2FS_SB(inode->i_sb), F2FS_DIRTY_DENTS);
-       atomic_inc(&F2FS_I(inode)->dirty_dents);
+       atomic_inc(&F2FS_I(inode)->dirty_pages);
+       if (S_ISDIR(inode->i_mode))
+               inc_page_count(F2FS_I_SB(inode), F2FS_DIRTY_DENTS);
 }
 
 static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
@@ -766,13 +801,15 @@ static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
        atomic_dec(&sbi->nr_pages[count_type]);
 }
 
-static inline void inode_dec_dirty_dents(struct inode *inode)
+static inline void inode_dec_dirty_pages(struct inode *inode)
 {
-       if (!S_ISDIR(inode->i_mode))
+       if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode))
                return;
 
-       dec_page_count(F2FS_SB(inode->i_sb), F2FS_DIRTY_DENTS);
-       atomic_dec(&F2FS_I(inode)->dirty_dents);
+       atomic_dec(&F2FS_I(inode)->dirty_pages);
+
+       if (S_ISDIR(inode->i_mode))
+               dec_page_count(F2FS_I_SB(inode), F2FS_DIRTY_DENTS);
 }
 
 static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
@@ -780,9 +817,9 @@ static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
        return atomic_read(&sbi->nr_pages[count_type]);
 }
 
-static inline int get_dirty_dents(struct inode *inode)
+static inline int get_dirty_pages(struct inode *inode)
 {
-       return atomic_read(&F2FS_I(inode)->dirty_dents);
+       return atomic_read(&F2FS_I(inode)->dirty_pages);
 }
 
 static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
@@ -820,7 +857,7 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
                if (flag == NAT_BITMAP)
                        return &ckpt->sit_nat_version_bitmap;
                else
-                       return ((unsigned char *)ckpt + F2FS_BLKSIZE);
+                       return (unsigned char *)ckpt + F2FS_BLKSIZE;
        } else {
                offset = (flag == NAT_BITMAP) ?
                        le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
@@ -922,7 +959,7 @@ static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
 static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
 {
        spin_lock(&sbi->stat_lock);
-       f2fs_bug_on(sbi->total_valid_inode_count == sbi->total_node_count);
+       f2fs_bug_on(sbi, sbi->total_valid_inode_count == sbi->total_node_count);
        sbi->total_valid_inode_count++;
        spin_unlock(&sbi->stat_lock);
 }
@@ -930,7 +967,7 @@ static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
 static inline void dec_valid_inode_count(struct f2fs_sb_info *sbi)
 {
        spin_lock(&sbi->stat_lock);
-       f2fs_bug_on(!sbi->total_valid_inode_count);
+       f2fs_bug_on(sbi, !sbi->total_valid_inode_count);
        sbi->total_valid_inode_count--;
        spin_unlock(&sbi->stat_lock);
 }
@@ -946,7 +983,7 @@ static inline void f2fs_put_page(struct page *page, int unlock)
                return;
 
        if (unlock) {
-               f2fs_bug_on(!PageLocked(page));
+               f2fs_bug_on(F2FS_P_SB(page), !PageLocked(page));
                unlock_page(page);
        }
        page_cache_release(page);
@@ -1159,6 +1196,11 @@ static inline int f2fs_readonly(struct super_block *sb)
        return sb->s_flags & MS_RDONLY;
 }
 
+static inline bool f2fs_cp_error(struct f2fs_sb_info *sbi)
+{
+       return is_set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+}
+
 static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
 {
        set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
@@ -1180,7 +1222,7 @@ static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
  */
 int f2fs_sync_file(struct file *, loff_t, loff_t, int);
 void truncate_data_blocks(struct dnode_of_data *);
-int truncate_blocks(struct inode *, u64);
+int truncate_blocks(struct inode *, u64, bool);
 void f2fs_truncate(struct inode *);
 int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int f2fs_setattr(struct dentry *, struct iattr *);
@@ -1265,9 +1307,8 @@ int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *);
 bool alloc_nid(struct f2fs_sb_info *, nid_t *);
 void alloc_nid_done(struct f2fs_sb_info *, nid_t);
 void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
-void recover_node_page(struct f2fs_sb_info *, struct page *,
-               struct f2fs_summary *, struct node_info *, block_t);
-bool recover_xattr_data(struct inode *, struct page *, block_t);
+void recover_inline_xattr(struct inode *, struct page *);
+void recover_xattr_data(struct inode *, struct page *, block_t);
 int recover_inode_page(struct f2fs_sb_info *, struct page *);
 int restore_node_summary(struct f2fs_sb_info *, unsigned int,
                                struct f2fs_summary_block *);
@@ -1288,7 +1329,7 @@ void destroy_flush_cmd_control(struct f2fs_sb_info *);
 void invalidate_blocks(struct f2fs_sb_info *, block_t);
 void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t);
 void clear_prefree_segments(struct f2fs_sb_info *);
-void discard_next_dnode(struct f2fs_sb_info *);
+void discard_next_dnode(struct f2fs_sb_info *, block_t);
 int npages_for_summary_flush(struct f2fs_sb_info *);
 void allocate_new_segments(struct f2fs_sb_info *);
 struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
@@ -1300,8 +1341,6 @@ void write_data_page(struct page *, struct dnode_of_data *, block_t *,
 void rewrite_data_page(struct page *, block_t, struct f2fs_io_info *);
 void recover_data_page(struct f2fs_sb_info *, struct page *,
                                struct f2fs_summary *, block_t, block_t);
-void rewrite_node_page(struct f2fs_sb_info *, struct page *,
-                               struct f2fs_summary *, block_t, block_t);
 void allocate_data_block(struct f2fs_sb_info *, struct page *,
                block_t, block_t *, struct f2fs_summary *, int);
 void f2fs_wait_on_page_writeback(struct page *, enum page_type);
@@ -1320,10 +1359,12 @@ void destroy_segment_manager_caches(void);
  */
 struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
 struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
-int ra_meta_pages(struct f2fs_sb_info *, int, int, int);
+struct page *get_meta_page_ra(struct f2fs_sb_info *, pgoff_t);
+int ra_meta_pages(struct f2fs_sb_info *, block_t, int, int);
 long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
 void add_dirty_inode(struct f2fs_sb_info *, nid_t, int type);
 void remove_dirty_inode(struct f2fs_sb_info *, nid_t, int type);
+void release_dirty_inode(struct f2fs_sb_info *);
 bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
 int acquire_orphan_inode(struct f2fs_sb_info *);
 void release_orphan_inode(struct f2fs_sb_info *);
@@ -1331,7 +1372,7 @@ void add_orphan_inode(struct f2fs_sb_info *, nid_t);
 void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
 void recover_orphan_inodes(struct f2fs_sb_info *);
 int get_valid_checkpoint(struct f2fs_sb_info *);
-void set_dirty_dir_page(struct inode *, struct page *);
+void update_dirty_page(struct inode *, struct page *);
 void add_dirty_dir_inode(struct inode *);
 void remove_dirty_dir_inode(struct inode *);
 void sync_dirty_dir_inodes(struct f2fs_sb_info *);
@@ -1419,12 +1460,12 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
 #define stat_inc_inline_inode(inode)                                   \
        do {                                                            \
                if (f2fs_has_inline_data(inode))                        \
-                       ((F2FS_SB(inode->i_sb))->inline_inode++);       \
+                       ((F2FS_I_SB(inode))->inline_inode++);           \
        } while (0)
 #define stat_dec_inline_inode(inode)                                   \
        do {                                                            \
                if (f2fs_has_inline_data(inode))                        \
-                       ((F2FS_SB(inode->i_sb))->inline_inode--);       \
+                       ((F2FS_I_SB(inode))->inline_inode--);           \
        } while (0)
 
 #define stat_inc_seg_type(sbi, curseg)                                 \
@@ -1501,8 +1542,8 @@ extern const struct inode_operations f2fs_special_inode_operations;
  */
 bool f2fs_may_inline(struct inode *);
 int f2fs_read_inline_data(struct inode *, struct page *);
-int f2fs_convert_inline_data(struct inode *, pgoff_t);
+int f2fs_convert_inline_data(struct inode *, pgoff_t, struct page *);
 int f2fs_write_inline_data(struct inode *, struct page *, unsigned int);
 void truncate_inline_data(struct inode *, u64);
-int recover_inline_data(struct inode *, struct page *);
+bool recover_inline_data(struct inode *, struct page *);
 #endif