/**
 * vxfs_stiget - find inode using the structural inode list
 * @sbp:	VFS superblock
 * @ino:	inode #
 *
 * Description:
 *  Find inode @ino in the filesystem described by @sbp using
 *  the structural inode list.
 *  Returns the matching VxFS inode on success, else a NULL pointer.
 */
struct vxfs_inode_info *
vxfs_stiget(struct super_block *sbp, ino_t ino)
{
	struct vxfs_inode_info *vip;

	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
	return IS_ERR(vip) ? NULL : vip;
}
Beispiel #2
0
/**
 * vxfs_read_olt - read olt
 * @sbp:	superblock of the filesystem
 * @bsize:	blocksize of the filesystem
 *
 * Description:
 *   vxfs_read_olt reads the olt of the filesystem described by @sbp
 *   into main memory and does some basic setup.
 *
 * Returns:
 *   Zero on success, else a negative error code.
 */
int
vxfs_read_olt(struct super_block *sbp, u_long bsize)
{
	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
	struct buffer_head	*bp;
	struct vxfs_olt		*op;
	char			*oaddr, *eaddr;


	bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
	if (!bp || !bp->b_data)
		goto fail;

	op = (struct vxfs_olt *)bp->b_data;
	if (op->olt_magic != VXFS_OLT_MAGIC) {
		printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
		goto fail;
	}

	/*
	 * It is in theory possible that vsi_oltsize is > 1.
	 * I've not seen any such filesystem yet and I'm lazy..  --hch
	 */
	if (infp->vsi_oltsize > 1) {
		printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
		printk(KERN_NOTICE "vxfs: please notify [email protected]\n");
		goto fail;
	}

	oaddr = bp->b_data + op->olt_size;
	eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);

	while (oaddr < eaddr) {
		struct vxfs_oltcommon	*ocp =
			(struct vxfs_oltcommon *)oaddr;
		
		switch (ocp->olt_type) {
		case VXFS_OLT_FSHEAD:
			vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
			break;
		case VXFS_OLT_ILIST:
			vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);
			break;
		}

		oaddr += ocp->olt_size;
	}

	brelse(bp);
	return 0;

fail:
	brelse(bp);
	return -EINVAL;
}
Beispiel #3
0
static void
vxfs_put_super(struct super_block *sbp)
{
	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);

	vxfs_put_fake_inode(infp->vsi_fship);
	vxfs_put_fake_inode(infp->vsi_ilist);
	vxfs_put_fake_inode(infp->vsi_stilist);

	brelse(infp->vsi_bp);
	kfree(infp);
}
Beispiel #4
0
/**
 * vxfs_iget - get an inode
 * @sbp:	the superblock to get the inode for
 * @ino:	the number of the inode to get
 *
 * Description:
 *  vxfs_read_inode creates an inode, reads the disk inode for @ino and fills
 *  in all relevant fields in the new inode.
 */
struct inode *
vxfs_iget(struct super_block *sbp, ino_t ino)
{
	struct vxfs_inode_info		*vip;
	const struct address_space_operations	*aops;
	struct inode *ip;

	ip = iget_locked(sbp, ino);
	if (!ip)
		return ERR_PTR(-ENOMEM);
	if (!(ip->i_state & I_NEW))
		return ip;

	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
	if (IS_ERR(vip)) {
		iget_failed(ip);
		return ERR_CAST(vip);
	}

	vxfs_iinit(ip, vip);

	if (VXFS_ISIMMED(vip))
		aops = &vxfs_immed_aops;
	else
		aops = &vxfs_aops;

	if (S_ISREG(ip->i_mode)) {
		ip->i_fop = &generic_ro_fops;
		ip->i_mapping->a_ops = aops;
	} else if (S_ISDIR(ip->i_mode)) {
		ip->i_op = &vxfs_dir_inode_ops;
		ip->i_fop = &vxfs_dir_operations;
		ip->i_mapping->a_ops = aops;
	} else if (S_ISLNK(ip->i_mode)) {
		if (!VXFS_ISIMMED(vip)) {
			ip->i_op = &page_symlink_inode_operations;
			inode_nohighmem(ip);
			ip->i_mapping->a_ops = &vxfs_aops;
		} else {
			ip->i_op = &simple_symlink_inode_operations;
			ip->i_link = vip->vii_immed.vi_immed;
			nd_terminate_link(ip->i_link, ip->i_size,
					  sizeof(vip->vii_immed.vi_immed) - 1);
		}
	} else
		init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev));

	unlock_new_inode(ip);
	return ip;
}
Beispiel #5
0
/**
 * vxfs_inode_by_name - find inode number for dentry
 * @dip:	directory to search in
 * @dp:		dentry we search for
 *
 * Description:
 *   vxfs_inode_by_name finds out the inode number of
 *   the path component described by @dp in @dip.
 *
 * Returns:
 *   The wanted inode number on success, else Zero.
 */
