f2fs: avoid memory allocation failure due to a long length
[deliverable/linux.git] / fs / f2fs / f2fs.h
index 7a4558d17f364e84d5d7c14925eabbd3110784bb..521cb92285fa1622239cbb5940330b5d7f7de857 100644 (file)
        } while (0)
 #endif
 
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+enum {
+       FAULT_KMALLOC,
+       FAULT_PAGE_ALLOC,
+       FAULT_ALLOC_NID,
+       FAULT_ORPHAN,
+       FAULT_BLOCK,
+       FAULT_DIR_DEPTH,
+       FAULT_EVICT_INODE,
+       FAULT_MAX,
+};
+
+struct f2fs_fault_info {
+       atomic_t inject_ops;
+       unsigned int inject_rate;
+       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;
+}
+#endif
+
 /*
  * For mount options
  */
 #define F2FS_MOUNT_EXTENT_CACHE                0x00002000
 #define F2FS_MOUNT_FORCE_FG_GC         0x00004000
 #define F2FS_MOUNT_DATA_FLUSH          0x00008000
+#define F2FS_MOUNT_FAULT_INJECTION     0x00010000
+#define F2FS_MOUNT_ADAPTIVE            0x00020000
+#define F2FS_MOUNT_LFS                 0x00040000
 
 #define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
 #define set_opt(sbi, option)   (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -76,6 +133,7 @@ struct f2fs_mount_info {
 };
 
 #define F2FS_FEATURE_ENCRYPT   0x0001
