Esempio n. 1
0
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];
}