]> Pileus Git - ~andy/linux/blobdiff - fs/f2fs/f2fs.h
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[~andy/linux] / fs / f2fs / f2fs.h
index 934b59cf819e5d3001d66642e70cc8f7a4acaa9c..fc3c558cb4f3d5a71b8ed03016e838cf5ec84cdf 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 */
@@ -155,13 +165,15 @@ enum {
        LOOKUP_NODE,                    /* look up a node without readahead */
        LOOKUP_NODE_RA,                 /*
                                         * look up a node with readahead called
-                                        * by get_datablock_ro.
+                                        * by get_data_block.
                                         */
 };
 
 #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,20 @@ 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 with 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 +394,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 */
@@ -376,8 +412,9 @@ struct f2fs_sb_info {
 
        /* for orphan inode management */
        struct list_head orphan_inode_list;     /* orphan inode list */
-       struct mutex orphan_inode_mutex;        /* for orphan inode list */
+       spinlock_t orphan_inode_lock;           /* for orphan inode list */
        unsigned int n_orphans;                 /* # of orphan inodes */
+       unsigned int max_orphans;               /* max orphan inodes */
 
        /* for directory inode management */
        struct list_head dir_inode_list;        /* dir inode list */
@@ -414,6 +451,9 @@ struct f2fs_sb_info {
        struct f2fs_gc_kthread  *gc_thread;     /* GC thread */
        unsigned int cur_victim_sec;            /* current victim section num */
 
+       /* maximum # of trials to find a victim segment for SSR and GC */
+       unsigned int max_victim_search;
+
        /*
         * for stat information.
         * one is for the LFS mode, and the other is for the SSR mode.
@@ -423,6 +463,7 @@ struct f2fs_sb_info {
        unsigned int segment_count[2];          /* # of allocated segments */
        unsigned int block_count[2];            /* # of allocated blocks */
        int total_hit_ext, read_hit_ext;        /* extent cache hit ratio */
+       int inline_inode;                       /* # of inline_data inodes */
        int bg_gc;                              /* background gc calls */
        unsigned int n_dirty_dirs;              /* # of dir inodes */
 #endif
@@ -462,6 +503,11 @@ static inline struct f2fs_node *F2FS_NODE(struct page *page)
        return (struct f2fs_node *)page_address(page);
 }
 
+static inline struct f2fs_inode *F2FS_INODE(struct page *page)
+{
+       return &((struct f2fs_node *)page_address(page))->i;
+}
+
 static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
 {
        return (struct f2fs_nm_info *)(sbi->nm_info);
@@ -487,6 +533,16 @@ static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi)
        return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
 }
 
+static inline struct address_space *META_MAPPING(struct f2fs_sb_info *sbi)
+{
+       return sbi->meta_inode->i_mapping;
+}
+
+static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi)
+{
+       return sbi->node_inode->i_mapping;
+}
+
 static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi)
 {
        sbi->s_dirty = 1;
@@ -534,7 +590,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 +604,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;
 }
@@ -561,9 +617,9 @@ static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
 static inline int F2FS_HAS_BLOCKS(struct inode *inode)
 {
        if (F2FS_I(inode)->i_xattr_nid)
-               return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1);
+               return inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1;
        else
-               return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS);
+               return inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS;
 }
 
 static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
@@ -574,7 +630,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 +641,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 +651,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 +741,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 +804,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 +823,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 +928,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 +968,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 +979,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 +1006,18 @@ static inline int inline_xattr_size(struct inode *inode)
                return 0;
 }
 
+static inline int f2fs_has_inline_data(struct inode *inode)
+{
+       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA);
+}
+
+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;
@@ -962,6 +1032,7 @@ static inline int f2fs_readonly(struct super_block *sb)
  */
 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);
 void f2fs_truncate(struct inode *);
 int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int f2fs_setattr(struct dentry *, struct iattr *);
@@ -1031,7 +1102,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);
@@ -1063,19 +1134,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_node_page(struct f2fs_sb_info *, struct page *,
+               struct f2fs_io_info *, unsigned int, block_t, 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);
 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 *,
@@ -1083,6 +1154,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
@@ -1094,7 +1167,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 *);
@@ -1109,13 +1182,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
@@ -1148,7 +1225,7 @@ struct f2fs_stat_info {
        int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
        int nats, sits, fnids;
        int total_count, utilization;
-       int bg_gc;
+       int bg_gc, inline_inode;
        unsigned int valid_count, valid_node_count, valid_inode_count;
        unsigned int bimodal, avg_vblocks;
        int util_free, util_valid, util_invalid;
@@ -1168,7 +1245,7 @@ struct f2fs_stat_info {
 
 static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
 {
-       return (struct f2fs_stat_info*)sbi->stat_info;
+       return (struct f2fs_stat_info *)sbi->stat_info;
 }
 
 #define stat_inc_call_count(si)                ((si)->call_count++)
@@ -1177,6 +1254,17 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
 #define stat_dec_dirty_dir(sbi)                ((sbi)->n_dirty_dirs--)
 #define stat_inc_total_hit(sb)         ((F2FS_SB(sb))->total_hit_ext++)
 #define stat_inc_read_hit(sb)          ((F2FS_SB(sb))->read_hit_ext++)
+#define stat_inc_inline_inode(inode)                                   \
+       do {                                                            \
+               if (f2fs_has_inline_data(inode))                        \
+                       ((F2FS_SB(inode->i_sb))->inline_inode++);       \
+       } while (0)
+#define stat_dec_inline_inode(inode)                                   \
+       do {                                                            \
+               if (f2fs_has_inline_data(inode))                        \
+                       ((F2FS_SB(inode->i_sb))->inline_inode--);       \
+       } while (0)
+
 #define stat_inc_seg_type(sbi, curseg)                                 \
                ((sbi)->segment_count[(curseg)->alloc_type]++)
 #define stat_inc_block_count(sbi, curseg)                              \
@@ -1220,6 +1308,8 @@ void f2fs_destroy_root_stats(void);
 #define stat_dec_dirty_dir(sbi)
 #define stat_inc_total_hit(sb)
 #define stat_inc_read_hit(sb)
+#define stat_inc_inline_inode(inode)
+#define stat_dec_inline_inode(inode)
 #define stat_inc_seg_type(sbi, curseg)
 #define stat_inc_block_count(sbi, curseg)
 #define stat_inc_seg_count(si, type)
@@ -1242,4 +1332,13 @@ 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;
+
+/*
+ * inline.c
+ */
+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_write_inline_data(struct inode *, struct page *, unsigned int);
+int recover_inline_data(struct inode *, struct page *);
 #endif