+#define F2FS_FEATURE_HMSMR     0x0002
 
 #define F2FS_HAS_FEATURE(sb, mask)                                     \
        ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -106,7 +164,7 @@ enum {
 #define BATCHED_TRIM_BLOCKS(sbi)       \
                (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
 #define DEF_CP_INTERVAL                        60      /* 60 secs */
-#define DEF_IDLE_INTERVAL              120     /* 2 mins */
+#define DEF_IDLE_INTERVAL              5       /* 5 secs */
 
 struct cp_control {
        int reason;
@@ -159,7 +217,6 @@ struct fsync_inode_entry {
        struct inode *inode;    /* vfs inode pointer */
        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(jnl)            (le16_to_cpu(jnl->n_nats))
@@ -385,24 +442,27 @@ 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_pages;           /* # of dirty pages */
+       struct percpu_counter 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 */
+       loff_t  last_disk_size;         /* lastly written file size */
 
-       struct list_head dirty_list;    /* linked in global dirty list */
+       struct list_head dirty_list;    /* dirty list for dirs and files */
+       struct list_head gdirty_list;   /* linked in global dirty list */
        struct list_head inmem_pages;   /* inmemory pages managed by f2fs */
        struct mutex inmem_lock;        /* lock for inmemory pages */
        struct extent_tree *extent_tree;        /* cached extent_tree entry */
+       struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
 };
 
 static inline void get_extent_info(struct extent_info *ext,
-                                       struct f2fs_extent i_ext)
+                                       struct f2fs_extent *i_ext)
 {
-       ext->fofs = le32_to_cpu(i_ext.fofs);
-       ext->blk = le32_to_cpu(i_ext.blk);
-       ext->len = le32_to_cpu(i_ext.len);
+       ext->fofs = le32_to_cpu(i_ext->fofs);
+       ext->blk = le32_to_cpu(i_ext->blk);
+       ext->len = le32_to_cpu(i_ext->len);
 }
 
 static inline void set_raw_extent(struct extent_info *ext,
@@ -447,11 +507,14 @@ static inline bool __is_front_mergeable(struct extent_info *cur,
        return __is_extent_mergeable(cur, front);
 }
 
-static inline void __try_update_largest_extent(struct extent_tree *et,
-                                               struct extent_node *en)
+extern void f2fs_mark_inode_dirty_sync(struct inode *);
+static inline void __try_update_largest_extent(struct inode *inode,
+                       struct extent_tree *et, struct extent_node *en)
 {
-       if (en->ei.len > et->largest.len)
+       if (en->ei.len > et->largest.len) {
                et->largest = en->ei;
+               f2fs_mark_inode_dirty_sync(inode);
+       }
 }
 
 struct f2fs_nm_info {
@@ -466,7 +529,7 @@ 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 */
-       struct rw_semaphore nat_tree_lock;      /* protect nat_tree_lock */
+       struct percpu_rw_semaphore nat_tree_lock;       /* protect nat_tree_lock */
        struct list_head nat_entries;   /* cached nat entry list (clean) */
        unsigned int nat_cnt;           /* the # of cached nat entries */
        unsigned int dirty_nat_cnt;     /* total num of nat entries in set */
@@ -548,6 +611,7 @@ struct flush_cmd {
 struct flush_cmd_control {
        struct task_struct *f2fs_issue_flush;   /* flush thread */
        wait_queue_head_t flush_wait_queue;     /* waiting queue for wake-up */
+       atomic_t submit_flush;                  /* # of issued flushes */
        struct llist_head issue_list;           /* list for command issue */
        struct llist_node *dispatch_list;       /* list for command dispatch */
 };
@@ -599,12 +663,12 @@ struct f2fs_sm_info {
  * dirty dentry blocks, dirty node blocks, and dirty meta blocks.
  */
 enum count_type {
-       F2FS_WRITEBACK,
        F2FS_DIRTY_DENTS,
        F2FS_DIRTY_DATA,
        F2FS_DIRTY_NODES,
        F2FS_DIRTY_META,
        F2FS_INMEM_PAGES,
+       F2FS_DIRTY_IMETA,
        NR_COUNT_TYPE,
 };
 
@@ -655,6 +719,7 @@ struct f2fs_bio_info {
 enum inode_type {
        DIR_INODE,                      /* for dirty dir inode */
        FILE_INODE,                     /* for dirty regular/symlink inode */
+       DIRTY_META,                     /* for all dirtied inode metadata */
        NR_INODE_TYPE,
 };
 
@@ -672,6 +737,7 @@ enum {
        SBI_IS_CLOSE,                           /* specify unmounting */
        SBI_NEED_FSCK,                          /* need fsck.f2fs to fix */
        SBI_POR_DOING,                          /* recovery is doing or not */
+       SBI_NEED_SB_WRITE,                      /* need to recover superblock */
 };
 
 enum {
@@ -680,6 +746,10 @@ enum {
        MAX_TIME,
 };
 
+#ifdef CONFIG_F2FS_FS_ENCRYPTION
+#define F2FS_KEY_DESC_PREFIX "f2fs:"
+#define F2FS_KEY_DESC_PREFIX_SIZE 5
+#endif
 struct f2fs_sb_info {
        struct super_block *sb;                 /* pointer to VFS super block */
        struct proc_dir_entry *s_proc;          /* proc entry */
@@ -687,6 +757,10 @@ struct f2fs_sb_info {
        int valid_super_block;                  /* valid super block no */
        int s_flag;                             /* flags for sbi */
 
+#ifdef CONFIG_F2FS_FS_ENCRYPTION
+       u8 key_prefix[F2FS_KEY_DESC_PREFIX_SIZE];
+       u8 key_prefix_size;
+#endif
        /* for node-related operations */
        struct f2fs_nm_info *nm_info;           /* node manager */
        struct inode *node_inode;               /* cache node blocks */
@@ -697,14 +771,14 @@ struct f2fs_sb_info {
        /* for bio operations */
        struct f2fs_bio_info read_io;                   /* for read bios */
        struct f2fs_bio_info write_io[NR_PAGE_TYPE];    /* for write bios */
+       struct mutex wio_mutex[NODE + 1];       /* bio ordering for NODE/DATA */
 
        /* for checkpoint */
        struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
        struct inode *meta_inode;               /* cache meta blocks */
        struct mutex cp_mutex;                  /* checkpoint procedure lock */
-       struct rw_semaphore cp_rwsem;           /* blocking FS operations */
+       struct percpu_rw_semaphore cp_rwsem;            /* blocking FS operations */
        struct rw_semaphore node_write;         /* locking node writes */
-       struct mutex writepages;                /* mutex for writepages() */
        wait_queue_head_t cp_wait;
        unsigned long last_time[MAX_TIME];      /* to store time in jiffies */
        long interval_time[MAX_TIME];           /* to store thresholds */
@@ -742,18 +816,24 @@ struct f2fs_sb_info {
        unsigned int total_sections;            /* total section count */
        unsigned int total_node_count;          /* total node block count */
        unsigned int total_valid_node_count;    /* valid node block count */
-       unsigned int total_valid_inode_count;   /* valid inode count */
        loff_t max_file_blocks;                 /* max block index of file */
        int active_logs;                        /* # of active logs */
        int dir_level;                          /* directory level */
 
        block_t user_block_count;               /* # of user blocks */
        block_t total_valid_block_count;        /* # of valid blocks */
-       block_t alloc_valid_block_count;        /* # of allocated blocks */
        block_t discard_blks;                   /* discard command candidats */
        block_t last_valid_block_count;         /* for recovery */
        u32 s_next_generation;                  /* for NFS support */
-       atomic_t nr_pages[NR_COUNT_TYPE];       /* # of pages, see count_type */
+       atomic_t nr_wb_bios;                    /* # of writeback bios */
+
+       /* # of pages, see count_type */
+       struct percpu_counter nr_pages[NR_COUNT_TYPE];
+       /* # of allocated blocks */
+       struct percpu_counter alloc_valid_block_count;
+
+       /* valid inode count */
+       struct percpu_counter total_valid_inode_count;
 
        struct f2fs_mount_info mount_opt;       /* mount options */
 
@@ -984,22 +1064,22 @@ static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
 
 static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
 {
-       down_read(&sbi->cp_rwsem);
+       percpu_down_read(&sbi->cp_rwsem);
 }
 
 static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi)
 {
-       up_read(&sbi->cp_rwsem);
+       percpu_up_read(&sbi->cp_rwsem);
 }
 
 static inline void f2fs_lock_all(struct f2fs_sb_info *sbi)
 {
-       down_write(&sbi->cp_rwsem);
+       percpu_down_write(&sbi->cp_rwsem);
 }
 
 static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
 {
-       up_write(&sbi->cp_rwsem);
+       percpu_up_write(&sbi->cp_rwsem);
 }
 
 static inline int __get_cp_reason(struct f2fs_sb_info *sbi)
@@ -1054,22 +1134,28 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)
        return ofs == XATTR_NODE_OFFSET;
 }
 
+static inline void f2fs_i_blocks_write(struct inode *, blkcnt_t, bool);
 static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
-                                struct inode *inode, blkcnt_t count)
+                                struct inode *inode, blkcnt_t *count)
 {
-       block_t valid_block_count;
-
-       spin_lock(&sbi->stat_lock);
-       valid_block_count =
-               sbi->total_valid_block_count + (block_t)count;
-       if (unlikely(valid_block_count > sbi->user_block_count)) {
-               spin_unlock(&sbi->stat_lock);
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+       if (time_to_inject(FAULT_BLOCK))
                return false;
+#endif
+       spin_lock(&sbi->stat_lock);
+       sbi->total_valid_block_count += (block_t)(*count);
+       if (unlikely(sbi->total_valid_block_count > sbi->user_block_count)) {
+               *count -= sbi->total_valid_block_count - sbi->user_block_count;
+               sbi->total_valid_block_count = sbi->user_block_count;
+               if (!*count) {
+                       spin_unlock(&sbi->stat_lock);
+                       return false;
+               }
        }
-       inode->i_blocks += count;
-       sbi->total_valid_block_count = valid_block_count;
-       sbi->alloc_valid_block_count += (block_t)count;
        spin_unlock(&sbi->stat_lock);
+
+       f2fs_i_blocks_write(inode, *count, true);
+       percpu_counter_add(&sbi->alloc_valid_block_count, (*count));
        return true;
 }
 
@@ -1080,27 +1166,27 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
        spin_lock(&sbi->stat_lock);
        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);
+       f2fs_i_blocks_write(inode, count, false);
 }
 
 static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
 {
-       atomic_inc(&sbi->nr_pages[count_type]);
+       percpu_counter_inc(&sbi->nr_pages[count_type]);
        set_sbi_flag(sbi, SBI_IS_DIRTY);
 }
 
 static inline void inode_inc_dirty_pages(struct inode *inode)
 {
-       atomic_inc(&F2FS_I(inode)->dirty_pages);
+       percpu_counter_inc(&F2FS_I(inode)->dirty_pages);
        inc_page_count(F2FS_I_SB(inode), S_ISDIR(inode->i_mode) ?
                                F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA);
 }
 
 static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
 {
-       atomic_dec(&sbi->nr_pages[count_type]);
+       percpu_counter_dec(&sbi->nr_pages[count_type]);
 }
 
 static inline void inode_dec_dirty_pages(struct inode *inode)
@@ -1109,26 +1195,28 @@ static inline void inode_dec_dirty_pages(struct inode *inode)
                        !S_ISLNK(inode->i_mode))
                return;
 
-       atomic_dec(&F2FS_I(inode)->dirty_pages);
+       percpu_counter_dec(&F2FS_I(inode)->dirty_pages);
        dec_page_count(F2FS_I_SB(inode), S_ISDIR(inode->i_mode) ?
                                F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA);
 }
 
-static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
+static inline s64 get_pages(struct f2fs_sb_info *sbi, int count_type)
 {
-       return atomic_read(&sbi->nr_pages[count_type]);
+       return percpu_counter_sum_positive(&sbi->nr_pages[count_type]);
 }
 
-static inline int get_dirty_pages(struct inode *inode)
+static inline s64 get_dirty_pages(struct inode *inode)
 {
-       return atomic_read(&F2FS_I(inode)->dirty_pages);
+       return percpu_counter_sum_positive(&F2FS_I(inode)->dirty_pages);
 }
 
 static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
 {
        unsigned int pages_per_sec = sbi->segs_per_sec * sbi->blocks_per_seg;
-       return ((get_pages(sbi, block_type) + pages_per_sec - 1)
-                       >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+       unsigned int segs = (get_pages(sbi, block_type) + pages_per_sec - 1) >>
+                                               sbi->log_blocks_per_seg;
+
+       return segs / sbi->segs_per_sec;
 }
 
 static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
@@ -1215,13 +1303,13 @@ static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
        }
 
        if (inode)
-               inode->i_blocks++;
+               f2fs_i_blocks_write(inode, 1, true);
 
-       sbi->alloc_valid_block_count++;
        sbi->total_valid_node_count++;
        sbi->total_valid_block_count++;
        spin_unlock(&sbi->stat_lock);
 
+       percpu_counter_inc(&sbi->alloc_valid_block_count);
        return true;
 }
 
@@ -1234,7 +1322,7 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
        f2fs_bug_on(sbi, !sbi->total_valid_node_count);
        f2fs_bug_on(sbi, !inode->i_blocks);
 
-       inode->i_blocks--;
+       f2fs_i_blocks_write(inode, 1, false);
        sbi->total_valid_node_count--;
        sbi->total_valid_block_count--;
 
@@ -1248,28 +1336,30 @@ 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, sbi->total_valid_inode_count == sbi->total_node_count);
-       sbi->total_valid_inode_count++;
-       spin_unlock(&sbi->stat_lock);
+       percpu_counter_inc(&sbi->total_valid_inode_count);
 }
 
 static inline void dec_valid_inode_count(struct f2fs_sb_info *sbi)
 {
-       spin_lock(&sbi->stat_lock);
-       f2fs_bug_on(sbi, !sbi->total_valid_inode_count);
-       sbi->total_valid_inode_count--;
-       spin_unlock(&sbi->stat_lock);
+       percpu_counter_dec(&sbi->total_valid_inode_count);
 }
 
-static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
+static inline s64 valid_inode_count(struct f2fs_sb_info *sbi)
 {
-       return sbi->total_valid_inode_count;
+       return percpu_counter_sum_positive(&sbi->total_valid_inode_count);
 }
 
 static inline struct page *f2fs_grab_cache_page(struct address_space *mapping,
                                                pgoff_t index, bool for_write)
 {
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+       struct page *page = find_lock_page(mapping, index);
+       if (page)
+               return page;
+
+       if (time_to_inject(FAULT_PAGE_ALLOC))
+               return NULL;
+#endif
        if (!for_write)
                return grab_cache_page(mapping, index);
        return grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS);
@@ -1429,13 +1519,12 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr)
 enum {
        FI_NEW_INODE,           /* indicate newly allocated inode */
        FI_DIRTY_INODE,         /* indicate inode is dirty or not */
+       FI_AUTO_RECOVER,        /* indicate inode is recoverable */
        FI_DIRTY_DIR,           /* indicate directory has dirty pages */
        FI_INC_LINK,            /* need to increment i_nlink */
        FI_ACL_MODE,            /* indicate acl mode */
        FI_NO_ALLOC,            /* should not allocate any blocks */
        FI_FREE_NID,            /* free allocated nide */
-       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*/
@@ -1453,64 +1542,143 @@ enum {
        FI_DIRTY_FILE,          /* indicate regular/symlink has dirty pages */
 };
 
-static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
+static inline void __mark_inode_dirty_flag(struct inode *inode,
+                                               int flag, bool set)
+{
+       switch (flag) {
+       case FI_INLINE_XATTR:
+       case FI_INLINE_DATA:
+       case FI_INLINE_DENTRY:
+               if (set)
+                       return;
+       case FI_DATA_EXIST:
+       case FI_INLINE_DOTS:
+               f2fs_mark_inode_dirty_sync(inode);
+       }
+}
+
+static inline void set_inode_flag(struct inode *inode, int flag)
+{
+       if (!test_bit(flag, &F2FS_I(inode)->flags))
+               set_bit(flag, &F2FS_I(inode)->flags);
+       __mark_inode_dirty_flag(inode, flag, true);
+}
+
+static inline int is_inode_flag_set(struct inode *inode, int flag)
+{
+       return test_bit(flag, &F2FS_I(inode)->flags);
+}
+
+static inline void clear_inode_flag(struct inode *inode, int flag)
+{
+       if (test_bit(flag, &F2FS_I(inode)->flags))
+               clear_bit(flag, &F2FS_I(inode)->flags);
+       __mark_inode_dirty_flag(inode, flag, false);
+}
+
+static inline void set_acl_inode(struct inode *inode, umode_t mode)
+{
+       F2FS_I(inode)->i_acl_mode = mode;
+       set_inode_flag(inode, FI_ACL_MODE);
+       f2fs_mark_inode_dirty_sync(inode);
+}
+
+static inline void f2fs_i_links_write(struct inode *inode, bool inc)
+{
+       if (inc)
+               inc_nlink(inode);
+       else
+               drop_nlink(inode);
+       f2fs_mark_inode_dirty_sync(inode);
+}
+
+static inline void f2fs_i_blocks_write(struct inode *inode,
+                                       blkcnt_t diff, bool add)
+{
+       bool clean = !is_inode_flag_set(inode, FI_DIRTY_INODE);
+       bool recover = is_inode_flag_set(inode, FI_AUTO_RECOVER);
+
+       inode->i_blocks = add ? inode->i_blocks + diff :
+                               inode->i_blocks - diff;
+       f2fs_mark_inode_dirty_sync(inode);
+       if (clean || recover)
+               set_inode_flag(inode, FI_AUTO_RECOVER);
+}
+
+static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
+{
+       bool clean = !is_inode_flag_set(inode, FI_DIRTY_INODE);
+       bool recover = is_inode_flag_set(inode, FI_AUTO_RECOVER);
+
+       if (i_size_read(inode) == i_size)
+               return;
+
+       i_size_write(inode, i_size);
+       f2fs_mark_inode_dirty_sync(inode);
+       if (clean || recover)
+               set_inode_flag(inode, FI_AUTO_RECOVER);
+}
+
+static inline bool f2fs_skip_inode_update(struct inode *inode)
 {
-       if (!test_bit(flag, &fi->flags))
-               set_bit(flag, &fi->flags);
+       if (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
+               return false;
+       return F2FS_I(inode)->last_disk_size == i_size_read(inode);
 }
 
-static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag)
+static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth)
 {
-       return test_bit(flag, &fi->flags);
+       F2FS_I(inode)->i_current_depth = depth;
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
-static inline void clear_inode_flag(struct f2fs_inode_info *fi, int flag)
+static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid)
 {
-       if (test_bit(flag, &fi->flags))
-               clear_bit(flag, &fi->flags);
+       F2FS_I(inode)->i_xattr_nid = xnid;
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
-static inline void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode)
+static inline void f2fs_i_pino_write(struct inode *inode, nid_t pino)
 {
-       fi->i_acl_mode = mode;
-       set_inode_flag(fi, FI_ACL_MODE);
+       F2FS_I(inode)->i_pino = pino;
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
-static inline void get_inline_info(struct f2fs_inode_info *fi,
-                                       struct f2fs_inode *ri)
+static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri)
 {
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+
        if (ri->i_inline & F2FS_INLINE_XATTR)
-               set_inode_flag(fi, FI_INLINE_XATTR);
+               set_bit(FI_INLINE_XATTR, &fi->flags);
        if (ri->i_inline & F2FS_INLINE_DATA)
-               set_inode_flag(fi, FI_INLINE_DATA);
+               set_bit(FI_INLINE_DATA, &fi->flags);
        if (ri->i_inline & F2FS_INLINE_DENTRY)
-               set_inode_flag(fi, FI_INLINE_DENTRY);
+               set_bit(FI_INLINE_DENTRY, &fi->flags);
        if (ri->i_inline & F2FS_DATA_EXIST)
-               set_inode_flag(fi, FI_DATA_EXIST);
+               set_bit(FI_DATA_EXIST, &fi->flags);
        if (ri->i_inline & F2FS_INLINE_DOTS)
-               set_inode_flag(fi, FI_INLINE_DOTS);
+               set_bit(FI_INLINE_DOTS, &fi->flags);
 }
 
