cregit-Linux how code gets into the kernel

Release 4.10 fs/f2fs/f2fs.h

Directory: fs/f2fs
/*
 * fs/f2fs/f2fs.h
 *
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *             http://www.samsung.com/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#ifndef _LINUX_F2FS_H

#define _LINUX_F2FS_H

#include <linux/types.h>
#include <linux/page-flags.h>
#include <linux/buffer_head.h>
#include <linux/slab.h>
#include <linux/crc32.h>
#include <linux/magic.h>
#include <linux/kobject.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/fscrypto.h>
#include <crypto/hash.h>

#ifdef CONFIG_F2FS_CHECK_FS

#define f2fs_bug_on(sbi, condition)	BUG_ON(condition)
#else

#define f2fs_bug_on(sbi, condition)					\
	do {                                                            \
                if (unlikely(condition)) {                              \
                        WARN_ON(1);                                     \
                        set_sbi_flag(sbi, SBI_NEED_FSCK);               \
                }                                                       \
        } while (0)
#endif

#ifdef CONFIG_F2FS_FAULT_INJECTION
enum {
	
FAULT_KMALLOC,
	
FAULT_PAGE_ALLOC,
	
FAULT_ALLOC_NID,
	
FAULT_ORPHAN,
	
FAULT_BLOCK,
	
FAULT_DIR_DEPTH,
	
FAULT_EVICT_INODE,
	
FAULT_IO,
	
FAULT_CHECKPOINT,
	
FAULT_MAX,
};


struct f2fs_fault_info {
	
atomic_t inject_ops;
	
unsigned int inject_rate;
	
unsigned int inject_type;
};

extern char *fault_name[FAULT_MAX];

#define IS_FAULT_SET(fi, type) (fi->inject_type & (1 << (type)))
#endif

/*
 * For mount options
 */

#define F2FS_MOUNT_BG_GC		0x00000001

#define F2FS_MOUNT_DISABLE_ROLL_FORWARD	0x00000002

#define F2FS_MOUNT_DISCARD		0x00000004

#define F2FS_MOUNT_NOHEAP		0x00000008

#define F2FS_MOUNT_XATTR_USER		0x00000010

#define F2FS_MOUNT_POSIX_ACL		0x00000020

#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY	0x00000040

#define F2FS_MOUNT_INLINE_XATTR		0x00000080

#define F2FS_MOUNT_INLINE_DATA		0x00000100

#define F2FS_MOUNT_INLINE_DENTRY	0x00000200

#define F2FS_MOUNT_FLUSH_MERGE		0x00000400

#define F2FS_MOUNT_NOBARRIER		0x00000800

#define F2FS_MOUNT_FASTBOOT		0x00001000

#define F2FS_MOUNT_EXTENT_CACHE		0x00002000

#define F2FS_MOUNT_FORCE_FG_GC		0x00004000

#define F2FS_MOUNT_DATA_FLUSH		0x00008000

#define F2FS_MOUNT_FAULT_INJECTION	0x00010000

#define F2FS_MOUNT_ADAPTIVE		0x00020000

#define F2FS_MOUNT_LFS			0x00040000


#define clear_opt(sbi, option)	(sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)

#define set_opt(sbi, option)	(sbi->mount_opt.opt |= F2FS_MOUNT_##option)

#define test_opt(sbi, option)	(sbi->mount_opt.opt & F2FS_MOUNT_##option)


#define ver_after(a, b)	(typecheck(unsigned long long, a) &&            \
                typecheck(unsigned long long, b) &&                     \
                ((long long)((a) - (b)) > 0))


typedef u32 block_t;	
/*
                         * should not change u32, since it is the on-disk block
                         * address format, __le32.
                         */

typedef u32 nid_t;


struct f2fs_mount_info {
	
unsigned int	opt;
};


#define F2FS_FEATURE_ENCRYPT	0x0001

#define F2FS_FEATURE_BLKZONED	0x0002


#define F2FS_HAS_FEATURE(sb, mask)					\
	((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)

#define F2FS_SET_FEATURE(sb, mask)					\
	F2FS_SB(sb)->raw_super->feature |= cpu_to_le32(mask)

#define F2FS_CLEAR_FEATURE(sb, mask)					\
	F2FS_SB(sb)->raw_super->feature &= ~cpu_to_le32(mask)

/*
 * For checkpoint manager
 */
enum {
	
NAT_BITMAP,
	
SIT_BITMAP
};

enum {
	
CP_UMOUNT,
	
CP_FASTBOOT,
	
CP_SYNC,
	
CP_RECOVERY,
	
CP_DISCARD,
};


#define DEF_BATCHED_TRIM_SECTIONS	2

#define BATCHED_TRIM_SEGMENTS(sbi)	\
		(SM_I(sbi)->trim_sections * (sbi)->segs_per_sec)

#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		5	
/* 5 secs */


struct cp_control {
	
int reason;
	
__u64 trim_start;
	
__u64 trim_end;
	
__u64 trim_minlen;
	
__u64 trimmed;
};

/*
 * For CP/NAT/SIT/SSA readahead
 */
enum {
	
META_CP,
	
META_NAT,
	
META_SIT,
	
META_SSA,
	
META_POR,
};

/* for the list of ino */
enum {
	
ORPHAN_INO,		/* for orphan ino list */
	
APPEND_INO,		/* for append ino list */
	
UPDATE_INO,		/* for update ino list */
	
MAX_INO_ENTRY,		/* max. list */
};


struct ino_entry {
	
struct list_head list;	/* list head */
	
nid_t ino;		/* inode number */
};

/* for the list of inodes to be GCed */

struct inode_entry {
	
struct list_head list;	/* list head */
	
struct inode *inode;	/* vfs inode pointer */
};

/* for the list of blockaddresses to be discarded */

struct discard_entry {
	
struct list_head list;	/* list head */
	
block_t blkaddr;	/* block address to be discarded */
	
int len;		/* # of consecutive blocks of the discard */
};


struct bio_entry {
	
struct list_head list;
	
struct bio *bio;
	
struct completion event;
	
int error;
};

/* for the list of fsync inodes, used only during recovery */

struct fsync_inode_entry {
	
struct list_head list;	/* list head */
	
struct inode *inode;	/* vfs inode pointer */
	
block_t blkaddr;	/* block address locating the last fsync */
	
block_t last_dentry;	/* block address locating the last dentry */
};


#define nats_in_cursum(jnl)		(le16_to_cpu(jnl->n_nats))

#define sits_in_cursum(jnl)		(le16_to_cpu(jnl->n_sits))


#define nat_in_journal(jnl, i)		(jnl->nat_j.entries[i].ne)

#define nid_in_journal(jnl, i)		(jnl->nat_j.entries[i].nid)

#define sit_in_journal(jnl, i)		(jnl->sit_j.entries[i].se)

#define segno_in_journal(jnl, i)	(jnl->sit_j.entries[i].segno)


#define MAX_NAT_JENTRIES(jnl)	(NAT_JOURNAL_ENTRIES - nats_in_cursum(jnl))

#define MAX_SIT_JENTRIES(jnl)	(SIT_JOURNAL_ENTRIES - sits_in_cursum(jnl))


static inline int update_nats_in_cursum(struct f2fs_journal *journal, int i) { int before = nats_in_cursum(journal); journal->n_nats = cpu_to_le16(before + i); return before; }

Contributors

PersonTokensPropCommitsCommitProp
jaegeuk kimjaegeuk kim3389.19%150.00%
chao yuchao yu410.81%150.00%
Total37100.00%2100.00%


static inline int update_sits_in_cursum(struct f2fs_journal *journal, int i) { int before = sits_in_cursum(journal); journal->n_sits = cpu_to_le16(before + i); return before; }

Contributors

PersonTokensPropCommitsCommitProp
jaegeuk kimjaegeuk kim3389.19%150.00%
chao yuchao yu410.81%150.00%
Total37100.00%2100.00%


static inline bool __has_cursum_space(struct f2fs_journal *journal, int size, int type) { if (type == NAT_JOURNAL) return size <= MAX_NAT_JENTRIES(journal); return size <= MAX_SIT_JENTRIES(journal); }

Contributors

PersonTokensPropCommitsCommitProp
chao yuchao yu3485.00%266.67%
jaegeuk kimjaegeuk kim615.00%133.33%
Total40100.00%3100.00%

/* * ioctl commands */ #define F2FS_IOC_GETFLAGS FS_IOC_GETFLAGS #define F2FS_IOC_SETFLAGS FS_IOC_SETFLAGS #define F2FS_IOC_GETVERSION FS_IOC_GETVERSION #define F2FS_IOCTL_MAGIC 0xf5 #define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) #define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) #define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3) #define F2FS_IOC_RELEASE_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 4) #define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) #define F2FS_IOC_GARBAGE_COLLECT _IO(F2FS_IOCTL_MAGIC, 6) #define F2FS_IOC_WRITE_CHECKPOINT _IO(F2FS_IOCTL_MAGIC, 7) #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_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY #define F2FS_IOC_GET_ENCRYPTION_PWSALT FS_IOC_GET_ENCRYPTION_PWSALT /* * should be same as XFS_IOC_GOINGDOWN. * Flags for going down operation used by FS_IOC_GOINGDOWN */ #define F2FS_IOC_SHUTDOWN _IOR('X', 125, __u32) /* Shutdown */ #define F2FS_GOING_DOWN_FULLSYNC 0x0 /* going down with full sync */ #define F2FS_GOING_DOWN_METASYNC 0x1 /* going down with metadata */ #define F2FS_GOING_DOWN_NOSYNC 0x2 /* going down */ #define F2FS_GOING_DOWN_METAFLUSH 0x3 /* going down with meta flush */ #if defined(__KERNEL__) && defined(CONFIG_COMPAT) /* * ioctl commands in 32 bit emulation */ #define F2FS_IOC32_GETFLAGS FS_IOC32_GETFLAGS #define F2FS_IOC32_SETFLAGS FS_IOC32_SETFLAGS #define F2FS_IOC32_GETVERSION FS_IOC32_GETVERSION #endif struct f2fs_defragment { u64 start; 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 directory operations */ struct f2fs_dentry_ptr { struct inode *inode; const void *bitmap; struct f2fs_dir_entry *dentry; __u8 (*filename)[F2FS_SLOT_LEN]; int max; };
static inline void make_dentry_ptr(struct inode *inode, struct f2fs_dentry_ptr *d, void *src, int type) { d->inode = inode; if (type == 1) { struct f2fs_dentry_block *t = (struct f2fs_dentry_block *)src; d->max = NR_DENTRY_IN_BLOCK; d->bitmap = &t->dentry_bitmap; d->dentry = t->dentry; d->filename = t->filename; } else { struct f2fs_inline_dentry *t = (struct f2fs_inline_dentry *)src; d->max = NR_INLINE_DENTRY; d->bitmap = &t->dentry_bitmap; d->dentry = t->dentry; d->filename = t->filename; } }

Contributors

PersonTokensPropCommitsCommitProp
jaegeuk kimjaegeuk kim127100.00%2100.00%
Total127100.00%2100.00%

/* * XATTR_NODE_OFFSET stores xattrs to one node block per file keeping -1 * as its node offset to distinguish from index node blocks. * But some bits are used to mark the node block. */ #define XATTR_NODE_OFFSET ((((unsigned int)-1) << OFFSET_BIT_SHIFT) \ >> OFFSET_BIT_SHIFT) enum { ALLOC_NODE, /* allocate a new node page if needed */ LOOKUP_NODE, /* look up a node without readahead */ LOOKUP_NODE_RA, /* * look up a node with readahead called * by get_data_block. */ }; #define F2FS_LINK_MAX 0xffffffff /* maximum link count per file */ #define MAX_DIR_RA_PAGES 4 /* maximum ra pages of dir */ /* vector size for gang look-up from extent cache that consists of radix tree */ #define EXT_TREE_VEC_SIZE 64 /* for in-memory extent cache entry */ #define F2FS_MIN_EXTENT_LEN 64 /* minimum extent length */ /* number of extent info in extent cache we try to shrink */ #define EXTENT_CACHE_SHRINK_NUMBER 128 struct extent_info { unsigned int fofs; /* start offset in a file */ u32 blk; /* start block address of the extent */ unsigned int len; /* length of the extent */ }; struct extent_node { struct rb_node rb_node; /* rb node located in rb-tree */ struct list_head list; /* node in global extent list of sbi */ struct extent_info ei; /* extent info */ struct extent_tree *et; /* extent tree pointer */ }; struct extent_tree { nid_t ino; /* inode number */ struct rb_root root; /* root of extent info rb-tree */ struct extent_node *cached_en; /* recently accessed extent node */ 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 */ atomic_t node_cnt; /* # of extent node in rb-tree*/ }; /* * This structure is taken from ext4_map_blocks. * * Note that, however, f2fs uses NEW and MAPPED flags for f2fs_map_blocks(). */ #define F2FS_MAP_NEW (1 << BH_New) #define F2FS_MAP_MAPPED (1 << BH_Mapped) #define F2FS_MAP_UNWRITTEN (1 << BH_Unwritten) #define F2FS_MAP_FLAGS (F2FS_MAP_NEW | F2FS_MAP_MAPPED |\ F2FS_MAP_UNWRITTEN) struct f2fs_map_blocks { block_t m_pblk; block_t m_lblk; unsigned int m_len; unsigned int m_flags; pgoff_t *m_next_pgofs; /* point next possible non-hole pgofs */ }; /* for flag in get_data_block */ #define F2FS_GET_BLOCK_READ 0 #define F2FS_GET_BLOCK_DIO 1 #define F2FS_GET_BLOCK_FIEMAP 2 #define F2FS_GET_BLOCK_BMAP 3 #define F2FS_GET_BLOCK_PRE_DIO 4 #define F2FS_GET_BLOCK_PRE_AIO 5 /* * i_advise uses FADVISE_XXX_BIT. We can add additional hints later. */ #define FADVISE_COLD_BIT 0x01 #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) #define file_set_cold(inode) set_file(inode, FADVISE_COLD_BIT) #define file_lost_pino(inode) set_file(inode, FADVISE_LOST_PINO_BIT) #define file_clear_cold(inode) clear_file(inode, FADVISE_COLD_BIT) #define file_got_pino(inode) clear_file(inode, FADVISE_LOST_PINO_BIT) #define file_is_encrypt(inode) is_file(inode, FADVISE_ENCRYPT_BIT) #define file_set_encrypt(inode) set_file(inode, FADVISE_ENCRYPT_BIT) #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 struct f2fs_inode_info { struct inode vfs_inode; /* serve a vfs inode */ unsigned long i_flags; /* keep an inode flags for ioctl */ unsigned char i_advise; /* use to give file attribute hints */ unsigned char i_dir_level; /* use for dentry level for large dir */ unsigned int i_current_depth; /* use only in directory structure */ unsigned int i_pino; /* parent inode number */ umode_t i_acl_mode; /* keep file acl mode temporarily */ /* Use below internally in f2fs*/ unsigned long flags; /* use to pass per-file flags */ struct rw_semaphore i_sem; /* protect fi info */ atomic_t dirty_pages; /* # of dirty pages */ f2fs_hash_t chash; /* hash value of given file name */ unsigned int clevel; /* maximum level of given file name */ nid_t i_xattr_nid; /* node id that contains xattrs */ unsigned long long xattr_ver; /* cp version of xattr modification */ loff_t last_disk_size; /* lastly written file size */ struct list_head dirty_list; /* dirty list for dirs and files */ struct list_head gdirty_list; /* linked in global dirty list */ struct list_head inmem_pages; /* inmemory pages managed by f2fs */ struct mutex inmem_lock; /* lock for inmemory pages */ struct extent_tree *extent_tree; /* cached extent_tree entry */ struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */ };
static inline void get_extent_info(struct extent_info *ext, struct f2fs_extent *i_ext) { ext->fofs = le32_to_cpu(i_ext->fofs); ext->blk = le32_to_cpu(i_ext->blk); ext->len = le32_to_cpu(i_ext->len); }

Contributors

PersonTokensPropCommitsCommitProp
jaegeuk kimjaegeuk kim4488.00%133.33%
chao yuchao yu612.00%266.67%
Total50100.00%3100.00%


static inline void set_raw_extent(struct extent_info *ext, struct f2fs_extent *i_ext) { i_ext->fofs = cpu_to_le32(ext->fofs); i_ext->blk = cpu_to_le32(ext->blk); i_ext->len = cpu_to_le32(ext->len); }

Contributors

PersonTokensPropCommitsCommitProp
jaegeuk kimjaegeuk kim4896.00%150.00%
chao yuchao yu24.00%150.00%
Total50100.00%2100.00%


static inline void set_extent_info(struct extent_info *ei, unsigned int fofs, u32 blk, unsigned int len) { ei->fofs = fofs; ei->blk = blk; ei->len = len; }

Contributors

PersonTokensPropCommitsCommitProp
chao yuchao yu41100.00%1100.00%
Total41100.00%1100.00%


static inline bool __is_extent_same(struct extent_info *ei1, struct extent_info *ei2) { return (ei1->fofs == ei2->fofs && ei1->blk == ei2->blk && ei1->len == ei2->len); }

Contributors

PersonTokensPropCommitsCommitProp
chao yuchao yu44100.00%1100.00%
Total44100.00%1100.00%


static inline bool __is_extent_mergeable(struct extent_info *back, struct extent_info *front) { return (back->fofs + back->len == front->fofs && back->blk + back->len == front->blk); }

Contributors

PersonTokensPropCommitsCommitProp
chao yuchao yu44100.00%1100.00%
Total44100.00%1100.00%


static inline bool __is_back_mergeable(struct extent_info *cur, struct extent_info *back) { return __is_extent_mergeable(back, cur); }

Contributors

PersonTokensPropCommitsCommitProp
chao yuchao yu25100.00%1100.00%
Total25100.00%1100.00%


static inline bool __is_front_mergeable(struct extent_info *cur, struct extent_info *front) { return __is_extent_mergeable(cur, front); }

Contributors

PersonTokensPropCommitsCommitProp
chao yuchao yu25100.00%1100.00%
Total25100.00%1100.00%

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, true); } }

