|
@@ -103,7 +103,7 @@ struct f2fs_mount_info {
|
|
|
};
|
|
|
|
|
|
#define F2FS_FEATURE_ENCRYPT 0x0001
|
|
|
-#define F2FS_FEATURE_HMSMR 0x0002
|
|
|
+#define F2FS_FEATURE_BLKZONED 0x0002
|
|
|
|
|
|
#define F2FS_HAS_FEATURE(sb, mask) \
|
|
|
((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
|
|
@@ -401,6 +401,7 @@ struct f2fs_map_blocks {
|
|
|
#define FADVISE_LOST_PINO_BIT 0x02
|
|
|
#define FADVISE_ENCRYPT_BIT 0x04
|
|
|
#define FADVISE_ENC_NAME_BIT 0x08
|
|
|
+#define FADVISE_KEEP_SIZE_BIT 0x10
|
|
|
|
|
|
#define file_is_cold(inode) is_file(inode, FADVISE_COLD_BIT)
|
|
|
#define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT)
|
|
@@ -413,6 +414,8 @@ struct f2fs_map_blocks {
|
|
|
#define file_clear_encrypt(inode) clear_file(inode, FADVISE_ENCRYPT_BIT)
|
|
|
#define file_enc_name(inode) is_file(inode, FADVISE_ENC_NAME_BIT)
|
|
|
#define file_set_enc_name(inode) set_file(inode, FADVISE_ENC_NAME_BIT)
|
|
|
+#define file_keep_isize(inode) is_file(inode, FADVISE_KEEP_SIZE_BIT)
|
|
|
+#define file_set_keep_isize(inode) set_file(inode, FADVISE_KEEP_SIZE_BIT)
|
|
|
|
|
|
#define DEF_DIR_LEVEL 0
|
|
|
|
|
@@ -428,7 +431,7 @@ 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 */
|
|
|
- struct percpu_counter dirty_pages; /* # of dirty 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 */
|
|
@@ -493,20 +496,26 @@ 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 *);
|
|
|
+extern void f2fs_mark_inode_dirty_sync(struct inode *, bool);
|
|
|
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;
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+enum nid_list {
|
|
|
+ FREE_NID_LIST,
|
|
|
+ ALLOC_NID_LIST,
|
|
|
+ MAX_NID_LIST,
|
|
|
+};
|
|
|
+
|
|
|
struct f2fs_nm_info {
|
|
|
block_t nat_blkaddr; /* base disk address of NAT */
|
|
|
nid_t max_nid; /* maximum possible node ids */
|
|
|
- nid_t available_nids; /* maximum available node ids */
|
|
|
+ nid_t available_nids; /* # of available node ids */
|
|
|
nid_t next_scan_nid; /* the next nid to be scanned */
|
|
|
unsigned int ram_thresh; /* control the memory footprint */
|
|
|
unsigned int ra_nid_pages; /* # of nid pages to be readaheaded */
|
|
@@ -522,9 +531,9 @@ struct f2fs_nm_info {
|
|
|
|
|
|
/* free node ids management */
|
|
|
struct radix_tree_root free_nid_root;/* root of the free_nid cache */
|
|
|
- struct list_head free_nid_list; /* a list for free nids */
|
|
|
- spinlock_t free_nid_list_lock; /* protect free nid list */
|
|
|
- unsigned int fcnt; /* the number of free node id */
|
|
|
+ struct list_head nid_list[MAX_NID_LIST];/* lists for free nids */
|
|
|
+ unsigned int nid_cnt[MAX_NID_LIST]; /* the number of free node id */
|
|
|
+ spinlock_t nid_list_lock; /* protect nid lists ops */
|
|
|
struct mutex build_lock; /* lock for build free nids */
|
|
|
|
|
|
/* for checkpoint */
|
|
@@ -585,7 +594,6 @@ enum {
|
|
|
CURSEG_WARM_NODE, /* direct node blocks of normal files */
|
|
|
CURSEG_COLD_NODE, /* indirect node blocks */
|
|
|
NO_CHECK_TYPE,
|
|
|
- CURSEG_DIRECT_IO, /* to use for the direct IO path */
|
|
|
};
|
|
|
|
|
|
struct flush_cmd {
|
|
@@ -649,6 +657,7 @@ struct f2fs_sm_info {
|
|
|
* f2fs monitors the number of several block types such as on-writeback,
|
|
|
* dirty dentry blocks, dirty node blocks, and dirty meta blocks.
|
|
|
*/
|
|
|
+#define WB_DATA_TYPE(p) (__is_cp_guaranteed(p) ? F2FS_WB_CP_DATA : F2FS_WB_DATA)
|
|
|
enum count_type {
|
|
|
F2FS_DIRTY_DENTS,
|
|
|
F2FS_DIRTY_DATA,
|
|
@@ -656,6 +665,8 @@ enum count_type {
|
|
|
F2FS_DIRTY_META,
|
|
|
F2FS_INMEM_PAGES,
|
|
|
F2FS_DIRTY_IMETA,
|
|
|
+ F2FS_WB_CP_DATA,
|
|
|
+ F2FS_WB_DATA,
|
|
|
NR_COUNT_TYPE,
|
|
|
};
|
|
|
|
|
@@ -704,6 +715,20 @@ struct f2fs_bio_info {
|
|
|
struct rw_semaphore io_rwsem; /* blocking op for bio */
|
|
|
};
|
|
|
|
|
|
+#define FDEV(i) (sbi->devs[i])
|
|
|
+#define RDEV(i) (raw_super->devs[i])
|
|
|
+struct f2fs_dev_info {
|
|
|
+ struct block_device *bdev;
|
|
|
+ char path[MAX_PATH_LEN];
|
|
|
+ unsigned int total_segments;
|
|
|
+ block_t start_blk;
|
|
|
+ block_t end_blk;
|
|
|
+#ifdef CONFIG_BLK_DEV_ZONED
|
|
|
+ unsigned int nr_blkz; /* Total number of zones */
|
|
|
+ u8 *blkz_type; /* Array of zones type */
|
|
|
+#endif
|
|
|
+};
|
|
|
+
|
|
|
enum inode_type {
|
|
|
DIR_INODE, /* for dirty dir inode */
|
|
|
FILE_INODE, /* for dirty regular/symlink inode */
|
|
@@ -750,6 +775,12 @@ struct f2fs_sb_info {
|
|
|
u8 key_prefix[F2FS_KEY_DESC_PREFIX_SIZE];
|
|
|
u8 key_prefix_size;
|
|
|
#endif
|
|
|
+
|
|
|
+#ifdef CONFIG_BLK_DEV_ZONED
|
|
|
+ unsigned int blocks_per_blkz; /* F2FS blocks per zone */
|
|
|
+ unsigned int log_blocks_per_blkz; /* log2 F2FS blocks per zone */
|
|
|
+#endif
|
|
|
+
|
|
|
/* for node-related operations */
|
|
|
struct f2fs_nm_info *nm_info; /* node manager */
|
|
|
struct inode *node_inode; /* cache node blocks */
|
|
@@ -764,6 +795,7 @@ struct f2fs_sb_info {
|
|
|
|
|
|
/* for checkpoint */
|
|
|
struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */
|
|
|
+ int cur_cp_pack; /* remain current cp pack */
|
|
|
spinlock_t cp_lock; /* for flag in ckpt */
|
|
|
struct inode *meta_inode; /* cache meta blocks */
|
|
|
struct mutex cp_mutex; /* checkpoint procedure lock */
|
|
@@ -815,10 +847,9 @@ struct f2fs_sb_info {
|
|
|
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_wb_bios; /* # of writeback bios */
|
|
|
|
|
|
/* # of pages, see count_type */
|
|
|
- struct percpu_counter nr_pages[NR_COUNT_TYPE];
|
|
|
+ atomic_t nr_pages[NR_COUNT_TYPE];
|
|
|
/* # of allocated blocks */
|
|
|
struct percpu_counter alloc_valid_block_count;
|
|
|
|
|
@@ -863,6 +894,8 @@ struct f2fs_sb_info {
|
|
|
|
|
|
/* For shrinker support */
|
|
|
struct list_head s_list;
|
|
|
+ int s_ndevs; /* number of devices */
|
|
|
+ struct f2fs_dev_info *devs; /* for device list */
|
|
|
struct mutex umount_mutex;
|
|
|
unsigned int shrinker_run_no;
|
|
|
|
|
@@ -1105,13 +1138,6 @@ static inline void clear_ckpt_flags(struct f2fs_sb_info *sbi, unsigned int f)
|
|
|
spin_unlock(&sbi->cp_lock);
|
|
|
}
|
|
|
|
|
|
-static inline bool f2fs_discard_en(struct f2fs_sb_info *sbi)
|
|
|
-{
|
|
|
- struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev);
|
|
|
-
|
|
|
- return blk_queue_discard(q);
|
|
|
-}
|
|
|
-
|
|
|
static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
|
|
|
{
|
|
|
down_read(&sbi->cp_rwsem);
|
|
@@ -1232,9 +1258,10 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
|
|
|
|
|
|
static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
|
|
|
{
|
|
|
- percpu_counter_inc(&sbi->nr_pages[count_type]);
|
|
|
+ atomic_inc(&sbi->nr_pages[count_type]);
|
|
|
|
|
|
- if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES)
|
|
|
+ if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES ||
|
|
|
+ count_type == F2FS_WB_CP_DATA || count_type == F2FS_WB_DATA)
|
|
|
return;
|
|
|
|
|
|
set_sbi_flag(sbi, SBI_IS_DIRTY);
|
|
@@ -1242,14 +1269,14 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
|
|
|
|
|
|
static inline void inode_inc_dirty_pages(struct inode *inode)
|
|
|
{
|
|
|
- percpu_counter_inc(&F2FS_I(inode)->dirty_pages);
|
|
|
+ atomic_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)
|
|
|
{
|
|
|
- percpu_counter_dec(&sbi->nr_pages[count_type]);
|
|
|
+ atomic_dec(&sbi->nr_pages[count_type]);
|
|
|
}
|
|
|
|
|
|
static inline void inode_dec_dirty_pages(struct inode *inode)
|
|
@@ -1258,19 +1285,19 @@ static inline void inode_dec_dirty_pages(struct inode *inode)
|
|
|
!S_ISLNK(inode->i_mode))
|
|
|
return;
|
|
|
|
|
|
- percpu_counter_dec(&F2FS_I(inode)->dirty_pages);
|
|
|
+ atomic_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 s64 get_pages(struct f2fs_sb_info *sbi, int count_type)
|
|
|
{
|
|
|
- return percpu_counter_sum_positive(&sbi->nr_pages[count_type]);
|
|
|
+ return atomic_read(&sbi->nr_pages[count_type]);
|
|
|
}
|
|
|
|
|
|
-static inline s64 get_dirty_pages(struct inode *inode)
|
|
|
+static inline int get_dirty_pages(struct inode *inode)
|
|
|
{
|
|
|
- return percpu_counter_sum_positive(&F2FS_I(inode)->dirty_pages);
|
|
|
+ return atomic_read(&F2FS_I(inode)->dirty_pages);
|
|
|
}
|
|
|
|
|
|
static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type)
|
|
@@ -1329,22 +1356,27 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
|
|
|
|
|
|
static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
|
|
|
{
|
|
|
- block_t start_addr;
|
|
|
- struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
|
|
|
- unsigned long long ckpt_version = cur_cp_version(ckpt);
|
|
|
-
|
|
|
- start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
|
|
|
+ block_t start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
|
|
|
|
|
|
- /*
|
|
|
- * odd numbered checkpoint should at cp segment 0
|
|
|
- * and even segment must be at cp segment 1
|
|
|
- */
|
|
|
- if (!(ckpt_version & 1))
|
|
|
+ if (sbi->cur_cp_pack == 2)
|
|
|
start_addr += sbi->blocks_per_seg;
|
|
|
+ return start_addr;
|
|
|
+}
|
|
|
+
|
|
|
+static inline block_t __start_cp_next_addr(struct f2fs_sb_info *sbi)
|
|
|
+{
|
|
|
+ block_t start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
|
|
|
|
|
|
+ if (sbi->cur_cp_pack == 1)
|
|
|
+ start_addr += sbi->blocks_per_seg;
|
|
|
return start_addr;
|
|
|
}
|
|
|
|
|
|
+static inline void __set_cp_next_pack(struct f2fs_sb_info *sbi)
|
|
|
+{
|
|
|
+ sbi->cur_cp_pack = (sbi->cur_cp_pack == 1) ? 2 : 1;
|
|
|
+}
|
|
|
+
|
|
|
static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
|
|
|
{
|
|
|
return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
|
|
@@ -1621,7 +1653,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
|
|
|
return;
|
|
|
case FI_DATA_EXIST:
|
|
|
case FI_INLINE_DOTS:
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1648,7 +1680,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);
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, false);
|
|
|
}
|
|
|
|
|
|
static inline void f2fs_i_links_write(struct inode *inode, bool inc)
|
|
@@ -1657,7 +1689,7 @@ static inline void f2fs_i_links_write(struct inode *inode, bool inc)
|
|
|
inc_nlink(inode);
|
|
|
else
|
|
|
drop_nlink(inode);
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
}
|
|
|
|
|
|
static inline void f2fs_i_blocks_write(struct inode *inode,
|
|
@@ -1668,7 +1700,7 @@ static inline void f2fs_i_blocks_write(struct inode *inode,
|
|
|
|
|
|
inode->i_blocks = add ? inode->i_blocks + diff :
|
|
|
inode->i_blocks - diff;
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
if (clean || recover)
|
|
|
set_inode_flag(inode, FI_AUTO_RECOVER);
|
|
|
}
|
|
@@ -1682,34 +1714,27 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
|
|
|
return;
|
|
|
|
|
|
i_size_write(inode, i_size);
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
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;
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
}
|
|
|
|
|
|
static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid)
|
|
|
{
|
|
|
F2FS_I(inode)->i_xattr_nid = xnid;
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
}
|
|
|
|
|
|
static inline void f2fs_i_pino_write(struct inode *inode, nid_t pino)
|
|
|
{
|
|
|
F2FS_I(inode)->i_pino = pino;
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
}
|
|
|
|
|
|
static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri)
|
|
@@ -1837,13 +1862,31 @@ 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);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
}
|
|
|
|
|
|
static inline void clear_file(struct inode *inode, int type)
|
|
|
{
|
|
|
F2FS_I(inode)->i_advise &= ~type;
|
|
|
- f2fs_mark_inode_dirty_sync(inode);
|
|
|
+ f2fs_mark_inode_dirty_sync(inode, true);
|
|
|
+}
|
|
|
+
|
|
|
+static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
|
|
|
+{
|
|
|
+ if (dsync) {
|
|
|
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
|
|
+ bool ret;
|
|
|
+
|
|
|
+ spin_lock(&sbi->inode_lock[DIRTY_META]);
|
|
|
+ ret = list_empty(&F2FS_I(inode)->gdirty_list);
|
|
|
+ spin_unlock(&sbi->inode_lock[DIRTY_META]);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ if (!is_inode_flag_set(inode, FI_AUTO_RECOVER) ||
|
|
|
+ file_keep_isize(inode) ||
|
|
|
+ i_size_read(inode) & PAGE_MASK)
|
|
|
+ return false;
|
|
|
+ return F2FS_I(inode)->last_disk_size == i_size_read(inode);
|
|
|
}
|
|
|
|
|
|
static inline int f2fs_readonly(struct super_block *sb)
|
|
@@ -1955,7 +1998,7 @@ 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 *,
|
|
|
+int f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *,
|
|
|
unsigned int, struct fscrypt_str *);
|
|
|
void do_make_empty_dir(struct inode *, struct inode *,
|
|
|
struct f2fs_dentry_ptr *);
|
|
@@ -1995,7 +2038,7 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
|
|
|
/*
|
|
|
* super.c
|
|
|
*/
|
|
|
-int f2fs_inode_dirtied(struct inode *);
|
|
|
+int f2fs_inode_dirtied(struct inode *, bool);
|
|
|
void f2fs_inode_synced(struct inode *);
|
|
|
int f2fs_commit_super(struct f2fs_sb_info *, bool);
|
|
|
int f2fs_sync_fs(struct super_block *, int);
|
|
@@ -2034,7 +2077,7 @@ 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 *);
|
|
|
+void build_free_nids(struct f2fs_sb_info *, bool);
|
|
|
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);
|
|
@@ -2060,7 +2103,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *, bool);
|
|
|
void f2fs_balance_fs_bg(struct f2fs_sb_info *);
|
|
|
int f2fs_issue_flush(struct f2fs_sb_info *);
|
|
|
int create_flush_cmd_control(struct f2fs_sb_info *);
|
|
|
-void destroy_flush_cmd_control(struct f2fs_sb_info *);
|
|
|
+void destroy_flush_cmd_control(struct f2fs_sb_info *, bool);
|
|
|
void invalidate_blocks(struct f2fs_sb_info *, block_t);
|
|
|
bool is_checkpointed_data(struct f2fs_sb_info *, block_t);
|
|
|
void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t);
|
|
@@ -2132,12 +2175,15 @@ void f2fs_submit_merged_bio_cond(struct f2fs_sb_info *, struct inode *,
|
|
|
void f2fs_flush_merged_bios(struct f2fs_sb_info *);
|
|
|
int f2fs_submit_page_bio(struct f2fs_io_info *);
|
|
|
void f2fs_submit_page_mbio(struct f2fs_io_info *);
|
|
|
+struct block_device *f2fs_target_device(struct f2fs_sb_info *,
|
|
|
+ block_t, struct bio *);
|
|
|
+int f2fs_target_device_index(struct f2fs_sb_info *, block_t);
|
|
|
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 *);
|
|
|
+int f2fs_preallocate_blocks(struct kiocb *, struct iov_iter *);
|
|
|
int f2fs_reserve_block(struct dnode_of_data *, pgoff_t);
|
|
|
struct page *get_read_data_page(struct inode *, pgoff_t, int, bool);
|
|
|
struct page *find_data_page(struct inode *, pgoff_t);
|
|
@@ -2160,7 +2206,7 @@ int f2fs_migrate_page(struct address_space *, struct page *, struct page *,
|
|
|
int start_gc_thread(struct f2fs_sb_info *);
|
|
|
void stop_gc_thread(struct f2fs_sb_info *);
|
|
|
block_t start_bidx_of_node(unsigned int, struct inode *);
|
|
|
-int f2fs_gc(struct f2fs_sb_info *, bool);
|
|
|
+int f2fs_gc(struct f2fs_sb_info *, bool, bool);
|
|
|
void build_gc_manager(struct f2fs_sb_info *);
|
|
|
|
|
|
/*
|
|
@@ -2181,12 +2227,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;
|
|
|
- s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, ndirty_imeta;
|
|
|
- s64 inmem_pages;
|
|
|
+ int ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, ndirty_imeta;
|
|
|
+ int inmem_pages;
|
|
|
unsigned int ndirty_dirs, ndirty_files, ndirty_all;
|
|
|
- int nats, dirty_nats, sits, dirty_sits, fnids;
|
|
|
+ int nats, dirty_nats, sits, dirty_sits, free_nids, alloc_nids;
|
|
|
int total_count, utilization;
|
|
|
- int bg_gc, wb_bios;
|
|
|
+ int bg_gc, nr_wb_cp_data, nr_wb_data;
|
|
|
int inline_xattr, inline_inode, inline_dir, orphans;
|
|
|
unsigned int valid_count, valid_node_count, valid_inode_count, discard_blks;
|
|
|
unsigned int bimodal, avg_vblocks;
|
|
@@ -2412,9 +2458,30 @@ 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)
|
|
|
+static inline int f2fs_sb_mounted_blkzoned(struct super_block *sb)
|
|
|
+{
|
|
|
+ return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_BLKZONED);
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_BLK_DEV_ZONED
|
|
|
+static inline int get_blkz_type(struct f2fs_sb_info *sbi,
|
|
|
+ struct block_device *bdev, block_t blkaddr)
|
|
|
+{
|
|
|
+ unsigned int zno = blkaddr >> sbi->log_blocks_per_blkz;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < sbi->s_ndevs; i++)
|
|
|
+ if (FDEV(i).bdev == bdev)
|
|
|
+ return FDEV(i).blkz_type[zno];
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static inline bool f2fs_discard_en(struct f2fs_sb_info *sbi)
|
|
|
{
|
|
|
- return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_HMSMR);
|
|
|
+ struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev);
|
|
|
+
|
|
|
+ return blk_queue_discard(q) || f2fs_sb_mounted_blkzoned(sbi->sb);
|
|
|
}
|
|
|
|
|
|
static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)
|