-static inline void set_raw_inline(struct f2fs_inode_info *fi,
-                                       struct f2fs_inode *ri)
+static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri)
 {
        ri->i_inline = 0;
 
-       if (is_inode_flag_set(fi, FI_INLINE_XATTR))
+       if (is_inode_flag_set(inode, FI_INLINE_XATTR))
                ri->i_inline |= F2FS_INLINE_XATTR;
-       if (is_inode_flag_set(fi, FI_INLINE_DATA))
+       if (is_inode_flag_set(inode, FI_INLINE_DATA))
                ri->i_inline |= F2FS_INLINE_DATA;
-       if (is_inode_flag_set(fi, FI_INLINE_DENTRY))
+       if (is_inode_flag_set(inode, FI_INLINE_DENTRY))
                ri->i_inline |= F2FS_INLINE_DENTRY;
-       if (is_inode_flag_set(fi, FI_DATA_EXIST))
+       if (is_inode_flag_set(inode, FI_DATA_EXIST))
                ri->i_inline |= F2FS_DATA_EXIST;
-       if (is_inode_flag_set(fi, FI_INLINE_DOTS))
+       if (is_inode_flag_set(inode, FI_INLINE_DOTS))
                ri->i_inline |= F2FS_INLINE_DOTS;
 }
 
 static inline int f2fs_has_inline_xattr(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_XATTR);
