Scalibility of non-inode disk layout is very bad, it's hard to add or reuse any fields in current structure, so, for new feature like node checksum which wants to add 4 bytes field in node structure, the bad scaliblity becomes a obstacle for its implementation.
In order to enhance scalibility, we introduce a new filesystem feature 'extended_node' which can be enabled via mkfs.f2fs, once this feature is set, we will add and configure f2fs_super_block::extra_nsize to indicate extended space used for storing new attribution, accordingly, it needs to recalculate space of original .addr/.nid/xattr space in node block. dnode, idnode, didnode, xnode disk layout: +----------------------+ | .addr or .nid, .xatt | +----------------------+<----+ | ...... | | | .epoch | | | .transaction_id | +------ f2fs_super_block::extra_nsize | .node_checksum | | +----------------------+<----+ | node_footer | | (nid, ino, offset) | +----------------------+ Signed-off-by: Chao Yu <[email protected]> --- fsck/dump.c | 5 +++-- fsck/mount.c | 3 +++ fsck/node.c | 8 ++++---- fsck/node.h | 2 +- fsck/xattr.c | 4 ++-- fsck/xattr.h | 7 ++++--- include/f2fs_fs.h | 30 +++++++++++++++++++++++++----- lib/libf2fs.c | 1 + mkfs/f2fs_format.c | 2 ++ mkfs/f2fs_format_main.c | 2 ++ 10 files changed, 47 insertions(+), 17 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index 7ccb03f121f5..32b68c932356 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -527,7 +527,8 @@ static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) free(node_blk); } -static void dump_data_offset(u32 blk_addr, int ofs_in_node) +static void dump_data_offset(struct f2fs_sb_info *sbi, + u32 blk_addr, int ofs_in_node) { struct f2fs_node *node_blk; unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; @@ -664,7 +665,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) MSG(0, " - Inode block : id = 0x%x from 0x%x\n", ni.ino, ino_ni.blk_addr); dump_node_from_blkaddr(sbi, ino_ni.blk_addr); - dump_data_offset(ni.blk_addr, + dump_data_offset(sbi, ni.blk_addr, le16_to_cpu(sum_entry.ofs_in_node)); } else { MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr); diff --git a/fsck/mount.c b/fsck/mount.c index 54eb061e4ffe..016e52471f11 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -460,6 +460,9 @@ void print_sb_state(struct f2fs_super_block *sb) if (f & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) { MSG(0, "%s", " inode_crtime"); } + if (f & cpu_to_le32(F2FS_FEATURE_EXTENDED_NODE)) { + MSG(0, "%s", " extended_node"); + } MSG(0, "\n"); MSG(0, "Info: superblock encrypt level = %d, salt = ", sb->encryption_level); diff --git a/fsck/node.c b/fsck/node.c index 7f4a28b1a5df..f4b8c5a59c5f 100644 --- a/fsck/node.c +++ b/fsck/node.c @@ -77,7 +77,7 @@ block_t new_node_block(struct f2fs_sb_info *sbi, node_blk->footer.cp_ver = ckpt->checkpoint_ver; type = CURSEG_COLD_NODE; - if (IS_DNODE(node_blk)) { + if (IS_DNODE(sbi, node_blk)) { if (S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode))) type = CURSEG_HOT_NODE; else @@ -105,8 +105,8 @@ block_t new_node_block(struct f2fs_sb_info *sbi, * * By default, it sets inline_xattr and inline_data */ -static int get_node_path(struct f2fs_node *node, long block, - int offset[4], unsigned int noffset[4]) +static int get_node_path(struct f2fs_sb_info *sbi, struct f2fs_node *node, + long block, int offset[4], unsigned int noffset[4]) { const long direct_index = ADDRS_PER_INODE(&node->i); const long direct_blks = ADDRS_PER_BLOCK; @@ -191,7 +191,7 @@ void get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, int level, i; int ret; - level = get_node_path(dn->inode_blk, index, offset, noffset); + level = get_node_path(sbi, dn->inode_blk, index, offset, noffset); nids[0] = dn->nid; parent = dn->inode_blk; diff --git a/fsck/node.h b/fsck/node.h index cbf7ed708bb2..28e703a7ea71 100644 --- a/fsck/node.h +++ b/fsck/node.h @@ -87,7 +87,7 @@ static inline void inc_inode_blocks(struct dnode_of_data *dn) dn->idirty = 1; } -static inline int IS_DNODE(struct f2fs_node *node_page) +static inline int IS_DNODE(struct f2fs_sb_info *sbi, struct f2fs_node *node_page) { unsigned int ofs = ofs_of_node(node_page); diff --git a/fsck/xattr.c b/fsck/xattr.c index 1d15d1b7fa82..9ee306649bee 100644 --- a/fsck/xattr.c +++ b/fsck/xattr.c @@ -131,7 +131,7 @@ int f2fs_setxattr(struct f2fs_sb_info *sbi, nid_t ino, int index, const char *na len = strlen(name); - if (len > F2FS_NAME_LEN || size > MAX_VALUE_LEN) + if (len > F2FS_NAME_LEN || size > MAX_VALUE_LEN(sbi)) return -ERANGE; if (ino < 3) @@ -174,7 +174,7 @@ int f2fs_setxattr(struct f2fs_sb_info *sbi, nid_t ino, int index, const char *na * If value is NULL, it is remove operation. * In case of update operation, we calculate free. */ - free = MIN_OFFSET - ((char *)last - (char *)base_addr); + free = MIN_OFFSET(sbi) - ((char *)last - (char *)base_addr); if (found) free = free + ENTRY_SIZE(here); if (free < newsize) { diff --git a/fsck/xattr.h b/fsck/xattr.h index e4a98e224a93..6a75fd34cdb0 100644 --- a/fsck/xattr.h +++ b/fsck/xattr.h @@ -127,10 +127,11 @@ static inline int f2fs_acl_count(int size) !IS_XATTR_LAST_ENTRY(entry); \ entry = XATTR_NEXT_ENTRY(entry)) -#define MIN_OFFSET XATTR_ALIGN(PAGE_SIZE - \ - sizeof(struct node_footer) - sizeof(__u32)) +#define MIN_OFFSET(s) XATTR_ALIGN(PAGE_SIZE - \ + sizeof(struct node_footer) - sizeof(__u32) - \ + get_extra_nsize(s->raw_super) * sizeof(__le32)) -#define MAX_VALUE_LEN (MIN_OFFSET - \ +#define MAX_VALUE_LEN(s) (MIN_OFFSET(s) - \ sizeof(struct f2fs_xattr_header) - \ sizeof(struct f2fs_xattr_entry)) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 548a3e85a1d5..1692cd5433ca 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -363,6 +363,7 @@ struct f2fs_configuration { int ro; int preserve_limits; /* preserve quota limits */ int large_nat_bitmap; + unsigned short extra_nsize; __le32 feature; /* defined features */ /* defragmentation parameters */ @@ -552,6 +553,7 @@ enum { #define F2FS_FEATURE_FLEXIBLE_INLINE_XATTR 0x0040 #define F2FS_FEATURE_QUOTA_INO 0x0080 #define F2FS_FEATURE_INODE_CRTIME 0x0100 +#define F2FS_FEATURE_EXTENDED_NODE 0x0200 #define MAX_VOLUME_NAME 512 @@ -609,7 +611,8 @@ struct f2fs_super_block { __u8 encrypt_pw_salt[16]; /* Salt used for string2key algorithm */ struct f2fs_device devs[MAX_DEVICES]; /* device list */ __le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */ - __u8 reserved[315]; /* valid reserved region */ + __le16 extra_nsize; /* extra node size */ + __u8 reserved[313]; /* valid reserved region */ } __attribute__((packed)); /* @@ -699,11 +702,13 @@ struct f2fs_extent { /* 200 bytes for inline xattrs by default */ #define DEFAULT_INLINE_XATTR_ADDRS 50 #define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ +#define DEF_ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ +#define DEF_NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ #define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \ __get_extra_isize(inode)) #define ADDRS_PER_INODE(i) addrs_per_inode(i) -#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ -#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ +#define ADDRS_PER_BLOCK addrs_per_dnode(sbi->raw_super) +#define NIDS_PER_BLOCK nids_per_idnode(sbi->raw_super) #define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) #define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) @@ -805,14 +810,14 @@ struct f2fs_inode { #pragma pack(1) #endif struct direct_node { - __le32 addr[ADDRS_PER_BLOCK]; /* array of data block address */ + __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */ } __attribute__((packed)); #ifdef ANDROID_WINDOWS_HOST #pragma pack(1) #endif struct indirect_node { - __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */ + __le32 nid[DEF_NIDS_PER_BLOCK]; /* array of data block address */ } __attribute__((packed)); enum { @@ -1209,6 +1214,21 @@ static inline int __get_extra_isize(struct f2fs_inode *inode) return 0; } +static inline int get_extra_nsize(struct f2fs_super_block *sb) +{ + return le16_to_cpu(sb->extra_nsize) / sizeof(__le32); +} + +static inline long addrs_per_dnode(struct f2fs_super_block *sb) +{ + return DEF_ADDRS_PER_BLOCK - get_extra_nsize(sb); +} + +static inline long nids_per_idnode(struct f2fs_super_block *sb) +{ + return DEF_NIDS_PER_BLOCK - get_extra_nsize(sb); +} + extern struct f2fs_configuration c; static inline int get_inline_xattr_addrs(struct f2fs_inode *inode) { diff --git a/lib/libf2fs.c b/lib/libf2fs.c index e8b1842b7391..61962cf7d461 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -624,6 +624,7 @@ void f2fs_init_configuration(void) c.kd = -1; c.dry_run = 0; c.large_nat_bitmap = 0; + c.extra_nsize = 0; c.fixed_time = -1; } diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 93e9feaecda6..51337b53a795 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -426,6 +426,8 @@ static int f2fs_prepare_super_block(void) qtype, next_ino - 1); } + sb->extra_nsize = cpu_to_le16(c.extra_nsize); + if (total_zones <= 6) { MSG(1, "\tError: %d zones: Need more zones " "by shrinking zone size\n", total_zones); diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c index b6f36853cd3e..93922b0af068 100644 --- a/mkfs/f2fs_format_main.c +++ b/mkfs/f2fs_format_main.c @@ -95,6 +95,8 @@ static void parse_feature(const char *features) c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO); } else if (!strcmp(features, "inode_crtime")) { c.feature |= cpu_to_le32(F2FS_FEATURE_INODE_CRTIME); + } else if (!strcmp(features, "extended_node")) { + c.feature |= cpu_to_le32(F2FS_FEATURE_EXTENDED_NODE); } else { MSG(0, "Error: Wrong features\n"); mkfs_usage(); -- 2.15.0.55.gc2ece9dc4de6 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