Contributors

PersonTokensPropCommitsCommitProp
chao yuchao yu3973.58%125.00%
jaegeuk kimjaegeuk kim1426.42%375.00%
Total53100.00%4100.00%

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; /* # 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 */ unsigned int dirty_nats_ratio; /* control dirty nats ratio threshold */ /* 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 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 */ /* free node ids management */ struct radix_tree_root free_nid_root;/* root of the free_nid cache */ 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 */ char *nat_bitmap; /* NAT bitmap pointer */ int bitmap_size; /* bitmap size */ }; /* * this structure is used as one of function parameters. * all the information are dedicated to a given direct node block determined * by the data offset in a file. */ struct dnode_of_data { struct inode *inode; /* vfs inode pointer */ struct page *inode_page; /* its inode page, NULL is possible */ struct page *node_page; /* cached direct node page */ nid_t nid; /* node id of the direct node block */ unsigned int ofs_in_node; /* data offset in the node page */ bool inode_page_locked; /* inode page is locked or not */ bool node_changed; /* is node block changed */ char cur_level; /* level of hole node page */ char max_level; /* level of current page located */ block_t data_blkaddr; /* block address of the node block */ };
static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, struct page *ipage, struct page *npage, nid_t nid) { memset(dn, 0, sizeof(*dn)); dn->inode = inode; dn->inode_page = ipage; dn->node_page = npage; dn->nid = nid; }