+       return is_inode_flag_set(inode, FI_INLINE_XATTR);
 }
 
 static inline unsigned int addrs_per_inode(struct inode *inode)
@@ -1537,43 +1705,43 @@ static inline int inline_xattr_size(struct inode *inode)
 
 static inline int f2fs_has_inline_data(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA);
+       return is_inode_flag_set(inode, FI_INLINE_DATA);
 }
 
 static inline void f2fs_clear_inline_inode(struct inode *inode)
 {
-       clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
-       clear_inode_flag(F2FS_I(inode), FI_DATA_EXIST);
+       clear_inode_flag(inode, FI_INLINE_DATA);
+       clear_inode_flag(inode, FI_DATA_EXIST);
 }
 
 static inline int f2fs_exist_data(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_DATA_EXIST);
+       return is_inode_flag_set(inode, FI_DATA_EXIST);
 }
 
 static inline int f2fs_has_inline_dots(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DOTS);
+       return is_inode_flag_set(inode, FI_INLINE_DOTS);
 }
 
 static inline bool f2fs_is_atomic_file(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_ATOMIC_FILE);
+       return is_inode_flag_set(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);
+       return is_inode_flag_set(inode, FI_VOLATILE_FILE);
 }
 
 static inline bool f2fs_is_first_block_written(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_FIRST_BLOCK_WRITTEN);
