1 /*-
2 * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29 /* udf_vfsops.c */
30 /* Implement the VFS side of things */
31
32 /*
33 * Ok, here's how it goes. The UDF specs are pretty clear on how each data
34 * structure is made up, but not very clear on how they relate to each other.
35 * Here is the skinny... This demostrates a filesystem with one file in the
36 * root directory. Subdirectories are treated just as normal files, but they
37 * have File Id Descriptors of their children as their file data. As for the
38 * Anchor Volume Descriptor Pointer, it can exist in two of the following three
39 * places: sector 256, sector n (the max sector of the disk), or sector
40 * n - 256. It's a pretty good bet that one will exist at sector 256 though.
41 * One caveat is unclosed CD media. For that, sector 256 cannot be written,
42 * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the
43 * media is closed.
44 *
45 * Sector:
46 * 256:
47 * n: Anchor Volume Descriptor Pointer
48 * n - 256: |
49 * |
50 * |-->Main Volume Descriptor Sequence
51 * | |
52 * | |
53 * | |-->Logical Volume Descriptor
54 * | |
55 * |-->Partition Descriptor |
56 * | |
57 * | |
58 * |-->Fileset Descriptor
59 * |
60 * |
61 * |-->Root Dir File Entry
62 * |
63 * |
64 * |-->File data:
65 * File Id Descriptor
66 * |
67 * |
68 * |-->File Entry
69 * |
70 * |
71 * |-->File data
72 */
73 #include <sys/types.h>
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/uio.h>
77 #include <sys/bio.h>
78 #include <sys/buf.h>
79 #include <sys/conf.h>
80 #include <sys/dirent.h>
81 #include <sys/fcntl.h>
82 #include <sys/iconv.h>
83 #include <sys/kernel.h>
84 #include <sys/malloc.h>
85 #include <sys/mount.h>
86 #include <sys/namei.h>
87 #include <sys/proc.h>
88 #include <sys/queue.h>
89 #include <sys/vnode.h>
90 #include <sys/endian.h>
91
92 #include <vm/uma.h>
93
94 #include <fs/udf/ecma167-udf.h>
95 #include <fs/udf/osta.h>
96 #include <fs/udf/udf.h>
97 #include <fs/udf/udf_mount.h>
98
99 MALLOC_DEFINE(M_UDFMOUNT, "UDF mount", "UDF mount structure");
100 MALLOC_DEFINE(M_UDFFENTRY, "UDF fentry", "UDF file entry structure");
101
102 struct iconv_functions *udf_iconv = NULL;
103
104 /* Zones */
105 uma_zone_t udf_zone_trans = NULL;
106 uma_zone_t udf_zone_node = NULL;
107 uma_zone_t udf_zone_ds = NULL;
108
109 static vfs_init_t udf_init;
110 static vfs_uninit_t udf_uninit;
111 static vfs_mount_t udf_mount;
112 static vfs_root_t udf_root;
113 static vfs_statfs_t udf_statfs;
114 static vfs_unmount_t udf_unmount;
115 static vfs_fhtovp_t udf_fhtovp;
116 static vfs_vptofh_t udf_vptofh;
117
118 static int udf_find_partmaps(struct udf_mnt *, struct logvol_desc *);
119
120 static struct vfsops udf_vfsops = {
121 .vfs_fhtovp = udf_fhtovp,
122 .vfs_init = udf_init,
123 .vfs_mount = udf_mount,
124 .vfs_root = udf_root,
125 .vfs_statfs = udf_statfs,
126 .vfs_uninit = udf_uninit,
127 .vfs_unmount = udf_unmount,
128 .vfs_vget = udf_vget,
129 .vfs_vptofh = udf_vptofh,
130 };
131 VFS_SET(udf_vfsops, udf, VFCF_READONLY);
132
133 MODULE_VERSION(udf, 1);
134
135 static int udf_mountfs(struct vnode *, struct mount *, struct thread *);
136
137 static int
138 udf_init(struct vfsconf *foo)
139 {
140
141 /*
142 * This code used to pre-allocate a certain number of pages for each
143 * pool, reducing the need to grow the zones later on. UMA doesn't
144 * advertise any such functionality, unfortunately =-<
145 */
146 udf_zone_trans = uma_zcreate("UDF translation buffer, zone", MAXNAMLEN *
147 sizeof(unicode_t), NULL, NULL, NULL, NULL, 0, 0);
148
149 udf_zone_node = uma_zcreate("UDF Node zone", sizeof(struct udf_node),
150 NULL, NULL, NULL, NULL, 0, 0);
151
152 udf_zone_ds = uma_zcreate("UDF Dirstream zone",
153 sizeof(struct udf_dirstream), NULL, NULL, NULL, NULL, 0, 0);
154
155 if ((udf_zone_node == NULL) || (udf_zone_trans == NULL) ||
156 (udf_zone_ds == NULL)) {
157 printf("Cannot create allocation zones.\n");
158 return (ENOMEM);
159 }
160
161 return 0;
162 }
163
164 static int
165 udf_uninit(struct vfsconf *foo)
166 {
167
168 if (udf_zone_trans != NULL) {
169 uma_zdestroy(udf_zone_trans);
170 udf_zone_trans = NULL;
171 }
172
173 if (udf_zone_node != NULL) {
174 uma_zdestroy(udf_zone_node);
175 udf_zone_node = NULL;
176 }
177
178 if (udf_zone_ds != NULL) {
179 uma_zdestroy(udf_zone_ds);
180 udf_zone_ds = NULL;
181 }
182
183 return (0);
184 }
185
186 static int
187 udf_mount(struct mount *mp, struct thread *td)
188 {
189 struct vnode *devvp; /* vnode of the mount device */
190 struct udf_mnt *imp = 0;
191 struct export_args *export;
192 struct vfsoptlist *opts;
193 char *fspec, *cs_disk, *cs_local;
194 size_t size;
195 int error, len, *udf_flags;
196 struct nameidata nd, *ndp = &nd;
197
198 opts = mp->mnt_optnew;
199
200 if ((mp->mnt_flag & MNT_RDONLY) == 0)
201 return (EROFS);
202
203 /*
204 * No root filesystem support. Probably not a big deal, since the
205 * bootloader doesn't understand UDF.
206 */
207 if (mp->mnt_flag & MNT_ROOTFS)
208 return (ENOTSUP);
209
210 fspec = NULL;
211 error = vfs_getopt(opts, "from", (void **)&fspec, &len);
212 if (!error && fspec[len - 1] != '\0')
213 return (EINVAL);
214
215 if (mp->mnt_flag & MNT_UPDATE) {
216 imp = VFSTOUDFFS(mp);
217 if (fspec == NULL) {
218 error = vfs_getopt(opts, "export", (void **)&export,
219 &len);
220 if (error || len != sizeof(struct export_args))
221 return (EINVAL);
222 return (vfs_export(mp, export));
223 }
224 }
225
226 /* Check that the mount device exists */
227 if (fspec == NULL)
228 return (EINVAL);
229 NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, td);
230 if ((error = namei(ndp)))
231 return (error);
232 NDFREE(ndp, NDF_ONLY_PNBUF);
233 devvp = ndp->ni_vp;
234
235 if (vn_isdisk(devvp, &error) == 0) {
236 vrele(devvp);
237 return (error);
238 }
239
240 /* Check the access rights on the mount device */
241 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
242 error = VOP_ACCESS(devvp, VREAD, td->td_ucred, td);
243 if (error)
244 error = suser(td);
245 if (error) {
246 vput(devvp);
247 return (error);
248 }
249 VOP_UNLOCK(devvp, 0, td);
250
251 if ((error = udf_mountfs(devvp, mp, td))) {
252 vrele(devvp);
253 return (error);
254 }
255
256 imp = VFSTOUDFFS(mp);
257
258 udf_flags = NULL;
259 error = vfs_getopt(opts, "flags", (void **)&udf_flags, &len);
260 if (error || len != sizeof(int))
261 return (EINVAL);
262 imp->im_flags = *udf_flags;
263
264 if (imp->im_flags & UDFMNT_KICONV && udf_iconv) {
265 cs_disk = NULL;
266 error = vfs_getopt(opts, "cs_disk", (void **)&cs_disk, &len);
267 if (!error && cs_disk[len - 1] != '\0')
268 return (EINVAL);
269 cs_local = NULL;
270 error = vfs_getopt(opts, "cs_local", (void **)&cs_local, &len);
271 if (!error && cs_local[len - 1] != '\0')
272 return (EINVAL);
273 udf_iconv->open(cs_local, cs_disk, &imp->im_d2l);
274 #if 0
275 udf_iconv->open(cs_disk, cs_local, &imp->im_l2d);
276 #endif
277 }
278
279 copystr(fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
280 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
281 udf_statfs(mp, &mp->mnt_stat, td);
282 return 0;
283 };
284
285 /*
286 * Check the descriptor tag for both the correct id and correct checksum.
287 * Return zero if all is good, EINVAL if not.
288 */
289 int
290 udf_checktag(struct desc_tag *tag, uint16_t id)
291 {
292 uint8_t *itag;
293 uint8_t i, cksum = 0;
294
295 itag = (uint8_t *)tag;
296
297 if (tag->id != id)
298 return (EINVAL);
299
300 for (i = 0; i < 16; i++)
301 cksum = cksum + itag[i];
302 cksum = cksum - itag[4];
303
304 if (cksum == tag->cksum)
305 return (0);
306
307 return (EINVAL);
308 }
309
310 static int
311 udf_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td) {
312 struct buf *bp = NULL;
313 struct anchor_vdp avdp;
314 struct udf_mnt *udfmp = NULL;
315 struct part_desc *pd;
316 struct logvol_desc *lvd;
317 struct fileset_desc *fsd;
318 struct file_entry *root_fentry;
319 uint32_t sector, size, mvds_start, mvds_end;
320 uint32_t fsd_offset = 0;
321 uint16_t part_num = 0, fsd_part = 0;
322 int error = EINVAL, needclose = 0;
323 int logvol_found = 0, part_found = 0, fsd_found = 0;
324 int bsize;
325
326 /*
327 * Disallow multiple mounts of the same device. Flush the buffer
328 * cache for the device.
329 */
330 if ((error = vfs_mountedon(devvp)))
331 return (error);
332 if (vcount(devvp) > 1)
333 return (EBUSY);
334 if ((error = vinvalbuf(devvp, V_SAVE, td->td_ucred, td, 0, 0)))
335 return (error);
336
337 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
338 error = VOP_OPEN(devvp, FREAD, FSCRED, td, -1);
339 VOP_UNLOCK(devvp, 0, td);
340 if (error)
341 return error;
342 needclose = 1;
343
344 MALLOC(udfmp, struct udf_mnt *, sizeof(struct udf_mnt), M_UDFMOUNT,
345 M_NOWAIT | M_ZERO);
346 if (udfmp == NULL) {
347 printf("Cannot allocate UDF mount struct\n");
348 error = ENOMEM;
349 goto bail;
350 }
351
352 mp->mnt_data = (qaddr_t)udfmp;
353 mp->mnt_stat.f_fsid.val[0] = dev2udev(devvp->v_rdev);
354 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
355 mp->mnt_flag |= MNT_LOCAL;
356 udfmp->im_mountp = mp;
357 udfmp->im_dev = devvp->v_rdev;
358 udfmp->im_devvp = devvp;
359 udfmp->im_d2l = NULL;
360 #if 0
361 udfmp->im_l2d = NULL;
362 #endif
363
364 bsize = 2048; /* XXX Should probe the media for it's size */
365
366 /*
367 * Get the Anchor Volume Descriptor Pointer from sector 256.
368 * XXX Should also check sector n - 256, n, and 512.
369 */
370 sector = 256;
371 if ((error = bread(devvp, sector * btodb(bsize), bsize, NOCRED,
372 &bp)) != 0)
373 goto bail;
374 if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
375 goto bail;
376
377 bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
378 brelse(bp);
379 bp = NULL;
380
381 /*
382 * Extract the Partition Descriptor and Logical Volume Descriptor
383 * from the Volume Descriptor Sequence.
384 * XXX Should we care about the partition type right now?
385 * XXX What about multiple partitions?
386 */
387 mvds_start = le32toh(avdp.main_vds_ex.loc);
388 mvds_end = mvds_start + (le32toh(avdp.main_vds_ex.len) - 1) / bsize;
389 for (sector = mvds_start; sector < mvds_end; sector++) {
390 if ((error = bread(devvp, sector * btodb(bsize), bsize,
391 NOCRED, &bp)) != 0) {
392 printf("Can't read sector %d of VDS\n", sector);
393 goto bail;
394 }
395 lvd = (struct logvol_desc *)bp->b_data;
396 if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
397 udfmp->bsize = le32toh(lvd->lb_size);
398 udfmp->bmask = udfmp->bsize - 1;
399 udfmp->bshift = ffs(udfmp->bsize) - 1;
400 fsd_part = le16toh(lvd->_lvd_use.fsd_loc.loc.part_num);
401 fsd_offset = le32toh(lvd->_lvd_use.fsd_loc.loc.lb_num);
402 if (udf_find_partmaps(udfmp, lvd))
403 break;
404 logvol_found = 1;
405 }
406 pd = (struct part_desc *)bp->b_data;
407 if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
408 part_found = 1;
409 part_num = le16toh(pd->part_num);
410 udfmp->part_len = le32toh(pd->part_len);
411 udfmp->part_start = le32toh(pd->start_loc);
412 }
413
414 brelse(bp);
415 bp = NULL;
416 if ((part_found) && (logvol_found))
417 break;
418 }
419
420 if (!part_found || !logvol_found) {
421 error = EINVAL;
422 goto bail;
423 }
424
425 if (fsd_part != part_num) {
426 printf("FSD does not lie within the partition!\n");
427 error = EINVAL;
428 goto bail;
429 }
430
431
432 /*
433 * Grab the Fileset Descriptor
434 * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
435 * me in the right direction here.
436 */
437 sector = udfmp->part_start + fsd_offset;
438 if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
439 printf("Cannot read sector %d of FSD\n", sector);
440 goto bail;
441 }
442 fsd = (struct fileset_desc *)bp->b_data;
443 if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
444 fsd_found = 1;
445 bcopy(&fsd->rootdir_icb, &udfmp->root_icb,
446 sizeof(struct long_ad));
447 }
448
449 brelse(bp);
450 bp = NULL;
451
452 if (!fsd_found) {
453 printf("Couldn't find the fsd\n");
454 error = EINVAL;
455 goto bail;
456 }
457
458 /*
459 * Find the file entry for the root directory.
460 */
461 sector = le32toh(udfmp->root_icb.loc.lb_num) + udfmp->part_start;
462 size = le32toh(udfmp->root_icb.len);
463 if ((error = udf_readlblks(udfmp, sector, size, &bp)) != 0) {
464 printf("Cannot read sector %d\n", sector);
465 goto bail;
466 }
467
468 root_fentry = (struct file_entry *)bp->b_data;
469 if ((error = udf_checktag(&root_fentry->tag, TAGID_FENTRY))) {
470 printf("Invalid root file entry!\n");
471 goto bail;
472 }
473
474 brelse(bp);
475 bp = NULL;
476
477 devvp->v_rdev->si_mountpoint = mp;
478
479 mtx_init(&udfmp->hash_mtx, "udf_hash", NULL, MTX_DEF);
480 udfmp->hashtbl = phashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, &udfmp->hashsz);
481
482 return 0;
483
484 bail:
485 if (udfmp != NULL)
486 FREE(udfmp, M_UDFMOUNT);
487 if (bp != NULL)
488 brelse(bp);
489 if (needclose)
490 VOP_CLOSE(devvp, FREAD, NOCRED, td);
491 return error;
492 };
493
494 static int
495 udf_unmount(struct mount *mp, int mntflags, struct thread *td)
496 {
497 struct udf_mnt *udfmp;
498 int error, flags = 0;
499
500 udfmp = VFSTOUDFFS(mp);
501
502 if (mntflags & MNT_FORCE)
503 flags |= FORCECLOSE;
504
505 if ((error = vflush(mp, 0, flags, td)))
506 return (error);
507
508 if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) {
509 if (udfmp->im_d2l)
510 udf_iconv->close(udfmp->im_d2l);
511 #if 0
512 if (udfmp->im_l2d)
513 udf_iconv->close(udfmp->im_l2d);
514 #endif
515 }
516
517 udfmp->im_devvp->v_rdev->si_mountpoint = NULL;
518 error = VOP_CLOSE(udfmp->im_devvp, FREAD, NOCRED, td);
519 vrele(udfmp->im_devvp);
520
521 if (udfmp->s_table != NULL)
522 FREE(udfmp->s_table, M_UDFMOUNT);
523
524 if (udfmp->hashtbl != NULL)
525 FREE(udfmp->hashtbl, M_UDFMOUNT);
526
527 FREE(udfmp, M_UDFMOUNT);
528
529 mp->mnt_data = (qaddr_t)0;
530 mp->mnt_flag &= ~MNT_LOCAL;
531
532 return (0);
533 }
534
535 static int
536 udf_root(struct mount *mp, struct vnode **vpp, struct thread *td)
537 {
538 struct udf_mnt *udfmp;
539 struct vnode *vp;
540 ino_t id;
541 int error;
542
543 udfmp = VFSTOUDFFS(mp);
544
545 id = udf_getid(&udfmp->root_icb);
546
547 error = udf_vget(mp, id, LK_EXCLUSIVE, vpp);
548 if (error)
549 return error;
550
551 vp = *vpp;
552 vp->v_vflag |= VV_ROOT;
553
554 return (0);
555 }
556
557 static int
558 udf_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
559 {
560 struct udf_mnt *udfmp;
561
562 udfmp = VFSTOUDFFS(mp);
563
564 sbp->f_bsize = udfmp->bsize;
565 sbp->f_iosize = udfmp->bsize;
566 sbp->f_blocks = udfmp->part_len;
567 sbp->f_bfree = 0;
568 sbp->f_bavail = 0;
569 sbp->f_files = 0;
570 sbp->f_ffree = 0;
571 if (sbp != &mp->mnt_stat) {
572 sbp->f_type = mp->mnt_vfc->vfc_typenum;
573 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
574 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
575 }
576
577 return 0;
578 }
579
580 int
581 udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
582 {
583 struct buf *bp;
584 struct vnode *devvp;
585 struct udf_mnt *udfmp;
586 struct thread *td;
587 struct vnode *vp;
588 struct udf_node *unode;
589 struct file_entry *fe;
590 int error, sector, size;
591
592 td = curthread;
593 udfmp = VFSTOUDFFS(mp);
594
595 /* See if we already have this in the cache */
596 if ((error = udf_hashlookup(udfmp, ino, flags, vpp)) != 0)
597 return (error);
598 if (*vpp != NULL) {
599 return (0);
600 }
601
602 /*
603 * Allocate memory and check the tag id's before grabbing a new
604 * vnode, since it's hard to roll back if there is a problem.
605 */
606 unode = uma_zalloc(udf_zone_node, M_WAITOK);
607 if (unode == NULL) {
608 printf("Cannot allocate udf node\n");
609 return (ENOMEM);
610 }
611
612 /*
613 * Copy in the file entry. Per the spec, the size can only be 1 block.
614 */
615 sector = ino + udfmp->part_start;
616 devvp = udfmp->im_devvp;
617 if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
618 printf("Cannot read sector %d\n", sector);
619 uma_zfree(udf_zone_node, unode);
620 return (error);
621 }
622
623 fe = (struct file_entry *)bp->b_data;
624 if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
625 printf("Invalid file entry!\n");
626 uma_zfree(udf_zone_node, unode);
627 brelse(bp);
628 return (ENOMEM);
629 }
630 size = UDF_FENTRY_SIZE + le32toh(fe->l_ea) + le32toh(fe->l_ad);
631 MALLOC(unode->fentry, struct file_entry *, size, M_UDFFENTRY,
632 M_NOWAIT | M_ZERO);
633 if (unode->fentry == NULL) {
634 printf("Cannot allocate file entry block\n");
635 uma_zfree(udf_zone_node, unode);
636 brelse(bp);
637 return (ENOMEM);
638 }
639
640 bcopy(bp->b_data, unode->fentry, size);
641
642 brelse(bp);
643 bp = NULL;
644
645 if ((error = udf_allocv(mp, &vp, td))) {
646 printf("Error from udf_allocv\n");
647 uma_zfree(udf_zone_node, unode);
648 return (error);
649 }
650
651 unode->i_vnode = vp;
652 unode->hash_id = ino;
653 unode->i_devvp = udfmp->im_devvp;
654 unode->i_dev = udfmp->im_dev;
655 unode->udfmp = udfmp;
656 vp->v_data = unode;
657 VREF(udfmp->im_devvp);
658 udf_hashins(unode);
659
660 switch (unode->fentry->icbtag.file_type) {
661 default:
662 vp->v_type = VBAD;
663 break;
664 case 4:
665 vp->v_type = VDIR;
666 break;
667 case 5:
668 vp->v_type = VREG;
669 break;
670 case 6:
671 vp->v_type = VBLK;
672 break;
673 case 7:
674 vp->v_type = VCHR;
675 break;
676 case 9:
677 vp->v_type = VFIFO;
678 break;
679 case 10:
680 vp->v_type = VSOCK;
681 break;
682 case 12:
683 vp->v_type = VLNK;
684 break;
685 }
686 *vpp = vp;
687
688 return (0);
689 }
690
691 struct ifid {
692 u_short ifid_len;
693 u_short ifid_pad;
694 int ifid_ino;
695 long ifid_start;
696 };
697
698 static int
699 udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
700 {
701 struct ifid *ifhp;
702 struct vnode *nvp;
703 int error;
704
705 ifhp = (struct ifid *)fhp;
706
707 if ((error = VFS_VGET(mp, ifhp->ifid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
708 *vpp = NULLVP;
709 return (error);
710 }
711
712 *vpp = nvp;
713 return (0);
714 }
715
716 static int
717 udf_vptofh (struct vnode *vp, struct fid *fhp)
718 {
719 struct udf_node *node;
720 struct ifid *ifhp;
721
722 node = VTON(vp);
723 ifhp = (struct ifid *)fhp;
724 ifhp->ifid_len = sizeof(struct ifid);
725 ifhp->ifid_ino = node->hash_id;
726
727 return (0);
728 }
729
730 static int
731 udf_find_partmaps(struct udf_mnt *udfmp, struct logvol_desc *lvd)
732 {
733 union udf_pmap *pmap;
734 struct part_map_spare *pms;
735 struct regid *pmap_id;
736 struct buf *bp;
737 unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
738 int i, ptype, psize, error;
739
740 for (i = 0; i < le32toh(lvd->n_pm); i++) {
741 pmap = (union udf_pmap *)&lvd->maps[i * UDF_PMAP_SIZE];
742 ptype = pmap->data[0];
743 psize = pmap->data[1];
744 if (((ptype != 1) && (ptype != 2)) ||
745 ((psize != UDF_PMAP_SIZE) && (psize != 6))) {
746 printf("Invalid partition map found\n");
747 return (1);
748 }
749
750 if (ptype == 1) {
751 /* Type 1 map. We don't care */
752 continue;
753 }
754
755 /* Type 2 map. Gotta find out the details */
756 pmap_id = (struct regid *)&pmap->data[4];
757 bzero(®id_id[0], UDF_REGID_ID_SIZE);
758 bcopy(&pmap_id->id[0], ®id_id[0], UDF_REGID_ID_SIZE);
759
760 if (bcmp(®id_id[0], "*UDF Sparable Partition",
761 UDF_REGID_ID_SIZE)) {
762 printf("Unsupported partition map: %s\n", ®id_id[0]);
763 return (1);
764 }
765
766 pms = &pmap->pms;
767 MALLOC(udfmp->s_table, struct udf_sparing_table *,
768 le32toh(pms->st_size), M_UDFMOUNT, M_NOWAIT | M_ZERO);
769 if (udfmp->s_table == NULL)
770 return (ENOMEM);
771
772 /* Calculate the number of sectors per packet. */
773 /* XXX Logical or physical? */
774 udfmp->p_sectors = le16toh(pms->packet_len) / udfmp->bsize;
775
776 /*
777 * XXX If reading the first Sparing Table fails, should look
778 * for another table.
779 */
780 if ((error = udf_readlblks(udfmp, le32toh(pms->st_loc[0]),
781 le32toh(pms->st_size), &bp)) != 0) {
782 if (bp != NULL)
783 brelse(bp);
784 printf("Failed to read Sparing Table at sector %d\n",
785 le32toh(pms->st_loc[0]));
786 return (error);
787 }
788 bcopy(bp->b_data, udfmp->s_table, le32toh(pms->st_size));
789 brelse(bp);
790
791 if (udf_checktag(&udfmp->s_table->tag, 0)) {
792 printf("Invalid sparing table found\n");
793 return (EINVAL);
794 }
795
796 /* See how many valid entries there are here. The list is
797 * supposed to be sorted. 0xfffffff0 and higher are not valid
798 */
799 for (i = 0; i < le16toh(udfmp->s_table->rt_l); i++) {
800 udfmp->s_table_entries = i;
801 if (le32toh(udfmp->s_table->entries[i].org) >=
802 0xfffffff0)
803 break;
804 }
805 }
806
807 return (0);
808 }
Cache object: 8ccdfaa123e679c10d3b711f249960a2
|