sload.f2fs: support sload files into directory includes inline dentry

It seems the new created directory always includes inline dentries,
let sload.f2fs supporting it.

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Kinglong Mee 2017-03-17 22:01:12 +08:00 committed by Jaegeuk Kim
parent 9a4df3c466
commit 0f3045d3e8
2 changed files with 117 additions and 26 deletions

View File

@ -158,12 +158,6 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi,
unsigned int max_depth;
unsigned int level;
if (dir->i.i_inline & F2FS_INLINE_DENTRY) {
ERR_MSG("Not support to find \"%s\" in inline_dir pino=%x\n",
de->name, de->pino);
return 0;
}
max_depth = le32_to_cpu(dir->i.i_current_depth);
for (level = 0; level < max_depth; level ++) {
if (find_in_level(sbi, dir, level, de))
@ -172,7 +166,7 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi,
return 0;
}
static void f2fs_update_dentry(nid_t ino, umode_t mode,
static void f2fs_update_dentry(nid_t ino, int file_type,
struct f2fs_dentry_ptr *d,
const unsigned char *name, int len, f2fs_hash_t name_hash,
unsigned int bit_pos)
@ -187,7 +181,7 @@ static void f2fs_update_dentry(nid_t ino, umode_t mode,
memcpy(d->filename[bit_pos], name, len);
d->filename[bit_pos][len] = 0;
de->ino = cpu_to_le32(ino);
set_de_type(de, mode);
de->file_type = file_type;
for (i = 0; i < slots; i++)
test_and_set_bit_le(bit_pos + i, d->bitmap);
}
@ -196,24 +190,21 @@ static void f2fs_update_dentry(nid_t ino, umode_t mode,
* f2fs_add_link - Add a new file(dir) to parent dir.
*/
static int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent,
struct f2fs_node *child, block_t p_blkaddr)
const unsigned char *name, int name_len, nid_t ino,
int file_type, block_t p_blkaddr, int inc_link)
{
int level = 0, current_depth, bit_pos;
int nbucket, nblock, bidx, block;
const unsigned char *name = child->i.i_name;
int name_len = le32_to_cpu(child->i.i_namelen);
int slots = GET_DENTRY_SLOTS(name_len);
f2fs_hash_t dentry_hash = f2fs_dentry_hash(name, name_len);
struct f2fs_dentry_block *dentry_blk;
struct f2fs_dentry_ptr d;
struct dnode_of_data dn = {0};
nid_t pino = le32_to_cpu(parent->footer.ino);
nid_t ino = le32_to_cpu(child->footer.ino);
umode_t mode = le16_to_cpu(child->i.i_mode);
unsigned int dir_level = parent->i.i_dir_level;
int ret;
if (parent == NULL || child == NULL)
if (parent == NULL)
return -EINVAL;
if (!pino) {
@ -266,7 +257,7 @@ start:
add_dentry:
make_dentry_ptr(&d, (void *)dentry_blk, 1);
f2fs_update_dentry(ino, mode, &d, name, name_len, dentry_hash, bit_pos);
f2fs_update_dentry(ino, file_type, &d, name, name_len, dentry_hash, bit_pos);
ret = dev_write_block(dentry_blk, dn.data_blkaddr);
ASSERT(ret >= 0);
@ -281,7 +272,7 @@ add_dentry:
}
/* Update parent's i_links info*/
if (S_ISDIR(mode)) {
if (inc_link && (file_type == F2FS_FT_DIR)){
u32 links = le32_to_cpu(parent->i.i_links);
parent->i.i_links = cpu_to_le32(links + 1);
dn.idirty = 1;
@ -445,6 +436,102 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
page_symlink(sbi, node_blk, de->link, size);
}
int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
block_t p_blkaddr)
{
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];
struct dnode_of_data dn = {0};
struct f2fs_dentry_ptr d;
unsigned long bit_pos = 0;
int ret = 0;
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);
inode->i_inline &= ~F2FS_INLINE_DENTRY;
ret = dev_write_block(node, p_blkaddr);
ASSERT(ret >= 0);
if (!dir_level) {
struct f2fs_inline_dentry *inline_dentry;
struct f2fs_dentry_block *dentry_blk;
dentry_blk = calloc(BLOCK_SZ, 1);
ASSERT(dentry_blk);
set_new_dnode(&dn, node, NULL, ino);
get_dnode_of_data(sbi, &dn, 0, ALLOC_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;
/* 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);
ret = dev_write_block(dentry_blk, dn.data_blkaddr);
ASSERT(ret >= 0);
MSG(1, "%s: copy inline entry to block\n", __func__);
free(dentry_blk);
return ret;
}
make_empty_dir(sbi, node);
make_dentry_ptr(&d, (void *)inline_data, 2);
while (bit_pos < d.max) {
struct f2fs_dir_entry *de;
const unsigned char *filename;
int namelen;
if (!test_bit_le(bit_pos, d.bitmap)) {
bit_pos++;
continue;
}
de = &d.dentry[bit_pos];
if (!de->name_len) {
bit_pos++;
continue;
}
filename = d.filename[bit_pos];
namelen = le32_to_cpu(de->name_len);
if (is_dot_dotdot(filename, namelen)) {
bit_pos += GET_DENTRY_SLOTS(namelen);
continue;
}
ret = f2fs_add_link(sbi, node, filename, namelen,
le32_to_cpu(de->ino),
de->file_type, p_blkaddr, 0);
if (ret)
MSG(0, "Convert file \"%s\" ERR=%d\n", filename, ret);
else
MSG(1, "%s: add inline entry to block\n", __func__);
bit_pos += GET_DENTRY_SLOTS(namelen);
}
return 0;
}
int f2fs_create(struct f2fs_sb_info *sbi, struct dentry *de)
{
struct f2fs_node *parent, *child;
@ -466,6 +553,13 @@ int f2fs_create(struct f2fs_sb_info *sbi, struct dentry *de)
ret = dev_read_block(parent, ni.blk_addr);
ASSERT(ret >= 0);
/* Must convert inline dentry before the following opertions */
ret = convert_inline_dentry(sbi, parent, ni.blk_addr);
if (ret) {
MSG(0, "Convert inline dentry for pino=%x failed.\n", de->pino);
return -1;
}
ret = f2fs_find_entry(sbi, parent, de);
if (ret) {
MSG(0, "Skip the existing \"%s\" pino=%x ERR=%d\n",
@ -474,13 +568,6 @@ int f2fs_create(struct f2fs_sb_info *sbi, struct dentry *de)
de->ino = 0;
goto free_parent_dir;
}
if (parent->i.i_inline & F2FS_INLINE_DENTRY) {
ERR_MSG("Not support adding \"%s\" in inline_dir pino=%x\n",
de->name, de->pino);
if (de->file_type == F2FS_FT_REG_FILE)
de->ino = 0;
goto free_parent_dir;
}
child = calloc(BLOCK_SZ, 1);
ASSERT(child);
@ -489,7 +576,11 @@ int f2fs_create(struct f2fs_sb_info *sbi, struct dentry *de)
init_inode_block(sbi, child, de);
ret = f2fs_add_link(sbi, parent, child, ni.blk_addr);
ret = f2fs_add_link(sbi, parent, child->i.i_name,
le32_to_cpu(child->i.i_namelen),
le32_to_cpu(child->footer.ino),
map_de_type(le16_to_cpu(child->i.i_mode)),
ni.blk_addr, 1);
if (ret) {
MSG(0, "Skip the existing \"%s\" pino=%x ERR=%d\n",
de->name, de->pino, ret);

View File

@ -444,9 +444,9 @@ static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
[S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK,
};
static inline void set_de_type(struct f2fs_dir_entry *de, umode_t mode)
static inline int map_de_type(umode_t mode)
{
de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
return f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
}
static inline void *inline_xattr_addr(struct f2fs_inode *inode)