+       return is_inode_flag_set(inode, FI_FIRST_BLOCK_WRITTEN);
 }
 
 static inline bool f2fs_is_drop_cache(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_DROP_CACHE);
+       return is_inode_flag_set(inode, FI_DROP_CACHE);
 }
 
 static inline void *inline_data_addr(struct page *page)
@@ -1584,7 +1752,7 @@ static inline void *inline_data_addr(struct page *page)
 
 static inline int f2fs_has_inline_dentry(struct inode *inode)
 {
-       return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DENTRY);
+       return is_inode_flag_set(inode, FI_INLINE_DENTRY);
 }
 
 static inline void f2fs_dentry_kunmap(struct inode *dir, struct page *page)
@@ -1601,11 +1769,13 @@ static inline int is_file(struct inode *inode, int type)
 static inline void set_file(struct inode *inode, int type)
 {
        F2FS_I(inode)->i_advise |= type;
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline void clear_file(struct inode *inode, int type)
 {
        F2FS_I(inode)->i_advise &= ~type;
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline int f2fs_readonly(struct super_block *sb)
@@ -1618,12 +1788,6 @@ static inline bool f2fs_cp_error(struct f2fs_sb_info *sbi)
        return is_set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
 }
 
-static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
-{
-       set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
-       sbi->sb->s_flags |= MS_RDONLY;
-}
-
 static inline bool is_dot_dotdot(const struct qstr *str)
 {
        if (str->len == 1 && str->name[0] == '.')
@@ -1638,12 +1802,21 @@ static inline bool is_dot_dotdot(const struct qstr *str)
 static inline bool f2fs_may_extent_tree(struct inode *inode)
 {
        if (!test_opt(F2FS_I_SB(inode), EXTENT_CACHE) ||
-                       is_inode_flag_set(F2FS_I(inode), FI_NO_EXTENT))
+                       is_inode_flag_set(inode, FI_NO_EXTENT))
                return false;
 
        return S_ISREG(inode->i_mode);
 }
 
+static inline void *f2fs_kmalloc(size_t size, gfp_t flags)
+{
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+       if (time_to_inject(FAULT_KMALLOC))
+               return NULL;
+#endif
+       return kmalloc(size, flags);
+}
+
 static inline void *f2fs_kvmalloc(size_t size, gfp_t flags)
 {
        void *ret;
@@ -1665,7 +1838,7 @@ static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)
 }
 
 #define get_inode_mode(i) \