static ino_t
vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
{
	struct vxfs_direct		*de;
	struct page			*pp;
	ino_t				ino = 0;

	de = vxfs_find_entry(dip, dp, &pp);
	if (de) {
		ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
		kunmap(pp);
		put_page(pp);
	}
	
	return (ino);
}
Beispiel #6
0
/**
 * vxfs_statfs - get filesystem information
 * @dentry:	VFS dentry to locate superblock
 * @bufp:	output buffer
 *
 * Description:
 *   vxfs_statfs fills the statfs buffer @bufp with information
 *   about the filesystem described by @dentry.
 *
 * Returns:
 *   Zero.
 *
 * Locking:
 *   No locks held.
 *
 * Notes:
 *   This is everything but complete...
 */
static int
vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
{
	struct vxfs_sb_info		*infp = VXFS_SBI(dentry->d_sb);

	bufp->f_type = VXFS_SUPER_MAGIC;
	bufp->f_bsize = dentry->d_sb->s_blocksize;
	bufp->f_blocks = infp->vsi_raw->vs_dsize;
	bufp->f_bfree = infp->vsi_raw->vs_free;
	bufp->f_bavail = 0;
	bufp->f_files = 0;
	bufp->f_ffree = infp->vsi_raw->vs_ifree;
	bufp->f_namelen = VXFS_NAMELEN;

	return 0;
}
Beispiel #7
0
/**
 * vxfs_statfs - get filesystem information
 * @sbp:	VFS superblock
 * @bufp:	output buffer
 *
 * Description:
 *   vxfs_statfs fills the statfs buffer @bufp with information
 *   about the filesystem described by @sbp.
 *
 * Returns:
 *   Zero.
 *
 * Locking:
 *   No locks held.
 *
 * Notes:
 *   This is everything but complete...
 */
static int
vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp)
{
	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);

	bufp->f_type = VXFS_SUPER_MAGIC;
	bufp->f_bsize = sbp->s_blocksize;
	bufp->f_blocks = infp->vsi_raw->vs_dsize;
	bufp->f_bfree = infp->vsi_raw->vs_free;
	bufp->f_bavail = 0;
	bufp->f_files = 0;
	bufp->f_ffree = infp->vsi_raw->vs_ifree;
	bufp->f_namelen = VXFS_NAMELEN;

	return 0;
}
Beispiel #8
0
/**
 * vxfs_read_inode - fill in inode information
 * @ip:		inode pointer to fill
 *
 * Description:
 *  vxfs_read_inode reads the disk inode for @ip and fills
 *  in all relevant fields in @ip.
 */
void
vxfs_read_inode(struct inode *ip)
{
	struct super_block		*sbp = ip->i_sb;
	struct vxfs_inode_info		*vip;
	struct address_space_operations	*aops;
	ino_t				ino = ip->i_ino;

	if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist)))
		return;

	vxfs_iinit(ip, vip);

	if (VXFS_ISIMMED(vip))
		aops = &vxfs_immed_aops;
	else
		aops = &vxfs_aops;

	if (S_ISREG(ip->i_mode)) {
		ip->i_fop = &vxfs_file_operations;
		ip->i_mapping->a_ops = aops;
	} else if (S_ISDIR(ip->i_mode)) {
		ip->i_op = &vxfs_dir_inode_ops;
		ip->i_fop = &vxfs_dir_operations;
		ip->i_mapping->a_ops = aops;
	} else if (S_ISLNK(ip->i_mode)) {
		if (!VXFS_ISIMMED(vip)) {
			ip->i_op = &page_symlink_inode_operations;
			ip->i_mapping->a_ops = &vxfs_aops;
		} else
			ip->i_op = &vxfs_immed_symlink_iops;
	} else
		init_special_inode(ip, ip->i_mode, vip->vii_rdev);

	return;
}
Beispiel #9
0
/**
 * vxfs_find_entry - find a mathing directory entry for a dentry
 * @ip:		directory inode
 * @dp:		dentry for which we want to find a direct
 * @ppp:	gets filled with the page the return value sits in
 *
 * Description:
 *   vxfs_find_entry finds a &struct vxfs_direct for the VFS directory
 *   cache entry @dp.  @ppp will be filled with the page the return
 *   value resides in.
 *
 * Returns:
 *   The wanted direct on success, else a NULL pointer.
 */
