Merge tag 'perf-urgent-for-mingo-20161017' of git://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / fs / f2fs / f2fs.h
index 14f5fe2..9e8de18 100644 (file)
@@ -46,6 +46,8 @@ enum {
        FAULT_BLOCK,
        FAULT_DIR_DEPTH,
        FAULT_EVICT_INODE,
+       FAULT_IO,
+       FAULT_CHECKPOINT,
        FAULT_MAX,
 };
 
@@ -55,40 +57,8 @@ struct f2fs_fault_info {
        unsigned int inject_type;
 };
 
-extern struct f2fs_fault_info f2fs_fault;
 extern char *fault_name[FAULT_MAX];
-#define IS_FAULT_SET(type) (f2fs_fault.inject_type & (1 << (type)))
-
-static inline bool time_to_inject(int type)
-{
-       if (!f2fs_fault.inject_rate)
-               return false;
-       if (type == FAULT_KMALLOC && !IS_FAULT_SET(type))
-               return false;
-       else if (type == FAULT_PAGE_ALLOC && !IS_FAULT_SET(type))
-               return false;
-       else if (type == FAULT_ALLOC_NID && !IS_FAULT_SET(type))
-               return false;
-       else if (type == FAULT_ORPHAN && !IS_FAULT_SET(type))
-               return false;
-       else if (type == FAULT_BLOCK && !IS_FAULT_SET(type))
-               return false;
-       else if (type == FAULT_DIR_DEPTH && !IS_FAULT_SET(type))
-               return false;
-       else if (type == FAULT_EVICT_INODE && !IS_FAULT_SET(type))
-               return false;
-
-       atomic_inc(&f2fs_fault.inject_ops);
-       if (atomic_read(&f2fs_fault.inject_ops) >= f2fs_fault.inject_rate) {
-               atomic_set(&f2fs_fault.inject_ops, 0);
-               printk("%sF2FS-fs : inject %s in %pF\n",
-                               KERN_INFO,
-                               fault_name[type],
-                               __builtin_return_address(0));
-               return true;
-       }
-       return false;
-}
+#define IS_FAULT_SET(fi, type) (fi->inject_type & (1 << (type)))
 #endif
 
 /*
@@ -158,7 +128,7 @@ enum {
        CP_DISCARD,
 };
 
-#define DEF_BATCHED_TRIM_SECTIONS      32
+#define DEF_BATCHED_TRIM_SECTIONS      2
 #define BATCHED_TRIM_SEGMENTS(sbi)     \
                (SM_I(sbi)->trim_sections * (sbi)->segs_per_sec)
 #define BATCHED_TRIM_BLOCKS(sbi)       \
@@ -211,6 +181,13 @@ struct discard_entry {
        int len;                /* # of consecutive blocks of the discard */
 };
 