-       ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
+       ((is_inode_flag_set(i, FI_ACL_MODE)) ? \
         (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
 
 /* get offset of first page in next direct node */
@@ -1680,7 +1853,7 @@ static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)
 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, bool);
-int f2fs_truncate(struct inode *, bool);
+int f2fs_truncate(struct inode *);
 int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int f2fs_setattr(struct dentry *, struct iattr *);
 int truncate_hole(struct inode *, pgoff_t, pgoff_t);
@@ -1710,7 +1883,7 @@ struct dentry *f2fs_get_parent(struct dentry *child);
  */
 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 *,
                        f2fs_hash_t, int *, struct f2fs_dentry_ptr *);
 bool f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *,
@@ -1721,7 +1894,7 @@ struct page *init_inode_metadata(struct inode *, struct inode *,
                        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 page *);
+void f2fs_drop_nlink(struct inode *, struct inode *);
 struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
                                                        struct page **);
 struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
@@ -1731,6 +1904,8 @@ void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
 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);
 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 *,
@@ -1747,6 +1922,8 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
 /*
  * super.c
  */
+int f2fs_inode_dirtied(struct inode *);
+void f2fs_inode_synced(struct inode *);
 int f2fs_commit_super(struct f2fs_sb_info *, bool);
 int f2fs_sync_fs(struct super_block *, int);
 extern __printf(3, 4)
