Esempio n. 1
0
static int __tux3_mknod(struct inode *dir, struct dentry *dentry,
			struct tux_iattr *iattr, dev_t rdev)
{
	struct inode *inode;
	int err, is_dir = S_ISDIR(iattr->mode);

	if (!huge_valid_dev(rdev))
		return -EINVAL;

	if (is_dir && dir->i_nlink >= TUX_LINK_MAX)
		return -EMLINK;

	change_begin(tux_sb(dir->i_sb));
	inode = tux_new_inode(dir, iattr, rdev);
	err = PTR_ERR(inode);
	if (!IS_ERR(inode)) {
		err = tux_add_dirent(dir, dentry, inode);
		if (!err) {
			unlock_new_inode(inode);
			if (is_dir)
				inode_inc_link_count(dir);
		}
	}
	change_end(tux_sb(dir->i_sb));
	return err;
}
Esempio n. 2
0
static int __tux3_symlink(struct inode *dir, struct dentry *dentry,
			  struct tux_iattr *iattr, const char *symname)
{
	struct sb *sb = tux_sb(dir->i_sb);
	struct inode *inode;
	unsigned len = strlen(symname) + 1;
	int err, err2;

	/* FIXME: We want more length? */
	if (len > PAGE_CACHE_SIZE)
		return -ENAMETOOLONG;

	change_begin(sb);
	inode = tux_new_inode(dir, iattr, 0);
	err = PTR_ERR(inode);
	if (!IS_ERR(inode)) {
		err = tux_create_dirent(dir, &dentry->d_name, inode);
		if (!err) {
			/* FIXME: we may want to initialize symlink earlier */
			err = page_symlink(inode, symname, len);
			if (!err) {
				d_instantiate(dentry, inode);
				unlock_new_inode(inode);
				goto out;
			}

			err2 = tux_del_dirent(dir, dentry);
			if (err2)
				tux3_fs_error(sb, "Failed to recover dir entry (err %d)", err2);
			clear_nlink(inode);
			tux3_mark_inode_dirty(inode);
			unlock_new_inode(inode);
			iput(inode);
		}
	}
out:
	change_end(sb);

	return err;
}
Esempio n. 3
0
static int tux3_fill_super(struct super_block *sb, void *data, int silent)
{
	static struct tux_iattr iattr;
	struct sb *sbi;
	struct root iroot;
	int err, blocksize;

	sbi = kzalloc(sizeof(struct sb), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	sbi->vfs_sb = sb;
	sb->s_fs_info = sbi;
	sb->s_maxbytes = MAX_LFS_FILESIZE;
	sb->s_magic = 0x54555833;
	sb->s_op = &tux3_super_ops;
	sb->s_time_gran = 1;

	mutex_init(&sbi->loglock);

	err = -EIO;
	blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
	if (!blocksize) {
		if (!silent)
			printk(KERN_ERR "TUX3: unable to set blocksize\n");
		goto error;
	}

	err = tux_load_sb(sb, &iroot, silent);
	if (err)
		goto error;
	printk("%s: depth %Lu, block %Lu\n",
	       __func__, (L)iroot.depth, (L)iroot.block);
	printk("%s: blocksize %u, blockbits %u, blockmask %08x\n",
	       __func__, sbi->blocksize, sbi->blockbits, sbi->blockmask);
	printk("%s: volblocks %Lu, freeblocks %Lu, nextalloc %Lu\n",
	       __func__, sbi->volblocks, sbi->freeblocks, sbi->nextalloc);
	printk("%s: freeatom %u, atomgen %u\n",
	       __func__, sbi->freeatom, sbi->atomgen);

	if (sbi->blocksize != blocksize) {
		if (!sb_set_blocksize(sb, sbi->blocksize)) {
			printk(KERN_ERR "TUX3: blocksize too small for device.\n");
			goto error;
		}
	}
	printk("%s: s_blocksize %lu\n", __func__, sb->s_blocksize);

	err = -ENOMEM;
	sbi->volmap = tux_new_volmap(tux_sb(sb));
	if (!sbi->volmap)
		goto error;

	/* Initialize itable btree */
	init_btree(itable_btree(sbi), sbi, iroot, &itable_ops);

//	struct inode *vtable;
	sbi->bitmap = tux3_iget(sb, TUX_BITMAP_INO);
	err = PTR_ERR(sbi->bitmap);
	if (IS_ERR(sbi->bitmap))
		goto error_bitmap;

	sbi->rootdir = tux3_iget(sb, TUX_ROOTDIR_INO);
	err = PTR_ERR(sbi->rootdir);
	if (IS_ERR(sbi->rootdir))
		goto error_rootdir;

	sbi->atable = tux3_iget(sb, TUX_ATABLE_INO);
	err = PTR_ERR(sbi->atable);
	if (IS_ERR(sbi->atable))
		goto error_atable;

	err = -ENOMEM;
	sbi->logmap = tux_new_inode(sbi->rootdir, &iattr, 0);
	if (!sbi->logmap)
		goto error_logmap;

	sb->s_root = d_alloc_root(sbi->rootdir);
	if (!sb->s_root)
		goto error_alloc_root;

	return 0;

error_alloc_root:
	iput(sbi->logmap);
error_logmap:
	iput(sbi->atable);
error_atable:
	iput(sbi->rootdir);
error_rootdir:
	iput(sbi->bitmap);
error_bitmap:
	iput(sbi->volmap);
error:
	kfree(sbi);
	return err;
}