static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
{
	u_long bsize = ip->i_sb->s_blocksize;
	const char *name = dp->d_name.name;
	int namelen = dp->d_name.len;
	loff_t limit = VXFS_DIRROUND(ip->i_size);
	struct vxfs_direct *de_exit = NULL;
	loff_t pos = 0;
	struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);

	while (pos < limit) {
		struct page *pp;
		char *kaddr;
		int pg_ofs = pos & ~PAGE_MASK;

		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
		if (IS_ERR(pp))
			return NULL;
		kaddr = (char *)page_address(pp);

		while (pg_ofs < PAGE_SIZE && pos < limit) {
			struct vxfs_direct *de;

			if ((pos & (bsize - 1)) < 4) {
				struct vxfs_dirblk *dbp =
					(struct vxfs_dirblk *)
					 (kaddr + (pos & ~PAGE_MASK));
				int overhead = VXFS_DIRBLKOV(sbi, dbp);

				pos += overhead;
				pg_ofs += overhead;
			}
			de = (struct vxfs_direct *)(kaddr + pg_ofs);

			if (!de->d_reclen) {
				pos += bsize - 1;
				pos &= ~(bsize - 1);
				break;
			}

			pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
			pos += fs16_to_cpu(sbi, de->d_reclen);
			if (!de->d_ino)
				continue;

			if (namelen != fs16_to_cpu(sbi, de->d_namelen))
				continue;
			if (!memcmp(name, de->d_name, namelen)) {
				*ppp = pp;
				de_exit = de;
				break;
			}
		}
		if (!de_exit)
			vxfs_put_page(pp);
		else
			break;
	}

	return de_exit;
}
Beispiel #10
0
/**
 * vxfs_readdir - read a directory
 * @fp:		the directory to read
 * @retp:	return buffer
 * @filler:	filldir callback
 *
 * Description:
 *   vxfs_readdir fills @retp with directory entries from @fp
 *   using the VFS supplied callback @filler.
 *
 * Returns:
 *   Zero.
 */
static int
vxfs_readdir(struct file *fp, struct dir_context *ctx)
{
	struct inode		*ip = file_inode(fp);
	struct super_block	*sbp = ip->i_sb;
	u_long			bsize = sbp->s_blocksize;
	loff_t			pos, limit;
	struct vxfs_sb_info	*sbi = VXFS_SBI(sbp);

	if (ctx->pos == 0) {
		if (!dir_emit_dot(fp, ctx))
			goto out;
		ctx->pos++;
	}
	if (ctx->pos == 1) {
		if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
			goto out;
		ctx->pos++;
	}

	limit = VXFS_DIRROUND(ip->i_size);
	if (ctx->pos > limit)
		goto out;

	pos = ctx->pos & ~3L;

	while (pos < limit) {
		struct page *pp;
		char *kaddr;
		int pg_ofs = pos & ~PAGE_MASK;
		int rc = 0;

		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
		if (IS_ERR(pp))
			return -ENOMEM;

		kaddr = (char *)page_address(pp);

		while (pg_ofs < PAGE_SIZE && pos < limit) {
			struct vxfs_direct *de;

			if ((pos & (bsize - 1)) < 4) {
				struct vxfs_dirblk *dbp =
					(struct vxfs_dirblk *)
					 (kaddr + (pos & ~PAGE_MASK));
				int overhead = VXFS_DIRBLKOV(sbi, dbp);

				pos += overhead;
				pg_ofs += overhead;
			}
			de = (struct vxfs_direct *)(kaddr + pg_ofs);

			if (!de->d_reclen) {
				pos += bsize - 1;
				pos &= ~(bsize - 1);
				break;
			}

			pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
			pos += fs16_to_cpu(sbi, de->d_reclen);
			if (!de->d_ino)
				continue;

			rc = dir_emit(ctx, de->d_name,
					fs16_to_cpu(sbi, de->d_namelen),
					fs32_to_cpu(sbi, de->d_ino),
					DT_UNKNOWN);
			if (!rc) {
				/* the dir entry was not read, fix pos. */
				pos -= fs16_to_cpu(sbi, de->d_reclen);
				break;
			}
		}
		vxfs_put_page(pp);
		if (!rc)
			break;
	}

	ctx->pos = pos | 2;

out:
	return 0;
}
Beispiel #11
0
/**
 * vxfs_stiget - find inode using the structural inode list
 * @sbp:	VFS superblock
 * @ino:	inode #
 *
 * Description:
 *  Find inode @ino in the filesystem described by @sbp using
 *  the structural inode list.
 *  Returns the matching VxFS inode on success, else a NULL pointer.
 */
struct vxfs_inode_info *
vxfs_stiget(struct super_block *sbp, ino_t ino)
{
        return __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
}
/**
 * vxfs_read_fshead - read the fileset headers
 * @sbp:	superblock to which the fileset belongs
 *
 * Description:
 *   vxfs_read_fshead will fill the inode and structural inode list in @sb.
 *
 * Returns:
 *   Zero on success, else a negative error code (-EINVAL).
 */
