f2fs: avoid memory allocation failure due to a long length
[deliverable/linux.git] / fs / f2fs / f2fs.h
index 2adef0e58461b39fad332d72137e78ff9c88f3a8..521cb92285fa1622239cbb5940330b5d7f7de857 100644 (file)
@@ -45,6 +45,7 @@ enum {
        FAULT_ORPHAN,
        FAULT_BLOCK,
        FAULT_DIR_DEPTH,
+       FAULT_EVICT_INODE,
        FAULT_MAX,
 };
 
@@ -74,6 +75,8 @@ static inline bool time_to_inject(int 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) {
@@ -108,6 +111,8 @@ static inline bool time_to_inject(int type)
 #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)
@@ -128,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)
@@ -158,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;
@@ -441,12 +447,14 @@ struct f2fs_inode_info {
        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;    /* 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,
@@ -499,12 +507,13 @@ static inline bool __is_front_mergeable(struct extent_info *cur,
        return __is_extent_mergeable(cur, front);
 }
 
+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) {
                et->largest = en->ei;
-               mark_inode_dirty_sync(inode);
+               f2fs_mark_inode_dirty_sync(inode);
        }
 }
 
@@ -520,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 */
@@ -602,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 */
 };
@@ -761,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 */
@@ -1054,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)
@@ -1128,30 +1138,23 @@ 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)
 {
-       block_t valid_block_count;
-
-       spin_lock(&sbi->stat_lock);
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-       if (time_to_inject(FAULT_BLOCK)) {
-               spin_unlock(&sbi->stat_lock);
+       if (time_to_inject(FAULT_BLOCK))
                return false;
-       }
 #endif
-       valid_block_count =
-               sbi->total_valid_block_count + (block_t)(*count);
-       if (unlikely(valid_block_count > sbi->user_block_count)) {
-               *count = sbi->user_block_count - sbi->total_valid_block_count;
+       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;
                }
        }
-       /* *count can be recalculated */
-       f2fs_i_blocks_write(inode, *count, true);
-       sbi->total_valid_block_count =
-               sbi->total_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;
 }
@@ -1163,9 +1166,9 @@ 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);
-       f2fs_i_blocks_write(inode, count, false);
        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)
@@ -1516,6 +1519,7 @@ 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 */
@@ -1549,7 +1553,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
                        return;
        case FI_DATA_EXIST:
        case FI_INLINE_DOTS:
-               mark_inode_dirty_sync(inode);
+               f2fs_mark_inode_dirty_sync(inode);
        }
 }
 
@@ -1576,7 +1580,7 @@ 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);
-       mark_inode_dirty_sync(inode);
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline void f2fs_i_links_write(struct inode *inode, bool inc)
@@ -1585,42 +1589,59 @@ static inline void f2fs_i_links_write(struct inode *inode, bool inc)
                inc_nlink(inode);
        else
                drop_nlink(inode);
-       mark_inode_dirty_sync(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;
-       mark_inode_dirty_sync(inode);
+       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);
-       mark_inode_dirty_sync(inode);
+       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 (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
+               return false;
+       return F2FS_I(inode)->last_disk_size == i_size_read(inode);
 }
 
 static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth)
 {
        F2FS_I(inode)->i_current_depth = depth;
-       mark_inode_dirty_sync(inode);
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid)
 {
        F2FS_I(inode)->i_xattr_nid = xnid;
-       mark_inode_dirty_sync(inode);
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline void f2fs_i_pino_write(struct inode *inode, nid_t pino)
 {
        F2FS_I(inode)->i_pino = pino;
-       mark_inode_dirty_sync(inode);
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri)
@@ -1748,13 +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;
-       mark_inode_dirty_sync(inode);
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline void clear_file(struct inode *inode, int type)
 {
        F2FS_I(inode)->i_advise &= ~type;
-       mark_inode_dirty_sync(inode);
+       f2fs_mark_inode_dirty_sync(inode);
 }
 
 static inline int f2fs_readonly(struct super_block *sb)
@@ -1832,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);
@@ -1873,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 **);
@@ -1901,6 +1922,7 @@ 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);
@@ -1936,9 +1958,10 @@ 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 move_node_page(struct page *, int);
-int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *,
-                                                               bool);
+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);
@@ -2015,7 +2038,7 @@ 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 *);
@@ -2050,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);
 
@@ -2250,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);
@@ -2275,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 *);
@@ -2310,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.03117 seconds and 5 git commands to generate.