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 "@(#)udf_vfsops.c 1.48 07/10/25 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, NULL)) != 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, NULL);
369 (void) VOP_CLOSE(bvp, flag, 1, (offset_t)0, cr, NULL);
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(), NULL);
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(), NULL);
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,
634 cr, NULL);
635 if (error) {
636 goto out;
637 }
638 needclose = 1;
639
640 /*
641 * Refuse to go any further if this
642 * device is being used for swapping.
643 */
644 if (IS_SWAPVP(devvp)) {
645 error = EBUSY;
646 goto out;
647 }
648 }
649
650 /*
651 * check for dev already mounted on
652 */
653 if (vfsp->vfs_flag & VFS_REMOUNT) {
654 struct tag *ttag;
655 int32_t index, count;
656 struct buf *tpt = 0;
657 caddr_t addr;
658
659
660 /* cannot remount to RDONLY */
661 if (vfsp->vfs_flag & VFS_RDONLY) {
662 return (EINVAL);
663 }
664
665 if (vfsp->vfs_dev != dev) {
666 return (EINVAL);
667 }
668
669 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
670 devvp = udf_vfsp->udf_devvp;
671
672 /*
673 * fsck may have altered the file system; discard
674 * as much incore data as possible. Don't flush
675 * if this is a rw to rw remount; it's just resetting
676 * the options.
677 */
678 if (udf_vfsp->udf_flags & UDF_FL_RDONLY) {
679 (void) dnlc_purge_vfsp(vfsp, 0);
680 (void) VOP_PUTPAGE(devvp, (offset_t)0, (uint_t)0,
681 B_INVAL, CRED(), NULL);
682 (void) ud_iflush(vfsp);
683 bflush(dev);
684 binval(dev);
685 }
686
687 /*
688 * We could read UDF1.50 and write UDF1.50 only
689 * disallow mount of any highier version
690 */
691 if ((udf_vfsp->udf_miread > UDF_150) ||
692 (udf_vfsp->udf_miwrite > UDF_150)) {
693 error = EINVAL;
694 goto remountout;
695 }
696
697 /*
698 * read/write to read/write; all done
699 */
700 if (udf_vfsp->udf_flags & UDF_FL_RW) {
701 goto remountout;
702 }
703
704 /*
705 * Does the media type allow a writable mount
706 */
707 if (udf_vfsp->udf_mtype != UDF_MT_OW) {
708 error = EINVAL;
709 goto remountout;
710 }
711
712 /*
713 * Read the metadata
714 * and check if it is possible to
715 * mount in rw mode
716 */
717 tpt = ud_bread(vfsp->vfs_dev,
718 udf_vfsp->udf_iseq_loc << udf_vfsp->udf_l2d_shift,
719 udf_vfsp->udf_iseq_len);
720 if (tpt->b_flags & B_ERROR) {
721 error = EIO;
722 goto remountout;
723 }
724 count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
725 addr = tpt->b_un.b_addr;
726 for (index = 0; index < count; index ++) {
727 ttag = (struct tag *)(addr + index * DEV_BSIZE);
728 desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
729 if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
730 udf_vfsp->udf_iseq_loc +
731 (index >> udf_vfsp->udf_l2d_shift),
732 1, desc_len) == 0) {
733 struct log_vol_int_desc *lvid;
734
735 lvid = (struct log_vol_int_desc *)ttag;
736
737 if (SWAP_32(lvid->lvid_int_type) !=
738 LOG_VOL_CLOSE_INT) {
739 error = EINVAL;
740 goto remountout;
741 }
742
743 /*
744 * Copy new data to old data
745 */
746 bcopy(udf_vfsp->udf_iseq->b_un.b_addr,
747 tpt->b_un.b_addr, udf_vfsp->udf_iseq_len);
748 break;
749 }
750 }
751
752 udf_vfsp->udf_flags = UDF_FL_RW;
753
754 mutex_enter(&udf_vfsp->udf_lock);
755 ud_sbwrite(udf_vfsp);
756 mutex_exit(&udf_vfsp->udf_lock);
757 remountout:
758 if (tpt != NULL) {
759 tpt->b_flags = B_AGE | B_STALE;
760 brelse(tpt);
761 }
762 return (error);
763 }
764
765 ASSERT(devvp != 0);
766 /*
767 * Flush back any dirty pages on the block device to
768 * try and keep the buffer cache in sync with the page
769 * cache if someone is trying to use block devices when
770 * they really should be using the raw device.
771 */
772 (void) VOP_PUTPAGE(common_specvp(devvp), (offset_t)0,
773 (uint32_t)0, B_INVAL, cr, NULL);
774
775
776 /*
777 * Check if the file system
778 * is a valid udfs and fill
779 * the required fields in udf_vfs
780 */
781 #ifndef __lint
782 _NOTE(NO_COMPETING_THREADS_NOW);
783 #endif
784
785 if ((lbsize = ud_get_lbsize(dev, &avd_loc)) == 0) {
786 error = EINVAL;
787 goto out;
788 }
789
790 udf_vfsp = ud_validate_and_fill_superblock(dev, lbsize, avd_loc);
791 if (udf_vfsp == NULL) {
792 error = EINVAL;
793 goto out;
794 }
795
796 /*
797 * Fill in vfs private data
798 */
799 vfsp->vfs_fstype = udf_fstype;
800 vfs_make_fsid(&vfsp->vfs_fsid, dev, udf_fstype);
801 vfsp->vfs_data = (caddr_t)udf_vfsp;
802 vfsp->vfs_dev = dev;
803 vfsp->vfs_flag |= VFS_NOTRUNC;
804 udf_vfsp->udf_devvp = devvp;
805
806 udf_vfsp->udf_fsmnt = kmem_zalloc(strlen(name) + 1, KM_SLEEP);
807 (void) strcpy(udf_vfsp->udf_fsmnt, name);
808
809 udf_vfsp->udf_vfs = vfsp;
810 udf_vfsp->udf_rdclustsz = udf_vfsp->udf_wrclustsz = maxphys;
811
812 udf_vfsp->udf_mod = 0;
813
814
815 lvid = udf_vfsp->udf_lvid;
816 if (vfsp->vfs_flag & VFS_RDONLY) {
817 /*
818 * We could read only UDF1.50
819 * disallow mount of any highier version
820 */
821 if (udf_vfsp->udf_miread > UDF_150) {
822 error = EINVAL;
823 goto out;
824 }
825 udf_vfsp->udf_flags = UDF_FL_RDONLY;
826 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
827 udf_vfsp->udf_clean = UDF_CLEAN;
828 } else {
829 /* Do we have a VAT at the end of the recorded media */
830 map = udf_vfsp->udf_maps;
831 for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
832 if (map->udm_flags & UDM_MAP_VPM) {
833 break;
834 }
835 map++;
836 }
837 if (i == udf_vfsp->udf_nmaps) {
838 error = ENOSPC;
839 goto out;
840 }
841 udf_vfsp->udf_clean = UDF_CLEAN;
842 }
843 } else {
844 /*
845 * We could read UDF1.50 and write UDF1.50 only
846 * disallow mount of any highier version
847 */
848 if ((udf_vfsp->udf_miread > UDF_150) ||
849 (udf_vfsp->udf_miwrite > UDF_150)) {
850 error = EINVAL;
851 goto out;
852 }
853 /*
854 * Check if the media allows
855 * us to mount read/write
856 */
857 if (udf_vfsp->udf_mtype != UDF_MT_OW) {
858 error = EACCES;
859 goto out;
860 }
861
862 /*
863 * Check if we have VAT on a writable media
864 * we cannot use the media in presence of VAT
865 * Dent RW mount.
866 */
867 map = udf_vfsp->udf_maps;
868 ASSERT(map != NULL);
869 for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
870 if (map->udm_flags & UDM_MAP_VPM) {
871 error = EACCES;
872 goto out;
873 }
874 map++;
875 }
876
877 /*
878 * Check if the domain Id allows
879 * us to write
880 */
881 if (udf_vfsp->udf_lvd->lvd_dom_id.reg_ids[2] & 0x3) {
882 error = EACCES;
883 goto out;
884 }
885 udf_vfsp->udf_flags = UDF_FL_RW;
886
887 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
888 udf_vfsp->udf_clean = UDF_CLEAN;
889 } else {
890 if (isroot) {
891 udf_vfsp->udf_clean = UDF_DIRTY;
892 } else {
893 error = ENOSPC;
894 goto out;
895 }
896 }
897 }
898
899 mutex_init(&udf_vfsp->udf_lock, NULL, MUTEX_DEFAULT, NULL);
900
901 mutex_init(&udf_vfsp->udf_rename_lck, NULL, MUTEX_DEFAULT, NULL);
902
903 #ifndef __lint
904 _NOTE(COMPETING_THREADS_NOW);
905 #endif
906 if (error = ud_iget(vfsp, udf_vfsp->udf_ricb_prn,
907 udf_vfsp->udf_ricb_loc, &rip, NULL, cr)) {
908 mutex_destroy(&udf_vfsp->udf_lock);
909 goto out;
910 }
911
912
913 /*
914 * Get the root inode and
915 * initialize the root vnode
916 */
917 rvp = ITOV(rip);
918 mutex_enter(&rvp->v_lock);
919 rvp->v_flag |= VROOT;
920 mutex_exit(&rvp->v_lock);
921 udf_vfsp->udf_root = rvp;
922
923
924 if (why == ROOT_INIT && isroot)
925 rootvp = devvp;
926
927 ud_vfs_add(udf_vfsp);
928
929 if (udf_vfsp->udf_flags == UDF_FL_RW) {
930 udf_vfsp->udf_clean = UDF_DIRTY;
931 ud_update_superblock(vfsp);
932 }
933
934 return (0);
935
936 out:
937 ud_destroy_fsp(udf_vfsp);
938 if (needclose) {
939 (void) VOP_CLOSE(devvp, (vfsp->vfs_flag & VFS_RDONLY) ?
940 FREAD : FREAD|FWRITE, 1, (offset_t)0, cr, NULL);
941 bflush(dev);
942 binval(dev);
943 }
944 VN_RELE(devvp);
945
946 return (error);
947 }
948
949
950 static struct udf_vfs *
951 ud_validate_and_fill_superblock(dev_t dev, int32_t bsize, uint32_t avd_loc)
952 {
953 int32_t error, count, index, shift;
954 uint32_t dummy, vds_loc;
955 caddr_t addr;
956 daddr_t blkno, lblkno;
957 struct buf *secbp, *bp;
958 struct tag *ttag;
959 struct anch_vol_desc_ptr *avdp;
960 struct file_set_desc *fsd;
961 struct udf_vfs *udf_vfsp = NULL;
962 struct pmap_hdr *hdr;
963 struct pmap_typ1 *typ1;
964 struct pmap_typ2 *typ2;
965 struct ud_map *map;
966 int32_t desc_len;
967
968 ud_printf("ud_validate_and_fill_superblock\n");
969
970 if (bsize < DEV_BSIZE) {
971 return (NULL);
972 }
973 shift = 0;
974 while ((bsize >> shift) > DEV_BSIZE) {
975 shift++;
976 }
977
978 /*
979 * Read Anchor Volume Descriptor
980 * Verify it and get the location of
981 * Main Volume Descriptor Sequence
982 */
983 secbp = ud_bread(dev, avd_loc << shift, ANCHOR_VOL_DESC_LEN);
984 if ((error = geterror(secbp)) != 0) {
985 cmn_err(CE_NOTE,
986 "udfs : Could not read Anchor Volume Desc %x", error);
987 brelse(secbp);
988 return (NULL);
989 }
990 avdp = (struct anch_vol_desc_ptr *)secbp->b_un.b_addr;
991 if (ud_verify_tag_and_desc(&avdp->avd_tag, UD_ANCH_VOL_DESC,
992 avd_loc, 1, ANCHOR_VOL_DESC_LEN) != 0) {
993 brelse(secbp);
994 return (NULL);
995 }
996 udf_vfsp = (struct udf_vfs *)
997 kmem_zalloc(sizeof (struct udf_vfs), KM_SLEEP);
998 udf_vfsp->udf_mvds_loc = SWAP_32(avdp->avd_main_vdse.ext_loc);
999 udf_vfsp->udf_mvds_len = SWAP_32(avdp->avd_main_vdse.ext_len);
1000 udf_vfsp->udf_rvds_loc = SWAP_32(avdp->avd_res_vdse.ext_loc);
1001 udf_vfsp->udf_rvds_len = SWAP_32(avdp->avd_res_vdse.ext_len);
1002 secbp->b_flags = B_AGE | B_STALE;
1003 brelse(secbp);
1004
1005 /*
1006 * Read Main Volume Descriptor Sequence
1007 * and process it
1008 */
1009 vds_loc = udf_vfsp->udf_mvds_loc;
1010 secbp = ud_bread(dev, vds_loc << shift,
1011 udf_vfsp->udf_mvds_len);
1012 if ((error = geterror(secbp)) != 0) {
1013 brelse(secbp);
1014 cmn_err(CE_NOTE,
1015 "udfs : Could not read Main Volume Desc %x", error);
1016
1017 vds_loc = udf_vfsp->udf_rvds_loc;
1018 secbp = ud_bread(dev, vds_loc << shift,
1019 udf_vfsp->udf_rvds_len);
1020 if ((error = geterror(secbp)) != 0) {
1021 brelse(secbp);
1022 cmn_err(CE_NOTE,
1023 "udfs : Could not read Res Volume Desc %x", error);
1024 return (NULL);
1025 }
1026 }
1027
1028 udf_vfsp->udf_vds = ngeteblk(udf_vfsp->udf_mvds_len);
1029 bp = udf_vfsp->udf_vds;
1030 bp->b_edev = dev;
1031 bp->b_dev = cmpdev(dev);
1032 bp->b_blkno = vds_loc << shift;
1033 bp->b_bcount = udf_vfsp->udf_mvds_len;
1034 bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_mvds_len);
1035 secbp->b_flags |= B_STALE | B_AGE;
1036 brelse(secbp);
1037
1038
1039 count = udf_vfsp->udf_mvds_len / DEV_BSIZE;
1040 addr = bp->b_un.b_addr;
1041 for (index = 0; index < count; index ++) {
1042 ttag = (struct tag *)(addr + index * DEV_BSIZE);
1043 desc_len = udf_vfsp->udf_mvds_len - (index * DEV_BSIZE);
1044 if (ud_verify_tag_and_desc(ttag, UD_PRI_VOL_DESC,
1045 vds_loc + (index >> shift),
1046 1, desc_len) == 0) {
1047 if (udf_vfsp->udf_pvd == NULL) {
1048 udf_vfsp->udf_pvd =
1049 (struct pri_vol_desc *)ttag;
1050 } else {
1051 struct pri_vol_desc *opvd, *npvd;
1052
1053 opvd = udf_vfsp->udf_pvd;
1054 npvd = (struct pri_vol_desc *)ttag;
1055
1056 if ((strncmp(opvd->pvd_vsi,
1057 npvd->pvd_vsi, 128) == 0) &&
1058 (strncmp(opvd->pvd_vol_id,
1059 npvd->pvd_vol_id, 32) == 0) &&
1060 (strncmp((caddr_t)&opvd->pvd_desc_cs,
1061 (caddr_t)&npvd->pvd_desc_cs,
1062 sizeof (charspec_t)) == 0)) {
1063
1064 if (SWAP_32(opvd->pvd_vdsn) <
1065 SWAP_32(npvd->pvd_vdsn)) {
1066 udf_vfsp->udf_pvd = npvd;
1067 }
1068 } else {
1069 goto out;
1070 }
1071 }
1072 } else if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_DESC,
1073 vds_loc + (index >> shift),
1074 1, desc_len) == 0) {
1075 struct log_vol_desc *lvd;
1076
1077 lvd = (struct log_vol_desc *)ttag;
1078 if (strncmp(lvd->lvd_dom_id.reg_id,
1079 UDF_DOMAIN_NAME, 23) != 0) {
1080 printf("Domain ID in lvd is not valid\n");
1081 goto out;
1082 }
1083
1084 if (udf_vfsp->udf_lvd == NULL) {
1085 udf_vfsp->udf_lvd = lvd;
1086 } else {
1087 struct log_vol_desc *olvd;
1088
1089 olvd = udf_vfsp->udf_lvd;
1090 if ((strncmp((caddr_t)&olvd->lvd_desc_cs,
1091 (caddr_t)&lvd->lvd_desc_cs,
1092 sizeof (charspec_t)) == 0) &&
1093 (strncmp(olvd->lvd_lvid,
1094 lvd->lvd_lvid, 128) == 0)) {
1095 if (SWAP_32(olvd->lvd_vdsn) <
1096 SWAP_32(lvd->lvd_vdsn)) {
1097 udf_vfsp->udf_lvd = lvd;
1098 }
1099 } else {
1100 goto out;
1101 }
1102 }
1103 } else if (ud_verify_tag_and_desc(ttag, UD_PART_DESC,
1104 vds_loc + (index >> shift),
1105 1, desc_len) == 0) {
1106 int32_t i;
1107 struct phdr_desc *hdr;
1108 struct part_desc *pdesc;
1109 struct ud_part *pnew, *pold, *part;
1110
1111 pdesc = (struct part_desc *)ttag;
1112 pold = udf_vfsp->udf_parts;
1113 for (i = 0; i < udf_vfsp->udf_npart; i++) {
1114 if (pold->udp_number ==
1115 SWAP_16(pdesc->pd_pnum)) {
1116 if (SWAP_32(pdesc->pd_vdsn) >
1117 pold->udp_seqno) {
1118 pold->udp_seqno =
1119 SWAP_32(pdesc->pd_vdsn);
1120 pold->udp_access =
1121 SWAP_32(pdesc->pd_acc_type);
1122 pold->udp_start =
1123 SWAP_32(pdesc->pd_part_start);
1124 pold->udp_length =
1125 SWAP_32(pdesc->pd_part_length);
1126 }
1127 goto loop_end;
1128 }
1129 pold ++;
1130 }
1131 pold = udf_vfsp->udf_parts;
1132 udf_vfsp->udf_npart++;
1133 pnew = kmem_zalloc(udf_vfsp->udf_npart *
1134 sizeof (struct ud_part), KM_SLEEP);
1135 udf_vfsp->udf_parts = pnew;
1136 if (pold) {
1137 bcopy(pold, pnew,
1138 sizeof (struct ud_part) *
1139 (udf_vfsp->udf_npart - 1));
1140 kmem_free(pold,
1141 sizeof (struct ud_part) *
1142 (udf_vfsp->udf_npart - 1));
1143 }
1144 part = pnew + (udf_vfsp->udf_npart - 1);
1145 part->udp_number = SWAP_16(pdesc->pd_pnum);
1146 part->udp_seqno = SWAP_32(pdesc->pd_vdsn);
1147 part->udp_access = SWAP_32(pdesc->pd_acc_type);
1148 part->udp_start = SWAP_32(pdesc->pd_part_start);
1149 part->udp_length = SWAP_32(pdesc->pd_part_length);
1150 part->udp_last_alloc = 0;
1151
1152 /*
1153 * Figure out space bitmaps
1154 * or space tables
1155 */
1156 hdr = (struct phdr_desc *)pdesc->pd_pc_use;
1157 if (hdr->phdr_ust.sad_ext_len) {
1158 part->udp_flags = UDP_SPACETBLS;
1159 part->udp_unall_loc =
1160 SWAP_32(hdr->phdr_ust.sad_ext_loc);
1161 part->udp_unall_len =
1162 SWAP_32(hdr->phdr_ust.sad_ext_len);
1163 part->udp_freed_loc =
1164 SWAP_32(hdr->phdr_fst.sad_ext_loc);
1165 part->udp_freed_len =
1166 SWAP_32(hdr->phdr_fst.sad_ext_len);
1167 } else {
1168 part->udp_flags = UDP_BITMAPS;
1169 part->udp_unall_loc =
1170 SWAP_32(hdr->phdr_usb.sad_ext_loc);
1171 part->udp_unall_len =
1172 SWAP_32(hdr->phdr_usb.sad_ext_len);
1173 part->udp_freed_loc =
1174 SWAP_32(hdr->phdr_fsb.sad_ext_loc);
1175 part->udp_freed_len =
1176 SWAP_32(hdr->phdr_fsb.sad_ext_len);
1177 }
1178 } else if (ud_verify_tag_and_desc(ttag, UD_TERM_DESC,
1179 vds_loc + (index >> shift),
1180 1, desc_len) == 0) {
1181
1182 break;
1183 }
1184 loop_end:
1185 ;
1186 }
1187 if ((udf_vfsp->udf_pvd == NULL) ||
1188 (udf_vfsp->udf_lvd == NULL) ||
1189 (udf_vfsp->udf_parts == NULL)) {
1190 goto out;
1191 }
1192
1193 /*
1194 * Process Primary Volume Descriptor
1195 */
1196 (void) strncpy(udf_vfsp->udf_volid, udf_vfsp->udf_pvd->pvd_vol_id, 32);
1197 udf_vfsp->udf_volid[31] = '\0';
1198 udf_vfsp->udf_tsno = SWAP_16(udf_vfsp->udf_pvd->pvd_tag.tag_sno);
1199
1200 /*
1201 * Process Logical Volume Descriptor
1202 */
1203 udf_vfsp->udf_lbsize =
1204 SWAP_32(udf_vfsp->udf_lvd->lvd_log_bsize);
1205 udf_vfsp->udf_lbmask = udf_vfsp->udf_lbsize - 1;
1206 udf_vfsp->udf_l2d_shift = shift;
1207 udf_vfsp->udf_l2b_shift = shift + DEV_BSHIFT;
1208
1209 /*
1210 * Check if the media is in
1211 * proper domain.
1212 */
1213 if (strcmp(udf_vfsp->udf_lvd->lvd_dom_id.reg_id,
1214 UDF_DOMAIN_NAME) != 0) {
1215 goto out;
1216 }
1217
1218 /*
1219 * AVDS offset does not match with the lbsize
1220 * in the lvd
1221 */
1222 if (udf_vfsp->udf_lbsize != bsize) {
1223 goto out;
1224 }
1225
1226 udf_vfsp->udf_iseq_loc =
1227 SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_loc);
1228 udf_vfsp->udf_iseq_len =
1229 SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_len);
1230
1231 udf_vfsp->udf_fsd_prn =
1232 SWAP_16(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_prn);
1233 udf_vfsp->udf_fsd_loc =
1234 SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_loc);
1235 udf_vfsp->udf_fsd_len =
1236 SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_len);
1237
1238
1239 /*
1240 * process paritions
1241 */
1242 udf_vfsp->udf_mtype = udf_vfsp->udf_parts[0].udp_access;
1243 for (index = 0; index < udf_vfsp->udf_npart; index ++) {
1244 if (udf_vfsp->udf_parts[index].udp_access <
1245 udf_vfsp->udf_mtype) {
1246 udf_vfsp->udf_mtype =
1247 udf_vfsp->udf_parts[index].udp_access;
1248 }
1249 }
1250 if ((udf_vfsp->udf_mtype < UDF_MT_RO) ||
1251 (udf_vfsp->udf_mtype > UDF_MT_OW)) {
1252 udf_vfsp->udf_mtype = UDF_MT_RO;
1253 }
1254
1255 udf_vfsp->udf_nmaps = 0;
1256 hdr = (struct pmap_hdr *)udf_vfsp->udf_lvd->lvd_pmaps;
1257 count = SWAP_32(udf_vfsp->udf_lvd->lvd_num_pmaps);
1258 for (index = 0; index < count; index++) {
1259
1260 if ((hdr->maph_type == MAP_TYPE1) &&
1261 (hdr->maph_length == MAP_TYPE1_LEN)) {
1262 typ1 = (struct pmap_typ1 *)hdr;
1263
1264 map = udf_vfsp->udf_maps;
1265 udf_vfsp->udf_maps =
1266 kmem_zalloc(sizeof (struct ud_map) *
1267 (udf_vfsp->udf_nmaps + 1),
1268 KM_SLEEP);
1269 if (map != NULL) {
1270 bcopy(map, udf_vfsp->udf_maps,
1271 sizeof (struct ud_map) * udf_vfsp->udf_nmaps);
1272 kmem_free(map,
1273 sizeof (struct ud_map) * udf_vfsp->udf_nmaps);
1274 }
1275 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1276 map->udm_flags = UDM_MAP_NORM;
1277 map->udm_vsn = SWAP_16(typ1->map1_vsn);
1278 map->udm_pn = SWAP_16(typ1->map1_pn);
1279 udf_vfsp->udf_nmaps ++;
1280 } else if ((hdr->maph_type == MAP_TYPE2) &&
1281 (hdr->maph_length == MAP_TYPE2_LEN)) {
1282 typ2 = (struct pmap_typ2 *)hdr;
1283
1284 if (strncmp(typ2->map2_pti.reg_id,
1285 UDF_VIRT_PART, 23) == 0) {
1286 /*
1287 * Add this to the normal
1288 * partition table so that
1289 * we donot
1290 */
1291 map = udf_vfsp->udf_maps;
1292 udf_vfsp->udf_maps =
1293 kmem_zalloc(sizeof (struct ud_map) *
1294 (udf_vfsp->udf_nmaps + 1),
1295 KM_SLEEP);
1296 if (map != NULL) {
1297 bcopy(map, udf_vfsp->udf_maps,
1298 sizeof (struct ud_map) *
1299 udf_vfsp->udf_nmaps);
1300 kmem_free(map,
1301 sizeof (struct ud_map) *
1302 udf_vfsp->udf_nmaps);
1303 }
1304 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1305 map->udm_flags = UDM_MAP_VPM;
1306 map->udm_vsn = SWAP_16(typ2->map2_vsn);
1307 map->udm_pn = SWAP_16(typ2->map2_pn);
1308 udf_vfsp->udf_nmaps ++;
1309 if (error = ud_get_last_block(dev, &lblkno)) {
1310 goto out;
1311 }
1312 if (error = ud_val_get_vat(udf_vfsp, dev,
1313 lblkno, map)) {
1314 goto out;
1315 }
1316 } else if (strncmp(typ2->map2_pti.reg_id,
1317 UDF_SPAR_PART, 23) == 0) {
1318
1319 if (SWAP_16(typ2->map2_pl) != 32) {
1320 printf(
1321 "Packet Length is not valid %x\n",
1322 SWAP_16(typ2->map2_pl));
1323 goto out;
1324 }
1325 if ((typ2->map2_nst < 1) ||
1326 (typ2->map2_nst > 4)) {
1327 goto out;
1328 }
1329 map = udf_vfsp->udf_maps;
1330 udf_vfsp->udf_maps =
1331 kmem_zalloc(sizeof (struct ud_map) *
1332 (udf_vfsp->udf_nmaps + 1),
1333 KM_SLEEP);
1334 if (map != NULL) {
1335 bcopy(map, udf_vfsp->udf_maps,
1336 sizeof (struct ud_map) *
1337 udf_vfsp->udf_nmaps);
1338 kmem_free(map,
1339 sizeof (struct ud_map) *
1340 udf_vfsp->udf_nmaps);
1341 }
1342 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1343 map->udm_flags = UDM_MAP_SPM;
1344 map->udm_vsn = SWAP_16(typ2->map2_vsn);
1345 map->udm_pn = SWAP_16(typ2->map2_pn);
1346
1347 udf_vfsp->udf_nmaps ++;
1348
1349 if (error = ud_read_sparing_tbls(udf_vfsp,
1350 dev, map, typ2)) {
1351 goto out;
1352 }
1353 } else {
1354 /*
1355 * Unknown type of partition
1356 * Bail out
1357 */
1358 goto out;
1359 }
1360 } else {
1361 /*
1362 * Unknown type of partition
1363 * Bail out
1364 */
1365 goto out;
1366 }
1367 hdr = (struct pmap_hdr *)(((uint8_t *)hdr) + hdr->maph_length);
1368 }
1369
1370
1371 /*
1372 * Read Logical Volume Integrity Sequence
1373 * and process it
1374 */
1375 secbp = ud_bread(dev, udf_vfsp->udf_iseq_loc << shift,
1376 udf_vfsp->udf_iseq_len);
1377 if ((error = geterror(secbp)) != 0) {
1378 cmn_err(CE_NOTE,
1379 "udfs : Could not read Logical Volume Integrity Sequence %x",
1380 error);
1381 brelse(secbp);
1382 goto out;
1383 }
1384 udf_vfsp->udf_iseq = ngeteblk(udf_vfsp->udf_iseq_len);
1385 bp = udf_vfsp->udf_iseq;
1386 bp->b_edev = dev;
1387 bp->b_dev = cmpdev(dev);
1388 bp->b_blkno = udf_vfsp->udf_iseq_loc << shift;
1389 bp->b_bcount = udf_vfsp->udf_iseq_len;
1390 bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_iseq_len);
1391 secbp->b_flags |= B_STALE | B_AGE;
1392 brelse(secbp);
1393
1394 count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
1395 addr = bp->b_un.b_addr;
1396 for (index = 0; index < count; index ++) {
1397 ttag = (struct tag *)(addr + index * DEV_BSIZE);
1398 desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
1399 if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
1400 udf_vfsp->udf_iseq_loc + (index >> shift),
1401 1, desc_len) == 0) {
1402
1403 struct log_vol_int_desc *lvid;
1404
1405 lvid = (struct log_vol_int_desc *)ttag;
1406 udf_vfsp->udf_lvid = lvid;
1407
1408 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
1409 udf_vfsp->udf_clean = UDF_CLEAN;
1410 } else {
1411 udf_vfsp->udf_clean = UDF_DIRTY;
1412 }
1413
1414 /*
1415 * update superblock with the metadata
1416 */
1417 ud_convert_to_superblock(udf_vfsp, lvid);
1418 break;
1419 }
1420 }
1421
1422 if (udf_vfsp->udf_lvid == NULL) {
1423 goto out;
1424 }
1425
1426 if ((blkno = ud_xlate_to_daddr(udf_vfsp,
1427 udf_vfsp->udf_fsd_prn, udf_vfsp->udf_fsd_loc,
1428 1, &dummy)) == 0) {
1429 goto out;
1430 }
1431 secbp = ud_bread(dev, blkno << shift, udf_vfsp->udf_fsd_len);
1432 if ((error = geterror(secbp)) != 0) {
1433 cmn_err(CE_NOTE,
1434 "udfs : Could not read File Set Descriptor %x", error);
1435 brelse(secbp);
1436 goto out;
1437 }
1438 fsd = (struct file_set_desc *)secbp->b_un.b_addr;
1439 if (ud_verify_tag_and_desc(&fsd->fsd_tag, UD_FILE_SET_DESC,
1440 udf_vfsp->udf_fsd_loc,
1441 1, udf_vfsp->udf_fsd_len) != 0) {
1442 secbp->b_flags = B_AGE | B_STALE;
1443 brelse(secbp);
1444 goto out;
1445 }
1446 udf_vfsp->udf_ricb_prn = SWAP_16(fsd->fsd_root_icb.lad_ext_prn);
1447 udf_vfsp->udf_ricb_loc = SWAP_32(fsd->fsd_root_icb.lad_ext_loc);
1448 udf_vfsp->udf_ricb_len = SWAP_32(fsd->fsd_root_icb.lad_ext_len);
1449 secbp->b_flags = B_AGE | B_STALE;
1450 brelse(secbp);
1451 udf_vfsp->udf_root_blkno = ud_xlate_to_daddr(udf_vfsp,
1452 udf_vfsp->udf_ricb_prn, udf_vfsp->udf_ricb_loc,
1453 1, &dummy);
1454
1455 return (udf_vfsp);
1456 out:
1457 ud_destroy_fsp(udf_vfsp);
1458
1459 return (NULL);
1460 }
1461
1462 /*
1463 * release/free resources from one ud_map; map data was zalloc'd in
1464 * ud_validate_and_fill_superblock() and fields may later point to
1465 * valid data
1466 */
1467 static void
1468 ud_free_map(struct ud_map *map)
1469 {
1470 uint32_t n;
1471
1472 if (map->udm_flags & UDM_MAP_VPM) {
1473 if (map->udm_count) {
1474 kmem_free(map->udm_count,
1475 map->udm_nent * sizeof (*map->udm_count));
1476 map->udm_count = NULL;
1477 }
1478 if (map->udm_bp) {
1479 for (n = 0; n < map->udm_nent; n++) {
1480 if (map->udm_bp[n])
1481 brelse(map->udm_bp[n]);
1482 }
1483 kmem_free(map->udm_bp,
1484 map->udm_nent * sizeof (*map->udm_bp));
1485 map->udm_bp = NULL;
1486 }
1487 if (map->udm_addr) {
1488 kmem_free(map->udm_addr,
1489 map->udm_nent * sizeof (*map->udm_addr));
1490 map->udm_addr = NULL;
1491 }
1492 }
1493 if (map->udm_flags & UDM_MAP_SPM) {
1494 for (n = 0; n < MAX_SPM; n++) {
1495 if (map->udm_sbp[n]) {
1496 brelse(map->udm_sbp[n]);
1497 map->udm_sbp[n] = NULL;
1498 map->udm_spaddr[n] = NULL;
1499 }
1500 }
1501 }
1502 }
1503
1504 void
1505 ud_destroy_fsp(struct udf_vfs *udf_vfsp)
1506 {
1507 int32_t i;
1508
1509 ud_printf("ud_destroy_fsp\n");
1510 if (udf_vfsp == NULL)
1511 return;
1512
1513 if (udf_vfsp->udf_maps) {
1514 for (i = 0; i < udf_vfsp->udf_nmaps; i++)
1515 ud_free_map(&udf_vfsp->udf_maps[i]);
1516
1517 kmem_free(udf_vfsp->udf_maps,
1518 udf_vfsp->udf_nmaps * sizeof (*udf_vfsp->udf_maps));
1519 }
1520
1521 if (udf_vfsp->udf_parts) {
1522 kmem_free(udf_vfsp->udf_parts,
1523 udf_vfsp->udf_npart * sizeof (*udf_vfsp->udf_parts));
1524 }
1525 if (udf_vfsp->udf_iseq) {
1526 udf_vfsp->udf_iseq->b_flags |= (B_STALE|B_AGE);
1527 brelse(udf_vfsp->udf_iseq);
1528 }
1529 if (udf_vfsp->udf_vds) {
1530 udf_vfsp->udf_vds->b_flags |= (B_STALE|B_AGE);
1531 brelse(udf_vfsp->udf_vds);
1532 }
1533 if (udf_vfsp->udf_vfs)
1534 ud_vfs_remove(udf_vfsp);
1535 if (udf_vfsp->udf_fsmnt) {
1536 kmem_free(udf_vfsp->udf_fsmnt,
1537 strlen(udf_vfsp->udf_fsmnt) + 1);
1538 }
1539 kmem_free(udf_vfsp, sizeof (*udf_vfsp));
1540 }
1541
1542 void
1543 ud_convert_to_superblock(struct udf_vfs *udf_vfsp,
1544 struct log_vol_int_desc *lvid)
1545 {
1546 int32_t i, c;
1547 uint32_t *temp;
1548 struct ud_part *ud_part;
1549 struct lvid_iu *iu;
1550
1551 udf_vfsp->udf_maxuniq = SWAP_64(lvid->lvid_uniqid);
1552 temp = lvid->lvid_fst;
1553 c = SWAP_32(lvid->lvid_npart);
1554 ud_part = udf_vfsp->udf_parts;
1555 for (i = 0; i < c; i++) {
1556 if (i >= udf_vfsp->udf_npart) {
1557 continue;
1558 }
1559 ud_part->udp_nfree = SWAP_32(temp[i]);
1560 ud_part->udp_nblocks = SWAP_32(temp[c + i]);
1561 udf_vfsp->udf_freeblks += SWAP_32(temp[i]);
1562 udf_vfsp->udf_totalblks += SWAP_32(temp[c + i]);
1563 ud_part++;
1564 }
1565
1566 iu = (struct lvid_iu *)(temp + c * 2);
1567 udf_vfsp->udf_nfiles = SWAP_32(iu->lvidiu_nfiles);
1568 udf_vfsp->udf_ndirs = SWAP_32(iu->lvidiu_ndirs);
1569 udf_vfsp->udf_miread = BCD2HEX_16(SWAP_16(iu->lvidiu_mread));
1570 udf_vfsp->udf_miwrite = BCD2HEX_16(SWAP_16(iu->lvidiu_mwrite));
1571 udf_vfsp->udf_mawrite = BCD2HEX_16(SWAP_16(iu->lvidiu_maxwr));
1572 }
1573
1574 void
1575 ud_update_superblock(struct vfs *vfsp)
1576 {
1577 struct udf_vfs *udf_vfsp;
1578
1579 ud_printf("ud_update_superblock\n");
1580
1581 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1582
1583 mutex_enter(&udf_vfsp->udf_lock);
1584 ud_sbwrite(udf_vfsp);
1585 mutex_exit(&udf_vfsp->udf_lock);
1586 }
1587
1588
1589 #include <sys/dkio.h>
1590 #include <sys/cdio.h>
1591 #include <sys/vtoc.h>
1592
1593 /*
1594 * This part of the code is known
1595 * to work with only sparc. It needs
1596 * to be evluated before using it with x86
1597 */
1598 int32_t
1599 ud_get_last_block(dev_t dev, daddr_t *blkno)
1600 {
1601 struct vtoc vtoc;
1602 struct dk_cinfo dki_info;
1603 int32_t rval, error;
1604
1605 if ((error = cdev_ioctl(dev, DKIOCGVTOC, (intptr_t)&vtoc,
1606 FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1607 cmn_err(CE_NOTE, "Could not get the vtoc information");
1608 return (error);
1609 }
1610
1611 if (vtoc.v_sanity != VTOC_SANE) {
1612 return (EINVAL);
1613 }
1614 if ((error = cdev_ioctl(dev, DKIOCINFO, (intptr_t)&dki_info,
1615 FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1616 cmn_err(CE_NOTE, "Could not get the slice information");
1617 return (error);
1618 }
1619
1620 if (dki_info.dki_partition > V_NUMPAR) {
1621 return (EINVAL);
1622 }
1623
1624
1625 *blkno = vtoc.v_part[dki_info.dki_partition].p_size;
1626
1627 return (0);
1628 }
1629
1630 /* Search sequentially N - 2, N, N - 152, N - 150 for vat icb */
1631 /*
1632 * int32_t ud_sub_blks[] = {2, 0, 152, 150};
1633 */
1634 int32_t ud_sub_blks[] = {152, 150, 2, 0};
1635 int32_t ud_sub_count = 4;
1636
1637 /*
1638 * Validate the VAT ICB
1639 */
1640 static int32_t
1641 ud_val_get_vat(struct udf_vfs *udf_vfsp, dev_t dev,
1642 daddr_t blkno, struct ud_map *udm)
1643 {
1644 struct buf *secbp;
1645 struct file_entry *fe;
1646 int32_t end_loc, i, j, ad_type;
1647 struct short_ad *sad;
1648 struct long_ad *lad;
1649 uint32_t count, blk;
1650 struct ud_part *ud_part;
1651 int err = 0;
1652
1653 end_loc = (blkno >> udf_vfsp->udf_l2d_shift) - 1;
1654
1655 for (i = 0; i < ud_sub_count; i++) {
1656 udm->udm_vat_icb = end_loc - ud_sub_blks[i];
1657
1658 secbp = ud_bread(dev,
1659 udm->udm_vat_icb << udf_vfsp->udf_l2d_shift,
1660 udf_vfsp->udf_lbsize);
1661 ASSERT(secbp->b_un.b_addr);
1662
1663 fe = (struct file_entry *)secbp->b_un.b_addr;
1664 if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY, 0,
1665 0, 0) == 0) {
1666 if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
1667 SWAP_32(fe->fe_tag.tag_loc),
1668 1, udf_vfsp->udf_lbsize) == 0) {
1669 if (fe->fe_icb_tag.itag_ftype == 0) {
1670 break;
1671 }
1672 }
1673 }
1674 secbp->b_flags |= B_AGE | B_STALE;
1675 brelse(secbp);
1676 }
1677 if (i == ud_sub_count) {
1678 return (EINVAL);
1679 }
1680
1681 ad_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x3;
1682 if (ad_type == ICB_FLAG_ONE_AD) {
1683 udm->udm_nent = 1;
1684 } else if (ad_type == ICB_FLAG_SHORT_AD) {
1685 udm->udm_nent =
1686 SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad);
1687 } else if (ad_type == ICB_FLAG_LONG_AD) {
1688 udm->udm_nent =
1689 SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad);
1690 } else {
1691 err = EINVAL;
1692 goto end;
1693 }
1694
1695 udm->udm_count = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_count),
1696 KM_SLEEP);
1697 udm->udm_bp = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_bp),
1698 KM_SLEEP);
1699 udm->udm_addr = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_addr),
1700 KM_SLEEP);
1701
1702 if (ad_type == ICB_FLAG_ONE_AD) {
1703 udm->udm_count[0] = (SWAP_64(fe->fe_info_len) - 36) /
1704 sizeof (uint32_t);
1705 udm->udm_bp[0] = secbp;
1706 udm->udm_addr[0] = (uint32_t *)
1707 &fe->fe_spec[SWAP_32(fe->fe_len_ear)];
1708 return (0);
1709 }
1710 for (i = 0; i < udm->udm_nent; i++) {
1711 if (ad_type == ICB_FLAG_SHORT_AD) {
1712 sad = (struct short_ad *)
1713 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1714 sad += i;
1715 count = SWAP_32(sad->sad_ext_len);
1716 blk = SWAP_32(sad->sad_ext_loc);
1717 } else {
1718 lad = (struct long_ad *)
1719 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1720 lad += i;
1721 count = SWAP_32(lad->lad_ext_len);
1722 blk = SWAP_32(lad->lad_ext_loc);
1723 ASSERT(SWAP_16(lad->lad_ext_prn) == udm->udm_pn);
1724 }
1725 if ((count & 0x3FFFFFFF) == 0) {
1726 break;
1727 }
1728 if (i < udm->udm_nent - 1) {
1729 udm->udm_count[i] = count / 4;
1730 } else {
1731 udm->udm_count[i] = (count - 36) / 4;
1732 }
1733 ud_part = udf_vfsp->udf_parts;
1734 for (j = 0; j < udf_vfsp->udf_npart; j++) {
1735 if (udm->udm_pn == ud_part->udp_number) {
1736 blk = ud_part->udp_start + blk;
1737 break;
1738 }
1739 }
1740 if (j == udf_vfsp->udf_npart) {
1741 err = EINVAL;
1742 break;
1743 }
1744
1745 count = (count + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1746 udm->udm_bp[i] = ud_bread(dev,
1747 blk << udf_vfsp->udf_l2d_shift, count);
1748 if ((udm->udm_bp[i]->b_error != 0) ||
1749 (udm->udm_bp[i]->b_resid)) {
1750 err = EINVAL;
1751 break;
1752 }
1753 udm->udm_addr[i] = (uint32_t *)udm->udm_bp[i]->b_un.b_addr;
1754 }
1755
1756 end:
1757 if (err)
1758 ud_free_map(udm);
1759 secbp->b_flags |= B_AGE | B_STALE;
1760 brelse(secbp);
1761 return (err);
1762 }
1763
1764 int32_t
1765 ud_read_sparing_tbls(struct udf_vfs *udf_vfsp,
1766 dev_t dev, struct ud_map *map, struct pmap_typ2 *typ2)
1767 {
1768 int32_t index, valid = 0;
1769 uint32_t sz;
1770 struct buf *bp;
1771 struct stbl *stbl;
1772
1773 map->udm_plen = SWAP_16(typ2->map2_pl);
1774 map->udm_nspm = typ2->map2_nst;
1775 map->udm_spsz = SWAP_32(typ2->map2_sest);
1776 sz = (map->udm_spsz + udf_vfsp->udf_lbmask) & ~udf_vfsp->udf_lbmask;
1777 if (sz == 0) {
1778 return (0);
1779 }
1780
1781 for (index = 0; index < map->udm_nspm; index++) {
1782 map->udm_loc[index] = SWAP_32(typ2->map2_st[index]);
1783
1784 bp = ud_bread(dev,
1785 map->udm_loc[index] << udf_vfsp->udf_l2d_shift, sz);
1786 if ((bp->b_error != 0) || (bp->b_resid)) {
1787 brelse(bp);
1788 continue;
1789 }
1790 stbl = (struct stbl *)bp->b_un.b_addr;
1791 if (strncmp(stbl->stbl_si.reg_id, UDF_SPAR_TBL, 23) != 0) {
1792 printf("Sparing Identifier does not match\n");
1793 bp->b_flags |= B_AGE | B_STALE;
1794 brelse(bp);
1795 continue;
1796 }
1797 map->udm_sbp[index] = bp;
1798 map->udm_spaddr[index] = bp->b_un.b_addr;
1799 #ifdef UNDEF
1800 {
1801 struct stbl_entry *te;
1802 int32_t i, tbl_len;
1803
1804 te = (struct stbl_entry *)&stbl->stbl_entry;
1805 tbl_len = SWAP_16(stbl->stbl_len);
1806
1807 printf("%x %x\n", tbl_len, SWAP_32(stbl->stbl_seqno));
1808 printf("%x %x\n", bp->b_un.b_addr, te);
1809
1810 for (i = 0; i < tbl_len; i++) {
1811 printf("%x %x\n", SWAP_32(te->sent_ol), SWAP_32(te->sent_ml));
1812 te ++;
1813 }
1814 }
1815 #endif
1816 valid ++;
1817 }
1818
1819 if (valid) {
1820 return (0);
1821 }
1822 return (EINVAL);
1823 }
1824
1825 uint32_t
1826 ud_get_lbsize(dev_t dev, uint32_t *loc)
1827 {
1828 int32_t bsize, shift, index, end_index;
1829 daddr_t last_block;
1830 uint32_t avd_loc;
1831 struct buf *bp;
1832 struct anch_vol_desc_ptr *avdp;
1833 uint32_t session_offset = 0;
1834 int32_t rval;
1835
1836 if (ud_get_last_block(dev, &last_block) != 0) {
1837 end_index = 1;
1838 } else {
1839 end_index = 3;
1840 }
1841
1842 if (cdev_ioctl(dev, CDROMREADOFFSET, (intptr_t)&session_offset,
1843 FKIOCTL|FREAD|FNATIVE, CRED(), &rval) != 0) {
1844 session_offset = 0;
1845 }
1846
1847 for (index = 0; index < end_index; index++) {
1848
1849 for (bsize = DEV_BSIZE, shift = 0;
1850 bsize <= MAXBSIZE; bsize <<= 1, shift++) {
1851
1852 if (index == 0) {
1853 avd_loc = 256;
1854 if (bsize <= 2048) {
1855 avd_loc +=
1856 session_offset * 2048 / bsize;
1857 } else {
1858 avd_loc +=
1859 session_offset / (bsize / 2048);
1860 }
1861 } else if (index == 1) {
1862 avd_loc = last_block - (1 << shift);
1863 } else {
1864 avd_loc = last_block - (256 << shift);
1865 }
1866
1867 bp = ud_bread(dev, avd_loc << shift,
1868 ANCHOR_VOL_DESC_LEN);
1869 if (geterror(bp) != 0) {
1870 brelse(bp);
1871 continue;
1872 }
1873
1874 /*
1875 * Verify if we have avdp here
1876 */
1877 avdp = (struct anch_vol_desc_ptr *)bp->b_un.b_addr;
1878 if (ud_verify_tag_and_desc(&avdp->avd_tag,
1879 UD_ANCH_VOL_DESC, avd_loc,
1880 1, ANCHOR_VOL_DESC_LEN) != 0) {
1881 bp->b_flags |= B_AGE | B_STALE;
1882 brelse(bp);
1883 continue;
1884 }
1885 bp->b_flags |= B_AGE | B_STALE;
1886 brelse(bp);
1887 *loc = avd_loc;
1888 return (bsize);
1889 }
1890 }
1891
1892 /*
1893 * Did not find AVD at all the locations
1894 */
1895 return (0);
1896 }
1897
1898 static int
1899 udfinit(int fstype, char *name)
1900 {
1901 static const fs_operation_def_t udf_vfsops_template[] = {
1902 VFSNAME_MOUNT, { .vfs_mount = udf_mount },
1903 VFSNAME_UNMOUNT, { .vfs_unmount = udf_unmount },
1904 VFSNAME_ROOT, { .vfs_root = udf_root },
1905 VFSNAME_STATVFS, { .vfs_statvfs = udf_statvfs },
1906 VFSNAME_SYNC, { .vfs_sync = udf_sync },
1907 VFSNAME_VGET, { .vfs_vget = udf_vget },
1908 VFSNAME_MOUNTROOT, { .vfs_mountroot = udf_mountroot },
1909 NULL, NULL
1910 };
1911 extern struct vnodeops *udf_vnodeops;
1912 extern const fs_operation_def_t udf_vnodeops_template[];
1913 int error;
1914
1915 ud_printf("udfinit\n");
1916
1917 error = vfs_setfsops(fstype, udf_vfsops_template, NULL);
1918 if (error != 0) {
1919 cmn_err(CE_WARN, "udfinit: bad vfs ops template");
1920 return (error);
1921 }
1922
1923 error = vn_make_ops(name, udf_vnodeops_template, &udf_vnodeops);
1924 if (error != 0) {
1925 (void) vfs_freevfsops_by_type(fstype);
1926 cmn_err(CE_WARN, "udfinit: bad vnode ops template");
1927 return (error);
1928 }
1929
1930 udf_fstype = fstype;
1931
1932 ud_init_inodes();
1933
1934 return (0);
1935 }