xref: /illumos-gate/usr/src/uts/common/fs/udfs/udf_vfsops.c (revision fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/t_lock.h>
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/systm.h>
33 #include <sys/sysmacros.h>
34 #include <sys/resource.h>
35 #include <sys/signal.h>
36 #include <sys/cred.h>
37 #include <sys/user.h>
38 #include <sys/buf.h>
39 #include <sys/vfs.h>
40 #include <sys/vfs_opreg.h>
41 #include <sys/stat.h>
42 #include <sys/vnode.h>
43 #include <sys/mode.h>
44 #include <sys/proc.h>
45 #include <sys/disp.h>
46 #include <sys/file.h>
47 #include <sys/fcntl.h>
48 #include <sys/flock.h>
49 #include <sys/kmem.h>
50 #include <sys/uio.h>
51 #include <sys/dnlc.h>
52 #include <sys/conf.h>
53 #include <sys/errno.h>
54 #include <sys/mman.h>
55 #include <sys/fbuf.h>
56 #include <sys/pathname.h>
57 #include <sys/debug.h>
58 #include <sys/vmsystm.h>
59 #include <sys/cmn_err.h>
60 #include <sys/dirent.h>
61 #include <sys/errno.h>
62 #include <sys/modctl.h>
63 #include <sys/statvfs.h>
64 #include <sys/mount.h>
65 #include <sys/sunddi.h>
66 #include <sys/bootconf.h>
67 #include <sys/policy.h>
68 
69 #include <vm/hat.h>
70 #include <vm/page.h>
71 #include <vm/pvn.h>
72 #include <vm/as.h>
73 #include <vm/seg.h>
74 #include <vm/seg_map.h>
75 #include <vm/seg_kmem.h>
76 #include <vm/seg_vn.h>
77 #include <vm/rm.h>
78 #include <vm/page.h>
79 #include <sys/swap.h>
80 #include <sys/mntent.h>
81 
82 
83 #include <fs/fs_subr.h>
84 
85 
86 #include <sys/fs/udf_volume.h>
87 #include <sys/fs/udf_inode.h>
88 
89 
90 extern struct vnode *common_specvp(struct vnode *vp);
91 
92 extern kmutex_t ud_sync_busy;
93 static int32_t ud_mountfs(struct vfs *,
94 	enum whymountroot, dev_t, char *, struct cred *, int32_t);
95 static struct udf_vfs *ud_validate_and_fill_superblock(dev_t,
96 			int32_t, uint32_t);
97 void ud_destroy_fsp(struct udf_vfs *);
98 void ud_convert_to_superblock(struct udf_vfs *,
99 	struct log_vol_int_desc *);
100 void ud_update_superblock(struct vfs *);
101 int32_t ud_get_last_block(dev_t, daddr_t *);
102 static int32_t ud_val_get_vat(struct udf_vfs *,
103 	dev_t, daddr_t, struct ud_map *);
104 int32_t ud_read_sparing_tbls(struct udf_vfs *,
105 	dev_t, struct ud_map *, struct pmap_typ2 *);
106 uint32_t ud_get_lbsize(dev_t, uint32_t *);
107 
108 static int32_t udf_mount(struct vfs *,
109 	struct vnode *, struct mounta *, struct cred *);
110 static int32_t udf_unmount(struct vfs *, int, struct cred *);
111 static int32_t udf_root(struct vfs *, struct vnode **);
112 static int32_t udf_statvfs(struct vfs *, struct statvfs64 *);
113 static int32_t udf_sync(struct vfs *, int16_t, struct cred *);
114 static int32_t udf_vget(struct vfs *, struct vnode **, struct fid *);
115 static int32_t udf_mountroot(struct vfs *vfsp, enum whymountroot);
116 
117 static int udfinit(int, char *);
118 
119 static mntopts_t udfs_mntopts;
120 
121 static vfsdef_t vfw = {
122 	VFSDEF_VERSION,
123 	"udfs",
124 	udfinit,
125 	VSW_HASPROTO|VSW_CANREMOUNT|VSW_STATS,
126 	&udfs_mntopts
127 };
128 
129 static mntopts_t udfs_mntopts = {
130 	0,
131 	NULL
132 };
133 
134 /*
135  * Module linkage information for the kernel.
136  */
137 extern struct mod_ops mod_fsops;
138 
139 static struct modlfs modlfs = {
140 	&mod_fsops, "filesystem for UDFS", &vfw
141 };
142 
143 static struct modlinkage modlinkage = {
144 	MODREV_1, (void *)&modlfs, NULL
145 };
146 
147 char _depends_on[] = "fs/specfs";
148 
149 int32_t udf_fstype = -1;
150 
151 int
152 _init()
153 {
154 	return (mod_install(&modlinkage));
155 }
156 
157 int
158 _fini()
159 {
160 	return (EBUSY);
161 }
162 
163 int
164 _info(struct modinfo *modinfop)
165 {
166 	return (mod_info(&modlinkage, modinfop));
167 }
168 
169 
170 /* -------------------- vfs routines -------------------- */
171 
172 /*
173  * XXX - this appears only to be used by the VM code to handle the case where
174  * UNIX is running off the mini-root.  That probably wants to be done
175  * differently.
176  */
177 struct vnode *rootvp;
178 #ifndef	__lint
179 _NOTE(SCHEME_PROTECTS_DATA("safe sharing", rootvp))
180 #endif
181 static int32_t
182 udf_mount(struct vfs *vfsp, struct vnode *mvp,
183 	struct mounta *uap, struct cred *cr)
184 {
185 	dev_t dev;
186 	struct vnode *bvp;
187 	struct pathname dpn;
188 	int32_t error;
189 	enum whymountroot why;
190 	int oflag, aflag;
191 
192 	ud_printf("udf_mount\n");
193 
194 	if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) {
195 		return (error);
196 	}
197 
198 	if (mvp->v_type != VDIR) {
199 		return (ENOTDIR);
200 	}
201 
202 	mutex_enter(&mvp->v_lock);
203 	if ((uap->flags & MS_REMOUNT) == 0 &&
204 	    (uap->flags & MS_OVERLAY) == 0 &&
205 		(mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
206 			mutex_exit(&mvp->v_lock);
207 			return (EBUSY);
208 	}
209 	mutex_exit(&mvp->v_lock);
210 
211 	if (error = pn_get(uap->dir, UIO_USERSPACE, &dpn)) {
212 		return (error);
213 	}
214 
215 	/*
216 	 * Resolve path name of special file being mounted.
217 	 */
218 	if (error = lookupname(uap->spec, UIO_USERSPACE, FOLLOW, NULLVPP,
219 	    &bvp)) {
220 		pn_free(&dpn);
221 		return (error);
222 	}
223 	if (bvp->v_type != VBLK) {
224 		error = ENOTBLK;
225 		goto out;
226 	}
227 	dev = bvp->v_rdev;
228 
229 	/*
230 	 * Ensure that this device isn't already mounted,
231 	 * unless this is a REMOUNT request
232 	 */
233 	if (vfs_devmounting(dev, vfsp)) {
234 		error = EBUSY;
235 		goto out;
236 	}
237 	if (vfs_devismounted(dev)) {
238 		if (uap->flags & MS_REMOUNT) {
239 			why = ROOT_REMOUNT;
240 		} else {
241 			error = EBUSY;
242 			goto out;
243 		}
244 	} else {
245 		why = ROOT_INIT;
246 	}
247 	if (getmajor(dev) >= devcnt) {
248 		error = ENXIO;
249 		goto out;
250 	}
251 
252 	/*
253 	 * If the device is a tape, mount it read only
254 	 */
255 	if (devopsp[getmajor(dev)]->devo_cb_ops->cb_flag & D_TAPE) {
256 		vfsp->vfs_flag |= VFS_RDONLY;
257 	}
258 
259 	if (uap->flags & MS_RDONLY) {
260 		vfsp->vfs_flag |= VFS_RDONLY;
261 	}
262 
263 	/*
264 	 * Set mount options.
265 	 */
266 	if (uap->flags & MS_RDONLY) {
267 		vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
268 	}
269 	if (uap->flags & MS_NOSUID) {
270 		vfs_setmntopt(vfsp, MNTOPT_NOSUID, NULL, 0);
271 	}
272 
273 	/*
274 	 * Verify that the caller can open the device special file as
275 	 * required.  It is not until this moment that we know whether
276 	 * we're mounting "ro" or not.
277 	 */
278 	if ((vfsp->vfs_flag & VFS_RDONLY) != 0) {
279 		oflag = FREAD;
280 		aflag = VREAD;
281 	} else {
282 		oflag = FREAD | FWRITE;
283 		aflag = VREAD | VWRITE;
284 	}
285 	if ((error = VOP_ACCESS(bvp, aflag, 0, cr)) != 0 ||
286 	    (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) {
287 		goto out;
288 	}
289 
290 	/*
291 	 * Mount the filesystem.
292 	 */
293 	error = ud_mountfs(vfsp, why, dev, dpn.pn_path, cr, 0);
294 out:
295 	VN_RELE(bvp);
296 	pn_free(&dpn);
297 
298 	return (error);
299 }
300 
301 
302 
303 /*
304  * unmount the file system pointed
305  * by vfsp
306  */
307 /* ARGSUSED */
308 static int32_t
309 udf_unmount(struct vfs *vfsp, int fflag, struct cred *cr)
310 {
311 	struct udf_vfs *udf_vfsp;
312 	struct vnode *bvp, *rvp;
313 	struct ud_inode *rip;
314 	int32_t flag;
315 
316 	ud_printf("udf_unmount\n");
317 
318 	if (secpolicy_fs_unmount(cr, vfsp) != 0) {
319 		return (EPERM);
320 	}
321 
322 	/*
323 	 * forced unmount is not supported by this file system
324 	 * and thus, ENOTSUP, is being returned.
325 	 */
326 	if (fflag & MS_FORCE)
327 		return (ENOTSUP);
328 
329 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
330 	flag = !(udf_vfsp->udf_flags & UDF_FL_RDONLY);
331 	bvp = udf_vfsp->udf_devvp;
332 
333 	rvp = udf_vfsp->udf_root;
334 	ASSERT(rvp != NULL);
335 	rip = VTOI(rvp);
336 
337 	(void) ud_release_cache(udf_vfsp);
338 
339 
340 	/* Flush all inodes except root */
341 	if (ud_iflush(vfsp) < 0) {
342 		return (EBUSY);
343 	}
344 
345 	rw_enter(&rip->i_contents, RW_WRITER);
346 	(void) ud_syncip(rip, B_INVAL, I_SYNC);
347 	rw_exit(&rip->i_contents);
348 
349 	mutex_enter(&ud_sync_busy);
350 	if ((udf_vfsp->udf_flags & UDF_FL_RDONLY) == 0) {
351 		bflush(vfsp->vfs_dev);
352 		mutex_enter(&udf_vfsp->udf_lock);
353 		udf_vfsp->udf_clean = UDF_CLEAN;
354 		mutex_exit(&udf_vfsp->udf_lock);
355 		ud_update_superblock(vfsp);
356 	}
357 	mutex_exit(&ud_sync_busy);
358 
359 	mutex_destroy(&udf_vfsp->udf_lock);
360 	mutex_destroy(&udf_vfsp->udf_rename_lck);
361 
362 	ud_delcache(rip);
363 	ITIMES(rip);
364 	VN_RELE(rvp);
365 
366 	ud_destroy_fsp(udf_vfsp);
367 
368 	(void) VOP_PUTPAGE(bvp, (offset_t)0, (uint32_t)0, B_INVAL, cr);
369 	(void) VOP_CLOSE(bvp, flag, 1, (offset_t)0, cr);
370 
371 	(void) bfinval(vfsp->vfs_dev, 1);
372 	VN_RELE(bvp);
373 
374 
375 	return (0);
376 }
377 
378 
379 /*
380  * Get the root vp for the
381  * file system
382  */
383 static int32_t
384 udf_root(struct vfs *vfsp, struct vnode **vpp)
385 {
386 	struct udf_vfs *udf_vfsp;
387 	struct vnode *vp;
388 
389 	ud_printf("udf_root\n");
390 
391 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
392 
393 	ASSERT(udf_vfsp != NULL);
394 	ASSERT(udf_vfsp->udf_root != NULL);
395 
396 	vp = udf_vfsp->udf_root;
397 	VN_HOLD(vp);
398 	*vpp = vp;
399 	return (0);
400 }
401 
402 
403 /*
404  * Get file system statistics.
405  */
406 static int32_t
407 udf_statvfs(struct vfs *vfsp, struct statvfs64 *sp)
408 {
409 	struct udf_vfs *udf_vfsp;
410 	struct ud_part *parts;
411 	dev32_t d32;
412 	int32_t index;
413 
414 	ud_printf("udf_statvfs\n");
415 
416 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
417 	(void) bzero(sp, sizeof (struct statvfs64));
418 
419 	mutex_enter(&udf_vfsp->udf_lock);
420 	sp->f_bsize = udf_vfsp->udf_lbsize;
421 	sp->f_frsize = udf_vfsp->udf_lbsize;
422 	sp->f_blocks = 0;
423 	sp->f_bfree = 0;
424 	parts = udf_vfsp->udf_parts;
425 	for (index = 0; index < udf_vfsp->udf_npart; index++) {
426 		sp->f_blocks += parts->udp_nblocks;
427 		sp->f_bfree += parts->udp_nfree;
428 		parts++;
429 	}
430 	sp->f_bavail = sp->f_bfree;
431 
432 	/*
433 	 * Since there are no real inodes allocated
434 	 * we will approximate
435 	 * each new file will occupy :
436 	 * 38(over head each dent) + MAXNAMLEN / 2 + inode_size(==block size)
437 	 */
438 	sp->f_ffree = sp->f_favail =
439 		(sp->f_bavail * sp->f_bsize) / (146 + sp->f_bsize);
440 
441 	/*
442 	 * The total number of inodes is
443 	 * the sum of files + directories + free inodes
444 	 */
445 	sp->f_files = sp->f_ffree +
446 			udf_vfsp->udf_nfiles +
447 			udf_vfsp->udf_ndirs;
448 	(void) cmpldev(&d32, vfsp->vfs_dev);
449 	sp->f_fsid = d32;
450 	(void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name);
451 	sp->f_flag = vf_to_stf(vfsp->vfs_flag);
452 	sp->f_namemax = MAXNAMLEN;
453 	(void) strcpy(sp->f_fstr, udf_vfsp->udf_volid);
454 
455 	mutex_exit(&udf_vfsp->udf_lock);
456 
457 	return (0);
458 }
459 
460 
461 /*
462  * Flush any pending I/O to file system vfsp.
463  * The ud_update() routine will only flush *all* udf files.
464  */
465 /*ARGSUSED*/
466 /* ARGSUSED */
467 static int32_t
468 udf_sync(struct vfs *vfsp, int16_t flag, struct cred *cr)
469 {
470 	ud_printf("udf_sync\n");
471 
472 	ud_update(flag);
473 	return (0);
474 }
475 
476 
477 
478 /* ARGSUSED */
479 static int32_t
480 udf_vget(struct vfs *vfsp,
481 	struct vnode **vpp, struct fid *fidp)
482 {
483 	int32_t error = 0;
484 	struct udf_fid *udfid;
485 	struct udf_vfs *udf_vfsp;
486 	struct ud_inode *ip;
487 
488 	ud_printf("udf_vget\n");
489 
490 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
491 	if (udf_vfsp == NULL) {
492 		*vpp = NULL;
493 		return (0);
494 	}
495 
496 	udfid = (struct udf_fid *)fidp;
497 	if ((error = ud_iget(vfsp, udfid->udfid_prn,
498 		udfid->udfid_icb_lbn, &ip, NULL, CRED())) != 0) {
499 		*vpp = NULL;
500 		return (error);
501 	}
502 
503 	rw_enter(&ip->i_contents, RW_READER);
504 	if ((udfid->udfid_uinq_lo != (ip->i_uniqid & 0xffffffff)) ||
505 			(udfid->udfid_prn != ip->i_icb_prn)) {
506 		rw_exit(&ip->i_contents);
507 		VN_RELE(ITOV(ip));
508 		*vpp = NULL;
509 		return (EINVAL);
510 	}
511 	rw_exit(&ip->i_contents);
512 
513 	*vpp = ITOV(ip);
514 	return (0);
515 }
516 
517 
518 /*
519  * Mount root file system.
520  * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to
521  * remount the root file system, and ROOT_UNMOUNT if called to
522  * unmount the root (e.g., as part of a system shutdown).
523  *
524  * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP
525  * operation, goes along with auto-configuration.  A mechanism should be
526  * provided by which machine-INdependent code in the kernel can say "get me the
527  * right root file system" and "get me the right initial swap area", and have
528  * that done in what may well be a machine-dependent fashion.
529  * Unfortunately, it is also file-system-type dependent (NFS gets it via
530  * bootparams calls, UFS gets it from various and sundry machine-dependent
531  * mechanisms, as SPECFS does for swap).
532  */
533 /* ARGSUSED */
534 static int32_t
535 udf_mountroot(struct vfs *vfsp, enum whymountroot why)
536 {
537 	dev_t rootdev;
538 	static int32_t udf_rootdone = 0;
539 	struct vnode *vp = NULL;
540 	int32_t ovflags, error;
541 	ud_printf("udf_mountroot\n");
542 
543 	if (why == ROOT_INIT) {
544 		if (udf_rootdone++) {
545 			return (EBUSY);
546 		}
547 		rootdev = getrootdev();
548 		if (rootdev == (dev_t)NODEV) {
549 			return (ENODEV);
550 		}
551 		vfsp->vfs_dev = rootdev;
552 		vfsp->vfs_flag |= VFS_RDONLY;
553 	} else if (why == ROOT_REMOUNT) {
554 		vp = ((struct udf_vfs *)vfsp->vfs_data)->udf_devvp;
555 		(void) dnlc_purge_vfsp(vfsp, 0);
556 		vp = common_specvp(vp);
557 		(void) VOP_PUTPAGE(vp, (offset_t)0,
558 			(uint32_t)0, B_INVAL, CRED());
559 		binval(vfsp->vfs_dev);
560 
561 		ovflags = vfsp->vfs_flag;
562 		vfsp->vfs_flag &= ~VFS_RDONLY;
563 		vfsp->vfs_flag |= VFS_REMOUNT;
564 		rootdev = vfsp->vfs_dev;
565 	} else if (why == ROOT_UNMOUNT) {
566 		ud_update(0);
567 		vp = ((struct udf_vfs *)vfsp->vfs_data)->udf_devvp;
568 		(void) VOP_CLOSE(vp, FREAD|FWRITE, 1,
569 					(offset_t)0, CRED());
570 		return (0);
571 	}
572 
573 	if ((error = vfs_lock(vfsp)) != 0) {
574 		return (error);
575 	}
576 
577 	error = ud_mountfs(vfsp, why, rootdev, "/", CRED(), 1);
578 	if (error) {
579 		vfs_unlock(vfsp);
580 		if (why == ROOT_REMOUNT) {
581 			vfsp->vfs_flag = ovflags;
582 		}
583 		if (rootvp) {
584 			VN_RELE(rootvp);
585 			rootvp = (struct vnode *)0;
586 		}
587 		return (error);
588 	}
589 
590 	if (why == ROOT_INIT) {
591 		vfs_add((struct vnode *)0, vfsp,
592 			(vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0);
593 	}
594 	vfs_unlock(vfsp);
595 	return (0);
596 }
597 
598 
599 /* ------------------------- local routines ------------------------- */
600 
601 
602 static int32_t
603 ud_mountfs(struct vfs *vfsp,
604 	enum whymountroot why, dev_t dev, char *name,
605 	struct cred *cr, int32_t isroot)
606 {
607 	struct vnode *devvp = NULL;
608 	int32_t error = 0;
609 	int32_t needclose = 0;
610 	struct udf_vfs *udf_vfsp = NULL;
611 	struct log_vol_int_desc *lvid;
612 	struct ud_inode *rip = NULL;
613 	struct vnode *rvp = NULL;
614 	int32_t i, lbsize;
615 	uint32_t avd_loc;
616 	struct ud_map *map;
617 	int32_t	desc_len;
618 
619 	ud_printf("ud_mountfs\n");
620 
621 	if (why == ROOT_INIT) {
622 		/*
623 		 * Open the device.
624 		 */
625 		devvp = makespecvp(dev, VBLK);
626 
627 		/*
628 		 * Open block device mounted on.
629 		 * When bio is fixed for vnodes this can all be vnode
630 		 * operations.
631 		 */
632 		error = VOP_OPEN(&devvp,
633 		    (vfsp->vfs_flag & VFS_RDONLY) ? FREAD : FREAD|FWRITE, cr);
634 		if (error) {
635 			goto out;
636 		}
637 		needclose = 1;
638 
639 		/*
640 		 * Refuse to go any further if this
641 		 * device is being used for swapping.
642 		 */
643 		if (IS_SWAPVP(devvp)) {
644 			error = EBUSY;
645 			goto out;
646 		}
647 	}
648 
649 	/*
650 	 * check for dev already mounted on
651 	 */
652 	if (vfsp->vfs_flag & VFS_REMOUNT) {
653 		struct tag *ttag;
654 		int32_t index, count;
655 		struct buf *tpt = 0;
656 		caddr_t addr;
657 
658 
659 		/* cannot remount to RDONLY */
660 		if (vfsp->vfs_flag & VFS_RDONLY) {
661 			return (EINVAL);
662 		}
663 
664 		if (vfsp->vfs_dev != dev) {
665 			return (EINVAL);
666 		}
667 
668 		udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
669 		devvp = udf_vfsp->udf_devvp;
670 
671 		/*
672 		 * fsck may have altered the file system; discard
673 		 * as much incore data as possible.  Don't flush
674 		 * if this is a rw to rw remount; it's just resetting
675 		 * the options.
676 		 */
677 		if (udf_vfsp->udf_flags & UDF_FL_RDONLY) {
678 			(void) dnlc_purge_vfsp(vfsp, 0);
679 			(void) VOP_PUTPAGE(devvp, (offset_t)0, (uint_t)0,
680 					B_INVAL, CRED());
681 			(void) ud_iflush(vfsp);
682 			bflush(dev);
683 			binval(dev);
684 		}
685 
686 		/*
687 		 * We could read UDF1.50 and write UDF1.50 only
688 		 * disallow mount of any highier version
689 		 */
690 		if ((udf_vfsp->udf_miread > UDF_150) ||
691 			(udf_vfsp->udf_miwrite > UDF_150)) {
692 			error = EINVAL;
693 			goto remountout;
694 		}
695 
696 		/*
697 		 * read/write to read/write; all done
698 		 */
699 		if (udf_vfsp->udf_flags & UDF_FL_RW) {
700 			goto remountout;
701 		}
702 
703 		/*
704 		 * Does the media type allow a writable mount
705 		 */
706 		if (udf_vfsp->udf_mtype != UDF_MT_OW) {
707 			error = EINVAL;
708 			goto remountout;
709 		}
710 
711 		/*
712 		 * Read the metadata
713 		 * and check if it is possible to
714 		 * mount in rw mode
715 		 */
716 		tpt = ud_bread(vfsp->vfs_dev,
717 			udf_vfsp->udf_iseq_loc << udf_vfsp->udf_l2d_shift,
718 			udf_vfsp->udf_iseq_len);
719 		if (tpt->b_flags & B_ERROR) {
720 			error = EIO;
721 			goto remountout;
722 		}
723 		count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
724 		addr = tpt->b_un.b_addr;
725 		for (index = 0; index < count; index ++) {
726 			ttag = (struct tag *)(addr + index * DEV_BSIZE);
727 			desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
728 			if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
729 			    udf_vfsp->udf_iseq_loc +
730 			    (index >> udf_vfsp->udf_l2d_shift),
731 			    1, desc_len) == 0) {
732 				struct log_vol_int_desc *lvid;
733 
734 				lvid = (struct log_vol_int_desc *)ttag;
735 
736 				if (SWAP_32(lvid->lvid_int_type) !=
737 					LOG_VOL_CLOSE_INT) {
738 					error = EINVAL;
739 					goto remountout;
740 				}
741 
742 				/*
743 				 * Copy new data to old data
744 				 */
745 				bcopy(udf_vfsp->udf_iseq->b_un.b_addr,
746 				tpt->b_un.b_addr, udf_vfsp->udf_iseq_len);
747 				break;
748 			}
749 		}
750 
751 		udf_vfsp->udf_flags = UDF_FL_RW;
752 
753 		mutex_enter(&udf_vfsp->udf_lock);
754 		ud_sbwrite(udf_vfsp);
755 		mutex_exit(&udf_vfsp->udf_lock);
756 remountout:
757 		if (tpt != NULL) {
758 			tpt->b_flags = B_AGE | B_STALE;
759 			brelse(tpt);
760 		}
761 		return (error);
762 	}
763 
764 	ASSERT(devvp != 0);
765 	/*
766 	 * Flush back any dirty pages on the block device to
767 	 * try and keep the buffer cache in sync with the page
768 	 * cache if someone is trying to use block devices when
769 	 * they really should be using the raw device.
770 	 */
771 	(void) VOP_PUTPAGE(common_specvp(devvp), (offset_t)0,
772 	    (uint32_t)0, B_INVAL, cr);
773 
774 
775 	/*
776 	 * Check if the file system
777 	 * is a valid udfs and fill
778 	 * the required fields in udf_vfs
779 	 */
780 #ifndef	__lint
781 	_NOTE(NO_COMPETING_THREADS_NOW);
782 #endif
783 
784 	if ((lbsize = ud_get_lbsize(dev, &avd_loc)) == 0) {
785 		error = EINVAL;
786 		goto out;
787 	}
788 
789 	udf_vfsp = ud_validate_and_fill_superblock(dev, lbsize, avd_loc);
790 	if (udf_vfsp == NULL) {
791 		error = EINVAL;
792 		goto out;
793 	}
794 
795 	/*
796 	 * Fill in vfs private data
797 	 */
798 	vfsp->vfs_fstype = udf_fstype;
799 	vfs_make_fsid(&vfsp->vfs_fsid, dev, udf_fstype);
800 	vfsp->vfs_data = (caddr_t)udf_vfsp;
801 	vfsp->vfs_dev = dev;
802 	vfsp->vfs_flag |= VFS_NOTRUNC;
803 	udf_vfsp->udf_devvp = devvp;
804 
805 	udf_vfsp->udf_fsmnt = kmem_zalloc(strlen(name) + 1, KM_SLEEP);
806 	(void) strcpy(udf_vfsp->udf_fsmnt, name);
807 
808 	udf_vfsp->udf_vfs = vfsp;
809 	udf_vfsp->udf_rdclustsz = udf_vfsp->udf_wrclustsz = maxphys;
810 
811 	udf_vfsp->udf_mod = 0;
812 
813 
814 	lvid = udf_vfsp->udf_lvid;
815 	if (vfsp->vfs_flag & VFS_RDONLY) {
816 		/*
817 		 * We could read only UDF1.50
818 		 * disallow mount of any highier version
819 		 */
820 		if (udf_vfsp->udf_miread > UDF_150) {
821 			error = EINVAL;
822 			goto out;
823 		}
824 		udf_vfsp->udf_flags = UDF_FL_RDONLY;
825 		if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
826 			udf_vfsp->udf_clean = UDF_CLEAN;
827 		} else {
828 			/* Do we have a VAT at the end of the recorded media */
829 			map = udf_vfsp->udf_maps;
830 			for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
831 				if (map->udm_flags & UDM_MAP_VPM) {
832 					break;
833 				}
834 				map++;
835 			}
836 			if (i == udf_vfsp->udf_nmaps) {
837 				error = ENOSPC;
838 				goto out;
839 			}
840 			udf_vfsp->udf_clean = UDF_CLEAN;
841 		}
842 	} else {
843 		/*
844 		 * We could read UDF1.50 and write UDF1.50 only
845 		 * disallow mount of any highier version
846 		 */
847 		if ((udf_vfsp->udf_miread > UDF_150) ||
848 			(udf_vfsp->udf_miwrite > UDF_150)) {
849 			error = EINVAL;
850 			goto out;
851 		}
852 		/*
853 		 * Check if the media allows
854 		 * us to mount read/write
855 		 */
856 		if (udf_vfsp->udf_mtype != UDF_MT_OW) {
857 			error = EACCES;
858 			goto out;
859 		}
860 
861 		/*
862 		 * Check if we have VAT on a writable media
863 		 * we cannot use the media in presence of VAT
864 		 * Dent RW mount.
865 		 */
866 		map = udf_vfsp->udf_maps;
867 		ASSERT(map != NULL);
868 		for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
869 			if (map->udm_flags & UDM_MAP_VPM) {
870 				error = EACCES;
871 				goto out;
872 			}
873 			map++;
874 		}
875 
876 		/*
877 		 * Check if the domain Id allows
878 		 * us to write
879 		 */
880 		if (udf_vfsp->udf_lvd->lvd_dom_id.reg_ids[2] & 0x3) {
881 			error = EACCES;
882 			goto out;
883 		}
884 		udf_vfsp->udf_flags = UDF_FL_RW;
885 
886 		if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
887 			udf_vfsp->udf_clean = UDF_CLEAN;
888 		} else {
889 			if (isroot) {
890 				udf_vfsp->udf_clean = UDF_DIRTY;
891 			} else {
892 				error = ENOSPC;
893 				goto out;
894 			}
895 		}
896 	}
897 
898 	mutex_init(&udf_vfsp->udf_lock, NULL, MUTEX_DEFAULT, NULL);
899 
900 	mutex_init(&udf_vfsp->udf_rename_lck, NULL, MUTEX_DEFAULT, NULL);
901 
902 #ifndef	__lint
903 	_NOTE(COMPETING_THREADS_NOW);
904 #endif
905 	if (error = ud_iget(vfsp, udf_vfsp->udf_ricb_prn,
906 			udf_vfsp->udf_ricb_loc, &rip, NULL, cr)) {
907 		mutex_destroy(&udf_vfsp->udf_lock);
908 		goto out;
909 	}
910 
911 
912 	/*
913 	 * Get the root inode and
914 	 * initialize the root vnode
915 	 */
916 	rvp = ITOV(rip);
917 	mutex_enter(&rvp->v_lock);
918 	rvp->v_flag |= VROOT;
919 	mutex_exit(&rvp->v_lock);
920 	udf_vfsp->udf_root = rvp;
921 
922 
923 	if (why == ROOT_INIT && isroot)
924 		rootvp = devvp;
925 
926 	ud_vfs_add(udf_vfsp);
927 
928 	if (udf_vfsp->udf_flags == UDF_FL_RW) {
929 		udf_vfsp->udf_clean = UDF_DIRTY;
930 		ud_update_superblock(vfsp);
931 	}
932 
933 	return (0);
934 
935 out:
936 	ud_destroy_fsp(udf_vfsp);
937 	if (needclose) {
938 		(void) VOP_CLOSE(devvp, (vfsp->vfs_flag & VFS_RDONLY) ?
939 			FREAD : FREAD|FWRITE, 1, (offset_t)0, cr);
940 		bflush(dev);
941 		binval(dev);
942 	}
943 	VN_RELE(devvp);
944 
945 	return (error);
946 }
947 
948 
949 static struct udf_vfs *
950 ud_validate_and_fill_superblock(dev_t dev, int32_t bsize, uint32_t avd_loc)
951 {
952 	int32_t error, count, index, shift;
953 	uint32_t dummy, vds_loc;
954 	caddr_t addr;
955 	daddr_t blkno, lblkno;
956 	struct buf *secbp, *bp;
957 	struct tag *ttag;
958 	struct anch_vol_desc_ptr *avdp;
959 	struct file_set_desc *fsd;
960 	struct udf_vfs *udf_vfsp = NULL;
961 	struct pmap_hdr *hdr;
962 	struct pmap_typ1 *typ1;
963 	struct pmap_typ2 *typ2;
964 	struct ud_map *map;
965 	int32_t	desc_len;
966 
967 	ud_printf("ud_validate_and_fill_superblock\n");
968 
969 	if (bsize < DEV_BSIZE) {
970 		return (NULL);
971 	}
972 	shift = 0;
973 	while ((bsize >> shift) > DEV_BSIZE) {
974 		shift++;
975 	}
976 
977 	/*
978 	 * Read Anchor Volume Descriptor
979 	 * Verify it and get the location of
980 	 * Main Volume Descriptor Sequence
981 	 */
982 	secbp = ud_bread(dev, avd_loc << shift, ANCHOR_VOL_DESC_LEN);
983 	if ((error = geterror(secbp)) != 0) {
984 		cmn_err(CE_NOTE,
985 		"udfs : Could not read Anchor Volume Desc %x", error);
986 		brelse(secbp);
987 		return (NULL);
988 	}
989 	avdp = (struct anch_vol_desc_ptr *)secbp->b_un.b_addr;
990 	if (ud_verify_tag_and_desc(&avdp->avd_tag, UD_ANCH_VOL_DESC,
991 	    avd_loc, 1, ANCHOR_VOL_DESC_LEN) != 0) {
992 		brelse(secbp);
993 		return (NULL);
994 	}
995 	udf_vfsp = (struct udf_vfs *)
996 		kmem_zalloc(sizeof (struct udf_vfs), KM_SLEEP);
997 	udf_vfsp->udf_mvds_loc = SWAP_32(avdp->avd_main_vdse.ext_loc);
998 	udf_vfsp->udf_mvds_len = SWAP_32(avdp->avd_main_vdse.ext_len);
999 	udf_vfsp->udf_rvds_loc = SWAP_32(avdp->avd_res_vdse.ext_loc);
1000 	udf_vfsp->udf_rvds_len = SWAP_32(avdp->avd_res_vdse.ext_len);
1001 	secbp->b_flags = B_AGE | B_STALE;
1002 	brelse(secbp);
1003 
1004 	/*
1005 	 * Read Main Volume Descriptor Sequence
1006 	 * and process it
1007 	 */
1008 	vds_loc = udf_vfsp->udf_mvds_loc;
1009 	secbp = ud_bread(dev, vds_loc << shift,
1010 			udf_vfsp->udf_mvds_len);
1011 	if ((error = geterror(secbp)) != 0) {
1012 		brelse(secbp);
1013 		cmn_err(CE_NOTE,
1014 		"udfs : Could not read Main Volume Desc %x", error);
1015 
1016 		vds_loc = udf_vfsp->udf_rvds_loc;
1017 		secbp = ud_bread(dev, vds_loc << shift,
1018 			udf_vfsp->udf_rvds_len);
1019 		if ((error = geterror(secbp)) != 0) {
1020 			brelse(secbp);
1021 			cmn_err(CE_NOTE,
1022 			"udfs : Could not read Res Volume Desc %x", error);
1023 			return (NULL);
1024 		}
1025 	}
1026 
1027 	udf_vfsp->udf_vds = ngeteblk(udf_vfsp->udf_mvds_len);
1028 	bp = udf_vfsp->udf_vds;
1029 	bp->b_edev = dev;
1030 	bp->b_dev = cmpdev(dev);
1031 	bp->b_blkno = vds_loc << shift;
1032 	bp->b_bcount = udf_vfsp->udf_mvds_len;
1033 	bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_mvds_len);
1034 	secbp->b_flags |= B_STALE | B_AGE;
1035 	brelse(secbp);
1036 
1037 
1038 	count = udf_vfsp->udf_mvds_len / DEV_BSIZE;
1039 	addr = bp->b_un.b_addr;
1040 	for (index = 0; index < count; index ++) {
1041 		ttag = (struct tag *)(addr + index * DEV_BSIZE);
1042 		desc_len = udf_vfsp->udf_mvds_len - (index * DEV_BSIZE);
1043 		if (ud_verify_tag_and_desc(ttag, UD_PRI_VOL_DESC,
1044 		    vds_loc + (index >> shift),
1045 		    1, desc_len) == 0) {
1046 			if (udf_vfsp->udf_pvd == NULL) {
1047 				udf_vfsp->udf_pvd =
1048 					(struct pri_vol_desc *)ttag;
1049 			} else {
1050 				struct pri_vol_desc *opvd, *npvd;
1051 
1052 				opvd = udf_vfsp->udf_pvd;
1053 				npvd = (struct pri_vol_desc *)ttag;
1054 
1055 				if ((strncmp(opvd->pvd_vsi,
1056 					npvd->pvd_vsi, 128) == 0) &&
1057 					(strncmp(opvd->pvd_vol_id,
1058 					npvd->pvd_vol_id, 32) == 0) &&
1059 					(strncmp((caddr_t)&opvd->pvd_desc_cs,
1060 						(caddr_t)&npvd->pvd_desc_cs,
1061 						sizeof (charspec_t)) == 0)) {
1062 
1063 					if (SWAP_32(opvd->pvd_vdsn) <
1064 						SWAP_32(npvd->pvd_vdsn)) {
1065 						udf_vfsp->udf_pvd = npvd;
1066 					}
1067 				} else {
1068 					goto out;
1069 				}
1070 			}
1071 		} else if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_DESC,
1072 		    vds_loc + (index >> shift),
1073 		    1, desc_len) == 0) {
1074 			struct log_vol_desc *lvd;
1075 
1076 			lvd = (struct log_vol_desc *)ttag;
1077 			if (strncmp(lvd->lvd_dom_id.reg_id,
1078 					UDF_DOMAIN_NAME, 23) != 0) {
1079 				printf("Domain ID in lvd is not valid\n");
1080 				goto out;
1081 			}
1082 
1083 			if (udf_vfsp->udf_lvd == NULL) {
1084 				udf_vfsp->udf_lvd = lvd;
1085 			} else {
1086 				struct log_vol_desc *olvd;
1087 
1088 				olvd = udf_vfsp->udf_lvd;
1089 				if ((strncmp((caddr_t)&olvd->lvd_desc_cs,
1090 						(caddr_t)&lvd->lvd_desc_cs,
1091 						sizeof (charspec_t)) == 0) &&
1092 					(strncmp(olvd->lvd_lvid,
1093 						lvd->lvd_lvid, 128) == 0)) {
1094 					if (SWAP_32(olvd->lvd_vdsn) <
1095 						SWAP_32(lvd->lvd_vdsn)) {
1096 						udf_vfsp->udf_lvd = lvd;
1097 					}
1098 				} else {
1099 					goto out;
1100 				}
1101 			}
1102 		} else if (ud_verify_tag_and_desc(ttag, UD_PART_DESC,
1103 		    vds_loc + (index >> shift),
1104 		    1, desc_len) == 0) {
1105 			int32_t i;
1106 			struct phdr_desc *hdr;
1107 			struct part_desc *pdesc;
1108 			struct ud_part *pnew, *pold, *part;
1109 
1110 			pdesc = (struct part_desc *)ttag;
1111 			pold = udf_vfsp->udf_parts;
1112 			for (i = 0; i < udf_vfsp->udf_npart; i++) {
1113 				if (pold->udp_number ==
1114 					SWAP_16(pdesc->pd_pnum)) {
1115 					if (SWAP_32(pdesc->pd_vdsn) >
1116 						pold->udp_seqno) {
1117 						pold->udp_seqno =
1118 							SWAP_32(pdesc->pd_vdsn);
1119 						pold->udp_access =
1120 						SWAP_32(pdesc->pd_acc_type);
1121 						pold->udp_start =
1122 						SWAP_32(pdesc->pd_part_start);
1123 						pold->udp_length =
1124 						SWAP_32(pdesc->pd_part_length);
1125 					}
1126 					goto loop_end;
1127 				}
1128 				pold ++;
1129 			}
1130 			pold = udf_vfsp->udf_parts;
1131 			udf_vfsp->udf_npart++;
1132 			pnew = kmem_zalloc(udf_vfsp->udf_npart *
1133 					sizeof (struct ud_part), KM_SLEEP);
1134 			udf_vfsp->udf_parts = pnew;
1135 			if (pold) {
1136 				bcopy(pold, pnew,
1137 					sizeof (struct ud_part) *
1138 					(udf_vfsp->udf_npart - 1));
1139 				kmem_free(pold,
1140 					sizeof (struct ud_part) *
1141 					(udf_vfsp->udf_npart - 1));
1142 			}
1143 			part = pnew + (udf_vfsp->udf_npart - 1);
1144 			part->udp_number = SWAP_16(pdesc->pd_pnum);
1145 			part->udp_seqno = SWAP_32(pdesc->pd_vdsn);
1146 			part->udp_access = SWAP_32(pdesc->pd_acc_type);
1147 			part->udp_start = SWAP_32(pdesc->pd_part_start);
1148 			part->udp_length = SWAP_32(pdesc->pd_part_length);
1149 			part->udp_last_alloc = 0;
1150 
1151 			/*
1152 			 * Figure out space bitmaps
1153 			 * or space tables
1154 			 */
1155 			hdr = (struct phdr_desc *)pdesc->pd_pc_use;
1156 			if (hdr->phdr_ust.sad_ext_len) {
1157 				part->udp_flags = UDP_SPACETBLS;
1158 				part->udp_unall_loc =
1159 					SWAP_32(hdr->phdr_ust.sad_ext_loc);
1160 				part->udp_unall_len =
1161 					SWAP_32(hdr->phdr_ust.sad_ext_len);
1162 				part->udp_freed_loc =
1163 					SWAP_32(hdr->phdr_fst.sad_ext_loc);
1164 				part->udp_freed_len =
1165 					SWAP_32(hdr->phdr_fst.sad_ext_len);
1166 			} else {
1167 				part->udp_flags = UDP_BITMAPS;
1168 				part->udp_unall_loc =
1169 					SWAP_32(hdr->phdr_usb.sad_ext_loc);
1170 				part->udp_unall_len =
1171 					SWAP_32(hdr->phdr_usb.sad_ext_len);
1172 				part->udp_freed_loc =
1173 					SWAP_32(hdr->phdr_fsb.sad_ext_loc);
1174 				part->udp_freed_len =
1175 					SWAP_32(hdr->phdr_fsb.sad_ext_len);
1176 			}
1177 		} else if (ud_verify_tag_and_desc(ttag, UD_TERM_DESC,
1178 		    vds_loc + (index >> shift),
1179 		    1, desc_len) == 0) {
1180 
1181 			break;
1182 		}
1183 loop_end:
1184 		;
1185 	}
1186 	if ((udf_vfsp->udf_pvd == NULL) ||
1187 		(udf_vfsp->udf_lvd == NULL) ||
1188 		(udf_vfsp->udf_parts == NULL)) {
1189 		goto out;
1190 	}
1191 
1192 	/*
1193 	 * Process Primary Volume Descriptor
1194 	 */
1195 	(void) strncpy(udf_vfsp->udf_volid, udf_vfsp->udf_pvd->pvd_vol_id, 32);
1196 	udf_vfsp->udf_volid[31] = '\0';
1197 	udf_vfsp->udf_tsno = SWAP_16(udf_vfsp->udf_pvd->pvd_tag.tag_sno);
1198 
1199 	/*
1200 	 * Process Logical Volume Descriptor
1201 	 */
1202 	udf_vfsp->udf_lbsize =
1203 		SWAP_32(udf_vfsp->udf_lvd->lvd_log_bsize);
1204 	udf_vfsp->udf_lbmask = udf_vfsp->udf_lbsize - 1;
1205 	udf_vfsp->udf_l2d_shift = shift;
1206 	udf_vfsp->udf_l2b_shift = shift + DEV_BSHIFT;
1207 
1208 	/*
1209 	 * Check if the media is in
1210 	 * proper domain.
1211 	 */
1212 	if (strcmp(udf_vfsp->udf_lvd->lvd_dom_id.reg_id,
1213 			UDF_DOMAIN_NAME) != 0) {
1214 		goto out;
1215 	}
1216 
1217 	/*
1218 	 * AVDS offset does not match with the lbsize
1219 	 * in the lvd
1220 	 */
1221 	if (udf_vfsp->udf_lbsize != bsize) {
1222 		goto out;
1223 	}
1224 
1225 	udf_vfsp->udf_iseq_loc =
1226 		SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_loc);
1227 	udf_vfsp->udf_iseq_len =
1228 		SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_len);
1229 
1230 	udf_vfsp->udf_fsd_prn =
1231 		SWAP_16(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_prn);
1232 	udf_vfsp->udf_fsd_loc =
1233 		SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_loc);
1234 	udf_vfsp->udf_fsd_len =
1235 		SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_len);
1236 
1237 
1238 	/*
1239 	 * process paritions
1240 	 */
1241 	udf_vfsp->udf_mtype = udf_vfsp->udf_parts[0].udp_access;
1242 	for (index = 0; index < udf_vfsp->udf_npart; index ++) {
1243 		if (udf_vfsp->udf_parts[index].udp_access <
1244 				udf_vfsp->udf_mtype) {
1245 			udf_vfsp->udf_mtype =
1246 				udf_vfsp->udf_parts[index].udp_access;
1247 		}
1248 	}
1249 	if ((udf_vfsp->udf_mtype < UDF_MT_RO) ||
1250 		(udf_vfsp->udf_mtype > UDF_MT_OW)) {
1251 		udf_vfsp->udf_mtype = UDF_MT_RO;
1252 	}
1253 
1254 	udf_vfsp->udf_nmaps = 0;
1255 	hdr = (struct pmap_hdr *)udf_vfsp->udf_lvd->lvd_pmaps;
1256 	count = SWAP_32(udf_vfsp->udf_lvd->lvd_num_pmaps);
1257 	for (index = 0; index < count; index++) {
1258 
1259 		if ((hdr->maph_type == MAP_TYPE1) &&
1260 			(hdr->maph_length == MAP_TYPE1_LEN)) {
1261 			typ1 = (struct pmap_typ1 *)hdr;
1262 
1263 			map = udf_vfsp->udf_maps;
1264 			udf_vfsp->udf_maps =
1265 				kmem_zalloc(sizeof (struct ud_map) *
1266 					(udf_vfsp->udf_nmaps + 1),
1267 					KM_SLEEP);
1268 			if (map != NULL) {
1269 				bcopy(map, udf_vfsp->udf_maps,
1270 				sizeof (struct ud_map) * udf_vfsp->udf_nmaps);
1271 				kmem_free(map,
1272 				sizeof (struct ud_map) * udf_vfsp->udf_nmaps);
1273 			}
1274 			map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1275 			map->udm_flags = UDM_MAP_NORM;
1276 			map->udm_vsn = SWAP_16(typ1->map1_vsn);
1277 			map->udm_pn = SWAP_16(typ1->map1_pn);
1278 			udf_vfsp->udf_nmaps ++;
1279 		} else if ((hdr->maph_type == MAP_TYPE2) &&
1280 			(hdr->maph_length == MAP_TYPE2_LEN)) {
1281 			typ2 = (struct pmap_typ2 *)hdr;
1282 
1283 			if (strncmp(typ2->map2_pti.reg_id,
1284 				UDF_VIRT_PART, 23) == 0) {
1285 				/*
1286 				 * Add this to the normal
1287 				 * partition table so that
1288 				 * we donot
1289 				 */
1290 				map = udf_vfsp->udf_maps;
1291 				udf_vfsp->udf_maps =
1292 					kmem_zalloc(sizeof (struct ud_map) *
1293 						(udf_vfsp->udf_nmaps + 1),
1294 						KM_SLEEP);
1295 				if (map != NULL) {
1296 					bcopy(map, udf_vfsp->udf_maps,
1297 						sizeof (struct ud_map) *
1298 						udf_vfsp->udf_nmaps);
1299 					kmem_free(map,
1300 						sizeof (struct ud_map) *
1301 						udf_vfsp->udf_nmaps);
1302 				}
1303 				map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1304 				map->udm_flags = UDM_MAP_VPM;
1305 				map->udm_vsn = SWAP_16(typ2->map2_vsn);
1306 				map->udm_pn = SWAP_16(typ2->map2_pn);
1307 				udf_vfsp->udf_nmaps ++;
1308 				if (error = ud_get_last_block(dev, &lblkno)) {
1309 					goto out;
1310 				}
1311 				if (error = ud_val_get_vat(udf_vfsp, dev,
1312 					lblkno, map)) {
1313 					goto out;
1314 				}
1315 			} else if (strncmp(typ2->map2_pti.reg_id,
1316 				UDF_SPAR_PART, 23) == 0) {
1317 
1318 				if (SWAP_16(typ2->map2_pl) != 32) {
1319 					printf(
1320 					"Packet Length is not valid %x\n",
1321 						SWAP_16(typ2->map2_pl));
1322 					goto out;
1323 				}
1324 				if ((typ2->map2_nst < 1) ||
1325 					(typ2->map2_nst > 4)) {
1326 					goto out;
1327 				}
1328 				map = udf_vfsp->udf_maps;
1329 				udf_vfsp->udf_maps =
1330 					kmem_zalloc(sizeof (struct ud_map) *
1331 						(udf_vfsp->udf_nmaps + 1),
1332 						KM_SLEEP);
1333 				if (map != NULL) {
1334 					bcopy(map, udf_vfsp->udf_maps,
1335 						sizeof (struct ud_map) *
1336 						udf_vfsp->udf_nmaps);
1337 					kmem_free(map,
1338 						sizeof (struct ud_map) *
1339 						udf_vfsp->udf_nmaps);
1340 				}
1341 				map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1342 				map->udm_flags = UDM_MAP_SPM;
1343 				map->udm_vsn = SWAP_16(typ2->map2_vsn);
1344 				map->udm_pn = SWAP_16(typ2->map2_pn);
1345 
1346 				udf_vfsp->udf_nmaps ++;
1347 
1348 				if (error = ud_read_sparing_tbls(udf_vfsp,
1349 						dev, map, typ2)) {
1350 					goto out;
1351 				}
1352 			} else {
1353 				/*
1354 				 * Unknown type of partition
1355 				 * Bail out
1356 				 */
1357 				goto out;
1358 			}
1359 		} else {
1360 			/*
1361 			 * Unknown type of partition
1362 			 * Bail out
1363 			 */
1364 			goto out;
1365 		}
1366 		hdr = (struct pmap_hdr *)(((uint8_t *)hdr) + hdr->maph_length);
1367 	}
1368 
1369 
1370 	/*
1371 	 * Read Logical Volume Integrity Sequence
1372 	 * and process it
1373 	 */
1374 	secbp = ud_bread(dev, udf_vfsp->udf_iseq_loc << shift,
1375 			udf_vfsp->udf_iseq_len);
1376 	if ((error = geterror(secbp)) != 0) {
1377 		cmn_err(CE_NOTE,
1378 		"udfs : Could not read Logical Volume Integrity Sequence %x",
1379 			error);
1380 		brelse(secbp);
1381 		goto out;
1382 	}
1383 	udf_vfsp->udf_iseq = ngeteblk(udf_vfsp->udf_iseq_len);
1384 	bp = udf_vfsp->udf_iseq;
1385 	bp->b_edev = dev;
1386 	bp->b_dev = cmpdev(dev);
1387 	bp->b_blkno = udf_vfsp->udf_iseq_loc << shift;
1388 	bp->b_bcount = udf_vfsp->udf_iseq_len;
1389 	bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_iseq_len);
1390 	secbp->b_flags |= B_STALE | B_AGE;
1391 	brelse(secbp);
1392 
1393 	count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
1394 	addr = bp->b_un.b_addr;
1395 	for (index = 0; index < count; index ++) {
1396 		ttag = (struct tag *)(addr + index * DEV_BSIZE);
1397 		desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
1398 		if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
1399 		    udf_vfsp->udf_iseq_loc + (index >> shift),
1400 		    1, desc_len) == 0) {
1401 
1402 			struct log_vol_int_desc *lvid;
1403 
1404 			lvid = (struct log_vol_int_desc *)ttag;
1405 			udf_vfsp->udf_lvid = lvid;
1406 
1407 			if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
1408 				udf_vfsp->udf_clean = UDF_CLEAN;
1409 			} else {
1410 				udf_vfsp->udf_clean = UDF_DIRTY;
1411 			}
1412 
1413 			/*
1414 			 * update superblock with the metadata
1415 			 */
1416 			ud_convert_to_superblock(udf_vfsp, lvid);
1417 			break;
1418 		}
1419 	}
1420 
1421 	if (udf_vfsp->udf_lvid == NULL) {
1422 		goto out;
1423 	}
1424 
1425 	if ((blkno = ud_xlate_to_daddr(udf_vfsp,
1426 		udf_vfsp->udf_fsd_prn, udf_vfsp->udf_fsd_loc,
1427 			1, &dummy)) == 0) {
1428 		goto out;
1429 	}
1430 	secbp = ud_bread(dev, blkno << shift, udf_vfsp->udf_fsd_len);
1431 	if ((error = geterror(secbp)) != 0) {
1432 		cmn_err(CE_NOTE,
1433 		"udfs : Could not read File Set Descriptor %x", error);
1434 		brelse(secbp);
1435 		goto out;
1436 	}
1437 	fsd = (struct file_set_desc *)secbp->b_un.b_addr;
1438 	if (ud_verify_tag_and_desc(&fsd->fsd_tag, UD_FILE_SET_DESC,
1439 	    udf_vfsp->udf_fsd_loc,
1440 	    1, udf_vfsp->udf_fsd_len) != 0) {
1441 		secbp->b_flags = B_AGE | B_STALE;
1442 		brelse(secbp);
1443 		goto out;
1444 	}
1445 	udf_vfsp->udf_ricb_prn = SWAP_16(fsd->fsd_root_icb.lad_ext_prn);
1446 	udf_vfsp->udf_ricb_loc = SWAP_32(fsd->fsd_root_icb.lad_ext_loc);
1447 	udf_vfsp->udf_ricb_len = SWAP_32(fsd->fsd_root_icb.lad_ext_len);
1448 	secbp->b_flags = B_AGE | B_STALE;
1449 	brelse(secbp);
1450 	udf_vfsp->udf_root_blkno = ud_xlate_to_daddr(udf_vfsp,
1451 			udf_vfsp->udf_ricb_prn, udf_vfsp->udf_ricb_loc,
1452 			1, &dummy);
1453 
1454 	return (udf_vfsp);
1455 out:
1456 	ud_destroy_fsp(udf_vfsp);
1457 
1458 	return (NULL);
1459 }
1460 
1461 /*
1462  * release/free resources from one ud_map; map data was zalloc'd in
1463  * ud_validate_and_fill_superblock() and fields may later point to
1464  * valid data
1465  */
1466 static void
1467 ud_free_map(struct ud_map *map)
1468 {
1469 	uint32_t n;
1470 
1471 	if (map->udm_flags & UDM_MAP_VPM) {
1472 		if (map->udm_count) {
1473 			kmem_free(map->udm_count,
1474 			    map->udm_nent * sizeof (*map->udm_count));
1475 			map->udm_count = NULL;
1476 		}
1477 		if (map->udm_bp) {
1478 			for (n = 0; n < map->udm_nent; n++) {
1479 				if (map->udm_bp[n])
1480 					brelse(map->udm_bp[n]);
1481 			}
1482 			kmem_free(map->udm_bp,
1483 			    map->udm_nent * sizeof (*map->udm_bp));
1484 			map->udm_bp = NULL;
1485 		}
1486 		if (map->udm_addr) {
1487 			kmem_free(map->udm_addr,
1488 			    map->udm_nent * sizeof (*map->udm_addr));
1489 			map->udm_addr = NULL;
1490 		}
1491 	}
1492 	if (map->udm_flags & UDM_MAP_SPM) {
1493 		for (n = 0; n < MAX_SPM; n++) {
1494 			if (map->udm_sbp[n]) {
1495 				brelse(map->udm_sbp[n]);
1496 				map->udm_sbp[n] = NULL;
1497 				map->udm_spaddr[n] = NULL;
1498 			}
1499 		}
1500 	}
1501 }
1502 
1503 void
1504 ud_destroy_fsp(struct udf_vfs *udf_vfsp)
1505 {
1506 	int32_t i;
1507 
1508 	ud_printf("ud_destroy_fsp\n");
1509 	if (udf_vfsp == NULL)
1510 		return;
1511 
1512 	if (udf_vfsp->udf_maps) {
1513 		for (i = 0; i < udf_vfsp->udf_nmaps; i++)
1514 			ud_free_map(&udf_vfsp->udf_maps[i]);
1515 
1516 		kmem_free(udf_vfsp->udf_maps,
1517 		    udf_vfsp->udf_nmaps * sizeof (*udf_vfsp->udf_maps));
1518 	}
1519 
1520 	if (udf_vfsp->udf_parts) {
1521 		kmem_free(udf_vfsp->udf_parts,
1522 		    udf_vfsp->udf_npart * sizeof (*udf_vfsp->udf_parts));
1523 	}
1524 	if (udf_vfsp->udf_iseq) {
1525 		udf_vfsp->udf_iseq->b_flags |= (B_STALE|B_AGE);
1526 		brelse(udf_vfsp->udf_iseq);
1527 	}
1528 	if (udf_vfsp->udf_vds) {
1529 		udf_vfsp->udf_vds->b_flags |= (B_STALE|B_AGE);
1530 		brelse(udf_vfsp->udf_vds);
1531 	}
1532 	if (udf_vfsp->udf_vfs)
1533 		ud_vfs_remove(udf_vfsp);
1534 	if (udf_vfsp->udf_fsmnt) {
1535 		kmem_free(udf_vfsp->udf_fsmnt,
1536 		    strlen(udf_vfsp->udf_fsmnt) + 1);
1537 	}
1538 	kmem_free(udf_vfsp, sizeof (*udf_vfsp));
1539 }
1540 
1541 void
1542 ud_convert_to_superblock(struct udf_vfs *udf_vfsp,
1543 	struct log_vol_int_desc *lvid)
1544 {
1545 	int32_t i, c;
1546 	uint32_t *temp;
1547 	struct ud_part *ud_part;
1548 	struct lvid_iu *iu;
1549 
1550 	udf_vfsp->udf_maxuniq = SWAP_64(lvid->lvid_uniqid);
1551 	temp = lvid->lvid_fst;
1552 	c = SWAP_32(lvid->lvid_npart);
1553 	ud_part = udf_vfsp->udf_parts;
1554 	for (i = 0; i < c; i++) {
1555 		if (i >= udf_vfsp->udf_npart) {
1556 			continue;
1557 		}
1558 		ud_part->udp_nfree =  SWAP_32(temp[i]);
1559 		ud_part->udp_nblocks =  SWAP_32(temp[c + i]);
1560 		udf_vfsp->udf_freeblks += SWAP_32(temp[i]);
1561 		udf_vfsp->udf_totalblks += SWAP_32(temp[c + i]);
1562 		ud_part++;
1563 	}
1564 
1565 	iu = (struct lvid_iu *)(temp + c * 2);
1566 	udf_vfsp->udf_nfiles = SWAP_32(iu->lvidiu_nfiles);
1567 	udf_vfsp->udf_ndirs = SWAP_32(iu->lvidiu_ndirs);
1568 	udf_vfsp->udf_miread = BCD2HEX_16(SWAP_16(iu->lvidiu_mread));
1569 	udf_vfsp->udf_miwrite = BCD2HEX_16(SWAP_16(iu->lvidiu_mwrite));
1570 	udf_vfsp->udf_mawrite = BCD2HEX_16(SWAP_16(iu->lvidiu_maxwr));
1571 }
1572 
1573 void
1574 ud_update_superblock(struct vfs *vfsp)
1575 {
1576 	struct udf_vfs *udf_vfsp;
1577 
1578 	ud_printf("ud_update_superblock\n");
1579 
1580 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1581 
1582 	mutex_enter(&udf_vfsp->udf_lock);
1583 	ud_sbwrite(udf_vfsp);
1584 	mutex_exit(&udf_vfsp->udf_lock);
1585 }
1586 
1587 
1588 #include <sys/dkio.h>
1589 #include <sys/cdio.h>
1590 #include <sys/vtoc.h>
1591 
1592 /*
1593  * This part of the code is known
1594  * to work with only sparc. It needs
1595  * to be evluated before using it with x86
1596  */
1597 int32_t
1598 ud_get_last_block(dev_t dev, daddr_t *blkno)
1599 {
1600 	struct vtoc vtoc;
1601 	struct dk_cinfo dki_info;
1602 	int32_t rval, error;
1603 
1604 	if ((error = cdev_ioctl(dev, DKIOCGVTOC, (intptr_t)&vtoc,
1605 			FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1606 		cmn_err(CE_NOTE, "Could not get the vtoc information");
1607 		return (error);
1608 	}
1609 
1610 	if (vtoc.v_sanity != VTOC_SANE) {
1611 		return (EINVAL);
1612 	}
1613 	if ((error = cdev_ioctl(dev, DKIOCINFO, (intptr_t)&dki_info,
1614 			FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1615 		cmn_err(CE_NOTE, "Could not get the slice information");
1616 		return (error);
1617 	}
1618 
1619 	if (dki_info.dki_partition > V_NUMPAR) {
1620 		return (EINVAL);
1621 	}
1622 
1623 
1624 	*blkno = vtoc.v_part[dki_info.dki_partition].p_size;
1625 
1626 	return (0);
1627 }
1628 
1629 /* Search sequentially N - 2, N, N - 152, N - 150 for vat icb */
1630 /*
1631  * int32_t ud_sub_blks[] = {2, 0, 152, 150};
1632  */
1633 int32_t ud_sub_blks[] = {152, 150, 2, 0};
1634 int32_t ud_sub_count = 4;
1635 
1636 /*
1637  * Validate the VAT ICB
1638  */
1639 static int32_t
1640 ud_val_get_vat(struct udf_vfs *udf_vfsp, dev_t dev,
1641 	daddr_t blkno, struct ud_map *udm)
1642 {
1643 	struct buf *secbp;
1644 	struct file_entry *fe;
1645 	int32_t end_loc, i, j, ad_type;
1646 	struct short_ad *sad;
1647 	struct long_ad *lad;
1648 	uint32_t count, blk;
1649 	struct ud_part *ud_part;
1650 	int err = 0;
1651 
1652 	end_loc = (blkno >> udf_vfsp->udf_l2d_shift) - 1;
1653 
1654 	for (i = 0; i < ud_sub_count; i++) {
1655 		udm->udm_vat_icb = end_loc - ud_sub_blks[i];
1656 
1657 		secbp = ud_bread(dev,
1658 			udm->udm_vat_icb << udf_vfsp->udf_l2d_shift,
1659 			udf_vfsp->udf_lbsize);
1660 		ASSERT(secbp->b_un.b_addr);
1661 
1662 		fe = (struct file_entry *)secbp->b_un.b_addr;
1663 		if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY, 0,
1664 		    0, 0) == 0) {
1665 			if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
1666 			    SWAP_32(fe->fe_tag.tag_loc),
1667 			    1, udf_vfsp->udf_lbsize) == 0) {
1668 				if (fe->fe_icb_tag.itag_ftype == 0) {
1669 					break;
1670 				}
1671 			}
1672 		}
1673 		secbp->b_flags |= B_AGE | B_STALE;
1674 		brelse(secbp);
1675 	}
1676 	if (i == ud_sub_count) {
1677 		return (EINVAL);
1678 	}
1679 
1680 	ad_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x3;
1681 	if (ad_type == ICB_FLAG_ONE_AD) {
1682 		udm->udm_nent = 1;
1683 	} else if (ad_type == ICB_FLAG_SHORT_AD) {
1684 		udm->udm_nent =
1685 			SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad);
1686 	} else if (ad_type == ICB_FLAG_LONG_AD) {
1687 		udm->udm_nent =
1688 			SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad);
1689 	} else {
1690 		err = EINVAL;
1691 		goto end;
1692 	}
1693 
1694 	udm->udm_count = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_count),
1695 	    KM_SLEEP);
1696 	udm->udm_bp = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_bp),
1697 	    KM_SLEEP);
1698 	udm->udm_addr = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_addr),
1699 	    KM_SLEEP);
1700 
1701 	if (ad_type == ICB_FLAG_ONE_AD) {
1702 			udm->udm_count[0] = (SWAP_64(fe->fe_info_len) - 36) /
1703 						sizeof (uint32_t);
1704 			udm->udm_bp[0] = secbp;
1705 			udm->udm_addr[0] = (uint32_t *)
1706 				&fe->fe_spec[SWAP_32(fe->fe_len_ear)];
1707 			return (0);
1708 	}
1709 	for (i = 0; i < udm->udm_nent; i++) {
1710 		if (ad_type == ICB_FLAG_SHORT_AD) {
1711 			sad = (struct short_ad *)
1712 				(fe->fe_spec + SWAP_32(fe->fe_len_ear));
1713 			sad += i;
1714 			count = SWAP_32(sad->sad_ext_len);
1715 			blk = SWAP_32(sad->sad_ext_loc);
1716 		} else {
1717 			lad = (struct long_ad *)
1718 				(fe->fe_spec + SWAP_32(fe->fe_len_ear));
1719 			lad += i;
1720 			count = SWAP_32(lad->lad_ext_len);
1721 			blk = SWAP_32(lad->lad_ext_loc);
1722 			ASSERT(SWAP_16(lad->lad_ext_prn) == udm->udm_pn);
1723 		}
1724 		if ((count & 0x3FFFFFFF) == 0) {
1725 			break;
1726 		}
1727 		if (i < udm->udm_nent - 1) {
1728 			udm->udm_count[i] = count / 4;
1729 		} else {
1730 			udm->udm_count[i] = (count - 36) / 4;
1731 		}
1732 		ud_part = udf_vfsp->udf_parts;
1733 		for (j = 0; j < udf_vfsp->udf_npart; j++) {
1734 			if (udm->udm_pn == ud_part->udp_number) {
1735 				blk = ud_part->udp_start + blk;
1736 				break;
1737 			}
1738 		}
1739 		if (j == udf_vfsp->udf_npart) {
1740 			err = EINVAL;
1741 			break;
1742 		}
1743 
1744 		count = (count + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1745 		udm->udm_bp[i] = ud_bread(dev,
1746 			blk << udf_vfsp->udf_l2d_shift, count);
1747 		if ((udm->udm_bp[i]->b_error != 0) ||
1748 			(udm->udm_bp[i]->b_resid)) {
1749 			err = EINVAL;
1750 			break;
1751 		}
1752 		udm->udm_addr[i] = (uint32_t *)udm->udm_bp[i]->b_un.b_addr;
1753 	}
1754 
1755 end:
1756 	if (err)
1757 		ud_free_map(udm);
1758 	secbp->b_flags |= B_AGE | B_STALE;
1759 	brelse(secbp);
1760 	return (err);
1761 }
1762 
1763 int32_t
1764 ud_read_sparing_tbls(struct udf_vfs *udf_vfsp,
1765 	dev_t dev, struct ud_map *map, struct pmap_typ2 *typ2)
1766 {
1767 	int32_t index, valid = 0;
1768 	uint32_t sz;
1769 	struct buf *bp;
1770 	struct stbl *stbl;
1771 
1772 	map->udm_plen = SWAP_16(typ2->map2_pl);
1773 	map->udm_nspm = typ2->map2_nst;
1774 	map->udm_spsz = SWAP_32(typ2->map2_sest);
1775 	sz = (map->udm_spsz + udf_vfsp->udf_lbmask) & ~udf_vfsp->udf_lbmask;
1776 	if (sz == 0) {
1777 		return (0);
1778 	}
1779 
1780 	for (index = 0; index < map->udm_nspm; index++) {
1781 		map->udm_loc[index] = SWAP_32(typ2->map2_st[index]);
1782 
1783 		bp = ud_bread(dev,
1784 			map->udm_loc[index] << udf_vfsp->udf_l2d_shift, sz);
1785 		if ((bp->b_error != 0) || (bp->b_resid)) {
1786 			brelse(bp);
1787 			continue;
1788 		}
1789 		stbl = (struct stbl *)bp->b_un.b_addr;
1790 		if (strncmp(stbl->stbl_si.reg_id, UDF_SPAR_TBL, 23) != 0) {
1791 			printf("Sparing Identifier does not match\n");
1792 			bp->b_flags |= B_AGE | B_STALE;
1793 			brelse(bp);
1794 			continue;
1795 		}
1796 		map->udm_sbp[index] = bp;
1797 		map->udm_spaddr[index] = bp->b_un.b_addr;
1798 #ifdef	UNDEF
1799 {
1800 	struct stbl_entry *te;
1801 	int32_t i, tbl_len;
1802 
1803 	te = (struct stbl_entry *)&stbl->stbl_entry;
1804 	tbl_len = SWAP_16(stbl->stbl_len);
1805 
1806 	printf("%x %x\n", tbl_len, SWAP_32(stbl->stbl_seqno));
1807 	printf("%x %x\n", bp->b_un.b_addr, te);
1808 
1809 	for (i = 0; i < tbl_len; i++) {
1810 		printf("%x %x\n", SWAP_32(te->sent_ol), SWAP_32(te->sent_ml));
1811 		te ++;
1812 	}
1813 }
1814 #endif
1815 		valid ++;
1816 	}
1817 
1818 	if (valid) {
1819 		return (0);
1820 	}
1821 	return (EINVAL);
1822 }
1823 
1824 uint32_t
1825 ud_get_lbsize(dev_t dev, uint32_t *loc)
1826 {
1827 	int32_t bsize, shift, index, end_index;
1828 	daddr_t last_block;
1829 	uint32_t avd_loc;
1830 	struct buf *bp;
1831 	struct anch_vol_desc_ptr *avdp;
1832 	uint32_t session_offset = 0;
1833 	int32_t rval;
1834 
1835 	if (ud_get_last_block(dev, &last_block) != 0) {
1836 		end_index = 1;
1837 	} else {
1838 		end_index = 3;
1839 	}
1840 
1841 	if (cdev_ioctl(dev, CDROMREADOFFSET, (intptr_t)&session_offset,
1842 			FKIOCTL|FREAD|FNATIVE, CRED(), &rval) != 0) {
1843 		session_offset = 0;
1844 	}
1845 
1846 	for (index = 0; index < end_index; index++) {
1847 
1848 		for (bsize = DEV_BSIZE, shift = 0;
1849 			bsize <= MAXBSIZE; bsize <<= 1, shift++) {
1850 
1851 			if (index == 0) {
1852 				avd_loc = 256;
1853 				if (bsize <= 2048) {
1854 					avd_loc +=
1855 						session_offset * 2048 / bsize;
1856 				} else {
1857 					avd_loc +=
1858 						session_offset / (bsize / 2048);
1859 				}
1860 			} else if (index == 1) {
1861 				avd_loc = last_block - (1 << shift);
1862 			} else {
1863 				avd_loc = last_block - (256 << shift);
1864 			}
1865 
1866 			bp = ud_bread(dev, avd_loc << shift,
1867 				ANCHOR_VOL_DESC_LEN);
1868 			if (geterror(bp) != 0) {
1869 				brelse(bp);
1870 				continue;
1871 			}
1872 
1873 			/*
1874 			 * Verify if we have avdp here
1875 			 */
1876 			avdp = (struct anch_vol_desc_ptr *)bp->b_un.b_addr;
1877 			if (ud_verify_tag_and_desc(&avdp->avd_tag,
1878 			    UD_ANCH_VOL_DESC, avd_loc,
1879 			    1, ANCHOR_VOL_DESC_LEN) != 0) {
1880 				bp->b_flags |= B_AGE | B_STALE;
1881 				brelse(bp);
1882 				continue;
1883 			}
1884 			bp->b_flags |= B_AGE | B_STALE;
1885 			brelse(bp);
1886 			*loc = avd_loc;
1887 			return (bsize);
1888 		}
1889 	}
1890 
1891 	/*
1892 	 * Did not find AVD at all the locations
1893 	 */
1894 	return (0);
1895 }
1896 
1897 static int
1898 udfinit(int fstype, char *name)
1899 {
1900 	static const fs_operation_def_t udf_vfsops_template[] = {
1901 		VFSNAME_MOUNT,		{ .vfs_mount = udf_mount },
1902 		VFSNAME_UNMOUNT,	{ .vfs_unmount = udf_unmount },
1903 		VFSNAME_ROOT,		{ .vfs_root = udf_root },
1904 		VFSNAME_STATVFS,	{ .vfs_statvfs = udf_statvfs },
1905 		VFSNAME_SYNC,		{ .vfs_sync = udf_sync },
1906 		VFSNAME_VGET,		{ .vfs_vget = udf_vget },
1907 		VFSNAME_MOUNTROOT,	{ .vfs_mountroot = udf_mountroot },
1908 		NULL,			NULL
1909 	};
1910 	extern struct vnodeops *udf_vnodeops;
1911 	extern const fs_operation_def_t udf_vnodeops_template[];
1912 	int error;
1913 
1914 	ud_printf("udfinit\n");
1915 
1916 	error = vfs_setfsops(fstype, udf_vfsops_template, NULL);
1917 	if (error != 0) {
1918 		cmn_err(CE_WARN, "udfinit: bad vfs ops template");
1919 		return (error);
1920 	}
1921 
1922 	error = vn_make_ops(name, udf_vnodeops_template, &udf_vnodeops);
1923 	if (error != 0) {
1924 		(void) vfs_freevfsops_by_type(fstype);
1925 		cmn_err(CE_WARN, "udfinit: bad vnode ops template");
1926 		return (error);
1927 	}
1928 
1929 	udf_fstype = fstype;
1930 
1931 	ud_init_inodes();
1932 
1933 	return (0);
1934 }
1935