int
vxfs_read_fshead(struct super_block *sbp)
{
	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
	struct vxfs_fsh			*pfp, *sfp;
	struct vxfs_inode_info		*vip, *tip;

	if (!(vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino))) {
		printk(KERN_ERR "vxfs: unabled to read fsh inode\n");
		return -EINVAL;
	} else if (!VXFS_ISFSH(vip)) {
		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
				vip->vii_mode & VXFS_TYPE_MASK); 
		return -EINVAL;
	}


#ifdef DIAGNOSTIC
	printk("vxfs: fsh inode dump:\n");
	vxfs_dumpi(vip, infp->vsi_fshino);
#endif

	if (!(infp->vsi_fship = vxfs_get_fake_inode(sbp, vip))) {
		printk(KERN_ERR "vxfs: unabled to get fsh inode\n");
		return -EINVAL;
	}

	if (!(sfp = vxfs_getfsh(infp->vsi_fship, 0))) {
		printk(KERN_ERR "vxfs: unabled to get structural fsh\n");
		return -EINVAL;
	} 

#ifdef DIAGNOSTIC
	vxfs_dumpfsh(sfp);
#endif

	if (!(pfp = vxfs_getfsh(infp->vsi_fship, 1))) {
		printk(KERN_ERR "vxfs: unabled to get primary fsh\n");
		return -EINVAL;
	}

#ifdef DIAGNOSTIC
	vxfs_dumpfsh(pfp);
#endif

	tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
	if (!tip || ((infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip)) == NULL)) {
		printk(KERN_ERR "vxfs: unabled to get structual list inode\n");
		return -EINVAL;
	} else if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
		printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n",
				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 
		return -EINVAL;
	}

	tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
	if (!tip || ((infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip)) == NULL)) {
		printk(KERN_ERR "vxfs: unabled to get inode list inode\n");
		return -EINVAL;
	} else if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
		return -EINVAL;
	}

	return 0;
}
/**
 * vxfs_read_fshead - read the fileset headers
 * @sbp:	superblock to which the fileset belongs
 *
 * Description:
 *   vxfs_read_fshead will fill the inode and structural inode list in @sb.
 *
 * Returns:
 *   Zero on success, else a negative error code (-EINVAL).
 */
int
vxfs_read_fshead(struct super_block *sbp)
{
	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
	struct vxfs_fsh			*pfp, *sfp;
	struct vxfs_inode_info		*vip, *tip;

	vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
	if (!vip) {
		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
		return -EINVAL;
	}
	if (!VXFS_ISFSH(vip)) {
		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
				vip->vii_mode & VXFS_TYPE_MASK); 
		goto out_free_fship;
	}


#ifdef DIAGNOSTIC
	printk(KERN_INFO "vxfs: fsh inode dump:\n");
	vxfs_dumpi(vip, infp->vsi_fshino);
#endif

	infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
	if (!infp->vsi_fship) {
		printk(KERN_ERR "vxfs: unable to get fsh inode\n");
		goto out_free_fship;
	}

	sfp = vxfs_getfsh(infp->vsi_fship, 0);
	if (!sfp) {
		printk(KERN_ERR "vxfs: unable to get structural fsh\n");
		goto out_iput_fship;
	} 

#ifdef DIAGNOSTIC
	vxfs_dumpfsh(sfp);
#endif

	pfp = vxfs_getfsh(infp->vsi_fship, 1);
	if (!pfp) {
		printk(KERN_ERR "vxfs: unable to get primary fsh\n");
		goto out_free_sfp;
	}

#ifdef DIAGNOSTIC
	vxfs_dumpfsh(pfp);
#endif

	tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
	if (!tip)
		goto out_free_pfp;

	infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
	if (!infp->vsi_stilist) {
		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
		kfree(tip);
		goto out_free_pfp;
	}
	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
		printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n",
				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 
		goto out_iput_stilist;
	}

	tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
	if (!tip)
		goto out_iput_stilist;
	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
	if (!infp->vsi_ilist) {
		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
		kfree(tip);
		goto out_iput_stilist;
	}
	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
		goto out_iput_ilist;
	}

	return 0;

 out_iput_ilist:
 	iput(infp->vsi_ilist);
 out_iput_stilist:
 	iput(infp->vsi_stilist);
 out_free_pfp:
	kfree(pfp);
 out_free_sfp:
 	kfree(sfp);
 out_iput_fship:
	iput(infp->vsi_fship);
	return -EINVAL;
 out_free_fship:
 	kfree(vip);
	return -EINVAL;
}