+struct bio_entry {
+       struct list_head list;
+       struct bio *bio;
+       struct completion event;
+       int error;
+};
+
 /* for the list of fsync inodes, used only during recovery */
 struct fsync_inode_entry {
        struct list_head list;  /* list head */
@@ -645,6 +622,7 @@ struct f2fs_sm_info {
 
        /* for small discard management */
        struct list_head discard_list;          /* 4KB discard list */
+       struct list_head wait_list;             /* linked with issued discard bio */
        int nr_discards;                        /* # of discards in the list */
        int max_discards;                       /* max. discards to be issued */
 
@@ -748,6 +726,7 @@ enum {
        SBI_NEED_FSCK,                          /* need fsck.f2fs to fix */
        SBI_POR_DOING,                          /* recovery is doing or not */
        SBI_NEED_SB_WRITE,                      /* need to recover superblock */
+       SBI_NEED_CP,                            /* need to checkpoint */
 };
 
 enum {
@@ -765,7 +744,7 @@ struct f2fs_sb_info {
        struct proc_dir_entry *s_proc;          /* proc entry */
        struct f2fs_super_block *raw_super;     /* raw super block pointer */
        int valid_super_block;                  /* valid super block no */
-       int s_flag;                             /* flags for sbi */
+       unsigned long s_flag;                           /* flags for sbi */
 
 #ifdef CONFIG_F2FS_FS_ENCRYPTION
        u8 key_prefix[F2FS_KEY_DESC_PREFIX_SIZE];
@@ -785,6 +764,7 @@ struct f2fs_sb_info {
 
        /* for checkpoint */
        struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
+       spinlock_t cp_lock;                     /* for flag in ckpt */
        struct inode *meta_inode;               /* cache meta blocks */
        struct mutex cp_mutex;                  /* checkpoint procedure lock */
        struct rw_semaphore cp_rwsem;           /* blocking FS operations */
@@ -892,8 +872,37 @@ struct f2fs_sb_info {
 
        /* Reference to checksum algorithm driver via cryptoapi */
        struct crypto_shash *s_chksum_driver;
+
+       /* For fault injection */
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+       struct f2fs_fault_info fault_info;
+#endif
 };
 
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type)
+{
+       struct f2fs_fault_info *ffi = &sbi->fault_info;
+
+       if (!ffi->inject_rate)
+               return false;
+
+       if (!IS_FAULT_SET(ffi, type))
+               return false;
+
+       atomic_inc(&ffi->inject_ops);
+       if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) {
+               atomic_set(&ffi->inject_ops, 0);
+               printk("%sF2FS-fs : inject %s in %pF\n",
+                               KERN_INFO,
+                               fault_name[type],
+                               __builtin_return_address(0));
+               return true;
+       }
+       return false;
+}
+#endif
+
 /* For write statistics. Suppose sector size is 512 bytes,
  * and the return value is in kbytes. s is of struct f2fs_sb_info.
  */
@@ -1034,17 +1043,17 @@ static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi)
 
 static inline bool is_sbi_flag_set(struct f2fs_sb_info *sbi, unsigned int type)
 {
-       return sbi->s_flag & (0x01 << type);
+       return test_bit(type, &sbi->s_flag);
 }
 
 static inline void set_sbi_flag(struct f2fs_sb_info *sbi, unsigned int type)
 {
-       sbi->s_flag |= (0x01 << type);
+       set_bit(type, &sbi->s_flag);
 }
 
 static inline void clear_sbi_flag(struct f2fs_sb_info *sbi, unsigned int type)
 {
-       sbi->s_flag &= ~(0x01 << type);
+       clear_bit(type, &sbi->s_flag);
 }
 
 static inline unsigned long long cur_cp_version(struct f2fs_checkpoint *cp)
@@ -1052,26 +1061,57 @@ static inline unsigned long long cur_cp_version(struct f2fs_checkpoint *cp)
        return le64_to_cpu(cp->checkpoint_ver);
 }
 
-static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+static inline bool __is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
 {
        unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+
        return ckpt_flags & f;
 }
 
-static inline void set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+static inline bool is_set_ckpt_flags(struct f2fs_sb_info *sbi, unsigned int f)
 {
-       unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+       return __is_set_ckpt_flags(F2FS_CKPT(sbi), f);
+}
+
+static inline void __set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+{
+       unsigned int ckpt_flags;
+
+       ckpt_flags = le32_to_cpu(cp->ckpt_flags);
        ckpt_flags |= f;
        cp->ckpt_flags = cpu_to_le32(ckpt_flags);
 }
 
-static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+static inline void set_ckpt_flags(struct f2fs_sb_info *sbi, unsigned int f)
 {
-       unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
+       spin_lock(&sbi->cp_lock);
+       __set_ckpt_flags(F2FS_CKPT(sbi), f);
+       spin_unlock(&sbi->cp_lock);
+}
+
+static inline void __clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
+{
+       unsigned int ckpt_flags;
+
+       ckpt_flags = le32_to_cpu(cp->ckpt_flags);
        ckpt_flags &= (~f);
        cp->ckpt_flags = cpu_to_le32(ckpt_flags);
 }
 
+static inline void clear_ckpt_flags(struct f2fs_sb_info *sbi, unsigned int f)
+{
+       spin_lock(&sbi->cp_lock);
+       __clear_ckpt_flags(F2FS_CKPT(sbi), f);
+       spin_unlock(&sbi->cp_lock);
+}
+
+static inline bool f2fs_discard_en(struct f2fs_sb_info *sbi)
+{
+       struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev);
+
+       return blk_queue_discard(q);
+}
+
 static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
 {
        down_read(&sbi->cp_rwsem);
@@ -1110,8 +1150,8 @@ static inline bool __remain_node_summaries(int reason)
 
 static inline bool __exist_node_summaries(struct f2fs_sb_info *sbi)
 {
-       return (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG) ||
-                       is_set_ckpt_flags(F2FS_CKPT(sbi), CP_FASTBOOT_FLAG));
+       return (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG) ||
+                       is_set_ckpt_flags(sbi, CP_FASTBOOT_FLAG));
 }
 
 /*
@@ -1151,7 +1191,7 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
        blkcnt_t diff;
 
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-       if (time_to_inject(FAULT_BLOCK))
+       if (time_to_inject(sbi, FAULT_BLOCK))
                return false;
 #endif
        /*
@@ -1193,6 +1233,10 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
 static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
 {
        percpu_counter_inc(&sbi->nr_pages[count_type]);
+
+       if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES)
+               return;
+
        set_sbi_flag(sbi, SBI_IS_DIRTY);
 }
 
@@ -1243,6 +1287,11 @@ static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
        return sbi->total_valid_block_count;
 }
 
+static inline block_t discard_blocks(struct f2fs_sb_info *sbi)
+{
+       return sbi->discard_blks;
+}
+
 static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
 {
        struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
@@ -1376,7 +1425,7 @@ static inline struct page *f2fs_grab_cache_page(struct address_space *mapping,
        if (page)
                return page;
 
-       if (time_to_inject(FAULT_PAGE_ALLOC))
+       if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_ALLOC))
                return NULL;
 #endif
        if (!for_write)
@@ -1804,7 +1853,7 @@ static inline int f2fs_readonly(struct super_block *sb)
 
 static inline bool f2fs_cp_error(struct f2fs_sb_info *sbi)
 {
-       return is_set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+       return is_set_ckpt_flags(sbi, CP_ERROR_FLAG);
 }
 
 static inline bool is_dot_dotdot(const struct qstr *str)
@@ -1827,10 +1876,11 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)
        return S_ISREG(inode->i_mode);
 }
 
-static inline void *f2fs_kmalloc(size_t size, gfp_t flags)
+static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi,
+                                       size_t size, gfp_t flags)
 {
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-       if (time_to_inject(FAULT_KMALLOC))
+       if (time_to_inject(sbi, FAULT_KMALLOC))
                return NULL;
 #endif
        return kmalloc(size, flags);
@@ -1885,6 +1935,7 @@ long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long);
  */
 void f2fs_set_inode_flags(struct inode *);
 struct inode *f2fs_iget(struct super_block *, unsigned long);
