|
@@ -21,6 +21,7 @@
|
|
#include <linux/sched.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/bio.h>
|
|
#include <linux/bio.h>
|
|
|
|
+#include <linux/blkdev.h>
|
|
|
|
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
#define f2fs_bug_on(sbi, condition) BUG_ON(condition)
|
|
#define f2fs_bug_on(sbi, condition) BUG_ON(condition)
|
|
@@ -54,6 +55,7 @@
|
|
#define F2FS_MOUNT_FASTBOOT 0x00001000
|
|
#define F2FS_MOUNT_FASTBOOT 0x00001000
|
|
#define F2FS_MOUNT_EXTENT_CACHE 0x00002000
|
|
#define F2FS_MOUNT_EXTENT_CACHE 0x00002000
|
|
#define F2FS_MOUNT_FORCE_FG_GC 0x00004000
|
|
#define F2FS_MOUNT_FORCE_FG_GC 0x00004000
|
|
|
|
+#define F2FS_MOUNT_DATA_FLUSH 0x00008000
|
|
|
|
|
|
#define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
|
|
#define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
|
|
#define set_opt(sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
|
|
#define set_opt(sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
|
|
@@ -125,6 +127,7 @@ enum {
|
|
#define BATCHED_TRIM_BLOCKS(sbi) \
|
|
#define BATCHED_TRIM_BLOCKS(sbi) \
|
|
(BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
|
|
(BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
|
|
#define DEF_CP_INTERVAL 60 /* 60 secs */
|
|
#define DEF_CP_INTERVAL 60 /* 60 secs */
|
|
|
|
+#define DEF_IDLE_INTERVAL 120 /* 2 mins */
|
|
|
|
|
|
struct cp_control {
|
|
struct cp_control {
|
|
int reason;
|
|
int reason;
|
|
@@ -158,13 +161,7 @@ struct ino_entry {
|
|
nid_t ino; /* inode number */
|
|
nid_t ino; /* inode number */
|
|
};
|
|
};
|
|
|
|
|
|
-/*
|
|
|
|
- * for the list of directory inodes or gc inodes.
|
|
|
|
- * NOTE: there are two slab users for this structure, if we add/modify/delete
|
|
|
|
- * fields in structure for one of slab users, it may affect fields or size of
|
|
|
|
- * other one, in this condition, it's better to split both of slab and related
|
|
|
|
- * data structure.
|
|
|
|
- */
|
|
|
|
|
|
+/* for the list of inodes to be GCed */
|
|
struct inode_entry {
|
|
struct inode_entry {
|
|
struct list_head list; /* list head */
|
|
struct list_head list; /* list head */
|
|
struct inode *inode; /* vfs inode pointer */
|
|
struct inode *inode; /* vfs inode pointer */
|
|
@@ -234,6 +231,7 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,
|
|
#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
|
|
#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
|
|
#define F2FS_IOC_GARBAGE_COLLECT _IO(F2FS_IOCTL_MAGIC, 6)
|
|
#define F2FS_IOC_GARBAGE_COLLECT _IO(F2FS_IOCTL_MAGIC, 6)
|
|
#define F2FS_IOC_WRITE_CHECKPOINT _IO(F2FS_IOCTL_MAGIC, 7)
|
|
#define F2FS_IOC_WRITE_CHECKPOINT _IO(F2FS_IOCTL_MAGIC, 7)
|
|
|
|
+#define F2FS_IOC_DEFRAGMENT _IO(F2FS_IOCTL_MAGIC, 8)
|
|
|
|
|
|
#define F2FS_IOC_SET_ENCRYPTION_POLICY \
|
|
#define F2FS_IOC_SET_ENCRYPTION_POLICY \
|
|
_IOR('f', 19, struct f2fs_encryption_policy)
|
|
_IOR('f', 19, struct f2fs_encryption_policy)
|
|
@@ -256,10 +254,16 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,
|
|
/*
|
|
/*
|
|
* ioctl commands in 32 bit emulation
|
|
* ioctl commands in 32 bit emulation
|
|
*/
|
|
*/
|
|
-#define F2FS_IOC32_GETFLAGS FS_IOC32_GETFLAGS
|
|
|
|
-#define F2FS_IOC32_SETFLAGS FS_IOC32_SETFLAGS
|
|
|
|
|
|
+#define F2FS_IOC32_GETFLAGS FS_IOC32_GETFLAGS
|
|
|
|
+#define F2FS_IOC32_SETFLAGS FS_IOC32_SETFLAGS
|
|
|
|
+#define F2FS_IOC32_GETVERSION FS_IOC32_GETVERSION
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+struct f2fs_defragment {
|
|
|
|
+ u64 start;
|
|
|
|
+ u64 len;
|
|
|
|
+};
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* For INODE and NODE manager
|
|
* For INODE and NODE manager
|
|
*/
|
|
*/
|
|
@@ -357,9 +361,9 @@ struct extent_tree {
|
|
struct rb_root root; /* root of extent info rb-tree */
|
|
struct rb_root root; /* root of extent info rb-tree */
|
|
struct extent_node *cached_en; /* recently accessed extent node */
|
|
struct extent_node *cached_en; /* recently accessed extent node */
|
|
struct extent_info largest; /* largested extent info */
|
|
struct extent_info largest; /* largested extent info */
|
|
|
|
+ struct list_head list; /* to be used by sbi->zombie_list */
|
|
rwlock_t lock; /* protect extent info rb-tree */
|
|
rwlock_t lock; /* protect extent info rb-tree */
|
|
- atomic_t refcount; /* reference count of rb-tree */
|
|
|
|
- unsigned int count; /* # of extent node in rb-tree*/
|
|
|
|
|
|
+ atomic_t node_cnt; /* # of extent node in rb-tree*/
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -434,8 +438,8 @@ struct f2fs_inode_info {
|
|
unsigned int clevel; /* maximum level of given file name */
|
|
unsigned int clevel; /* maximum level of given file name */
|
|
nid_t i_xattr_nid; /* node id that contains xattrs */
|
|
nid_t i_xattr_nid; /* node id that contains xattrs */
|
|
unsigned long long xattr_ver; /* cp version of xattr modification */
|
|
unsigned long long xattr_ver; /* cp version of xattr modification */
|
|
- struct inode_entry *dirty_dir; /* the pointer of dirty dir */
|
|
|
|
|
|
|
|
|
|
+ struct list_head dirty_list; /* linked in global dirty list */
|
|
struct list_head inmem_pages; /* inmemory pages managed by f2fs */
|
|
struct list_head inmem_pages; /* inmemory pages managed by f2fs */
|
|
struct mutex inmem_lock; /* lock for inmemory pages */
|
|
struct mutex inmem_lock; /* lock for inmemory pages */
|
|
|
|
|
|
@@ -544,6 +548,7 @@ struct dnode_of_data {
|
|
nid_t nid; /* node id of the direct node block */
|
|
nid_t nid; /* node id of the direct node block */
|
|
unsigned int ofs_in_node; /* data offset in the node page */
|
|
unsigned int ofs_in_node; /* data offset in the node page */
|
|
bool inode_page_locked; /* inode page is locked or not */
|
|
bool inode_page_locked; /* inode page is locked or not */
|
|
|
|
+ bool node_changed; /* is node block changed */
|
|
block_t data_blkaddr; /* block address of the node block */
|
|
block_t data_blkaddr; /* block address of the node block */
|
|
};
|
|
};
|
|
|
|
|
|
@@ -647,6 +652,7 @@ struct f2fs_sm_info {
|
|
enum count_type {
|
|
enum count_type {
|
|
F2FS_WRITEBACK,
|
|
F2FS_WRITEBACK,
|
|
F2FS_DIRTY_DENTS,
|
|
F2FS_DIRTY_DENTS,
|
|
|
|
+ F2FS_DIRTY_DATA,
|
|
F2FS_DIRTY_NODES,
|
|
F2FS_DIRTY_NODES,
|
|
F2FS_DIRTY_META,
|
|
F2FS_DIRTY_META,
|
|
F2FS_INMEM_PAGES,
|
|
F2FS_INMEM_PAGES,
|
|
@@ -695,6 +701,12 @@ struct f2fs_bio_info {
|
|
struct rw_semaphore io_rwsem; /* blocking op for bio */
|
|
struct rw_semaphore io_rwsem; /* blocking op for bio */
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+enum inode_type {
|
|
|
|
+ DIR_INODE, /* for dirty dir inode */
|
|
|
|
+ FILE_INODE, /* for dirty regular/symlink inode */
|
|
|
|
+ NR_INODE_TYPE,
|
|
|
|
+};
|
|
|
|
+
|
|
/* for inner inode cache management */
|
|
/* for inner inode cache management */
|
|
struct inode_management {
|
|
struct inode_management {
|
|
struct radix_tree_root ino_root; /* ino entry array */
|
|
struct radix_tree_root ino_root; /* ino entry array */
|
|
@@ -711,11 +723,17 @@ enum {
|
|
SBI_POR_DOING, /* recovery is doing or not */
|
|
SBI_POR_DOING, /* recovery is doing or not */
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+enum {
|
|
|
|
+ CP_TIME,
|
|
|
|
+ REQ_TIME,
|
|
|
|
+ MAX_TIME,
|
|
|
|
+};
|
|
|
|
+
|
|
struct f2fs_sb_info {
|
|
struct f2fs_sb_info {
|
|
struct super_block *sb; /* pointer to VFS super block */
|
|
struct super_block *sb; /* pointer to VFS super block */
|
|
struct proc_dir_entry *s_proc; /* proc entry */
|
|
struct proc_dir_entry *s_proc; /* proc entry */
|
|
- struct buffer_head *raw_super_buf; /* buffer head of raw sb */
|
|
|
|
struct f2fs_super_block *raw_super; /* raw super block pointer */
|
|
struct f2fs_super_block *raw_super; /* raw super block pointer */
|
|
|
|
+ int valid_super_block; /* valid super block no */
|
|
int s_flag; /* flags for sbi */
|
|
int s_flag; /* flags for sbi */
|
|
|
|
|
|
/* for node-related operations */
|
|
/* for node-related operations */
|
|
@@ -737,23 +755,26 @@ struct f2fs_sb_info {
|
|
struct rw_semaphore node_write; /* locking node writes */
|
|
struct rw_semaphore node_write; /* locking node writes */
|
|
struct mutex writepages; /* mutex for writepages() */
|
|
struct mutex writepages; /* mutex for writepages() */
|
|
wait_queue_head_t cp_wait;
|
|
wait_queue_head_t cp_wait;
|
|
- long cp_expires, cp_interval; /* next expected periodic cp */
|
|
|
|
|
|
+ unsigned long last_time[MAX_TIME]; /* to store time in jiffies */
|
|
|
|
+ long interval_time[MAX_TIME]; /* to store thresholds */
|
|
|
|
|
|
struct inode_management im[MAX_INO_ENTRY]; /* manage inode cache */
|
|
struct inode_management im[MAX_INO_ENTRY]; /* manage inode cache */
|
|
|
|
|
|
/* for orphan inode, use 0'th array */
|
|
/* for orphan inode, use 0'th array */
|
|
unsigned int max_orphans; /* max orphan inodes */
|
|
unsigned int max_orphans; /* max orphan inodes */
|
|
|
|
|
|
- /* for directory inode management */
|
|
|
|
- struct list_head dir_inode_list; /* dir inode list */
|
|
|
|
- spinlock_t dir_inode_lock; /* for dir inode list lock */
|
|
|
|
|
|
+ /* for inode management */
|
|
|
|
+ struct list_head inode_list[NR_INODE_TYPE]; /* dirty inode list */
|
|
|
|
+ spinlock_t inode_lock[NR_INODE_TYPE]; /* for dirty inode list lock */
|
|
|
|
|
|
/* for extent tree cache */
|
|
/* for extent tree cache */
|
|
struct radix_tree_root extent_tree_root;/* cache extent cache entries */
|
|
struct radix_tree_root extent_tree_root;/* cache extent cache entries */
|
|
struct rw_semaphore extent_tree_lock; /* locking extent radix tree */
|
|
struct rw_semaphore extent_tree_lock; /* locking extent radix tree */
|
|
struct list_head extent_list; /* lru list for shrinker */
|
|
struct list_head extent_list; /* lru list for shrinker */
|
|
spinlock_t extent_lock; /* locking extent lru list */
|
|
spinlock_t extent_lock; /* locking extent lru list */
|
|
- int total_ext_tree; /* extent tree count */
|
|
|
|
|
|
+ atomic_t total_ext_tree; /* extent tree count */
|
|
|
|
+ struct list_head zombie_list; /* extent zombie tree list */
|
|
|
|
+ atomic_t total_zombie_tree; /* extent zombie tree count */
|
|
atomic_t total_ext_node; /* extent info count */
|
|
atomic_t total_ext_node; /* extent info count */
|
|
|
|
|
|
/* basic filesystem units */
|
|
/* basic filesystem units */
|
|
@@ -771,6 +792,7 @@ struct f2fs_sb_info {
|
|
unsigned int total_node_count; /* total node block count */
|
|
unsigned int total_node_count; /* total node block count */
|
|
unsigned int total_valid_node_count; /* valid node block count */
|
|
unsigned int total_valid_node_count; /* valid node block count */
|
|
unsigned int total_valid_inode_count; /* valid inode 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 active_logs; /* # of active logs */
|
|
int dir_level; /* directory level */
|
|
int dir_level; /* directory level */
|
|
|
|
|
|
@@ -809,7 +831,7 @@ struct f2fs_sb_info {
|
|
atomic_t inline_inode; /* # of inline_data inodes */
|
|
atomic_t inline_inode; /* # of inline_data inodes */
|
|
atomic_t inline_dir; /* # of inline_dentry inodes */
|
|
atomic_t inline_dir; /* # of inline_dentry inodes */
|
|
int bg_gc; /* background gc calls */
|
|
int bg_gc; /* background gc calls */
|
|
- unsigned int n_dirty_dirs; /* # of dir inodes */
|
|
|
|
|
|
+ unsigned int ndirty_inode[NR_INODE_TYPE]; /* # of dirty inodes */
|
|
#endif
|
|
#endif
|
|
unsigned int last_victim[2]; /* last victim segment # */
|
|
unsigned int last_victim[2]; /* last victim segment # */
|
|
spinlock_t stat_lock; /* lock for stat operations */
|
|
spinlock_t stat_lock; /* lock for stat operations */
|
|
@@ -824,6 +846,31 @@ struct f2fs_sb_info {
|
|
unsigned int shrinker_run_no;
|
|
unsigned int shrinker_run_no;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static inline void f2fs_update_time(struct f2fs_sb_info *sbi, int type)
|
|
|
|
+{
|
|
|
|
+ sbi->last_time[type] = jiffies;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type)
|
|
|
|
+{
|
|
|
|
+ struct timespec ts = {sbi->interval_time[type], 0};
|
|
|
|
+ unsigned long interval = timespec_to_jiffies(&ts);
|
|
|
|
+
|
|
|
|
+ return time_after(jiffies, sbi->last_time[type] + interval);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline bool is_idle(struct f2fs_sb_info *sbi)
|
|
|
|
+{
|
|
|
|
+ struct block_device *bdev = sbi->sb->s_bdev;
|
|
|
|
+ struct request_queue *q = bdev_get_queue(bdev);
|
|
|
|
+ struct request_list *rl = &q->root_rl;
|
|
|
|
+
|
|
|
|
+ if (rl->count[BLK_RW_SYNC] || rl->count[BLK_RW_ASYNC])
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ return f2fs_time_over(sbi, REQ_TIME);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Inline functions
|
|
* Inline functions
|
|
*/
|
|
*/
|
|
@@ -1059,8 +1106,8 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
|
|
static inline void inode_inc_dirty_pages(struct inode *inode)
|
|
static inline void inode_inc_dirty_pages(struct inode *inode)
|
|
{
|
|
{
|
|
atomic_inc(&F2FS_I(inode)->dirty_pages);
|
|
atomic_inc(&F2FS_I(inode)->dirty_pages);
|
|
- if (S_ISDIR(inode->i_mode))
|
|
|
|
- inc_page_count(F2FS_I_SB(inode), F2FS_DIRTY_DENTS);
|
|
|
|
|
|
+ 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)
|
|
static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
|
|
@@ -1075,9 +1122,8 @@ static inline void inode_dec_dirty_pages(struct inode *inode)
|
|
return;
|
|
return;
|
|
|
|
|
|
atomic_dec(&F2FS_I(inode)->dirty_pages);
|
|
atomic_dec(&F2FS_I(inode)->dirty_pages);
|
|
-
|
|
|
|
- if (S_ISDIR(inode->i_mode))
|
|
|
|
- dec_page_count(F2FS_I_SB(inode), F2FS_DIRTY_DENTS);
|
|
|
|
|
|
+ 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 int get_pages(struct f2fs_sb_info *sbi, int count_type)
|
|
@@ -1092,8 +1138,7 @@ static inline int get_dirty_pages(struct inode *inode)
|
|
|
|
|
|
static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
|
|
static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
|
|
{
|
|
{
|
|
- unsigned int pages_per_sec = sbi->segs_per_sec *
|
|
|
|
- (1 << sbi->log_blocks_per_seg);
|
|
|
|
|
|
+ unsigned int pages_per_sec = sbi->segs_per_sec * sbi->blocks_per_seg;
|
|
return ((get_pages(sbi, block_type) + pages_per_sec - 1)
|
|
return ((get_pages(sbi, block_type) + pages_per_sec - 1)
|
|
>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
|
|
>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
|
|
}
|
|
}
|
|
@@ -1416,6 +1461,8 @@ enum {
|
|
FI_DROP_CACHE, /* drop dirty page cache */
|
|
FI_DROP_CACHE, /* drop dirty page cache */
|
|
FI_DATA_EXIST, /* indicate data exists */
|
|
FI_DATA_EXIST, /* indicate data exists */
|
|
FI_INLINE_DOTS, /* indicate inline dot dentries */
|
|
FI_INLINE_DOTS, /* indicate inline dot dentries */
|
|
|
|
+ FI_DO_DEFRAG, /* indicate defragment is running */
|
|
|
|
+ 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 set_inode_flag(struct f2fs_inode_info *fi, int flag)
|
|
@@ -1659,8 +1706,8 @@ long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long);
|
|
void f2fs_set_inode_flags(struct inode *);
|
|
void f2fs_set_inode_flags(struct inode *);
|
|
struct inode *f2fs_iget(struct super_block *, unsigned long);
|
|
struct inode *f2fs_iget(struct super_block *, unsigned long);
|
|
int try_to_free_nats(struct f2fs_sb_info *, int);
|
|
int try_to_free_nats(struct f2fs_sb_info *, int);
|
|
-void update_inode(struct inode *, struct page *);
|
|
|
|
-void update_inode_page(struct inode *);
|
|
|
|
|
|
+int update_inode(struct inode *, struct page *);
|
|
|
|
+int update_inode_page(struct inode *);
|
|
int f2fs_write_inode(struct inode *, struct writeback_control *);
|
|
int f2fs_write_inode(struct inode *, struct writeback_control *);
|
|
void f2fs_evict_inode(struct inode *);
|
|
void f2fs_evict_inode(struct inode *);
|
|
void handle_failed_inode(struct inode *);
|
|
void handle_failed_inode(struct inode *);
|
|
@@ -1765,7 +1812,7 @@ void destroy_node_manager_caches(void);
|
|
*/
|
|
*/
|
|
void register_inmem_page(struct inode *, struct page *);
|
|
void register_inmem_page(struct inode *, struct page *);
|
|
int commit_inmem_pages(struct inode *, bool);
|
|
int commit_inmem_pages(struct inode *, bool);
|
|
-void f2fs_balance_fs(struct f2fs_sb_info *);
|
|
|
|
|
|
+void f2fs_balance_fs(struct f2fs_sb_info *, bool);
|
|
void f2fs_balance_fs_bg(struct f2fs_sb_info *);
|
|
void f2fs_balance_fs_bg(struct f2fs_sb_info *);
|
|
int f2fs_issue_flush(struct f2fs_sb_info *);
|
|
int f2fs_issue_flush(struct f2fs_sb_info *);
|
|
int create_flush_cmd_control(struct f2fs_sb_info *);
|
|
int create_flush_cmd_control(struct f2fs_sb_info *);
|
|
@@ -1811,9 +1858,9 @@ bool is_valid_blkaddr(struct f2fs_sb_info *, block_t, int);
|
|
int ra_meta_pages(struct f2fs_sb_info *, block_t, int, int, bool);
|
|
int ra_meta_pages(struct f2fs_sb_info *, block_t, int, int, bool);
|
|
void ra_meta_pages_cond(struct f2fs_sb_info *, pgoff_t);
|
|
void ra_meta_pages_cond(struct f2fs_sb_info *, pgoff_t);
|
|
long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
|
|
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);
|
|
|
|
-void release_dirty_inode(struct f2fs_sb_info *);
|
|
|
|
|
|
+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 *);
|
|
bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
|
|
bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
|
|
int acquire_orphan_inode(struct f2fs_sb_info *);
|
|
int acquire_orphan_inode(struct f2fs_sb_info *);
|
|
void release_orphan_inode(struct f2fs_sb_info *);
|
|
void release_orphan_inode(struct f2fs_sb_info *);
|
|
@@ -1823,9 +1870,9 @@ int recover_orphan_inodes(struct f2fs_sb_info *);
|
|
int get_valid_checkpoint(struct f2fs_sb_info *);
|
|
int get_valid_checkpoint(struct f2fs_sb_info *);
|
|
void update_dirty_page(struct inode *, struct page *);
|
|
void update_dirty_page(struct inode *, struct page *);
|
|
void add_dirty_dir_inode(struct inode *);
|
|
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 *, struct cp_control *);
|
|
|
|
|
|
+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 *);
|
|
void init_ino_entry_info(struct f2fs_sb_info *);
|
|
void init_ino_entry_info(struct f2fs_sb_info *);
|
|
int __init create_checkpoint_caches(void);
|
|
int __init create_checkpoint_caches(void);
|
|
void destroy_checkpoint_caches(void);
|
|
void destroy_checkpoint_caches(void);
|
|
@@ -1845,6 +1892,7 @@ struct page *find_data_page(struct inode *, pgoff_t);
|
|
struct page *get_lock_data_page(struct inode *, pgoff_t, bool);
|
|
struct page *get_lock_data_page(struct inode *, pgoff_t, bool);
|
|
struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
|
|
struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
|
|
int do_write_data_page(struct f2fs_io_info *);
|
|
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);
|
|
int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *, u64, u64);
|
|
void f2fs_invalidate_page(struct page *, unsigned int, unsigned int);
|
|
void f2fs_invalidate_page(struct page *, unsigned int, unsigned int);
|
|
int f2fs_release_page(struct page *, gfp_t);
|
|
int f2fs_release_page(struct page *, gfp_t);
|
|
@@ -1875,8 +1923,9 @@ struct f2fs_stat_info {
|
|
int main_area_segs, main_area_sections, main_area_zones;
|
|
int main_area_segs, main_area_sections, main_area_zones;
|
|
unsigned long long hit_largest, hit_cached, hit_rbtree;
|
|
unsigned long long hit_largest, hit_cached, hit_rbtree;
|
|
unsigned long long hit_total, total_ext;
|
|
unsigned long long hit_total, total_ext;
|
|
- int ext_tree, ext_node;
|
|
|
|
- int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
|
|
|
|
|
|
+ int ext_tree, zombie_tree, ext_node;
|
|
|
|
+ int ndirty_node, ndirty_meta;
|
|
|
|
+ int ndirty_dent, ndirty_dirs, ndirty_data, ndirty_files;
|
|
int nats, dirty_nats, sits, dirty_sits, fnids;
|
|
int nats, dirty_nats, sits, dirty_sits, fnids;
|
|
int total_count, utilization;
|
|
int total_count, utilization;
|
|
int bg_gc, inmem_pages, wb_pages;
|
|
int bg_gc, inmem_pages, wb_pages;
|
|
@@ -1886,7 +1935,7 @@ struct f2fs_stat_info {
|
|
int util_free, util_valid, util_invalid;
|
|
int util_free, util_valid, util_invalid;
|
|
int rsvd_segs, overp_segs;
|
|
int rsvd_segs, overp_segs;
|
|
int dirty_count, node_pages, meta_pages;
|
|
int dirty_count, node_pages, meta_pages;
|
|
- int prefree_count, call_count, cp_count;
|
|
|
|
|
|
+ int prefree_count, call_count, cp_count, bg_cp_count;
|
|
int tot_segs, node_segs, data_segs, free_segs, free_secs;
|
|
int tot_segs, node_segs, data_segs, free_segs, free_secs;
|
|
int bg_node_segs, bg_data_segs;
|
|
int bg_node_segs, bg_data_segs;
|
|
int tot_blks, data_blks, node_blks;
|
|
int tot_blks, data_blks, node_blks;
|
|
@@ -1907,10 +1956,11 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
|
|
}
|
|
}
|
|
|
|
|
|
#define stat_inc_cp_count(si) ((si)->cp_count++)
|
|
#define stat_inc_cp_count(si) ((si)->cp_count++)
|
|
|
|
+#define stat_inc_bg_cp_count(si) ((si)->bg_cp_count++)
|
|
#define stat_inc_call_count(si) ((si)->call_count++)
|
|
#define stat_inc_call_count(si) ((si)->call_count++)
|
|
#define stat_inc_bggc_count(sbi) ((sbi)->bg_gc++)
|
|
#define stat_inc_bggc_count(sbi) ((sbi)->bg_gc++)
|
|
-#define stat_inc_dirty_dir(sbi) ((sbi)->n_dirty_dirs++)
|
|
|
|
-#define stat_dec_dirty_dir(sbi) ((sbi)->n_dirty_dirs--)
|
|
|
|
|
|
+#define stat_inc_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]++)
|
|
|
|
+#define stat_dec_dirty_inode(sbi, type) ((sbi)->ndirty_inode[type]--)
|
|
#define stat_inc_total_hit(sbi) (atomic64_inc(&(sbi)->total_hit_ext))
|
|
#define stat_inc_total_hit(sbi) (atomic64_inc(&(sbi)->total_hit_ext))
|
|
#define stat_inc_rbtree_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_rbtree))
|
|
#define stat_inc_rbtree_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_rbtree))
|
|
#define stat_inc_largest_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_largest))
|
|
#define stat_inc_largest_node_hit(sbi) (atomic64_inc(&(sbi)->read_hit_largest))
|
|
@@ -1985,14 +2035,15 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
|
|
|
|
|
|
int f2fs_build_stats(struct f2fs_sb_info *);
|
|
int f2fs_build_stats(struct f2fs_sb_info *);
|
|
void f2fs_destroy_stats(struct f2fs_sb_info *);
|
|
void f2fs_destroy_stats(struct f2fs_sb_info *);
|
|
-void __init f2fs_create_root_stats(void);
|
|
|
|
|
|
+int __init f2fs_create_root_stats(void);
|
|
void f2fs_destroy_root_stats(void);
|
|
void f2fs_destroy_root_stats(void);
|
|
#else
|
|
#else
|
|
#define stat_inc_cp_count(si)
|
|
#define stat_inc_cp_count(si)
|
|
|
|
+#define stat_inc_bg_cp_count(si)
|
|
#define stat_inc_call_count(si)
|
|
#define stat_inc_call_count(si)
|
|
#define stat_inc_bggc_count(si)
|
|
#define stat_inc_bggc_count(si)
|
|
-#define stat_inc_dirty_dir(sbi)
|
|
|
|
-#define stat_dec_dirty_dir(sbi)
|
|
|
|
|
|
+#define stat_inc_dirty_inode(sbi, type)
|
|
|
|
+#define stat_dec_dirty_inode(sbi, type)
|
|
#define stat_inc_total_hit(sb)
|
|
#define stat_inc_total_hit(sb)
|
|
#define stat_inc_rbtree_node_hit(sb)
|
|
#define stat_inc_rbtree_node_hit(sb)
|
|
#define stat_inc_largest_node_hit(sbi)
|
|
#define stat_inc_largest_node_hit(sbi)
|
|
@@ -2013,7 +2064,7 @@ void f2fs_destroy_root_stats(void);
|
|
|
|
|
|
static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
|
|
static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
|
|
static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
|
|
static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
|
|
-static inline void __init f2fs_create_root_stats(void) { }
|
|
|
|
|
|
+static inline int __init f2fs_create_root_stats(void) { return 0; }
|
|
static inline void f2fs_destroy_root_stats(void) { }
|
|
static inline void f2fs_destroy_root_stats(void) { }
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -2067,8 +2118,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *);
|
|
* extent_cache.c
|
|
* extent_cache.c
|
|
*/
|
|
*/
|
|
unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
|
|
unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
|
|
-void f2fs_drop_largest_extent(struct inode *, pgoff_t);
|
|
|
|
-void f2fs_init_extent_tree(struct inode *, struct f2fs_extent *);
|
|
|
|
|
|
+bool f2fs_init_extent_tree(struct inode *, struct f2fs_extent *);
|
|
unsigned int f2fs_destroy_extent_node(struct inode *);
|
|
unsigned int f2fs_destroy_extent_node(struct inode *);
|
|
void f2fs_destroy_extent_tree(struct inode *);
|
|
void f2fs_destroy_extent_tree(struct inode *);
|
|
bool f2fs_lookup_extent_cache(struct inode *, pgoff_t, struct extent_info *);
|
|
bool f2fs_lookup_extent_cache(struct inode *, pgoff_t, struct extent_info *);
|