struct super_block *capifs_read_super(struct super_block *s, void *data,
				      int silent)
{
	struct inode * root_inode;
	struct dentry * root;
	struct capifs_sb_info *sbi;

	/* Super block already completed? */
	if (s->s_root)
		goto out;

	sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
	if ( !sbi )
		goto fail;

	memset(sbi, 0, sizeof(struct capifs_sb_info));
	sbi->magic  = CAPIFS_SBI_MAGIC;

	if ( capifs_parse_options(data,sbi) ) {
		kfree(sbi);
		printk("capifs: called with bogus options\n");
		goto fail;
	}

	sbi->nccis = kmalloc(sizeof(struct capifs_ncci) * sbi->max_ncci, GFP_KERNEL);
	if ( !sbi->nccis ) {
		kfree(sbi);
		goto fail;
	}
	memset(sbi->nccis, 0, sizeof(struct capifs_ncci) * sbi->max_ncci);

	s->u.generic_sbp = (void *) sbi;
	s->s_blocksize = 1024;
	s->s_blocksize_bits = 10;
	s->s_magic = CAPIFS_SUPER_MAGIC;
	s->s_op = &capifs_sops;
	s->s_root = NULL;

	/*
	 * Get the root inode and dentry, but defer checking for errors.
	 */
	root_inode = capifs_new_inode(s);
	if (root_inode) {
		root_inode->i_ino = 1;
		root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
		root_inode->i_op = &capifs_root_inode_operations;
		root_inode->i_fop = &capifs_root_operations;
		root_inode->i_nlink = 2;
	} 
	root = d_alloc_root(root_inode);

	/*
	 * Check whether somebody else completed the super block.
	 */
	if (s->s_root) {
		if (root) dput(root);
		else iput(root_inode);
		goto out;
	}

	if (!root) {
		printk("capifs: get root dentry failed\n");
		/*
	 	* iput() can block, so we clear the super block first.
	 	*/
		iput(root_inode);
		kfree(sbi->nccis);
		kfree(sbi);
		goto fail;
	}

	/*
	 * Check whether somebody else completed the super block.
	 */
	if (s->s_root)
		goto out;
	
	/*
	 * Success! Install the root dentry now to indicate completion.
	 */
	s->s_root = root;

	sbi->next = mounts;
	if ( sbi->next )
		SBI(sbi->next)->back = &(sbi->next);
	sbi->back = &mounts;
	mounts = s;

out:	/* Success ... somebody else completed the super block for us. */ 
	return s;
fail:
	return NULL;
}
Esempio n. 2
0
struct super_block *capifs_read_super(struct super_block *s, void *data,
				      int silent)
{
	struct inode * root_inode;
	struct dentry * root;
	struct capifs_sb_info *sbi;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
	MOD_INC_USE_COUNT;
	lock_super(s);
#endif
	/* Super block already completed? */
	if (s->s_root)
		goto out;

	sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
	if ( !sbi )
		goto fail;

	memset(sbi, 0, sizeof(struct capifs_sb_info));
	sbi->magic  = CAPIFS_SBI_MAGIC;

	if ( capifs_parse_options(data,sbi) ) {
		kfree(sbi);
		printk("capifs: called with bogus options\n");
		goto fail;
	}

	sbi->nccis = kmalloc(sizeof(struct capifs_ncci) * sbi->max_ncci, GFP_KERNEL);
	if ( !sbi->nccis ) {
		kfree(sbi);
		goto fail;
	}
	memset(sbi->nccis, 0, sizeof(struct capifs_ncci) * sbi->max_ncci);

	s->u.generic_sbp = (void *) sbi;
	s->s_blocksize = 1024;
	s->s_blocksize_bits = 10;
	s->s_magic = CAPIFS_SUPER_MAGIC;
	s->s_op = &capifs_sops;
	s->s_root = NULL;

	/*
	 * Get the root inode and dentry, but defer checking for errors.
	 */
	root_inode = iget(s, 1); /* inode 1 == root directory */
	root = d_alloc_root(root_inode);

	/*
	 * Check whether somebody else completed the super block.
	 */
	if (s->s_root) {
		if (root) dput(root);
		else iput(root_inode);
		goto out;
	}

	if (!root) {
		printk("capifs: get root dentry failed\n");
		/*
	 	* iput() can block, so we clear the super block first.
	 	*/
		iput(root_inode);
		kfree(sbi->nccis);
		kfree(sbi);
		goto fail;
	}

	/*
	 * Check whether somebody else completed the super block.
	 */
	if (s->s_root)
		goto out;
	
	/*
	 * Success! Install the root dentry now to indicate completion.
	 */
	s->s_root = root;

	sbi->next = mounts;
	if ( sbi->next )
		SBI(sbi->next)->back = &(sbi->next);
	sbi->back = &mounts;
	mounts = s;

out:	/* Success ... somebody else completed the super block for us. */ 
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
	unlock_super(s);
#endif
	return s;
fail:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
	unlock_super(s);
	MOD_DEC_USE_COUNT;
#endif
	return NULL;
}