相关数据结构

node manager

记录空闲块和数据位图,在内存中:

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) */
        spinlock_t nat_list_lock;       /* protect clean nat entry list */
        unsigned int nat_cnt;           /* the # of cached nat entries */
        unsigned int dirty_nat_cnt;     /* total num of nat entries in set */
        unsigned int nat_blocks;        /* # of nat blocks */

        /* free node ids management */
        struct radix_tree_root free_nid_root;/* root of the free_nid cache */
        struct list_head free_nid_list;         /* list for free nids excluding preallocated nids */
        unsigned int nid_cnt[MAX_NID_STATE];    /* the number of free node id */
        spinlock_t nid_list_lock;       /* protect nid lists ops */
        struct mutex build_lock;        /* lock for build free nids */
        unsigned char **free_nid_bitmap;
        unsigned char *nat_block_bitmap;
        unsigned short *free_nid_count; /* free nid count of NAT block */

        /* for checkpoint */
        char *nat_bitmap;               /* NAT bitmap pointer */

        unsigned int nat_bits_blocks;   /* # of nat bits blocks */
        unsigned char *nat_bits;        /* NAT bits blocks */
        unsigned char *full_nat_bits;   /* full NAT pages */
        unsigned char *empty_nat_bits;  /* empty NAT pages */
#ifdef CONFIG_F2FS_CHECK_FS
        char *nat_bitmap_mir;           /* NAT bitmap mirror */
#endif
        int bitmap_size;                /* bitmap size */
};

全局记录上述信息的sb_info

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 */
        struct rw_semaphore sb_lock;            /* lock for raw super block */
        int valid_super_block;                  /* valid super block no */
        unsigned long s_flag;                           /* flags for sbi */
        struct mutex writepages;                /* mutex for writepages() */

#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 *write_io[NR_PAGE_TYPE];   /* for write bios */
        struct mutex wio_mutex[NR_PAGE_TYPE - 1][NR_TEMP_TYPE];
                                                /* bio ordering for NODE/DATA */
        /* keep migration IO order for LFS mode */
        struct rw_semaphore io_order_lock;
        mempool_t *write_io_dummy;              /* Dummy pages */

理解blk/node的分配必须看懂的关键数据结构

nid: node id
node id是inode内部对索引节点的编号,根据层次内逐渐递增,当前层次遍历完了之后会对后面的层次进行遍历递归。
相关的数据结构定义有:

 /*
 * f2fs assigns the following node offsets described as (num).
 * N = NIDS_PER_BLOCK
 *
 *  Inode block (0)
 *    |- direct node (1)
 *    |- direct node (2)
 *    |- indirect node (3)
 *    |            `- direct node (4 => 4 + N - 1)
 *    |- indirect node (4 + N)
 *    |            `- direct node (5 + N => 5 + 2N - 1)
 *    `- double indirect node (5 + 2N)
 *                 `- indirect node (6 + 2N)
 *                       `- direct node
 *                 ......
 *                 `- indirect node ((6 + 2N) + x(N + 1))
 *                       `- direct node
 *                 ......
 *                 `- indirect node ((6 + 2N) + (N - 1)(N + 1))
 *                       `- direct node
 */
static inline bool IS_DNODE(struct page *node_page)
{
        unsigned int ofs = ofs_of_node(node_page);

        if (f2fs_has_xattr_block(ofs))
                return true;

        if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
                        ofs == 5 + 2 * NIDS_PER_BLOCK)
                return false;
        if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
                ofs -= 6 + 2 * NIDS_PER_BLOCK;
                if (!((long int)ofs % (NIDS_PER_BLOCK + 1)))
                        return false;
        }
        return true;
}

/*
 * For node information
 *  这个数据结构建立了起来indoe number 所属的node  info
*/
struct node_info {
        nid_t nid;              /* node id, index from 0 to pyhsical max node number - 1 */
        nid_t ino;              /* inode number of the node's owner */
        block_t blk_addr;       /* block address of the node */
        unsigned char version;  /* version of the node */
        unsigned char flag;     /* for node information bits */
};

struct nat_entry {
        struct list_head list;  /* for clean or dirty nat list */
        struct node_info ni;    /* in-memory node information */
};

由此可见, node id是per inode的, 所以NAT journal中还需要记录其他inode number 机器blkaddr, 这里的blkaddr是一个
物理上的地址。

相关的函数有: