f2fs: introduce a new direct_IO write path
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / fs / f2fs / f2fs.h
index 89dc7508faf2edf173441a9e25cad8a9ff4856aa..8cbc5a6bf484f1860d2ae44d94a7f560fddff6fb 100644 (file)
 
 #ifdef CONFIG_F2FS_CHECK_FS
 #define f2fs_bug_on(condition) BUG_ON(condition)
+#define f2fs_down_write(x, y)  down_write_nest_lock(x, y)
 #else
 #define f2fs_bug_on(condition)
+#define f2fs_down_write(x, y)  down_write(x)
 #endif
 
 /*
@@ -37,6 +39,7 @@
 #define F2FS_MOUNT_POSIX_ACL           0x00000020
 #define F2FS_MOUNT_DISABLE_EXT_IDENTIFY        0x00000040
 #define F2FS_MOUNT_INLINE_XATTR                0x00000080
+#define F2FS_MOUNT_INLINE_DATA         0x00000100
 
 #define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
 #define set_opt(sbi, option)   (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -97,6 +100,13 @@ struct dir_inode_entry {
        struct inode *inode;    /* vfs inode pointer */
 };
 
+/* for the list of blockaddresses to be discarded */
+struct discard_entry {
+       struct list_head list;  /* list head */
+       block_t blkaddr;        /* block address to be discarded */
+       int len;                /* # of consecutive blocks of the discard */
+};
+
 /* for the list of fsync inodes, used only during recovery */
 struct fsync_inode_entry {
        struct list_head list;  /* list head */
@@ -162,6 +172,8 @@ enum {
 #define F2FS_LINK_MAX          32000   /* maximum link count per file */
 
 /* for in-memory extent cache entry */
+#define F2FS_MIN_EXTENT_LEN    16      /* minimum extent length */
+
 struct extent_info {
        rwlock_t ext_lock;      /* rwlock for consistency */
        unsigned int fofs;      /* start offset in a file */
@@ -308,6 +320,14 @@ struct f2fs_sm_info {
 
        /* a threshold to reclaim prefree segments */
        unsigned int rec_prefree_segments;
+
+       /* for small discard management */
+       struct list_head discard_list;          /* 4KB discard list */
+       int nr_discards;                        /* # of discards in the list */
+       int max_discards;                       /* max. discards to be issued */
+
+       unsigned int ipu_policy;        /* in-place-update policy */
+       unsigned int min_ipu_util;      /* in-place-update threshold */
 };
 
 /*
@@ -338,6 +358,7 @@ enum count_type {
  *                     with waiting the bio's completion
  * ...                 Only can be used with META.
  */
+#define PAGE_TYPE_OF_BIO(type) ((type) > META ? META : (type))
 enum page_type {
        DATA,
        NODE,
@@ -346,6 +367,21 @@ enum page_type {
        META_FLUSH,
 };
 
+struct f2fs_io_info {
+       enum page_type type;            /* contains DATA/NODE/META/META_FLUSH */
+       int rw;                         /* contains R/RS/W/WS */
+       int rw_flag;                    /* contains REQ_META/REQ_PRIO */
+};
+
+#define is_read_io(rw) (((rw) & 1) == READ)
+struct f2fs_bio_info {
+       struct f2fs_sb_info *sbi;       /* f2fs superblock */
+       struct bio *bio;                /* bios to merge */
+       sector_t last_block_in_bio;     /* last block number */
+       struct f2fs_io_info fio;        /* store buffered io info. */
+       struct mutex io_mutex;          /* mutex for bio */
+};
+
 struct f2fs_sb_info {
        struct super_block *sb;                 /* pointer to VFS super block */
        struct proc_dir_entry *s_proc;          /* proc entry */
@@ -359,9 +395,10 @@ struct f2fs_sb_info {
 
        /* for segment-related operations */
        struct f2fs_sm_info *sm_info;           /* segment manager */
-       struct bio *bio[NR_PAGE_TYPE];          /* bios to merge */
-       sector_t last_block_in_bio[NR_PAGE_TYPE];       /* last block number */
-       struct rw_semaphore bio_sem;            /* IO semaphore */
+
+       /* for bio operations */
+       struct f2fs_bio_info read_io;                   /* for read bios */
+       struct f2fs_bio_info write_io[NR_PAGE_TYPE];    /* for write bios */
 
        /* for checkpoint */
        struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
@@ -534,7 +571,7 @@ static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi)
 
 static inline void f2fs_lock_all(struct f2fs_sb_info *sbi)
 {
-       down_write_nest_lock(&sbi->cp_rwsem, &sbi->cp_mutex);
+       f2fs_down_write(&sbi->cp_rwsem, &sbi->cp_mutex);
 }
 
 static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
@@ -548,7 +585,7 @@ static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
 static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
 {
        WARN_ON((nid >= NM_I(sbi)->max_nid));
-       if (nid >= NM_I(sbi)->max_nid)
+       if (unlikely(nid >= NM_I(sbi)->max_nid))
                return -EINVAL;
        return 0;
 }
@@ -574,7 +611,7 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
        spin_lock(&sbi->stat_lock);
        valid_block_count =
                sbi->total_valid_block_count + (block_t)count;
-       if (valid_block_count > sbi->user_block_count) {
+       if (unlikely(valid_block_count > sbi->user_block_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
@@ -585,7 +622,7 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
        return true;
 }
 
-static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
+static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
                                                struct inode *inode,
                                                blkcnt_t count)
 {
@@ -595,7 +632,6 @@ static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
        inode->i_blocks -= count;
        sbi->total_valid_block_count -= (block_t)count;
        spin_unlock(&sbi->stat_lock);
-       return 0;
 }
 
 static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
@@ -686,50 +722,48 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
 }
 
 static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
-                                               struct inode *inode,
-                                               unsigned int count)
+                                               struct inode *inode)
 {
        block_t valid_block_count;
        unsigned int valid_node_count;
 
        spin_lock(&sbi->stat_lock);
 
-       valid_block_count = sbi->total_valid_block_count + (block_t)count;
-       sbi->alloc_valid_block_count += (block_t)count;
-       valid_node_count = sbi->total_valid_node_count + count;
-
-       if (valid_block_count > sbi->user_block_count) {
+       valid_block_count = sbi->total_valid_block_count + 1;
+       if (unlikely(valid_block_count > sbi->user_block_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
 
-       if (valid_node_count > sbi->total_node_count) {
+       valid_node_count = sbi->total_valid_node_count + 1;
+       if (unlikely(valid_node_count > sbi->total_node_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
 
        if (inode)
-               inode->i_blocks += count;
-       sbi->total_valid_node_count = valid_node_count;
-       sbi->total_valid_block_count = valid_block_count;
+               inode->i_blocks++;
+
+       sbi->alloc_valid_block_count++;
+       sbi->total_valid_node_count++;
+       sbi->total_valid_block_count++;
        spin_unlock(&sbi->stat_lock);
 
        return true;
 }
 
 static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
-                                               struct inode *inode,
-                                               unsigned int count)
+                                               struct inode *inode)
 {
        spin_lock(&sbi->stat_lock);
 
-       f2fs_bug_on(sbi->total_valid_block_count < count);
-       f2fs_bug_on(sbi->total_valid_node_count < count);
-       f2fs_bug_on(inode->i_blocks < count);
+       f2fs_bug_on(!sbi->total_valid_block_count);
+       f2fs_bug_on(!sbi->total_valid_node_count);
+       f2fs_bug_on(!inode->i_blocks);
 
-       inode->i_blocks -= count;
-       sbi->total_valid_node_count -= count;
-       sbi->total_valid_block_count -= (block_t)count;
+       inode->i_blocks--;
+       sbi->total_valid_node_count--;
+       sbi->total_valid_block_count--;
 
        spin_unlock(&sbi->stat_lock);
 }
@@ -751,13 +785,12 @@ static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
        spin_unlock(&sbi->stat_lock);
 }
 
-static inline int dec_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);
        sbi->total_valid_inode_count--;
        spin_unlock(&sbi->stat_lock);
-       return 0;
 }
 
 static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
@@ -771,7 +804,7 @@ static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
 
 static inline void f2fs_put_page(struct page *page, int unlock)
 {
-       if (!page || IS_ERR(page))
+       if (!page)
                return;
 
        if (unlock) {
@@ -876,7 +909,9 @@ enum {
        FI_NO_ALLOC,            /* should not allocate any blocks */
        FI_UPDATE_DIR,          /* should update inode block for consistency */
        FI_DELAY_IPUT,          /* used for the recovery */
+       FI_NO_EXTENT,           /* not to use the extent cache */
        FI_INLINE_XATTR,        /* used for inline xattr */
+       FI_INLINE_DATA,         /* used for inline data*/
 };
 
 static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
@@ -914,6 +949,8 @@ static inline void get_inline_info(struct f2fs_inode_info *fi,
 {
        if (ri->i_inline & F2FS_INLINE_XATTR)
                set_inode_flag(fi, FI_INLINE_XATTR);
+       if (ri->i_inline & F2FS_INLINE_DATA)
+               set_inode_flag(fi, FI_INLINE_DATA);
 }
 
 static inline void set_raw_inline(struct f2fs_inode_info *fi,
@@ -923,6 +960,8 @@ static inline void set_raw_inline(struct f2fs_inode_info *fi,
 
        if (is_inode_flag_set(fi, FI_INLINE_XATTR))
                ri->i_inline |= F2FS_INLINE_XATTR;
+       if (is_inode_flag_set(fi, FI_INLINE_DATA))
+               ri->i_inline |= F2FS_INLINE_DATA;
 }
 
 static inline unsigned int addrs_per_inode(struct f2fs_inode_info *fi)
@@ -948,6 +987,13 @@ static inline int inline_xattr_size(struct inode *inode)
                return 0;
 }
 
+static inline void *inline_data_addr(struct page *page)
+{
+       struct f2fs_inode *ri;
+       ri = (struct f2fs_inode *)page_address(page);
+       return (void *)&(ri->i_addr[1]);
+}
+
 static inline int f2fs_readonly(struct super_block *sb)
 {
        return sb->s_flags & MS_RDONLY;
@@ -1027,7 +1073,7 @@ int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
 int truncate_inode_blocks(struct inode *, pgoff_t);
 int truncate_xattr_node(struct inode *, struct page *);
 int wait_on_node_pages_writeback(struct f2fs_sb_info *, nid_t);
-int remove_inode_page(struct inode *);
+void remove_inode_page(struct inode *);
 struct page *new_inode_page(struct inode *, const struct qstr *);
 struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *);
 void ra_node_page(struct f2fs_sb_info *, nid_t);
@@ -1059,19 +1105,19 @@ void clear_prefree_segments(struct f2fs_sb_info *);
 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);
-struct bio *f2fs_bio_alloc(struct block_device *, int);
-void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool);
-void f2fs_wait_on_page_writeback(struct page *, enum page_type, bool);
 void write_meta_page(struct f2fs_sb_info *, struct page *);
 void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
                                        block_t, block_t *);
-void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
-                                       block_t, block_t *);
-void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
+void write_data_page(struct page *, struct dnode_of_data *, block_t *,
+                                       struct f2fs_io_info *);
+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, bool);
 void write_data_summaries(struct f2fs_sb_info *, block_t);
 void write_node_summaries(struct f2fs_sb_info *, block_t);
 int lookup_journal_in_cursum(struct f2fs_summary_block *,
@@ -1079,6 +1125,8 @@ int lookup_journal_in_cursum(struct f2fs_summary_block *,
 void flush_sit_entries(struct f2fs_sb_info *);
 int build_segment_manager(struct f2fs_sb_info *);
 void destroy_segment_manager(struct f2fs_sb_info *);
+int __init create_segment_manager_caches(void);
+void destroy_segment_manager_caches(void);
 
 /*
  * checkpoint.c
@@ -1090,7 +1138,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *);
 void release_orphan_inode(struct f2fs_sb_info *);
 void add_orphan_inode(struct f2fs_sb_info *, nid_t);
 void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
-int recover_orphan_inodes(struct f2fs_sb_info *);
+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 add_dirty_dir_inode(struct inode *);
@@ -1105,13 +1153,17 @@ void destroy_checkpoint_caches(void);
 /*
  * data.c
  */
+void f2fs_submit_merged_bio(struct f2fs_sb_info *, enum page_type, int);
+int f2fs_submit_page_bio(struct f2fs_sb_info *, struct page *, block_t, int);
+void f2fs_submit_page_mbio(struct f2fs_sb_info *, struct page *, block_t,
+                                               struct f2fs_io_info *);
 int reserve_new_block(struct dnode_of_data *);
+int f2fs_reserve_block(struct dnode_of_data *, pgoff_t);
 void update_extent_cache(block_t, struct dnode_of_data *);
 struct page *find_data_page(struct inode *, pgoff_t, bool);
 struct page *get_lock_data_page(struct inode *, pgoff_t);
 struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
-int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
-int do_write_data_page(struct page *);
+int do_write_data_page(struct page *, struct f2fs_io_info *);
 
 /*
  * gc.c
@@ -1238,4 +1290,5 @@ extern const struct address_space_operations f2fs_meta_aops;
 extern const struct inode_operations f2fs_dir_inode_operations;
 extern const struct inode_operations f2fs_symlink_inode_operations;
 extern const struct inode_operations f2fs_special_inode_operations;
+
 #endif