Пример #1
0
static struct inode *scfs_alloc_inode(struct super_block *sb)
{
	struct scfs_inode_info *sii;

	sii = kmem_cache_alloc(scfs_inode_info_cache, GFP_KERNEL);
	if (!sii)
		return NULL;

	profile_add_kmcached(sizeof(struct scfs_inode_info), SCFS_S(sb));
	memset(sii, 0, offsetof(struct scfs_inode_info, vfs_inode));
	sii->vfs_inode.i_version = 1;
	if (SCFS_S(sb)->options.flags & SCFS_DATA_COMPRESSABLE)
		sii->flags |= SCFS_DATA_COMPRESSABLE;

	mutex_init(&sii->lower_file_mutex);
	mutex_init(&sii->cinfo_mutex);
	INIT_LIST_HEAD(&sii->cinfo_list);

#ifdef SCFS_MULTI_THREAD_COMPRESSION
	INIT_LIST_HEAD(&sii->cbm_list);
	sii->cbm_list_comp_count = 0;
	sii->cbm_list_write_count = 0;
	sii->is_inserted_to_sii_list = 0;
	sii->cbm_list_comp = NULL;
#endif
	
	return &sii->vfs_inode;
}
static int scfs_open(struct inode *inode, struct file *file)
{
	struct scfs_sb_info *sbi = SCFS_S(inode->i_sb);
	struct scfs_inode_info *sii = SCFS_I(inode);
	struct scfs_file_info *fi;
	int ret = 0;
	struct file *lower_file;

	if (IS_WROPENED(sii)) {
		SCFS_PRINT("This file is already opened with 'WRITE' flag\n");
		return -EPERM;
	}

	fi = kmem_cache_zalloc(scfs_file_info_cache, GFP_KERNEL);
	if (!fi)
		return -ENOMEM;

	profile_add_kmcached(sizeof(struct scfs_file_info), sbi);

	file->private_data = fi;

	mutex_lock(&sii->cinfo_mutex);
	if (IS_INVALID_META(sii)) {
		SCFS_PRINT("meta is invalid, so we should re-load it\n");
		ret = scfs_reload_meta(file);
		if (ret) {
			SCFS_PRINT_ERROR("error in re-reading footer, err : %d\n", ret);
			goto out;
		}
	} else if (sii->compressed && !sii->cinfo_array) {
		/* 1st lower-open is for getting cinfo */
		ret = scfs_initialize_lower_file(file->f_dentry, &lower_file, O_RDONLY); 
		if (ret) {
			SCFS_PRINT_ERROR("err in get_lower_file %s\n",
				file->f_dentry->d_name.name);
			goto out;
		}
		scfs_set_lower_file(file, lower_file);

		SCFS_PRINT("info size = %d \n", sii->cinfo_array_size);
		ret = scfs_load_cinfo(sii, lower_file);
		if (ret) {
			SCFS_PRINT_ERROR("err in loading cinfo, ret : %d\n",
				file->f_dentry->d_name.name);
			fput(lower_file);
			goto out;
		}
		fput(lower_file);
	}

	ret = scfs_initialize_lower_file(file->f_dentry, &lower_file, file->f_flags); 
	if (ret) {
		SCFS_PRINT_ERROR("err in get_lower_file %s\n",
			file->f_dentry->d_name.name);

		goto out;
	}
	scfs_set_lower_file(file, lower_file);
out:
	if (!ret) {
		fsstack_copy_attr_all(inode, scfs_lower_inode(inode));
		if (file->f_flags & (O_RDWR | O_WRONLY))
			MAKE_WROPENED(sii);
	} else {
		scfs_set_lower_file(file, NULL);
		kmem_cache_free(scfs_file_info_cache, file->private_data);
		profile_sub_kmcached(sizeof(struct scfs_file_info), sbi);
		sii->cinfo_array = NULL;
	}
	mutex_unlock(&sii->cinfo_mutex);
	SCFS_PRINT("lower, dentry name : %s, count : %d, ret : %d\n",
		file->f_dentry->d_name.name, file->f_dentry->d_count, ret);
	
	return ret;
}