+struct inode *f2fs_iget_retry(struct super_block *, unsigned long);
 int try_to_free_nats(struct f2fs_sb_info *, int);
 int update_inode(struct inode *, struct page *);
 int update_inode_page(struct inode *);
@@ -1900,7 +1951,6 @@ struct dentry *f2fs_get_parent(struct dentry *child);
 /*
  * dir.c
  */
-extern unsigned char f2fs_filetype_table[F2FS_FT_MAX];
 void set_de_type(struct f2fs_dir_entry *, umode_t);
 unsigned char get_de_type(struct f2fs_dir_entry *);
 struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *,
@@ -1910,10 +1960,12 @@ bool f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *,
 void do_make_empty_dir(struct inode *, struct inode *,
                        struct f2fs_dentry_ptr *);
 struct page *init_inode_metadata(struct inode *, struct inode *,
-                       const struct qstr *, struct page *);
+               const struct qstr *, const struct qstr *, struct page *);
 void update_parent_metadata(struct inode *, struct inode *, unsigned int);
 int room_for_filename(const void *, int, int);
 void f2fs_drop_nlink(struct inode *, struct inode *);
+struct f2fs_dir_entry *__f2fs_find_entry(struct inode *, struct fscrypt_name *,
+                                                       struct page **);
 struct f2fs_dir_entry *f2fs_find_entry(struct inode *, const struct qstr *,
                                                        struct page **);
 struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
