* [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).