Merge from vendor branch NTPD:
[dragonfly.git] / sys / vfs / udf / udf_vfsops.c
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: src/sys/fs/udf/udf_vfsops.c,v 1.16 2003/11/05 06:56:08 scottl Exp $
27  * $DragonFly: src/sys/vfs/udf/udf_vfsops.c,v 1.9 2004/10/12 19:21:10 dillon Exp $
28  */
29
30 /* udf_vfsops.c */
31 /* Implement the VFS side of things */
32
33 /*
34  * Ok, here's how it goes.  The UDF specs are pretty clear on how each data
35  * structure is made up, but not very clear on how they relate to each other.
36  * Here is the skinny... This demostrates a filesystem with one file in the
37  * root directory.  Subdirectories are treated just as normal files, but they
38  * have File Id Descriptors of their children as their file data.  As for the
39  * Anchor Volume Descriptor Pointer, it can exist in two of the following three
40  * places: sector 256, sector n (the max sector of the disk), or sector
41  * n - 256.  It's a pretty good bet that one will exist at sector 256 though.
42  * One caveat is unclosed CD media.  For that, sector 256 cannot be written,
43  * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the
44  * media is closed.
45  *
46  *  Sector:
47  *     256:
48  *       n: Anchor Volume Descriptor Pointer
49  * n - 256:     |
50  *              |
51  *              |-->Main Volume Descriptor Sequence
52  *                      |       |
53  *                      |       |
54  *                      |       |-->Logical Volume Descriptor
55  *                      |                         |
56  *                      |-->Partition Descriptor  |
57  *                              |                 |
58  *                              |                 |
59  *                              |-->Fileset Descriptor
60  *                                      |
61  *                                      |
62  *                                      |-->Root Dir File Entry
63  *                                              |
64  *                                              |
65  *                                              |-->File data:
66  *                                                  File Id Descriptor
67  *                                                      |
68  *                                                      |
69  *                                                      |-->File Entry
70  *                                                              |
71  *                                                              |
72  *                                                              |-->File data
73  */
74
75 #include <sys/types.h>
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/uio.h>
79 #include <sys/buf.h>
80 #include <sys/conf.h>
81 #include <sys/dirent.h>
82 #include <sys/fcntl.h>
83 #include <sys/module.h>
84 #include <sys/kernel.h>
85 #include <sys/malloc.h>
86 #include <sys/mount.h>
87 #include <sys/namei.h>
88 #include <sys/proc.h>
89 #include <sys/queue.h>
90 #include <sys/vnode.h>
91
92 #include <vfs/udf/ecma167-udf.h>
93 #include <vfs/udf/osta.h>
94 #include <vfs/udf/udf.h>
95 #include <vfs/udf/udf_mount.h>
96
97 extern struct vnodeopv_entry_desc udf_vnodeop_entries[];
98
99 MALLOC_DEFINE(M_UDFNODE, "UDF node", "UDF node structure");
100 MALLOC_DEFINE(M_UDFMOUNT, "UDF mount", "UDF mount structure");
101 MALLOC_DEFINE(M_UDFFENTRY, "UDF fentry", "UDF file entry structure");
102
103 static int udf_mount(struct mount *, char *, caddr_t, struct thread *);
104 static int udf_unmount(struct mount *, int, struct thread *);
105 static int udf_root(struct mount *, struct vnode **);
106 static int udf_statfs(struct mount *, struct statfs *, struct thread *);
107 static int udf_fhtovp(struct mount *, struct fid *, struct vnode **);
108 static int udf_vptofh(struct vnode *, struct fid *);
109
110 static int udf_find_partmaps(struct udf_mnt *, struct logvol_desc *);
111
112 static struct vfsops udf_vfsops = {
113         udf_mount,
114         vfs_stdstart,
115         udf_unmount,
116         udf_root,
117         vfs_stdquotactl,
118         udf_statfs,
119         vfs_stdsync,
120         udf_vget,
121         udf_fhtovp,
122         vfs_stdcheckexp,
123         udf_vptofh,
124         vfs_stdinit,
125         vfs_stduninit,
126         vfs_stdextattrctl,
127 };
128 VFS_SET(udf_vfsops, udf, VFCF_READONLY);
129
130 MODULE_VERSION(udf, 1);
131
132 static int udf_mountfs(struct vnode *, struct mount *, struct thread *);
133
134 static int
135 udf_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
136 {
137         struct vnode *devvp;    /* vnode of the mount device */
138         struct udf_args args;
139         struct udf_mnt *imp = 0;
140         size_t size;
141         int error;
142         struct nameidata nd;
143
144         if ((mp->mnt_flag & MNT_RDONLY) == 0)
145                 return (EROFS);
146
147         /*
148          * No root filesystem support.  Probably not a big deal, since the
149          * bootloader doesn't understand UDF.
150          */
151         if (mp->mnt_flag & MNT_ROOTFS)
152                 return (ENOTSUP);
153
154         if ((error = copyin(data, (caddr_t)&args, sizeof(struct udf_args))))
155                 return(error);
156
157         if (mp->mnt_flag & MNT_UPDATE) {
158                 imp = VFSTOUDFFS(mp);
159                 if (args.fspec == NULL)
160                         return(vfs_export(mp, &imp->im_export, &args.export));
161         }
162
163         /* Check that the mount device exists */
164         NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, args.fspec, td);
165         if ((error = namei(&nd)))
166                 return(error);
167         NDFREE(&nd, NDF_ONLY_PNBUF);
168         devvp = nd.ni_vp;
169
170         if (vn_isdisk(devvp, &error) == 0) {
171                 vrele(devvp);
172                 return(error);
173         }
174
175         /* Check the access rights on the mount device */
176         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
177         error = VOP_ACCESS(devvp, VREAD, td->td_proc->p_ucred, td);
178         if (error)
179                 error = suser(td);
180         if (error) {
181                 vput(devvp);
182                 return(error);
183         }
184         VOP_UNLOCK(devvp, 0, td);
185
186         if ((error = udf_mountfs(devvp, mp, td))) {
187                 vrele(devvp);
188                 return(error);
189         }
190
191         imp = VFSTOUDFFS(mp);
192
193         imp->im_flags = args.flags;
194
195         copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
196         bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
197         copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
198         bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
199         udf_statfs(mp, &mp->mnt_stat, td);
200         return(0);
201 }
202
203 /*
204  * Check the descriptor tag for both the correct id and correct checksum.
205  * Return zero if all is good, EINVAL if not.
206  */
207 int
208 udf_checktag(struct desc_tag *tag, uint16_t id)
209 {
210         uint8_t *itag;
211         uint8_t i, cksum = 0;
212
213         itag = (uint8_t *)tag;
214
215         if (tag->id != id)
216                 return(EINVAL);
217
218         for (i = 0; i < 15; i++)
219                 cksum = cksum + itag[i];
220         cksum = cksum - itag[4];
221
222         if (cksum == tag->cksum)
223                 return(0);
224
225         return(EINVAL);
226 }
227
228 static int
229 udf_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td) 
230 {
231         struct buf *bp = NULL;
232         struct anchor_vdp avdp;
233         struct udf_mnt *udfmp = NULL;
234         struct part_desc *pd;
235         struct logvol_desc *lvd;
236         struct fileset_desc *fsd;
237         struct file_entry *root_fentry;
238         dev_t dev;
239         uint32_t sector, size, mvds_start, mvds_end;
240         uint32_t fsd_offset = 0;
241         uint16_t part_num = 0, fsd_part = 0;
242         int error = EINVAL, needclose = 0;
243         int logvol_found = 0, part_found = 0, fsd_found = 0;
244         int bsize;
245
246         /*
247          * Disallow multiple mounts of the same device. Flush the buffer
248          * cache for the device.
249          */
250         if ((error = vfs_mountedon(devvp)))
251                 return(error);
252         if (count_udev(devvp->v_udev) > 0)
253                 return(EBUSY);
254         if ((error = vinvalbuf(devvp, V_SAVE, td, 0, 0)))
255                 return(error);
256
257         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td);
258         error = VOP_OPEN(devvp, FREAD, FSCRED, td);
259         VOP_UNLOCK(devvp, 0, td);
260         if (error)
261                 return(error);
262         needclose = 1;
263         dev = devvp->v_rdev;
264
265         udfmp = malloc(sizeof(*udfmp), M_UDFMOUNT, M_WAITOK | M_ZERO);
266
267         mp->mnt_data = (qaddr_t)udfmp;
268         mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
269         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
270         mp->mnt_maxsymlinklen = 0;
271         mp->mnt_flag |= MNT_LOCAL;
272         udfmp->im_mountp = mp;
273         udfmp->im_dev = dev;
274         udfmp->im_devvp = devvp;
275
276         bsize = 2048;   /* XXX Should probe the media for it's size */
277
278         /* 
279          * Get the Anchor Volume Descriptor Pointer from sector 256.
280          * XXX Should also check sector n - 256, n, and 512.
281          */
282         sector = 256;
283         if ((error = bread(devvp, sector * btodb(bsize), bsize, &bp)) != 0)
284                 goto bail;
285         if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
286                 goto bail;
287
288         bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
289         brelse(bp);
290         bp = NULL;
291
292         /*
293          * Extract the Partition Descriptor and Logical Volume Descriptor
294          * from the Volume Descriptor Sequence.
295          * XXX Should we care about the partition type right now?
296          * XXX What about multiple partitions?
297          */
298         mvds_start = avdp.main_vds_ex.loc;
299         mvds_end = mvds_start + (avdp.main_vds_ex.len - 1) / bsize;
300         for (sector = mvds_start; sector < mvds_end; sector++) {
301                 if ((error = bread(devvp, sector * btodb(bsize), bsize,
302                                    &bp)) != 0) {
303                         printf("Can't read sector %d of VDS\n", sector);
304                         goto bail;
305                 }
306                 lvd = (struct logvol_desc *)bp->b_data;
307                 if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
308                         udfmp->bsize = lvd->lb_size;
309                         udfmp->bmask = udfmp->bsize - 1;
310                         udfmp->bshift = ffs(udfmp->bsize) - 1;
311                         fsd_part = lvd->_lvd_use.fsd_loc.loc.part_num;
312                         fsd_offset = lvd->_lvd_use.fsd_loc.loc.lb_num;
313                         if (udf_find_partmaps(udfmp, lvd))
314                                 break;
315                         logvol_found = 1;
316                 }
317                 pd = (struct part_desc *)bp->b_data;
318                 if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
319                         part_found = 1;
320                         part_num = pd->part_num;
321                         udfmp->part_len = pd->part_len;
322                         udfmp->part_start = pd->start_loc;
323                 }
324
325                 brelse(bp); 
326                 bp = NULL;
327                 if ((part_found) && (logvol_found))
328                         break;
329         }
330
331         if (!part_found || !logvol_found) {
332                 error = EINVAL;
333                 goto bail;
334         }
335
336         if (fsd_part != part_num) {
337                 printf("FSD does not lie within the partition!\n");
338                 error = EINVAL;
339                 goto bail;
340         }
341
342
343         /*
344          * Grab the Fileset Descriptor
345          * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
346          * me in the right direction here.
347          */
348         sector = udfmp->part_start + fsd_offset;
349         if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
350                 printf("Cannot read sector %d of FSD\n", sector);
351                 goto bail;
352         }
353         fsd = (struct fileset_desc *)bp->b_data;
354         if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
355                 fsd_found = 1;
356                 bcopy(&fsd->rootdir_icb, &udfmp->root_icb,
357                       sizeof(struct long_ad));
358         }
359
360         brelse(bp);
361         bp = NULL;
362
363         if (!fsd_found) {
364                 printf("Couldn't find the fsd\n");
365                 error = EINVAL;
366                 goto bail;
367         } 
368
369         vfs_add_vnodeops(&mp->mnt_vn_ops, udf_vnodeop_entries);
370
371         /*
372          * Find the file entry for the root directory.
373          */
374         sector = udfmp->root_icb.loc.lb_num + udfmp->part_start;
375         size = udfmp->root_icb.len;
376         if ((error = udf_readlblks(udfmp, sector, size, &bp)) != 0) {
377                 printf("Cannot read sector %d\n", sector);
378                 goto bail;
379         }
380
381         root_fentry = (struct file_entry *)bp->b_data;
382         if ((error = udf_checktag(&root_fentry->tag, TAGID_FENTRY))) {
383                 printf("Invalid root file entry!\n");
384                 goto bail;
385         }
386
387         brelse(bp);
388         bp = NULL;
389
390         lwkt_token_init(&udfmp->hash_token);
391         udfmp->hashtbl = phashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, &udfmp->hashsz);
392
393         return(0);
394
395 bail:
396         if (udfmp != NULL)
397                 free(udfmp, M_UDFMOUNT);
398         if (bp != NULL)
399                 brelse(bp);
400         if (needclose)
401                 VOP_CLOSE(devvp, FREAD, td);
402         return(error);
403 }
404
405 static int
406 udf_unmount(struct mount *mp, int mntflags, struct thread *td)
407 {
408         struct udf_mnt *udfmp;
409         int error, flags = 0;
410
411         udfmp = VFSTOUDFFS(mp);
412
413         if (mntflags & MNT_FORCE)
414                 flags |= FORCECLOSE;
415
416         if ((error = vflush(mp, 0, flags)))
417                 return (error);
418
419         udfmp->im_devvp->v_rdev->si_mountpoint = NULL;
420         error = VOP_CLOSE(udfmp->im_devvp, FREAD, td);
421         vrele(udfmp->im_devvp);
422
423         if (udfmp->s_table)
424                 free(udfmp->s_table, M_UDFMOUNT);
425         if (udfmp->hashtbl)
426                 free(udfmp->hashtbl, M_UDFMOUNT);
427         free(udfmp, M_UDFMOUNT);
428
429         mp->mnt_data = (qaddr_t)0;
430         mp->mnt_flag &= ~MNT_LOCAL;
431
432         return (error);
433 }
434
435 static int
436 udf_root(struct mount *mp, struct vnode **vpp)
437 {
438         struct udf_mnt *udfmp;
439         struct vnode *vp;
440         ino_t id;
441         int error;
442
443         udfmp = VFSTOUDFFS(mp);
444
445         id = udf_getid(&udfmp->root_icb);
446
447         error = udf_vget(mp, id, vpp);
448         if (error)
449                 return(error);
450
451         vp = *vpp;
452         vp->v_flag |= VROOT;
453         udfmp->root_vp = vp;
454
455         return(0);
456 }
457
458 static int
459 udf_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
460 {
461         struct udf_mnt *udfmp;
462
463         udfmp = VFSTOUDFFS(mp);
464
465         sbp->f_bsize = udfmp->bsize;
466         sbp->f_iosize = udfmp->bsize;
467         sbp->f_blocks = udfmp->part_len;
468         sbp->f_bfree = 0;
469         sbp->f_bavail = 0;
470         sbp->f_files = 0;
471         sbp->f_ffree = 0;
472         if (sbp != &mp->mnt_stat) {
473                 sbp->f_type = mp->mnt_vfc->vfc_typenum;
474                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
475                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
476         }
477
478         return(0);
479 }
480
481 int
482 udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
483 {
484         struct buf *bp;
485         struct vnode *devvp;
486         struct udf_mnt *udfmp;
487         struct thread *td;
488         struct vnode *vp;
489         struct udf_node *unode;
490         struct file_entry *fe;
491         int error, sector, size;
492
493         td = curthread;
494         udfmp = VFSTOUDFFS(mp);
495
496         /* See if we already have this in the cache */
497         if ((error = udf_hashlookup(udfmp, ino, vpp)) != 0)
498                 return(error);
499         if (*vpp != NULL) {
500                 return(0);
501         }
502
503         /*
504          * Allocate memory and check the tag id's before grabbing a new
505          * vnode, since it's hard to roll back if there is a problem.
506          */
507         unode = malloc(sizeof(*unode), M_UDFNODE, M_WAITOK | M_ZERO);
508
509         /*
510          * Copy in the file entry.  Per the spec, the size can only be 1 block.
511          */
512         sector = ino + udfmp->part_start;
513         devvp = udfmp->im_devvp;
514         if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
515                 printf("Cannot read sector %d\n", sector);
516                 free(unode, M_UDFNODE);
517                 return(error);
518         }
519
520         fe = (struct file_entry *)bp->b_data;
521         if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
522                 printf("Invalid file entry!\n");
523                 free(unode, M_UDFNODE);
524                 brelse(bp);
525                 return(ENOMEM);
526         }
527         size = UDF_FENTRY_SIZE + fe->l_ea + fe->l_ad;
528         unode->fentry = malloc(size, M_UDFFENTRY, M_WAITOK | M_ZERO);
529
530         bcopy(bp->b_data, unode->fentry, size);
531         
532         brelse(bp);
533         bp = NULL;
534
535         if ((error = udf_allocv(mp, &vp))) {
536                 printf("Error from udf_allocv\n");
537                 free(unode, M_UDFNODE);
538                 return(error);
539         }
540
541         unode->i_vnode = vp;
542         unode->hash_id = ino;
543         unode->i_devvp = udfmp->im_devvp;
544         unode->i_dev = udfmp->im_dev;
545         unode->udfmp = udfmp;
546         vp->v_data = unode;
547         vref(udfmp->im_devvp);
548         udf_hashins(unode);
549
550         switch (unode->fentry->icbtag.file_type) {
551         default:
552                 vp->v_type = VBAD;
553                 break;
554         case 4:
555                 vp->v_type = VDIR;
556                 break;
557         case 5:
558                 vp->v_type = VREG;
559                 break;
560         case 6:
561                 vp->v_type = VBLK;
562                 break;
563         case 7:
564                 vp->v_type = VCHR;
565                 break;
566         case 9:
567                 vp->v_type = VFIFO;
568                 break;
569         case 10:
570                 vp->v_type = VSOCK;
571                 break;
572         case 12:
573                 vp->v_type = VLNK;
574                 break;
575         }
576         /*
577          * Locked and refd vnode returned
578          */
579         *vpp = vp;
580
581         return(0);
582 }
583
584 struct ifid {
585         u_short ifid_len;
586         u_short ifid_pad;
587         int     ifid_ino;
588         long    ifid_start;
589 };
590
591 static int
592 udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
593 {
594         struct ifid *ifhp;
595         struct vnode *nvp;
596         int error;
597
598         ifhp = (struct ifid *)fhp;
599
600         if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
601                 *vpp = NULLVP;
602                 return(error);
603         }
604
605         *vpp = nvp;
606         return(0);
607 }
608
609 static int
610 udf_vptofh (struct vnode *vp, struct fid *fhp)
611 {
612         struct udf_node *node;
613         struct ifid *ifhp;
614
615         node = VTON(vp);
616         ifhp = (struct ifid *)fhp;
617         ifhp->ifid_len = sizeof(struct ifid);
618         ifhp->ifid_ino = node->hash_id;
619
620         return(0);
621 }
622
623 static int
624 udf_find_partmaps(struct udf_mnt *udfmp, struct logvol_desc *lvd)
625 {
626         union udf_pmap *pmap;
627         struct part_map_spare *pms;
628         struct regid *pmap_id;
629         struct buf *bp;
630         unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
631         int ptype, psize, error;
632         unsigned int i;
633
634         for (i = 0; i < lvd->n_pm; i++) {
635                 pmap = (union udf_pmap *)&lvd->maps[i * UDF_PMAP_SIZE];
636                 ptype = pmap->data[0];
637                 psize = pmap->data[1];
638                 if (((ptype != 1) && (ptype != 2)) ||
639                     ((psize != UDF_PMAP_SIZE) && (psize != 6))) {
640                         printf("Invalid partition map found\n");
641                         return(1);
642                 }
643
644                 if (ptype == 1) {
645                         /* Type 1 map.  We don't care */
646                         continue;
647                 }
648
649                 /* Type 2 map.  Gotta find out the details */
650                 pmap_id = (struct regid *)&pmap->data[4];
651                 bzero(&regid_id[0], UDF_REGID_ID_SIZE);
652                 bcopy(&pmap_id->id[0], &regid_id[0], UDF_REGID_ID_SIZE);
653
654                 if (bcmp(&regid_id[0], "*UDF Sparable Partition",
655                     UDF_REGID_ID_SIZE)) {
656                         printf("Unsupported partition map: %s\n", &regid_id[0]);
657                         return(1);
658                 }
659
660                 pms = &pmap->pms;
661                 udfmp->s_table = malloc(pms->st_size, M_UDFMOUNT,
662                                         M_WAITOK | M_ZERO);
663                 if (udfmp->s_table == NULL)
664                         return(ENOMEM);
665
666                 /* Calculate the number of sectors per packet. */
667                 /* XXX Logical or physical? */
668                 udfmp->p_sectors = pms->packet_len / udfmp->bsize;
669
670                 /*
671                  * XXX If reading the first Sparing Table fails, should look
672                  * for another table.
673                  */
674                 if ((error = udf_readlblks(udfmp, pms->st_loc[0], pms->st_size,
675                     &bp)) != 0) {
676                         if (bp)
677                                 brelse(bp);
678                         printf("Failed to read Sparing Table at sector %d\n",
679                             pms->st_loc[0]);
680                         return(error);
681                 }
682                 bcopy(bp->b_data, udfmp->s_table, pms->st_size);
683                 brelse(bp);
684
685                 if (udf_checktag(&udfmp->s_table->tag, 0)) {
686                         printf("Invalid sparing table found\n");
687                         return(EINVAL);
688                 }
689
690                 /* See how many valid entries there are here.  The list is
691                  * supposed to be sorted. 0xfffffff0 and higher are not valid
692                  */
693                 for (i = 0; i < udfmp->s_table->rt_l; i++) {
694                         udfmp->s_table_entries = i;
695                         if (udfmp->s_table->entries[i].org >= 0xfffffff0)
696                                 break;
697                 }
698         }
699
700         return(0);
701 }