Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[firefly-linux-kernel-4.4.55.git] / fs / f2fs / f2fs.h
index e921242186f6a1e8af2a128460db45b064027b67..8171e80b2ee9f9709c953b4264ea92bee01011c6 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) WARN_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
 
@@ -90,6 +96,20 @@ enum {
        SIT_BITMAP
 };
 
+enum {
+       CP_UMOUNT,
+       CP_SYNC,
+       CP_DISCARD,
+};
+
+struct cp_control {
+       int reason;
+       __u64 trim_start;
+       __u64 trim_end;
+       __u64 trim_minlen;
+       __u64 trimmed;
+};
+
 /*
  * For CP/NAT/SIT/SSA readahead
  */
@@ -97,7 +117,8 @@ enum {
        META_CP,
        META_NAT,
        META_SIT,
-       META_SSA
+       META_SSA,
+       META_POR,
 };
 
 /* for the list of ino */
@@ -130,7 +151,9 @@ struct discard_entry {
 struct fsync_inode_entry {
        struct list_head list;  /* list head */
        struct inode *inode;    /* vfs inode pointer */
-       block_t blkaddr;        /* block address locating the last inode */
+       block_t blkaddr;        /* block address locating the last fsync */
+       block_t last_dentry;    /* block address locating the last dentry */
+       block_t last_inode;     /* block address locating the last inode */
 };
 
 #define nats_in_cursum(sum)            (le16_to_cpu(sum->n_nats))
@@ -141,6 +164,9 @@ struct fsync_inode_entry {
 #define sit_in_journal(sum, i)         (sum->sit_j.entries[i].se)
 #define segno_in_journal(sum, i)       (sum->sit_j.entries[i].segno)
 
+#define MAX_NAT_JENTRIES(sum)  (NAT_JOURNAL_ENTRIES - nats_in_cursum(sum))
+#define MAX_SIT_JENTRIES(sum)  (SIT_JOURNAL_ENTRIES - sits_in_cursum(sum))
+
 static inline int update_nats_in_cursum(struct f2fs_summary_block *rs, int i)
 {
        int before = nats_in_cursum(rs);
@@ -155,11 +181,24 @@ 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 size <= MAX_NAT_JENTRIES(sum);
+       return size <= MAX_SIT_JENTRIES(sum);
+}
+
 /*
  * ioctl commands
  */
-#define F2FS_IOC_GETFLAGS               FS_IOC_GETFLAGS
-#define F2FS_IOC_SETFLAGS               FS_IOC_SETFLAGS
+#define F2FS_IOC_GETFLAGS              FS_IOC_GETFLAGS
+#define F2FS_IOC_SETFLAGS              FS_IOC_SETFLAGS
+
+#define F2FS_IOCTL_MAGIC               0xf5
+#define F2FS_IOC_START_ATOMIC_WRITE    _IO(F2FS_IOCTL_MAGIC, 1)
+#define F2FS_IOC_COMMIT_ATOMIC_WRITE   _IO(F2FS_IOCTL_MAGIC, 2)
+#define F2FS_IOC_START_VOLATILE_WRITE  _IO(F2FS_IOCTL_MAGIC, 3)
 
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /*
@@ -222,13 +261,16 @@ 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 */
        unsigned long long xattr_ver;   /* cp version of xattr modification */
        struct extent_info ext;         /* in-memory extent cache entry */
        struct dir_inode_entry *dirty_dir;      /* the pointer of dirty dir */
+
+       struct list_head inmem_pages;   /* inmemory pages managed by f2fs */
+       struct mutex inmem_lock;        /* lock for inmemory pages */
 };
 
 static inline void get_extent_info(struct extent_info *ext,
@@ -260,11 +302,10 @@ struct f2fs_nm_info {
 
        /* NAT cache management */
        struct radix_tree_root nat_root;/* root of the nat entry cache */
+       struct radix_tree_root nat_set_root;/* root of the nat set cache */
        rwlock_t nat_tree_lock;         /* protect nat_tree_lock */
-       unsigned int nat_cnt;           /* the # of cached nat entries */
        struct list_head nat_entries;   /* cached nat entry list (clean) */
-       struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */
-       struct list_head nat_entry_set; /* nat entry set list */
+       unsigned int nat_cnt;           /* the # of cached nat entries */
        unsigned int dirty_nat_cnt;     /* total num of nat entries in set */
 
        /* free node ids management */
@@ -332,18 +373,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 {
@@ -369,8 +408,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;
@@ -434,6 +476,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 */
@@ -539,6 +582,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);
@@ -703,8 +761,8 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
                                                blkcnt_t count)
 {
        spin_lock(&sbi->stat_lock);
-       f2fs_bug_on(sbi->total_valid_block_count < (block_t) count);
-       f2fs_bug_on(inode->i_blocks < count);
+       f2fs_bug_on(sbi, sbi->total_valid_block_count < (block_t) count);
+       f2fs_bug_on(sbi, inode->i_blocks < count);
        inode->i_blocks -= count;
        sbi->total_valid_block_count -= (block_t)count;
        spin_unlock(&sbi->stat_lock);
@@ -716,10 +774,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)
@@ -727,13 +786,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)
@@ -741,9 +802,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)
@@ -848,9 +909,9 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
 {
        spin_lock(&sbi->stat_lock);
 
-       f2fs_bug_on(!sbi->total_valid_block_count);
-       f2fs_bug_on(!sbi->total_valid_node_count);
-       f2fs_bug_on(!inode->i_blocks);
+       f2fs_bug_on(sbi, !sbi->total_valid_block_count);
+       f2fs_bug_on(sbi, !sbi->total_valid_node_count);
+       f2fs_bug_on(sbi, !inode->i_blocks);
 
        inode->i_blocks--;
        sbi->total_valid_node_count--;
@@ -867,7 +928,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);
 }