@@ -1924,7 +1976,9 @@ int update_dent_inode(struct inode *, struct inode *, const struct qstr *);
 void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *,
                        const struct qstr *, f2fs_hash_t , unsigned int);
 int f2fs_add_regular_entry(struct inode *, const struct qstr *,
-                                               struct inode *, nid_t, umode_t);
+                       const struct qstr *, struct inode *, nid_t, umode_t);
+int __f2fs_do_add_link(struct inode *, struct fscrypt_name*, struct inode *,
+                       nid_t, umode_t);
 int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *, nid_t,
                        umode_t);
 void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *,
@@ -2010,9 +2064,9 @@ void destroy_flush_cmd_control(struct f2fs_sb_info *);
 void invalidate_blocks(struct f2fs_sb_info *, block_t);
 bool is_checkpointed_data(struct f2fs_sb_info *, block_t);
 void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t);
+void f2fs_wait_all_discard_bio(struct f2fs_sb_info *);
 void clear_prefree_segments(struct f2fs_sb_info *, struct cp_control *);
 void release_discard_addrs(struct f2fs_sb_info *);
-bool discard_next_dnode(struct f2fs_sb_info *, block_t);
 int npages_for_summary_flush(struct f2fs_sb_info *, bool);
 void allocate_new_segments(struct f2fs_sb_info *);
 int f2fs_trim_fs(struct f2fs_sb_info *, struct fstrim_range *);
@@ -2095,6 +2149,10 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *, u64, u64);
 void f2fs_set_page_dirty_nobuffers(struct page *);
 void f2fs_invalidate_page(struct page *, unsigned int, unsigned int);
 int f2fs_release_page(struct page *, gfp_t);
+#ifdef CONFIG_MIGRATION
+int f2fs_migrate_page(struct address_space *, struct page *, struct page *,
+                               enum migrate_mode);
+#endif
 
 /*
  * gc.c
@@ -2123,13 +2181,14 @@ struct f2fs_stat_info {
        unsigned long long hit_largest, hit_cached, hit_rbtree;
        unsigned long long hit_total, total_ext;
        int ext_tree, zombie_tree, ext_node;
-       s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, inmem_pages;
+       s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, ndirty_imeta;
+       s64 inmem_pages;
        unsigned int ndirty_dirs, ndirty_files, ndirty_all;
        int nats, dirty_nats, sits, dirty_sits, fnids;
        int total_count, utilization;
        int bg_gc, wb_bios;
        int inline_xattr, inline_inode, inline_dir, orphans;
-       unsigned int valid_count, valid_node_count, valid_inode_count;
+       unsigned int valid_count, valid_node_count, valid_inode_count, discard_blks;
        unsigned int bimodal, avg_vblocks;
        int util_free, util_valid, util_invalid;
        int rsvd_segs, overp_segs;
@@ -2294,8 +2353,8 @@ bool recover_inline_data(struct inode *, struct page *);
 struct f2fs_dir_entry *find_in_inline_dir(struct inode *,
                                struct fscrypt_name *, struct page **);
 int make_empty_inline_dir(struct inode *inode, struct inode *, struct page *);
-int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,
-                                               nid_t, umode_t);
+int f2fs_add_inline_entry(struct inode *, const struct qstr *,
+               const struct qstr *, struct inode *, nid_t, umode_t);
 void f2fs_delete_inline_entry(struct f2fs_dir_entry *, struct page *,
                                                struct inode *, struct inode *);
 bool f2fs_empty_inline_dir(struct inode *);