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