Merge remote-tracking branch 'lsk/v3.10/topic/aosp' into linux-linaro-lsk-android
[firefly-linux-kernel-4.4.55.git] / fs / f2fs / f2fs.h
index 201c8d3b0f863f829dae24de708c9077576dc763..20aab02f2a427181a4240ad99ad2b8200a235509 100644 (file)
@@ -125,11 +125,15 @@ static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
                                         * file keeping -1 as its node offset to
                                         * distinguish from index node blocks.
                                         */
-#define RDONLY_NODE            1       /*
-                                        * specify a read-only mode when getting
-                                        * a node block. 0 is read-write mode.
-                                        * used by get_dnode_of_data().
+enum {
+       ALLOC_NODE,                     /* allocate a new node page if needed */
+       LOOKUP_NODE,                    /* look up a node without readahead */
+       LOOKUP_NODE_RA,                 /*
+                                        * look up a node with readahead called
+                                        * by get_datablock_ro.
                                         */
+};
+
 #define F2FS_LINK_MAX          32000   /* maximum link count per file */
 
 /* for in-memory extent cache entry */
@@ -144,6 +148,7 @@ struct extent_info {
  * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
  */
 #define FADVISE_COLD_BIT       0x01
+#define FADVISE_CP_BIT         0x02
 
 struct f2fs_inode_info {
        struct inode vfs_inode;         /* serve a vfs inode */
@@ -155,7 +160,6 @@ struct f2fs_inode_info {
 
        /* Use below internally in f2fs*/
        unsigned long flags;            /* use to pass per-file flags */
-       unsigned long long data_version;/* latest version of data for fsync */
        atomic_t dirty_dents;           /* # of dirty dentry pages */
        f2fs_hash_t chash;              /* hash value of given file name */
        unsigned int clevel;            /* maximum level of given file name */
@@ -186,7 +190,6 @@ static inline void set_raw_extent(struct extent_info *ext,
 struct f2fs_nm_info {
        block_t nat_blkaddr;            /* base disk address of NAT */
        nid_t max_nid;                  /* maximum possible node ids */
-       nid_t init_scan_nid;            /* the first nid to be scanned */
        nid_t next_scan_nid;            /* the next nid to be scanned */
 
        /* NAT cache management */
@@ -305,23 +308,12 @@ enum count_type {
 };
 
 /*
- * FS_LOCK nesting subclasses for the lock validator:
- *
- * The locking order between these classes is
- * RENAME -> DENTRY_OPS -> DATA_WRITE -> DATA_NEW
- *    -> DATA_TRUNC -> NODE_WRITE -> NODE_NEW -> NODE_TRUNC
+ * Uses as sbi->fs_lock[NR_GLOBAL_LOCKS].
+ * The checkpoint procedure blocks all the locks in this fs_lock array.
+ * Some FS operations grab free locks, and if there is no free lock,
+ * then wait to grab a lock in a round-robin manner.
  */
-enum lock_type {
-       RENAME,         /* for renaming operations */
-       DENTRY_OPS,     /* for directory operations */
-       DATA_WRITE,     /* for data write */
-       DATA_NEW,       /* for data allocation */
-       DATA_TRUNC,     /* for data truncate */
-       NODE_NEW,       /* for node allocation */
-       NODE_TRUNC,     /* for node truncate */
-       NODE_WRITE,     /* for node write */
-       NR_LOCK_TYPE,
-};
+#define NR_GLOBAL_LOCKS        8
 
 /*
  * The below are the page types of bios used in submti_bio().
@@ -361,11 +353,13 @@ struct f2fs_sb_info {
        /* for checkpoint */
        struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
        struct inode *meta_inode;               /* cache meta blocks */
-       struct mutex cp_mutex;                  /* for checkpoint procedure */
-       struct mutex fs_lock[NR_LOCK_TYPE];     /* for blocking FS operations */
-       struct mutex write_inode;               /* mutex for write inode */
+       struct mutex cp_mutex;                  /* checkpoint procedure lock */
+       struct mutex fs_lock[NR_GLOBAL_LOCKS];  /* blocking FS operations */
+       struct mutex node_write;                /* locking node writes */
        struct mutex writepages;                /* mutex for writepages() */
+       unsigned char next_lock_num;            /* round-robin global locks */
        int por_doing;                          /* recovery is doing or not */
+       int on_build_free_nids;                 /* build_free_nids is doing */
 
        /* for orphan inode management */
        struct list_head orphan_inode_list;     /* orphan inode list */
@@ -406,6 +400,7 @@ struct f2fs_sb_info {
        /* for cleaning operations */
        struct mutex gc_mutex;                  /* mutex for GC */
        struct f2fs_gc_kthread  *gc_thread;     /* GC thread */
+       unsigned int cur_victim_sec;            /* current victim section num */
 
        /*
         * for stat information.
@@ -498,22 +493,51 @@ static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
        cp->ckpt_flags = cpu_to_le32(ckpt_flags);
 }
 
-static inline void mutex_lock_op(struct f2fs_sb_info *sbi, enum lock_type t)
+static inline void mutex_lock_all(struct f2fs_sb_info *sbi)
 {
-       mutex_lock_nested(&sbi->fs_lock[t], t);
+       int i = 0;
+       for (; i < NR_GLOBAL_LOCKS; i++)
+               mutex_lock(&sbi->fs_lock[i]);
 }
 
-static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, enum lock_type t)
+static inline void mutex_unlock_all(struct f2fs_sb_info *sbi)
 {
-       mutex_unlock(&sbi->fs_lock[t]);
+       int i = 0;
+       for (; i < NR_GLOBAL_LOCKS; i++)
+               mutex_unlock(&sbi->fs_lock[i]);
+}
+
+static inline int mutex_lock_op(struct f2fs_sb_info *sbi)
+{
+       unsigned char next_lock = sbi->next_lock_num % NR_GLOBAL_LOCKS;
+       int i = 0;
+
+       for (; i < NR_GLOBAL_LOCKS; i++)
+               if (mutex_trylock(&sbi->fs_lock[i]))
+                       return i;
+
+       mutex_lock(&sbi->fs_lock[next_lock]);
+       sbi->next_lock_num++;
+       return next_lock;
+}
+
+static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, int ilock)
+{
+       if (ilock < 0)
+               return;
+       BUG_ON(ilock >= NR_GLOBAL_LOCKS);
+       mutex_unlock(&sbi->fs_lock[ilock]);
 }
 
 /*
  * Check whether the given nid is within node id range.
  */
-static inline void check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
+static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
 {
-       BUG_ON((nid >= NM_I(sbi)->max_nid));
+       WARN_ON((nid >= NM_I(sbi)->max_nid));
+       if (nid >= NM_I(sbi)->max_nid)
+               return -EINVAL;
+       return 0;
 }
 
 #define F2FS_DEFAULT_ALLOCATED_BLOCKS  1
@@ -819,7 +843,6 @@ static inline int f2fs_clear_bit(unsigned int nr, char *addr)
 /* used for f2fs_inode_info->flags */
 enum {
        FI_NEW_INODE,           /* indicate newly allocated inode */
-       FI_NEED_CP,             /* need to do checkpoint during fsync */
        FI_INC_LINK,            /* need to increment i_nlink */
        FI_ACL_MODE,            /* indicate acl mode */
        FI_NO_ALLOC,            /* should not allocate any blocks */
@@ -872,6 +895,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);
 void update_inode(struct inode *, struct page *);
+int update_inode_page(struct inode *);
 int f2fs_write_inode(struct inode *, struct writeback_control *);
 void f2fs_evict_inode(struct inode *);
 
@@ -973,7 +997,6 @@ int lookup_journal_in_cursum(struct f2fs_summary_block *,
                                        int, unsigned int, int);
 void flush_sit_entries(struct f2fs_sb_info *);
 int build_segment_manager(struct f2fs_sb_info *);
-void reset_victim_segmap(struct f2fs_sb_info *);
 void destroy_segment_manager(struct f2fs_sb_info *);
 
 /*
@@ -1000,7 +1023,7 @@ void destroy_checkpoint_caches(void);
  */
 int reserve_new_block(struct dnode_of_data *);
 void update_extent_cache(block_t, struct dnode_of_data *);
-struct page *find_data_page(struct inode *, pgoff_t);
+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 *, pgoff_t, bool);
 int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
@@ -1020,7 +1043,7 @@ void destroy_gc_caches(void);
 /*
  * recovery.c
  */
-void recover_fsync_data(struct f2fs_sb_info *);
+int recover_fsync_data(struct f2fs_sb_info *);
 bool space_for_roll_forward(struct f2fs_sb_info *);
 
 /*