@@ -1780,8 +1957,11 @@ struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *);
 void ra_node_page(struct f2fs_sb_info *, nid_t);
 struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
 struct page *get_node_page_ra(struct page *, int);
-void sync_inode_page(struct dnode_of_data *);
-int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *);
+void move_node_page(struct page *, int);
+int fsync_node_pages(struct f2fs_sb_info *, struct inode *,
+                       struct writeback_control *, bool);
+int sync_node_pages(struct f2fs_sb_info *, struct writeback_control *);
+void build_free_nids(struct f2fs_sb_info *);
 bool alloc_nid(struct f2fs_sb_info *, nid_t *);
 void alloc_nid_done(struct f2fs_sb_info *, nid_t);
 void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
@@ -1843,6 +2023,7 @@ void destroy_segment_manager_caches(void);
 /*
  * checkpoint.c
  */
+void f2fs_stop_checkpoint(struct f2fs_sb_info *, bool);
 struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
 struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
 struct page *get_tmp_page(struct f2fs_sb_info *, pgoff_t);
@@ -1852,16 +2033,16 @@ void ra_meta_pages_cond(struct f2fs_sb_info *, pgoff_t);
 long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
 void add_ino_entry(struct f2fs_sb_info *, nid_t, int type);
 void remove_ino_entry(struct f2fs_sb_info *, nid_t, int type);
