Exemplo n.º 1
0
static int
udf_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
{
	struct vnode *devvp;	/* vnode of the mount device */
	struct udf_args args;
	struct udf_mnt *imp = NULL;
	size_t size;
	int error;
	struct nlookupdata nd;

	if ((mp->mnt_flag & MNT_RDONLY) == 0)
		return (EROFS);

	/*
	 * No root filesystem support.  Probably not a big deal, since the
	 * bootloader doesn't understand UDF.
	 */
	if (mp->mnt_flag & MNT_ROOTFS)
		return (ENOTSUP);

	if ((error = copyin(data, (caddr_t)&args, sizeof(struct udf_args))))
		return(error);

	if (mp->mnt_flag & MNT_UPDATE) {
		imp = VFSTOUDFFS(mp);
		if (args.fspec == NULL)
			return(vfs_export(mp, &imp->im_export, &args.export));
	}
Exemplo n.º 2
0
static int
udf_root(struct mount *mp, int flags, struct vnode **vpp)
{
	struct udf_mnt *udfmp;
	ino_t id;

	udfmp = VFSTOUDFFS(mp);

	id = udf_getid(&udfmp->root_icb);

	return (udf_vget(mp, id, flags, vpp));
}
Exemplo n.º 3
0
static int
udf_statfs(struct mount *mp, struct statfs *sbp)
{
	struct udf_mnt *udfmp;

	udfmp = VFSTOUDFFS(mp);

	sbp->f_bsize = udfmp->bsize;
	sbp->f_iosize = udfmp->bsize;
	sbp->f_blocks = udfmp->part_len;
	sbp->f_bfree = 0;
	sbp->f_bavail = 0;
	sbp->f_files = 0;
	sbp->f_ffree = 0;
	return 0;
}
Exemplo n.º 4
0
int
udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
{
	struct umount *ump;

	ump = VFSTOUDFFS(mp);

	sbp->f_bsize = ump->um_bsize;
	sbp->f_iosize = ump->um_bsize;
	sbp->f_blocks = ump->um_len;
	sbp->f_bfree = 0;
	sbp->f_bavail = 0;
	sbp->f_files = 0;
	sbp->f_ffree = 0;

	return (0);
}
Exemplo n.º 5
0
static int
udf_unmount(struct mount *mp, int mntflags)
{
	struct udf_mnt *udfmp;
	int error, flags = 0;

	udfmp = VFSTOUDFFS(mp);

	if (mntflags & MNT_FORCE)
		flags |= FORCECLOSE;

	if ((error = vflush(mp, 0, flags, curthread)))
		return (error);

	if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) {
		if (udfmp->im_d2l)
			udf_iconv->close(udfmp->im_d2l);
#if 0
		if (udfmp->im_l2d)
			udf_iconv->close(udfmp->im_l2d);
#endif
	}

	DROP_GIANT();
	g_topology_lock();
	g_vfs_close(udfmp->im_cp);
	g_topology_unlock();
	PICKUP_GIANT();
	vrele(udfmp->im_devvp);
	dev_rel(udfmp->im_dev);

	if (udfmp->s_table != NULL)
		free(udfmp->s_table, M_UDFMOUNT);

	free(udfmp, M_UDFMOUNT);

	mp->mnt_data = NULL;
	MNT_ILOCK(mp);
	mp->mnt_flag &= ~MNT_LOCAL;
	MNT_IUNLOCK(mp);

	return (0);
}
Exemplo n.º 6
0
int
udf_unmount(struct mount *mp, int mntflags, struct proc *p)
{
	struct umount *ump;
	struct vnode *devvp;
	int error, flags = 0;

	ump = VFSTOUDFFS(mp);
	devvp = ump->um_devvp;

	if (mntflags & MNT_FORCE)
		flags |= FORCECLOSE;

	if ((error = vflush(mp, NULL, flags)))
		return (error);

	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
	vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0);
	error = VOP_CLOSE(devvp, FREAD, NOCRED, p);
	VOP_UNLOCK(devvp, 0, p);
	if (error)
		return (error);

	devvp->v_specmountpoint = NULL;
	vrele(devvp);

	if (ump->um_flags & UDF_MNT_USES_VAT)
		free(ump->um_vat, M_UDFMOUNT);

	if (ump->um_stbl != NULL)
		free(ump->um_stbl, M_UDFMOUNT);

	if (ump->um_hashtbl != NULL)
		free(ump->um_hashtbl, M_UDFMOUNT);

	free(ump, M_UDFMOUNT);

	mp->mnt_data = (qaddr_t)0;
	mp->mnt_flag &= ~MNT_LOCAL;

	return (0);
}
Exemplo n.º 7
0
int
udf_root(struct mount *mp, struct vnode **vpp)
{
	struct umount *ump;
	struct vnode *vp;
	ino_t id;
	int error;

	ump = VFSTOUDFFS(mp);

	id = udf_getid(&ump->um_root_icb);

	error = udf_vget(mp, id, vpp);
	if (error)
		return (error);

	vp = *vpp;
	vp->v_flag |= VROOT;

	return (0);
}
Exemplo n.º 8
0
static int
udf_mount(struct mount *mp, struct nameidata *ndp, struct thread *td)
{
	struct vnode *devvp;	/* vnode of the mount device */
	struct udf_mnt *imp = 0;
	struct export_args *export;
	struct vfsoptlist *opts;
	char *fspec;
	size_t size;
	int error, len;

	opts = mp->mnt_optnew;

	if ((mp->mnt_flag & MNT_RDONLY) == 0)
		return (EROFS);

	/*
	 * No root filesystem support.  Probably not a big deal, since the
	 * bootloader doesn't understand UDF.
	 */
	if (mp->mnt_flag & MNT_ROOTFS)
		return (ENOTSUP);

	fspec = NULL;
	error = vfs_getopt(opts, "from", (void **)&fspec, &len);
	if (!error && fspec[len - 1] != '\0')
		return (EINVAL);

	if (mp->mnt_flag & MNT_UPDATE) {
		imp = VFSTOUDFFS(mp);
		if (fspec == NULL) {
			error = vfs_getopt(opts, "export", (void **)&export,
			    &len);
			if (error || len != sizeof(struct export_args))
				return (EINVAL);
			return (vfs_export(mp, export));
		}
Exemplo n.º 9
0
int
udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
{
	struct buf *bp;
	struct vnode *devvp;
	struct umount *ump;
	struct proc *p;
	struct vnode *vp, *nvp;
	struct unode *up;
	struct extfile_entry *xfe;
	struct file_entry *fe;
	int error, sector, size;

	p = curproc;
	bp = NULL;
	*vpp = NULL;
	ump = VFSTOUDFFS(mp);

	/* See if we already have this in the cache */
	if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
		return (error);
	if (*vpp != NULL)
		return (0);

	/*
	 * Allocate memory and check the tag id's before grabbing a new
	 * vnode, since it's hard to roll back if there is a problem.
	 */
	up = pool_get(&unode_pool, PR_WAITOK | PR_ZERO);

	/*
	 * Copy in the file entry.  Per the spec, the size can only be 1 block.
	 */
	sector = ino;
	devvp = ump->um_devvp;
	udf_vat_map(ump, &sector);
	if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
		printf("Cannot read sector %d\n", sector);
		pool_put(&unode_pool, up);
		if (bp != NULL)
			brelse(bp);
		return (error);
	}

	xfe = (struct extfile_entry *)bp->b_data;
	fe = (struct file_entry *)bp->b_data;
	error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY);
	if (error == 0) {
		size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad);
	} else {
		error = udf_checktag(&fe->tag, TAGID_FENTRY);
		if (error) {
			printf("Invalid file entry!\n");
			pool_put(&unode_pool, up);
			if (bp != NULL)
				brelse(bp);
			return (ENOMEM);
		} else
			size = letoh32(fe->l_ea) + letoh32(fe->l_ad);
	}

	/* Allocate max size of FE/XFE. */
	up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO);
	if (up->u_fentry == NULL) {
		pool_put(&unode_pool, up);
		if (bp != NULL)
			brelse(bp);
		return (ENOMEM); /* Cannot allocate file entry block */
	}

	if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0)
		bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE);
	else
		bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE);
	
	brelse(bp);
	bp = NULL;

	if ((error = udf_allocv(mp, &vp, p))) {
		free(up->u_fentry, M_UDFFENTRY);
		pool_put(&unode_pool, up);
		return (error); /* Error from udf_allocv() */
	}

	up->u_vnode = vp;
	up->u_ino = ino;
	up->u_devvp = ump->um_devvp;
	up->u_dev = ump->um_dev;
	up->u_ump = ump;
	vp->v_data = up;
	vref(ump->um_devvp);

	lockinit(&up->u_lock, PINOD, "unode", 0, 0);

	/*
	 * udf_hashins() will lock the vnode for us.
	 */
	udf_hashins(up);

	switch (up->u_fentry->icbtag.file_type) {
	default:
		printf("Unrecognized file type (%d)\n", vp->v_type);
		vp->v_type = VREG;
		break;
	case UDF_ICB_FILETYPE_DIRECTORY:
		vp->v_type = VDIR;
		break;
	case UDF_ICB_FILETYPE_BLOCKDEVICE:
		vp->v_type = VBLK;
		break;
	case UDF_ICB_FILETYPE_CHARDEVICE:
		vp->v_type = VCHR;
		break;
	case UDF_ICB_FILETYPE_FIFO:
		vp->v_type = VFIFO;
		break;
	case UDF_ICB_FILETYPE_SOCKET:
		vp->v_type = VSOCK;
		break;
	case UDF_ICB_FILETYPE_SYMLINK:
		vp->v_type = VLNK;
		break;
	case UDF_ICB_FILETYPE_RANDOMACCESS:
	case UDF_ICB_FILETYPE_REALTIME:
	case UDF_ICB_FILETYPE_UNKNOWN:
		vp->v_type = VREG;
		break;
	}

	/* check if this is a vnode alias */
	if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) {
		printf("found a vnode alias\n");
		/*
		 * Discard unneeded vnode, but save its udf_node.
		 * Note that the lock is carried over in the udf_node
		 */
		nvp->v_data = vp->v_data;
		vp->v_data = NULL;
		vp->v_op = spec_vnodeop_p;
		vrele(vp);
		vgone(vp);
		/*
		 * Reinitialize aliased inode.
		 */
		vp = nvp;
		ump->um_devvp = vp;
	}

	*vpp = vp;

	return (0);
}
Exemplo n.º 10
0
int
udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
{
	struct buf *bp;
	struct vnode *devvp;
	struct udf_mnt *udfmp;
	struct thread *td;
	struct vnode *vp;
	struct udf_node *unode;
	struct file_entry *fe;
	int error, sector, size;

	error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL);
	if (error || *vpp != NULL)
		return (error);

	/*
	 * We must promote to an exclusive lock for vnode creation.  This
	 * can happen if lookup is passed LOCKSHARED.
 	 */
	if ((flags & LK_TYPE_MASK) == LK_SHARED) {
		flags &= ~LK_TYPE_MASK;
		flags |= LK_EXCLUSIVE;
	}

	/*
	 * We do not lock vnode creation as it is believed to be too
	 * expensive for such rare case as simultaneous creation of vnode
	 * for same ino by different processes. We just allow them to race
	 * and check later to decide who wins. Let the race begin!
	 */

	td = curthread;
	udfmp = VFSTOUDFFS(mp);

	unode = uma_zalloc(udf_zone_node, M_WAITOK | M_ZERO);

	if ((error = udf_allocv(mp, &vp, td))) {
		printf("Error from udf_allocv\n");
		uma_zfree(udf_zone_node, unode);
		return (error);
	}

	unode->i_vnode = vp;
	unode->hash_id = ino;
	unode->udfmp = udfmp;
	vp->v_data = unode;

	lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
	error = insmntque(vp, mp);
	if (error != 0) {
		uma_zfree(udf_zone_node, unode);
		return (error);
	}
	error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
	if (error || *vpp != NULL)
		return (error);

	/*
	 * Copy in the file entry.  Per the spec, the size can only be 1 block.
	 */
	sector = ino + udfmp->part_start;
	devvp = udfmp->im_devvp;
	if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
		printf("Cannot read sector %d\n", sector);
		vgone(vp);
		vput(vp);
		brelse(bp);
		*vpp = NULL;
		return (error);
	}

	fe = (struct file_entry *)bp->b_data;
	if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
		printf("Invalid file entry!\n");
		vgone(vp);
		vput(vp);
		brelse(bp);
		*vpp = NULL;
		return (ENOMEM);
	}
	size = UDF_FENTRY_SIZE + le32toh(fe->l_ea) + le32toh(fe->l_ad);
	unode->fentry = malloc(size, M_UDFFENTRY, M_NOWAIT | M_ZERO);
	if (unode->fentry == NULL) {
		printf("Cannot allocate file entry block\n");
		vgone(vp);
		vput(vp);
		brelse(bp);
		*vpp = NULL;
		return (ENOMEM);
	}

	bcopy(bp->b_data, unode->fentry, size);
	
	brelse(bp);
	bp = NULL;

	switch (unode->fentry->icbtag.file_type) {
	default:
		vp->v_type = VBAD;
		break;
	case 4:
		vp->v_type = VDIR;
		break;
	case 5:
		vp->v_type = VREG;
		break;
	case 6:
		vp->v_type = VBLK;
		break;
	case 7:
		vp->v_type = VCHR;
		break;
	case 9:
		vp->v_type = VFIFO;
		vp->v_op = &udf_fifoops;
		break;
	case 10:
		vp->v_type = VSOCK;
		break;
	case 12:
		vp->v_type = VLNK;
		break;
	}

	if (vp->v_type != VFIFO)
		VN_LOCK_ASHARE(vp);

	if (ino == udf_getid(&udfmp->root_icb))
		vp->v_vflag |= VV_ROOT;

	*vpp = vp;

	return (0);
}
Exemplo n.º 11
0
static int
udf_mount(struct mount *mp)
{
	struct vnode *devvp;	/* vnode of the mount device */
	struct thread *td;
	struct udf_mnt *imp = NULL;
	struct vfsoptlist *opts;
	char *fspec, *cs_disk, *cs_local;
	int error, len, *udf_flags;
	struct nameidata nd, *ndp = &nd;

	td = curthread;
	opts = mp->mnt_optnew;

	/*
	 * Unconditionally mount as read-only.
	 */
	MNT_ILOCK(mp);
	mp->mnt_flag |= MNT_RDONLY;
	MNT_IUNLOCK(mp);

	/*
	 * No root filesystem support.  Probably not a big deal, since the
	 * bootloader doesn't understand UDF.
	 */
	if (mp->mnt_flag & MNT_ROOTFS)
		return (ENOTSUP);

	fspec = NULL;
	error = vfs_getopt(opts, "from", (void **)&fspec, &len);
	if (!error && fspec[len - 1] != '\0')
		return (EINVAL);

	if (mp->mnt_flag & MNT_UPDATE) {
		return (0);
	}

	/* Check that the mount device exists */
	if (fspec == NULL)
		return (EINVAL);
	NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
	if ((error = namei(ndp)))
		return (error);
	NDFREE(ndp, NDF_ONLY_PNBUF);
	devvp = ndp->ni_vp;

	if (vn_isdisk(devvp, &error) == 0) {
		vput(devvp);
		return (error);
	}

	/* Check the access rights on the mount device */
	error = VOP_ACCESS(devvp, VREAD, td->td_ucred, td);
	if (error)
		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
	if (error) {
		vput(devvp);
		return (error);
	}

	if ((error = udf_mountfs(devvp, mp))) {
		vrele(devvp);
		return (error);
	}

	imp = VFSTOUDFFS(mp);

	udf_flags = NULL;
	error = vfs_getopt(opts, "flags", (void **)&udf_flags, &len);
	if (error || len != sizeof(int))
		return (EINVAL);
	imp->im_flags = *udf_flags;

	if (imp->im_flags & UDFMNT_KICONV && udf_iconv) {
		cs_disk = NULL;
		error = vfs_getopt(opts, "cs_disk", (void **)&cs_disk, &len);
		if (!error && cs_disk[len - 1] != '\0')
			return (EINVAL);
		cs_local = NULL;
		error = vfs_getopt(opts, "cs_local", (void **)&cs_local, &len);
		if (!error && cs_local[len - 1] != '\0')
			return (EINVAL);
		udf_iconv->open(cs_local, cs_disk, &imp->im_d2l);
#if 0
		udf_iconv->open(cs_disk, cs_local, &imp->im_l2d);
#endif
	}

	vfs_mountedfrom(mp, fspec);
	return 0;
};
Exemplo n.º 12
0
int
udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
{
	struct buf *bp;
	struct vnode *devvp;
	struct umount *ump;
	struct proc *p;
	struct vnode *vp;
	struct unode *up;
	struct file_entry *fe;
	int error, sector, size;

	p = curproc;
	bp = NULL;
	*vpp = NULL;
	ump = VFSTOUDFFS(mp);

	/* See if we already have this in the cache */
	if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
		return (error);
	if (*vpp != NULL)
		return (0);

	/*
	 * Allocate memory and check the tag id's before grabbing a new
	 * vnode, since it's hard to roll back if there is a problem.
	 */
	up = pool_get(&unode_pool, PR_WAITOK);
	bzero(up, sizeof(struct unode));

	/*
	 * Copy in the file entry.  Per the spec, the size can only be 1 block.
	 */
	sector = ino;
	devvp = ump->um_devvp;
	udf_vat_map(ump, &sector);
	if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
		printf("Cannot read sector %d\n", sector);
		pool_put(&unode_pool, up);
		if (bp != NULL)
			brelse(bp);
		return (error);
	}

	fe = (struct file_entry *)bp->b_data;
	if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
		printf("Invalid file entry!\n");
		pool_put(&unode_pool, up);
		brelse(bp);
		return (ENOMEM);
	}

	size = UDF_FENTRY_SIZE + letoh32(fe->l_ea) + letoh32(fe->l_ad);

	up->u_fentry = malloc(size, M_UDFFENTRY, M_NOWAIT);
	if (up->u_fentry == NULL) {
		pool_put(&unode_pool, up);
		brelse(bp);
		return (ENOMEM); /* Cannot allocate file entry block */
	}

	bcopy(bp->b_data, up->u_fentry, size);
	
	brelse(bp);
	bp = NULL;

	if ((error = udf_allocv(mp, &vp, p))) {
		free(up->u_fentry, M_UDFFENTRY);
		pool_put(&unode_pool, up);
		return (error); /* Error from udf_allocv() */
	}

	up->u_vnode = vp;
	up->u_ino = ino;
	up->u_devvp = ump->um_devvp;
	up->u_dev = ump->um_dev;
	up->u_ump = ump;
	vp->v_data = up;
	VREF(ump->um_devvp);

	lockinit(&up->u_lock, PINOD, "unode", 0, 0);

	/*
	 * udf_hashins() will lock the vnode for us.
	 */
	udf_hashins(up);

	switch (up->u_fentry->icbtag.file_type) {
	default:
		vp->v_type = VBAD;
		break;
	case UDF_ICB_TYPE_DIR:
		vp->v_type = VDIR;
		break;
	case UDF_ICB_TYPE_FILE:
		vp->v_type = VREG;
		break;
	case UDF_ICB_TYPE_BLKDEV:
		vp->v_type = VBLK;
		break;
	case UDF_ICB_TYPE_CHRDEV:
		vp->v_type = VCHR;
		break;
	case UDF_ICB_TYPE_FIFO:
		vp->v_type = VFIFO;
		break;
	case UDF_ICB_TYPE_SOCKET:
		vp->v_type = VSOCK;
		break;
	case UDF_ICB_TYPE_SYMLINK:
		vp->v_type = VLNK;
		break;
	case UDF_ICB_TYPE_VAT_150:
		vp->v_type = VREG;
		break;
	}

	*vpp = vp;

	return (0);
}