Contributors

PersonTokensPropCommitsCommitProp
jaegeuk kimjaegeuk kim67100.00%2100.00%
Total67100.00%2100.00%

/* * For SIT manager * * By default, there are 6 active log areas across the whole main area. * When considering hot and cold data separation to reduce cleaning overhead, * we split 3 for data logs and 3 for node logs as hot, warm, and cold types, * respectively. * In the current design, you should not change the numbers intentionally. * Instead, as a mount option such as active_logs=x, you can use 2, 4, and 6 * logs individually according to the underlying devices. (default: 6) * Just in case, on-disk layout covers maximum 16 logs that consist of 8 for * data and 8 for node logs. */ #define NR_CURSEG_DATA_TYPE (3) #define NR_CURSEG_NODE_TYPE (3) #define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE) enum { CURSEG_HOT_DATA = 0, /* directory entry blocks */ CURSEG_WARM_DATA, /* data blocks */ CURSEG_COLD_DATA, /* multimedia or GCed data blocks */ CURSEG_HOT_NODE, /* direct node blocks of directory files */ CURSEG_WARM_NODE, /* direct node blocks of normal files */ CURSEG_COLD_NODE, /* indirect node blocks */ NO_CHECK_TYPE, }; struct flush_cmd { struct completion wait; struct llist_node llnode; int ret; }; 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 */ }; struct f2fs_sm_info { struct sit_info *sit_info; /* whole segment information */ struct free_segmap_info *free_info; /* free segment information */ struct dirty_seglist_info *dirty_info; /* dirty segment information */ struct curseg_info *curseg_array; /* active segment information */ block_t seg0_blkaddr; /* block address of 0'th segment */ block_t main_blkaddr; /* start block address of main area */ block_t ssa_blkaddr; /* start block address of SSA area */ unsigned int segment_count; /* total # of segments */ unsigned int main_segments; /* # of segments in main area */ unsigned int reserved_segments; /* # of reserved segments */ unsigned int ovp_segments; /* # of overprovision segments */ /* a threshold to reclaim prefree segments */ unsigned int rec_prefree_segments; /* for small discard management */ struct list_head discard_list; /* 4KB discard list */ struct list_head wait_list; /* linked with issued discard bio */ int nr_discards; /* # of discards in the list */ int max_discards; /* max. discards to be issued */ /* for batched trimming */ unsigned int trim_sections; /* # of sections to trim */ struct list_head sit_entry_set; /* sit entry set list */ unsigned int ipu_policy; /* in-place-update policy */ unsigned int min_ipu_util; /* in-place-update threshold */ unsigned int min_fsync_blocks; /* threshold for fsync */ /* for flush command control */ struct flush_cmd_control *cmd_control_info; }; /* * For superblock */ /* * COUNT_TYPE for monitoring * * 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, F2FS_DIRTY_NODES, F2FS_DIRTY_META, F2FS_INMEM_PAGES, F2FS_DIRTY_IMETA, F2FS_WB_CP_DATA, F2FS_WB_DATA, NR_COUNT_TYPE, }; /* * The below are the page types of bios used in submit_bio(). * The available types are: * DATA User data pages. It operates as async mode. * NODE Node pages. It operates as async mode. * META FS metadata pages such as SIT, NAT, CP. * NR_PAGE_TYPE The number of page types. * META_FLUSH Make sure the previous pages are written * with waiting the bio's completion * ... Only can be used with META. */ #define PAGE_TYPE_OF_BIO(type) ((type) > META ? META : (type)) enum page_type { DATA, NODE, META, NR_PAGE_TYPE, META_FLUSH, INMEM, /* the below types are used by tracepoints only. */ INMEM_DROP, INMEM_REVOKE, IPU, OPU, }; struct f2fs_io_info { struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */ enum page_type type; /* contains DATA/NODE/META/META_FLUSH */ int op; /* contains REQ_OP_ */ int op_flags; /* req_flag_bits */ block_t new_blkaddr; /* new block address to be written */ block_t old_blkaddr; /* old block address before Cow */ struct page *page; /* page to be written */ struct page *encrypted_page; /* encrypted page */ }; #define is_read_io(rw) (rw == READ) struct f2fs_bio_info { struct f2fs_sb_info *sbi; /* f2fs superblock */ struct bio *bio; /* bios to merge */ sector_t last_block_in_bio; /* last block number */ struct f2fs_io_info fio; /* store buffered io 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 */ DIRTY_META, /* for all dirtied inode metadata */ NR_INODE_TYPE, }; /* for inner inode cache management */ struct inode_management { struct radix_tree_root ino_root; /* ino entry array */ spinlock_t ino_lock; /* for ino entry lock */ struct list_head ino_list; /* inode list head */ unsigned long ino_num; /* number of entries */ }; /* For s_flag in struct f2fs_sb_info */ enum { SBI_IS_DIRTY, /* dirty flag for checkpoint */ SBI_IS_CLOSE, /* specify unmounting */ SBI_NEED_FSCK, /* need fsck.f2fs to fix */ SBI_POR_DOING, /* recovery is doing or not */ SBI_NEED_SB_WRITE, /* need to recover superblock */ SBI_NEED_CP, /* need to checkpoint */ }; enum { CP_TIME, REQ_TIME, MAX_TIME, }; #ifdef CONFIG_F2FS_FS_ENCRYPTION #define F2FS_KEY_DESC_PREFIX "f2fs:" #define F2FS_KEY_DESC_PREFIX_SIZE 5 #endif struct f2fs_sb_info { struct super_block *sb; /* pointer to VFS super block */ struct proc_dir_entry *s_proc; /* proc entry */ struct f2fs_super_block *raw_super; /* raw super block pointer */ int valid_super_block; /* valid super block no */ unsigned long s_flag; /* flags for sbi */ #ifdef CONFIG_F2FS_FS_ENCRYPTION 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 */ /* for segment-related operations */ struct f2fs_sm_info *sm_info; /* segment manager */ /* 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 */ 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 */ struct rw_semaphore cp_rwsem; /* blocking FS operations */ struct rw_semaphore node_write; /* locking node writes */ 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 */