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