xref: /openbsd/sys/isofs/udf/udf_vfsops.c (revision d89ec533)
1 /*	$OpenBSD: udf_vfsops.c,v 1.69 2020/06/23 16:31:06 krw Exp $	*/
2 
3 /*
4  * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.25 2005/01/25 15:52:03 phk Exp $
29  */
30 
31 /*
32  * Ported to OpenBSD by Pedro Martelletto in February 2005.
33  */
34 
35 /*
36  * Ok, here's how it goes.  The UDF specs are pretty clear on how each data
37  * structure is made up, but not very clear on how they relate to each other.
38  * Here is the skinny... This demostrates a filesystem with one file in the
39  * root directory.  Subdirectories are treated just as normal files, but they
40  * have File Id Descriptors of their children as their file data.  As for the
41  * Anchor Volume Descriptor Pointer, it can exist in two of the following three
42  * places: sector 256, sector n (the max sector of the disk), or sector
43  * n - 256.  It's a pretty good bet that one will exist at sector 256 though.
44  * One caveat is unclosed CD media.  For that, sector 256 cannot be written,
45  * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the
46  * media is closed.
47  */
48 
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/uio.h>
52 #include <sys/buf.h>
53 #include <sys/dirent.h>
54 #include <sys/fcntl.h>
55 #include <sys/kernel.h>
56 #include <sys/malloc.h>
57 #include <sys/mutex.h>
58 #include <sys/mount.h>
59 #include <sys/namei.h>
60 #include <sys/pool.h>
61 #include <sys/proc.h>
62 #include <sys/lock.h>
63 #include <sys/queue.h>
64 #include <sys/vnode.h>
65 #include <sys/lock.h>
66 #include <sys/endian.h>
67 #include <sys/specdev.h>
68 
69 #include <crypto/siphash.h>
70 
71 #include <isofs/udf/ecma167-udf.h>
72 #include <isofs/udf/udf.h>
73 #include <isofs/udf/udf_extern.h>
74 
75 struct pool udf_trans_pool;
76 struct pool unode_pool;
77 struct pool udf_ds_pool;
78 
79 int udf_find_partmaps(struct umount *, struct logvol_desc *);
80 int udf_get_vpartmap(struct umount *, struct part_map_virt *);
81 int udf_get_spartmap(struct umount *, struct part_map_spare *);
82 int udf_get_mpartmap(struct umount *, struct part_map_meta *);
83 int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *);
84 
85 const struct vfsops udf_vfsops = {
86 	.vfs_mount	= udf_mount,
87 	.vfs_start	= udf_start,
88 	.vfs_unmount	= udf_unmount,
89 	.vfs_root	= udf_root,
90 	.vfs_quotactl	= udf_quotactl,
91 	.vfs_statfs	= udf_statfs,
92 	.vfs_sync	= udf_sync,
93 	.vfs_vget	= udf_vget,
94 	.vfs_fhtovp	= udf_fhtovp,
95 	.vfs_vptofh	= udf_vptofh,
96 	.vfs_init	= udf_init,
97 	.vfs_sysctl	= udf_sysctl,
98 	.vfs_checkexp	= udf_checkexp,
99 };
100 
101 int
102 udf_init(struct vfsconf *foo)
103 {
104 	pool_init(&udf_trans_pool, MAXNAMLEN * sizeof(unicode_t), 0, IPL_NONE,
105 	    PR_WAITOK, "udftrpl", NULL);
106 	pool_init(&unode_pool, sizeof(struct unode), 0, IPL_NONE,
107 	    PR_WAITOK, "udfndpl", NULL);
108 	pool_init(&udf_ds_pool, sizeof(struct udf_dirstream), 0, IPL_NONE,
109 	    PR_WAITOK, "udfdspl", NULL);
110 
111 	return (0);
112 }
113 
114 int
115 udf_start(struct mount *mp, int flags, struct proc *p)
116 {
117 	return (0);
118 }
119 
120 int
121 udf_mount(struct mount *mp, const char *path, void *data,
122     struct nameidata *ndp,  struct proc *p)
123 {
124 	struct vnode *devvp;	/* vnode of the mount device */
125 	struct udf_args *args = data;
126 	char fspec[MNAMELEN];
127 	int error;
128 
129 	if ((mp->mnt_flag & MNT_RDONLY) == 0) {
130 		mp->mnt_flag |= MNT_RDONLY;
131 #ifdef UDF_DEBUG
132 		printf("udf_mount: enforcing read-only mode\n");
133 #endif
134 	}
135 
136 	/*
137 	 * No root filesystem support.  Probably not a big deal, since the
138 	 * bootloader doesn't understand UDF.
139 	 */
140 	if (mp->mnt_flag & MNT_ROOTFS)
141 		return (EOPNOTSUPP);
142 
143 	/*
144 	 * If updating, check whether changing from read-only to
145 	 * read/write; if there is no device name, that's all we do.
146 	 */
147 	if (mp->mnt_flag & MNT_UPDATE) {
148 		return (0);
149 	}
150 
151 	error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
152 	if (error)
153 		return (error);
154 
155 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p);
156 	if ((error = namei(ndp)))
157 		return (error);
158 
159 	devvp = ndp->ni_vp;
160 	if (devvp->v_type != VBLK) {
161 		vrele(devvp);
162 		return (ENOTBLK);
163 	}
164 
165 	if (major(devvp->v_rdev) >= nblkdev) {
166 		vrele(devvp);
167 		return (ENXIO);
168 	}
169 
170 	if ((error = udf_mountfs(devvp, mp, args->lastblock, p))) {
171 		vrele(devvp);
172 		return (error);
173 	}
174 
175 	/*
176 	 * Keep a copy of the mount information.
177 	 */
178 	bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
179 	strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
180 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
181 	strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
182 	bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
183 	strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
184 
185 	return (0);
186 };
187 
188 /*
189  * Check the descriptor tag for both the correct id and correct checksum.
190  * Return zero if all is good, EINVAL if not.
191  */
192 int
193 udf_checktag(struct desc_tag *tag, uint16_t id)
194 {
195 	uint8_t *itag;
196 	uint8_t i, cksum = 0;
197 
198 	itag = (uint8_t *)tag;
199 
200 	if (letoh16(tag->id) != id)
201 		return (EINVAL);
202 
203 	for (i = 0; i < 15; i++)
204 		cksum = cksum + itag[i];
205 	cksum = cksum - itag[4];
206 
207 	if (cksum == tag->cksum)
208 		return (0);
209 
210 	return (EINVAL);
211 }
212 
213 int
214 udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
215 {
216 	struct buf *bp = NULL;
217 	struct anchor_vdp avdp;
218 	struct umount *ump = NULL;
219 	struct part_desc *pd;
220 	struct logvol_desc *lvd;
221 	struct fileset_desc *fsd;
222 	struct extfile_entry *xfentry;
223 	struct file_entry *fentry;
224 	uint32_t sector, size, mvds_start, mvds_end;
225 	uint32_t fsd_offset = 0;
226 	uint16_t part_num = 0, fsd_part = 0;
227 	int error = EINVAL;
228 	int logvol_found = 0, part_found = 0, fsd_found = 0;
229 	int bsize;
230 
231 	/*
232 	 * Disallow multiple mounts of the same device.
233 	 * Disallow mounting of a device that is currently in use
234 	 * (except for root, which might share swap device for miniroot).
235 	 * Flush out any old buffers remaining from a previous use.
236 	 */
237 	if ((error = vfs_mountedon(devvp)))
238 		return (error);
239 	if (vcount(devvp) > 1 && devvp != rootvp)
240 		return (EBUSY);
241 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
242 	error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, INFSLP);
243 	VOP_UNLOCK(devvp);
244 	if (error)
245 		return (error);
246 
247 	error = VOP_OPEN(devvp, FREAD, FSCRED, p);
248 	if (error)
249 		return (error);
250 
251 	ump = malloc(sizeof(*ump), M_UDFMOUNT, M_WAITOK | M_ZERO);
252 
253 	mp->mnt_data = ump;
254 	mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
255 	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
256 	mp->mnt_stat.f_namemax = NAME_MAX;
257 	mp->mnt_flag |= MNT_LOCAL;
258 
259 	ump->um_mountp = mp;
260 	ump->um_dev = devvp->v_rdev;
261 	ump->um_devvp = devvp;
262 
263 	bsize = 2048;	/* Should probe the media for its size. */
264 
265 	/*
266 	 * Get the Anchor Volume Descriptor Pointer from sector 256.
267 	 * Should also check sector n - 256, n, and 512.
268 	 */
269 	sector = 256;
270 	if ((error = bread(devvp, sector * btodb(bsize), bsize, &bp)) != 0)
271 		goto bail;
272 	if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
273 		goto bail;
274 
275 	bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
276 	brelse(bp);
277 	bp = NULL;
278 
279 	/*
280 	 * Extract the Partition Descriptor and Logical Volume Descriptor
281 	 * from the Volume Descriptor Sequence.
282 	 * Should we care about the partition type right now?
283 	 * What about multiple partitions?
284 	 */
285 	mvds_start = letoh32(avdp.main_vds_ex.loc);
286 	mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
287 	for (sector = mvds_start; sector < mvds_end; sector++) {
288 		if ((error = bread(devvp, sector * btodb(bsize), bsize,
289 				   &bp)) != 0) {
290 			printf("Can't read sector %d of VDS\n", sector);
291 			goto bail;
292 		}
293 		lvd = (struct logvol_desc *)bp->b_data;
294 		if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
295 			ump->um_bsize = letoh32(lvd->lb_size);
296 			ump->um_bmask = ump->um_bsize - 1;
297 			ump->um_bshift = ffs(ump->um_bsize) - 1;
298 			fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num);
299 			fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num);
300 			if (udf_find_partmaps(ump, lvd))
301 				break;
302 			logvol_found = 1;
303 		}
304 		pd = (struct part_desc *)bp->b_data;
305 		if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
306 			part_found = 1;
307 			part_num = letoh16(pd->part_num);
308 			ump->um_len = ump->um_reallen = letoh32(pd->part_len);
309 			ump->um_start = ump->um_realstart = letoh32(pd->start_loc);
310 		}
311 
312 		brelse(bp);
313 		bp = NULL;
314 		if ((part_found) && (logvol_found))
315 			break;
316 	}
317 
318 	if (!part_found || !logvol_found) {
319 		error = EINVAL;
320 		goto bail;
321 	}
322 
323 	if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
324 		/* Read Metadata File 'File Entry' to find Metadata file. */
325 		struct long_ad *la;
326 		sector = ump->um_start + ump->um_meta_start; /* Set in udf_get_mpartmap() */
327 		if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
328 			printf("Cannot read sector %d for Metadata File Entry\n", sector);
329 			error = EINVAL;
330 			goto bail;
331 		}
332 		xfentry = (struct extfile_entry *)bp->b_data;
333 		fentry = (struct file_entry *)bp->b_data;
334 		if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0)
335 			la = (struct long_ad *)&xfentry->data[letoh32(xfentry->l_ea)];
336 		else if (udf_checktag(&fentry->tag, TAGID_FENTRY) == 0)
337 			la = (struct long_ad *)&fentry->data[letoh32(fentry->l_ea)];
338 		else {
339 			printf("Invalid Metadata File FE @ sector %d! (tag.id %d)\n",
340 			    sector, fentry->tag.id);
341 			error = EINVAL;
342 			goto bail;
343 		}
344 		ump->um_meta_start = letoh32(la->loc.lb_num);
345 		ump->um_meta_len = letoh32(la->len);
346 		if (bp != NULL) {
347 			brelse(bp);
348 			bp = NULL;
349 		}
350 	} else if (fsd_part != part_num) {
351 		printf("FSD does not lie within the partition!\n");
352 		error = EINVAL;
353 		goto bail;
354 	}
355 
356 	mtx_init(&ump->um_hashmtx, IPL_NONE);
357 	ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
358 	    &ump->um_hashsz);
359 	arc4random_buf(&ump->um_hashkey, sizeof(ump->um_hashkey));
360 
361 	/* Get the VAT, if needed */
362 	if (ump->um_flags & UDF_MNT_FIND_VAT) {
363 		error = udf_vat_get(ump, lb);
364 		if (error)
365 			goto bail;
366 	}
367 
368 	/*
369 	 * Grab the Fileset Descriptor
370 	 * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
371 	 * me in the right direction here.
372 	 */
373 
374 	if (ISSET(ump->um_flags, UDF_MNT_USES_META))
375 		sector = ump->um_meta_start;
376 	else
377 		sector = fsd_offset;
378 	udf_vat_map(ump, &sector);
379 	if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
380 		printf("Cannot read sector %d of FSD\n", sector);
381 		goto bail;
382 	}
383 	fsd = (struct fileset_desc *)bp->b_data;
384 	if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
385 		fsd_found = 1;
386 		bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
387 		    sizeof(struct long_ad));
388 		if (ISSET(ump->um_flags, UDF_MNT_USES_META)) {
389 			ump->um_root_icb.loc.lb_num += ump->um_meta_start;
390 			ump->um_root_icb.loc.part_num = part_num;
391 		}
392 	}
393 
394 	brelse(bp);
395 	bp = NULL;
396 
397 	if (!fsd_found) {
398 		printf("Couldn't find the fsd\n");
399 		error = EINVAL;
400 		goto bail;
401 	}
402 
403 	/*
404 	 * Find the file entry for the root directory.
405 	 */
406 	sector = letoh32(ump->um_root_icb.loc.lb_num);
407 	size = letoh32(ump->um_root_icb.len);
408 	udf_vat_map(ump, &sector);
409 	if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) {
410 		printf("Cannot read sector %d\n", sector);
411 		goto bail;
412 	}
413 
414 	xfentry = (struct extfile_entry *)bp->b_data;
415 	fentry = (struct file_entry *)bp->b_data;
416 	error = udf_checktag(&xfentry->tag, TAGID_EXTFENTRY);
417 	if (error) {
418 	    	error = udf_checktag(&fentry->tag, TAGID_FENTRY);
419 		if (error) {
420 			printf("Invalid root file entry!\n");
421 			goto bail;
422 		}
423 	}
424 
425 	brelse(bp);
426 	bp = NULL;
427 
428 	devvp->v_specmountpoint = mp;
429 
430 	return (0);
431 
432 bail:
433 	if (ump != NULL) {
434 		hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE, M_UDFMOUNT);
435 		free(ump, M_UDFMOUNT, 0);
436 		mp->mnt_data = NULL;
437 		mp->mnt_flag &= ~MNT_LOCAL;
438 	}
439 	if (devvp->v_specinfo)
440 		devvp->v_specmountpoint = NULL;
441 	if (bp != NULL)
442 		brelse(bp);
443 
444 	vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY);
445 	VOP_CLOSE(devvp, FREAD, FSCRED, p);
446 	VOP_UNLOCK(devvp);
447 
448 	return (error);
449 }
450 
451 int
452 udf_unmount(struct mount *mp, int mntflags, struct proc *p)
453 {
454 	struct umount *ump;
455 	struct vnode *devvp;
456 	int error, flags = 0;
457 
458 	ump = VFSTOUDFFS(mp);
459 	devvp = ump->um_devvp;
460 
461 	if (mntflags & MNT_FORCE)
462 		flags |= FORCECLOSE;
463 
464 	if ((error = vflush(mp, NULL, flags)))
465 		return (error);
466 
467 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
468 	vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, INFSLP);
469 	(void)VOP_CLOSE(devvp, FREAD, NOCRED, p);
470 	VOP_UNLOCK(devvp);
471 
472 	devvp->v_specmountpoint = NULL;
473 	vrele(devvp);
474 
475 	if (ump->um_flags & UDF_MNT_USES_VAT)
476 		free(ump->um_vat, M_UDFMOUNT, 0);
477 
478 	if (ump->um_stbl != NULL)
479 		free(ump->um_stbl, M_UDFMOUNT, 0);
480 
481 	hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE, M_UDFMOUNT);
482 	free(ump, M_UDFMOUNT, 0);
483 
484 	mp->mnt_data = NULL;
485 	mp->mnt_flag &= ~MNT_LOCAL;
486 
487 	return (0);
488 }
489 
490 int
491 udf_root(struct mount *mp, struct vnode **vpp)
492 {
493 	struct umount *ump;
494 	struct vnode *vp;
495 	udfino_t id;
496 	int error;
497 
498 	ump = VFSTOUDFFS(mp);
499 
500 	id = udf_getid(&ump->um_root_icb);
501 
502 	error = udf_vget(mp, id, vpp);
503 	if (error)
504 		return (error);
505 
506 	vp = *vpp;
507 	vp->v_flag |= VROOT;
508 
509 	return (0);
510 }
511 
512 int
513 udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
514     struct proc *p)
515 {
516 	return (EOPNOTSUPP);
517 }
518 
519 int
520 udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
521 {
522 	struct umount *ump;
523 
524 	ump = VFSTOUDFFS(mp);
525 
526 	sbp->f_bsize = ump->um_bsize;
527 	sbp->f_iosize = ump->um_bsize;
528 	sbp->f_blocks = ump->um_len;
529 	sbp->f_bfree = 0;
530 	sbp->f_bavail = 0;
531 	sbp->f_files = 0;
532 	sbp->f_ffree = 0;
533 	sbp->f_favail = 0;
534 	copy_statfs_info(sbp, mp);
535 
536 	return (0);
537 }
538 
539 int
540 udf_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
541 {
542 	return (0);
543 }
544 
545 int
546 udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
547 {
548 	struct buf *bp;
549 	struct vnode *devvp;
550 	struct umount *ump;
551 	struct proc *p;
552 	struct vnode *vp, *nvp;
553 	struct unode *up;
554 	struct extfile_entry *xfe;
555 	struct file_entry *fe;
556 	uint32_t sector;
557 	int error, size;
558 
559 	if (ino > (udfino_t)-1)
560 		panic("udf_vget: alien ino_t %llu", (unsigned long long)ino);
561 
562 	p = curproc;
563 	bp = NULL;
564 	*vpp = NULL;
565 	ump = VFSTOUDFFS(mp);
566 
567 	/* See if we already have this in the cache */
568 	if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
569 		return (error);
570 	if (*vpp != NULL)
571 		return (0);
572 
573 	/*
574 	 * Allocate memory and check the tag id's before grabbing a new
575 	 * vnode, since it's hard to roll back if there is a problem.
576 	 */
577 	up = pool_get(&unode_pool, PR_WAITOK | PR_ZERO);
578 
579 	/*
580 	 * Copy in the file entry.  Per the spec, the size can only be 1 block.
581 	 */
582 	sector = ino;
583 	devvp = ump->um_devvp;
584 	udf_vat_map(ump, &sector);
585 	if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
586 		printf("Cannot read sector %d\n", sector);
587 		pool_put(&unode_pool, up);
588 		if (bp != NULL)
589 			brelse(bp);
590 		return (error);
591 	}
592 
593 	xfe = (struct extfile_entry *)bp->b_data;
594 	fe = (struct file_entry *)bp->b_data;
595 	error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY);
596 	if (error == 0) {
597 		size = letoh32(xfe->l_ea) + letoh32(xfe->l_ad);
598 	} else {
599 		error = udf_checktag(&fe->tag, TAGID_FENTRY);
600 		if (error) {
601 			printf("Invalid file entry!\n");
602 			pool_put(&unode_pool, up);
603 			if (bp != NULL)
604 				brelse(bp);
605 			return (ENOMEM);
606 		} else
607 			size = letoh32(fe->l_ea) + letoh32(fe->l_ad);
608 	}
609 
610 	/* Allocate max size of FE/XFE. */
611 	up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE, M_UDFFENTRY, M_NOWAIT | M_ZERO);
612 	if (up->u_fentry == NULL) {
613 		pool_put(&unode_pool, up);
614 		if (bp != NULL)
615 			brelse(bp);
616 		return (ENOMEM); /* Cannot allocate file entry block */
617 	}
618 
619 	if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0)
620 		bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE);
621 	else
622 		bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE);
623 
624 	brelse(bp);
625 	bp = NULL;
626 
627 	if ((error = udf_allocv(mp, &vp, p))) {
628 		free(up->u_fentry, M_UDFFENTRY, 0);
629 		pool_put(&unode_pool, up);
630 		return (error); /* Error from udf_allocv() */
631 	}
632 
633 	up->u_vnode = vp;
634 	up->u_ino = ino;
635 	up->u_devvp = ump->um_devvp;
636 	up->u_dev = ump->um_dev;
637 	up->u_ump = ump;
638 	vp->v_data = up;
639 	vref(ump->um_devvp);
640 
641 	rrw_init_flags(&up->u_lock, "unode", RWL_DUPOK | RWL_IS_VNODE);
642 
643 	/*
644 	 * udf_hashins() will lock the vnode for us.
645 	 */
646 	udf_hashins(up);
647 
648 	switch (up->u_fentry->icbtag.file_type) {
649 	default:
650 		printf("Unrecognized file type (%d)\n", vp->v_type);
651 		vp->v_type = VREG;
652 		break;
653 	case UDF_ICB_FILETYPE_DIRECTORY:
654 		vp->v_type = VDIR;
655 		break;
656 	case UDF_ICB_FILETYPE_BLOCKDEVICE:
657 		vp->v_type = VBLK;
658 		break;
659 	case UDF_ICB_FILETYPE_CHARDEVICE:
660 		vp->v_type = VCHR;
661 		break;
662 	case UDF_ICB_FILETYPE_FIFO:
663 		vp->v_type = VFIFO;
664 		break;
665 	case UDF_ICB_FILETYPE_SOCKET:
666 		vp->v_type = VSOCK;
667 		break;
668 	case UDF_ICB_FILETYPE_SYMLINK:
669 		vp->v_type = VLNK;
670 		break;
671 	case UDF_ICB_FILETYPE_RANDOMACCESS:
672 	case UDF_ICB_FILETYPE_REALTIME:
673 	case UDF_ICB_FILETYPE_UNKNOWN:
674 		vp->v_type = VREG;
675 		break;
676 	}
677 
678 	/* check if this is a vnode alias */
679 	if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL) {
680 		printf("found a vnode alias\n");
681 		/*
682 		 * Discard unneeded vnode, but save its udf_node.
683 		 * Note that the lock is carried over in the udf_node
684 		 */
685 		nvp->v_data = vp->v_data;
686 		vp->v_data = NULL;
687 		vp->v_op = &spec_vops;
688 		vrele(vp);
689 		vgone(vp);
690 		/*
691 		 * Reinitialize aliased inode.
692 		 */
693 		vp = nvp;
694 		ump->um_devvp = vp;
695 	}
696 
697 	*vpp = vp;
698 
699 	return (0);
700 }
701 
702 struct ifid {
703 	u_short	ifid_len;
704 	u_short	ifid_pad;
705 	int	ifid_ino;
706 	long	ifid_start;
707 };
708 
709 int
710 udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
711 {
712 	struct ifid *ifhp;
713 	struct vnode *nvp;
714 	int error;
715 
716 	ifhp = (struct ifid *)fhp;
717 
718 	if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
719 		*vpp = NULLVP;
720 		return (error);
721 	}
722 
723 	*vpp = nvp;
724 
725 	return (0);
726 }
727 
728 int
729 udf_vptofh(struct vnode *vp, struct fid *fhp)
730 {
731 	struct unode *up;
732 	struct ifid *ifhp;
733 
734 	up = VTOU(vp);
735 	ifhp = (struct ifid *)fhp;
736 	ifhp->ifid_len = sizeof(struct ifid);
737 	ifhp->ifid_ino = up->u_ino;
738 
739 	return (0);
740 }
741 
742 int
743 udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
744     size_t newlen, struct proc *p)
745 {
746 	return (EINVAL);
747 }
748 
749 int
750 udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
751     struct ucred **credanonp)
752 {
753 	return (EACCES); /* For the time being */
754 }
755 
756 /* Handle a virtual partition map */
757 int
758 udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv)
759 {
760 	ump->um_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */
761 	return (0);
762 }
763 
764 /* Handle a sparable partition map */
765 int
766 udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
767 {
768 	struct buf *bp;
769 	int i, error;
770 
771 	ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT);
772 	if (ump->um_stbl == NULL)
773 		return (ENOMEM);
774 
775 	bzero(ump->um_stbl, letoh32(pms->st_size));
776 
777 	/* Calculate the number of sectors per packet */
778 	ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize;
779 
780 	error = udf_readlblks(ump, letoh32(pms->st_loc[0]),
781 	    letoh32(pms->st_size), &bp);
782 
783 	if (error) {
784 		if (bp != NULL)
785 			brelse(bp);
786 		free(ump->um_stbl, M_UDFMOUNT, 0);
787 		return (error); /* Failed to read sparing table */
788 	}
789 
790 	bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size));
791 	brelse(bp);
792 	bp = NULL;
793 
794 	if (udf_checktag(&ump->um_stbl->tag, 0)) {
795 		free(ump->um_stbl, M_UDFMOUNT, 0);
796 		return (EINVAL); /* Invalid sparing table found */
797 	}
798 
799 	/*
800 	 * See how many valid entries there are here. The list is
801 	 * supposed to be sorted, 0xfffffff0 and higher are not valid.
802 	 */
803 	for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) {
804 		ump->um_stbl_len = i;
805 		if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0)
806 			break;
807 	}
808 
809 	return (0);
810 }
811 
812 /* Handle a metadata partition map */
813 int
814 udf_get_mpartmap(struct umount *ump, struct part_map_meta *pmm)
815 {
816 	ump->um_flags |= UDF_MNT_USES_META;
817 	ump->um_meta_start = pmm->meta_file_lbn;
818 	return (0);
819 }
820 
821 /* Scan the partition maps */
822 int
823 udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
824 {
825 	struct regid *pmap_id;
826 	unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
827 	int i, ptype, psize, error;
828 	uint8_t *pmap = (uint8_t *) &lvd->maps[0];
829 
830 	for (i = 0; i < letoh32(lvd->n_pm); i++) {
831 		ptype = pmap[0];
832 		psize = pmap[1];
833 
834 		if (ptype != 1 && ptype != 2)
835 			return (EINVAL); /* Invalid partition map type */
836 
837 		if (psize != sizeof(struct part_map_1)  &&
838 		    psize != sizeof(struct part_map_2))
839 			return (EINVAL); /* Invalid partition map size */
840 
841 		if (ptype == 1) {
842 			pmap += sizeof(struct part_map_1);
843 			continue;
844 		}
845 
846 		/* Type 2 map. Find out the details */
847 		pmap_id = (struct regid *) &pmap[4];
848 		regid_id[UDF_REGID_ID_SIZE] = '\0';
849 		bcopy(&pmap_id->id[0], &regid_id[0], UDF_REGID_ID_SIZE);
850 
851 		if (!bcmp(&regid_id[0], "*UDF Virtual Partition",
852 		    UDF_REGID_ID_SIZE))
853 			error = udf_get_vpartmap(ump,
854 			    (struct part_map_virt *) pmap);
855 		else if (!bcmp(&regid_id[0], "*UDF Sparable Partition",
856 		    UDF_REGID_ID_SIZE))
857 			error = udf_get_spartmap(ump,
858 			    (struct part_map_spare *) pmap);
859 		else if (!bcmp(&regid_id[0], "*UDF Metadata Partition",
860 		    UDF_REGID_ID_SIZE))
861 			error = udf_get_mpartmap(ump,
862 			    (struct part_map_meta *) pmap);
863 		else
864 			return (EINVAL); /* Unsupported partition map */
865 
866 		if (error)
867 			return (error); /* Error getting partition */
868 
869 		pmap += sizeof(struct part_map_2);
870 	}
871 
872 	return (0);
873 }
874