int f2fs_create(struct f2fs_sb_info *sbi, struct dentry *de) { struct f2fs_node *parent, *child; struct node_info ni; struct f2fs_summary sum; block_t blkaddr = NULL_ADDR; int ret; /* Find if there is a */ get_node_info(sbi, de->pino, &ni); if (ni.blk_addr == NULL_ADDR) { MSG(0, "No parent directory pino=%x\n", de->pino); return -1; } parent = calloc(BLOCK_SZ, 1); ASSERT(parent); 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", de->name, de->pino, ret); if (de->file_type == F2FS_FT_REG_FILE) de->ino = 0; goto free_parent_dir; } child = calloc(BLOCK_SZ, 1); ASSERT(child); f2fs_alloc_nid(sbi, &de->ino, 1); init_inode_block(sbi, child, de); 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); goto free_child_dir; } /* write child */ set_summary(&sum, de->ino, 0, ni.version); reserve_new_block(sbi, &blkaddr, &sum, CURSEG_HOT_NODE); /* update nat info */ update_nat_blkaddr(sbi, de->ino, de->ino, blkaddr); ret = dev_write_block(child, blkaddr); ASSERT(ret >= 0); update_free_segments(sbi); MSG(1, "Info: Create %s -> %s\n" " -- ino=%x, type=%x, mode=%x, uid=%x, " "gid=%x, cap=%"PRIx64", size=%lu, pino=%x\n", de->full_path, de->path, de->ino, de->file_type, de->mode, de->uid, de->gid, de->capabilities, de->size, de->pino); free_child_dir: free(child); free_parent_dir: free(parent); return 0; }
void get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, pgoff_t index, int mode) { int offset[4]; unsigned int noffset[4]; struct f2fs_node *parent = NULL; nid_t nids[4]; block_t nblk[4]; struct node_info ni; int level, i; int ret; level = get_node_path(index, offset, noffset); nids[0] = dn->nid; parent = dn->inode_blk; if (level != 0) nids[1] = get_nid(parent, offset[0], 1); else dn->node_blk = dn->inode_blk; get_node_info(sbi, nids[0], &ni); nblk[0] = ni.blk_addr; for (i = 1; i <= level; i++) { if (!nids[i] && mode == ALLOC_NODE) { f2fs_alloc_nid(sbi, &nids[i], 0); dn->nid = nids[i]; /* Function new_node_blk get a new f2fs_node blk and update*/ /* We should make sure that dn->node_blk == NULL*/ nblk[i] = new_node_block(sbi, dn, noffset[i]); ASSERT(nblk[i]); set_nid(parent, offset[i - 1], nids[i], i == 1); } else { /* If Sparse file no read API, */ struct node_info ni; get_node_info(sbi, nids[i], &ni); dn->node_blk = calloc(BLOCK_SZ, 1); ASSERT(dn->node_blk); ret = dev_read_block(dn->node_blk, ni.blk_addr); ASSERT(ret >= 0); nblk[i] = ni.blk_addr; } if (mode == ALLOC_NODE){ /* Parent node may have changed */ ret = dev_write_block(parent, nblk[i - 1]); ASSERT(ret >= 0); } if (i != 1) free(parent); if (i < level) { parent = dn->node_blk; nids[i + 1] = get_nid(parent, offset[i], 0); } } dn->nid = nids[level]; dn->ofs_in_node = offset[level]; dn->data_blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node); dn->node_blkaddr = nblk[level]; }