summaryrefslogtreecommitdiff
path: root/sys/isofs
diff options
context:
space:
mode:
authorPedro Martelletto <pedro@cvs.openbsd.org>2006-07-05 17:57:51 +0000
committerPedro Martelletto <pedro@cvs.openbsd.org>2006-07-05 17:57:51 +0000
commite8d61eff01a7c10b1ed93d666610ee8624b18b3f (patch)
treead19737e67262f1c0033324dd93fb86b87dfce24 /sys/isofs
parent1a0e57227fae21b3378b06ad28ba1bb8f91ad365 (diff)
Add VAT support a la UDF 1.50
Diffstat (limited to 'sys/isofs')
-rw-r--r--sys/isofs/udf/udf.h14
-rw-r--r--sys/isofs/udf/udf_extern.h8
-rw-r--r--sys/isofs/udf/udf_subr.c85
-rw-r--r--sys/isofs/udf/udf_vfsops.c34
-rw-r--r--sys/isofs/udf/udf_vnops.c4
5 files changed, 128 insertions, 17 deletions
diff --git a/sys/isofs/udf/udf.h b/sys/isofs/udf/udf.h
index 3d42b186868..63e61d4fd1f 100644
--- a/sys/isofs/udf/udf.h
+++ b/sys/isofs/udf/udf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf.h,v 1.4 2006/06/24 21:47:50 pedro Exp $ */
+/* $OpenBSD: udf.h,v 1.5 2006/07/05 17:57:50 pedro Exp $ */
/*
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
@@ -42,10 +42,16 @@ struct udf_node {
struct lock i_lock;
dev_t i_dev;
ino_t hash_id;
- long diroff;
+ union {
+ long diroff;
+ long vatlen;
+ } un_u;
struct file_entry *fentry;
};
+#define diroff un_u.diroff
+#define vatlen un_u.vatlen
+
struct udf_mnt {
int im_flags;
struct mount *im_mountp;
@@ -56,6 +62,7 @@ struct udf_mnt {
int bmask;
uint32_t part_start;
uint32_t part_len;
+ struct vnode *im_vat;
struct vnode *root_vp;
struct long_ad root_icb;
LIST_HEAD(udf_hash_lh, udf_node) *hashtbl;
@@ -66,6 +73,9 @@ struct udf_mnt {
struct udf_sparing_table *s_table;
};
+#define UDF_MNT_FIND_VAT 0x01 /* Indicates a VAT must be found */
+#define UDF_MNT_USES_VAT 0x02 /* Indicates a VAT must be used */
+
struct udf_dirstream {
struct udf_node *node;
struct udf_mnt *udfmp;
diff --git a/sys/isofs/udf/udf_extern.h b/sys/isofs/udf/udf_extern.h
index 6d314c533e7..72db7d4615a 100644
--- a/sys/isofs/udf/udf_extern.h
+++ b/sys/isofs/udf/udf_extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf_extern.h,v 1.3 2006/01/14 19:04:17 miod Exp $ */
+/* $OpenBSD: udf_extern.h,v 1.4 2006/07/05 17:57:50 pedro Exp $ */
/*
* Written by Pedro Martelletto <pedro@openbsd.org> in February 2005.
@@ -9,13 +9,15 @@
* udf_subr.c
*/
int udf_rawnametounicode(u_int len, char *, unicode_t *);
+int udf_vat_get(struct udf_mnt *);
+int udf_vat_map(struct udf_mnt *, uint32_t *);
/*
* udf_vfsops.c
*/
int udf_init(struct vfsconf *);
int udf_mount(struct mount *, const char *, void *, struct nameidata *,
- struct proc *);
+ struct proc *);
int udf_unmount(struct mount *, int, struct proc *);
int udf_start(struct mount *, int, struct proc *);
int udf_root(struct mount *, struct vnode **);
@@ -49,6 +51,8 @@ int udf_unlock(void *v);
int udf_islocked(void *v);
int udf_print(void *v);
int udf_transname(char *, char *, int, struct udf_mnt *);
+int udf_readatoffset(struct udf_node *, int *, off_t, struct buf **,
+ uint8_t **);
/*
* Memory pools.
diff --git a/sys/isofs/udf/udf_subr.c b/sys/isofs/udf/udf_subr.c
index 2d05cf7b6ee..6d27148ed1e 100644
--- a/sys/isofs/udf/udf_subr.c
+++ b/sys/isofs/udf/udf_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf_subr.c,v 1.4 2006/01/15 00:04:42 pedro Exp $ */
+/* $OpenBSD: udf_subr.c,v 1.5 2006/07/05 17:57:50 pedro Exp $ */
/*
* Copyright (c) 2006, Miodrag Vallat
@@ -42,6 +42,8 @@
#include <isofs/udf/udf.h>
#include <isofs/udf/udf_extern.h>
+int udf_vat_read(struct udf_mnt *, uint32_t *);
+
/*
* Convert a CS0 dstring to a 16-bit Unicode string.
* Returns the length of the Unicode string, in unicode characters (not
@@ -178,3 +180,84 @@ out:
return (error);
}
+
+/* Get a vnode for the Virtual Allocation Table (VAT) */
+int
+udf_vat_get(struct udf_mnt *ump)
+{
+ struct vnode *vp;
+ struct udf_node *unp;
+ int error;
+
+ error = udf_vget(ump->im_mountp, ump->part_len - 3, &vp);
+ if (error)
+ return (error);
+
+ unp = VTON(vp);
+ unp->vatlen = (letoh64(unp->fentry->inf_len) - 36) >> 2;
+
+ ump->im_vat = vp;
+ ump->im_flags &= ~UDF_MNT_FIND_VAT;
+ ump->im_flags |= UDF_MNT_USES_VAT;
+
+ vput(vp);
+
+ return (0);
+}
+
+/* Look up a sector in the VAT */
+int
+udf_vat_map(struct udf_mnt *ump, uint32_t *sector)
+{
+ /* If there's no VAT, then it's easy */
+ if (!(ump->im_flags & UDF_MNT_USES_VAT)) {
+ *sector += ump->part_start;
+ return (0);
+ }
+
+ /* Sanity check the given sector */
+ if (*sector >= VTON(ump->im_vat)->vatlen)
+ return (EINVAL);
+
+ return (udf_vat_read(ump, sector));
+}
+
+/* Read from the VAT */
+int
+udf_vat_read(struct udf_mnt *ump, uint32_t *sector)
+{
+ struct udf_node *unp;
+ struct buf *bp;
+ uint8_t *data;
+ int error, size;
+
+ unp = VTON(ump->im_vat);
+ size = 4;
+
+ /*
+ * Note that we rely on the buffer cache to keep frequently accessed
+ * buffers around to avoid reading them from the disk all the time.
+ */
+ error = udf_readatoffset(unp, &size, *sector << 2, &bp, &data);
+ if (error) {
+ if (bp != NULL)
+ brelse(bp);
+
+ return (error);
+ }
+
+ /* Make sure we read at least a whole entry */
+ if (size < 4) {
+ if (bp != NULL)
+ brelse(bp);
+
+ return (EINVAL);
+ }
+
+ /* Map the sector */
+ *sector = letoh32(*(uint32_t *)data) + ump->part_start;
+
+ brelse(bp);
+
+ return (0);
+}
diff --git a/sys/isofs/udf/udf_vfsops.c b/sys/isofs/udf/udf_vfsops.c
index edb8f8617c3..e2e49f562ea 100644
--- a/sys/isofs/udf/udf_vfsops.c
+++ b/sys/isofs/udf/udf_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf_vfsops.c,v 1.13 2006/07/01 00:08:57 pedro Exp $ */
+/* $OpenBSD: udf_vfsops.c,v 1.14 2006/07/05 17:57:50 pedro Exp $ */
/*
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
@@ -328,13 +328,24 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
goto bail;
}
+ mtx_init(&udfmp->hash_mtx, IPL_NONE);
+ udfmp->hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
+ &udfmp->hashsz);
+
+ /* Get the VAT, if needed */
+ if (udfmp->im_flags & UDF_MNT_FIND_VAT) {
+ error = udf_vat_get(udfmp);
+ if (error)
+ goto bail;
+ }
/*
* Grab the Fileset Descriptor
* Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
* me in the right direction here.
*/
- sector = udfmp->part_start + fsd_offset;
+ sector = fsd_offset;
+ udf_vat_map(udfmp, &sector);
if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
printf("Cannot read sector %d of FSD\n", sector);
goto bail;
@@ -358,8 +369,9 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
/*
* Find the file entry for the root directory.
*/
- sector = letoh32(udfmp->root_icb.loc.lb_num) + udfmp->part_start;
+ sector = letoh32(udfmp->root_icb.loc.lb_num);
size = letoh32(udfmp->root_icb.len);
+ udf_vat_map(udfmp, &sector);
if ((error = udf_readlblks(udfmp, sector, size, &bp)) != 0) {
printf("Cannot read sector %d\n", sector);
goto bail;
@@ -374,15 +386,14 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
brelse(bp);
bp = NULL;
- mtx_init(&udfmp->hash_mtx, IPL_NONE);
- udfmp->hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
- &udfmp->hashsz);
-
devvp->v_specmountpoint = mp;
return (0);
bail:
+ if (udfmp->hashtbl != NULL)
+ free(udfmp->hashtbl, M_UDFMOUNT);
+
if (udfmp != NULL) {
FREE(udfmp, M_UDFMOUNT);
mp->mnt_data = NULL;
@@ -522,8 +533,9 @@ udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
/*
* Copy in the file entry. Per the spec, the size can only be 1 block.
*/
- sector = ino + udfmp->part_start;
+ sector = ino;
devvp = udfmp->im_devvp;
+ udf_vat_map(udfmp, &sector);
if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
printf("Cannot read sector %d\n", sector);
pool_put(&udf_node_pool, unode);
@@ -600,6 +612,9 @@ udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
case UDF_ICB_TYPE_SYMLINK:
vp->v_type = VLNK;
break;
+ case UDF_ICB_TYPE_VAT_150:
+ vp->v_type = VREG;
+ break;
}
*vpp = vp;
@@ -665,7 +680,8 @@ udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
int
udf_get_vpartmap(struct udf_mnt *udfmp, struct part_map_virt *pmv)
{
- return (EOPNOTSUPP); /* Not supported yet */
+ udfmp->im_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */
+ return (0);
}
/* Handle a sparable partition map */
diff --git a/sys/isofs/udf/udf_vnops.c b/sys/isofs/udf/udf_vnops.c
index c6b5d59164c..e0243e2ddda 100644
--- a/sys/isofs/udf/udf_vnops.c
+++ b/sys/isofs/udf/udf_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udf_vnops.c,v 1.14 2006/07/01 00:08:57 pedro Exp $ */
+/* $OpenBSD: udf_vnops.c,v 1.15 2006/07/05 17:57:50 pedro Exp $ */
/*
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
@@ -55,8 +55,6 @@
#include <isofs/udf/udf.h>
#include <isofs/udf/udf_extern.h>
-int udf_readatoffset(struct udf_node *, int *, off_t, struct buf **,
- uint8_t **);
int udf_bmap_internal(struct udf_node *, off_t, daddr_t *, uint32_t *);
int (**udf_vnodeop_p)(void *);