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