linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] f2fs-tools: spread struct f2fs_dentry_ptr for inline path
@ 2017-07-16  7:12 Chao Yu
  2017-07-16  7:12 ` [PATCH 2/3] f2fs-tools: enhance on-disk inode structure scalability Chao Yu
  2017-07-16  7:12 ` [PATCH 3/3] f2fs-tools: support project quota Chao Yu
  0 siblings, 2 replies; 5+ messages in thread
From: Chao Yu @ 2017-07-16  7:12 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel

From: Chao Yu <yuchao0@huawei.com>

Use f2fs_dentry_ptr structure to indicate inline dentry structure as
much as possible, so we can wrap inline dentry with size-fixed fields
to the one with size-changeable fields. With this change, we can
handle size-changeable inline dentry more easily.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/dir.c  | 25 +++++++++++++------------
 fsck/f2fs.h |  1 +
 fsck/fsck.c | 15 ++++++++-------
 fsck/fsck.h |  1 +
 4 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/fsck/dir.c b/fsck/dir.c
index 57b7f9b..62bc7b9 100644
--- a/fsck/dir.c
+++ b/fsck/dir.c
@@ -34,17 +34,19 @@ next:
 
 }
 
-static void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
+void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
 {
 	if (type == 1) {
 		struct f2fs_dentry_block *t = (struct f2fs_dentry_block *)src;
 		d->max = NR_DENTRY_IN_BLOCK;
+		d->nr_bitmap = SIZE_OF_DENTRY_BITMAP;
 		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->nr_bitmap = INLINE_DENTRY_BITMAP_SIZE;
 		d->bitmap = t->dentry_bitmap;
 		d->dentry = t->dentry;
 		d->filename = t->filename;
@@ -459,8 +461,8 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
 	ASSERT(ret >= 0);
 
 	if (!dir_level) {
-		struct f2fs_inline_dentry *inline_dentry;
 		struct f2fs_dentry_block *dentry_blk;
+		struct f2fs_dentry_ptr src, dst;
 
 		dentry_blk = calloc(BLOCK_SZ, 1);
 		ASSERT(dentry_blk);
@@ -470,17 +472,16 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
 		if (dn.data_blkaddr == NULL_ADDR)
 			new_data_block(sbi, dentry_blk, &dn, CURSEG_HOT_DATA);
 
-		inline_dentry = (struct f2fs_inline_dentry *)inline_data;
+		make_dentry_ptr(&src, (void *)inline_data, 2);
+		make_dentry_ptr(&dst, (void *)dentry_blk, 1);
+
 		 /* copy data from inline dentry block to new dentry block */
-		memcpy(dentry_blk->dentry_bitmap, inline_dentry->dentry_bitmap,
-				INLINE_DENTRY_BITMAP_SIZE);
-		memset(dentry_blk->dentry_bitmap + INLINE_DENTRY_BITMAP_SIZE, 0,
-			SIZE_OF_DENTRY_BITMAP - INLINE_DENTRY_BITMAP_SIZE);
-
-		memcpy(dentry_blk->dentry, inline_dentry->dentry,
-			sizeof(struct f2fs_dir_entry) * NR_INLINE_DENTRY);
-		memcpy(dentry_blk->filename, inline_dentry->filename,
-				NR_INLINE_DENTRY * F2FS_SLOT_LEN);
+		memcpy(dst.bitmap, src.bitmap, src.nr_bitmap);
+		memset(dst.bitmap + src.nr_bitmap, 0,
+					dst.nr_bitmap - src.nr_bitmap);
+
+		memcpy(dst.dentry, src.dentry, SIZE_OF_DIR_ENTRY * src.max);
+		memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN);
 
 		ret = dev_write_block(dentry_blk, dn.data_blkaddr);
 		ASSERT(ret >= 0);
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index efc43f6..d1626e3 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -129,6 +129,7 @@ struct f2fs_dentry_ptr {
 	struct f2fs_dir_entry *dentry;
 	__u8 (*filename)[F2FS_SLOT_LEN];
 	int max;
+	int nr_bitmap;
 };
 
 struct dentry {
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 56336ad..84196cf 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -1355,17 +1355,18 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
 		struct f2fs_node *node_blk, struct child_info *child)
 {
 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
-	struct f2fs_inline_dentry *de_blk;
+	struct f2fs_dentry_ptr d;
+	void *inline_dentry;
 	int dentries;
 
-	de_blk = inline_data_addr(node_blk);
-	ASSERT(de_blk != NULL);
+	inline_dentry = inline_data_addr(node_blk);
+	ASSERT(inline_dentry != NULL);
+
+	make_dentry_ptr(&d, inline_dentry, 2);
 
 	fsck->dentry_depth++;
 	dentries = __chk_dentries(sbi, child,
-			de_blk->dentry_bitmap,
-			de_blk->dentry, de_blk->filename,
-			NR_INLINE_DENTRY, 1,
+			d.bitmap, d.dentry, d.filename, d.max, 1,
 			file_enc_name(&node_blk->i));
 	if (dentries < 0) {
 		DBG(1, "[%3d] Inline Dentry Block Fixed hash_codes\n\n",
@@ -1374,7 +1375,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
 		DBG(1, "[%3d] Inline Dentry Block Done : "
 				"dentries:%d in %d slots (len:%d)\n\n",
 			fsck->dentry_depth, dentries,
-			(int)NR_INLINE_DENTRY, F2FS_NAME_LEN);
+			d.max, F2FS_NAME_LEN);
 	}
 	fsck->dentry_depth--;
 	return dentries;
diff --git a/fsck/fsck.h b/fsck/fsck.h
index c54eccb..5d2cfd6 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -221,6 +221,7 @@ block_t new_node_block(struct f2fs_sb_info *,
 					struct dnode_of_data *, unsigned int);
 void get_dnode_of_data(struct f2fs_sb_info *, struct dnode_of_data *,
 					pgoff_t, int);
+void make_dentry_ptr(struct f2fs_dentry_ptr *, void *, int);
 int f2fs_create(struct f2fs_sb_info *, struct dentry *);
 int f2fs_mkdir(struct f2fs_sb_info *, struct dentry *);
 int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
-- 
2.13.0.90.g1eb437020


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] f2fs-tools: enhance on-disk inode structure scalability
  2017-07-16  7:12 [PATCH 1/3] f2fs-tools: spread struct f2fs_dentry_ptr for inline path Chao Yu
@ 2017-07-16  7:12 ` Chao Yu
  2017-07-17 22:22   ` Jaegeuk Kim
  2017-07-16  7:12 ` [PATCH 3/3] f2fs-tools: support project quota Chao Yu
  1 sibling, 1 reply; 5+ messages in thread
From: Chao Yu @ 2017-07-16  7:12 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel

From: Chao Yu <yuchao0@huawei.com>

Adjust to change of kernel side:

This patch add new flag F2FS_EXTRA_ATTR storing in inode.i_inline
to indicate that on-disk structure of current inode is extended.

In order to extend, we changed the inode structure a bit:

Original one:

struct f2fs_inode {
	...
	struct f2fs_extent i_ext;
	__le32 i_addr[DEF_ADDRS_PER_INODE];
	__le32 i_nid[DEF_NIDS_PER_INODE];
}

Extended one:

struct f2fs_inode {
        ...
        struct f2fs_extent i_ext;
	union {
		struct {
			__le16 i_extra_isize;
			__le16 i_padding;
		};
		__le32 i_addr[DEF_ADDRS_PER_INODE];
	};
        __le32 i_nid[DEF_NIDS_PER_INODE];
}

Once F2FS_EXTRA_ATTR is set, we will steal four bytes in the head of
i_addr field for storing i_extra_isize and i_padding. with i_extra_isize,
we can calculate actual size of reserved space in i_addr, available
attribute fields included in total extra attribute fields for current
inode can be described as below:

  +--------------------+
  | .i_mode            |
  | ...                |
  | .i_ext             |
  +--------------------+
  | .i_extra_isize     |-----+
  | .i_padding         |     |
  | .i_prjid           |     |
  | .i_atime_extra     |     |
  | .i_ctime_extra     |     |
  | .i_mtime_extra     |<----+
  | .i_inode_cs        |<----- store blkaddr/inline from here
  | .i_xattr_cs        |
  | ...                |
  +--------------------+
  |                    |
  |    block address   |
  |                    |
  +--------------------+
  | .i_nid             |
  +--------------------+
  |   node_footer      |
  | (nid, ino, offset) |
  +--------------------+

Hence, with this patch, we would enhance scalability of f2fs inode for
storing more newly added attribute.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/dir.c         | 48 +++++++++++++++++++---------------
 fsck/dump.c        |  6 ++---
 fsck/f2fs.h        |  4 ++-
 fsck/fsck.c        | 35 +++++++++++++++----------
 fsck/fsck.h        |  2 +-
 fsck/mount.c       | 20 ++++++++++-----
 fsck/node.c        |  6 ++---
 fsck/node.h        |  7 ++++-
 fsck/segment.c     |  5 ++--
 include/f2fs_fs.h  | 75 +++++++++++++++++++++++++++++++++++++++++-------------
 lib/libf2fs.c      |  4 +--
 mkfs/f2fs_format.c |  4 ++-
 12 files changed, 143 insertions(+), 73 deletions(-)

diff --git a/fsck/dir.c b/fsck/dir.c
index 62bc7b9..d70183f 100644
--- a/fsck/dir.c
+++ b/fsck/dir.c
@@ -34,7 +34,8 @@ next:
 
 }
 
-void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
+void make_dentry_ptr(struct f2fs_dentry_ptr *d, struct f2fs_node *node_blk,
+							void *src, int type)
 {
 	if (type == 1) {
 		struct f2fs_dentry_block *t = (struct f2fs_dentry_block *)src;
@@ -44,12 +45,16 @@ void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
 		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->nr_bitmap = INLINE_DENTRY_BITMAP_SIZE;
-		d->bitmap = t->dentry_bitmap;
-		d->dentry = t->dentry;
-		d->filename = t->filename;
+		int entry_cnt = NR_INLINE_DENTRY(node_blk);
+		int bitmap_size = INLINE_DENTRY_BITMAP_SIZE(node_blk);
+		int reserved_size = INLINE_RESERVED_SIZE(node_blk);
+
+		d->max = entry_cnt;
+		d->nr_bitmap = bitmap_size;
+		d->bitmap = src;
+		d->dentry = src + bitmap_size + reserved_size;
+		d->filename = src + bitmap_size + reserved_size +
+						SIZE_OF_DIR_ENTRY * entry_cnt;
 	}
 }
 
@@ -95,7 +100,7 @@ static struct f2fs_dir_entry *find_in_block(void *block,
 {
 	struct f2fs_dentry_ptr d;
 
-	make_dentry_ptr(&d, block, 1);
+	make_dentry_ptr(&d, NULL, block, 1);
 	return find_target_dentry(name, len, namehash, max_slots, &d);
 }
 
@@ -258,7 +263,7 @@ start:
 	goto start;
 
 add_dentry:
-	make_dentry_ptr(&d, (void *)dentry_blk, 1);
+	make_dentry_ptr(&d, NULL, (void *)dentry_blk, 1);
 	f2fs_update_dentry(ino, file_type, &d, name, name_len, dentry_hash, bit_pos);
 
 	ret = dev_write_block(dentry_blk, dn.data_blkaddr);
@@ -338,7 +343,7 @@ static void make_empty_dir(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
 	ret = dev_write_block(dent_blk, blkaddr);
 	ASSERT(ret >= 0);
 
-	inode->i.i_addr[0] = cpu_to_le32(blkaddr);
+	inode->i.i_addr[get_extra_isize(inode)] = cpu_to_le32(blkaddr);
 	free(dent_blk);
 }
 
@@ -355,10 +360,10 @@ static void page_symlink(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
 	get_node_info(sbi, ino, &ni);
 
 	/* store into inline_data */
-	if (symlen + 1 <= MAX_INLINE_DATA) {
+	if (symlen + 1 <= MAX_INLINE_DATA(inode)) {
 		inode->i.i_inline |= F2FS_INLINE_DATA;
 		inode->i.i_inline |= F2FS_DATA_EXIST;
-		memcpy(&inode->i.i_addr[1], symname, symlen);
+		memcpy(inline_data_addr(inode), symname, symlen);
 		return;
 	}
 
@@ -373,7 +378,7 @@ static void page_symlink(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
 	ret = dev_write_block(data_blk, blkaddr);
 	ASSERT(ret >= 0);
 
-	inode->i.i_addr[0] = cpu_to_le32(blkaddr);
+	inode->i.i_addr[get_extra_isize(inode)] = cpu_to_le32(blkaddr);
 	free(data_blk);
 }
 
@@ -398,7 +403,7 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
 		ASSERT(de->link);
 		mode |= S_IFLNK;
 		size = strlen(de->link);
-		if (size + 1 > MAX_INLINE_DATA)
+		if (size + 1 > MAX_INLINE_DATA(node_blk))
 			blocks++;
 	} else {
 		ASSERT(0);
@@ -421,11 +426,12 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
 	node_blk->i.i_current_depth = cpu_to_le32(1);
 	node_blk->i.i_xattr_nid = 0;
 	node_blk->i.i_flags = 0;
-	node_blk->i.i_inline = F2FS_INLINE_XATTR;
+	node_blk->i.i_inline = F2FS_INLINE_XATTR | F2FS_EXTRA_ATTR;
 	node_blk->i.i_pino = cpu_to_le32(de->pino);
 	node_blk->i.i_namelen = cpu_to_le32(de->len);
 	memcpy(node_blk->i.i_name, de->name, de->len);
 	node_blk->i.i_name[de->len] = 0;
+	node_blk->i.i_extra_isize = cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
 
 	node_blk->footer.ino = cpu_to_le32(de->ino);
 	node_blk->footer.nid = cpu_to_le32(de->ino);
@@ -444,7 +450,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
 	struct f2fs_inode *inode = &(node->i);
 	unsigned int dir_level = node->i.i_dir_level;
 	nid_t ino = le32_to_cpu(node->footer.ino);
-	char inline_data[MAX_INLINE_DATA];
+	char inline_data[MAX_INLINE_DATA(node)];
 	struct dnode_of_data dn = {0};
 	struct f2fs_dentry_ptr d;
 	unsigned long bit_pos = 0;
@@ -453,8 +459,8 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
 	if (!(inode->i_inline & F2FS_INLINE_DENTRY))
 		return 0;
 
-	memcpy(inline_data, inline_data_addr(node), MAX_INLINE_DATA);
-	memset(inline_data_addr(node), 0, MAX_INLINE_DATA);
+	memcpy(inline_data, inline_data_addr(node), MAX_INLINE_DATA(node));
+	memset(inline_data_addr(node), 0, MAX_INLINE_DATA(node));
 	inode->i_inline &= ~F2FS_INLINE_DENTRY;
 
 	ret = dev_write_block(node, p_blkaddr);
@@ -472,8 +478,8 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
 		if (dn.data_blkaddr == NULL_ADDR)
 			new_data_block(sbi, dentry_blk, &dn, CURSEG_HOT_DATA);
 
-		make_dentry_ptr(&src, (void *)inline_data, 2);
-		make_dentry_ptr(&dst, (void *)dentry_blk, 1);
+		make_dentry_ptr(&src, node, (void *)inline_data, 2);
+		make_dentry_ptr(&dst, NULL, (void *)dentry_blk, 1);
 
 		 /* copy data from inline dentry block to new dentry block */
 		memcpy(dst.bitmap, src.bitmap, src.nr_bitmap);
@@ -493,7 +499,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
 	}
 
 	make_empty_dir(sbi, node);
-	make_dentry_ptr(&d, (void *)inline_data, 2);
+	make_dentry_ptr(&d, node, (void *)inline_data, 2);
 
 	while (bit_pos < d.max) {
 		struct f2fs_dir_entry *de;
diff --git a/fsck/dump.c b/fsck/dump.c
index 22e2265..128dc53 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -322,14 +322,14 @@ static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 		DBG(3, "ino[0x%x] has inline data!\n", nid);
 		/* recover from inline data */
 		dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
-							0, MAX_INLINE_DATA);
+						0, MAX_INLINE_DATA(node_blk));
 		return;
 	}
 
 	/* check data blocks in inode */
 	for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
-		dump_data_blk(sbi, ofs * F2FS_BLKSIZE,
-				le32_to_cpu(node_blk->i.i_addr[i]));
+		dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu(
+			node_blk->i.i_addr[get_extra_isize(node_blk) + i]));
 
 	/* check node blocks in inode */
 	for (i = 0; i < 5; i++) {
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index d1626e3..871cffc 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -233,7 +233,9 @@ static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
 
 static inline void *inline_data_addr(struct f2fs_node *node_blk)
 {
-	return (void *)&(node_blk->i.i_addr[1]);
+	int ofs = get_extra_isize(node_blk) + DEF_INLINE_RESERVED_SIZE;
+
+	return (void *)&(node_blk->i.i_addr[ofs]);
 }
 
 static inline unsigned int ofs_of_node(struct f2fs_node *node_blk)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 84196cf..7a81855 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -226,10 +226,13 @@ static int is_valid_summary(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
 		goto out;
 
 	/* check its block address */
-	if (node_blk->footer.nid == node_blk->footer.ino)
-		target_blk_addr = node_blk->i.i_addr[ofs_in_node];
-	else
+	if (node_blk->footer.nid == node_blk->footer.ino) {
+		int ofs = get_extra_isize(node_blk);
+
+		target_blk_addr = node_blk->i.i_addr[ofs + ofs_in_node];
+	} else {
 		target_blk_addr = node_blk->dn.addr[ofs_in_node];
+	}
 
 	if (blk_addr == le32_to_cpu(target_blk_addr))
 		ret = 1;
@@ -658,20 +661,22 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 		goto check;
 
 	if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
-		if (le32_to_cpu(node_blk->i.i_addr[0]) != 0) {
+		int ofs = get_extra_isize(node_blk);
+
+		if (le32_to_cpu(node_blk->i.i_addr[ofs]) != 0) {
 			/* should fix this bug all the time */
 			FIX_MSG("inline_data has wrong 0'th block = %x",
-					le32_to_cpu(node_blk->i.i_addr[0]));
-			node_blk->i.i_addr[0] = 0;
+					le32_to_cpu(node_blk->i.i_addr[ofs]));
+			node_blk->i.i_addr[ofs] = 0;
 			node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
 			need_fix = 1;
 		}
 		if (!(node_blk->i.i_inline & F2FS_DATA_EXIST)) {
-			char buf[MAX_INLINE_DATA];
-			memset(buf, 0, MAX_INLINE_DATA);
+			char buf[MAX_INLINE_DATA(node_blk)];
+			memset(buf, 0, MAX_INLINE_DATA(node_blk));
 
-			if (memcmp(buf, &node_blk->i.i_addr[1],
-							MAX_INLINE_DATA)) {
+			if (memcmp(buf, inline_data_addr(node_blk),
+						MAX_INLINE_DATA(node_blk))) {
 				FIX_MSG("inline_data has DATA_EXIST");
 				node_blk->i.i_inline |= F2FS_DATA_EXIST;
 				need_fix = 1;
@@ -710,7 +715,8 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 	/* check data blocks in inode */
 	for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i);
 						idx++, child.pgofs++) {
-		block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[idx]);
+		int ofs = get_extra_isize(node_blk);
+		block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[ofs + idx]);
 
 		/* check extent info */
 		check_extent_info(&child, blkaddr, 0);
@@ -724,9 +730,10 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 			if (!ret) {
 				*blk_cnt = *blk_cnt + 1;
 			} else if (c.fix_on) {
-				node_blk->i.i_addr[idx] = 0;
+				node_blk->i.i_addr[ofs + idx] = 0;
 				need_fix = 1;
-				FIX_MSG("[0x%x] i_addr[%d] = 0", nid, idx);
+				FIX_MSG("[0x%x] i_addr[%d] = 0",
+							nid, ofs + idx);
 			}
 		}
 	}
@@ -1362,7 +1369,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
 	inline_dentry = inline_data_addr(node_blk);
 	ASSERT(inline_dentry != NULL);
 
-	make_dentry_ptr(&d, inline_dentry, 2);
+	make_dentry_ptr(&d, node_blk, inline_dentry, 2);
 
 	fsck->dentry_depth++;
 	dentries = __chk_dentries(sbi, child,
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 5d2cfd6..1e8ed0b 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -221,7 +221,7 @@ block_t new_node_block(struct f2fs_sb_info *,
 					struct dnode_of_data *, unsigned int);
 void get_dnode_of_data(struct f2fs_sb_info *, struct dnode_of_data *,
 					pgoff_t, int);
-void make_dentry_ptr(struct f2fs_dentry_ptr *, void *, int);
+void make_dentry_ptr(struct f2fs_dentry_ptr *, struct f2fs_node *, void *, int);
 int f2fs_create(struct f2fs_sb_info *, struct dentry *);
 int f2fs_mkdir(struct f2fs_sb_info *, struct dentry *);
 int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
diff --git a/fsck/mount.c b/fsck/mount.c
index a0b0bea..693e4a8 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -41,6 +41,7 @@ void print_inode_info(struct f2fs_inode *inode, int name)
 	unsigned int i = 0;
 	int namelen = le32_to_cpu(inode->i_namelen);
 	int enc_name = file_enc_name(inode);
+	int ofs = __get_extra_isize(inode);
 
 	namelen = convert_encrypted_name(inode->i_name, namelen, en, enc_name);
 	en[namelen] = '\0';
@@ -87,12 +88,15 @@ void print_inode_info(struct f2fs_inode *inode, int name)
 			le32_to_cpu(inode->i_ext.blk_addr),
 			le32_to_cpu(inode->i_ext.len));
 
-	DISP_u32(inode, i_addr[0]);	/* Pointers to data blocks */
-	DISP_u32(inode, i_addr[1]);	/* Pointers to data blocks */
-	DISP_u32(inode, i_addr[2]);	/* Pointers to data blocks */
-	DISP_u32(inode, i_addr[3]);	/* Pointers to data blocks */
+	DISP_u16(inode, i_extra_isize);
+	DISP_u16(inode, i_padding);
 
-	for (i = 4; i < ADDRS_PER_INODE(inode); i++) {
+	DISP_u32(inode, i_addr[ofs]);		/* Pointers to data blocks */
+	DISP_u32(inode, i_addr[ofs + 1]);	/* Pointers to data blocks */
+	DISP_u32(inode, i_addr[ofs + 2]);	/* Pointers to data blocks */
+	DISP_u32(inode, i_addr[ofs + 3]);	/* Pointers to data blocks */
+
+	for (i = ofs + 4; i < ADDRS_PER_INODE(inode); i++) {
 		if (inode->i_addr[i] != 0x0) {
 			printf("i_addr[0x%x] points data block\r\t\t[0x%4x]\n",
 					i, le32_to_cpu(inode->i_addr[i]));
@@ -1357,8 +1361,10 @@ void update_data_blkaddr(struct f2fs_sb_info *sbi, nid_t nid,
 
 	/* check its block address */
 	if (node_blk->footer.nid == node_blk->footer.ino) {
-		oldaddr = le32_to_cpu(node_blk->i.i_addr[ofs_in_node]);
-		node_blk->i.i_addr[ofs_in_node] = cpu_to_le32(newaddr);
+		int ofs = get_extra_isize(node_blk);
+
+		oldaddr = le32_to_cpu(node_blk->i.i_addr[ofs + ofs_in_node]);
+		node_blk->i.i_addr[ofs + ofs_in_node] = cpu_to_le32(newaddr);
 	} else {
 		oldaddr = le32_to_cpu(node_blk->dn.addr[ofs_in_node]);
 		node_blk->dn.addr[ofs_in_node] = cpu_to_le32(newaddr);
diff --git a/fsck/node.c b/fsck/node.c
index fe923e5..e37b817 100644
--- a/fsck/node.c
+++ b/fsck/node.c
@@ -105,10 +105,10 @@ block_t new_node_block(struct f2fs_sb_info *sbi,
  *
  * By default, it sets inline_xattr and inline_data
  */
-static int get_node_path(unsigned long block,
+static int get_node_path(struct f2fs_node *node, unsigned long block,
 				int offset[4], unsigned int noffset[4])
 {
-	const long direct_index = DEF_ADDRS_PER_INODE_INLINE_XATTR;
+	const long direct_index = ADDRS_PER_INODE(&node->i);
 	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;
@@ -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(index, offset, noffset);
+	level = get_node_path(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 721e5b7..cbf7ed7 100644
--- a/fsck/node.h
+++ b/fsck/node.h
@@ -26,9 +26,14 @@ static inline int IS_INODE(struct f2fs_node *node)
 	return ((node)->footer.nid == (node)->footer.ino);
 }
 
+static inline __le32 *blkaddr_in_inode(struct f2fs_node *node)
+{
+	return node->i.i_addr + get_extra_isize(node);
+}
+
 static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
 {
-	return IS_INODE(node) ? node->i.i_addr : node->dn.addr;
+	return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr;
 }
 
 static inline block_t datablock_addr(struct f2fs_node *node_page,
diff --git a/fsck/segment.c b/fsck/segment.c
index 6b2f6c1..e21339b 100644
--- a/fsck/segment.c
+++ b/fsck/segment.c
@@ -179,7 +179,7 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
 	}
 
 	/* inline_data support */
-	if (de->size <= MAX_INLINE_DATA) {
+	if (de->size <= DEF_MAX_INLINE_DATA) {
 		struct node_info ni;
 		struct f2fs_node *node_blk;
 		int ret;
@@ -194,9 +194,10 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
 
 		node_blk->i.i_inline |= F2FS_INLINE_DATA;
 		node_blk->i.i_inline |= F2FS_DATA_EXIST;
+		node_blk->i.i_inline |= F2FS_EXTRA_ATTR;
 		n = read(fd, buffer, BLOCK_SZ);
 		ASSERT(n == de->size);
-		memcpy(&node_blk->i.i_addr[1], buffer, de->size);
+		memcpy(inline_data_addr(node_blk), buffer, de->size);
 
 		node_blk->i.i_size = cpu_to_le64(de->size);
 
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index dd2635b..88ceb61 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -167,6 +167,14 @@ static inline uint64_t bswap_64(uint64_t val)
 		printf("%-30s" fmt, #member, ((ptr)->member));	\
 	} while (0)
 
+#define DISP_u16(ptr, member)						\
+	do {								\
+		assert(sizeof((ptr)->member) == 2);			\
+		printf("%-30s" "\t\t[0x%8x : %u]\n",			\
+			#member, le16_to_cpu(((ptr)->member)),		\
+			le16_to_cpu(((ptr)->member)));			\
+	} while (0)
+
 #define DISP_u32(ptr, member)						\
 	do {								\
 		assert(sizeof((ptr)->member) <= 4);			\
@@ -585,6 +593,8 @@ struct f2fs_extent {
 #define F2FS_NAME_LEN		255
 #define F2FS_INLINE_XATTR_ADDRS	50	/* 200 bytes for inline xattrs */
 #define DEF_ADDRS_PER_INODE	923	/* Address Pointers in an Inode */
+#define CUR_ADDRS_PER_INODE(inode)	(DEF_ADDRS_PER_INODE - \
+					__get_extra_isize(inode))
 #define ADDRS_PER_INODE(i)	addrs_per_inode(i)
 #define DEF_ADDRS_PER_INODE_INLINE_XATTR				\
 		(DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS)
@@ -602,12 +612,27 @@ struct f2fs_extent {
 #define F2FS_INLINE_DENTRY	0x04	/* file inline dentry flag */
 #define F2FS_DATA_EXIST		0x08	/* file inline data exist flag */
 #define F2FS_INLINE_DOTS	0x10	/* file having implicit dot dentries */
+#define F2FS_EXTRA_ATTR		0x20	/* file having extra attribute */
 
-#define MAX_INLINE_DATA (sizeof(__le32) *				\
-			(DEF_ADDRS_PER_INODE_INLINE_XATTR - 1))
+#if !defined(offsetof)
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
 
+#define F2FS_TOTAL_EXTRA_ATTR_SIZE			\
+	(offsetof(struct f2fs_inode, i_extra_end) -	\
+	offsetof(struct f2fs_inode, i_extra_isize))	\
+
+#define MAX_INLINE_DATA(node) (sizeof(__le32) *				\
+				(DEF_ADDRS_PER_INODE_INLINE_XATTR -	\
+				get_extra_isize(node) -			\
+				DEF_INLINE_RESERVED_SIZE))
+#define DEF_MAX_INLINE_DATA	(sizeof(__le32) *			\
+				(DEF_ADDRS_PER_INODE_INLINE_XATTR -	\
+				F2FS_TOTAL_EXTRA_ATTR_SIZE -		\
+				DEF_INLINE_RESERVED_SIZE))
 #define INLINE_DATA_OFFSET	(PAGE_CACHE_SIZE - sizeof(struct node_footer) \
-				- sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1))
+				- sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - \
+				DEF_INLINE_RESERVED_SIZE))
 
 #define DEF_DIR_LEVEL		0
 
@@ -648,8 +673,14 @@ struct f2fs_inode {
 
 	struct f2fs_extent i_ext;	/* caching a largest extent */
 
-	__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
-
+	union {
+		struct {
+			__le16 i_extra_isize;	/* extra inode attribute size */
+			__le16 i_padding;	/* padding */
+			__le32 i_extra_end[0];	/* for attribute size calculation */
+		};
+		__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
+	};
 	__le32 i_nid[5];		/* direct(2), indirect(2),
 						double_indirect(1) node id */
 } __attribute__((packed));
@@ -909,23 +940,19 @@ struct f2fs_dentry_block {
 	__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
 } __attribute__((packed));
 
+/* for inline stuff */
+#define DEF_INLINE_RESERVED_SIZE	1
+
 /* for inline dir */
-#define NR_INLINE_DENTRY	(MAX_INLINE_DATA * BITS_PER_BYTE / \
+#define NR_INLINE_DENTRY(node)	(MAX_INLINE_DATA(node) * BITS_PER_BYTE / \
 				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
 				BITS_PER_BYTE + 1))
-#define INLINE_DENTRY_BITMAP_SIZE	((NR_INLINE_DENTRY + \
+#define INLINE_DENTRY_BITMAP_SIZE(node)	((NR_INLINE_DENTRY(node) + \
 					BITS_PER_BYTE - 1) / BITS_PER_BYTE)
-#define INLINE_RESERVED_SIZE	(MAX_INLINE_DATA - \
+#define INLINE_RESERVED_SIZE(node)	(MAX_INLINE_DATA(node) - \
 				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
-				NR_INLINE_DENTRY + INLINE_DENTRY_BITMAP_SIZE))
-
-/* inline directory entry structure */
-struct f2fs_inline_dentry {
-	__u8 dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
-	__u8 reserved[INLINE_RESERVED_SIZE];
-	struct f2fs_dir_entry dentry[NR_INLINE_DENTRY];
-	__u8 filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
-} __attribute__((packed));
+				NR_INLINE_DENTRY(node) + \
+				INLINE_DENTRY_BITMAP_SIZE(node)))
 
 /* file types used in inode_info->flags */
 enum FILE_TYPE {
@@ -990,6 +1017,20 @@ extern int dev_read_version(void *, __u64, size_t);
 extern void get_kernel_version(__u8 *);
 f2fs_hash_t f2fs_dentry_hash(const unsigned char *, int);
 
+static inline bool f2fs_has_extra_isize(struct f2fs_inode *inode)
+{
+	return (inode->i_inline & F2FS_EXTRA_ATTR);
+}
+
+static inline int __get_extra_isize(struct f2fs_inode *inode)
+{
+	if (f2fs_has_extra_isize(inode))
+		return le16_to_cpu(inode->i_extra_isize) / sizeof(__le32);
+	return 0;
+}
+
+#define get_extra_isize(node)	__get_extra_isize(&node->i)
+
 #define F2FS_ZONED_NONE		0
 #define F2FS_ZONED_HA		1
 #define F2FS_ZONED_HM		2
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 31836db..a3091bb 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -457,8 +457,8 @@ f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len)
 unsigned int addrs_per_inode(struct f2fs_inode *i)
 {
 	if (i->i_inline & F2FS_INLINE_XATTR)
-		return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS;
-	return DEF_ADDRS_PER_INODE;
+		return CUR_ADDRS_PER_INODE(i) - F2FS_INLINE_XATTR_ADDRS;
+	return CUR_ADDRS_PER_INODE(i);
 }
 
 /*
diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index ff1153a..4f2b403 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -922,10 +922,12 @@ static int f2fs_write_root_inode(void)
 	raw_node->i.i_flags = 0;
 	raw_node->i.i_current_depth = cpu_to_le32(1);
 	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
+	raw_node->i.i_inline = F2FS_EXTRA_ATTR;
+	raw_node->i.i_extra_isize = cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
 
 	data_blk_nor = get_sb(main_blkaddr) +
 		c.cur_seg[CURSEG_HOT_DATA] * c.blks_per_seg;
-	raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor);
+	raw_node->i.i_addr[get_extra_isize(raw_node)] = cpu_to_le32(data_blk_nor);
 
 	raw_node->i.i_ext.fofs = 0;
 	raw_node->i.i_ext.blk_addr = 0;
-- 
2.13.0.90.g1eb437020


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] f2fs-tools: support project quota
  2017-07-16  7:12 [PATCH 1/3] f2fs-tools: spread struct f2fs_dentry_ptr for inline path Chao Yu
  2017-07-16  7:12 ` [PATCH 2/3] f2fs-tools: enhance on-disk inode structure scalability Chao Yu
@ 2017-07-16  7:12 ` Chao Yu
  1 sibling, 0 replies; 5+ messages in thread
From: Chao Yu @ 2017-07-16  7:12 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel

From: Chao Yu <yuchao0@huawei.com>

This patch introduce a new option '-p' for enabling project quota
functionality during mkfs.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/mount.c            | 4 ++++
 include/f2fs_fs.h       | 5 +++++
 lib/libf2fs.c           | 1 +
 mkfs/f2fs_format.c      | 1 +
 mkfs/f2fs_format_main.c | 8 +++++++-
 5 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/fsck/mount.c b/fsck/mount.c
index 693e4a8..b4f8958 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -90,6 +90,7 @@ void print_inode_info(struct f2fs_inode *inode, int name)
 
 	DISP_u16(inode, i_extra_isize);
 	DISP_u16(inode, i_padding);
+	DISP_u32(inode, i_projid);
 
 	DISP_u32(inode, i_addr[ofs]);		/* Pointers to data blocks */
 	DISP_u32(inode, i_addr[ofs + 1]);	/* Pointers to data blocks */
@@ -284,6 +285,9 @@ void print_sb_state(struct f2fs_super_block *sb)
 	if (f & cpu_to_le32(F2FS_FEATURE_BLKZONED)) {
 		MSG(0, "%s", " zoned block device");
 	}
+	if (f & cpu_to_le32(F2FS_FEATURE_PRJQUOTA)) {
+		MSG(0, "%s", " project quota");
+	}
 	MSG(0, "\n");
 	MSG(0, "Info: superblock encrypt level = %d, salt = ",
 					sb->encryption_level);
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 88ceb61..b49b6f5 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -267,6 +267,7 @@ struct f2fs_configuration {
 	int sparse_mode;
 	int zoned_mode;
 	int zoned_model;
+	int project_quota;
 	size_t zone_blocks;
 	double overprovision;
 	double new_overprovision;
@@ -470,6 +471,7 @@ enum {
 
 #define F2FS_FEATURE_ENCRYPT	0x0001
 #define F2FS_FEATURE_BLKZONED	0x0002
+#define F2FS_FEATURE_PRJQUOTA	0x0004
 
 #define MAX_VOLUME_NAME		512
 
@@ -622,6 +624,8 @@ struct f2fs_extent {
 	(offsetof(struct f2fs_inode, i_extra_end) -	\
 	offsetof(struct f2fs_inode, i_extra_isize))	\
 
+#define	F2FS_DEF_PROJID		0	/* default project ID */
+
 #define MAX_INLINE_DATA(node) (sizeof(__le32) *				\
 				(DEF_ADDRS_PER_INODE_INLINE_XATTR -	\
 				get_extra_isize(node) -			\
@@ -677,6 +681,7 @@ struct f2fs_inode {
 		struct {
 			__le16 i_extra_isize;	/* extra inode attribute size */
 			__le16 i_padding;	/* padding */
+			__le32 i_projid;	/* project id */
 			__le32 i_extra_end[0];	/* for attribute size calculation */
 		};
 		__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index a3091bb..c595130 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -557,6 +557,7 @@ void f2fs_init_configuration(void)
 	c.zoned_mode = 0;
 	c.zoned_model = 0;
 	c.zone_blocks = 0;
+	c.project_quota = 0;
 
 	for (i = 0; i < MAX_DEVICES; i++) {
 		memset(&c.devices[i], 0, sizeof(struct device_info));
diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index 4f2b403..ebb9d3c 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -924,6 +924,7 @@ static int f2fs_write_root_inode(void)
 	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
 	raw_node->i.i_inline = F2FS_EXTRA_ATTR;
 	raw_node->i.i_extra_isize = cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
+	raw_node->i.i_projid = cpu_to_le32(F2FS_DEF_PROJID);
 
 	data_blk_nor = get_sb(main_blkaddr) +
 		c.cur_seg[CURSEG_HOT_DATA] * c.blks_per_seg;
diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c
index 5525d1c..4ce075c 100644
--- a/mkfs/f2fs_format_main.c
+++ b/mkfs/f2fs_format_main.c
@@ -88,7 +88,7 @@ static void parse_feature(const char *features)
 
 static void f2fs_parse_options(int argc, char *argv[])
 {
-	static const char *option_string = "qa:c:d:e:l:mo:O:s:S:z:t:f";
+	static const char *option_string = "qa:c:d:e:l:mo:O:p:s:S:z:t:f";
 	int32_t option=0;
 
 	while ((option = getopt(argc,argv,option_string)) != EOF) {
@@ -135,6 +135,9 @@ static void f2fs_parse_options(int argc, char *argv[])
 		case 'O':
 			parse_feature(optarg);
 			break;
+		case 'p':
+			c.project_quota = 1;
+			break;
 		case 's':
 			c.segs_per_sec = atoi(optarg);
 			break;
@@ -180,6 +183,9 @@ static void f2fs_parse_options(int argc, char *argv[])
 
 	if (c.zoned_mode)
 		c.feature |= cpu_to_le32(F2FS_FEATURE_BLKZONED);
+
+	if (c.project_quota)
+		c.feature |= cpu_to_le32(F2FS_FEATURE_PRJQUOTA);
 }
 
 #ifdef HAVE_LIBBLKID
-- 
2.13.0.90.g1eb437020


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/3] f2fs-tools: enhance on-disk inode structure scalability
  2017-07-16  7:12 ` [PATCH 2/3] f2fs-tools: enhance on-disk inode structure scalability Chao Yu
@ 2017-07-17 22:22   ` Jaegeuk Kim
  2017-07-18  1:51     ` Chao Yu
  0 siblings, 1 reply; 5+ messages in thread
From: Jaegeuk Kim @ 2017-07-17 22:22 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-f2fs-devel

Hi Chao,

Nice work!
Looking at a glance, we need to consider backward compatibility where old f2fs
cannot interpret extra i_size. So, we need to add an option to enable this in
order for users to be aware of it.

On 07/16, Chao Yu wrote:
> From: Chao Yu <yuchao0@huawei.com>
> 
> Adjust to change of kernel side:
> 
> This patch add new flag F2FS_EXTRA_ATTR storing in inode.i_inline
> to indicate that on-disk structure of current inode is extended.
> 
> In order to extend, we changed the inode structure a bit:
> 
> Original one:
> 
> struct f2fs_inode {
> 	...
> 	struct f2fs_extent i_ext;
> 	__le32 i_addr[DEF_ADDRS_PER_INODE];
> 	__le32 i_nid[DEF_NIDS_PER_INODE];
> }
> 
> Extended one:
> 
> struct f2fs_inode {
>         ...
>         struct f2fs_extent i_ext;
> 	union {
> 		struct {
> 			__le16 i_extra_isize;
> 			__le16 i_padding;

	union {
		struct {
			__le16 i_extra_isize;	/* extra inode attribute size */
			__le16 i_padding;	/* padding */
			__le32 i_extra_end[0];	/* for attribute size calculation */
		};
		__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
	};

Need to update.

Thanks,

> 		};
> 		__le32 i_addr[DEF_ADDRS_PER_INODE];
> 	};
>         __le32 i_nid[DEF_NIDS_PER_INODE];
> }
> 
> Once F2FS_EXTRA_ATTR is set, we will steal four bytes in the head of
> i_addr field for storing i_extra_isize and i_padding. with i_extra_isize,
> we can calculate actual size of reserved space in i_addr, available
> attribute fields included in total extra attribute fields for current
> inode can be described as below:
> 
>   +--------------------+
>   | .i_mode            |
>   | ...                |
>   | .i_ext             |
>   +--------------------+
>   | .i_extra_isize     |-----+
>   | .i_padding         |     |
>   | .i_prjid           |     |
>   | .i_atime_extra     |     |
>   | .i_ctime_extra     |     |
>   | .i_mtime_extra     |<----+
>   | .i_inode_cs        |<----- store blkaddr/inline from here
>   | .i_xattr_cs        |
>   | ...                |
>   +--------------------+
>   |                    |
>   |    block address   |
>   |                    |
>   +--------------------+
>   | .i_nid             |
>   +--------------------+
>   |   node_footer      |
>   | (nid, ino, offset) |
>   +--------------------+
> 
> Hence, with this patch, we would enhance scalability of f2fs inode for
> storing more newly added attribute.
> 
> Signed-off-by: Chao Yu <yuchao0@huawei.com>
> ---
>  fsck/dir.c         | 48 +++++++++++++++++++---------------
>  fsck/dump.c        |  6 ++---
>  fsck/f2fs.h        |  4 ++-
>  fsck/fsck.c        | 35 +++++++++++++++----------
>  fsck/fsck.h        |  2 +-
>  fsck/mount.c       | 20 ++++++++++-----
>  fsck/node.c        |  6 ++---
>  fsck/node.h        |  7 ++++-
>  fsck/segment.c     |  5 ++--
>  include/f2fs_fs.h  | 75 +++++++++++++++++++++++++++++++++++++++++-------------
>  lib/libf2fs.c      |  4 +--
>  mkfs/f2fs_format.c |  4 ++-
>  12 files changed, 143 insertions(+), 73 deletions(-)
> 
> diff --git a/fsck/dir.c b/fsck/dir.c
> index 62bc7b9..d70183f 100644
> --- a/fsck/dir.c
> +++ b/fsck/dir.c
> @@ -34,7 +34,8 @@ next:
>  
>  }
>  
> -void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
> +void make_dentry_ptr(struct f2fs_dentry_ptr *d, struct f2fs_node *node_blk,
> +							void *src, int type)
>  {
>  	if (type == 1) {
>  		struct f2fs_dentry_block *t = (struct f2fs_dentry_block *)src;
> @@ -44,12 +45,16 @@ void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
>  		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->nr_bitmap = INLINE_DENTRY_BITMAP_SIZE;
> -		d->bitmap = t->dentry_bitmap;
> -		d->dentry = t->dentry;
> -		d->filename = t->filename;
> +		int entry_cnt = NR_INLINE_DENTRY(node_blk);
> +		int bitmap_size = INLINE_DENTRY_BITMAP_SIZE(node_blk);
> +		int reserved_size = INLINE_RESERVED_SIZE(node_blk);
> +
> +		d->max = entry_cnt;
> +		d->nr_bitmap = bitmap_size;
> +		d->bitmap = src;
> +		d->dentry = src + bitmap_size + reserved_size;
> +		d->filename = src + bitmap_size + reserved_size +
> +						SIZE_OF_DIR_ENTRY * entry_cnt;
>  	}
>  }
>  
> @@ -95,7 +100,7 @@ static struct f2fs_dir_entry *find_in_block(void *block,
>  {
>  	struct f2fs_dentry_ptr d;
>  
> -	make_dentry_ptr(&d, block, 1);
> +	make_dentry_ptr(&d, NULL, block, 1);
>  	return find_target_dentry(name, len, namehash, max_slots, &d);
>  }
>  
> @@ -258,7 +263,7 @@ start:
>  	goto start;
>  
>  add_dentry:
> -	make_dentry_ptr(&d, (void *)dentry_blk, 1);
> +	make_dentry_ptr(&d, NULL, (void *)dentry_blk, 1);
>  	f2fs_update_dentry(ino, file_type, &d, name, name_len, dentry_hash, bit_pos);
>  
>  	ret = dev_write_block(dentry_blk, dn.data_blkaddr);
> @@ -338,7 +343,7 @@ static void make_empty_dir(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
>  	ret = dev_write_block(dent_blk, blkaddr);
>  	ASSERT(ret >= 0);
>  
> -	inode->i.i_addr[0] = cpu_to_le32(blkaddr);
> +	inode->i.i_addr[get_extra_isize(inode)] = cpu_to_le32(blkaddr);
>  	free(dent_blk);
>  }
>  
> @@ -355,10 +360,10 @@ static void page_symlink(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
>  	get_node_info(sbi, ino, &ni);
>  
>  	/* store into inline_data */
> -	if (symlen + 1 <= MAX_INLINE_DATA) {
> +	if (symlen + 1 <= MAX_INLINE_DATA(inode)) {
>  		inode->i.i_inline |= F2FS_INLINE_DATA;
>  		inode->i.i_inline |= F2FS_DATA_EXIST;
> -		memcpy(&inode->i.i_addr[1], symname, symlen);
> +		memcpy(inline_data_addr(inode), symname, symlen);
>  		return;
>  	}
>  
> @@ -373,7 +378,7 @@ static void page_symlink(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
>  	ret = dev_write_block(data_blk, blkaddr);
>  	ASSERT(ret >= 0);
>  
> -	inode->i.i_addr[0] = cpu_to_le32(blkaddr);
> +	inode->i.i_addr[get_extra_isize(inode)] = cpu_to_le32(blkaddr);
>  	free(data_blk);
>  }
>  
> @@ -398,7 +403,7 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
>  		ASSERT(de->link);
>  		mode |= S_IFLNK;
>  		size = strlen(de->link);
> -		if (size + 1 > MAX_INLINE_DATA)
> +		if (size + 1 > MAX_INLINE_DATA(node_blk))
>  			blocks++;
>  	} else {
>  		ASSERT(0);
> @@ -421,11 +426,12 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
>  	node_blk->i.i_current_depth = cpu_to_le32(1);
>  	node_blk->i.i_xattr_nid = 0;
>  	node_blk->i.i_flags = 0;
> -	node_blk->i.i_inline = F2FS_INLINE_XATTR;
> +	node_blk->i.i_inline = F2FS_INLINE_XATTR | F2FS_EXTRA_ATTR;
>  	node_blk->i.i_pino = cpu_to_le32(de->pino);
>  	node_blk->i.i_namelen = cpu_to_le32(de->len);
>  	memcpy(node_blk->i.i_name, de->name, de->len);
>  	node_blk->i.i_name[de->len] = 0;
> +	node_blk->i.i_extra_isize = cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
>  
>  	node_blk->footer.ino = cpu_to_le32(de->ino);
>  	node_blk->footer.nid = cpu_to_le32(de->ino);
> @@ -444,7 +450,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>  	struct f2fs_inode *inode = &(node->i);
>  	unsigned int dir_level = node->i.i_dir_level;
>  	nid_t ino = le32_to_cpu(node->footer.ino);
> -	char inline_data[MAX_INLINE_DATA];
> +	char inline_data[MAX_INLINE_DATA(node)];
>  	struct dnode_of_data dn = {0};
>  	struct f2fs_dentry_ptr d;
>  	unsigned long bit_pos = 0;
> @@ -453,8 +459,8 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>  	if (!(inode->i_inline & F2FS_INLINE_DENTRY))
>  		return 0;
>  
> -	memcpy(inline_data, inline_data_addr(node), MAX_INLINE_DATA);
> -	memset(inline_data_addr(node), 0, MAX_INLINE_DATA);
> +	memcpy(inline_data, inline_data_addr(node), MAX_INLINE_DATA(node));
> +	memset(inline_data_addr(node), 0, MAX_INLINE_DATA(node));
>  	inode->i_inline &= ~F2FS_INLINE_DENTRY;
>  
>  	ret = dev_write_block(node, p_blkaddr);
> @@ -472,8 +478,8 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>  		if (dn.data_blkaddr == NULL_ADDR)
>  			new_data_block(sbi, dentry_blk, &dn, CURSEG_HOT_DATA);
>  
> -		make_dentry_ptr(&src, (void *)inline_data, 2);
> -		make_dentry_ptr(&dst, (void *)dentry_blk, 1);
> +		make_dentry_ptr(&src, node, (void *)inline_data, 2);
> +		make_dentry_ptr(&dst, NULL, (void *)dentry_blk, 1);
>  
>  		 /* copy data from inline dentry block to new dentry block */
>  		memcpy(dst.bitmap, src.bitmap, src.nr_bitmap);
> @@ -493,7 +499,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>  	}
>  
>  	make_empty_dir(sbi, node);
> -	make_dentry_ptr(&d, (void *)inline_data, 2);
> +	make_dentry_ptr(&d, node, (void *)inline_data, 2);
>  
>  	while (bit_pos < d.max) {
>  		struct f2fs_dir_entry *de;
> diff --git a/fsck/dump.c b/fsck/dump.c
> index 22e2265..128dc53 100644
> --- a/fsck/dump.c
> +++ b/fsck/dump.c
> @@ -322,14 +322,14 @@ static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>  		DBG(3, "ino[0x%x] has inline data!\n", nid);
>  		/* recover from inline data */
>  		dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
> -							0, MAX_INLINE_DATA);
> +						0, MAX_INLINE_DATA(node_blk));
>  		return;
>  	}
>  
>  	/* check data blocks in inode */
>  	for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
> -		dump_data_blk(sbi, ofs * F2FS_BLKSIZE,
> -				le32_to_cpu(node_blk->i.i_addr[i]));
> +		dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu(
> +			node_blk->i.i_addr[get_extra_isize(node_blk) + i]));
>  
>  	/* check node blocks in inode */
>  	for (i = 0; i < 5; i++) {
> diff --git a/fsck/f2fs.h b/fsck/f2fs.h
> index d1626e3..871cffc 100644
> --- a/fsck/f2fs.h
> +++ b/fsck/f2fs.h
> @@ -233,7 +233,9 @@ static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
>  
>  static inline void *inline_data_addr(struct f2fs_node *node_blk)
>  {
> -	return (void *)&(node_blk->i.i_addr[1]);
> +	int ofs = get_extra_isize(node_blk) + DEF_INLINE_RESERVED_SIZE;
> +
> +	return (void *)&(node_blk->i.i_addr[ofs]);
>  }
>  
>  static inline unsigned int ofs_of_node(struct f2fs_node *node_blk)
> diff --git a/fsck/fsck.c b/fsck/fsck.c
> index 84196cf..7a81855 100644
> --- a/fsck/fsck.c
> +++ b/fsck/fsck.c
> @@ -226,10 +226,13 @@ static int is_valid_summary(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
>  		goto out;
>  
>  	/* check its block address */
> -	if (node_blk->footer.nid == node_blk->footer.ino)
> -		target_blk_addr = node_blk->i.i_addr[ofs_in_node];
> -	else
> +	if (node_blk->footer.nid == node_blk->footer.ino) {
> +		int ofs = get_extra_isize(node_blk);
> +
> +		target_blk_addr = node_blk->i.i_addr[ofs + ofs_in_node];
> +	} else {
>  		target_blk_addr = node_blk->dn.addr[ofs_in_node];
> +	}
>  
>  	if (blk_addr == le32_to_cpu(target_blk_addr))
>  		ret = 1;
> @@ -658,20 +661,22 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>  		goto check;
>  
>  	if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
> -		if (le32_to_cpu(node_blk->i.i_addr[0]) != 0) {
> +		int ofs = get_extra_isize(node_blk);
> +
> +		if (le32_to_cpu(node_blk->i.i_addr[ofs]) != 0) {
>  			/* should fix this bug all the time */
>  			FIX_MSG("inline_data has wrong 0'th block = %x",
> -					le32_to_cpu(node_blk->i.i_addr[0]));
> -			node_blk->i.i_addr[0] = 0;
> +					le32_to_cpu(node_blk->i.i_addr[ofs]));
> +			node_blk->i.i_addr[ofs] = 0;
>  			node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
>  			need_fix = 1;
>  		}
>  		if (!(node_blk->i.i_inline & F2FS_DATA_EXIST)) {
> -			char buf[MAX_INLINE_DATA];
> -			memset(buf, 0, MAX_INLINE_DATA);
> +			char buf[MAX_INLINE_DATA(node_blk)];
> +			memset(buf, 0, MAX_INLINE_DATA(node_blk));
>  
> -			if (memcmp(buf, &node_blk->i.i_addr[1],
> -							MAX_INLINE_DATA)) {
> +			if (memcmp(buf, inline_data_addr(node_blk),
> +						MAX_INLINE_DATA(node_blk))) {
>  				FIX_MSG("inline_data has DATA_EXIST");
>  				node_blk->i.i_inline |= F2FS_DATA_EXIST;
>  				need_fix = 1;
> @@ -710,7 +715,8 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>  	/* check data blocks in inode */
>  	for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i);
>  						idx++, child.pgofs++) {
> -		block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[idx]);
> +		int ofs = get_extra_isize(node_blk);
> +		block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[ofs + idx]);
>  
>  		/* check extent info */
>  		check_extent_info(&child, blkaddr, 0);
> @@ -724,9 +730,10 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>  			if (!ret) {
>  				*blk_cnt = *blk_cnt + 1;
>  			} else if (c.fix_on) {
> -				node_blk->i.i_addr[idx] = 0;
> +				node_blk->i.i_addr[ofs + idx] = 0;
>  				need_fix = 1;
> -				FIX_MSG("[0x%x] i_addr[%d] = 0", nid, idx);
> +				FIX_MSG("[0x%x] i_addr[%d] = 0",
> +							nid, ofs + idx);
>  			}
>  		}
>  	}
> @@ -1362,7 +1369,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
>  	inline_dentry = inline_data_addr(node_blk);
>  	ASSERT(inline_dentry != NULL);
>  
> -	make_dentry_ptr(&d, inline_dentry, 2);
> +	make_dentry_ptr(&d, node_blk, inline_dentry, 2);
>  
>  	fsck->dentry_depth++;
>  	dentries = __chk_dentries(sbi, child,
> diff --git a/fsck/fsck.h b/fsck/fsck.h
> index 5d2cfd6..1e8ed0b 100644
> --- a/fsck/fsck.h
> +++ b/fsck/fsck.h
> @@ -221,7 +221,7 @@ block_t new_node_block(struct f2fs_sb_info *,
>  					struct dnode_of_data *, unsigned int);
>  void get_dnode_of_data(struct f2fs_sb_info *, struct dnode_of_data *,
>  					pgoff_t, int);
> -void make_dentry_ptr(struct f2fs_dentry_ptr *, void *, int);
> +void make_dentry_ptr(struct f2fs_dentry_ptr *, struct f2fs_node *, void *, int);
>  int f2fs_create(struct f2fs_sb_info *, struct dentry *);
>  int f2fs_mkdir(struct f2fs_sb_info *, struct dentry *);
>  int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
> diff --git a/fsck/mount.c b/fsck/mount.c
> index a0b0bea..693e4a8 100644
> --- a/fsck/mount.c
> +++ b/fsck/mount.c
> @@ -41,6 +41,7 @@ void print_inode_info(struct f2fs_inode *inode, int name)
>  	unsigned int i = 0;
>  	int namelen = le32_to_cpu(inode->i_namelen);
>  	int enc_name = file_enc_name(inode);
> +	int ofs = __get_extra_isize(inode);
>  
>  	namelen = convert_encrypted_name(inode->i_name, namelen, en, enc_name);
>  	en[namelen] = '\0';
> @@ -87,12 +88,15 @@ void print_inode_info(struct f2fs_inode *inode, int name)
>  			le32_to_cpu(inode->i_ext.blk_addr),
>  			le32_to_cpu(inode->i_ext.len));
>  
> -	DISP_u32(inode, i_addr[0]);	/* Pointers to data blocks */
> -	DISP_u32(inode, i_addr[1]);	/* Pointers to data blocks */
> -	DISP_u32(inode, i_addr[2]);	/* Pointers to data blocks */
> -	DISP_u32(inode, i_addr[3]);	/* Pointers to data blocks */
> +	DISP_u16(inode, i_extra_isize);
> +	DISP_u16(inode, i_padding);
>  
> -	for (i = 4; i < ADDRS_PER_INODE(inode); i++) {
> +	DISP_u32(inode, i_addr[ofs]);		/* Pointers to data blocks */
> +	DISP_u32(inode, i_addr[ofs + 1]);	/* Pointers to data blocks */
> +	DISP_u32(inode, i_addr[ofs + 2]);	/* Pointers to data blocks */
> +	DISP_u32(inode, i_addr[ofs + 3]);	/* Pointers to data blocks */
> +
> +	for (i = ofs + 4; i < ADDRS_PER_INODE(inode); i++) {
>  		if (inode->i_addr[i] != 0x0) {
>  			printf("i_addr[0x%x] points data block\r\t\t[0x%4x]\n",
>  					i, le32_to_cpu(inode->i_addr[i]));
> @@ -1357,8 +1361,10 @@ void update_data_blkaddr(struct f2fs_sb_info *sbi, nid_t nid,
>  
>  	/* check its block address */
>  	if (node_blk->footer.nid == node_blk->footer.ino) {
> -		oldaddr = le32_to_cpu(node_blk->i.i_addr[ofs_in_node]);
> -		node_blk->i.i_addr[ofs_in_node] = cpu_to_le32(newaddr);
> +		int ofs = get_extra_isize(node_blk);
> +
> +		oldaddr = le32_to_cpu(node_blk->i.i_addr[ofs + ofs_in_node]);
> +		node_blk->i.i_addr[ofs + ofs_in_node] = cpu_to_le32(newaddr);
>  	} else {
>  		oldaddr = le32_to_cpu(node_blk->dn.addr[ofs_in_node]);
>  		node_blk->dn.addr[ofs_in_node] = cpu_to_le32(newaddr);
> diff --git a/fsck/node.c b/fsck/node.c
> index fe923e5..e37b817 100644
> --- a/fsck/node.c
> +++ b/fsck/node.c
> @@ -105,10 +105,10 @@ block_t new_node_block(struct f2fs_sb_info *sbi,
>   *
>   * By default, it sets inline_xattr and inline_data
>   */
> -static int get_node_path(unsigned long block,
> +static int get_node_path(struct f2fs_node *node, unsigned long block,
>  				int offset[4], unsigned int noffset[4])
>  {
> -	const long direct_index = DEF_ADDRS_PER_INODE_INLINE_XATTR;
> +	const long direct_index = ADDRS_PER_INODE(&node->i);
>  	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;
> @@ -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(index, offset, noffset);
> +	level = get_node_path(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 721e5b7..cbf7ed7 100644
> --- a/fsck/node.h
> +++ b/fsck/node.h
> @@ -26,9 +26,14 @@ static inline int IS_INODE(struct f2fs_node *node)
>  	return ((node)->footer.nid == (node)->footer.ino);
>  }
>  
> +static inline __le32 *blkaddr_in_inode(struct f2fs_node *node)
> +{
> +	return node->i.i_addr + get_extra_isize(node);
> +}
> +
>  static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
>  {
> -	return IS_INODE(node) ? node->i.i_addr : node->dn.addr;
> +	return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr;
>  }
>  
>  static inline block_t datablock_addr(struct f2fs_node *node_page,
> diff --git a/fsck/segment.c b/fsck/segment.c
> index 6b2f6c1..e21339b 100644
> --- a/fsck/segment.c
> +++ b/fsck/segment.c
> @@ -179,7 +179,7 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
>  	}
>  
>  	/* inline_data support */
> -	if (de->size <= MAX_INLINE_DATA) {
> +	if (de->size <= DEF_MAX_INLINE_DATA) {
>  		struct node_info ni;
>  		struct f2fs_node *node_blk;
>  		int ret;
> @@ -194,9 +194,10 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
>  
>  		node_blk->i.i_inline |= F2FS_INLINE_DATA;
>  		node_blk->i.i_inline |= F2FS_DATA_EXIST;
> +		node_blk->i.i_inline |= F2FS_EXTRA_ATTR;
>  		n = read(fd, buffer, BLOCK_SZ);
>  		ASSERT(n == de->size);
> -		memcpy(&node_blk->i.i_addr[1], buffer, de->size);
> +		memcpy(inline_data_addr(node_blk), buffer, de->size);
>  
>  		node_blk->i.i_size = cpu_to_le64(de->size);
>  
> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
> index dd2635b..88ceb61 100644
> --- a/include/f2fs_fs.h
> +++ b/include/f2fs_fs.h
> @@ -167,6 +167,14 @@ static inline uint64_t bswap_64(uint64_t val)
>  		printf("%-30s" fmt, #member, ((ptr)->member));	\
>  	} while (0)
>  
> +#define DISP_u16(ptr, member)						\
> +	do {								\
> +		assert(sizeof((ptr)->member) == 2);			\
> +		printf("%-30s" "\t\t[0x%8x : %u]\n",			\
> +			#member, le16_to_cpu(((ptr)->member)),		\
> +			le16_to_cpu(((ptr)->member)));			\
> +	} while (0)
> +
>  #define DISP_u32(ptr, member)						\
>  	do {								\
>  		assert(sizeof((ptr)->member) <= 4);			\
> @@ -585,6 +593,8 @@ struct f2fs_extent {
>  #define F2FS_NAME_LEN		255
>  #define F2FS_INLINE_XATTR_ADDRS	50	/* 200 bytes for inline xattrs */
>  #define DEF_ADDRS_PER_INODE	923	/* Address Pointers in an Inode */
> +#define CUR_ADDRS_PER_INODE(inode)	(DEF_ADDRS_PER_INODE - \
> +					__get_extra_isize(inode))
>  #define ADDRS_PER_INODE(i)	addrs_per_inode(i)
>  #define DEF_ADDRS_PER_INODE_INLINE_XATTR				\
>  		(DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS)
> @@ -602,12 +612,27 @@ struct f2fs_extent {
>  #define F2FS_INLINE_DENTRY	0x04	/* file inline dentry flag */
>  #define F2FS_DATA_EXIST		0x08	/* file inline data exist flag */
>  #define F2FS_INLINE_DOTS	0x10	/* file having implicit dot dentries */
> +#define F2FS_EXTRA_ATTR		0x20	/* file having extra attribute */
>  
> -#define MAX_INLINE_DATA (sizeof(__le32) *				\
> -			(DEF_ADDRS_PER_INODE_INLINE_XATTR - 1))
> +#if !defined(offsetof)
> +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
> +#endif
>  
> +#define F2FS_TOTAL_EXTRA_ATTR_SIZE			\
> +	(offsetof(struct f2fs_inode, i_extra_end) -	\
> +	offsetof(struct f2fs_inode, i_extra_isize))	\
> +
> +#define MAX_INLINE_DATA(node) (sizeof(__le32) *				\
> +				(DEF_ADDRS_PER_INODE_INLINE_XATTR -	\
> +				get_extra_isize(node) -			\
> +				DEF_INLINE_RESERVED_SIZE))
> +#define DEF_MAX_INLINE_DATA	(sizeof(__le32) *			\
> +				(DEF_ADDRS_PER_INODE_INLINE_XATTR -	\
> +				F2FS_TOTAL_EXTRA_ATTR_SIZE -		\
> +				DEF_INLINE_RESERVED_SIZE))
>  #define INLINE_DATA_OFFSET	(PAGE_CACHE_SIZE - sizeof(struct node_footer) \
> -				- sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1))
> +				- sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - \
> +				DEF_INLINE_RESERVED_SIZE))
>  
>  #define DEF_DIR_LEVEL		0
>  
> @@ -648,8 +673,14 @@ struct f2fs_inode {
>  
>  	struct f2fs_extent i_ext;	/* caching a largest extent */
>  
> -	__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
> -
> +	union {
> +		struct {
> +			__le16 i_extra_isize;	/* extra inode attribute size */
> +			__le16 i_padding;	/* padding */
> +			__le32 i_extra_end[0];	/* for attribute size calculation */
> +		};
> +		__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
> +	};
>  	__le32 i_nid[5];		/* direct(2), indirect(2),
>  						double_indirect(1) node id */
>  } __attribute__((packed));
> @@ -909,23 +940,19 @@ struct f2fs_dentry_block {
>  	__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
>  } __attribute__((packed));
>  
> +/* for inline stuff */
> +#define DEF_INLINE_RESERVED_SIZE	1
> +
>  /* for inline dir */
> -#define NR_INLINE_DENTRY	(MAX_INLINE_DATA * BITS_PER_BYTE / \
> +#define NR_INLINE_DENTRY(node)	(MAX_INLINE_DATA(node) * BITS_PER_BYTE / \
>  				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
>  				BITS_PER_BYTE + 1))
> -#define INLINE_DENTRY_BITMAP_SIZE	((NR_INLINE_DENTRY + \
> +#define INLINE_DENTRY_BITMAP_SIZE(node)	((NR_INLINE_DENTRY(node) + \
>  					BITS_PER_BYTE - 1) / BITS_PER_BYTE)
> -#define INLINE_RESERVED_SIZE	(MAX_INLINE_DATA - \
> +#define INLINE_RESERVED_SIZE(node)	(MAX_INLINE_DATA(node) - \
>  				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
> -				NR_INLINE_DENTRY + INLINE_DENTRY_BITMAP_SIZE))
> -
> -/* inline directory entry structure */
> -struct f2fs_inline_dentry {
> -	__u8 dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
> -	__u8 reserved[INLINE_RESERVED_SIZE];
> -	struct f2fs_dir_entry dentry[NR_INLINE_DENTRY];
> -	__u8 filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
> -} __attribute__((packed));
> +				NR_INLINE_DENTRY(node) + \
> +				INLINE_DENTRY_BITMAP_SIZE(node)))
>  
>  /* file types used in inode_info->flags */
>  enum FILE_TYPE {
> @@ -990,6 +1017,20 @@ extern int dev_read_version(void *, __u64, size_t);
>  extern void get_kernel_version(__u8 *);
>  f2fs_hash_t f2fs_dentry_hash(const unsigned char *, int);
>  
> +static inline bool f2fs_has_extra_isize(struct f2fs_inode *inode)
> +{
> +	return (inode->i_inline & F2FS_EXTRA_ATTR);
> +}
> +
> +static inline int __get_extra_isize(struct f2fs_inode *inode)
> +{
> +	if (f2fs_has_extra_isize(inode))
> +		return le16_to_cpu(inode->i_extra_isize) / sizeof(__le32);
> +	return 0;
> +}
> +
> +#define get_extra_isize(node)	__get_extra_isize(&node->i)
> +
>  #define F2FS_ZONED_NONE		0
>  #define F2FS_ZONED_HA		1
>  #define F2FS_ZONED_HM		2
> diff --git a/lib/libf2fs.c b/lib/libf2fs.c
> index 31836db..a3091bb 100644
> --- a/lib/libf2fs.c
> +++ b/lib/libf2fs.c
> @@ -457,8 +457,8 @@ f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len)
>  unsigned int addrs_per_inode(struct f2fs_inode *i)
>  {
>  	if (i->i_inline & F2FS_INLINE_XATTR)
> -		return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS;
> -	return DEF_ADDRS_PER_INODE;
> +		return CUR_ADDRS_PER_INODE(i) - F2FS_INLINE_XATTR_ADDRS;
> +	return CUR_ADDRS_PER_INODE(i);
>  }
>  
>  /*
> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
> index ff1153a..4f2b403 100644
> --- a/mkfs/f2fs_format.c
> +++ b/mkfs/f2fs_format.c
> @@ -922,10 +922,12 @@ static int f2fs_write_root_inode(void)
>  	raw_node->i.i_flags = 0;
>  	raw_node->i.i_current_depth = cpu_to_le32(1);
>  	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
> +	raw_node->i.i_inline = F2FS_EXTRA_ATTR;
> +	raw_node->i.i_extra_isize = cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
>  
>  	data_blk_nor = get_sb(main_blkaddr) +
>  		c.cur_seg[CURSEG_HOT_DATA] * c.blks_per_seg;
> -	raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor);
> +	raw_node->i.i_addr[get_extra_isize(raw_node)] = cpu_to_le32(data_blk_nor);
>  
>  	raw_node->i.i_ext.fofs = 0;
>  	raw_node->i.i_ext.blk_addr = 0;
> -- 
> 2.13.0.90.g1eb437020

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/3] f2fs-tools: enhance on-disk inode structure scalability
  2017-07-17 22:22   ` Jaegeuk Kim
@ 2017-07-18  1:51     ` Chao Yu
  0 siblings, 0 replies; 5+ messages in thread
From: Chao Yu @ 2017-07-18  1:51 UTC (permalink / raw)
  To: Jaegeuk Kim, Chao Yu; +Cc: linux-f2fs-devel

Hi Jaegeuk,

On 2017/7/18 6:22, Jaegeuk Kim wrote:
> Hi Chao,
> 
> Nice work!
> Looking at a glance, we need to consider backward compatibility where old f2fs
> cannot interpret extra i_size. So, we need to add an option to enable this in
> order for users to be aware of it.

OK, let me add F2FS_FEATURE_EXTRA_ATTR feature flag in superblock if user use
'-e' option during mkfs.f2fs. In kernel side, we can create inode with new
format which has F2FS_EXTRA_ATTR flag if F2FS_FEATURE_EXTRA_ATTR is set.

> 
> On 07/16, Chao Yu wrote:
>> From: Chao Yu <yuchao0@huawei.com>
>>
>> Adjust to change of kernel side:
>>
>> This patch add new flag F2FS_EXTRA_ATTR storing in inode.i_inline
>> to indicate that on-disk structure of current inode is extended.
>>
>> In order to extend, we changed the inode structure a bit:
>>
>> Original one:
>>
>> struct f2fs_inode {
>> 	...
>> 	struct f2fs_extent i_ext;
>> 	__le32 i_addr[DEF_ADDRS_PER_INODE];
>> 	__le32 i_nid[DEF_NIDS_PER_INODE];
>> }
>>
>> Extended one:
>>
>> struct f2fs_inode {
>>         ...
>>         struct f2fs_extent i_ext;
>> 	union {
>> 		struct {
>> 			__le16 i_extra_isize;
>> 			__le16 i_padding;
> 
> 	union {
> 		struct {
> 			__le16 i_extra_isize;	/* extra inode attribute size */
> 			__le16 i_padding;	/* padding */
> 			__le32 i_extra_end[0];	/* for attribute size calculation */
> 		};
> 		__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
> 	};
> 
> Need to update.

