|
@@ -45,6 +45,7 @@ enum {
|
|
FAULT_ORPHAN,
|
|
FAULT_ORPHAN,
|
|
FAULT_BLOCK,
|
|
FAULT_BLOCK,
|
|
FAULT_DIR_DEPTH,
|
|
FAULT_DIR_DEPTH,
|
|
|
|
+ FAULT_EVICT_INODE,
|
|
FAULT_MAX,
|
|
FAULT_MAX,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -74,6 +75,8 @@ static inline bool time_to_inject(int type)
|
|
return false;
|
|
return false;
|
|
else if (type == FAULT_DIR_DEPTH && !IS_FAULT_SET(type))
|
|
else if (type == FAULT_DIR_DEPTH && !IS_FAULT_SET(type))
|
|
return false;
|
|
return false;
|
|
|
|
+ else if (type == FAULT_EVICT_INODE && !IS_FAULT_SET(type))
|
|
|
|
+ return false;
|
|
|
|
|
|
atomic_inc(&f2fs_fault.inject_ops);
|
|
atomic_inc(&f2fs_fault.inject_ops);
|
|
if (atomic_read(&f2fs_fault.inject_ops) >= f2fs_fault.inject_rate) {
|
|
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_FORCE_FG_GC 0x00004000
|
|
#define F2FS_MOUNT_DATA_FLUSH 0x00008000
|
|
#define F2FS_MOUNT_DATA_FLUSH 0x00008000
|
|
#define F2FS_MOUNT_FAULT_INJECTION 0x00010000
|
|
#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 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)
|
|
@@ -128,6 +133,7 @@ struct f2fs_mount_info {
|
|
};
|
|
};
|
|
|
|
|
|
#define F2FS_FEATURE_ENCRYPT 0x0001
|
|
#define F2FS_FEATURE_ENCRYPT 0x0001
|
|
|
|
+#define F2FS_FEATURE_HMSMR 0x0002
|
|
|
|
|
|
#define F2FS_HAS_FEATURE(sb, mask) \
|
|
#define F2FS_HAS_FEATURE(sb, mask) \
|
|
((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
|
|
((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
|
|
@@ -158,7 +164,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 */
|
|
|
|
|
|
+#define DEF_IDLE_INTERVAL 5 /* 5 secs */
|
|
|
|
|
|
struct cp_control {
|
|
struct cp_control {
|
|
int reason;
|
|
int reason;
|
|
@@ -262,6 +268,8 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,
|
|
#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_DEFRAGMENT _IO(F2FS_IOCTL_MAGIC, 8)
|
|
|
|
+#define F2FS_IOC_MOVE_RANGE _IOWR(F2FS_IOCTL_MAGIC, 9, \
|
|
|
|
+ struct f2fs_move_range)
|
|
|
|
|
|
#define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY
|
|
#define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY
|
|
#define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY
|
|
#define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY
|
|
@@ -291,6 +299,13 @@ struct f2fs_defragment {
|
|
u64 len;
|
|
u64 len;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+struct f2fs_move_range {
|
|
|
|
+ u32 dst_fd; /* destination fd */
|
|
|
|
+ u64 pos_in; /* start position in src_fd */
|
|
|
|
+ u64 pos_out; /* start position in dst_fd */
|
|
|
|
+ u64 len; /* size to move */
|
|
|
|
+};
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* For INODE and NODE manager
|
|
* For INODE and NODE manager
|
|
*/
|
|
*/
|
|
@@ -441,11 +456,14 @@ 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 */
|
|
|
|
+ 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 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 */
|
|
struct extent_tree *extent_tree; /* cached extent_tree entry */
|
|
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,
|
|
static inline void get_extent_info(struct extent_info *ext,
|
|
@@ -498,11 +516,14 @@ static inline bool __is_front_mergeable(struct extent_info *cur,
|
|
return __is_extent_mergeable(cur, front);
|
|
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;
|
|
et->largest = en->ei;
|
|
|
|
+ f2fs_mark_inode_dirty_sync(inode);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
struct f2fs_nm_info {
|
|
struct f2fs_nm_info {
|
|
@@ -517,7 +538,7 @@ struct f2fs_nm_info {
|
|
/* NAT cache management */
|
|
/* NAT cache management */
|
|
struct radix_tree_root nat_root;/* root of the nat entry cache */
|
|
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 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) */
|
|
struct list_head nat_entries; /* cached nat entry list (clean) */
|
|
unsigned int nat_cnt; /* the # of cached nat entries */
|
|
unsigned int nat_cnt; /* the # of cached nat entries */
|
|
unsigned int dirty_nat_cnt; /* total num of nat entries in set */
|
|
unsigned int dirty_nat_cnt; /* total num of nat entries in set */
|
|
@@ -599,6 +620,7 @@ struct flush_cmd {
|
|
struct flush_cmd_control {
|
|
struct flush_cmd_control {
|
|
struct task_struct *f2fs_issue_flush; /* flush thread */
|
|
struct task_struct *f2fs_issue_flush; /* flush thread */
|
|
wait_queue_head_t flush_wait_queue; /* waiting queue for wake-up */
|
|
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_head issue_list; /* list for command issue */
|
|
struct llist_node *dispatch_list; /* list for command dispatch */
|
|
struct llist_node *dispatch_list; /* list for command dispatch */
|
|
};
|
|
};
|
|
@@ -655,6 +677,7 @@ enum count_type {
|
|
F2FS_DIRTY_NODES,
|
|
F2FS_DIRTY_NODES,
|
|
F2FS_DIRTY_META,
|
|
F2FS_DIRTY_META,
|
|
F2FS_INMEM_PAGES,
|
|
F2FS_INMEM_PAGES,
|
|
|
|
+ F2FS_DIRTY_IMETA,
|
|
NR_COUNT_TYPE,
|
|
NR_COUNT_TYPE,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -706,6 +729,7 @@ struct f2fs_bio_info {
|
|
enum inode_type {
|
|
enum inode_type {
|
|
DIR_INODE, /* for dirty dir inode */
|
|
DIR_INODE, /* for dirty dir inode */
|
|
FILE_INODE, /* for dirty regular/symlink inode */
|
|
FILE_INODE, /* for dirty regular/symlink inode */
|
|
|
|
+ DIRTY_META, /* for all dirtied inode metadata */
|
|
NR_INODE_TYPE,
|
|
NR_INODE_TYPE,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -757,14 +781,14 @@ struct f2fs_sb_info {
|
|
/* for bio operations */
|
|
/* for bio operations */
|
|
struct f2fs_bio_info read_io; /* for read bios */
|
|
struct f2fs_bio_info read_io; /* for read bios */
|
|
struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write 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 */
|
|
/* for checkpoint */
|
|
struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */
|
|
struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */
|
|
struct inode *meta_inode; /* cache meta blocks */
|
|
struct inode *meta_inode; /* cache meta blocks */
|
|
struct mutex cp_mutex; /* checkpoint procedure lock */
|
|
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 rw_semaphore node_write; /* locking node writes */
|
|
- struct mutex writepages; /* mutex for writepages() */
|
|
|
|
wait_queue_head_t cp_wait;
|
|
wait_queue_head_t cp_wait;
|
|
unsigned long last_time[MAX_TIME]; /* to store time in jiffies */
|
|
unsigned long last_time[MAX_TIME]; /* to store time in jiffies */
|
|
long interval_time[MAX_TIME]; /* to store thresholds */
|
|
long interval_time[MAX_TIME]; /* to store thresholds */
|
|
@@ -1050,22 +1074,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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
static inline int __get_cp_reason(struct f2fs_sb_info *sbi)
|
|
@@ -1120,34 +1144,37 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)
|
|
return ofs == XATTR_NODE_OFFSET;
|
|
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,
|
|
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;
|
|
|
|
|
|
+ blkcnt_t diff;
|
|
|
|
|
|
- spin_lock(&sbi->stat_lock);
|
|
|
|
#ifdef CONFIG_F2FS_FAULT_INJECTION
|
|
#ifdef CONFIG_F2FS_FAULT_INJECTION
|
|
- if (time_to_inject(FAULT_BLOCK)) {
|
|
|
|
- spin_unlock(&sbi->stat_lock);
|
|
|
|
|
|
+ if (time_to_inject(FAULT_BLOCK))
|
|
return false;
|
|
return false;
|
|
- }
|
|
|
|
#endif
|
|
#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;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * let's increase this in prior to actual block count change in order
|
|
|
|
+ * for f2fs_sync_file to avoid data races when deciding checkpoint.
|
|
|
|
+ */
|
|
|
|
+ percpu_counter_add(&sbi->alloc_valid_block_count, (*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)) {
|
|
|
|
+ diff = sbi->total_valid_block_count - sbi->user_block_count;
|
|
|
|
+ *count -= diff;
|
|
|
|
+ sbi->total_valid_block_count = sbi->user_block_count;
|
|
if (!*count) {
|
|
if (!*count) {
|
|
spin_unlock(&sbi->stat_lock);
|
|
spin_unlock(&sbi->stat_lock);
|
|
|
|
+ percpu_counter_sub(&sbi->alloc_valid_block_count, diff);
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- /* *count can be recalculated */
|
|
|
|
- inode->i_blocks += *count;
|
|
|
|
- sbi->total_valid_block_count =
|
|
|
|
- sbi->total_valid_block_count + (block_t)(*count);
|
|
|
|
spin_unlock(&sbi->stat_lock);
|
|
spin_unlock(&sbi->stat_lock);
|
|
|
|
|
|
- percpu_counter_add(&sbi->alloc_valid_block_count, (*count));
|
|
|
|
|
|
+ f2fs_i_blocks_write(inode, *count, true);
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1158,9 +1185,9 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
|
|
spin_lock(&sbi->stat_lock);
|
|
spin_lock(&sbi->stat_lock);
|
|
f2fs_bug_on(sbi, sbi->total_valid_block_count < (block_t) count);
|
|
f2fs_bug_on(sbi, sbi->total_valid_block_count < (block_t) count);
|
|
f2fs_bug_on(sbi, inode->i_blocks < count);
|
|
f2fs_bug_on(sbi, inode->i_blocks < count);
|
|
- inode->i_blocks -= count;
|
|
|
|
sbi->total_valid_block_count -= (block_t)count;
|
|
sbi->total_valid_block_count -= (block_t)count;
|
|
spin_unlock(&sbi->stat_lock);
|
|
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)
|
|
static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
|
|
@@ -1295,7 +1322,7 @@ static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
|
|
}
|
|
}
|
|
|
|
|
|
if (inode)
|
|
if (inode)
|
|
- inode->i_blocks++;
|
|
|
|
|
|
+ f2fs_i_blocks_write(inode, 1, true);
|
|
|
|
|
|
sbi->total_valid_node_count++;
|
|
sbi->total_valid_node_count++;
|
|
sbi->total_valid_block_count++;
|
|
sbi->total_valid_block_count++;
|
|
@@ -1314,7 +1341,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, !sbi->total_valid_node_count);
|
|
f2fs_bug_on(sbi, !inode->i_blocks);
|
|
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_node_count--;
|
|
sbi->total_valid_block_count--;
|
|
sbi->total_valid_block_count--;
|
|
|
|
|
|
@@ -1511,12 +1538,12 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr)
|
|
enum {
|
|
enum {
|
|
FI_NEW_INODE, /* indicate newly allocated inode */
|
|
FI_NEW_INODE, /* indicate newly allocated inode */
|
|
FI_DIRTY_INODE, /* indicate inode is dirty or not */
|
|
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_DIRTY_DIR, /* indicate directory has dirty pages */
|
|
FI_INC_LINK, /* need to increment i_nlink */
|
|
FI_INC_LINK, /* need to increment i_nlink */
|
|
FI_ACL_MODE, /* indicate acl mode */
|
|
FI_ACL_MODE, /* indicate acl mode */
|
|
FI_NO_ALLOC, /* should not allocate any blocks */
|
|
FI_NO_ALLOC, /* should not allocate any blocks */
|
|
FI_FREE_NID, /* free allocated nide */
|
|
FI_FREE_NID, /* free allocated nide */
|
|
- FI_UPDATE_DIR, /* should update inode block for consistency */
|
|
|
|
FI_NO_EXTENT, /* not to use the extent cache */
|
|
FI_NO_EXTENT, /* not to use the extent cache */
|
|
FI_INLINE_XATTR, /* used for inline xattr */
|
|
FI_INLINE_XATTR, /* used for inline xattr */
|
|
FI_INLINE_DATA, /* used for inline data*/
|
|
FI_INLINE_DATA, /* used for inline data*/
|
|
@@ -1534,64 +1561,143 @@ enum {
|
|
FI_DIRTY_FILE, /* indicate regular/symlink has dirty pages */
|
|
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)
|
|
{
|
|
{
|
|
- if (!test_bit(flag, &fi->flags))
|
|
|
|
- set_bit(flag, &fi->flags);
|
|
|
|
|
|
+ F2FS_I(inode)->i_acl_mode = mode;
|
|
|
|
+ set_inode_flag(inode, FI_ACL_MODE);
|
|
|
|
+ f2fs_mark_inode_dirty_sync(inode);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag)
|
|
|
|
|
|
+static inline void f2fs_i_links_write(struct inode *inode, bool inc)
|
|
{
|
|
{
|
|
- return test_bit(flag, &fi->flags);
|
|
|
|
|
|
+ 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 void clear_inode_flag(struct f2fs_inode_info *fi, int flag)
|
|
|
|
|
|
+static inline bool f2fs_skip_inode_update(struct inode *inode)
|
|
{
|
|
{
|
|
- if (test_bit(flag, &fi->flags))
|
|
|
|
- clear_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 void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode)
|
|
|
|
|
|
+static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth)
|
|
{
|
|
{
|
|
- fi->i_acl_mode = mode;
|
|
|
|
- set_inode_flag(fi, FI_ACL_MODE);
|
|
|
|
|
|
+ F2FS_I(inode)->i_current_depth = depth;
|
|
|
|
+ f2fs_mark_inode_dirty_sync(inode);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void get_inline_info(struct f2fs_inode_info *fi,
|
|
|
|
- struct f2fs_inode *ri)
|
|
|
|
|
|
+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);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
ri->i_inline |= F2FS_INLINE_DOTS;
|
|
}
|
|
}
|
|
|
|
|
|
static inline int f2fs_has_inline_xattr(struct inode *inode)
|
|
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)
|
|
static inline unsigned int addrs_per_inode(struct inode *inode)
|
|
@@ -1618,43 +1724,43 @@ static inline int inline_xattr_size(struct inode *inode)
|
|
|
|
|
|
static inline int f2fs_has_inline_data(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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
static inline void *inline_data_addr(struct page *page)
|
|
@@ -1665,7 +1771,7 @@ static inline void *inline_data_addr(struct page *page)
|
|
|
|
|
|
static inline int f2fs_has_inline_dentry(struct inode *inode)
|
|
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)
|
|
static inline void f2fs_dentry_kunmap(struct inode *dir, struct page *page)
|
|
@@ -1682,11 +1788,13 @@ static inline int is_file(struct inode *inode, int type)
|
|
static inline void set_file(struct inode *inode, int type)
|
|
static inline void set_file(struct inode *inode, int type)
|
|
{
|
|
{
|
|
F2FS_I(inode)->i_advise |= type;
|
|
F2FS_I(inode)->i_advise |= type;
|
|
|
|
+ f2fs_mark_inode_dirty_sync(inode);
|
|
}
|
|
}
|
|
|
|
|
|
static inline void clear_file(struct inode *inode, int type)
|
|
static inline void clear_file(struct inode *inode, int type)
|
|
{
|
|
{
|
|
F2FS_I(inode)->i_advise &= ~type;
|
|
F2FS_I(inode)->i_advise &= ~type;
|
|
|
|
+ f2fs_mark_inode_dirty_sync(inode);
|
|
}
|
|
}
|
|
|
|
|
|
static inline int f2fs_readonly(struct super_block *sb)
|
|
static inline int f2fs_readonly(struct super_block *sb)
|
|
@@ -1713,7 +1821,7 @@ static inline bool is_dot_dotdot(const struct qstr *str)
|
|
static inline bool f2fs_may_extent_tree(struct inode *inode)
|
|
static inline bool f2fs_may_extent_tree(struct inode *inode)
|
|
{
|
|
{
|
|
if (!test_opt(F2FS_I_SB(inode), EXTENT_CACHE) ||
|
|
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 false;
|
|
|
|
|
|
return S_ISREG(inode->i_mode);
|
|
return S_ISREG(inode->i_mode);
|
|
@@ -1749,7 +1857,7 @@ static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)
|
|
}
|
|
}
|
|
|
|
|
|
#define get_inode_mode(i) \
|
|
#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))
|
|
(F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
|
|
|
|
|
|
/* get offset of first page in next direct node */
|
|
/* get offset of first page in next direct node */
|
|
@@ -1764,7 +1872,7 @@ static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)
|
|
int f2fs_sync_file(struct file *, loff_t, loff_t, int);
|
|
int f2fs_sync_file(struct file *, loff_t, loff_t, int);
|
|
void truncate_data_blocks(struct dnode_of_data *);
|
|
void truncate_data_blocks(struct dnode_of_data *);
|
|
int truncate_blocks(struct inode *, u64, bool);
|
|
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_getattr(struct vfsmount *, struct dentry *, struct kstat *);
|
|
int f2fs_setattr(struct dentry *, struct iattr *);
|
|
int f2fs_setattr(struct dentry *, struct iattr *);
|
|
int truncate_hole(struct inode *, pgoff_t, pgoff_t);
|
|
int truncate_hole(struct inode *, pgoff_t, pgoff_t);
|
|
@@ -1805,11 +1913,11 @@ struct page *init_inode_metadata(struct inode *, struct inode *,
|
|
const struct qstr *, struct page *);
|
|
const struct qstr *, struct page *);
|
|
void update_parent_metadata(struct inode *, struct inode *, unsigned int);
|
|
void update_parent_metadata(struct inode *, struct inode *, unsigned int);
|
|
int room_for_filename(const void *, int, 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 f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
|
|
struct page **);
|
|
struct page **);
|
|
struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
|
|
struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
|
|
-ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
|
|
|
|
|
|
+ino_t f2fs_inode_by_name(struct inode *, struct qstr *, struct page **);
|
|
void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
|
|
void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
|
|
struct page *, struct inode *);
|
|
struct page *, struct inode *);
|
|
int update_dent_inode(struct inode *, struct inode *, const struct qstr *);
|
|
int update_dent_inode(struct inode *, struct inode *, const struct qstr *);
|
|
@@ -1833,6 +1941,8 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
|
|
/*
|
|
/*
|
|
* super.c
|
|
* 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_commit_super(struct f2fs_sb_info *, bool);
|
|
int f2fs_sync_fs(struct super_block *, int);
|
|
int f2fs_sync_fs(struct super_block *, int);
|
|
extern __printf(3, 4)
|
|
extern __printf(3, 4)
|
|
@@ -1866,11 +1976,11 @@ struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *);
|
|
void ra_node_page(struct f2fs_sb_info *, nid_t);
|
|
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(struct f2fs_sb_info *, pgoff_t);
|
|
struct page *get_node_page_ra(struct page *, int);
|
|
struct page *get_node_page_ra(struct page *, int);
|
|
-void sync_inode_page(struct dnode_of_data *);
|
|
|
|
void move_node_page(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 *);
|
|
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 *);
|
|
bool alloc_nid(struct f2fs_sb_info *, nid_t *);
|
|
void alloc_nid_done(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);
|
|
void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
|
|
@@ -1944,9 +2054,10 @@ 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 remove_ino_entry(struct f2fs_sb_info *, nid_t, int type);
|
|
void release_ino_entry(struct f2fs_sb_info *, bool);
|
|
void release_ino_entry(struct f2fs_sb_info *, bool);
|
|
bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
|
|
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 *);
|
|
int acquire_orphan_inode(struct f2fs_sb_info *);
|
|
void release_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);
|
|
void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
|
|
int recover_orphan_inodes(struct f2fs_sb_info *);
|
|
int recover_orphan_inodes(struct f2fs_sb_info *);
|
|
int get_valid_checkpoint(struct f2fs_sb_info *);
|
|
int get_valid_checkpoint(struct f2fs_sb_info *);
|
|
@@ -1981,6 +2092,7 @@ 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_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_set_page_dirty_nobuffers(struct page *);
|
|
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);
|
|
|
|
|
|
@@ -2012,7 +2124,7 @@ struct f2fs_stat_info {
|
|
unsigned long long hit_total, total_ext;
|
|
unsigned long long hit_total, total_ext;
|
|
int ext_tree, zombie_tree, ext_node;
|
|
int ext_tree, zombie_tree, ext_node;
|
|
s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, inmem_pages;
|
|
s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, inmem_pages;
|
|
- unsigned int ndirty_dirs, ndirty_files;
|
|
|
|
|
|
+ unsigned int ndirty_dirs, ndirty_files, ndirty_all;
|
|
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, wb_bios;
|
|
int bg_gc, wb_bios;
|
|
@@ -2181,7 +2293,6 @@ int f2fs_write_inline_data(struct inode *, struct page *);
|
|
bool recover_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 f2fs_dir_entry *find_in_inline_dir(struct inode *,
|
|
struct fscrypt_name *, struct page **);
|
|
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 make_empty_inline_dir(struct inode *inode, struct inode *, struct page *);
|
|
int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,
|
|
int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,
|
|
nid_t, umode_t);
|
|
nid_t, umode_t);
|
|
@@ -2206,6 +2317,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *);
|
|
*/
|
|
*/
|
|
unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
|
|
unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
|
|
bool f2fs_init_extent_tree(struct inode *, struct f2fs_extent *);
|
|
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 *);
|
|
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 *);
|
|
@@ -2241,6 +2353,26 @@ static inline int f2fs_sb_has_crypto(struct super_block *sb)
|
|
return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_ENCRYPT);
|
|
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)
|
|
static inline bool f2fs_may_encrypt(struct inode *inode)
|
|
{
|
|
{
|
|
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|
|
#ifdef CONFIG_F2FS_FS_ENCRYPTION
|