[PATCH 1/2] f2fs: enhance scalibility of {d,id,did,x}node disk layout

From: Chao Yu
Date: Sat Jan 27 2018 - 04:44:11 EST


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 <yuchao0@xxxxxxxxxx>
---
fs/f2fs/f2fs.h | 23 +++++++++++++++++++++++
fs/f2fs/file.c | 7 ++++---
fs/f2fs/gc.c | 9 +++++----
fs/f2fs/node.c | 46 +++++++++++++++++++++++++---------------------
fs/f2fs/node.h | 13 ++++++++-----
fs/f2fs/super.c | 16 +++++++++++-----
fs/f2fs/sysfs.c | 7 +++++++
fs/f2fs/xattr.c | 10 ++++++----
fs/f2fs/xattr.h | 6 ++++--
include/linux/f2fs_fs.h | 18 ++++++++++--------
10 files changed, 103 insertions(+), 52 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 6ac1c09419e2..6f5e41657c62 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -127,6 +127,7 @@ struct f2fs_mount_info {
#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 F2FS_HAS_FEATURE(sb, mask) \
((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -416,6 +417,7 @@ struct f2fs_flush_device {
#define DEF_INLINE_RESERVED_SIZE 1
#define DEF_MIN_INLINE_SIZE 1
static inline int get_extra_isize(struct inode *inode);
+static inline int get_extra_nsize(struct super_block *sb);
static inline int get_inline_xattr_addrs(struct inode *inode);
#define MAX_INLINE_DATA(inode) (sizeof(__le32) * \
(CUR_ADDRS_PER_INODE(inode) - \
@@ -1123,6 +1125,7 @@ struct f2fs_sb_info {
int inline_xattr_size; /* inline xattr size */
unsigned int trigger_ssr_threshold; /* threshold to trigger ssr */
int readdir_ra; /* readahead inode in readdir */
+ unsigned int extra_nsize; /* extra attr size in {d,id,did,x}node */

block_t user_block_count; /* # of user blocks */
block_t total_valid_block_count; /* # of valid blocks */
@@ -2344,6 +2347,16 @@ static inline unsigned int addrs_per_inode(struct inode *inode)
return CUR_ADDRS_PER_INODE(inode) - get_inline_xattr_addrs(inode);
}

+static inline unsigned int addrs_per_dnode(struct inode *inode)
+{
+ return DEF_ADDRS_PER_BLOCK - get_extra_nsize(inode->i_sb);
+}
+
+static inline unsigned int nids_per_idnode(struct inode *inode)
+{
+ return DEF_NIDS_PER_BLOCK - get_extra_nsize(inode->i_sb);
+}
+
static inline void *inline_xattr_addr(struct inode *inode, struct page *page)
{
struct f2fs_inode *ri = F2FS_INODE(page);
@@ -2533,6 +2546,11 @@ static inline int get_extra_isize(struct inode *inode)
return F2FS_I(inode)->i_extra_isize / sizeof(__le32);
}

+static inline int get_extra_nsize(struct super_block *sb)
+{
+ return F2FS_SB(sb)->extra_nsize / sizeof(__le32);
+}
+
static inline int get_inline_xattr_addrs(struct inode *inode)
{
return F2FS_I(inode)->i_inline_xattr_size;
@@ -3229,6 +3247,11 @@ static inline int f2fs_sb_has_inode_crtime(struct super_block *sb)
return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_INODE_CRTIME);
}

+static inline int f2fs_sb_has_extended_node(struct super_block *sb)
+{
+ return F2FS_HAS_FEATURE(sb, F2FS_FEATURE_EXTENDED_NODE);
+}
+
#ifdef CONFIG_BLK_DEV_ZONED
static inline int get_blkz_type(struct f2fs_sb_info *sbi,
struct block_device *bdev, block_t blkaddr)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index d56c3b7a8ba1..b8810843dc21 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -540,7 +540,7 @@ void truncate_data_blocks_range(struct dnode_of_data *dn, int count)

void truncate_data_blocks(struct dnode_of_data *dn)
{
- truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
+ truncate_data_blocks_range(dn, ADDRS_PER_BLOCK(dn->inode));
}

static int truncate_partial_data_page(struct inode *inode, u64 from,
@@ -978,7 +978,8 @@ static int __read_out_blkaddrs(struct inode *inode, block_t *blkaddr,
} else if (ret == -ENOENT) {
if (dn.max_level == 0)
return -ENOENT;
- done = min((pgoff_t)ADDRS_PER_BLOCK - dn.ofs_in_node, len);
+ done = min((pgoff_t)ADDRS_PER_BLOCK(inode) - dn.ofs_in_node,
+ len);
blkaddr += done;
do_replace += done;
goto next;
@@ -1122,7 +1123,7 @@ static int __exchange_data_block(struct inode *src_inode,
int ret;

while (len) {
- olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
+ olen = min((pgoff_t)4 * ADDRS_PER_BLOCK(src_inode), len);

src_blkaddr = f2fs_kvzalloc(F2FS_I_SB(src_inode),
sizeof(block_t) * olen, GFP_KERNEL);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 3b26aa19430b..0da1e218a1ec 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -538,7 +538,7 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
*/
block_t start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
{
- unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
+ unsigned int indirect_blks = 2 * NIDS_PER_BLOCK(inode) + 4;
unsigned int bidx;

if (node_ofs == 0)
@@ -547,13 +547,14 @@ block_t start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
if (node_ofs <= 2) {
bidx = node_ofs - 1;
} else if (node_ofs <= indirect_blks) {
- int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
+ int dec = (node_ofs - 4) / (NIDS_PER_BLOCK(inode) + 1);
bidx = node_ofs - 2 - dec;
} else {
- int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
+ int dec = (node_ofs - indirect_blks - 3) /
+ (NIDS_PER_BLOCK(inode) + 1);
bidx = node_ofs - 5 - dec;
}
- return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(inode);
+ return bidx * ADDRS_PER_BLOCK(inode) + ADDRS_PER_INODE(inode);
}

static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 7cded843cf18..bc8424babf36 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -461,7 +461,8 @@ static void ra_node_pages(struct page *parent, int start, int n)

/* Then, try readahead for siblings of the desired node */
end = start + n;
- end = min(end, NIDS_PER_BLOCK);
+ end = min_t(unsigned int, end, DEF_NIDS_PER_BLOCK -
+ get_extra_nsize(sbi->sb));
for (i = start; i < end; i++) {
nid = get_nid(parent, i, false);
ra_node_page(sbi, nid);
@@ -473,9 +474,10 @@ static void ra_node_pages(struct page *parent, int start, int n)
pgoff_t get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
{
const long direct_index = ADDRS_PER_INODE(dn->inode);
- const long direct_blks = ADDRS_PER_BLOCK;
- const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
- unsigned int skipped_unit = ADDRS_PER_BLOCK;
+ const long direct_blks = ADDRS_PER_BLOCK(dn->inode);
+ const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) *
+ NIDS_PER_BLOCK(dn->inode);
+ unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode);
int cur_level = dn->cur_level;
int max_level = dn->max_level;
pgoff_t base = 0;
@@ -484,7 +486,7 @@ pgoff_t get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
return pgofs + 1;

while (max_level-- > cur_level)
- skipped_unit *= NIDS_PER_BLOCK;
+ skipped_unit *= NIDS_PER_BLOCK(dn->inode);

switch (dn->max_level) {
case 3:
@@ -509,10 +511,11 @@ static int get_node_path(struct inode *inode, long block,
int offset[4], unsigned int noffset[4])
{
const long direct_index = ADDRS_PER_INODE(inode);
- const long direct_blks = ADDRS_PER_BLOCK;
- const long dptrs_per_blk = NIDS_PER_BLOCK;
- const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
- const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
+ const long direct_blks = ADDRS_PER_BLOCK(inode);
+ const long dptrs_per_blk = NIDS_PER_BLOCK(inode);
+ const long indirect_blks = ADDRS_PER_BLOCK(inode) *
+ NIDS_PER_BLOCK(inode);
+ const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK(inode);
int n = 0;
int level = 0;

@@ -758,7 +761,7 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
int i, ret;

if (dn->nid == 0)
- return NIDS_PER_BLOCK + 1;
+ return NIDS_PER_BLOCK(dn->inode) + 1;

trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr);

@@ -768,11 +771,11 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
return PTR_ERR(page);
}

- ra_node_pages(page, ofs, NIDS_PER_BLOCK);
+ ra_node_pages(page, ofs, NIDS_PER_BLOCK(dn->inode));

rn = F2FS_NODE(page);
if (depth < 3) {
- for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
+ for (i = ofs; i < NIDS_PER_BLOCK(dn->inode); i++, freed++) {
child_nid = le32_to_cpu(rn->in.nid[i]);
if (child_nid == 0)
continue;
@@ -784,16 +787,16 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
dn->node_changed = true;
}
} else {
- child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
- for (i = ofs; i < NIDS_PER_BLOCK; i++) {
+ child_nofs = nofs + ofs * (NIDS_PER_BLOCK(dn->inode) + 1) + 1;
+ for (i = ofs; i < NIDS_PER_BLOCK(dn->inode); i++) {
child_nid = le32_to_cpu(rn->in.nid[i]);
if (child_nid == 0) {
- child_nofs += NIDS_PER_BLOCK + 1;
+ child_nofs += NIDS_PER_BLOCK(dn->inode) + 1;
continue;
}
rdn.nid = child_nid;
ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
- if (ret == (NIDS_PER_BLOCK + 1)) {
+ if (ret == (NIDS_PER_BLOCK(dn->inode) + 1)) {
if (set_nid(page, i, 0, false))
dn->node_changed = true;
child_nofs += ret;
@@ -847,10 +850,10 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
}

- ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK);
+ ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK(dn->inode));

/* free direct nodes linked to a partial indirect node */
- for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) {
+ for (i = offset[idx + 1]; i < NIDS_PER_BLOCK(dn->inode); i++) {
child_nid = get_nid(pages[idx], i, false);
if (!child_nid)
continue;
@@ -922,10 +925,10 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from)
err = truncate_partial_nodes(&dn, ri, offset, level);
if (err < 0 && err != -ENOENT)
goto fail;
- nofs += 1 + NIDS_PER_BLOCK;
+ nofs += 1 + NIDS_PER_BLOCK(inode);
break;
case 3:
- nofs = 5 + 2 * NIDS_PER_BLOCK;
+ nofs = 5 + 2 * NIDS_PER_BLOCK(inode);
if (!offset[level - 1])
goto skip_partial;
err = truncate_partial_nodes(&dn, ri, offset, level);
@@ -2278,7 +2281,8 @@ int recover_xattr_data(struct inode *inode, struct page *page)
update_inode_page(inode);

/* 3: update and set xattr node page dirty */
- memcpy(F2FS_NODE(xpage), F2FS_NODE(page), VALID_XATTR_BLOCK_SIZE);
+ memcpy(F2FS_NODE(xpage), F2FS_NODE(page),
+ VALID_XATTR_BLOCK_SIZE(inode));

set_page_dirty(xpage);
f2fs_put_page(xpage, 1);
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index 081ef0d672bf..b051196b5d5b 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -338,17 +338,20 @@ static inline bool is_recoverable_dnode(struct page *page)
*/
static inline bool IS_DNODE(struct page *node_page)
{
+ struct f2fs_sb_info *sbi = F2FS_P_SB(node_page);
unsigned int ofs = ofs_of_node(node_page);
+ unsigned int nids_per_block = DEF_NIDS_PER_BLOCK -
+ get_extra_nsize(sbi->sb);

if (f2fs_has_xattr_block(ofs))
return true;

- if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
- ofs == 5 + 2 * NIDS_PER_BLOCK)
+ 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)))
+ 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;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index f6fb8d9928bc..368f63d7bad2 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1901,10 +1901,12 @@ static const struct export_operations f2fs_export_ops = {
.get_parent = f2fs_get_parent,
};

-static loff_t max_file_blocks(void)
+static loff_t max_file_blocks(struct super_block *sb)
{
+ unsigned int nids_per_block = DEF_NIDS_PER_BLOCK -
+ get_extra_nsize(sb);
+ loff_t leaf_count = DEF_ADDRS_PER_BLOCK - get_extra_nsize(sb);
loff_t result = 0;
- loff_t leaf_count = ADDRS_PER_BLOCK;

/*
* note: previously, result is equal to (DEF_ADDRS_PER_INODE -
@@ -1917,11 +1919,11 @@ static loff_t max_file_blocks(void)
result += (leaf_count * 2);

/* two indirect node blocks */
- leaf_count *= NIDS_PER_BLOCK;
+ leaf_count *= nids_per_block;
result += (leaf_count * 2);

/* one double indirect node block */
- leaf_count *= NIDS_PER_BLOCK;
+ leaf_count *= nids_per_block;
result += leaf_count;

return result;
@@ -2554,6 +2556,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
goto free_sb_buf;
}
#endif
+
+ if (f2fs_sb_has_extended_node(sb))
+ sbi->extra_nsize = le16_to_cpu(raw_super->extra_nsize);
+
default_options(sbi);
/* parse mount options */
options = kstrdup((const char *)data, GFP_KERNEL);
@@ -2566,7 +2572,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
if (err)
goto free_options;

- sbi->max_file_blocks = max_file_blocks();
+ sbi->max_file_blocks = max_file_blocks(sb);
sb->s_maxbytes = sbi->max_file_blocks <<
le32_to_cpu(raw_super->log_blocksize);
sb->s_max_links = F2FS_LINK_MAX;
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index d978c7b6ea04..f25a6fc0a17e 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -116,6 +116,9 @@ static ssize_t features_show(struct f2fs_attr *a,
if (f2fs_sb_has_inode_crtime(sb))
len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
len ? ", " : "", "inode_crtime");
+ if (f2fs_sb_has_extended_node(sb))
+ len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
+ len ? ", " : "", "extended_node");
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
return len;
}
@@ -236,6 +239,7 @@ enum feat_id {
FEAT_FLEXIBLE_INLINE_XATTR,
FEAT_QUOTA_INO,
FEAT_INODE_CRTIME,
+ FEAT_EXTENDED_NODE,
};

static ssize_t f2fs_feature_show(struct f2fs_attr *a,
@@ -251,6 +255,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
case FEAT_FLEXIBLE_INLINE_XATTR:
case FEAT_QUOTA_INO:
case FEAT_INODE_CRTIME:
+ case FEAT_EXTENDED_NODE:
return snprintf(buf, PAGE_SIZE, "supported\n");
}
return 0;
@@ -329,6 +334,7 @@ F2FS_FEATURE_RO_ATTR(inode_checksum, FEAT_INODE_CHECKSUM);
F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR);
F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO);
F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME);
+F2FS_FEATURE_RO_ATTR(extended_node, FEAT_EXTENDED_NODE);

#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = {
@@ -383,6 +389,7 @@ static struct attribute *f2fs_feat_attrs[] = {
ATTR_LIST(flexible_inline_xattr),
ATTR_LIST(quota_ino),
ATTR_LIST(inode_crtime),
+ ATTR_LIST(extended_node),
NULL,
};

diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index ae2dfa709f5d..d847b2b11659 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -278,7 +278,8 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr)
return PTR_ERR(xpage);

xattr_addr = page_address(xpage);
- memcpy(txattr_addr + inline_size, xattr_addr, VALID_XATTR_BLOCK_SIZE);
+ memcpy(txattr_addr + inline_size, xattr_addr,
+ VALID_XATTR_BLOCK_SIZE(inode));
f2fs_put_page(xpage, 1);

return 0;
@@ -291,7 +292,7 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
{
void *cur_addr, *txattr_addr, *last_addr = NULL;
nid_t xnid = F2FS_I(inode)->i_xattr_nid;
- unsigned int size = xnid ? VALID_XATTR_BLOCK_SIZE : 0;
+ unsigned int size = xnid ? VALID_XATTR_BLOCK_SIZE(inode) : 0;
unsigned int inline_size = inline_xattr_size(inode);
int err = 0;

@@ -346,7 +347,7 @@ static int read_all_xattrs(struct inode *inode, struct page *ipage,
{
struct f2fs_xattr_header *header;
nid_t xnid = F2FS_I(inode)->i_xattr_nid;
- unsigned int size = VALID_XATTR_BLOCK_SIZE;
+ unsigned int size = VALID_XATTR_BLOCK_SIZE(inode);
unsigned int inline_size = inline_xattr_size(inode);
void *txattr_addr;
int err;
@@ -454,7 +455,8 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,

if (inline_size)
memcpy(inline_addr, txattr_addr, inline_size);
- memcpy(xattr_addr, txattr_addr + inline_size, VALID_XATTR_BLOCK_SIZE);
+ memcpy(xattr_addr, txattr_addr + inline_size,
+ VALID_XATTR_BLOCK_SIZE(inode));

if (inline_size)
set_page_dirty(ipage ? ipage : in_page);
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
index dbcd1d16e669..8ddc94ea5d00 100644
--- a/fs/f2fs/xattr.h
+++ b/fs/f2fs/xattr.h
@@ -72,10 +72,12 @@ struct f2fs_xattr_entry {
for (entry = XATTR_FIRST_ENTRY(addr);\
!IS_XATTR_LAST_ENTRY(entry);\
entry = XATTR_NEXT_ENTRY(entry))
-#define VALID_XATTR_BLOCK_SIZE (PAGE_SIZE - sizeof(struct node_footer))
+#define VALID_XATTR_BLOCK_SIZE(i) (PAGE_SIZE - \
+ sizeof(struct node_footer) - \
+ F2FS_I_SB(i)->extra_nsize)
#define XATTR_PADDING_SIZE (sizeof(__u32))
#define MIN_OFFSET(i) XATTR_ALIGN(inline_xattr_size(i) + \
- VALID_XATTR_BLOCK_SIZE)
+ VALID_XATTR_BLOCK_SIZE(i))

#define MAX_VALUE_LEN(i) (MIN_OFFSET(i) - \
sizeof(struct f2fs_xattr_header) - \
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index f7f09907e69d..a6bacfdd378d 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -111,7 +111,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 */
} __packed;

/*
@@ -192,15 +193,16 @@ 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 DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */
#define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \
get_extra_isize(inode))
-#define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */
#define ADDRS_PER_INODE(inode) addrs_per_inode(inode)
-#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(inode) addrs_per_dnode(inode)
+#define NIDS_PER_BLOCK(inode) nids_per_idnode(inode)
#define ADDRS_PER_PAGE(page, inode) \
- (IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK)
+ (IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK(inode))

#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1)
#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2)
@@ -265,11 +267,11 @@ struct f2fs_inode {
} __packed;

struct direct_node {
- __le32 addr[ADDRS_PER_BLOCK]; /* array of data block address */
+ __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */
} __packed;

struct indirect_node {
- __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */
+ __le32 nid[DEF_NIDS_PER_BLOCK]; /* array of data block address */
} __packed;

enum {
--
2.15.0.55.gc2ece9dc4de6