Will do.

Thanks,

> 
> Thanks,
> 
>> 		};
>> 		__le32 i_addr[DEF_ADDRS_PER_INODE];
>> 	};
>>         __le32 i_nid[DEF_NIDS_PER_INODE];
>> }
>>
>> Once F2FS_EXTRA_ATTR is set, we will steal four bytes in the head of
>> i_addr field for storing i_extra_isize and i_padding. with i_extra_isize,
>> we can calculate actual size of reserved space in i_addr, available
>> attribute fields included in total extra attribute fields for current
>> inode can be described as below:
>>
>>   +--------------------+
>>   | .i_mode            |
>>   | ...                |
>>   | .i_ext             |
>>   +--------------------+
>>   | .i_extra_isize     |-----+
>>   | .i_padding         |     |
>>   | .i_prjid           |     |
>>   | .i_atime_extra     |     |
>>   | .i_ctime_extra     |     |
>>   | .i_mtime_extra     |<----+
>>   | .i_inode_cs        |<----- store blkaddr/inline from here
>>   | .i_xattr_cs        |
>>   | ...                |
>>   +--------------------+
>>   |                    |
>>   |    block address   |
>>   |                    |
>>   +--------------------+
>>   | .i_nid             |
>>   +--------------------+
>>   |   node_footer      |
>>   | (nid, ino, offset) |
>>   +--------------------+
>>
>> Hence, with this patch, we would enhance scalability of f2fs inode for
>> storing more newly added attribute.
>>
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>>  fsck/dir.c         | 48 +++++++++++++++++++---------------
>>  fsck/dump.c        |  6 ++---
>>  fsck/f2fs.h        |  4 ++-
>>  fsck/fsck.c        | 35 +++++++++++++++----------
>>  fsck/fsck.h        |  2 +-
>>  fsck/mount.c       | 20 ++++++++++-----
>>  fsck/node.c        |  6 ++---
>>  fsck/node.h        |  7 ++++-
>>  fsck/segment.c     |  5 ++--
>>  include/f2fs_fs.h  | 75 +++++++++++++++++++++++++++++++++++++++++-------------
>>  lib/libf2fs.c      |  4 +--
>>  mkfs/f2fs_format.c |  4 ++-
>>  12 files changed, 143 insertions(+), 73 deletions(-)
>>
>> diff --git a/fsck/dir.c b/fsck/dir.c
>> index 62bc7b9..d70183f 100644
>> --- a/fsck/dir.c
>> +++ b/fsck/dir.c
>> @@ -34,7 +34,8 @@ next:
>>  
>>  }
>>  
>> -void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
>> +void make_dentry_ptr(struct f2fs_dentry_ptr *d, struct f2fs_node *node_blk,
>> +							void *src, int type)
>>  {
>>  	if (type == 1) {
>>  		struct f2fs_dentry_block *t = (struct f2fs_dentry_block *)src;
>> @@ -44,12 +45,16 @@ void make_dentry_ptr(struct f2fs_dentry_ptr *d, void *src, int type)
>>  		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->nr_bitmap = INLINE_DENTRY_BITMAP_SIZE;
>> -		d->bitmap = t->dentry_bitmap;
>> -		d->dentry = t->dentry;
>> -		d->filename = t->filename;
>> +		int entry_cnt = NR_INLINE_DENTRY(node_blk);
>> +		int bitmap_size = INLINE_DENTRY_BITMAP_SIZE(node_blk);
>> +		int reserved_size = INLINE_RESERVED_SIZE(node_blk);
>> +
>> +		d->max = entry_cnt;
>> +		d->nr_bitmap = bitmap_size;
>> +		d->bitmap = src;
>> +		d->dentry = src + bitmap_size + reserved_size;
>> +		d->filename = src + bitmap_size + reserved_size +
>> +						SIZE_OF_DIR_ENTRY * entry_cnt;
>>  	}
>>  }
>>  
>> @@ -95,7 +100,7 @@ static struct f2fs_dir_entry *find_in_block(void *block,
>>  {
>>  	struct f2fs_dentry_ptr d;
>>  
>> -	make_dentry_ptr(&d, block, 1);
>> +	make_dentry_ptr(&d, NULL, block, 1);
>>  	return find_target_dentry(name, len, namehash, max_slots, &d);
>>  }
>>  
>> @@ -258,7 +263,7 @@ start:
>>  	goto start;
>>  
>>  add_dentry:
>> -	make_dentry_ptr(&d, (void *)dentry_blk, 1);
>> +	make_dentry_ptr(&d, NULL, (void *)dentry_blk, 1);
>>  	f2fs_update_dentry(ino, file_type, &d, name, name_len, dentry_hash, bit_pos);
>>  
>>  	ret = dev_write_block(dentry_blk, dn.data_blkaddr);
>> @@ -338,7 +343,7 @@ static void make_empty_dir(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
>>  	ret = dev_write_block(dent_blk, blkaddr);
>>  	ASSERT(ret >= 0);
>>  
>> -	inode->i.i_addr[0] = cpu_to_le32(blkaddr);
>> +	inode->i.i_addr[get_extra_isize(inode)] = cpu_to_le32(blkaddr);
>>  	free(dent_blk);
>>  }
>>  
>> @@ -355,10 +360,10 @@ static void page_symlink(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
>>  	get_node_info(sbi, ino, &ni);
>>  
>>  	/* store into inline_data */
>> -	if (symlen + 1 <= MAX_INLINE_DATA) {
>> +	if (symlen + 1 <= MAX_INLINE_DATA(inode)) {
>>  		inode->i.i_inline |= F2FS_INLINE_DATA;
>>  		inode->i.i_inline |= F2FS_DATA_EXIST;
>> -		memcpy(&inode->i.i_addr[1], symname, symlen);
>> +		memcpy(inline_data_addr(inode), symname, symlen);
>>  		return;
>>  	}
>>  
>> @@ -373,7 +378,7 @@ static void page_symlink(struct f2fs_sb_info *sbi, struct f2fs_node *inode,
>>  	ret = dev_write_block(data_blk, blkaddr);
>>  	ASSERT(ret >= 0);
>>  
>> -	inode->i.i_addr[0] = cpu_to_le32(blkaddr);
>> +	inode->i.i_addr[get_extra_isize(inode)] = cpu_to_le32(blkaddr);
>>  	free(data_blk);
>>  }
>>  
>> @@ -398,7 +403,7 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
>>  		ASSERT(de->link);
>>  		mode |= S_IFLNK;
>>  		size = strlen(de->link);
>> -		if (size + 1 > MAX_INLINE_DATA)
>> +		if (size + 1 > MAX_INLINE_DATA(node_blk))
>>  			blocks++;
>>  	} else {
>>  		ASSERT(0);
>> @@ -421,11 +426,12 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
>>  	node_blk->i.i_current_depth = cpu_to_le32(1);
>>  	node_blk->i.i_xattr_nid = 0;
>>  	node_blk->i.i_flags = 0;
>> -	node_blk->i.i_inline = F2FS_INLINE_XATTR;
>> +	node_blk->i.i_inline = F2FS_INLINE_XATTR | F2FS_EXTRA_ATTR;
>>  	node_blk->i.i_pino = cpu_to_le32(de->pino);
>>  	node_blk->i.i_namelen = cpu_to_le32(de->len);
>>  	memcpy(node_blk->i.i_name, de->name, de->len);
>>  	node_blk->i.i_name[de->len] = 0;
>> +	node_blk->i.i_extra_isize = cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
>>  
>>  	node_blk->footer.ino = cpu_to_le32(de->ino);
>>  	node_blk->footer.nid = cpu_to_le32(de->ino);
>> @@ -444,7 +450,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>>  	struct f2fs_inode *inode = &(node->i);
>>  	unsigned int dir_level = node->i.i_dir_level;
>>  	nid_t ino = le32_to_cpu(node->footer.ino);
>> -	char inline_data[MAX_INLINE_DATA];
>> +	char inline_data[MAX_INLINE_DATA(node)];
>>  	struct dnode_of_data dn = {0};
>>  	struct f2fs_dentry_ptr d;
>>  	unsigned long bit_pos = 0;
>> @@ -453,8 +459,8 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>>  	if (!(inode->i_inline & F2FS_INLINE_DENTRY))
>>  		return 0;
>>  
>> -	memcpy(inline_data, inline_data_addr(node), MAX_INLINE_DATA);
>> -	memset(inline_data_addr(node), 0, MAX_INLINE_DATA);
>> +	memcpy(inline_data, inline_data_addr(node), MAX_INLINE_DATA(node));
>> +	memset(inline_data_addr(node), 0, MAX_INLINE_DATA(node));
>>  	inode->i_inline &= ~F2FS_INLINE_DENTRY;
>>  
>>  	ret = dev_write_block(node, p_blkaddr);
>> @@ -472,8 +478,8 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>>  		if (dn.data_blkaddr == NULL_ADDR)
>>  			new_data_block(sbi, dentry_blk, &dn, CURSEG_HOT_DATA);
>>  
>> -		make_dentry_ptr(&src, (void *)inline_data, 2);
>> -		make_dentry_ptr(&dst, (void *)dentry_blk, 1);
>> +		make_dentry_ptr(&src, node, (void *)inline_data, 2);
>> +		make_dentry_ptr(&dst, NULL, (void *)dentry_blk, 1);
>>  
>>  		 /* copy data from inline dentry block to new dentry block */
>>  		memcpy(dst.bitmap, src.bitmap, src.nr_bitmap);
>> @@ -493,7 +499,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
>>  	}
>>  
>>  	make_empty_dir(sbi, node);
>> -	make_dentry_ptr(&d, (void *)inline_data, 2);
>> +	make_dentry_ptr(&d, node, (void *)inline_data, 2);
>>  
>>  	while (bit_pos < d.max) {
>>  		struct f2fs_dir_entry *de;
>> diff --git a/fsck/dump.c b/fsck/dump.c
>> index 22e2265..128dc53 100644
>> --- a/fsck/dump.c
>> +++ b/fsck/dump.c
>> @@ -322,14 +322,14 @@ static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>>  		DBG(3, "ino[0x%x] has inline data!\n", nid);
>>  		/* recover from inline data */
>>  		dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
>> -							0, MAX_INLINE_DATA);
>> +						0, MAX_INLINE_DATA(node_blk));
>>  		return;
>>  	}
>>  
>>  	/* check data blocks in inode */
>>  	for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
>> -		dump_data_blk(sbi, ofs * F2FS_BLKSIZE,
>> -				le32_to_cpu(node_blk->i.i_addr[i]));
>> +		dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu(
>> +			node_blk->i.i_addr[get_extra_isize(node_blk) + i]));
>>  
>>  	/* check node blocks in inode */
>>  	for (i = 0; i < 5; i++) {
>> diff --git a/fsck/f2fs.h b/fsck/f2fs.h
>> index d1626e3..871cffc 100644
>> --- a/fsck/f2fs.h
>> +++ b/fsck/f2fs.h
>> @@ -233,7 +233,9 @@ static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
>>  
>>  static inline void *inline_data_addr(struct f2fs_node *node_blk)
>>  {
>> -	return (void *)&(node_blk->i.i_addr[1]);
>> +	int ofs = get_extra_isize(node_blk) + DEF_INLINE_RESERVED_SIZE;
>> +
>> +	return (void *)&(node_blk->i.i_addr[ofs]);
>>  }
>>  
>>  static inline unsigned int ofs_of_node(struct f2fs_node *node_blk)
>> diff --git a/fsck/fsck.c b/fsck/fsck.c
>> index 84196cf..7a81855 100644
>> --- a/fsck/fsck.c
>> +++ b/fsck/fsck.c
>> @@ -226,10 +226,13 @@ static int is_valid_summary(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
>>  		goto out;
>>  
>>  	/* check its block address */
>> -	if (node_blk->footer.nid == node_blk->footer.ino)
>> -		target_blk_addr = node_blk->i.i_addr[ofs_in_node];
>> -	else
>> +	if (node_blk->footer.nid == node_blk->footer.ino) {
>> +		int ofs = get_extra_isize(node_blk);
>> +
>> +		target_blk_addr = node_blk->i.i_addr[ofs + ofs_in_node];
>> +	} else {
>>  		target_blk_addr = node_blk->dn.addr[ofs_in_node];
>> +	}
>>  
>>  	if (blk_addr == le32_to_cpu(target_blk_addr))
>>  		ret = 1;
>> @@ -658,20 +661,22 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>>  		goto check;
>>  
>>  	if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
>> -		if (le32_to_cpu(node_blk->i.i_addr[0]) != 0) {
>> +		int ofs = get_extra_isize(node_blk);
>> +
>> +		if (le32_to_cpu(node_blk->i.i_addr[ofs]) != 0) {
>>  			/* should fix this bug all the time */
>>  			FIX_MSG("inline_data has wrong 0'th block = %x",
>> -					le32_to_cpu(node_blk->i.i_addr[0]));
>> -			node_blk->i.i_addr[0] = 0;
>> +					le32_to_cpu(node_blk->i.i_addr[ofs]));
>> +			node_blk->i.i_addr[ofs] = 0;
>>  			node_blk->i.i_blocks = cpu_to_le64(*blk_cnt);
>>  			need_fix = 1;
>>  		}
>>  		if (!(node_blk->i.i_inline & F2FS_DATA_EXIST)) {
>> -			char buf[MAX_INLINE_DATA];
>> -			memset(buf, 0, MAX_INLINE_DATA);
>> +			char buf[MAX_INLINE_DATA(node_blk)];
>> +			memset(buf, 0, MAX_INLINE_DATA(node_blk));
>>  
>> -			if (memcmp(buf, &node_blk->i.i_addr[1],
>> -							MAX_INLINE_DATA)) {
>> +			if (memcmp(buf, inline_data_addr(node_blk),
>> +						MAX_INLINE_DATA(node_blk))) {
>>  				FIX_MSG("inline_data has DATA_EXIST");
>>  				node_blk->i.i_inline |= F2FS_DATA_EXIST;
>>  				need_fix = 1;
>> @@ -710,7 +715,8 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>>  	/* check data blocks in inode */
>>  	for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i);
>>  						idx++, child.pgofs++) {
>> -		block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[idx]);
>> +		int ofs = get_extra_isize(node_blk);
>> +		block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[ofs + idx]);
>>  
>>  		/* check extent info */
>>  		check_extent_info(&child, blkaddr, 0);
>> @@ -724,9 +730,10 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
>>  			if (!ret) {
>>  				*blk_cnt = *blk_cnt + 1;
>>  			} else if (c.fix_on) {
>> -				node_blk->i.i_addr[idx] = 0;
>> +				node_blk->i.i_addr[ofs + idx] = 0;
>>  				need_fix = 1;
>> -				FIX_MSG("[0x%x] i_addr[%d] = 0", nid, idx);
>> +				FIX_MSG("[0x%x] i_addr[%d] = 0",
>> +							nid, ofs + idx);
>>  			}
>>  		}
>>  	}
>> @@ -1362,7 +1369,7 @@ int fsck_chk_inline_dentries(struct f2fs_sb_info *sbi,
>>  	inline_dentry = inline_data_addr(node_blk);
>>  	ASSERT(inline_dentry != NULL);
>>  
>> -	make_dentry_ptr(&d, inline_dentry, 2);
>> +	make_dentry_ptr(&d, node_blk, inline_dentry, 2);
>>  
>>  	fsck->dentry_depth++;
>>  	dentries = __chk_dentries(sbi, child,
>> diff --git a/fsck/fsck.h b/fsck/fsck.h
>> index 5d2cfd6..1e8ed0b 100644
>> --- a/fsck/fsck.h
>> +++ b/fsck/fsck.h
>> @@ -221,7 +221,7 @@ block_t new_node_block(struct f2fs_sb_info *,
>>  					struct dnode_of_data *, unsigned int);
>>  void get_dnode_of_data(struct f2fs_sb_info *, struct dnode_of_data *,
>>  					pgoff_t, int);
>> -void make_dentry_ptr(struct f2fs_dentry_ptr *, void *, int);
>> +void make_dentry_ptr(struct f2fs_dentry_ptr *, struct f2fs_node *, void *, int);
>>  int f2fs_create(struct f2fs_sb_info *, struct dentry *);
>>  int f2fs_mkdir(struct f2fs_sb_info *, struct dentry *);
>>  int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
>> diff --git a/fsck/mount.c b/fsck/mount.c
>> index a0b0bea..693e4a8 100644
>> --- a/fsck/mount.c
>> +++ b/fsck/mount.c
>> @@ -41,6 +41,7 @@ void print_inode_info(struct f2fs_inode *inode, int name)
>>  	unsigned int i = 0;
>>  	int namelen = le32_to_cpu(inode->i_namelen);
>>  	int enc_name = file_enc_name(inode);
>> +	int ofs = __get_extra_isize(inode);
>>  
>>  	namelen = convert_encrypted_name(inode->i_name, namelen, en, enc_name);
>>  	en[namelen] = '\0';
>> @@ -87,12 +88,15 @@ void print_inode_info(struct f2fs_inode *inode, int name)
>>  			le32_to_cpu(inode->i_ext.blk_addr),
>>  			le32_to_cpu(inode->i_ext.len));
>>  
>> -	DISP_u32(inode, i_addr[0]);	/* Pointers to data blocks */
>> -	DISP_u32(inode, i_addr[1]);	/* Pointers to data blocks */
>> -	DISP_u32(inode, i_addr[2]);	/* Pointers to data blocks */
>> -	DISP_u32(inode, i_addr[3]);	/* Pointers to data blocks */
>> +	DISP_u16(inode, i_extra_isize);
>> +	DISP_u16(inode, i_padding);
>>  
>> -	for (i = 4; i < ADDRS_PER_INODE(inode); i++) {
>> +	DISP_u32(inode, i_addr[ofs]);		/* Pointers to data blocks */
>> +	DISP_u32(inode, i_addr[ofs + 1]);	/* Pointers to data blocks */
>> +	DISP_u32(inode, i_addr[ofs + 2]);	/* Pointers to data blocks */
>> +	DISP_u32(inode, i_addr[ofs + 3]);	/* Pointers to data blocks */
>> +
>> +	for (i = ofs + 4; i < ADDRS_PER_INODE(inode); i++) {
>>  		if (inode->i_addr[i] != 0x0) {
>>  			printf("i_addr[0x%x] points data block\r\t\t[0x%4x]\n",
>>  					i, le32_to_cpu(inode->i_addr[i]));
>> @@ -1357,8 +1361,10 @@ void update_data_blkaddr(struct f2fs_sb_info *sbi, nid_t nid,
>>  
>>  	/* check its block address */
>>  	if (node_blk->footer.nid == node_blk->footer.ino) {
>> -		oldaddr = le32_to_cpu(node_blk->i.i_addr[ofs_in_node]);
>> -		node_blk->i.i_addr[ofs_in_node] = cpu_to_le32(newaddr);
>> +		int ofs = get_extra_isize(node_blk);
>> +
>> +		oldaddr = le32_to_cpu(node_blk->i.i_addr[ofs + ofs_in_node]);
>> +		node_blk->i.i_addr[ofs + ofs_in_node] = cpu_to_le32(newaddr);
>>  	} else {
>>  		oldaddr = le32_to_cpu(node_blk->dn.addr[ofs_in_node]);
>>  		node_blk->dn.addr[ofs_in_node] = cpu_to_le32(newaddr);
>> diff --git a/fsck/node.c b/fsck/node.c
>> index fe923e5..e37b817 100644
>> --- a/fsck/node.c
>> +++ b/fsck/node.c
>> @@ -105,10 +105,10 @@ block_t new_node_block(struct f2fs_sb_info *sbi,
>>   *
>>   * By default, it sets inline_xattr and inline_data
>>   */
>> -static int get_node_path(unsigned long block,
>> +static int get_node_path(struct f2fs_node *node, unsigned long block,
>>  				int offset[4], unsigned int noffset[4])
>>  {
>> -	const long direct_index = DEF_ADDRS_PER_INODE_INLINE_XATTR;
>> +	const long direct_index = ADDRS_PER_INODE(&node->i);
>>  	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;
>> @@ -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(index, offset, noffset);
>> +	level = get_node_path(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 721e5b7..cbf7ed7 100644
>> --- a/fsck/node.h
>> +++ b/fsck/node.h
>> @@ -26,9 +26,14 @@ static inline int IS_INODE(struct f2fs_node *node)
>>  	return ((node)->footer.nid == (node)->footer.ino);
>>  }
>>  
>> +static inline __le32 *blkaddr_in_inode(struct f2fs_node *node)
>> +{
>> +	return node->i.i_addr + get_extra_isize(node);
>> +}
>> +
>>  static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
>>  {
>> -	return IS_INODE(node) ? node->i.i_addr : node->dn.addr;
>> +	return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr;
>>  }
>>  
>>  static inline block_t datablock_addr(struct f2fs_node *node_page,
>> diff --git a/fsck/segment.c b/fsck/segment.c
>> index 6b2f6c1..e21339b 100644
>> --- a/fsck/segment.c
>> +++ b/fsck/segment.c
>> @@ -179,7 +179,7 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
>>  	}
>>  
>>  	/* inline_data support */
>> -	if (de->size <= MAX_INLINE_DATA) {
>> +	if (de->size <= DEF_MAX_INLINE_DATA) {
>>  		struct node_info ni;
>>  		struct f2fs_node *node_blk;
>>  		int ret;
>> @@ -194,9 +194,10 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de)
>>  
>>  		node_blk->i.i_inline |= F2FS_INLINE_DATA;
>>  		node_blk->i.i_inline |= F2FS_DATA_EXIST;
>> +		node_blk->i.i_inline |= F2FS_EXTRA_ATTR;
>>  		n = read(fd, buffer, BLOCK_SZ);
>>  		ASSERT(n == de->size);
>> -		memcpy(&node_blk->i.i_addr[1], buffer, de->size);
>> +		memcpy(inline_data_addr(node_blk), buffer, de->size);
>>  
>>  		node_blk->i.i_size = cpu_to_le64(de->size);
>>  
>> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
>> index dd2635b..88ceb61 100644
>> --- a/include/f2fs_fs.h
>> +++ b/include/f2fs_fs.h
>> @@ -167,6 +167,14 @@ static inline uint64_t bswap_64(uint64_t val)
>>  		printf("%-30s" fmt, #member, ((ptr)->member));	\
>>  	} while (0)
>>  
>> +#define DISP_u16(ptr, member)						\
>> +	do {								\
>> +		assert(sizeof((ptr)->member) == 2);			\
>> +		printf("%-30s" "\t\t[0x%8x : %u]\n",			\
>> +			#member, le16_to_cpu(((ptr)->member)),		\
>> +			le16_to_cpu(((ptr)->member)));			\
>> +	} while (0)
>> +
>>  #define DISP_u32(ptr, member)						\
>>  	do {								\
>>  		assert(sizeof((ptr)->member) <= 4);			\
>> @@ -585,6 +593,8 @@ struct f2fs_extent {
>>  #define F2FS_NAME_LEN		255
>>  #define F2FS_INLINE_XATTR_ADDRS	50	/* 200 bytes for inline xattrs */
>>  #define DEF_ADDRS_PER_INODE	923	/* Address Pointers in an Inode */
>> +#define CUR_ADDRS_PER_INODE(inode)	(DEF_ADDRS_PER_INODE - \
>> +					__get_extra_isize(inode))
>>  #define ADDRS_PER_INODE(i)	addrs_per_inode(i)
>>  #define DEF_ADDRS_PER_INODE_INLINE_XATTR				\
>>  		(DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS)
>> @@ -602,12 +612,27 @@ struct f2fs_extent {
>>  #define F2FS_INLINE_DENTRY	0x04	/* file inline dentry flag */
>>  #define F2FS_DATA_EXIST		0x08	/* file inline data exist flag */
>>  #define F2FS_INLINE_DOTS	0x10	/* file having implicit dot dentries */
>> +#define F2FS_EXTRA_ATTR		0x20	/* file having extra attribute */
>>  
>> -#define MAX_INLINE_DATA (sizeof(__le32) *				\
>> -			(DEF_ADDRS_PER_INODE_INLINE_XATTR - 1))
>> +#if !defined(offsetof)
>> +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
>> +#endif
>>  
>> +#define F2FS_TOTAL_EXTRA_ATTR_SIZE			\
>> +	(offsetof(struct f2fs_inode, i_extra_end) -	\
>> +	offsetof(struct f2fs_inode, i_extra_isize))	\
>> +
>> +#define MAX_INLINE_DATA(node) (sizeof(__le32) *				\
>> +				(DEF_ADDRS_PER_INODE_INLINE_XATTR -	\
>> +				get_extra_isize(node) -			\
>> +				DEF_INLINE_RESERVED_SIZE))
>> +#define DEF_MAX_INLINE_DATA	(sizeof(__le32) *			\
>> +				(DEF_ADDRS_PER_INODE_INLINE_XATTR -	\
>> +				F2FS_TOTAL_EXTRA_ATTR_SIZE -		\
>> +				DEF_INLINE_RESERVED_SIZE))
>>  #define INLINE_DATA_OFFSET	(PAGE_CACHE_SIZE - sizeof(struct node_footer) \
>> -				- sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1))
>> +				- sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - \
>> +				DEF_INLINE_RESERVED_SIZE))
>>  
>>  #define DEF_DIR_LEVEL		0
>>  
>> @@ -648,8 +673,14 @@ struct f2fs_inode {
>>  
>>  	struct f2fs_extent i_ext;	/* caching a largest extent */
>>  
>> -	__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
>> -
>> +	union {
>> +		struct {
>> +			__le16 i_extra_isize;	/* extra inode attribute size */
>> +			__le16 i_padding;	/* padding */
>> +			__le32 i_extra_end[0];	/* for attribute size calculation */
>> +		};
>> +		__le32 i_addr[DEF_ADDRS_PER_INODE];	/* Pointers to data blocks */
>> +	};
>>  	__le32 i_nid[5];		/* direct(2), indirect(2),
>>  						double_indirect(1) node id */
>>  } __attribute__((packed));
>> @@ -909,23 +940,19 @@ struct f2fs_dentry_block {
>>  	__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
>>  } __attribute__((packed));
>>  
>> +/* for inline stuff */
>> +#define DEF_INLINE_RESERVED_SIZE	1
>> +
>>  /* for inline dir */
>> -#define NR_INLINE_DENTRY	(MAX_INLINE_DATA * BITS_PER_BYTE / \
>> +#define NR_INLINE_DENTRY(node)	(MAX_INLINE_DATA(node) * BITS_PER_BYTE / \
>>  				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
>>  				BITS_PER_BYTE + 1))
>> -#define INLINE_DENTRY_BITMAP_SIZE	((NR_INLINE_DENTRY + \
>> +#define INLINE_DENTRY_BITMAP_SIZE(node)	((NR_INLINE_DENTRY(node) + \
>>  					BITS_PER_BYTE - 1) / BITS_PER_BYTE)
>> -#define INLINE_RESERVED_SIZE	(MAX_INLINE_DATA - \
>> +#define INLINE_RESERVED_SIZE(node)	(MAX_INLINE_DATA(node) - \
>>  				((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
>> -				NR_INLINE_DENTRY + INLINE_DENTRY_BITMAP_SIZE))
>> -
>> -/* inline directory entry structure */
>> -struct f2fs_inline_dentry {
>> -	__u8 dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
>> -	__u8 reserved[INLINE_RESERVED_SIZE];
>> -	struct f2fs_dir_entry dentry[NR_INLINE_DENTRY];
>> -	__u8 filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
>> -} __attribute__((packed));
>> +				NR_INLINE_DENTRY(node) + \
>> +				INLINE_DENTRY_BITMAP_SIZE(node)))
>>  
>>  /* file types used in inode_info->flags */
>>  enum FILE_TYPE {
>> @@ -990,6 +1017,20 @@ extern int dev_read_version(void *, __u64, size_t);
>>  extern void get_kernel_version(__u8 *);
>>  f2fs_hash_t f2fs_dentry_hash(const unsigned char *, int);
>>  
>> +static inline bool f2fs_has_extra_isize(struct f2fs_inode *inode)
>> +{
>> +	return (inode->i_inline & F2FS_EXTRA_ATTR);
>> +}
>> +
>> +static inline int __get_extra_isize(struct f2fs_inode *inode)
>> +{
>> +	if (f2fs_has_extra_isize(inode))
>> +		return le16_to_cpu(inode->i_extra_isize) / sizeof(__le32);
>> +	return 0;
>> +}
>> +
>> +#define get_extra_isize(node)	__get_extra_isize(&node->i)
>> +
>>  #define F2FS_ZONED_NONE		0
>>  #define F2FS_ZONED_HA		1
>>  #define F2FS_ZONED_HM		2
>> diff --git a/lib/libf2fs.c b/lib/libf2fs.c
>> index 31836db..a3091bb 100644
>> --- a/lib/libf2fs.c
>> +++ b/lib/libf2fs.c
>> @@ -457,8 +457,8 @@ f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len)
>>  unsigned int addrs_per_inode(struct f2fs_inode *i)
>>  {
>>  	if (i->i_inline & F2FS_INLINE_XATTR)
>> -		return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS;
>> -	return DEF_ADDRS_PER_INODE;
>> +		return CUR_ADDRS_PER_INODE(i) - F2FS_INLINE_XATTR_ADDRS;
>> +	return CUR_ADDRS_PER_INODE(i);
>>  }
>>  
>>  /*
>> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
>> index ff1153a..4f2b403 100644
>> --- a/mkfs/f2fs_format.c
>> +++ b/mkfs/f2fs_format.c
>> @@ -922,10 +922,12 @@ static int f2fs_write_root_inode(void)
>>  	raw_node->i.i_flags = 0;
>>  	raw_node->i.i_current_depth = cpu_to_le32(1);
>>  	raw_node->i.i_dir_level = DEF_DIR_LEVEL;
>> +	raw_node->i.i_inline = F2FS_EXTRA_ATTR;
>> +	raw_node->i.i_extra_isize = cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
>>  
>>  	data_blk_nor = get_sb(main_blkaddr) +
>>  		c.cur_seg[CURSEG_HOT_DATA] * c.blks_per_seg;
>> -	raw_node->i.i_addr[0] = cpu_to_le32(data_blk_nor);
>> +	raw_node->i.i_addr[get_extra_isize(raw_node)] = cpu_to_le32(data_blk_nor);
>>  
>>  	raw_node->i.i_ext.fofs = 0;
>>  	raw_node->i.i_ext.blk_addr = 0;
>> -- 
>> 2.13.0.90.g1eb437020
> 
> .
> 


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-07-18  1:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-16  7:12 [PATCH 1/3] f2fs-tools: spread struct f2fs_dentry_ptr for inline path Chao Yu
2017-07-16  7:12 ` [PATCH 2/3] f2fs-tools: enhance on-disk inode structure scalability Chao Yu
2017-07-17 22:22   ` Jaegeuk Kim
2017-07-18  1:51     ` Chao Yu
2017-07-16  7:12 ` [PATCH 3/3] f2fs-tools: support project quota Chao Yu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).