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; }
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; }
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; }