Пример #1
0
int
affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type)
{
	struct super_block *sb = dir->i_sb;
	struct buffer_head *inode_bh = NULL;
	struct buffer_head *bh;
	u32 block = 0;
	int retval;

	pr_debug("%s(dir=%lu, inode=%lu, \"%pd\", type=%d)\n", __func__,
		 dir->i_ino, inode->i_ino, dentry, type);

	retval = -EIO;
	bh = affs_bread(sb, inode->i_ino);
	if (!bh)
		goto done;

	affs_lock_link(inode);
	switch (type) {
	case ST_LINKFILE:
	case ST_LINKDIR:
		retval = -ENOSPC;
		block = affs_alloc_block(dir, dir->i_ino);
		if (!block)
			goto err;
		retval = -EIO;
		inode_bh = bh;
		bh = affs_getzeroblk(sb, block);
		if (!bh)
			goto err;
		break;
	default:
		break;
	}

	AFFS_HEAD(bh)->ptype = cpu_to_be32(T_SHORT);
	AFFS_HEAD(bh)->key = cpu_to_be32(bh->b_blocknr);
	affs_copy_name(AFFS_TAIL(sb, bh)->name, dentry);
	AFFS_TAIL(sb, bh)->stype = cpu_to_be32(type);
	AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);

	if (inode_bh) {
		__be32 chain;
	       	chain = AFFS_TAIL(sb, inode_bh)->link_chain;
		AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
		AFFS_TAIL(sb, bh)->link_chain = chain;
		AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
		affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
		mark_buffer_dirty_inode(inode_bh, inode);
		set_nlink(inode, 2);
		ihold(inode);
	}
	affs_fix_checksum(sb, bh);
	mark_buffer_dirty_inode(bh, inode);
	dentry->d_fsdata = (void *)(long)bh->b_blocknr;

	affs_lock_dir(dir);
	retval = affs_insert_hash(dir, bh);
	mark_buffer_dirty_inode(bh, inode);
	affs_unlock_dir(dir);
	affs_unlock_link(inode);

	d_instantiate(dentry, inode);
done:
	affs_brelse(inode_bh);
	affs_brelse(bh);
	return retval;
err:
	if (block)
		affs_free_block(sb, block);
	affs_unlock_link(inode);
	goto done;
}
Пример #2
0
int
affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
	       struct dentry *dentry, int type)
{
	struct buffer_head	*dir_bh;
	struct buffer_head	*inode_bh;
	struct buffer_head	*link_bh;
	int			 retval;
	const unsigned char	*name = dentry->d_name.name;
	int			 len  = dentry->d_name.len;

	pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d)\n",dir->i_ino,inode->i_ino,
		 len,name,type);

	if ((retval = affs_check_name(name,len)))
		return retval;
	if (len > 30)
		len = 30;

	dir_bh   = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));
	inode_bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
	link_bh  = NULL;
	retval   = -EIO;
	if (!dir_bh || !inode_bh)
		goto addentry_done;
	if (link) {
		link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link));
		if (!link_bh)
			goto addentry_done;
	}
	((struct dir_front *)inode_bh->b_data)->primary_type = cpu_to_be32(T_SHORT);
	((struct dir_front *)inode_bh->b_data)->own_key      = cpu_to_be32(inode->i_ino);
	DIR_END(inode_bh->b_data,inode)->dir_name[0]         = len;
	strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len);
	DIR_END(inode_bh->b_data,inode)->secondary_type = cpu_to_be32(type);
	DIR_END(inode_bh->b_data,inode)->parent         = cpu_to_be32(dir->i_ino);

	lock_super(inode->i_sb);
	retval = affs_insert_hash(dir->i_ino,inode_bh,dir);

	if (link_bh) {
		LINK_END(inode_bh->b_data,inode)->original   = cpu_to_be32(link->i_ino);
		LINK_END(inode_bh->b_data,inode)->link_chain =
						FILE_END(link_bh->b_data,link)->link_chain;
		FILE_END(link_bh->b_data,link)->link_chain   = cpu_to_be32(inode->i_ino);
		affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5);
		link->i_version = ++global_event;
		mark_inode_dirty(link);
		mark_buffer_dirty(link_bh,1);
	}
	affs_fix_checksum(AFFS_I2BSIZE(inode),inode_bh->b_data,5);
	affs_fix_checksum(AFFS_I2BSIZE(dir),dir_bh->b_data,5);
	dir->i_version = ++global_event;
	dir->i_mtime   = dir->i_atime = dir->i_ctime = CURRENT_TIME;
	unlock_super(inode->i_sb);

	mark_inode_dirty(dir);
	mark_inode_dirty(inode);
	mark_buffer_dirty(dir_bh,1);
	mark_buffer_dirty(inode_bh,1);

addentry_done:
	affs_brelse(dir_bh);
	affs_brelse(inode_bh);
	affs_brelse(link_bh);

	return retval;
}