@@ -875,7 +936,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);
 }
@@ -891,7 +952,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);
@@ -998,7 +1059,9 @@ enum {
        FI_INLINE_DATA,         /* used for inline data*/
        FI_APPEND_WRITE,        /* inode has appended data */
        FI_UPDATE_WRITE,        /* inode has in-place-update data */
-       FI_NEED_IPU,            /* used fo ipu for fdatasync */
+       FI_NEED_IPU,            /* used for ipu per file */
+       FI_ATOMIC_FILE,         /* indicate atomic file */
+       FI_VOLATILE_FILE,       /* indicate volatile file */
 };
 
 static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
@@ -1085,6 +1148,16 @@ static inline int f2fs_has_inline_data(struct inode *inode)
        return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA);
 }
 
+static inline bool f2fs_is_atomic_file(struct inode *inode)
+{
+       return is_inode_flag_set(F2FS_I(inode), FI_ATOMIC_FILE);
+}
+
+static inline bool f2fs_is_volatile_file(struct inode *inode)
+{
+       return is_inode_flag_set(F2FS_I(inode), FI_VOLATILE_FILE);
+}
+
 static inline void *inline_data_addr(struct page *page)
 {
        struct f2fs_inode *ri = F2FS_INODE(page);
@@ -1141,6 +1214,7 @@ void update_inode(struct inode *, struct page *);
 void update_inode_page(struct inode *);
 int f2fs_write_inode(struct inode *, struct writeback_control *);
 void f2fs_evict_inode(struct inode *);
+void handle_failed_inode(struct inode *);
 
 /*
  * namei.c
@@ -1188,9 +1262,9 @@ struct dnode_of_data;
 struct node_info;
 
 bool available_free_memory(struct f2fs_sb_info *, int);
-int is_checkpointed_node(struct f2fs_sb_info *, nid_t);
-bool fsync_mark_done(struct f2fs_sb_info *, nid_t);
-void fsync_mark_clear(struct f2fs_sb_info *, nid_t);
+bool is_checkpointed_node(struct f2fs_sb_info *, nid_t);
+bool has_fsynced_inode(struct f2fs_sb_info *, nid_t);
+bool need_inode_block_update(struct f2fs_sb_info *, nid_t);
 void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
 int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
 int truncate_inode_blocks(struct inode *, pgoff_t);
@@ -1221,6 +1295,8 @@ void destroy_node_manager_caches(void);
 /*
  * segment.c
  */
+void register_inmem_page(struct inode *, struct page *);
+void commit_inmem_pages(struct inode *, bool);
 void f2fs_balance_fs(struct f2fs_sb_info *);
 void f2fs_balance_fs_bg(struct f2fs_sb_info *);
 int f2fs_issue_flush(struct f2fs_sb_info *);
@@ -1229,9 +1305,11 @@ 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 release_discard_addrs(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 *);
+int f2fs_trim_fs(struct f2fs_sb_info *, struct fstrim_range *);
 struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
 void write_meta_page(struct f2fs_sb_info *, struct page *);
 void write_node_page(struct f2fs_sb_info *, struct page *,
@@ -1248,7 +1326,7 @@ 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 *,
                                        int, unsigned int, int);
-void flush_sit_entries(struct f2fs_sb_info *);
+void flush_sit_entries(struct f2fs_sb_info *, struct cp_control *);
 int build_segment_manager(struct f2fs_sb_info *);
 void destroy_segment_manager(struct f2fs_sb_info *);
 int __init create_segment_manager_caches(void);
@@ -1259,7 +1337,8 @@ 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);
@@ -1271,11 +1350,11 @@ 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 *);
-void write_checkpoint(struct f2fs_sb_info *, bool);
+void write_checkpoint(struct f2fs_sb_info *, struct cp_control *);
 void init_ino_entry_info(struct f2fs_sb_info *);
 int __init create_checkpoint_caches(void);
 void destroy_checkpoint_caches(void);
@@ -1359,12 +1438,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)                                 \