-void release_ino_entry(struct f2fs_sb_info *);
+void release_ino_entry(struct f2fs_sb_info *, bool);
 bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
+int f2fs_sync_inode_meta(struct f2fs_sb_info *);
 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 add_orphan_inode(struct inode *);
 void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
 int recover_orphan_inodes(struct f2fs_sb_info *);
 int get_valid_checkpoint(struct f2fs_sb_info *);
 void update_dirty_page(struct inode *, struct page *);
-void add_dirty_dir_inode(struct inode *);
 void remove_dirty_inode(struct inode *);
 int sync_dirty_inodes(struct f2fs_sb_info *, enum inode_type);
 int write_checkpoint(struct f2fs_sb_info *, struct cp_control *);
@@ -1880,6 +2061,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *);
 void f2fs_submit_page_mbio(struct f2fs_io_info *);
 void set_data_blkaddr(struct dnode_of_data *);
 void f2fs_update_data_blkaddr(struct dnode_of_data *, block_t);
+int reserve_new_blocks(struct dnode_of_data *, blkcnt_t);
 int reserve_new_block(struct dnode_of_data *);
 int f2fs_get_block(struct dnode_of_data *, pgoff_t);
 ssize_t f2fs_preallocate_blocks(struct kiocb *, struct iov_iter *);
@@ -1891,6 +2073,7 @@ struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
 int do_write_data_page(struct f2fs_io_info *);
 int f2fs_map_blocks(struct inode *, struct f2fs_map_blocks *, int, int);
 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);
 
@@ -1906,7 +2089,7 @@ void build_gc_manager(struct f2fs_sb_info *);
 /*
  * recovery.c
  */
-int recover_fsync_data(struct f2fs_sb_info *);
+int recover_fsync_data(struct f2fs_sb_info *, bool);
 bool space_for_roll_forward(struct f2fs_sb_info *);
 
 /*
@@ -1921,12 +2104,12 @@ 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;
-       int ndirty_node, ndirty_meta;
-       int ndirty_dent, ndirty_dirs, ndirty_data, ndirty_files;
+       s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, 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, inmem_pages, wb_pages;
-       int inline_xattr, inline_inode, inline_dir;
+       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 bimodal, avg_vblocks;
        int util_free, util_valid, util_invalid;
@@ -2091,7 +2274,6 @@ int f2fs_write_inline_data(struct inode *, struct page *);
 bool recover_inline_data(struct inode *, struct page *);
 struct f2fs_dir_entry *find_in_inline_dir(struct inode *,
                                struct fscrypt_name *, struct page **);
-struct f2fs_dir_entry *f2fs_parent_inline_dir(struct inode *, 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);
@@ -2116,6 +2298,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *);
  */
 unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
 bool f2fs_init_extent_tree(struct inode *, struct f2fs_extent *);
+void f2fs_drop_extent_tree(struct inode *);
 unsigned int f2fs_destroy_extent_node(struct inode *);
 void f2fs_destroy_extent_tree(struct inode *);
 bool f2fs_lookup_extent_cache(struct inode *, pgoff_t, struct extent_info *);
@@ -2151,6 +2334,26 @@ static inline int f2fs_sb_has_crypto(struct super_block *sb)
        return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_ENCRYPT);
 }
 
+static inline int f2fs_sb_mounted_hmsmr(struct super_block *sb)
+{
+       return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_HMSMR);
+}
+
+static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)
+{
+       clear_opt(sbi, ADAPTIVE);
+       clear_opt(sbi, LFS);
+
+       switch (mt) {
+       case F2FS_MOUNT_ADAPTIVE:
+               set_opt(sbi, ADAPTIVE);
+               break;
+       case F2FS_MOUNT_LFS:
+               set_opt(sbi, LFS);
+               break;
+       }
+}
+
 static inline bool f2fs_may_encrypt(struct inode *inode)
 {
 #ifdef CONFIG_F2FS_FS_ENCRYPTION
This page took 0.037796 seconds and 5 git commands to generate.