Import writing part of the UDF file system making optical media like CD's
and DVD's behave like floppy discs. Writing is supported upto and including version 2.01; version 2.50 and 2.60 will follow. Also extending the UDF implementation to support symbolic links and hardlinks. Added are the mmcformat(8) tool to format rewritable CD/DVD discs and newfs_udf(8). Limitations: all operations can be performed on the file system though the sheduling is currently optimised for archiving workloads. mv(1)/rename(2) is currently only implemented for non-directories.
This commit is contained in:
parent
20275ee931
commit
e979c658c9
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.746 2008/05/11 18:01:46 joerg Exp $
|
||||
# $NetBSD: mi,v 1.747 2008/05/14 16:49:47 reinoud Exp $
|
||||
#
|
||||
# Note: Don't delete entries from here - mark them as "obsolete" instead,
|
||||
# unless otherwise stated below.
|
||||
@ -216,6 +216,7 @@
|
||||
./sbin/newfs_lfs base-sysutil-root
|
||||
./sbin/newfs_msdos base-sysutil-root
|
||||
./sbin/newfs_sysvbfs base-sysutil-root
|
||||
./sbin/newfs_udf base-sysutil-root
|
||||
./sbin/newlfs base-obsolete obsolete
|
||||
./sbin/nfsd base-obsolete obsolete
|
||||
./sbin/nfsiod base-obsolete obsolete
|
||||
@ -1170,6 +1171,7 @@
|
||||
./usr/sbin/mknetid base-nis-bin yp
|
||||
./usr/sbin/mld6query base-netutil-bin use_inet6
|
||||
./usr/sbin/mlxctl base-sysutil-bin
|
||||
./usr/sbin/mmcformat base-sysutil-bin
|
||||
./usr/sbin/mopa.out base-obsolete obsolete
|
||||
./usr/sbin/mopchk base-bootserver-bin
|
||||
./usr/sbin/mopcopy base-bootserver-bin
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.1069 2008/05/11 18:01:46 joerg Exp $
|
||||
# $NetBSD: mi,v 1.1070 2008/05/14 16:49:47 reinoud Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
#
|
||||
@ -2173,6 +2173,7 @@
|
||||
./usr/share/man/cat8/mknod.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/mld6query.0 man-netutil-catman use_inet6,.cat
|
||||
./usr/share/man/cat8/mlxctl.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/mmcformat.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/mmeye/MAKEDEV.0 man-obsolete obsolete
|
||||
./usr/share/man/cat8/mmeye/makedev.0 man-obsolete obsolete
|
||||
./usr/share/man/cat8/modload.0 man-sysutil-catman .cat
|
||||
@ -2246,6 +2247,7 @@
|
||||
./usr/share/man/cat8/newfs_lfs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newfs_msdos.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newfs_sysvbfs.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newfs_udf.0 man-sysutil-catman .cat
|
||||
./usr/share/man/cat8/newlfs.0 man-obsolete obsolete
|
||||
./usr/share/man/cat8/news68k/MAKEDEV.0 man-obsolete obsolete
|
||||
./usr/share/man/cat8/news68k/makedev.0 man-obsolete obsolete
|
||||
@ -4723,6 +4725,7 @@
|
||||
./usr/share/man/man8/mknod.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/mld6query.8 man-netutil-man use_inet6,.man
|
||||
./usr/share/man/man8/mlxctl.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/mmcformat.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/mmeye/MAKEDEV.8 man-obsolete obsolete
|
||||
./usr/share/man/man8/mmeye/makedev.8 man-obsolete obsolete
|
||||
./usr/share/man/man8/modload.8 man-sysutil-man .man
|
||||
@ -4796,6 +4799,7 @@
|
||||
./usr/share/man/man8/newfs_lfs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newfs_msdos.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newfs_sysvbfs.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newfs_udf.8 man-sysutil-man .man
|
||||
./usr/share/man/man8/newlfs.8 man-obsolete obsolete
|
||||
./usr/share/man/man8/news68k/MAKEDEV.8 man-obsolete obsolete
|
||||
./usr/share/man/man8/news68k/makedev.8 man-obsolete obsolete
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.109 2008/02/09 19:32:28 jmmv Exp $
|
||||
# $NetBSD: Makefile,v 1.110 2008/05/14 16:49:47 reinoud Exp $
|
||||
# @(#)Makefile 8.5 (Berkeley) 3/31/94
|
||||
|
||||
# Not ported: XNSrouted enpload scsiformat startslip
|
||||
@ -24,6 +24,7 @@ SUBDIR+= newfs fsck_ffs fsdb dump restore clri tunefs
|
||||
SUBDIR+= newfs_lfs fsck_lfs dump_lfs resize_lfs
|
||||
SUBDIR+= newfs_msdos fsck_msdos
|
||||
SUBDIR+= newfs_sysvbfs
|
||||
SUBDIR+= newfs_udf
|
||||
SUBDIR+= mount_ados
|
||||
SUBDIR+= mount_cd9660
|
||||
SUBDIR+= mount_efs
|
||||
|
18
sbin/newfs_udf/Makefile
Normal file
18
sbin/newfs_udf/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
# $NetBSD: Makefile,v 1.1 2008/05/14 16:49:48 reinoud Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
WARNS= 4
|
||||
PROG= newfs_udf
|
||||
MAN= newfs_udf.8
|
||||
SRCS= newfs_udf.c udf_create.o udf_osta.o fattr.c
|
||||
|
||||
MOUNT= ${NETBSDSRCDIR}/sbin/mount
|
||||
KUDF= ${NETBSDSRCDIR}/sys/fs/udf
|
||||
CPPFLAGS+= -I${MOUNT} -I${KUDF} -I${NETBSDSRCDIR}/sys
|
||||
.PATH: ${MOUNT} ${KUDF}
|
||||
|
||||
DPADD+=${LIBUTIL}
|
||||
LDADD+=-lutil
|
||||
|
||||
.include <bsd.prog.mk>
|
144
sbin/newfs_udf/newfs_udf.8
Normal file
144
sbin/newfs_udf/newfs_udf.8
Normal file
@ -0,0 +1,144 @@
|
||||
.\" $NetBSD: newfs_udf.8,v 1.1 2008/05/14 16:49:48 reinoud Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2008 Reinoud Zandijk
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in
|
||||
.\" the documentation and/or other materials provided with the
|
||||
.\" distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
|
||||
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
|
||||
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.Dd May 9, 2008
|
||||
.Dt NEWFS_UDF 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm newfs_udf
|
||||
.Nd construct a new UDF file system
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl c
|
||||
.Op Fl F
|
||||
.Op Fl L Ar loglabel
|
||||
.Op Fl M
|
||||
.Op Fl v Ar min_udf
|
||||
.Op Fl V Ar max_udf
|
||||
.Op Fl P Ar discid
|
||||
.Op Fl s Ar size
|
||||
.Op Fl S Ar setlabel
|
||||
.Op Fl t Ar gmtoff
|
||||
.Ar special
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility creates an UDF file system on device
|
||||
.Ar special
|
||||
suitable for the media currently inserted.
|
||||
.Pp
|
||||
The options are as follow:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c
|
||||
Perform a crude surface check first to weed out disc faults on rewritable
|
||||
media.
|
||||
.It Fl F
|
||||
Force file system construction on non-empty recordable media.
|
||||
.It Fl L Ar loglabel
|
||||
Set the disc logical label to the specified
|
||||
.Ar loglabel .
|
||||
.It Fl M
|
||||
Disable metadata partition flavour selection.
|
||||
.It Fl v Ar min_udf
|
||||
Select
|
||||
.Ar min_udf
|
||||
as the minimum UDF version to be supported. Notation "0x201" for UDF version
|
||||
2.01.
|
||||
.It Fl V Ar max_udf
|
||||
Select
|
||||
.Ar max_udf
|
||||
as the maximum UDF version to be supported. Notation "0x250" for UDF version
|
||||
2.50.
|
||||
.It Fl P Ar discid
|
||||
Set the phyisical disc label to the specified
|
||||
.Ar discid .
|
||||
For strict conformance and interchange dont set this manually.
|
||||
.It Fl s Ar size
|
||||
Ignored for now.
|
||||
.It Fl S Ar setlabel
|
||||
Set the disc set label to the specified
|
||||
.Ar setlabel .
|
||||
For strict conformance and interchange dont set this manually.
|
||||
.It Fl t Ar gmtoff
|
||||
Use the specified
|
||||
.Ar gmtoff
|
||||
as gmt time offset for recording times on the disc.
|
||||
.El
|
||||
.Sh NOTES
|
||||
The UDF file system is defined for the entire optical medium. It can only
|
||||
function on the entire CD/DVD/BD so the raw partition has to be specified for
|
||||
read/write actions. For
|
||||
.Nm
|
||||
this means specifying the raw device with the raw partition. i.e.
|
||||
.Pa /dev/rcd0d
|
||||
or
|
||||
.Pa /dev/rcd0c.
|
||||
.Pp
|
||||
Some rewritable optical media needs to be formatted first before it can be
|
||||
used by UDF. This can be done using
|
||||
.Xr mmcformat 8 .
|
||||
.Pp
|
||||
The default UDF version is version 2.01 that can be specified if required
|
||||
as "0x201".
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal -offset indent
|
||||
newfs_udf -S "Encyclopedia" -L "volume 2" -P "copy-nr-1" /dev/rcd0d
|
||||
.Ed
|
||||
.Pp
|
||||
Create a file system, using the specified names on the device
|
||||
.Pa /dev/rcd0d
|
||||
with the default UDF version.
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
dd if=/dev/zero of=bigdisk.2048.udf seek=9999999 count=1
|
||||
vnconfig -c vnd0 bigdisk.2048.udf 2048/1/1/1
|
||||
newfs_udf -L bigdisk /dev/rvnd0d
|
||||
.Ed
|
||||
.Pp
|
||||
Create a 4.8 Gb sparse file and configure it using
|
||||
.Xr vnconfig 8
|
||||
to be a 2048 sector size disc and create a new UDF file system on
|
||||
.Pa /dev/rvnd0d .
|
||||
.Bd -literal -offset indent
|
||||
newfs_udf -L "My USB stick" /dev/rsd0d
|
||||
.Ed
|
||||
.Pp
|
||||
Create a new UDF file system on the inserted USB stick using its `native'
|
||||
sectorsize of 512.
|
||||
.Sh SEE ALSO
|
||||
.Xr disktab 5 ,
|
||||
.Xr disklabel 8 ,
|
||||
.Xr mmcformat 8 ,
|
||||
.Xr newfs 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.Nx 5.0 .
|
||||
.Sh AUTHORS
|
||||
.An Reinoud Zandijk Aq reinoud@NetBSD.org .
|
1456
sbin/newfs_udf/newfs_udf.c
Normal file
1456
sbin/newfs_udf/newfs_udf.c
Normal file
File diff suppressed because it is too large
Load Diff
1513
sbin/newfs_udf/udf_create.c
Normal file
1513
sbin/newfs_udf/udf_create.c
Normal file
File diff suppressed because it is too large
Load Diff
234
sbin/newfs_udf/udf_create.h
Normal file
234
sbin/newfs_udf/udf_create.h
Normal file
@ -0,0 +1,234 @@
|
||||
/* $NetBSD: udf_create.h,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _FS_UDF_UDF_CREATE_H_
|
||||
#define _FS_UDF_UDF_CREATE_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fs/udf/ecma167-udf.h>
|
||||
#include "udf_bswap.h"
|
||||
#include "udf_osta.h"
|
||||
|
||||
|
||||
/* format flags indicating properties of disc to create */
|
||||
#define FORMAT_WRITEONCE 0x00001
|
||||
#define FORMAT_SEQUENTIAL 0x00002
|
||||
#define FORMAT_REWRITABLE 0x00004
|
||||
#define FORMAT_SPARABLE 0x00008
|
||||
#define FORMAT_META 0x00010
|
||||
#define FORMAT_LOW 0x00020
|
||||
#define FORMAT_VAT 0x00040
|
||||
#define FORMAT_WORM 0x00080
|
||||
#define FORMAT_TRACK512 0x00100
|
||||
#define FORMAT_INVALID 0x00200
|
||||
#define FORMAT_FLAGBITS \
|
||||
"\10\1WRITEONCE\2SEQUENTIAL\3REWRITABLE\4SPARABLE\5META\6LOW" \
|
||||
"\7VAT\10WORM\11TRACK512\12INVALID"
|
||||
|
||||
|
||||
/* structure space */
|
||||
#define UDF_ANCHORS 4 /* 256, 512, N-256, N */
|
||||
#define UDF_PARTITIONS 4 /* overkill */
|
||||
#define UDF_PMAPS 4 /* overkill */
|
||||
|
||||
/* misc constants */
|
||||
#define UDF_MAX_NAMELEN 255 /* as per SPEC */
|
||||
|
||||
/* translation constants */
|
||||
#define UDF_VTOP_RAWPART UDF_PMAPS /* [0..UDF_PMAPS> are normal */
|
||||
|
||||
/* virtual to physical mapping types */
|
||||
#define UDF_VTOP_TYPE_RAW 0
|
||||
#define UDF_VTOP_TYPE_UNKNOWN 0
|
||||
#define UDF_VTOP_TYPE_PHYS 1
|
||||
#define UDF_VTOP_TYPE_VIRT 2
|
||||
#define UDF_VTOP_TYPE_SPARABLE 3
|
||||
#define UDF_VTOP_TYPE_META 4
|
||||
|
||||
#define UDF_TRANS_ZERO ((uint64_t) -1)
|
||||
#define UDF_TRANS_UNMAPPED ((uint64_t) -2)
|
||||
#define UDF_TRANS_INTERN ((uint64_t) -3)
|
||||
#define UDF_MAX_SECTOR ((uint64_t) -10) /* high water mark */
|
||||
|
||||
/* handys */
|
||||
#define UDF_ROUNDUP(val, gran) \
|
||||
((gran) * (((val) + (gran)-1) / (gran)))
|
||||
|
||||
#define UDF_ROUNDDOWN(val, gran) \
|
||||
((gran) * (((val)) / (gran)))
|
||||
|
||||
|
||||
/* disc offsets for various structures and their sizes */
|
||||
struct udf_disclayout {
|
||||
uint32_t wrtrack_skew;
|
||||
|
||||
uint32_t iso9660_vrs;
|
||||
uint32_t anchors[UDF_ANCHORS];
|
||||
uint32_t vds_size, vds1, vds2;
|
||||
uint32_t lvis_size, lvis;
|
||||
|
||||
uint32_t first_lba, last_lba;
|
||||
uint32_t sector_size;
|
||||
uint32_t blockingnr, align_blockingnr, sparable_blockingnr;
|
||||
|
||||
uint32_t bitmap_dscr_size;
|
||||
uint32_t unalloc_space, freed_space;
|
||||
|
||||
uint32_t sparable_blocks;
|
||||
uint32_t sparable_area, sparable_area_size;
|
||||
uint32_t sparing_table_dscr_lbas;
|
||||
uint32_t spt_1, spt_2;
|
||||
|
||||
uint32_t fsd, rootdir, vat;
|
||||
|
||||
/* partition */
|
||||
uint32_t part_start_lba, part_size_lbas;
|
||||
};
|
||||
|
||||
|
||||
/* all info about discs and descriptors building */
|
||||
struct udf_create_context {
|
||||
/* descriptors */
|
||||
int dscrver; /* 2 or 3 */
|
||||
int min_udf; /* hex */
|
||||
int max_udf; /* hex */
|
||||
int serialnum; /* format serialno */
|
||||
|
||||
int gmtoff; /* in minutes */
|
||||
|
||||
/* XXX to layout? */
|
||||
int sector_size;
|
||||
|
||||
/* identification */
|
||||
char *logvol_name;
|
||||
char *primary_name;
|
||||
char *volset_name;
|
||||
char *fileset_name;
|
||||
|
||||
char const *app_name;
|
||||
char const *impl_name;
|
||||
int app_version_main;
|
||||
int app_version_sub;
|
||||
|
||||
/* building */
|
||||
int vds_seq; /* for building functions */
|
||||
int unique_id; /* only first few are used */
|
||||
|
||||
/* constructed structures */
|
||||
struct anchor_vdp *anchors[UDF_ANCHORS]; /* anchors to VDS */
|
||||
struct pri_vol_desc *primary_vol; /* identification */
|
||||
struct logvol_desc *logical_vol; /* main mapping v->p */
|
||||
struct unalloc_sp_desc *unallocated; /* free UDF space */
|
||||
struct impvol_desc *implementation; /* likely reduntant */
|
||||
struct logvol_int_desc *logvol_integrity; /* current integrity */
|
||||
struct part_desc *partitions[UDF_PARTITIONS]; /* partitions */
|
||||
|
||||
/* XXX to layout? */
|
||||
int data_part;
|
||||
int metadata_part;
|
||||
|
||||
/* derived; points *into* other structures */
|
||||
struct udf_logvol_info *logvol_info; /* inside integrity */
|
||||
|
||||
/* fileset and root directories */
|
||||
struct fileset_desc *fileset_desc; /* normally one */
|
||||
|
||||
/* logical to physical translations */
|
||||
int vtop[UDF_PMAPS+1]; /* vpartnr trans */
|
||||
int vtop_tp[UDF_PMAPS+1]; /* type of trans */
|
||||
|
||||
/* sparable */
|
||||
struct udf_sparing_table*sparing_table; /* replacements */
|
||||
|
||||
/* lvint */
|
||||
int num_files;
|
||||
int num_directories;
|
||||
uint32_t part_size[UDF_PARTITIONS];
|
||||
uint32_t part_free[UDF_PARTITIONS];
|
||||
|
||||
struct space_bitmap_desc*part_unalloc_bits[UDF_PARTITIONS];
|
||||
struct space_bitmap_desc*part_freed_bits [UDF_PARTITIONS];
|
||||
};
|
||||
|
||||
|
||||
/* globals */
|
||||
|
||||
extern struct udf_create_context context;
|
||||
extern struct udf_disclayout layout;
|
||||
|
||||
/* prototypes */
|
||||
void udf_init_create_context(void);
|
||||
int udf_calculate_disc_layout(int format_flags, int min_udf,
|
||||
uint32_t wrtrack_skew,
|
||||
uint32_t first_lba, uint32_t last_lba,
|
||||
uint32_t sector_size, uint32_t blockingnr,
|
||||
uint32_t sparable_blocks);
|
||||
|
||||
void udf_osta_charset(struct charspec *charspec);
|
||||
void udf_encode_osta_id(char *osta_id, uint16_t len, char *text);
|
||||
|
||||
void udf_set_regid(struct regid *regid, char const *name);
|
||||
void udf_add_domain_regid(struct regid *regid);
|
||||
void udf_add_udf_regid(struct regid *regid);
|
||||
void udf_add_impl_regid(struct regid *regid);
|
||||
void udf_add_app_regid(struct regid *regid);
|
||||
|
||||
int udf_validate_tag_sum(union dscrptr *dscr);
|
||||
int udf_validate_tag_and_crc_sums(union dscrptr *dscr);
|
||||
|
||||
void udf_set_timestamp_now(struct timestamp *timestamp);
|
||||
|
||||
|
||||
void udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc);
|
||||
int udf_create_anchor(int num);
|
||||
|
||||
void udf_create_terminator(union dscrptr *dscr, uint32_t loc);
|
||||
int udf_create_primaryd(void);
|
||||
int udf_create_partitiond(int part_num, int part_accesstype);
|
||||
int udf_create_unalloc_spaced(void);
|
||||
int udf_create_sparing_tabled(void);
|
||||
int udf_create_space_bitmap(struct space_bitmap_desc **sbdp);
|
||||
int udf_create_logical_dscr(int format_flags);
|
||||
int udf_create_impvold(char *field1, char *field2, char *field3);
|
||||
int udf_create_fsd(void);
|
||||
int udf_create_lvintd(int type);
|
||||
void udf_update_lvintd(int type);
|
||||
|
||||
int udf_register_bad_block(uint32_t location);
|
||||
void udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks);
|
||||
|
||||
int udf_create_new_fe(struct file_entry **fep, int file_type,
|
||||
struct long_ad *parent_icb);
|
||||
int udf_create_new_efe(struct extfile_entry **efep, int file_type,
|
||||
struct long_ad *parent_icb);
|
||||
|
||||
int udf_create_new_rootdir(union dscrptr **dscr);
|
||||
int udf_create_new_VAT(union dscrptr **vat_dscr);
|
||||
|
||||
#endif /* _FS_UDF_UDF_CREATE_H_ */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: ecma167-udf.h,v 1.7 2007/12/25 18:33:44 perry Exp $ */
|
||||
/* $NetBSD: ecma167-udf.h,v 1.8 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006 Reinoud Zandijk <reinoud@netbsd.org>
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2008 Reinoud Zandijk
|
||||
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -101,7 +101,7 @@ enum {
|
||||
TAGID_FSD = 256,
|
||||
TAGID_FID = 257,
|
||||
TAGID_ALLOCEXTENT = 258,
|
||||
TAGID_INDIRECT_ENTRY = 259,
|
||||
TAGID_INDIRECTENTRY = 259,
|
||||
TAGID_ICB_TERM = 260,
|
||||
TAGID_FENTRY = 261,
|
||||
TAGID_EXTATTR_HDR = 262,
|
||||
@ -209,6 +209,7 @@ union icb {
|
||||
#define UDF_EXT_REDIRECT (3<<30)
|
||||
#define UDF_EXT_FLAGS(len) ((len) & (3<<30))
|
||||
#define UDF_EXT_LEN(len) ((len) & ((1<<30)-1))
|
||||
#define UDF_EXT_MAXLEN ((1<<30)-1)
|
||||
|
||||
|
||||
/* Character set spec [1/7.2.1] */
|
||||
@ -218,6 +219,21 @@ struct charspec {
|
||||
} __packed;
|
||||
|
||||
|
||||
struct pathcomp {
|
||||
uint8_t type;
|
||||
uint8_t l_ci;
|
||||
uint16_t comp_filever;
|
||||
uint8_t ident[256];
|
||||
} __packed;
|
||||
#define UDF_PATH_COMP_SIZE 4
|
||||
#define UDF_PATH_COMP_RESERVED 0
|
||||
#define UDF_PATH_COMP_ROOT 1
|
||||
#define UDF_PATH_COMP_MOUNTROOT 2
|
||||
#define UDF_PATH_COMP_PARENTDIR 3
|
||||
#define UDF_PATH_COMP_CURDIR 4
|
||||
#define UDF_PATH_COMP_NAME 5
|
||||
|
||||
|
||||
/* Timestamp [1/7.3] */
|
||||
struct timestamp {
|
||||
uint16_t type_tz;
|
||||
@ -629,7 +645,7 @@ struct fileid_desc {
|
||||
uint8_t l_fi; /* Length of file identifier area */
|
||||
struct long_ad icb;
|
||||
uint16_t l_iu; /* Length of implementation use area */
|
||||
uint8_t data[1];
|
||||
uint8_t data[0];
|
||||
} __packed;
|
||||
#define UDF_FID_SIZE 38
|
||||
#define UDF_FILE_CHAR_VIS (1 << 0) /* Invisible */
|
||||
@ -764,6 +780,7 @@ struct extfile_entry {
|
||||
uint32_t l_ad; /* Length of allocation descriptors */
|
||||
uint8_t data[1];
|
||||
} __packed;
|
||||
#define UDF_EXTFENTRY_SIZE 216
|
||||
|
||||
|
||||
/* Indirect entry [ecma 48.7] */
|
||||
@ -774,7 +791,7 @@ struct indirect_entry {
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Allocation extent descritor [ecma 48.5] */
|
||||
/* Allocation extent descriptor [ecma 48.5] */
|
||||
struct alloc_ext_entry {
|
||||
struct desc_tag tag;
|
||||
uint32_t prev_entry;
|
||||
@ -806,13 +823,5 @@ union dscrptr {
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Useful defines */
|
||||
|
||||
#define GETICB(ad_type, fentry, offset) \
|
||||
(struct ad_type *)&fentry->data[offset]
|
||||
|
||||
#define GETICBLEN(ad_type, icb) ((struct ad_type *)(icb))->len
|
||||
|
||||
|
||||
#endif /* !_FS_UDF_ECMA167_UDF_H_ */
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.udf,v 1.1 2006/02/02 15:19:15 reinoud Exp $
|
||||
# $NetBSD: files.udf,v 1.2 2008/05/14 16:49:48 reinoud Exp $
|
||||
|
||||
deffs fs_udf.h UDF
|
||||
|
||||
@ -6,4 +6,12 @@ file fs/udf/udf_osta.c udf
|
||||
file fs/udf/udf_vfsops.c udf
|
||||
file fs/udf/udf_vnops.c udf
|
||||
file fs/udf/udf_subr.c udf
|
||||
file fs/udf/udf_readwrite.c udf
|
||||
file fs/udf/udf_strat_bootstrap.c udf
|
||||
file fs/udf/udf_strat_sequential.c udf
|
||||
file fs/udf/udf_strat_direct.c udf
|
||||
file fs/udf/udf_strat_rmw.c udf
|
||||
file fs/udf/udf_allocation.c udf
|
||||
|
||||
defflag opt_udf.h UDF_READWRITE
|
||||
|
||||
|
335
sys/fs/udf/udf.h
335
sys/fs/udf/udf.h
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: udf.h,v 1.10 2007/10/10 20:42:25 ad Exp $ */
|
||||
/* $NetBSD: udf.h,v 1.11 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Reinoud Zandijk
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -12,13 +12,6 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the
|
||||
* NetBSD Project. See http://www.NetBSD.org/ for
|
||||
* information about NetBSD.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
@ -43,28 +36,41 @@
|
||||
#include "udf_osta.h"
|
||||
#include "ecma167-udf.h"
|
||||
#include <sys/cdio.h>
|
||||
#include <sys/bufq.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
|
||||
/* TODO make `udf_verbose' set by sysctl */
|
||||
/* debug section */
|
||||
extern int udf_verbose;
|
||||
|
||||
/* initial value of udf_verbose */
|
||||
#define UDF_DEBUGGING 0x000
|
||||
/* undefine UDF_COMPLETE_DELETE to need `purge'; but purge is not implemented */
|
||||
#define UDF_COMPLETE_DELETE
|
||||
|
||||
/* debug categories */
|
||||
#define UDF_DEBUG_VOLUMES 0x001
|
||||
#define UDF_DEBUG_LOCKING 0x002
|
||||
#define UDF_DEBUG_NODE 0x004
|
||||
#define UDF_DEBUG_LOOKUP 0x008
|
||||
#define UDF_DEBUG_READDIR 0x010
|
||||
#define UDF_DEBUG_FIDS 0x020
|
||||
#define UDF_DEBUG_DESCRIPTOR 0x040
|
||||
#define UDF_DEBUG_TRANSLATE 0x080
|
||||
#define UDF_DEBUG_STRATEGY 0x100
|
||||
#define UDF_DEBUG_READ 0x200
|
||||
#define UDF_DEBUG_CALL 0x400
|
||||
#define UDF_DEBUG_NOTIMPL UDF_DEBUG_CALL
|
||||
#define UDF_DEBUG_VOLUMES 0x00001
|
||||
#define UDF_DEBUG_LOCKING 0x00002
|
||||
#define UDF_DEBUG_NODE 0x00004
|
||||
#define UDF_DEBUG_LOOKUP 0x00008
|
||||
#define UDF_DEBUG_READDIR 0x00010
|
||||
#define UDF_DEBUG_FIDS 0x00020
|
||||
#define UDF_DEBUG_DESCRIPTOR 0x00040
|
||||
#define UDF_DEBUG_TRANSLATE 0x00080
|
||||
#define UDF_DEBUG_STRATEGY 0x00100
|
||||
#define UDF_DEBUG_READ 0x00200
|
||||
#define UDF_DEBUG_WRITE 0x00400
|
||||
#define UDF_DEBUG_CALL 0x00800
|
||||
#define UDF_DEBUG_ATTR 0x01000
|
||||
#define UDF_DEBUG_EXTATTR 0x02000
|
||||
#define UDF_DEBUG_ALLOC 0x04000
|
||||
#define UDF_DEBUG_ADWLK 0x08000
|
||||
#define UDF_DEBUG_NOTIMPL 0x10000
|
||||
#define UDF_DEBUG_SHEDULE 0x20000
|
||||
#define UDF_DEBUG_SYNC 0x40000
|
||||
#define UDF_DEBUG_PARANOIA 0x80000
|
||||
|
||||
/* initial value of udf_verbose */
|
||||
#define UDF_DEBUGGING 0
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -101,21 +107,34 @@ SYSCTL_SETUP_PROTO(sysctl_vfs_udf_setup);
|
||||
|
||||
/* DON'T change these: they identify 13thmonkey's UDF implementation */
|
||||
#define APP_NAME "*NetBSD UDF"
|
||||
#define APP_VERSION_MAIN 1
|
||||
#define APP_VERSION_SUB 0
|
||||
#define IMPL_NAME "*13thMonkey.org"
|
||||
#define APP_VERSION_MAIN 0
|
||||
#define APP_VERSION_SUB 4
|
||||
#define IMPL_NAME "*NetBSD kernel UDF"
|
||||
|
||||
|
||||
/* Configuration values */
|
||||
#define UDF_INODE_HASHBITS 10
|
||||
#define UDF_INODE_HASHSIZE (1<<UDF_INODE_HASHBITS)
|
||||
#define UDF_INODE_HASHMASK (UDF_INODE_HASHSIZE - 1)
|
||||
#define UDF_ECCBUF_HASHBITS 10
|
||||
#define UDF_ECCBUF_HASHSIZE (1<<UDF_ECCBUF_HASHBITS)
|
||||
#define UDF_ECCBUF_HASHMASK (UDF_ECCBUF_HASHSIZE -1)
|
||||
|
||||
#define UDF_ECCLINE_MAXFREE 10 /* picked */
|
||||
#define UDF_ECCLINE_MAXBUSY 100 /* picked */
|
||||
|
||||
#define UDF_MAX_MAPPINGS (MAXPHYS/DEV_BSIZE) /* 128 */
|
||||
#define UDF_VAT_CHUNKSIZE (64*1024) /* picked */
|
||||
#define UDF_SYMLINKBUFLEN (64*1024) /* picked */
|
||||
|
||||
|
||||
/* structure space */
|
||||
#define UDF_ANCHORS 4 /* 256, 512, N-256, N */
|
||||
#define UDF_PARTITIONS 4 /* overkill */
|
||||
#define UDF_PMAPS 4 /* overkill */
|
||||
#define UDF_PMAPS 5 /* overkill */
|
||||
#define UDF_LVDINT_SEGMENTS 100 /* big overkill */
|
||||
#define UDF_LVINT_LOSSAGE 4 /* lose 2 openings */
|
||||
#define UDF_MAX_ALLOC_EXTENTS 10 /* overkill */
|
||||
|
||||
|
||||
/* constants */
|
||||
@ -126,14 +145,113 @@ SYSCTL_SETUP_PROTO(sysctl_vfs_udf_setup);
|
||||
#define UDF_MAX_SECTOR ((uint64_t) -10) /* high water mark */
|
||||
|
||||
|
||||
/* RW content hint for allocation and other purposes */
|
||||
#define UDF_C_PROCESSED 0 /* not relevant */
|
||||
#define UDF_C_USERDATA 1 /* all but userdata is metadata */
|
||||
//#define UDF_C_METADATA 2 /* unspecified metadata */
|
||||
#define UDF_C_DSCR 3 /* update sectornr and CRC */
|
||||
#define UDF_C_NODE 4 /* file/dir node, update sectornr and CRC */
|
||||
#define UDF_C_EXTATTRS 5 /* dunno what to do yet */
|
||||
#define UDF_C_FIDS 6 /* update all contained fids */
|
||||
|
||||
|
||||
/* use unused b_freelistindex for our UDF_C_TYPE */
|
||||
#define b_udf_c_type b_freelistindex
|
||||
|
||||
|
||||
/* virtual to physical mapping types */
|
||||
#define UDF_VTOP_RAWPART UDF_PMAPS /* [0..UDF_PMAPS> are normal */
|
||||
|
||||
#define UDF_VTOP_TYPE_RAW 0
|
||||
#define UDF_VTOP_TYPE_UNKNOWN 0
|
||||
#define UDF_VTOP_TYPE_PHYS 1
|
||||
#define UDF_VTOP_TYPE_VIRT 2
|
||||
#define UDF_VTOP_TYPE_SPARABLE 3
|
||||
#define UDF_VTOP_TYPE_META 4
|
||||
|
||||
|
||||
/* allocation strategies */
|
||||
#define UDF_ALLOC_SEQUENTIAL 1 /* linear on NWA */
|
||||
#define UDF_ALLOC_VAT 2 /* VAT handling */
|
||||
#define UDF_ALLOC_SPACEMAP 3 /* spacemaps */
|
||||
#define UDF_ALLOC_METABITMAP 4 /* metadata bitmap */
|
||||
#define UDF_ALLOC_METASEQUENTIAL 5 /* in chunks seq., nodes not seq */
|
||||
#define UDF_ALLOC_RELAXEDSEQUENTIAL 6 /* only nodes not seq. */
|
||||
|
||||
|
||||
/* logical volume open/close actions */
|
||||
#define UDF_OPEN_SESSION 0x01 /* if needed writeout VRS + VDS */
|
||||
#define UDF_CLOSE_SESSION 0x02 /* close session after writing VAT */
|
||||
#define UDF_WRITE_VAT 0x04 /* sequential VAT filesystem */
|
||||
#define UDF_WRITE_LVINT 0x08 /* write out open lvint */
|
||||
#define UDF_WRITE_PART_BITMAPS 0x10 /* write out partition space bitmaps */
|
||||
#define UDF_APPENDONLY_LVINT 0x20 /* no shifting, only appending */
|
||||
#define UDFLOGVOL_BITS "\20\1OPENSESSION\2CLOSESESSION\3WRITEVAT\4WRITELVINT"\
|
||||
"\5APPENDONLY"
|
||||
|
||||
/* logical volume error handling actions */
|
||||
#define UDF_UPDATE_TRACKINFO 0x01 /* update trackinfo and re-shedule */
|
||||
#define UDF_REMAP_BLOCK 0x02 /* remap the failing block length */
|
||||
#define UDFONERROR_BITS "\20\1UPDATE_TRACKINFO\2REMAP_BLOCK"
|
||||
|
||||
|
||||
/* readdir cookies */
|
||||
#define UDF_DIRCOOKIE_DOT 1
|
||||
|
||||
|
||||
/* malloc pools */
|
||||
MALLOC_DECLARE(M_UDFMNT);
|
||||
MALLOC_DECLARE(M_UDFVOLD);
|
||||
MALLOC_DECLARE(M_UDFTEMP);
|
||||
|
||||
struct pool udf_node_pool;
|
||||
|
||||
struct udf_node;
|
||||
struct udf_strategy;
|
||||
|
||||
|
||||
struct udf_lvintq {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint32_t pos;
|
||||
uint32_t wpos;
|
||||
};
|
||||
|
||||
|
||||
struct udf_bitmap {
|
||||
uint8_t *blob; /* allocated */
|
||||
uint8_t *bits; /* bits themselves */
|
||||
uint8_t *pages; /* dirty pages */
|
||||
uint32_t max_offset; /* in bits */
|
||||
uint32_t data_pos; /* position in data */
|
||||
uint32_t metadata_pos; /* .. in metadata */
|
||||
};
|
||||
|
||||
|
||||
struct udf_strat_args {
|
||||
struct udf_mount *ump;
|
||||
struct udf_node *udf_node;
|
||||
struct long_ad *icb;
|
||||
union dscrptr *dscr;
|
||||
struct buf *nestbuf;
|
||||
kauth_cred_t cred;
|
||||
int waitfor;
|
||||
};
|
||||
|
||||
struct udf_strategy {
|
||||
int (*create_logvol_dscr) (struct udf_strat_args *args);
|
||||
void (*free_logvol_dscr) (struct udf_strat_args *args);
|
||||
int (*read_logvol_dscr) (struct udf_strat_args *args);
|
||||
int (*write_logvol_dscr) (struct udf_strat_args *args);
|
||||
void (*queuebuf) (struct udf_strat_args *args);
|
||||
void (*discstrat_init) (struct udf_strat_args *args);
|
||||
void (*discstrat_finish) (struct udf_strat_args *args);
|
||||
};
|
||||
|
||||
extern struct udf_strategy udf_strat_bootstrap;
|
||||
extern struct udf_strategy udf_strat_sequential;
|
||||
extern struct udf_strategy udf_strat_direct;
|
||||
extern struct udf_strategy udf_strat_rmw;
|
||||
|
||||
|
||||
/* pre cleanup */
|
||||
struct udf_mount {
|
||||
@ -142,7 +260,8 @@ struct udf_mount {
|
||||
struct mmc_discinfo discinfo;
|
||||
struct udf_args mount_args;
|
||||
|
||||
/* read in structures */
|
||||
/* format descriptors */
|
||||
kmutex_t logvol_mutex;
|
||||
struct anchor_vdp *anchors[UDF_ANCHORS]; /* anchors to VDS */
|
||||
struct pri_vol_desc *primary_vol; /* identification */
|
||||
struct logvol_desc *logical_vol; /* main mapping v->p */
|
||||
@ -150,113 +269,147 @@ struct udf_mount {
|
||||
struct impvol_desc *implementation; /* likely reduntant */
|
||||
struct logvol_int_desc *logvol_integrity; /* current integrity */
|
||||
struct part_desc *partitions[UDF_PARTITIONS]; /* partitions */
|
||||
|
||||
/* derived; points *into* other structures */
|
||||
/* logvol_info is derived; points *into* other structures */
|
||||
struct udf_logvol_info *logvol_info; /* integrity descr. */
|
||||
|
||||
/* fileset and root directories */
|
||||
struct fileset_desc *fileset_desc; /* normally one */
|
||||
|
||||
/* tracing logvol integrity history */
|
||||
struct udf_lvintq lvint_trace[UDF_LVDINT_SEGMENTS];
|
||||
int lvopen; /* logvol actions */
|
||||
int lvclose; /* logvol actions */
|
||||
|
||||
/* disc allocation / writing method */
|
||||
int lvreadwrite; /* bits */
|
||||
int data_alloc; /* all userdata */
|
||||
int meta_alloc; /* all metadata */
|
||||
int data_part;
|
||||
int metadata_part;
|
||||
kmutex_t allocate_mutex;
|
||||
|
||||
/* logical to physical translations */
|
||||
int vtop[UDF_PMAPS+1]; /* vpartnr trans */
|
||||
int vtop_tp[UDF_PMAPS+1]; /* type of trans */
|
||||
|
||||
/* sequential track info */
|
||||
struct mmc_trackinfo data_track;
|
||||
struct mmc_trackinfo metadata_track;
|
||||
|
||||
/* VAT */
|
||||
uint32_t first_possible_vat_location;
|
||||
uint32_t last_possible_vat_location;
|
||||
uint32_t vat_table_alloc_length;
|
||||
uint32_t vat_entries;
|
||||
uint32_t vat_offset; /* offset in table */
|
||||
uint8_t *vat_table; /* read in data */
|
||||
uint32_t vat_last_free_lb; /* last free lb_num */
|
||||
uint32_t vat_table_len;
|
||||
uint32_t vat_table_alloc_len;
|
||||
uint8_t *vat_table;
|
||||
uint8_t *vat_pages; /* TODO */
|
||||
struct udf_node *vat_node; /* system node */
|
||||
|
||||
/* space bitmaps */
|
||||
struct space_bitmap_desc*part_unalloc_dscr[UDF_PARTITIONS];
|
||||
struct space_bitmap_desc*part_freed_dscr [UDF_PARTITIONS];
|
||||
struct udf_bitmap part_unalloc_bits[UDF_PARTITIONS];
|
||||
struct udf_bitmap part_freed_bits [UDF_PARTITIONS];
|
||||
|
||||
/* sparable */
|
||||
uint32_t sparable_packet_len;
|
||||
uint32_t sparable_packet_size;
|
||||
uint32_t packet_size;
|
||||
struct udf_sparing_table*sparing_table;
|
||||
|
||||
/* meta */
|
||||
struct udf_node *metadata_file;
|
||||
struct udf_node *metadatamirror_file;
|
||||
struct udf_node *metadatabitmap_file;
|
||||
struct udf_node *metadata_node; /* system node */
|
||||
struct udf_node *metadatamirror_node; /* system node */
|
||||
struct udf_node *metadatabitmap_node; /* system node */
|
||||
struct udf_bitmap metadata_bitmap; /* TODO : readin */
|
||||
|
||||
/* disc allocation */
|
||||
int data_alloc, meta_alloc; /* allocation scheme */
|
||||
|
||||
struct mmc_trackinfo datatrack;
|
||||
struct mmc_trackinfo metadatatrack;
|
||||
/* TODO free space and usage per partition */
|
||||
/* ... [UDF_PARTITIONS]; */
|
||||
|
||||
/* hash table to lookup ino_t -> udf_node */
|
||||
LIST_HEAD(, udf_node) udf_nodes[UDF_INODE_HASHSIZE];
|
||||
|
||||
/* allocation pool for udf_node's descriptors */
|
||||
struct pool *desc_pool;
|
||||
|
||||
/* locks */
|
||||
/* hash table to lookup icb -> udf_node and sorted list for sync */
|
||||
kmutex_t ihash_lock;
|
||||
kmutex_t get_node_lock;
|
||||
LIST_HEAD(, udf_node) udf_nodes[UDF_INODE_HASHSIZE];
|
||||
LIST_HEAD(, udf_node) sorted_udf_nodes; /* sorted sync list */
|
||||
|
||||
/* syncing */
|
||||
int syncing; /* are we syncing? */
|
||||
kcondvar_t dirtynodes_cv; /* sleeping on sync */
|
||||
|
||||
/* late allocation */
|
||||
uint32_t uncomitted_lb; /* for free space */
|
||||
struct long_ad *la_node_ad_cpy; /* issue buf */
|
||||
uint64_t *la_lmapping, *la_pmapping; /* issue buf */
|
||||
|
||||
/* lists */
|
||||
STAILQ_HEAD(, udf_node) dirty_nodes;
|
||||
STAILQ_HEAD(udfmntpts, udf_mount) all_udf_mntpnts;
|
||||
|
||||
/* device strategy */
|
||||
struct udf_strategy *strategy;
|
||||
void *strategy_private;
|
||||
};
|
||||
|
||||
|
||||
#define UDF_VTOP_RAWPART UDF_PMAPS /* [0..UDF_PMAPS> are normal */
|
||||
|
||||
/* virtual to physical mapping types */
|
||||
#define UDF_VTOP_TYPE_RAW 0
|
||||
#define UDF_VTOP_TYPE_UNKNOWN 0
|
||||
#define UDF_VTOP_TYPE_PHYS 1
|
||||
#define UDF_VTOP_TYPE_VIRT 2
|
||||
#define UDF_VTOP_TYPE_SPARABLE 3
|
||||
#define UDF_VTOP_TYPE_META 4
|
||||
|
||||
/* allocation strategies */
|
||||
#define UDF_ALLOC_SPACEMAP 1 /* spacemaps */
|
||||
#define UDF_ALLOC_SEQUENTIAL 2 /* linear on NWA */
|
||||
#define UDF_ALLOC_VAT 3 /* VAT handling */
|
||||
#define UDF_ALLOC_METABITMAP 4 /* metadata bitmap */
|
||||
#define UDF_ALLOC_METASEQUENTIAL 5 /* in chunks seq., nodes not seq */
|
||||
#define UDF_ALLOC_RELAXEDSEQUENTIAL 6 /* only nodes not seq. */
|
||||
|
||||
/* readdir cookies */
|
||||
#define UDF_DIRCOOKIE_DOT 1
|
||||
|
||||
|
||||
/*
|
||||
* UDF node describing a file/directory.
|
||||
*
|
||||
* BUGALERT claim node_mutex before reading/writing to prevent inconsistencies !
|
||||
*/
|
||||
struct udf_node {
|
||||
struct genfs_node i_gnode; /* has to be first */
|
||||
struct vnode *vnode; /* vnode associated */
|
||||
struct udf_mount *ump;
|
||||
|
||||
kmutex_t node_mutex;
|
||||
kcondvar_t node_lock; /* sleeping lock */
|
||||
char const *lock_fname;
|
||||
int lock_lineno;
|
||||
|
||||
/* one of `fe' or `efe' can be set, not both (UDF file entry dscr.) */
|
||||
struct file_entry *fe;
|
||||
struct extfile_entry *efe;
|
||||
struct alloc_ext_entry *ext[UDF_MAX_ALLOC_EXTENTS];
|
||||
int num_extensions;
|
||||
|
||||
/* location found and recording location & hints */
|
||||
/* location found, recording location & hints */
|
||||
struct long_ad loc; /* FID/hash loc. */
|
||||
struct long_ad next_loc; /* strat 4096 loc */
|
||||
struct long_ad write_loc; /* strat 4096 loc */
|
||||
int needs_indirect; /* has missing indr. */
|
||||
struct long_ad ext_loc[UDF_MAX_ALLOC_EXTENTS];
|
||||
|
||||
uint64_t last_diroffset; /* speeding up lookup*/
|
||||
|
||||
/* TODO support for allocation extents? */
|
||||
|
||||
/* device number from extended attributes = makedev(min,maj) */
|
||||
dev_t rdev;
|
||||
|
||||
/* misc */
|
||||
uint32_t i_flags; /* associated flags */
|
||||
struct lockf *lockf; /* lock list */
|
||||
uint32_t outstanding_bufs; /* file data */
|
||||
uint32_t outstanding_nodedscr; /* node dscr */
|
||||
|
||||
/* possibly not needed */
|
||||
long refcnt;
|
||||
int dirty;
|
||||
int hold;
|
||||
|
||||
/* references to associated nodes */
|
||||
struct udf_node *extattr;
|
||||
struct udf_node *streamdir;
|
||||
struct udf_node *my_parent; /* if extended attr. */
|
||||
|
||||
LIST_ENTRY(udf_node) hashchain; /* all udf nodes */
|
||||
STAILQ_ENTRY(udf_node) dirty_nodes; /* dirty udf nodes */
|
||||
LIST_ENTRY(udf_node) hashchain; /* inside hash line */
|
||||
LIST_ENTRY(udf_node) sortchain; /* sorted udf nodes */
|
||||
};
|
||||
|
||||
|
||||
/* misc. flags stored in i_flags (XXX needs cleaning up) */
|
||||
#define IN_ACCESS 0x0001 /* Inode access time update request. */
|
||||
#define IN_CHANGE 0x0002 /* Inode change time update request. */
|
||||
#define IN_UPDATE 0x0004 /* Inode was written to; update mtime*/
|
||||
#define IN_MODIFY 0x0008 /* Modification time update request. */
|
||||
#define IN_MODIFIED 0x0010 /* node has been modified. */
|
||||
#define IN_ACCESSED 0x0020 /* node has been accessed. */
|
||||
#define IN_RENAME 0x0040 /* node is being renamed. XXX ?? */
|
||||
#define IN_DELETED 0x0080 /* node is unlinked, no FID reference */
|
||||
#define IN_LOCKED 0x0100 /* node is locked by condvar */
|
||||
#define IN_SYNCED 0x0200 /* node is being used by sync */
|
||||
#define IN_CALLBACK_ULK 0x0400 /* node will be unlocked by callback */
|
||||
|
||||
|
||||
#define IN_FLAGBITS \
|
||||
"\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFY\5IN_MODIFIED" \
|
||||
"\6IN_ACCESSED\7IN_RENAME\10IN_DELETED\11IN_LOCKED\12IN_SYNCED" \
|
||||
"\13IN_CALLBACK_ULK"
|
||||
|
||||
#endif /* !_FS_UDF_UDF_H_ */
|
||||
|
2338
sys/fs/udf/udf_allocation.c
Normal file
2338
sys/fs/udf/udf_allocation.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: udf_bswap.h,v 1.4 2006/03/05 16:55:44 christos Exp $ */
|
||||
/* $NetBSD: udf_bswap.h,v 1.5 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
|
@ -1,7 +1,9 @@
|
||||
/* $NetBSD: udf_osta.c,v 1.5 2007/12/11 12:05:27 lukem Exp $ */
|
||||
/* $NetBSD: udf_osta.c,v 1.6 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_osta.c,v 1.5 2007/12/11 12:05:27 lukem Exp $");
|
||||
#ifndef lint
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_osta.c,v 1.6 2008/05/14 16:49:48 reinoud Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Various routines from the OSTA 2.01 specs. Copyrights are included with
|
||||
@ -12,6 +14,9 @@ __KERNEL_RCSID(0, "$NetBSD: udf_osta.c,v 1.5 2007/12/11 12:05:27 lukem Exp $");
|
||||
|
||||
#include "udf_osta.h"
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/***********************************************************************
|
||||
@ -199,6 +204,27 @@ udf_unicode_cksum(s, n)
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculates a 16-bit checksum of the Implementation Use
|
||||
* Extended Attribute header or Application Use Extended Attribute
|
||||
* header. The fields AttributeType through ImplementationIdentifier
|
||||
* (or ApplicationIdentifier) inclusively represent the
|
||||
* data covered by the checksum (48 bytes).
|
||||
*
|
||||
*/
|
||||
uint16_t udf_ea_cksum(uint8_t *data) {
|
||||
uint16_t checksum = 0;
|
||||
int count;
|
||||
|
||||
for (count = 0; count < 48; count++) {
|
||||
checksum += *data++;
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAIN
|
||||
unsigned char bytes[] = { 0x70, 0x6A, 0x77 };
|
||||
|
||||
@ -275,9 +301,11 @@ int UnicodeLength(unicode_t *string) {
|
||||
}
|
||||
|
||||
|
||||
static int isprint(unsigned char c) {
|
||||
#ifdef _KERNEL
|
||||
static int isprint(int c) {
|
||||
return (c >= ' ') && (c != 127);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: udf_osta.h,v 1.3 2006/03/05 16:55:44 christos Exp $ */
|
||||
/* $NetBSD: udf_osta.h,v 1.4 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Prototypes for the OSTA functions
|
||||
@ -8,9 +8,12 @@
|
||||
#ifndef _FS_UDF_OSTA_H_
|
||||
#define _FS_UDF_OSTA_H_
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifndef UNIX
|
||||
#define UNIX
|
||||
#endif
|
||||
@ -33,6 +36,7 @@ int udf_UncompressUnicode(int, byte *, unicode_t *);
|
||||
int udf_CompressUnicode(int, int, unicode_t *, byte *);
|
||||
unsigned short udf_cksum(unsigned char *, int);
|
||||
unsigned short udf_unicode_cksum(unsigned short *, int);
|
||||
uint16_t udf_ea_cksum(uint8_t *data);
|
||||
int UDFTransName(unicode_t *, unicode_t *, int);
|
||||
int UnicodeLength(unicode_t *string);
|
||||
|
||||
|
658
sys/fs/udf/udf_readwrite.c
Normal file
658
sys/fs/udf/udf_readwrite.c
Normal file
@ -0,0 +1,658 @@
|
||||
/* $NetBSD: udf_readwrite.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_quota.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <dev/clock_subr.h>
|
||||
|
||||
#include <fs/udf/ecma167-udf.h>
|
||||
#include <fs/udf/udf_mount.h>
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_udf.h"
|
||||
#endif
|
||||
|
||||
#include "udf.h"
|
||||
#include "udf_subr.h"
|
||||
#include "udf_bswap.h"
|
||||
|
||||
|
||||
#define VTOI(vnode) ((struct udf_node *) vnode->v_data)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
udf_fixup_fid_block(uint8_t *blob, int lb_size,
|
||||
int rfix_pos, int max_rfix_pos, uint32_t lb_num)
|
||||
{
|
||||
struct fileid_desc *fid;
|
||||
uint8_t *fid_pos;
|
||||
int fid_len, found;
|
||||
|
||||
/* needs to be word aligned */
|
||||
KASSERT(rfix_pos % 4 == 0);
|
||||
|
||||
/* first resync with the FID stream !!! */
|
||||
found = 0;
|
||||
while (rfix_pos + sizeof(struct desc_tag) <= max_rfix_pos) {
|
||||
fid_pos = blob + rfix_pos;
|
||||
fid = (struct fileid_desc *) fid_pos;
|
||||
if (udf_rw16(fid->tag.id) == TAGID_FID) {
|
||||
if (udf_check_tag((union dscrptr *) fid) == 0)
|
||||
found = 1;
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
/* try next location; can only be 4 bytes aligned */
|
||||
rfix_pos += 4;
|
||||
}
|
||||
|
||||
/* walk over the fids */
|
||||
fid_pos = blob + rfix_pos;
|
||||
while (rfix_pos + sizeof(struct desc_tag) <= max_rfix_pos) {
|
||||
fid = (struct fileid_desc *) fid_pos;
|
||||
if (udf_rw16(fid->tag.id) != TAGID_FID) {
|
||||
/* end of FID stream; end of directory or currupted */
|
||||
break;
|
||||
}
|
||||
|
||||
/* update sector number and recalculate checkum */
|
||||
fid->tag.tag_loc = udf_rw32(lb_num);
|
||||
udf_validate_tag_sum((union dscrptr *) fid);
|
||||
|
||||
/* if the FID crosses the memory, we're done! */
|
||||
if (rfix_pos + UDF_FID_SIZE >= max_rfix_pos)
|
||||
break;
|
||||
|
||||
fid_len = udf_fidsize(fid);
|
||||
fid_pos += fid_len;
|
||||
rfix_pos += fid_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
udf_fixup_internal_extattr(uint8_t *blob, uint32_t lb_num)
|
||||
{
|
||||
struct desc_tag *tag;
|
||||
struct file_entry *fe;
|
||||
struct extfile_entry *efe;
|
||||
struct extattrhdr_desc *eahdr;
|
||||
int l_ea, error;
|
||||
|
||||
/* get information from fe/efe */
|
||||
tag = (struct desc_tag *) blob;
|
||||
switch (udf_rw16(tag->id)) {
|
||||
case TAGID_FENTRY :
|
||||
fe = (struct file_entry *) blob;
|
||||
l_ea = udf_rw32(fe->l_ea);
|
||||
eahdr = (struct extattrhdr_desc *) fe->data;
|
||||
break;
|
||||
case TAGID_EXTFENTRY :
|
||||
efe = (struct extfile_entry *) blob;
|
||||
l_ea = udf_rw32(efe->l_ea);
|
||||
eahdr = (struct extattrhdr_desc *) efe->data;
|
||||
break;
|
||||
case TAGID_INDIRECTENTRY :
|
||||
case TAGID_ALLOCEXTENT :
|
||||
case TAGID_EXTATTR_HDR :
|
||||
return;
|
||||
default:
|
||||
panic("%s: passed bad tag\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
/* something recorded here? (why am i called?) */
|
||||
if (l_ea == 0)
|
||||
return;
|
||||
|
||||
/* check extended attribute tag */
|
||||
/* TODO XXX what to do when we encounter an error here? */
|
||||
error = udf_check_tag(eahdr);
|
||||
if (error)
|
||||
return; /* for now */
|
||||
if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR)
|
||||
return; /* for now */
|
||||
error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
|
||||
if (error)
|
||||
return; /* for now */
|
||||
|
||||
DPRINTF(EXTATTR, ("node fixup: found %d bytes of extended attributes\n",
|
||||
l_ea));
|
||||
|
||||
/* fixup eahdr tag */
|
||||
eahdr->tag.tag_loc = udf_rw32(lb_num);
|
||||
udf_validate_tag_sum((union dscrptr *) eahdr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
udf_fixup_node_internals(struct udf_mount *ump, uint8_t *blob, int udf_c_type)
|
||||
{
|
||||
struct desc_tag *tag;
|
||||
struct file_entry *fe;
|
||||
struct extfile_entry *efe;
|
||||
uint32_t lb_size, lb_num;
|
||||
uint32_t rfid_pos, max_rfid_pos;
|
||||
int icbflags, addr_type, has_fids, l_ea;
|
||||
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
/* if its not a node we're done */
|
||||
if (udf_c_type != UDF_C_NODE)
|
||||
return;
|
||||
|
||||
/* NOTE this could also be done in write_internal */
|
||||
/* start of a descriptor */
|
||||
has_fids = 0;
|
||||
max_rfid_pos = rfid_pos = lb_num = 0; /* shut up gcc! */
|
||||
|
||||
tag = (struct desc_tag *) blob;
|
||||
switch (udf_rw16(tag->id)) {
|
||||
case TAGID_FENTRY :
|
||||
fe = (struct file_entry *) tag;
|
||||
l_ea = udf_rw32(fe->l_ea);
|
||||
icbflags = udf_rw16(fe->icbtag.flags);
|
||||
addr_type = (icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK);
|
||||
has_fids = (addr_type == UDF_ICB_INTERN_ALLOC);
|
||||
rfid_pos = UDF_FENTRY_SIZE + l_ea;
|
||||
max_rfid_pos = rfid_pos + udf_rw64(fe->inf_len);
|
||||
lb_num = udf_rw32(fe->tag.tag_loc);
|
||||
break;
|
||||
case TAGID_EXTFENTRY :
|
||||
efe = (struct extfile_entry *) tag;
|
||||
l_ea = udf_rw32(efe->l_ea);
|
||||
icbflags = udf_rw16(efe->icbtag.flags);
|
||||
addr_type = (icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK);
|
||||
has_fids = (addr_type == UDF_ICB_INTERN_ALLOC);
|
||||
rfid_pos = UDF_EXTFENTRY_SIZE + l_ea;
|
||||
max_rfid_pos = rfid_pos + udf_rw64(efe->inf_len);
|
||||
lb_num = udf_rw32(efe->tag.tag_loc);
|
||||
break;
|
||||
case TAGID_INDIRECTENTRY :
|
||||
case TAGID_ALLOCEXTENT :
|
||||
case TAGID_EXTATTR_HDR :
|
||||
l_ea = 0;
|
||||
has_fids = 0;
|
||||
break;
|
||||
default:
|
||||
panic("%s: passed bad tag\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
|
||||
/* fixup internal extended attributes if present */
|
||||
if (l_ea)
|
||||
udf_fixup_internal_extattr(blob, lb_num);
|
||||
|
||||
if (has_fids) {
|
||||
udf_fixup_fid_block(blob, lb_size, rfid_pos,
|
||||
max_rfid_pos, lb_num);
|
||||
}
|
||||
udf_validate_tag_and_crc_sums(blob);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Set of generic descriptor readers and writers and their helper functions.
|
||||
* Descriptors inside `logical space' i.e. inside logically mapped partitions
|
||||
* can never be longer than one logical sector.
|
||||
*
|
||||
* NOTE that these functions *can* be used by the sheduler backends to read
|
||||
* node descriptors too.
|
||||
*
|
||||
* For reading, the size of allocated piece is returned in multiple of sector
|
||||
* size due to udf_calc_udf_malloc_size().
|
||||
*/
|
||||
|
||||
|
||||
/* SYNC reading of n blocks from specified sector */
|
||||
/* NOTE only used by udf_read_phys_dscr */
|
||||
static int
|
||||
udf_read_phys_sectors(struct udf_mount *ump, int what, void *blob,
|
||||
uint32_t start, uint32_t sectors)
|
||||
{
|
||||
struct buf *buf, *nestbuf;
|
||||
uint32_t buf_offset;
|
||||
off_t lblkno, rblkno;
|
||||
int sector_size = ump->discinfo.sector_size;
|
||||
int blks = sector_size / DEV_BSIZE;
|
||||
int piece;
|
||||
int error;
|
||||
|
||||
DPRINTF(READ, ("udf_intbreadn() : sectors = %d, sector_size = %d\n",
|
||||
sectors, sector_size));
|
||||
buf = getiobuf(ump->devvp, true);
|
||||
buf->b_flags = B_READ;
|
||||
buf->b_cflags = BC_BUSY; /* needed? */
|
||||
buf->b_iodone = NULL;
|
||||
buf->b_data = blob;
|
||||
buf->b_bcount = sectors * sector_size;
|
||||
buf->b_resid = buf->b_bcount;
|
||||
buf->b_bufsize = buf->b_bcount;
|
||||
buf->b_private = NULL; /* not needed yet */
|
||||
BIO_SETPRIO(buf, BPRIO_DEFAULT);
|
||||
buf->b_lblkno = buf->b_blkno = buf->b_rawblkno = start * blks;
|
||||
buf->b_proc = NULL;
|
||||
|
||||
error = 0;
|
||||
buf_offset = 0;
|
||||
rblkno = start;
|
||||
lblkno = 0;
|
||||
while ((sectors > 0) && (error == 0)) {
|
||||
piece = MIN(MAXPHYS/sector_size, sectors);
|
||||
DPRINTF(READ, ("read in %d + %d\n", (uint32_t) rblkno, piece));
|
||||
|
||||
nestbuf = getiobuf(NULL, true);
|
||||
nestiobuf_setup(buf, nestbuf, buf_offset, piece * sector_size);
|
||||
/* nestbuf is B_ASYNC */
|
||||
|
||||
/* identify this nestbuf */
|
||||
nestbuf->b_lblkno = lblkno;
|
||||
|
||||
/* CD shedules on raw blkno */
|
||||
nestbuf->b_blkno = rblkno * blks;
|
||||
nestbuf->b_proc = NULL;
|
||||
nestbuf->b_rawblkno = rblkno * blks;
|
||||
nestbuf->b_udf_c_type = what;
|
||||
|
||||
udf_discstrat_queuebuf(ump, nestbuf);
|
||||
|
||||
lblkno += piece;
|
||||
rblkno += piece;
|
||||
buf_offset += piece * sector_size;
|
||||
sectors -= piece;
|
||||
}
|
||||
error = biowait(buf);
|
||||
putiobuf(buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* synchronous generic descriptor read */
|
||||
int
|
||||
udf_read_phys_dscr(struct udf_mount *ump, uint32_t sector,
|
||||
struct malloc_type *mtype, union dscrptr **dstp)
|
||||
{
|
||||
union dscrptr *dst, *new_dst;
|
||||
uint8_t *pos;
|
||||
int sectors, dscrlen;
|
||||
int i, error, sector_size;
|
||||
|
||||
sector_size = ump->discinfo.sector_size;
|
||||
|
||||
*dstp = dst = NULL;
|
||||
dscrlen = sector_size;
|
||||
|
||||
/* read initial piece */
|
||||
dst = malloc(sector_size, mtype, M_WAITOK);
|
||||
error = udf_read_phys_sectors(ump, UDF_C_DSCR, dst, sector, 1);
|
||||
DPRINTFIF(DESCRIPTOR, error, ("read error (%d)\n", error));
|
||||
|
||||
if (!error) {
|
||||
/* check if its a valid tag */
|
||||
error = udf_check_tag(dst);
|
||||
if (error) {
|
||||
/* check if its an empty block */
|
||||
pos = (uint8_t *) dst;
|
||||
for (i = 0; i < sector_size; i++, pos++) {
|
||||
if (*pos) break;
|
||||
}
|
||||
if (i == sector_size) {
|
||||
/* return no error but with no dscrptr */
|
||||
/* dispose first block */
|
||||
free(dst, mtype);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* calculate descriptor size */
|
||||
dscrlen = udf_tagsize(dst, sector_size);
|
||||
}
|
||||
DPRINTFIF(DESCRIPTOR, error, ("bad tag checksum\n"));
|
||||
|
||||
if (!error && (dscrlen > sector_size)) {
|
||||
DPRINTF(DESCRIPTOR, ("multi block descriptor read\n"));
|
||||
/*
|
||||
* Read the rest of descriptor. Since it is only used at mount
|
||||
* time its overdone to define and use a specific udf_intbreadn
|
||||
* for this alone.
|
||||
*/
|
||||
|
||||
new_dst = realloc(dst, dscrlen, mtype, M_WAITOK);
|
||||
if (new_dst == NULL) {
|
||||
free(dst, mtype);
|
||||
return ENOMEM;
|
||||
}
|
||||
dst = new_dst;
|
||||
|
||||
sectors = (dscrlen + sector_size -1) / sector_size;
|
||||
DPRINTF(DESCRIPTOR, ("dscrlen = %d (%d blk)\n", dscrlen, sectors));
|
||||
|
||||
pos = (uint8_t *) dst + sector_size;
|
||||
error = udf_read_phys_sectors(ump, UDF_C_DSCR, pos,
|
||||
sector + 1, sectors-1);
|
||||
|
||||
DPRINTFIF(DESCRIPTOR, error, ("read error on multi (%d)\n",
|
||||
error));
|
||||
}
|
||||
if (!error) {
|
||||
error = udf_check_tag_payload(dst, dscrlen);
|
||||
DPRINTFIF(DESCRIPTOR, error, ("bad payload check sum\n"));
|
||||
}
|
||||
if (error && dst) {
|
||||
free(dst, mtype);
|
||||
dst = NULL;
|
||||
}
|
||||
*dstp = dst;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_write_phys_buf(struct udf_mount *ump, int what, struct buf *buf)
|
||||
{
|
||||
struct buf *nestbuf;
|
||||
uint32_t buf_offset;
|
||||
off_t lblkno, rblkno;
|
||||
int sector_size = ump->discinfo.sector_size;
|
||||
int blks = sector_size / DEV_BSIZE;
|
||||
uint32_t sectors;
|
||||
int piece;
|
||||
int error;
|
||||
|
||||
sectors = buf->b_bcount / sector_size;
|
||||
DPRINTF(WRITE, ("udf_intbwriten() : sectors = %d, sector_size = %d\n",
|
||||
sectors, sector_size));
|
||||
|
||||
/* don't forget to increase pending count for the bwrite itself */
|
||||
/* panic("NO WRITING\n"); */
|
||||
if (buf->b_vp) {
|
||||
mutex_enter(&buf->b_vp->v_interlock);
|
||||
buf->b_vp->v_numoutput++;
|
||||
mutex_exit(&buf->b_vp->v_interlock);
|
||||
}
|
||||
|
||||
error = 0;
|
||||
buf_offset = 0;
|
||||
rblkno = buf->b_blkno / blks;
|
||||
lblkno = 0;
|
||||
while ((sectors > 0) && (error == 0)) {
|
||||
piece = MIN(MAXPHYS/sector_size, sectors);
|
||||
DPRINTF(WRITE, ("write out %d + %d\n",
|
||||
(uint32_t) rblkno, piece));
|
||||
|
||||
nestbuf = getiobuf(NULL, true);
|
||||
nestiobuf_setup(buf, nestbuf, buf_offset, piece * sector_size);
|
||||
/* nestbuf is B_ASYNC */
|
||||
|
||||
/* identify this nestbuf */
|
||||
nestbuf->b_lblkno = lblkno;
|
||||
|
||||
/* CD shedules on raw blkno */
|
||||
nestbuf->b_blkno = rblkno * blks;
|
||||
nestbuf->b_proc = NULL;
|
||||
nestbuf->b_rawblkno = rblkno * blks;
|
||||
nestbuf->b_udf_c_type = what;
|
||||
|
||||
udf_discstrat_queuebuf(ump, nestbuf);
|
||||
|
||||
lblkno += piece;
|
||||
rblkno += piece;
|
||||
buf_offset += piece * sector_size;
|
||||
sectors -= piece;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* synchronous generic descriptor write */
|
||||
int
|
||||
udf_write_phys_dscr_sync(struct udf_mount *ump, struct udf_node *udf_node, int what,
|
||||
union dscrptr *dscr, uint32_t sector, uint32_t logsector)
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct buf *buf;
|
||||
int sector_size = ump->discinfo.sector_size;
|
||||
int blks = sector_size / DEV_BSIZE;
|
||||
int dscrlen;
|
||||
int error;
|
||||
|
||||
/* set sector number in the descriptor and validate */
|
||||
dscr->tag.tag_loc = udf_rw32(logsector);
|
||||
udf_validate_tag_and_crc_sums(dscr);
|
||||
|
||||
/* calculate descriptor size */
|
||||
dscrlen = udf_tagsize(dscr, sector_size);
|
||||
|
||||
/* get transfer buffer */
|
||||
vp = udf_node ? udf_node->vnode : ump->devvp;
|
||||
buf = getiobuf(vp, true);
|
||||
buf->b_flags = B_WRITE;
|
||||
buf->b_cflags = BC_BUSY; /* needed? */
|
||||
buf->b_iodone = NULL;
|
||||
buf->b_data = (void *) dscr;
|
||||
buf->b_bcount = dscrlen;
|
||||
buf->b_resid = buf->b_bcount;
|
||||
buf->b_bufsize = buf->b_bcount;
|
||||
buf->b_private = NULL; /* not needed yet */
|
||||
BIO_SETPRIO(buf, BPRIO_DEFAULT);
|
||||
buf->b_lblkno = buf->b_blkno = buf->b_rawblkno = sector * blks;
|
||||
buf->b_proc = NULL;
|
||||
|
||||
/* do the write, wait and return error */
|
||||
udf_write_phys_buf(ump, what, buf);
|
||||
error = biowait(buf);
|
||||
putiobuf(buf);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* asynchronous generic descriptor write */
|
||||
int
|
||||
udf_write_phys_dscr_async(struct udf_mount *ump, struct udf_node *udf_node,
|
||||
int what, union dscrptr *dscr,
|
||||
uint32_t sector, uint32_t logsector,
|
||||
void (*dscrwr_callback)(struct buf *))
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct buf *buf;
|
||||
int dscrlen;
|
||||
int sector_size = ump->discinfo.sector_size;
|
||||
int blks = sector_size / DEV_BSIZE;
|
||||
|
||||
KASSERT(dscrwr_callback);
|
||||
DPRINTF(NODE, ("udf_write_phys_dscr_async() called\n"));
|
||||
|
||||
/* set sector number in the descriptor and validate */
|
||||
dscr->tag.tag_loc = udf_rw32(logsector);
|
||||
udf_validate_tag_and_crc_sums(dscr);
|
||||
|
||||
/* calculate descriptor size */
|
||||
dscrlen = udf_tagsize(dscr, sector_size);
|
||||
|
||||
/* get transfer buffer */
|
||||
vp = udf_node ? udf_node->vnode : ump->devvp;
|
||||
buf = getiobuf(vp, true);
|
||||
buf->b_flags = B_WRITE; // | B_ASYNC;
|
||||
buf->b_cflags = BC_BUSY;
|
||||
buf->b_iodone = dscrwr_callback;
|
||||
buf->b_data = dscr;
|
||||
buf->b_bcount = dscrlen;
|
||||
buf->b_resid = buf->b_bcount;
|
||||
buf->b_bufsize = buf->b_bcount;
|
||||
buf->b_private = NULL; /* not needed yet */
|
||||
BIO_SETPRIO(buf, BPRIO_DEFAULT);
|
||||
buf->b_lblkno = buf->b_blkno = buf->b_rawblkno = sector * blks;
|
||||
buf->b_proc = NULL;
|
||||
|
||||
/* do the write and return no error */
|
||||
udf_write_phys_buf(ump, what, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* disc strategy dispatchers */
|
||||
|
||||
int
|
||||
udf_create_logvol_dscr(struct udf_mount *ump, struct udf_node *udf_node, struct long_ad *icb,
|
||||
union dscrptr **dscrptr)
|
||||
{
|
||||
struct udf_strategy *strategy = ump->strategy;
|
||||
struct udf_strat_args args;
|
||||
int error;
|
||||
|
||||
args.ump = ump;
|
||||
args.udf_node = udf_node;
|
||||
args.icb = icb;
|
||||
args.dscr = NULL;
|
||||
|
||||
error = (strategy->create_logvol_dscr)(&args);
|
||||
*dscrptr = args.dscr;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
udf_free_logvol_dscr(struct udf_mount *ump, struct long_ad *icb,
|
||||
void *dscr)
|
||||
{
|
||||
struct udf_strategy *strategy = ump->strategy;
|
||||
struct udf_strat_args args;
|
||||
|
||||
args.ump = ump;
|
||||
args.icb = icb;
|
||||
args.dscr = dscr;
|
||||
|
||||
(strategy->free_logvol_dscr)(&args);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
udf_read_logvol_dscr(struct udf_mount *ump, struct long_ad *icb,
|
||||
union dscrptr **dscrptr)
|
||||
{
|
||||
struct udf_strategy *strategy = ump->strategy;
|
||||
struct udf_strat_args args;
|
||||
int error;
|
||||
|
||||
args.ump = ump;
|
||||
args.icb = icb;
|
||||
args.dscr = NULL;
|
||||
|
||||
error = (strategy->read_logvol_dscr)(&args);
|
||||
*dscrptr = args.dscr;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
udf_write_logvol_dscr(struct udf_node *udf_node, union dscrptr *dscr,
|
||||
struct long_ad *icb, int waitfor)
|
||||
{
|
||||
struct udf_strategy *strategy = udf_node->ump->strategy;
|
||||
struct udf_strat_args args;
|
||||
int error;
|
||||
|
||||
args.ump = udf_node->ump;
|
||||
args.udf_node = udf_node;
|
||||
args.icb = icb;
|
||||
args.dscr = dscr;
|
||||
args.waitfor = waitfor;
|
||||
|
||||
error = (strategy->write_logvol_dscr)(&args);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
udf_discstrat_queuebuf(struct udf_mount *ump, struct buf *nestbuf)
|
||||
{
|
||||
struct udf_strategy *strategy = ump->strategy;
|
||||
struct udf_strat_args args;
|
||||
|
||||
args.ump = ump;
|
||||
args.nestbuf = nestbuf;
|
||||
|
||||
(strategy->queuebuf)(&args);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
udf_discstrat_init(struct udf_mount *ump)
|
||||
{
|
||||
struct udf_strategy *strategy = ump->strategy;
|
||||
struct udf_strat_args args;
|
||||
|
||||
args.ump = ump;
|
||||
(strategy->discstrat_init)(&args);
|
||||
}
|
||||
|
||||
|
||||
void udf_discstrat_finish(struct udf_mount *ump)
|
||||
{
|
||||
struct udf_strategy *strategy = ump->strategy;
|
||||
struct udf_strat_args args;
|
||||
|
||||
args.ump = ump;
|
||||
(strategy->discstrat_finish)(&args);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
150
sys/fs/udf/udf_strat_bootstrap.c
Normal file
150
sys/fs/udf/udf_strat_bootstrap.c
Normal file
@ -0,0 +1,150 @@
|
||||
/* $NetBSD: udf_strat_bootstrap.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_strat_bootstrap.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_quota.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <dev/clock_subr.h>
|
||||
|
||||
#include <fs/udf/ecma167-udf.h>
|
||||
#include <fs/udf/udf_mount.h>
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_udf.h"
|
||||
#endif
|
||||
|
||||
#include "udf.h"
|
||||
#include "udf_subr.h"
|
||||
#include "udf_bswap.h"
|
||||
|
||||
|
||||
#define VTOI(vnode) ((struct udf_node *) vnode->v_data)
|
||||
#define PRIV(ump) ((struct strat_private *) ump->strategy_private)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
udf_create_logvol_dscr_bootstrap(struct udf_strat_args *args)
|
||||
{
|
||||
panic("udf_create_logvol_dscr_bootstrap: not possible\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_free_logvol_dscr_bootstrap(struct udf_strat_args *args)
|
||||
{
|
||||
panic("udf_free_logvol_dscr_bootstrap: no node descriptor reading\n");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_read_logvol_dscr_bootstrap(struct udf_strat_args *args)
|
||||
{
|
||||
panic("udf_read_logvol_dscr_bootstrap: no node descriptor reading\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_write_logvol_dscr_bootstrap(struct udf_strat_args *args)
|
||||
{
|
||||
panic("udf_write_logvol_dscr_bootstrap: no writing\n");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
udf_queuebuf_bootstrap(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct buf *buf = args->nestbuf;
|
||||
|
||||
KASSERT(ump);
|
||||
KASSERT(buf);
|
||||
KASSERT(buf->b_iodone == nestiobuf_iodone);
|
||||
|
||||
KASSERT(buf->b_flags & B_READ);
|
||||
VOP_STRATEGY(ump->devvp, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
udf_discstrat_init_bootstrap(struct udf_strat_args *args)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_discstrat_finish_bootstrap(struct udf_strat_args *args)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
struct udf_strategy udf_strat_bootstrap =
|
||||
{
|
||||
udf_create_logvol_dscr_bootstrap,
|
||||
udf_free_logvol_dscr_bootstrap,
|
||||
udf_read_logvol_dscr_bootstrap,
|
||||
udf_write_logvol_dscr_bootstrap,
|
||||
udf_queuebuf_bootstrap,
|
||||
udf_discstrat_init_bootstrap,
|
||||
udf_discstrat_finish_bootstrap
|
||||
};
|
||||
|
||||
|
450
sys/fs/udf/udf_strat_direct.c
Normal file
450
sys/fs/udf/udf_strat_direct.c
Normal file
@ -0,0 +1,450 @@
|
||||
/* $NetBSD: udf_strat_direct.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_quota.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <dev/clock_subr.h>
|
||||
|
||||
#include <fs/udf/ecma167-udf.h>
|
||||
#include <fs/udf/udf_mount.h>
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_udf.h"
|
||||
#endif
|
||||
|
||||
#include "udf.h"
|
||||
#include "udf_subr.h"
|
||||
#include "udf_bswap.h"
|
||||
|
||||
|
||||
#define VTOI(vnode) ((struct udf_node *) vnode->v_data)
|
||||
#define PRIV(ump) ((struct strat_private *) ump->strategy_private)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* BUFQ's */
|
||||
#define UDF_SHED_MAX 3
|
||||
|
||||
#define UDF_SHED_READING 0
|
||||
#define UDF_SHED_WRITING 1
|
||||
#define UDF_SHED_SEQWRITING 2
|
||||
|
||||
|
||||
struct strat_private {
|
||||
struct pool desc_pool; /* node descriptors */
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
udf_wr_nodedscr_callback(struct buf *buf)
|
||||
{
|
||||
struct udf_node *udf_node;
|
||||
|
||||
KASSERT(buf);
|
||||
KASSERT(buf->b_data);
|
||||
|
||||
/* called when write action is done */
|
||||
DPRINTF(WRITE, ("udf_wr_nodedscr_callback(): node written out\n"));
|
||||
|
||||
udf_node = VTOI(buf->b_vp);
|
||||
if (udf_node == NULL) {
|
||||
putiobuf(buf);
|
||||
printf("udf_wr_node_callback: NULL node?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX noone is waiting on this outstanding_nodedscr */
|
||||
udf_node->outstanding_nodedscr--;
|
||||
if (udf_node->outstanding_nodedscr == 0)
|
||||
wakeup(&udf_node->outstanding_nodedscr);
|
||||
|
||||
/* XXX right flags to mark dirty again on error? */
|
||||
if (buf->b_error) {
|
||||
/* write error on `defect free' media??? how to solve? */
|
||||
/* XXX lookup UDF standard for unallocatable space */
|
||||
udf_node->i_flags |= IN_MODIFIED | IN_ACCESSED;
|
||||
}
|
||||
|
||||
/* first unlock the node */
|
||||
KASSERT(udf_node->i_flags & IN_CALLBACK_ULK);
|
||||
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
|
||||
|
||||
/* unreference the vnode so it can be recycled */
|
||||
holdrele(udf_node->vnode);
|
||||
|
||||
putiobuf(buf);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
udf_getblank_nodedscr_direct(struct udf_strat_args *args)
|
||||
{
|
||||
union dscrptr **dscrptr = &args->dscr;
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
uint32_t lb_size;
|
||||
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
*dscrptr = pool_get(&priv->desc_pool, PR_WAITOK);
|
||||
memset(*dscrptr, 0, lb_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_free_nodedscr_direct(struct udf_strat_args *args)
|
||||
{
|
||||
union dscrptr *dscr = args->dscr;
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
|
||||
pool_put(&priv->desc_pool, dscr);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_read_nodedscr_direct(struct udf_strat_args *args)
|
||||
{
|
||||
union dscrptr **dscrptr = &args->dscr;
|
||||
union dscrptr *tmpdscr;
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct long_ad *icb = args->icb;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
uint32_t lb_size;
|
||||
uint32_t sector, dummy;
|
||||
int error;
|
||||
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
|
||||
error = udf_translate_vtop(ump, icb, §or, &dummy);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* try to read in fe/efe */
|
||||
error = udf_read_phys_dscr(ump, sector, M_UDFTEMP, &tmpdscr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
*dscrptr = pool_get(&priv->desc_pool, PR_WAITOK);
|
||||
memcpy(*dscrptr, tmpdscr, lb_size);
|
||||
free(tmpdscr, M_UDFTEMP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_write_nodedscr_direct(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct udf_node *udf_node = args->udf_node;
|
||||
union dscrptr *dscr = args->dscr;
|
||||
struct long_ad *icb = args->icb;
|
||||
int waitfor = args->waitfor;
|
||||
uint32_t logsector, sector, dummy;
|
||||
int error, vpart;
|
||||
|
||||
/*
|
||||
* we have to decide if we write it out sequential or at its fixed
|
||||
* position by examining the partition its (to be) written on.
|
||||
*/
|
||||
vpart = udf_rw16(udf_node->loc.loc.part_num);
|
||||
logsector = udf_rw32(icb->loc.lb_num);
|
||||
KASSERT(ump->vtop_tp[vpart] != UDF_VTOP_TYPE_VIRT);
|
||||
|
||||
sector = 0;
|
||||
error = udf_translate_vtop(ump, icb, §or, &dummy);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
UDF_LOCK_NODE(udf_node, IN_CALLBACK_ULK);
|
||||
|
||||
if (waitfor) {
|
||||
DPRINTF(WRITE, ("udf_write_nodedscr: sync write\n"));
|
||||
|
||||
error = udf_write_phys_dscr_sync(ump, udf_node, UDF_C_NODE,
|
||||
dscr, sector, logsector);
|
||||
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
|
||||
} else {
|
||||
DPRINTF(WRITE, ("udf_write_nodedscr: no wait, async write\n"));
|
||||
|
||||
/* add reference to the vnode to prevent recycling */
|
||||
vhold(udf_node->vnode);
|
||||
|
||||
udf_node->outstanding_nodedscr++;
|
||||
|
||||
error = udf_write_phys_dscr_async(ump, udf_node, UDF_C_NODE,
|
||||
dscr, sector, logsector, udf_wr_nodedscr_callback);
|
||||
/* will be UNLOCKED in call back */
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
udf_queue_buf_direct(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct buf *buf = args->nestbuf;
|
||||
struct buf *nestbuf;
|
||||
struct long_ad *node_ad_cpy;
|
||||
uint64_t *lmapping, *pmapping, *lmappos, blknr, run_start;
|
||||
uint32_t our_sectornr, sectornr;
|
||||
uint32_t lb_size, buf_offset, rbuflen, bpos;
|
||||
uint8_t *fidblk;
|
||||
off_t rblk;
|
||||
int sector_size = ump->discinfo.sector_size;
|
||||
int blks = sector_size / DEV_BSIZE;
|
||||
int len, buf_len, sector, sectors, run_length;
|
||||
int what, class, queue;
|
||||
|
||||
KASSERT(ump);
|
||||
KASSERT(buf);
|
||||
KASSERT(buf->b_iodone == nestiobuf_iodone);
|
||||
|
||||
what = buf->b_udf_c_type;
|
||||
queue = UDF_SHED_READING;
|
||||
if ((buf->b_flags & B_READ) == 0) {
|
||||
/* writing */
|
||||
queue = UDF_SHED_SEQWRITING;
|
||||
if (what == UDF_C_DSCR)
|
||||
queue = UDF_SHED_WRITING;
|
||||
if (what == UDF_C_NODE)
|
||||
queue = UDF_SHED_WRITING;
|
||||
}
|
||||
|
||||
/* use disc sheduler */
|
||||
class = ump->discinfo.mmc_class;
|
||||
KASSERT((class == MMC_CLASS_UNKN) || (class == MMC_CLASS_DISC) ||
|
||||
(ump->discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE));
|
||||
|
||||
if (queue == UDF_SHED_READING) {
|
||||
DPRINTF(SHEDULE, ("\nudf_issue_buf READ %p : sector %d type %d,"
|
||||
"b_resid %d, b_bcount %d, b_bufsize %d\n",
|
||||
buf, (uint32_t) buf->b_blkno / blks, buf->b_udf_c_type,
|
||||
buf->b_resid, buf->b_bcount, buf->b_bufsize));
|
||||
VOP_STRATEGY(ump->devvp, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* (sectorsize == lb_size) for UDF */
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
blknr = buf->b_blkno;
|
||||
our_sectornr = blknr / blks;
|
||||
|
||||
if (queue == UDF_SHED_WRITING) {
|
||||
DPRINTF(SHEDULE, ("\nudf_issue_buf WRITE %p : sector %d "
|
||||
"type %d, b_resid %d, b_bcount %d, b_bufsize %d\n",
|
||||
buf, (uint32_t) buf->b_blkno / blks, buf->b_udf_c_type,
|
||||
buf->b_resid, buf->b_bcount, buf->b_bufsize));
|
||||
/* if we have FIDs fixup using buffer's sector number(s) */
|
||||
if (buf->b_udf_c_type == UDF_C_FIDS) {
|
||||
panic("UDF_C_FIDS in SHED_WRITING!\n");
|
||||
buf_len = buf->b_bcount;
|
||||
sectornr = our_sectornr;
|
||||
bpos = 0;
|
||||
while (buf_len) {
|
||||
len = MIN(buf_len, sector_size);
|
||||
fidblk = (uint8_t *) buf->b_data + bpos;
|
||||
udf_fixup_fid_block(fidblk, sector_size,
|
||||
0, len, sectornr);
|
||||
sectornr++;
|
||||
bpos += len;
|
||||
buf_len -= len;
|
||||
}
|
||||
}
|
||||
udf_fixup_node_internals(ump, buf->b_data, buf->b_udf_c_type);
|
||||
VOP_STRATEGY(ump->devvp, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* UDF_SHED_SEQWRITING */
|
||||
KASSERT(queue == UDF_SHED_SEQWRITING);
|
||||
DPRINTF(SHEDULE, ("\nudf_issue_buf SEQWRITE %p : sector XXXX "
|
||||
"type %d, b_resid %d, b_bcount %d, b_bufsize %d\n",
|
||||
buf, buf->b_udf_c_type, buf->b_resid, buf->b_bcount,
|
||||
buf->b_bufsize));
|
||||
|
||||
/*
|
||||
* Buffers should not have been allocated to disc addresses yet on
|
||||
* this queue. Note that a buffer can get multiple extents allocated.
|
||||
*
|
||||
* lmapping contains lb_num relative to base partition.
|
||||
* pmapping contains lb_num as used for disc adressing.
|
||||
*/
|
||||
lmapping = ump->la_lmapping;
|
||||
pmapping = ump->la_pmapping;
|
||||
node_ad_cpy = ump->la_node_ad_cpy;
|
||||
|
||||
/* write physical blocknr in buf and get its mappings */
|
||||
udf_late_allocate_buf(ump, buf, lmapping, pmapping, node_ad_cpy);
|
||||
|
||||
/* if we have FIDs, fixup using the new allocation table */
|
||||
if (buf->b_udf_c_type == UDF_C_FIDS) {
|
||||
buf_len = buf->b_bcount;
|
||||
bpos = 0;
|
||||
lmappos = lmapping;
|
||||
while (buf_len) {
|
||||
sectornr = *lmappos++;
|
||||
len = MIN(buf_len, sector_size);
|
||||
fidblk = (uint8_t *) buf->b_data + bpos;
|
||||
udf_fixup_fid_block(fidblk, sector_size,
|
||||
0, len, sectornr);
|
||||
bpos += len;
|
||||
buf_len -= len;
|
||||
}
|
||||
}
|
||||
udf_fixup_node_internals(ump, buf->b_data, buf->b_udf_c_type);
|
||||
|
||||
/* speed up : try to conglomerate as many writes in one go */
|
||||
sectors = (buf->b_bcount + sector_size -1) / sector_size;
|
||||
for (sector = 0; sector < sectors; sector++) {
|
||||
buf_offset = sector * sector_size;
|
||||
DPRINTF(WRITE, ("\tprocessing rel sector %d\n", sector));
|
||||
|
||||
DPRINTF(WRITE, ("\tissue write sector %"PRIu64"\n",
|
||||
pmapping[sector]));
|
||||
|
||||
run_start = pmapping[sector];
|
||||
run_length = 1;
|
||||
while (sector < sectors-1) {
|
||||
if (pmapping[sector+1] != pmapping[sector]+1)
|
||||
break;
|
||||
run_length++;
|
||||
sector++;
|
||||
}
|
||||
|
||||
/* nest an iobuf for the extent */
|
||||
rbuflen = run_length * sector_size;
|
||||
rblk = run_start * (sector_size/DEV_BSIZE);
|
||||
|
||||
nestbuf = getiobuf(NULL, true);
|
||||
nestiobuf_setup(buf, nestbuf, buf_offset, rbuflen);
|
||||
/* nestbuf is B_ASYNC */
|
||||
|
||||
/* identify this nestbuf */
|
||||
nestbuf->b_lblkno = sector;
|
||||
assert(nestbuf->b_vp == buf->b_vp);
|
||||
|
||||
/* CD shedules on raw blkno */
|
||||
nestbuf->b_blkno = rblk;
|
||||
nestbuf->b_proc = NULL;
|
||||
nestbuf->b_rawblkno = rblk;
|
||||
nestbuf->b_udf_c_type = UDF_C_PROCESSED;
|
||||
|
||||
VOP_STRATEGY(ump->devvp, nestbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_discstrat_init_direct(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
uint32_t lb_size;
|
||||
|
||||
KASSERT(priv == NULL);
|
||||
ump->strategy_private = malloc(sizeof(struct strat_private),
|
||||
M_UDFTEMP, M_WAITOK);
|
||||
priv = ump->strategy_private;
|
||||
memset(priv, 0 , sizeof(struct strat_private));
|
||||
|
||||
/*
|
||||
* Initialise pool for descriptors associated with nodes. This is done
|
||||
* in lb_size units though currently lb_size is dictated to be
|
||||
* sector_size.
|
||||
*/
|
||||
memset(&priv->desc_pool, 0, sizeof(struct pool));
|
||||
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
pool_init(&priv->desc_pool, lb_size, 0, 0, 0, "udf_desc_pool", NULL,
|
||||
IPL_NONE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_discstrat_finish_direct(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
|
||||
/* destroy our pool */
|
||||
pool_destroy(&priv->desc_pool);
|
||||
|
||||
/* free our private space */
|
||||
free(ump->strategy_private, M_UDFTEMP);
|
||||
ump->strategy_private = NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
struct udf_strategy udf_strat_direct =
|
||||
{
|
||||
udf_getblank_nodedscr_direct,
|
||||
udf_free_nodedscr_direct,
|
||||
udf_read_nodedscr_direct,
|
||||
udf_write_nodedscr_direct,
|
||||
udf_queue_buf_direct,
|
||||
udf_discstrat_init_direct,
|
||||
udf_discstrat_finish_direct
|
||||
};
|
||||
|
1401
sys/fs/udf/udf_strat_rmw.c
Normal file
1401
sys/fs/udf/udf_strat_rmw.c
Normal file
File diff suppressed because it is too large
Load Diff
696
sys/fs/udf/udf_strat_sequential.c
Normal file
696
sys/fs/udf/udf_strat_sequential.c
Normal file
@ -0,0 +1,696 @@
|
||||
/* $NetBSD: udf_strat_sequential.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_quota.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <dev/clock_subr.h>
|
||||
|
||||
#include <fs/udf/ecma167-udf.h>
|
||||
#include <fs/udf/udf_mount.h>
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_udf.h"
|
||||
#endif
|
||||
|
||||
#include "udf.h"
|
||||
#include "udf_subr.h"
|
||||
#include "udf_bswap.h"
|
||||
|
||||
|
||||
#define VTOI(vnode) ((struct udf_node *) vnode->v_data)
|
||||
#define PRIV(ump) ((struct strat_private *) ump->strategy_private)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* BUFQ's */
|
||||
#define UDF_SHED_MAX 3
|
||||
|
||||
#define UDF_SHED_READING 0
|
||||
#define UDF_SHED_WRITING 1
|
||||
#define UDF_SHED_SEQWRITING 2
|
||||
|
||||
struct strat_private {
|
||||
struct pool desc_pool; /* node descriptors */
|
||||
|
||||
lwp_t *queue_lwp;
|
||||
kcondvar_t discstrat_cv; /* to wait on */
|
||||
kmutex_t discstrat_mutex; /* disc strategy */
|
||||
|
||||
int run_thread; /* thread control */
|
||||
int cur_queue;
|
||||
|
||||
struct disk_strategy old_strategy_setting;
|
||||
struct bufq_state *queues[UDF_SHED_MAX];
|
||||
struct timespec last_queued[UDF_SHED_MAX];
|
||||
};
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
udf_wr_nodedscr_callback(struct buf *buf)
|
||||
{
|
||||
struct udf_node *udf_node;
|
||||
|
||||
KASSERT(buf);
|
||||
KASSERT(buf->b_data);
|
||||
|
||||
/* called when write action is done */
|
||||
DPRINTF(WRITE, ("udf_wr_nodedscr_callback(): node written out\n"));
|
||||
|
||||
udf_node = VTOI(buf->b_vp);
|
||||
if (udf_node == NULL) {
|
||||
putiobuf(buf);
|
||||
printf("udf_wr_node_callback: NULL node?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX noone is waiting on this outstanding_nodedscr */
|
||||
udf_node->outstanding_nodedscr--;
|
||||
if (udf_node->outstanding_nodedscr == 0)
|
||||
wakeup(&udf_node->outstanding_nodedscr);
|
||||
|
||||
/* XXX right flags to mark dirty again on error? */
|
||||
if (buf->b_error) {
|
||||
udf_node->i_flags |= IN_MODIFIED | IN_ACCESSED;
|
||||
/* XXX TODO reshedule on error */
|
||||
}
|
||||
|
||||
/* first unlock the node */
|
||||
KASSERT(udf_node->i_flags & IN_CALLBACK_ULK);
|
||||
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
|
||||
|
||||
/* unreference the vnode so it can be recycled */
|
||||
holdrele(udf_node->vnode);
|
||||
|
||||
putiobuf(buf);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
udf_create_logvol_dscr_seq(struct udf_strat_args *args)
|
||||
{
|
||||
union dscrptr **dscrptr = &args->dscr;
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
uint32_t lb_size;
|
||||
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
*dscrptr = pool_get(&priv->desc_pool, PR_WAITOK);
|
||||
memset(*dscrptr, 0, lb_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_free_logvol_dscr_seq(struct udf_strat_args *args)
|
||||
{
|
||||
union dscrptr *dscr = args->dscr;
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
|
||||
pool_put(&priv->desc_pool, dscr);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_read_logvol_dscr_seq(struct udf_strat_args *args)
|
||||
{
|
||||
union dscrptr **dscrptr = &args->dscr;
|
||||
union dscrptr *tmpdscr;
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct long_ad *icb = args->icb;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
uint32_t lb_size;
|
||||
uint32_t sector, dummy;
|
||||
int error;
|
||||
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
|
||||
error = udf_translate_vtop(ump, icb, §or, &dummy);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* try to read in fe/efe */
|
||||
error = udf_read_phys_dscr(ump, sector, M_UDFTEMP, &tmpdscr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
*dscrptr = pool_get(&priv->desc_pool, PR_WAITOK);
|
||||
memcpy(*dscrptr, tmpdscr, lb_size);
|
||||
free(tmpdscr, M_UDFTEMP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_write_logvol_dscr_seq(struct udf_strat_args *args)
|
||||
{
|
||||
union dscrptr *dscr = args->dscr;
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct udf_node *udf_node = args->udf_node;
|
||||
struct long_ad *icb = args->icb;
|
||||
int waitfor = args->waitfor;
|
||||
uint32_t logsectornr, sectornr, dummy;
|
||||
int error, vpart;
|
||||
|
||||
/*
|
||||
* we have to decide if we write it out sequential or at its fixed
|
||||
* position by examining the partition its (to be) written on.
|
||||
*/
|
||||
vpart = udf_rw16(udf_node->loc.loc.part_num);
|
||||
logsectornr = udf_rw32(icb->loc.lb_num);
|
||||
sectornr = 0;
|
||||
if (ump->vtop_tp[vpart] != UDF_VTOP_TYPE_VIRT) {
|
||||
error = udf_translate_vtop(ump, icb, §ornr, &dummy);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
UDF_LOCK_NODE(udf_node, IN_CALLBACK_ULK);
|
||||
|
||||
if (waitfor) {
|
||||
DPRINTF(WRITE, ("udf_write_logvol_dscr: sync write\n"));
|
||||
|
||||
error = udf_write_phys_dscr_sync(ump, udf_node, UDF_C_NODE,
|
||||
dscr, sectornr, logsectornr);
|
||||
UDF_UNLOCK_NODE(udf_node, IN_CALLBACK_ULK);
|
||||
} else {
|
||||
DPRINTF(WRITE, ("udf_write_logvol_dscr: no wait, async write\n"));
|
||||
|
||||
/* add reference to the vnode to prevent recycling */
|
||||
vhold(udf_node->vnode);
|
||||
|
||||
udf_node->outstanding_nodedscr++;
|
||||
|
||||
error = udf_write_phys_dscr_async(ump, udf_node, UDF_C_NODE,
|
||||
dscr, sectornr, logsectornr, udf_wr_nodedscr_callback);
|
||||
/* will be UNLOCKED in call back */
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Main file-system specific sheduler. Due to the nature of optical media
|
||||
* sheduling can't be performed in the traditional way. Most OS
|
||||
* implementations i've seen thus read or write a file atomically giving all
|
||||
* kinds of side effects.
|
||||
*
|
||||
* This implementation uses a kernel thread to shedule the queued requests in
|
||||
* such a way that is semi-optimal for optical media; this means aproximately
|
||||
* (R*|(Wr*|Ws*))* since switching between reading and writing is expensive in
|
||||
* time.
|
||||
*/
|
||||
|
||||
static void
|
||||
udf_queuebuf_seq(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct buf *nestbuf = args->nestbuf;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
int queue;
|
||||
int what;
|
||||
|
||||
KASSERT(ump);
|
||||
KASSERT(nestbuf);
|
||||
KASSERT(nestbuf->b_iodone == nestiobuf_iodone);
|
||||
|
||||
what = nestbuf->b_udf_c_type;
|
||||
queue = UDF_SHED_READING;
|
||||
if ((nestbuf->b_flags & B_READ) == 0) {
|
||||
/* writing */
|
||||
queue = UDF_SHED_SEQWRITING;
|
||||
if (what == UDF_C_DSCR)
|
||||
queue = UDF_SHED_WRITING;
|
||||
if (what == UDF_C_NODE) {
|
||||
if (ump->meta_alloc != UDF_ALLOC_VAT)
|
||||
queue = UDF_SHED_WRITING;
|
||||
}
|
||||
#if 0
|
||||
if (queue == UDF_SHED_SEQWRITING) {
|
||||
/* TODO do add sector to uncommitted space */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* use our own sheduler lists for more complex sheduling */
|
||||
mutex_enter(&priv->discstrat_mutex);
|
||||
BUFQ_PUT(priv->queues[queue], nestbuf);
|
||||
vfs_timestamp(&priv->last_queued[queue]);
|
||||
mutex_exit(&priv->discstrat_mutex);
|
||||
|
||||
/* signal our thread that there might be something to do */
|
||||
cv_signal(&priv->discstrat_cv);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* TODO convert to lb_size */
|
||||
static void
|
||||
udf_VAT_mapping_update(struct udf_mount *ump, struct buf *buf)
|
||||
{
|
||||
union dscrptr *fdscr = (union dscrptr *) buf->b_data;
|
||||
struct vnode *vp = buf->b_vp;
|
||||
struct udf_node *udf_node = VTOI(vp);
|
||||
struct part_desc *pdesc;
|
||||
uint32_t lb_size, blks;
|
||||
uint32_t lb_num, lb_map;
|
||||
uint32_t udf_rw32_lbmap;
|
||||
int c_type = buf->b_udf_c_type;
|
||||
int error;
|
||||
|
||||
/* only interested when we're using a VAT */
|
||||
if (ump->meta_alloc != UDF_ALLOC_VAT)
|
||||
return;
|
||||
KASSERT(ump->vat_node);
|
||||
|
||||
/* only nodes are recorded in the VAT */
|
||||
/* NOTE: and the fileset descriptor (FIXME ?) */
|
||||
if (c_type != UDF_C_NODE)
|
||||
return;
|
||||
|
||||
/* we now have an UDF FE/EFE node on media with VAT (or VAT itself) */
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
blks = lb_size / DEV_BSIZE;
|
||||
|
||||
/* calculate offset from base partition */
|
||||
pdesc = ump->partitions[ump->vtop[ump->metadata_part]];
|
||||
lb_map = buf->b_blkno / blks;
|
||||
lb_map -= udf_rw32(pdesc->start_loc);
|
||||
|
||||
udf_rw32_lbmap = udf_rw32(lb_map);
|
||||
|
||||
/* if we're the VAT itself, only update our assigned sector number */
|
||||
if (udf_node == ump->vat_node) {
|
||||
fdscr->tag.tag_loc = udf_rw32_lbmap;
|
||||
udf_validate_tag_sum(fdscr);
|
||||
DPRINTF(TRANSLATE, ("VAT assigned to sector %u\n",
|
||||
udf_rw32(udf_rw32_lbmap)));
|
||||
/* no use mapping the VAT node in the VAT */
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for tag location is false for allocation extents */
|
||||
KASSERT(fdscr->tag.tag_loc == udf_node->write_loc.loc.lb_num);
|
||||
|
||||
/* record new position in VAT file */
|
||||
lb_num = udf_rw32(udf_node->write_loc.loc.lb_num);
|
||||
|
||||
DPRINTF(TRANSLATE, ("VAT entry change (log %u -> phys %u)\n",
|
||||
lb_num, lb_map));
|
||||
|
||||
/* VAT should be the longer than this write, can't go wrong */
|
||||
KASSERT(lb_num <= ump->vat_entries);
|
||||
|
||||
mutex_enter(&ump->allocate_mutex);
|
||||
error = udf_vat_write(ump->vat_node,
|
||||
(uint8_t *) &udf_rw32_lbmap, 4,
|
||||
ump->vat_offset + lb_num * 4);
|
||||
mutex_exit(&ump->allocate_mutex);
|
||||
|
||||
if (error)
|
||||
panic( "udf_VAT_mapping_update: HELP! i couldn't "
|
||||
"write in the VAT file ?\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_issue_buf(struct udf_mount *ump, int queue, struct buf *buf)
|
||||
{
|
||||
struct long_ad *node_ad_cpy;
|
||||
uint64_t *lmapping, *pmapping, *lmappos, blknr;
|
||||
uint32_t our_sectornr, sectornr, bpos;
|
||||
uint8_t *fidblk;
|
||||
int sector_size = ump->discinfo.sector_size;
|
||||
int blks = sector_size / DEV_BSIZE;
|
||||
int len, buf_len;
|
||||
|
||||
/* if reading, just pass to the device's STRATEGY */
|
||||
if (queue == UDF_SHED_READING) {
|
||||
DPRINTF(SHEDULE, ("\nudf_issue_buf READ %p : sector %d type %d,"
|
||||
"b_resid %d, b_bcount %d, b_bufsize %d\n",
|
||||
buf, (uint32_t) buf->b_blkno / blks, buf->b_udf_c_type,
|
||||
buf->b_resid, buf->b_bcount, buf->b_bufsize));
|
||||
VOP_STRATEGY(ump->devvp, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
blknr = buf->b_blkno;
|
||||
our_sectornr = blknr / blks;
|
||||
|
||||
if (queue == UDF_SHED_WRITING) {
|
||||
DPRINTF(SHEDULE, ("\nudf_issue_buf WRITE %p : sector %d "
|
||||
"type %d, b_resid %d, b_bcount %d, b_bufsize %d\n",
|
||||
buf, (uint32_t) buf->b_blkno / blks, buf->b_udf_c_type,
|
||||
buf->b_resid, buf->b_bcount, buf->b_bufsize));
|
||||
/* if we have FIDs fixup using buffer's sector number(s) */
|
||||
if (buf->b_udf_c_type == UDF_C_FIDS) {
|
||||
panic("UDF_C_FIDS in SHED_WRITING!\n");
|
||||
buf_len = buf->b_bcount;
|
||||
sectornr = our_sectornr;
|
||||
bpos = 0;
|
||||
while (buf_len) {
|
||||
len = MIN(buf_len, sector_size);
|
||||
fidblk = (uint8_t *) buf->b_data + bpos;
|
||||
udf_fixup_fid_block(fidblk, sector_size,
|
||||
0, len, sectornr);
|
||||
sectornr++;
|
||||
bpos += len;
|
||||
buf_len -= len;
|
||||
}
|
||||
}
|
||||
udf_fixup_node_internals(ump, buf->b_data, buf->b_udf_c_type);
|
||||
VOP_STRATEGY(ump->devvp, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
KASSERT(queue == UDF_SHED_SEQWRITING);
|
||||
DPRINTF(SHEDULE, ("\nudf_issue_buf SEQWRITE %p : sector XXXX "
|
||||
"type %d, b_resid %d, b_bcount %d, b_bufsize %d\n",
|
||||
buf, buf->b_udf_c_type, buf->b_resid, buf->b_bcount,
|
||||
buf->b_bufsize));
|
||||
|
||||
/*
|
||||
* Buffers should not have been allocated to disc addresses yet on
|
||||
* this queue. Note that a buffer can get multiple extents allocated.
|
||||
*
|
||||
* lmapping contains lb_num relative to base partition.
|
||||
* pmapping contains lb_num as used for disc adressing.
|
||||
*/
|
||||
lmapping = ump->la_lmapping;
|
||||
pmapping = ump->la_pmapping;
|
||||
node_ad_cpy = ump->la_node_ad_cpy;
|
||||
|
||||
/* allocate buf and get its logical and physical mappings */
|
||||
udf_late_allocate_buf(ump, buf, lmapping, pmapping, node_ad_cpy);
|
||||
udf_VAT_mapping_update(ump, buf); /* XXX could pass *lmapping */
|
||||
|
||||
/* if we have FIDs, fixup using the new allocation table */
|
||||
if (buf->b_udf_c_type == UDF_C_FIDS) {
|
||||
buf_len = buf->b_bcount;
|
||||
bpos = 0;
|
||||
lmappos = lmapping;
|
||||
while (buf_len) {
|
||||
sectornr = *lmappos++;
|
||||
len = MIN(buf_len, sector_size);
|
||||
fidblk = (uint8_t *) buf->b_data + bpos;
|
||||
udf_fixup_fid_block(fidblk, sector_size,
|
||||
0, len, sectornr);
|
||||
bpos += len;
|
||||
buf_len -= len;
|
||||
}
|
||||
}
|
||||
udf_fixup_node_internals(ump, buf->b_data, buf->b_udf_c_type);
|
||||
VOP_STRATEGY(ump->devvp, buf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_doshedule(struct udf_mount *ump)
|
||||
{
|
||||
struct buf *buf;
|
||||
struct timespec now, *last;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
void (*b_callback)(struct buf *);
|
||||
int new_queue;
|
||||
int error;
|
||||
|
||||
buf = BUFQ_GET(priv->queues[priv->cur_queue]);
|
||||
if (buf) {
|
||||
/* transfer from the current queue to the device queue */
|
||||
mutex_exit(&priv->discstrat_mutex);
|
||||
|
||||
/* transform buffer to synchronous; XXX needed? */
|
||||
b_callback = buf->b_iodone;
|
||||
buf->b_iodone = NULL;
|
||||
CLR(buf->b_flags, B_ASYNC);
|
||||
|
||||
/* issue and wait on completion */
|
||||
udf_issue_buf(ump, priv->cur_queue, buf);
|
||||
biowait(buf);
|
||||
|
||||
mutex_enter(&priv->discstrat_mutex);
|
||||
|
||||
/* if there is an error, repair this error, otherwise propagate */
|
||||
if (buf->b_error && ((buf->b_flags & B_READ) == 0)) {
|
||||
/* check what we need to do */
|
||||
panic("UDF write error, can't handle yet!\n");
|
||||
}
|
||||
|
||||
/* propagate result to higher layers */
|
||||
if (b_callback) {
|
||||
buf->b_iodone = b_callback;
|
||||
(*buf->b_iodone)(buf);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we're idling in this state */
|
||||
vfs_timestamp(&now);
|
||||
last = &priv->last_queued[priv->cur_queue];
|
||||
if (ump->discinfo.mmc_class == MMC_CLASS_CD) {
|
||||
/* dont switch too fast for CD media; its expensive in time */
|
||||
if (now.tv_sec - last->tv_sec < 3)
|
||||
return;
|
||||
}
|
||||
|
||||
/* check if we can/should switch */
|
||||
new_queue = priv->cur_queue;
|
||||
|
||||
if (BUFQ_PEEK(priv->queues[UDF_SHED_READING]))
|
||||
new_queue = UDF_SHED_READING;
|
||||
if (BUFQ_PEEK(priv->queues[UDF_SHED_SEQWRITING]))
|
||||
new_queue = UDF_SHED_SEQWRITING;
|
||||
if (BUFQ_PEEK(priv->queues[UDF_SHED_WRITING])) /* only for unmount */
|
||||
new_queue = UDF_SHED_WRITING;
|
||||
if (priv->cur_queue == UDF_SHED_READING) {
|
||||
if (new_queue == UDF_SHED_SEQWRITING) {
|
||||
/* TODO use flag to signal if this is needed */
|
||||
mutex_exit(&priv->discstrat_mutex);
|
||||
|
||||
/* update trackinfo for data and metadata */
|
||||
error = udf_update_trackinfo(ump,
|
||||
&ump->data_track);
|
||||
assert(error == 0);
|
||||
error = udf_update_trackinfo(ump,
|
||||
&ump->metadata_track);
|
||||
assert(error == 0);
|
||||
mutex_enter(&priv->discstrat_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_queue != priv->cur_queue) {
|
||||
DPRINTF(SHEDULE, ("switching from %d to %d\n",
|
||||
priv->cur_queue, new_queue));
|
||||
}
|
||||
|
||||
priv->cur_queue = new_queue;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_discstrat_thread(void *arg)
|
||||
{
|
||||
struct udf_mount *ump = (struct udf_mount *) arg;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
int empty;
|
||||
|
||||
empty = 1;
|
||||
mutex_enter(&priv->discstrat_mutex);
|
||||
while (priv->run_thread || !empty) {
|
||||
/* process the current selected queue */
|
||||
udf_doshedule(ump);
|
||||
empty = (BUFQ_PEEK(priv->queues[UDF_SHED_READING]) == NULL);
|
||||
empty &= (BUFQ_PEEK(priv->queues[UDF_SHED_WRITING]) == NULL);
|
||||
empty &= (BUFQ_PEEK(priv->queues[UDF_SHED_SEQWRITING]) == NULL);
|
||||
|
||||
/* wait for more if needed */
|
||||
if (empty)
|
||||
cv_timedwait(&priv->discstrat_cv,
|
||||
&priv->discstrat_mutex, hz/8);
|
||||
}
|
||||
mutex_exit(&priv->discstrat_mutex);
|
||||
|
||||
wakeup(&priv->run_thread);
|
||||
kthread_exit(0);
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
udf_discstrat_init_seq(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
struct disk_strategy dkstrat;
|
||||
uint32_t lb_size;
|
||||
|
||||
KASSERT(ump);
|
||||
KASSERT(ump->logical_vol);
|
||||
KASSERT(priv == NULL);
|
||||
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
KASSERT(lb_size > 0);
|
||||
|
||||
/* initialise our memory space */
|
||||
ump->strategy_private = malloc(sizeof(struct strat_private),
|
||||
M_UDFTEMP, M_WAITOK);
|
||||
priv = ump->strategy_private;
|
||||
memset(priv, 0 , sizeof(struct strat_private));
|
||||
|
||||
/* initialise locks */
|
||||
cv_init(&priv->discstrat_cv, "udfstrat");
|
||||
mutex_init(&priv->discstrat_mutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
/*
|
||||
* Initialise pool for descriptors associated with nodes. This is done
|
||||
* in lb_size units though currently lb_size is dictated to be
|
||||
* sector_size.
|
||||
*/
|
||||
pool_init(&priv->desc_pool, lb_size, 0, 0, 0, "udf_desc_pool", NULL,
|
||||
IPL_NONE);
|
||||
|
||||
/*
|
||||
* remember old device strategy method and explicit set method
|
||||
* `discsort' since we have our own more complex strategy that is not
|
||||
* implementable on the CD device and other strategies will get in the
|
||||
* way.
|
||||
*/
|
||||
memset(&priv->old_strategy_setting, 0,
|
||||
sizeof(struct disk_strategy));
|
||||
VOP_IOCTL(ump->devvp, DIOCGSTRATEGY, &priv->old_strategy_setting,
|
||||
FREAD | FKIOCTL, NOCRED);
|
||||
memset(&dkstrat, 0, sizeof(struct disk_strategy));
|
||||
strcpy(dkstrat.dks_name, "discsort");
|
||||
VOP_IOCTL(ump->devvp, DIOCSSTRATEGY, &dkstrat, FWRITE | FKIOCTL,
|
||||
NOCRED);
|
||||
|
||||
/* initialise our internal sheduler */
|
||||
priv->cur_queue = UDF_SHED_READING;
|
||||
bufq_alloc(&priv->queues[UDF_SHED_READING], "disksort",
|
||||
BUFQ_SORT_RAWBLOCK);
|
||||
bufq_alloc(&priv->queues[UDF_SHED_WRITING], "disksort",
|
||||
BUFQ_SORT_RAWBLOCK);
|
||||
bufq_alloc(&priv->queues[UDF_SHED_SEQWRITING], "fcfs", 0);
|
||||
vfs_timestamp(&priv->last_queued[UDF_SHED_READING]);
|
||||
vfs_timestamp(&priv->last_queued[UDF_SHED_WRITING]);
|
||||
vfs_timestamp(&priv->last_queued[UDF_SHED_SEQWRITING]);
|
||||
|
||||
/* create our disk strategy thread */
|
||||
priv->run_thread = 1;
|
||||
if (kthread_create(PRI_NONE, 0 /* KTHREAD_MPSAFE*/, NULL /* cpu_info*/,
|
||||
udf_discstrat_thread, ump, &priv->queue_lwp,
|
||||
"%s", "udf_rw")) {
|
||||
panic("fork udf_rw");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udf_discstrat_finish_seq(struct udf_strat_args *args)
|
||||
{
|
||||
struct udf_mount *ump = args->ump;
|
||||
struct strat_private *priv = PRIV(ump);
|
||||
int error;
|
||||
|
||||
if (ump == NULL)
|
||||
return;
|
||||
|
||||
/* stop our sheduling thread */
|
||||
KASSERT(priv->run_thread == 1);
|
||||
priv->run_thread = 0;
|
||||
wakeup(priv->queue_lwp);
|
||||
do {
|
||||
error = tsleep(&priv->run_thread, PRIBIO+1,
|
||||
"udfshedfin", hz);
|
||||
} while (error);
|
||||
/* kthread should be finished now */
|
||||
|
||||
/* set back old device strategy method */
|
||||
VOP_IOCTL(ump->devvp, DIOCSSTRATEGY, &priv->old_strategy_setting,
|
||||
FWRITE, NOCRED);
|
||||
|
||||
/* destroy our pool */
|
||||
pool_destroy(&priv->desc_pool);
|
||||
|
||||
/* free our private space */
|
||||
free(ump->strategy_private, M_UDFTEMP);
|
||||
ump->strategy_private = NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
struct udf_strategy udf_strat_sequential =
|
||||
{
|
||||
udf_create_logvol_dscr_seq,
|
||||
udf_free_logvol_dscr_seq,
|
||||
udf_read_logvol_dscr_seq,
|
||||
udf_write_logvol_dscr_seq,
|
||||
udf_queuebuf_seq,
|
||||
udf_discstrat_init_seq,
|
||||
udf_discstrat_finish_seq
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: udf_subr.h,v 1.4 2006/03/05 16:55:44 christos Exp $ */
|
||||
/* $NetBSD: udf_subr.h,v 1.5 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Reinoud Zandijk
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -12,13 +12,6 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the
|
||||
* NetBSD Project. See http://www.NetBSD.org/ for
|
||||
* information about NetBSD.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
@ -33,52 +26,157 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FS_UDF_UDF_SUBR_H_
|
||||
#define _FS_UDF_UDF_SUBR_H_
|
||||
|
||||
/* handies */
|
||||
#define VFSTOUDF(mp) ((struct udf_mount *)mp->mnt_data)
|
||||
|
||||
|
||||
/* device information updating */
|
||||
int udf_update_trackinfo(struct udf_mount *ump, struct mmc_trackinfo *trackinfo);
|
||||
int udf_update_discinfo(struct udf_mount *ump);
|
||||
int udf_search_tracks(struct udf_mount *ump, struct udf_args *args,
|
||||
int *first_tracknr, int *last_tracknr);
|
||||
int udf_search_writing_tracks(struct udf_mount *ump);
|
||||
int udf_setup_writeparams(struct udf_mount *ump);
|
||||
int udf_synchronise_caches(struct udf_mount *ump);
|
||||
|
||||
/* tags and read/write descriptors */
|
||||
/* tags operations */
|
||||
int udf_fidsize(struct fileid_desc *fid);
|
||||
int udf_check_tag(void *blob);
|
||||
int udf_check_tag_payload(void *blob, uint32_t max_length);
|
||||
int udf_validate_tag_sum(void *blob);
|
||||
int udf_validate_tag_and_crc_sums(void *blob);
|
||||
void udf_validate_tag_sum(void *blob);
|
||||
void udf_validate_tag_and_crc_sums(void *blob);
|
||||
int udf_tagsize(union dscrptr *dscr, uint32_t udf_sector_size);
|
||||
|
||||
int udf_read_descriptor(
|
||||
/* read/write descriptors */
|
||||
int udf_read_phys_dscr(
|
||||
struct udf_mount *ump,
|
||||
uint32_t sector,
|
||||
struct malloc_type *mtype, /* where to allocate */
|
||||
union dscrptr **dstp); /* out */
|
||||
|
||||
int udf_write_phys_dscr_sync(struct udf_mount *ump, struct udf_node *udf_node,
|
||||
int what, union dscrptr *dscr,
|
||||
uint32_t sector, uint32_t logsector);
|
||||
int udf_write_phys_dscr_async(struct udf_mount *ump, struct udf_node *udf_node,
|
||||
int what, union dscrptr *dscr,
|
||||
uint32_t sector, uint32_t logsector,
|
||||
void (*dscrwr_callback)(struct buf *));
|
||||
|
||||
/* read/write node descriptors */
|
||||
int udf_create_logvol_dscr(struct udf_mount *ump, struct udf_node *udf_node,
|
||||
struct long_ad *icb, union dscrptr **dscrptr);
|
||||
void udf_free_logvol_dscr(struct udf_mount *ump, struct long_ad *icb_loc,
|
||||
void *dscr);
|
||||
int udf_read_logvol_dscr(struct udf_mount *ump, struct long_ad *icb,
|
||||
union dscrptr **dscrptr);
|
||||
int udf_write_logvol_dscr(struct udf_node *udf_node, union dscrptr *dscr,
|
||||
struct long_ad *icb, int waitfor);
|
||||
|
||||
|
||||
/* volume descriptors readers and checkers */
|
||||
int udf_read_anchors(struct udf_mount *ump, struct udf_args *args);
|
||||
|
||||
int udf_read_anchors(struct udf_mount *ump);
|
||||
int udf_read_vds_space(struct udf_mount *ump);
|
||||
int udf_process_vds(struct udf_mount *ump, struct udf_args *args);
|
||||
int udf_read_vds_tables(struct udf_mount *ump, struct udf_args *args);
|
||||
int udf_read_rootdirs(struct udf_mount *ump, struct udf_args *args);
|
||||
int udf_process_vds(struct udf_mount *ump);
|
||||
int udf_read_vds_tables(struct udf_mount *ump);
|
||||
int udf_read_rootdirs(struct udf_mount *ump);
|
||||
|
||||
/* open/close and sync volumes */
|
||||
int udf_open_logvol(struct udf_mount *ump);
|
||||
int udf_close_logvol(struct udf_mount *ump, int mntflags);
|
||||
int udf_writeout_vat(struct udf_mount *ump);
|
||||
int udf_write_partition_spacetables(struct udf_mount *ump, int waitfor);
|
||||
void udf_do_sync(struct udf_mount *ump, kauth_cred_t cred, int waitfor);
|
||||
|
||||
/* translation services */
|
||||
int udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc, uint32_t *lb_numres, uint32_t *extres);
|
||||
int udf_translate_file_extent(struct udf_node *node, uint32_t from, uint32_t pages, uint64_t *map);
|
||||
int udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc,
|
||||
uint32_t *lb_numres, uint32_t *extres);
|
||||
int udf_translate_file_extent(struct udf_node *node,
|
||||
uint32_t from, uint32_t num_lb, uint64_t *map);
|
||||
void udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb, int *eof);
|
||||
int udf_append_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb);
|
||||
|
||||
int udf_vat_read(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset);
|
||||
int udf_vat_write(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offset);
|
||||
|
||||
/* disc allocation */
|
||||
void udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, uint64_t *lmapping, uint64_t *pmapping, struct long_ad *node_ad_cpy);
|
||||
void udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, uint16_t vpart_num, uint32_t num_lb);
|
||||
int udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, int num_lb, uint16_t *alloc_partp, uint64_t *lmapping, uint64_t *pmapping);
|
||||
int udf_grow_node(struct udf_node *node, uint64_t new_size);
|
||||
int udf_shrink_node(struct udf_node *node, uint64_t new_size);
|
||||
|
||||
/* node readers and writers */
|
||||
int udf_get_node(struct udf_mount *ump, struct long_ad *icbloc, struct udf_node **noderes);
|
||||
int udf_dispose_node(struct udf_node *node);
|
||||
int udf_dispose_locked_node(struct udf_node *node);
|
||||
void udf_read_filebuf(struct udf_node *node, struct buf *buf);
|
||||
int udf_read_file_extent(struct udf_node *node, uint32_t from, uint32_t sectors, uint8_t *blob);
|
||||
uint64_t udf_advance_uniqueid(struct udf_mount *ump);
|
||||
|
||||
/* directory read and parse utils */
|
||||
void udf_to_unix_name(char *result, char *id, int len, struct charspec *chsp);
|
||||
void unix_to_udf_name(char *result, char *name, uint8_t *result_len, struct charspec *chsp);
|
||||
int udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, struct long_ad *icb_loc);
|
||||
#define UDF_LOCK_NODE(udf_node, flag) udf_lock_node(udf_node, (flag), __FILE__, __LINE__)
|
||||
#define UDF_UNLOCK_NODE(udf_node, flag) udf_unlock_node(udf_node, (flag))
|
||||
void udf_lock_node(struct udf_node *udf_node, int flag, char const *fname, const int lineno);
|
||||
void udf_unlock_node(struct udf_node *udf_node, int flag);
|
||||
|
||||
int udf_get_node(struct udf_mount *ump, struct long_ad *icbloc, struct udf_node **noderes);
|
||||
int udf_writeout_node(struct udf_node *udf_node, int waitfor);
|
||||
int udf_dispose_node(struct udf_node *node);
|
||||
|
||||
/* node ops */
|
||||
int udf_resize_node(struct udf_node *node, uint64_t new_size, int *extended);
|
||||
int udf_extattr_search_intern(struct udf_node *node, uint32_t sattr, char const *sattrname, uint32_t *offsetp, uint32_t *lengthp);
|
||||
|
||||
/* node data buffer read/write */
|
||||
void udf_read_filebuf(struct udf_node *node, struct buf *buf);
|
||||
void udf_write_filebuf(struct udf_node *node, struct buf *buf);
|
||||
void udf_fixup_fid_block(uint8_t *blob, int lb_size, int rfix_pos, int max_rfix_pos, uint32_t lb_num);
|
||||
void udf_fixup_internal_extattr(uint8_t *blob, uint32_t lb_num);
|
||||
void udf_fixup_node_internals(struct udf_mount *ump, uint8_t *blob, int udf_c_type);
|
||||
|
||||
/* device strategy */
|
||||
void udf_discstrat_init(struct udf_mount *ump);
|
||||
void udf_discstrat_finish(struct udf_mount *ump);
|
||||
void udf_discstrat_queuebuf(struct udf_mount *ump, struct buf *nestbuf);
|
||||
|
||||
/* structure writers */
|
||||
int udf_write_terminator(struct udf_mount *ump, uint32_t sector);
|
||||
|
||||
/* structure creators */
|
||||
void udf_set_regid(struct regid *regid, char const *name);
|
||||
void udf_add_domain_regid(struct udf_mount *ump, struct regid *regid);
|
||||
void udf_add_udf_regid(struct udf_mount *ump, struct regid *regid);
|
||||
void udf_add_impl_regid(struct udf_mount *ump, struct regid *regid);
|
||||
void udf_add_app_regid(struct udf_mount *ump, struct regid *regid);
|
||||
|
||||
/* directory operations and helpers */
|
||||
void udf_osta_charset(struct charspec *charspec);
|
||||
int udf_read_fid_stream(struct vnode *vp, uint64_t *offset, struct fileid_desc *fid, struct dirent *dirent);
|
||||
int udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, struct long_ad *icb_loc);
|
||||
int udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, struct componentname *cnp);
|
||||
void udf_delete_node(struct udf_node *udf_node);
|
||||
|
||||
int udf_chsize(struct vnode *vp, u_quad_t newsize, kauth_cred_t cred);
|
||||
int udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node, struct udf_node *udf_node, struct componentname *cnp);
|
||||
int udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node, struct udf_node *udf_node, struct vattr *vap, struct componentname *cnp);
|
||||
|
||||
/* update and times */
|
||||
void udf_add_to_dirtylist(struct udf_node *udf_node);
|
||||
void udf_remove_from_dirtylist(struct udf_node *udf_node);
|
||||
void udf_itimes(struct udf_node *udf_node, struct timespec *acc,
|
||||
struct timespec *mod, struct timespec *changed);
|
||||
int udf_update(struct vnode *node, struct timespec *acc,
|
||||
struct timespec *mod, int updflags);
|
||||
|
||||
/* helpers and converters */
|
||||
long udf_calchash(struct long_ad *icbptr); /* for `inode' numbering */
|
||||
uint32_t udf_getaccessmode(struct udf_node *node);
|
||||
void udf_setaccessmode(struct udf_node *udf_node, mode_t mode);
|
||||
void udf_getownership(struct udf_node *udf_node, uid_t *uidp, gid_t *gidp);
|
||||
void udf_setownership(struct udf_node *udf_node, uid_t uid, gid_t gid);
|
||||
|
||||
void udf_to_unix_name(char *result, char *id, int len, struct charspec *chsp);
|
||||
void unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len, struct charspec *chsp);
|
||||
|
||||
void udf_timestamp_to_timespec(struct udf_mount *ump, struct timestamp *timestamp, struct timespec *timespec);
|
||||
void udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp);
|
||||
|
||||
/* vnode operations */
|
||||
int udf_inactive(void *v);
|
||||
@ -93,7 +191,7 @@ int udf_access(void *v);
|
||||
int udf_read(void *v);
|
||||
int udf_write(void *v);
|
||||
int udf_trivial_bmap(void *v);
|
||||
int udf_strategy(void *v);
|
||||
int udf_vfsstrategy(void *v);
|
||||
int udf_lookup(void *v);
|
||||
int udf_create(void *v);
|
||||
int udf_mknod(void *v);
|
||||
@ -107,10 +205,4 @@ int udf_rmdir(void *v);
|
||||
int udf_fsync(void *v);
|
||||
int udf_advlock(void *v);
|
||||
|
||||
|
||||
/* helpers and converters */
|
||||
long udf_calchash(struct long_ad *icbptr); /* for `inode' numbering */
|
||||
uint32_t udf_getaccessmode(struct udf_node *node);
|
||||
void udf_timestamp_to_timespec(struct udf_mount *ump, struct timestamp *timestamp, struct timespec *timespec);
|
||||
|
||||
#endif /* !_FS_UDF_UDF_SUBR_H_ */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: udf_vfsops.c,v 1.37 2008/05/10 02:26:09 rumble Exp $ */
|
||||
/* $NetBSD: udf_vfsops.c,v 1.38 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Reinoud Zandijk
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -12,13 +12,6 @@
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the
|
||||
* NetBSD Project. See http://www.NetBSD.org/ for
|
||||
* information about NetBSD.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
@ -33,16 +26,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.37 2008/05/10 02:26:09 rumble Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.38 2008/05/14 16:49:48 reinoud Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_quota.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_udf.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -76,6 +69,8 @@ __KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.37 2008/05/10 02:26:09 rumble Exp $
|
||||
|
||||
MODULE(MODULE_CLASS_VFS, udf, NULL);
|
||||
|
||||
#define VTOI(vnode) ((struct udf_node *) vnode->v_data)
|
||||
|
||||
/* verbose levels of the udf filingsystem */
|
||||
int udf_verbose = UDF_DEBUGGING;
|
||||
|
||||
@ -91,13 +86,6 @@ VFS_PROTOS(udf);
|
||||
|
||||
/* internal functions */
|
||||
static int udf_mountfs(struct vnode *, struct mount *, struct lwp *, struct udf_args *);
|
||||
#if 0
|
||||
static int update_mp(struct mount *, struct udf_args *);
|
||||
#endif
|
||||
|
||||
|
||||
/* handies */
|
||||
#define VFSTOUDF(mp) ((struct udf_mount *)mp->mnt_data)
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -140,20 +128,6 @@ struct vfsops udf_vfsops = {
|
||||
{ NULL, NULL, }, /* LIST_ENTRY(vfsops) */
|
||||
};
|
||||
|
||||
static int
|
||||
udf_modcmd(modcmd_t cmd, void *arg)
|
||||
{
|
||||
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
return vfs_attach(&udf_vfsops);
|
||||
case MODULE_CMD_FINI:
|
||||
return vfs_detach(&udf_vfsops);
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* file system starts here */
|
||||
@ -172,7 +146,6 @@ udf_init(void)
|
||||
IPL_NONE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
udf_reinit(void)
|
||||
@ -181,7 +154,6 @@ udf_reinit(void)
|
||||
/* reinit pool? */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
udf_done(void)
|
||||
@ -194,6 +166,21 @@ udf_done(void)
|
||||
malloc_type_detach(M_UDFTEMP);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_modcmd(modcmd_t cmd, void *arg)
|
||||
{
|
||||
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
return vfs_attach(&udf_vfsops);
|
||||
case MODULE_CMD_FINI:
|
||||
return vfs_detach(&udf_vfsops);
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
@ -217,23 +204,6 @@ free_udf_mountinfo(struct mount *mp)
|
||||
|
||||
ump = VFSTOUDF(mp);
|
||||
if (ump) {
|
||||
/* dereference all system nodes */
|
||||
if (ump->metadata_file)
|
||||
vrele(ump->metadata_file->vnode);
|
||||
if (ump->metadatamirror_file)
|
||||
vrele(ump->metadatamirror_file->vnode);
|
||||
if (ump->metadatabitmap_file)
|
||||
vrele(ump->metadatabitmap_file->vnode);
|
||||
|
||||
/* vflush all (system) nodes if any */
|
||||
(void) vflush(mp, NULLVP, FORCECLOSE);
|
||||
|
||||
/* dispose of our descriptor pool */
|
||||
if (ump->desc_pool) {
|
||||
pool_destroy(ump->desc_pool);
|
||||
free(ump->desc_pool, M_UDFMNT);
|
||||
}
|
||||
|
||||
/* clear our data */
|
||||
for (i = 0; i < UDF_ANCHORS; i++)
|
||||
MPFREE(ump->anchors[i], M_UDFVOLD);
|
||||
@ -242,14 +212,25 @@ free_udf_mountinfo(struct mount *mp)
|
||||
MPFREE(ump->unallocated, M_UDFVOLD);
|
||||
MPFREE(ump->implementation, M_UDFVOLD);
|
||||
MPFREE(ump->logvol_integrity, M_UDFVOLD);
|
||||
for (i = 0; i < UDF_PARTITIONS; i++)
|
||||
for (i = 0; i < UDF_PARTITIONS; i++) {
|
||||
MPFREE(ump->partitions[i], M_UDFVOLD);
|
||||
MPFREE(ump->part_unalloc_dscr[i], M_UDFVOLD);
|
||||
MPFREE(ump->part_freed_dscr[i], M_UDFVOLD);
|
||||
}
|
||||
MPFREE(ump->fileset_desc, M_UDFVOLD);
|
||||
MPFREE(ump->vat_table, M_UDFVOLD);
|
||||
MPFREE(ump->sparing_table, M_UDFVOLD);
|
||||
MPFREE(ump->metadata_bitmap.bits, M_UDFVOLD);
|
||||
|
||||
MPFREE(ump->la_node_ad_cpy, M_UDFMNT);
|
||||
MPFREE(ump->la_pmapping, M_TEMP);
|
||||
MPFREE(ump->la_lmapping, M_TEMP);
|
||||
|
||||
mutex_destroy(&ump->ihash_lock);
|
||||
mutex_destroy(&ump->get_node_lock);
|
||||
|
||||
mutex_destroy(&ump->allocate_mutex);
|
||||
MPFREE(ump->vat_table, M_UDFVOLD);
|
||||
|
||||
free(ump, M_UDFMNT);
|
||||
}
|
||||
}
|
||||
@ -257,6 +238,35 @@ free_udf_mountinfo(struct mount *mp)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* if the system nodes exist, release them */
|
||||
static void
|
||||
udf_release_system_nodes(struct mount *mp)
|
||||
{
|
||||
struct udf_mount *ump = VFSTOUDF(mp);
|
||||
int error;
|
||||
|
||||
/* if we haven't even got an ump, dont bother */
|
||||
if (!ump)
|
||||
return;
|
||||
|
||||
/* VAT partition support */
|
||||
if (ump->vat_node)
|
||||
vrele(ump->vat_node->vnode);
|
||||
|
||||
/* Metadata partition support */
|
||||
if (ump->metadata_node)
|
||||
vrele(ump->metadata_node->vnode);
|
||||
if (ump->metadatamirror_node)
|
||||
vrele(ump->metadatamirror_node->vnode);
|
||||
if (ump->metadatabitmap_node)
|
||||
vrele(ump->metadatabitmap_node->vnode);
|
||||
|
||||
/* This flush should NOT write anything nor allow any node to remain */
|
||||
if ((error = vflush(ump->vfs_mountp, NULLVP, 0)) != 0)
|
||||
panic("Failure to flush UDF system vnodes\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
udf_mount(struct mount *mp, const char *path,
|
||||
void *data, size_t *data_len)
|
||||
@ -320,8 +330,14 @@ udf_mount(struct mount *mp, const char *path,
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
#ifndef UDF_READWRITE
|
||||
/* force read-only for now */
|
||||
mp->mnt_flag |= MNT_RDONLY;
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
|
||||
printf("Enable kernel option UDF_READWRITE for writing\n");
|
||||
vrele(devvp);
|
||||
return EROFS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If mount by non-root, then verify that user has necessary
|
||||
@ -353,6 +369,9 @@ udf_mount(struct mount *mp, const char *path,
|
||||
/* opened ok, try mounting */
|
||||
error = udf_mountfs(devvp, mp, l, args);
|
||||
if (error) {
|
||||
udf_release_system_nodes(mp);
|
||||
/* cleanup */
|
||||
udf_discstrat_finish(VFSTOUDF(mp));
|
||||
free_udf_mountinfo(mp);
|
||||
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
|
||||
(void) VOP_CLOSE(devvp, openflags, NOCRED);
|
||||
@ -371,8 +390,23 @@ udf_mount(struct mount *mp, const char *path,
|
||||
/* successfully mounted */
|
||||
DPRINTF(VOLUMES, ("udf_mount() successfull\n"));
|
||||
|
||||
return set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
|
||||
error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
|
||||
mp->mnt_op->vfs_name, mp, l);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* If we're not opened read-only, open its logical volume */
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
|
||||
if ((error = udf_open_logvol(VFSTOUDF(mp))) != 0) {
|
||||
printf( "mount_udf: can't open logical volume for "
|
||||
"writing,downgrading access to read-only\n");
|
||||
mp->mnt_flag |= MNT_RDONLY;
|
||||
/* FIXME we can't return error now on open failure */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -423,16 +457,38 @@ udf_unmount(struct mount *mp, int mntflags)
|
||||
if ((error = vflush(mp, NULLVP, flags | SKIPSYSTEM)) != 0)
|
||||
return error;
|
||||
|
||||
/* update nodes and wait for completion of writeout of system nodes */
|
||||
udf_sync(mp, FSYNC_WAIT, NOCRED);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (udf_verbose & UDF_DEBUG_LOCKING)
|
||||
udf_unmount_sanity_check(mp);
|
||||
#endif
|
||||
|
||||
DPRINTF(VOLUMES, ("flush OK\n"));
|
||||
/* flush again, to check if we are still busy for something else */
|
||||
if ((error = vflush(ump->vfs_mountp, NULLVP, flags | SKIPSYSTEM)) != 0)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* TODO close logical volume and close session if requested.
|
||||
*/
|
||||
DPRINTF(VOLUMES, ("flush OK on unmount\n"));
|
||||
|
||||
/* close logical volume and close session if requested */
|
||||
if ((error = udf_close_logvol(ump, mntflags)) != 0)
|
||||
return error;
|
||||
|
||||
#ifdef DEBUG
|
||||
DPRINTF(VOLUMES, ("FINAL sanity check\n"));
|
||||
if (udf_verbose & UDF_DEBUG_LOCKING)
|
||||
udf_unmount_sanity_check(mp);
|
||||
#endif
|
||||
|
||||
/* NOTE release system nodes should NOT write anything */
|
||||
udf_release_system_nodes(mp);
|
||||
|
||||
/* finalise disc strategy */
|
||||
udf_discstrat_finish(ump);
|
||||
|
||||
/* synchronise device caches */
|
||||
(void) udf_synchronise_caches(ump);
|
||||
|
||||
/* close device */
|
||||
DPRINTF(VOLUMES, ("closing device\n"));
|
||||
@ -454,10 +510,10 @@ udf_unmount(struct mount *mp, int mntflags)
|
||||
ump->devvp->v_specmountpoint = NULL;
|
||||
vput(ump->devvp);
|
||||
|
||||
/* free up umt structure */
|
||||
/* free our ump */
|
||||
free_udf_mountinfo(mp);
|
||||
|
||||
/* free ump struct reference */
|
||||
/* free ump struct references */
|
||||
mp->mnt_data = NULL;
|
||||
mp->mnt_flag &= ~MNT_LOCAL;
|
||||
|
||||
@ -477,20 +533,32 @@ udf_mountfs(struct vnode *devvp, struct mount *mp,
|
||||
{
|
||||
struct udf_mount *ump;
|
||||
uint32_t sector_size, lb_size, bshift;
|
||||
uint32_t logvol_integrity;
|
||||
int num_anchors, error, lst;
|
||||
|
||||
/* flush out any old buffers remaining from a previous use. */
|
||||
if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)))
|
||||
return error;
|
||||
|
||||
/* setup basic mount information */
|
||||
mp->mnt_data = NULL;
|
||||
mp->mnt_stat.f_fsidx.__fsid_val[0] = (uint32_t) devvp->v_rdev;
|
||||
mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_UDF);
|
||||
mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
|
||||
mp->mnt_stat.f_namemax = UDF_MAX_NAMELEN;
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
|
||||
/* allocate udf part of mount structure; malloc always succeeds */
|
||||
ump = malloc(sizeof(struct udf_mount), M_UDFMNT, M_WAITOK | M_ZERO);
|
||||
|
||||
/* init locks */
|
||||
mutex_init(&ump->logvol_mutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
mutex_init(&ump->ihash_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
mutex_init(&ump->get_node_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
mutex_init(&ump->allocate_mutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
cv_init(&ump->dirtynodes_cv, "udfsync2");
|
||||
|
||||
/* init `ino_t' to udf_node hash table */
|
||||
/* init `ino_t' to udf_node hash table and other lists */
|
||||
for (lst = 0; lst < UDF_INODE_HASHSIZE; lst++) {
|
||||
LIST_INIT(&ump->udf_nodes[lst]);
|
||||
}
|
||||
@ -518,10 +586,29 @@ udf_mountfs(struct vnode *devvp, struct mount *mp,
|
||||
return EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inspect if we're asked to mount read-write on a non recordable or
|
||||
* closed sequential disc.
|
||||
*/
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
|
||||
if ((ump->discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
|
||||
printf("UDF mount: disc is not recordable\n");
|
||||
return EROFS;
|
||||
}
|
||||
/*
|
||||
* TODO if on sequential media and last session is closed,
|
||||
* check for enough space to open/close new session
|
||||
*/
|
||||
}
|
||||
|
||||
/* initialise bootstrap disc strategy */
|
||||
ump->strategy = &udf_strat_bootstrap;
|
||||
udf_discstrat_init(ump);
|
||||
|
||||
/* read all anchors to get volume descriptor sequence */
|
||||
num_anchors = udf_read_anchors(ump, args);
|
||||
num_anchors = udf_read_anchors(ump);
|
||||
if (num_anchors == 0)
|
||||
return ENOENT;
|
||||
return EINVAL;
|
||||
|
||||
DPRINTF(VOLUMES, ("Read %d anchors on this disc, session %d\n",
|
||||
num_anchors, args->sessionnr));
|
||||
@ -532,50 +619,63 @@ udf_mountfs(struct vnode *devvp, struct mount *mp,
|
||||
return error;
|
||||
}
|
||||
|
||||
/* close down (direct) disc strategy */
|
||||
udf_discstrat_finish(ump);
|
||||
|
||||
/* check consistency and completeness */
|
||||
if ((error = udf_process_vds(ump, args))) {
|
||||
if ((error = udf_process_vds(ump))) {
|
||||
printf( "UDF mount: disc not properly formatted"
|
||||
"(bad VDS)\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise pool for descriptors associated with nodes. This is done
|
||||
* in lb_size units though currently lb_size is dictated to be
|
||||
* sector_size.
|
||||
*/
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
ump->desc_pool = malloc(sizeof(struct pool), M_UDFMNT, M_WAITOK);
|
||||
memset(ump->desc_pool, 0, sizeof(struct pool));
|
||||
pool_init(ump->desc_pool, lb_size, 0, 0, 0, "udf_desc_pool", NULL,
|
||||
IPL_NONE);
|
||||
/* switch to new disc strategy */
|
||||
KASSERT(ump->strategy != &udf_strat_bootstrap);
|
||||
udf_discstrat_init(ump);
|
||||
|
||||
/* initialise late allocation administration space */
|
||||
ump->la_lmapping = malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS,
|
||||
M_TEMP, M_WAITOK);
|
||||
ump->la_pmapping = malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS,
|
||||
M_TEMP, M_WAITOK);
|
||||
|
||||
/* setup node cleanup extents copy space */
|
||||
lb_size = udf_rw32(ump->logical_vol->lb_size);
|
||||
ump->la_node_ad_cpy = malloc(lb_size * UDF_MAX_ALLOC_EXTENTS,
|
||||
M_UDFMNT, M_WAITOK);
|
||||
memset(ump->la_node_ad_cpy, 0, lb_size * UDF_MAX_ALLOC_EXTENTS);
|
||||
|
||||
/* setup rest of mount information */
|
||||
mp->mnt_data = ump;
|
||||
|
||||
/* bshift is allways equal to disc sector size */
|
||||
mp->mnt_dev_bshift = bshift;
|
||||
mp->mnt_fs_bshift = bshift;
|
||||
|
||||
/* note that the mp info needs to be initialised for reading! */
|
||||
/* read vds support tables like VAT, sparable etc. */
|
||||
if ((error = udf_read_vds_tables(ump, args))) {
|
||||
if ((error = udf_read_vds_tables(ump))) {
|
||||
printf( "UDF mount: error in format or damaged disc "
|
||||
"(VDS tables failing)\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = udf_read_rootdirs(ump, args))) {
|
||||
/* check if volume integrity is closed otherwise its dirty */
|
||||
logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type);
|
||||
if (logvol_integrity != UDF_INTEGRITY_CLOSED) {
|
||||
printf("UDF mount: file system is not clean; ");
|
||||
printf("please fsck(8)\n");
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
/* read root directory */
|
||||
if ((error = udf_read_rootdirs(ump))) {
|
||||
printf( "UDF mount: "
|
||||
"disc not properly formatted or damaged disc "
|
||||
"(rootdirs failing)\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
/* setup rest of mount information */
|
||||
mp->mnt_data = ump;
|
||||
mp->mnt_stat.f_fsidx.__fsid_val[0] = (uint32_t) devvp->v_rdev;
|
||||
mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_UDF);
|
||||
mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
|
||||
mp->mnt_stat.f_namemax = UDF_MAX_NAMELEN;
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
|
||||
/* bshift is always equal to disc sector size */
|
||||
mp->mnt_dev_bshift = bshift;
|
||||
mp->mnt_fs_bshift = bshift;
|
||||
|
||||
/* do we have to set this? */
|
||||
devvp->v_specmountpoint = mp;
|
||||
|
||||
@ -638,14 +738,23 @@ udf_statvfs(struct mount *mp, struct statvfs *sbp)
|
||||
sbp->f_frsize = ump->discinfo.sector_size;
|
||||
sbp->f_iosize = ump->discinfo.sector_size;
|
||||
|
||||
/* TODO integrity locking */
|
||||
/* free and used space for mountpoint based on logvol integrity */
|
||||
mutex_enter(&ump->allocate_mutex);
|
||||
lvid = ump->logvol_integrity;
|
||||
if (lvid) {
|
||||
num_part = udf_rw32(lvid->num_part);
|
||||
impl = (struct udf_logvol_info *) (lvid->tables + 2*num_part);
|
||||
freeblks = sizeblks = 0;
|
||||
|
||||
freeblks = sizeblks = 0;
|
||||
/* Sequentials report free space directly (CD/DVD/BD-R) */
|
||||
KASSERT(lvid);
|
||||
num_part = udf_rw32(lvid->num_part);
|
||||
impl = (struct udf_logvol_info *) (lvid->tables + 2*num_part);
|
||||
|
||||
if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
|
||||
/* XXX assumption at most two tracks open */
|
||||
freeblks = ump->data_track.free_blocks;
|
||||
if (ump->data_track.tracknr != ump->metadata_track.tracknr)
|
||||
freeblks += ump->metadata_track.free_blocks;
|
||||
sizeblks = ump->discinfo.last_possible_lba;
|
||||
} else {
|
||||
/* free and used space for mountpoint based on logvol integrity */
|
||||
for (part=0; part < num_part; part++) {
|
||||
pos1 = &lvid->tables[0] + part;
|
||||
pos2 = &lvid->tables[0] + num_part + part;
|
||||
@ -654,33 +763,79 @@ udf_statvfs(struct mount *mp, struct statvfs *sbp)
|
||||
sizeblks += udf_rw32(*pos2);
|
||||
}
|
||||
}
|
||||
sbp->f_blocks = sizeblks;
|
||||
sbp->f_bfree = freeblks;
|
||||
}
|
||||
freeblks -= ump->uncomitted_lb;
|
||||
|
||||
sbp->f_blocks = sizeblks;
|
||||
sbp->f_bfree = freeblks;
|
||||
sbp->f_files = 0;
|
||||
if (impl) {
|
||||
sbp->f_files = udf_rw32(impl->num_files);
|
||||
sbp->f_files += udf_rw32(impl->num_directories);
|
||||
|
||||
/* XXX read only for now XXX */
|
||||
sbp->f_bavail = 0;
|
||||
sbp->f_bresvd = 0;
|
||||
|
||||
/* tricky, next only aplies to ffs i think, so set to zero */
|
||||
sbp->f_ffree = 0;
|
||||
sbp->f_favail = 0;
|
||||
sbp->f_fresvd = 0;
|
||||
}
|
||||
|
||||
/* XXX read only for now XXX */
|
||||
sbp->f_bavail = 0;
|
||||
sbp->f_bresvd = 0;
|
||||
|
||||
/* tricky, next only aplies to ffs i think, so set to zero */
|
||||
sbp->f_ffree = 0;
|
||||
sbp->f_favail = 0;
|
||||
sbp->f_fresvd = 0;
|
||||
|
||||
mutex_exit(&ump->allocate_mutex);
|
||||
|
||||
copy_statvfs_info(sbp, mp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* TODO what about writing out free space maps, lvid etc? only on `waitfor'
|
||||
* i.e. explicit syncing by the user?
|
||||
*/
|
||||
|
||||
int
|
||||
udf_sync(struct mount *mp, int waitfor,
|
||||
kauth_cred_t cred)
|
||||
udf_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
|
||||
{
|
||||
struct udf_mount *ump = VFSTOUDF(mp);
|
||||
int error;
|
||||
|
||||
DPRINTF(CALL, ("udf_sync called\n"));
|
||||
/* nothing to be done as upto now read-only */
|
||||
/* if called when mounted readonly, just ignore */
|
||||
if (mp->mnt_flag & MNT_RDONLY)
|
||||
return 0;
|
||||
|
||||
if (ump->syncing && !waitfor) {
|
||||
printf("UDF: skipping autosync\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get sync lock */
|
||||
ump->syncing = 1;
|
||||
|
||||
udf_do_sync(ump, cred, waitfor);
|
||||
|
||||
if (waitfor == MNT_WAIT) {
|
||||
/* XXX lock for VAT en bitmaps? */
|
||||
/* metadata nodes are written synchronous */
|
||||
DPRINTF(CALL, ("udf_sync: syncing metadata\n"));
|
||||
if (ump->lvclose & UDF_WRITE_VAT)
|
||||
udf_writeout_vat(ump);
|
||||
if (ump->lvclose & UDF_WRITE_PART_BITMAPS) {
|
||||
error = udf_write_partition_spacetables(ump, waitfor);
|
||||
if (error) {
|
||||
printf( "udf_close_logvol: writeout of space "
|
||||
"tables failed\n");
|
||||
}
|
||||
ump->lvclose &= ~UDF_WRITE_PART_BITMAPS;
|
||||
}
|
||||
|
||||
}
|
||||
DPRINTF(CALL, ("end of udf_sync()\n"));
|
||||
ump->syncing = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.1 2006/02/02 15:19:16 reinoud Exp $
|
||||
# $NetBSD: Makefile,v 1.2 2008/05/14 16:49:48 reinoud Exp $
|
||||
|
||||
.include "../Makefile.inc"
|
||||
|
||||
@ -7,6 +7,12 @@
|
||||
KMOD= udf
|
||||
|
||||
SRCS= lkminit_vfs.c
|
||||
SRCS+= udf_osta.c udf_subr.c udf_vfsops.c udf_vnops.c
|
||||
SRCS+= udf_osta.c udf_subr.c udf_vfsops.c udf_vnops.c \
|
||||
udf_readwrite.c udf_strat_bootstrap.c udf_strat_direct.c \
|
||||
udf_strat_sequential.c udf_strat_rmw.c udf_allocation.c
|
||||
|
||||
CFLAGS+= -DLKM
|
||||
CFLAGS+= -DPOOL_DIAGNOSTICS
|
||||
CFLAGS+= -DUDF_READWRITE
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: genfs_io.c,v 1.6 2008/04/19 11:53:13 hannken Exp $ */
|
||||
/* $NetBSD: genfs_io.c,v 1.7 2008/05/14 16:49:47 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.6 2008/04/19 11:53:13 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.7 2008/05/14 16:49:47 reinoud Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -1211,6 +1211,29 @@ genfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
genfs_gop_write_rwmap(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
|
||||
{
|
||||
off_t off;
|
||||
vaddr_t kva;
|
||||
size_t len;
|
||||
int error;
|
||||
UVMHIST_FUNC(__func__); UVMHIST_CALLED(ubchist);
|
||||
|
||||
UVMHIST_LOG(ubchist, "vp %p pgs %p npages %d flags 0x%x",
|
||||
vp, pgs, npages, flags);
|
||||
|
||||
off = pgs[0]->offset;
|
||||
kva = uvm_pagermapin(pgs, npages,
|
||||
UVMPAGER_MAPIN_READ | UVMPAGER_MAPIN_WAITOK);
|
||||
len = npages << PAGE_SHIFT;
|
||||
|
||||
error = genfs_do_io(vp, off, kva, len, flags, UIO_WRITE,
|
||||
uvm_aio_biodone);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Backend routine for doing I/O to vnode pages. Pages are already locked
|
||||
* and mapped into kernel memory. Here we just look up the underlying
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: genfs_node.h,v 1.16 2007/02/20 16:19:42 ad Exp $ */
|
||||
/* $NetBSD: genfs_node.h,v 1.17 2008/05/14 16:49:47 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Chuck Silvers.
|
||||
@ -85,6 +85,7 @@ void genfs_size(struct vnode *, off_t, off_t *, int);
|
||||
void genfs_node_init(struct vnode *, const struct genfs_ops *);
|
||||
void genfs_node_destroy(struct vnode *);
|
||||
int genfs_gop_write(struct vnode *, struct vm_page **, int, int);
|
||||
int genfs_gop_write_rwmap(struct vnode *, struct vm_page **, int, int);
|
||||
int genfs_compat_gop_write(struct vnode *, struct vm_page **, int, int);
|
||||
void genfs_directio(struct vnode *, struct uio *, int);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.232 2008/04/15 11:17:48 plunky Exp $
|
||||
# $NetBSD: Makefile,v 1.233 2008/05/14 16:49:47 reinoud Exp $
|
||||
# from: @(#)Makefile 5.20 (Berkeley) 6/12/93
|
||||
|
||||
.include <bsd.own.mk>
|
||||
@ -11,7 +11,7 @@ SUBDIR= ac accton acpitools altq amd apm apmd arp bad144 bind bootp \
|
||||
grfconfig grfinfo gspa hilinfo ifwatchd inetd installboot \
|
||||
iopctl iostat ipwctl irdaattach isdn iteconfig iwictl\
|
||||
kgmon lastlogin link lmcconfig lockstat lpr mailwrapper makefs \
|
||||
map-mbone mdconfig memswitch mlxctl mopd mountd moused \
|
||||
map-mbone mdconfig memswitch mlxctl mmcformat mopd mountd moused \
|
||||
mrinfo mrouted mscdlabel mtrace \
|
||||
mtree ndbootd ndiscvt netgroup_mkdb nfsd ntp ofctl paxctl pcictl \
|
||||
pkg_install \
|
||||
|
12
usr.sbin/mmcformat/Makefile
Normal file
12
usr.sbin/mmcformat/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
# $NetBSD: Makefile,v 1.1 2008/05/14 16:49:48 reinoud Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
WARNS= 4
|
||||
PROG= mmcformat
|
||||
MAN= mmcformat.8
|
||||
SRCS= mmcformat.c uscsi_sense.c uscsi_subr.c
|
||||
|
||||
CPPFLAGS+= -DSCSI -DUSCSI_SCSIPI -I${NETBSDSRCDIR}/sys
|
||||
|
||||
.include <bsd.prog.mk>
|
43
usr.sbin/mmcformat/defs.h
Normal file
43
usr.sbin/mmcformat/defs.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* $NetBSD: defs.h,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* File "defs.h" is part of the UDFclient toolkit.
|
||||
* File $Id: defs.h,v 1.1 2008/05/14 16:49:48 reinoud Exp $ $Name: $
|
||||
*
|
||||
* Copyright (c) 2003, 2004, 2005, 2006 Reinoud Zandijk <reinoud@netbsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* The UDFclient toolkit is distributed under the Clarified Artistic Licence.
|
||||
* A copy of the licence is included in the distribution as
|
||||
* `LICENCE.clearified.artistic' and a copy of the licence can also be
|
||||
* requested at the GNU foundantion's website.
|
||||
*
|
||||
* Visit the UDFclient toolkit homepage http://www.13thmonkey.org/udftoolkit/
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DEFS_H_
|
||||
#define _DEFS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#endif /* _DEFS_H_ */
|
||||
|
136
usr.sbin/mmcformat/mmcformat.8
Normal file
136
usr.sbin/mmcformat/mmcformat.8
Normal file
@ -0,0 +1,136 @@
|
||||
.\" $NetBSD: mmcformat.8,v 1.1 2008/05/14 16:49:48 reinoud Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2008 Reinoud Zandijk
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in
|
||||
.\" the documentation and/or other materials provided with the
|
||||
.\" distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
|
||||
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
|
||||
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.Dd May, 9, 2008
|
||||
.Dt MMCFORMAT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mmcformat
|
||||
.Nd format optical media
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl B
|
||||
.Op Fl F
|
||||
.Op Fl O
|
||||
.Op Fl M
|
||||
.Op Fl R
|
||||
.Op Fl G
|
||||
.Op Fl S
|
||||
.Op Fl s
|
||||
.Op Fl w
|
||||
.Op Fl p
|
||||
.Op Fl c Ar cert-num
|
||||
.Op Fl r
|
||||
.Op Fl h
|
||||
.Op Fl H
|
||||
.Op Fl I
|
||||
.\" .Op X format is not implemented yet
|
||||
.Op Fl b blockingnr
|
||||
.Op D
|
||||
.Ar special
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility formats optical media conforming to the MMC standard. These include
|
||||
CD , DVD, and Blu-Ray (BD) media.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl B
|
||||
Blank media when possible before formatting it.
|
||||
.It Fl F
|
||||
Format media.
|
||||
.It Fl O
|
||||
Old style CD-RW formatting ; recommended for CD-RW.
|
||||
.It Fl M
|
||||
Select MRW (Mount Raineer) error correcting background format.
|
||||
.It Fl R
|
||||
Restart previously stopped MCD-MRW or DVD+RW backfround format.
|
||||
.It Fl G
|
||||
Grow last CD-RW/DVD-RW session.
|
||||
.It Fl S
|
||||
Grow spare space DVD-RAM / BD-RE.
|
||||
.It Fl s
|
||||
Format DVD+MRW / BD-RE with extra spare space.
|
||||
.It Fl w
|
||||
Wait until completion of background format.
|
||||
.It Fl p
|
||||
Explicitly set packet format.
|
||||
.It Fl c Ar cert-num
|
||||
Certify media for DVD-RAM / DV-RE. The argument cert-num specifies: 0) no
|
||||
certification , 1) full certification , 2) quick certification.
|
||||
.It Fl r
|
||||
Recompile defect list for DVD-RAM.
|
||||
.It Fl h
|
||||
Show help or inquiry format possibilities for inserted media.
|
||||
.It Fl H
|
||||
Show help or inquiry format possibilities for inserted media.
|
||||
.It Fl i
|
||||
Show help or inquiry format possibilities for inserted media.
|
||||
.It Fl b blockingnr
|
||||
Explicit select packet size in sectors for CD-RW only; not recommended to
|
||||
change from its default 32.
|
||||
.It Fl D
|
||||
Verbose all SCSI/ATAPI command errors.
|
||||
.El
|
||||
.Sh NOTES
|
||||
Due to the enormous varieties in optical media, the tool is made as generic as
|
||||
possible. This can result in confusion.
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal -offset indent
|
||||
mmcformat -B -O /dev/rcd0d
|
||||
.Ed
|
||||
.Pp
|
||||
Blanks and then formats a CD-RW disc using the `old-style' format command. Its
|
||||
recommended to use this `old-style' command unless your drive reports its not
|
||||
supported; if so, resort to the default
|
||||
.Fl F
|
||||
.
|
||||
Note that a CD-RW disc can be reformatted without being blanked. Blanking
|
||||
swiches between sequential and fixed packet writing by erasing the disc. This
|
||||
can also help to revive old discs.
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
mmcformat -F -M /dev/rcd0d
|
||||
.Ed
|
||||
.Pp
|
||||
Format a CD-RW or a DVD+RW to use MRW (Mount Raineer). This format tries to
|
||||
hide media flaws as much as possible by relocation.
|
||||
.Sh SEE ALSO
|
||||
.Xr scsictl 8
|
||||
.Sh BUGS
|
||||
It could be merged with
|
||||
.Xr scsictl 8
|
||||
but that tool is very harddisc oriented.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.Nx 5.0 .
|
||||
.Sh AUTHORS
|
||||
.An Reinoud Zandijk Aq reinoud@NetBSD.org .
|
1084
usr.sbin/mmcformat/mmcformat.c
Normal file
1084
usr.sbin/mmcformat/mmcformat.c
Normal file
File diff suppressed because it is too large
Load Diff
829
usr.sbin/mmcformat/uscsi_sense.c
Normal file
829
usr.sbin/mmcformat/uscsi_sense.c
Normal file
@ -0,0 +1,829 @@
|
||||
/* $NetBSD: uscsi_sense.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Small changes made by Reinoud Zandijk <reinoud@netbsd.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI sense interpretation. Lifted from src/sys/dev/scsipi/scsipi_verbose.c,
|
||||
* and modified for userland.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "uscsilib.h"
|
||||
|
||||
|
||||
static const char *sense_keys[16] = {
|
||||
"No Additional Sense",
|
||||
"Recovered Error",
|
||||
"Not Ready",
|
||||
"Media Error",
|
||||
"Hardware Error",
|
||||
"Illegal Request",
|
||||
"Unit Attention",
|
||||
"Write Protected",
|
||||
"Blank Check",
|
||||
"Vendor Unique",
|
||||
"Copy Aborted",
|
||||
"Aborted Command",
|
||||
"Equal Error",
|
||||
"Volume Overflow",
|
||||
"Miscompare Error",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
/*
|
||||
* The current version of this list can be obtained from
|
||||
* <ftp://ftp.t10.org/t10/drafts/spc3/asc-num.txt>
|
||||
*/
|
||||
|
||||
static const struct {
|
||||
unsigned char asc;
|
||||
unsigned char ascq;
|
||||
const char *description;
|
||||
} adesc[] = {
|
||||
{ 0x00, 0x00, "No Additional Sense Information" },
|
||||
{ 0x00, 0x01, "Filemark Detected" },
|
||||
{ 0x00, 0x02, "End-Of-Partition/Medium Detected" },
|
||||
{ 0x00, 0x03, "Setmark Detected" },
|
||||
{ 0x00, 0x04, "Beginning-Of-Partition/Medium Detected" },
|
||||
{ 0x00, 0x05, "End-Of-Data Detected" },
|
||||
{ 0x00, 0x06, "I/O Process Terminated" },
|
||||
{ 0x00, 0x11, "Audio Play Operation In Progress" },
|
||||
{ 0x00, 0x12, "Audio Play Operation Paused" },
|
||||
{ 0x00, 0x13, "Audio Play Operation Successfully Completed" },
|
||||
{ 0x00, 0x14, "Audio Play Operation Stopped Due to Error" },
|
||||
{ 0x00, 0x15, "No Current Audio Status To Return" },
|
||||
{ 0x00, 0x16, "Operation In Progress" },
|
||||
{ 0x00, 0x17, "Cleaning Requested" },
|
||||
{ 0x00, 0x18, "Erase Operation In Progress" },
|
||||
{ 0x00, 0x19, "Locate Operation In Progress" },
|
||||
{ 0x00, 0x1A, "Rewind Operation In Progress" },
|
||||
{ 0x00, 0x1B, "Set Capacity Operation In Progess" },
|
||||
{ 0x00, 0x1C, "Verify Operation In Progress" },
|
||||
{ 0x01, 0x00, "No Index/Sector Signal" },
|
||||
{ 0x02, 0x00, "No Seek Complete" },
|
||||
{ 0x03, 0x00, "Peripheral Device Write Fault" },
|
||||
{ 0x03, 0x01, "No Write Current" },
|
||||
{ 0x03, 0x02, "Excessive Write Errors" },
|
||||
{ 0x04, 0x00, "Logical Unit Not Ready, Cause Not Reportable" },
|
||||
{ 0x04, 0x01, "Logical Unit Is in Process Of Becoming Ready" },
|
||||
{ 0x04, 0x02, "Logical Unit Not Ready, Initialization Command Required" },
|
||||
{ 0x04, 0x03, "Logical Unit Not Ready, Manual Intervention Required" },
|
||||
{ 0x04, 0x04, "Logical Unit Not Ready, Format In Progress" },
|
||||
{ 0x04, 0x05, "Logical Unit Not Ready, Rebuild In Progress" },
|
||||
{ 0x04, 0x06, "Logical Unit Not Ready, Recalculation In Progress" },
|
||||
{ 0x04, 0x07, "Logical Unit Not Ready, Operation In Progress" },
|
||||
{ 0x04, 0x08, "Logical Unit Not Ready, Long Write In Progress" },
|
||||
{ 0x04, 0x09, "Logical Unit Not Ready, Self-Test In Progress" },
|
||||
{ 0x04, 0x0A, "Logical Unit Not Accessible, Asymmetric Access State "
|
||||
"Transition" },
|
||||
{ 0x04, 0x0B, "Logical Unit Not Accessible, Target Port In Standby State" },
|
||||
{ 0x04, 0x0C, "Logical Unit Not Accessible, Target Port In Unavailable State" },
|
||||
{ 0x04, 0x10, "Logical Unit Not Ready, Auxiliary Memory Not Accessible" },
|
||||
{ 0x04, 0x11, "Logical Unit Not Ready, Notify (Enable_Spinup) Required" },
|
||||
{ 0x05, 0x00, "Logical Unit Does Not Respond To Selection" },
|
||||
{ 0x06, 0x00, "No Reference Position Found" },
|
||||
{ 0x07, 0x00, "Multiple Peripheral Devices Selected" },
|
||||
{ 0x08, 0x00, "Logical Unit Communication Failure" },
|
||||
{ 0x08, 0x01, "Logical Unit Communication Timeout" },
|
||||
{ 0x08, 0x02, "Logical Unit Communication Parity Error" },
|
||||
{ 0x08, 0x03, "Logical Unit Communication CRC Error" },
|
||||
{ 0x08, 0x04, "Unreachable Copy Target" },
|
||||
{ 0x09, 0x00, "Track Following Error" },
|
||||
{ 0x09, 0x01, "Tracking Servo Failure" },
|
||||
{ 0x09, 0x02, "Focus Servo Failure" },
|
||||
{ 0x09, 0x03, "Spindle Servo Failure" },
|
||||
{ 0x09, 0x04, "Head Select Fault" },
|
||||
{ 0x0A, 0x00, "Error Log Overflow" },
|
||||
{ 0x0B, 0x00, "Warning" },
|
||||
{ 0x0B, 0x01, "Warning - Specified Temperature Exceeded" },
|
||||
{ 0x0B, 0x02, "Warning - Enclosure Degraded" },
|
||||
{ 0x0C, 0x00, "Write Error" },
|
||||
{ 0x0C, 0x01, "Write Error - Recovered with Auto Reallocation" },
|
||||
{ 0x0C, 0x02, "Write Error - Auto Reallocate Failed" },
|
||||
{ 0x0C, 0x03, "Write Error - Recommend Reassignment" },
|
||||
{ 0x0C, 0x04, "Compression Check Miscompare Error" },
|
||||
{ 0x0C, 0x05, "Data Expansion Occurred During Compression" },
|
||||
{ 0x0C, 0x06, "Block Not Compressible" },
|
||||
{ 0x0C, 0x07, "Write Error - Recovery Needed" },
|
||||
{ 0x0C, 0x08, "Write Error - Recovery Failed" },
|
||||
{ 0x0C, 0x09, "Write Error - Loss Of Streaming" },
|
||||
{ 0x0C, 0x0A, "Write Error - Padding Blocks Added" },
|
||||
{ 0x0C, 0x0B, "Auxiliary Memory Write Error" },
|
||||
{ 0x0C, 0x0C, "Write Error - Unexpected Unsolicited Data" },
|
||||
{ 0x0C, 0x0D, "Write Error - Not Enough Unsolicited Data" },
|
||||
{ 0x0D, 0x00, "Error Detected By Third Party Temporary Initiator" },
|
||||
{ 0x0D, 0x01, "Third Party Device Failure" },
|
||||
{ 0x0D, 0x02, "Copy Target Device Not Reachable" },
|
||||
{ 0x0D, 0x03, "Incorrect Copy Target Device Type" },
|
||||
{ 0x0D, 0x04, "Copy Target Device Data Underrun" },
|
||||
{ 0x0D, 0x05, "Copy Target Device Data Overrun" },
|
||||
{ 0x0E, 0x00, "Invalid Information Unit" },
|
||||
{ 0x0E, 0x01, "Information Unit Too Short" },
|
||||
{ 0x0E, 0x02, "Information Unit Too Long" },
|
||||
{ 0x10, 0x00, "ID CRC Or ECC Error" },
|
||||
{ 0x11, 0x00, "Unrecovered Read Error" },
|
||||
{ 0x11, 0x01, "Read Retries Exhausted" },
|
||||
{ 0x11, 0x02, "Error Too Long To Correct" },
|
||||
{ 0x11, 0x03, "Multiple Read Errors" },
|
||||
{ 0x11, 0x04, "Unrecovered Read Error - Auto Reallocate Failed" },
|
||||
{ 0x11, 0x05, "L-EC Uncorrectable Error" },
|
||||
{ 0x11, 0x06, "CIRC Unrecovered Error" },
|
||||
{ 0x11, 0x07, "Data Re-synchronization Error" },
|
||||
{ 0x11, 0x08, "Incomplete Block Read" },
|
||||
{ 0x11, 0x09, "No Gap Found" },
|
||||
{ 0x11, 0x0A, "Miscorrected Error" },
|
||||
{ 0x11, 0x0B, "Uncorrected Read Error - Recommend Reassignment" },
|
||||
{ 0x11, 0x0C, "Uncorrected Read Error - Recommend Rewrite the Data" },
|
||||
{ 0x11, 0x0D, "De-Compression CRC Error" },
|
||||
{ 0x11, 0x0E, "Cannot Decompress Using Declared Algorithm" },
|
||||
{ 0x11, 0x0F, "Error Reading UPC/EAN Number" },
|
||||
{ 0x11, 0x10, "Error Reading ISRC Number" },
|
||||
{ 0x11, 0x11, "Read Error - Loss Of Streaming" },
|
||||
{ 0x11, 0x12, "Auxiliary Memory Read Error" },
|
||||
{ 0x11, 0x13, "Read Error - Failed Retransmission Request" },
|
||||
{ 0x12, 0x00, "Address Mark Not Found for ID Field" },
|
||||
{ 0x13, 0x00, "Address Mark Not Found for Data Field" },
|
||||
{ 0x14, 0x00, "Recorded Entity Not Found" },
|
||||
{ 0x14, 0x01, "Record Not Found" },
|
||||
{ 0x14, 0x02, "Filemark or Setmark Not Found" },
|
||||
{ 0x14, 0x03, "End-Of-Data Not Found" },
|
||||
{ 0x14, 0x04, "Block Sequence Error" },
|
||||
{ 0x14, 0x05, "Record Not Found - Recommend Reassignment" },
|
||||
{ 0x14, 0x06, "Record Not Found - Data Auto-Reallocated" },
|
||||
{ 0x14, 0x07, "Locate Operation Failure" },
|
||||
{ 0x15, 0x00, "Random Positioning Error" },
|
||||
{ 0x15, 0x01, "Mechanical Positioning Error" },
|
||||
{ 0x15, 0x02, "Positioning Error Detected By Read of Medium" },
|
||||
{ 0x16, 0x00, "Data Synchronization Mark Error" },
|
||||
{ 0x16, 0x01, "Data Sync Error - Data Rewritten" },
|
||||
{ 0x16, 0x02, "Data Sync Error - Recommend Rewrite" },
|
||||
{ 0x16, 0x03, "Data Sync Error - Data Auto-Reallocated" },
|
||||
{ 0x16, 0x04, "Data Sync Error - Recommend Reassignment" },
|
||||
{ 0x17, 0x00, "Recovered Data With No Error Correction Applied" },
|
||||
{ 0x17, 0x01, "Recovered Data With Retries" },
|
||||
{ 0x17, 0x02, "Recovered Data With Positive Head Offset" },
|
||||
{ 0x17, 0x03, "Recovered Data With Negative Head Offset" },
|
||||
{ 0x17, 0x04, "Recovered Data With Retries and/or CIRC Applied" },
|
||||
{ 0x17, 0x05, "Recovered Data Using Previous Sector ID" },
|
||||
{ 0x17, 0x06, "Recovered Data Without ECC - Data Auto-Reallocated" },
|
||||
{ 0x17, 0x07, "Recovered Data Without ECC - Recommend Reassignment" },
|
||||
{ 0x17, 0x08, "Recovered Data Without ECC - Recommend Rewrite" },
|
||||
{ 0x17, 0x09, "Recovered Data Without ECC - Data Rewritten" },
|
||||
{ 0x18, 0x00, "Recovered Data With Error Correction Applied" },
|
||||
{ 0x18, 0x01, "Recovered Data With Error Correction & Retries Applied" },
|
||||
{ 0x18, 0x02, "Recovered Data - Data Auto-Reallocated" },
|
||||
{ 0x18, 0x03, "Recovered Data With CIRC" },
|
||||
{ 0x18, 0x04, "Recovered Data With LEC" },
|
||||
{ 0x18, 0x05, "Recovered Data - Recommend Reassignment" },
|
||||
{ 0x18, 0x06, "Recovered Data - Recommend Rewrite" },
|
||||
{ 0x18, 0x07, "Recovered Data With ECC - Data Rewritten" },
|
||||
{ 0x18, 0x08, "Recovered Data With Linking" },
|
||||
{ 0x19, 0x00, "Defect List Error" },
|
||||
{ 0x19, 0x01, "Defect List Not Available" },
|
||||
{ 0x19, 0x02, "Defect List Error in Primary List" },
|
||||
{ 0x19, 0x03, "Defect List Error in Grown List" },
|
||||
{ 0x1A, 0x00, "Parameter List Length Error" },
|
||||
{ 0x1B, 0x00, "Synchronous Data Transfer Error" },
|
||||
{ 0x1C, 0x00, "Defect List Not Found" },
|
||||
{ 0x1C, 0x01, "Primary Defect List Not Found" },
|
||||
{ 0x1C, 0x02, "Grown Defect List Not Found" },
|
||||
{ 0x1D, 0x00, "Miscompare During Verify Operation" },
|
||||
{ 0x1E, 0x00, "Recovered ID with ECC Correction" },
|
||||
{ 0x1F, 0x00, "Partial Defect List Transfer" },
|
||||
{ 0x20, 0x00, "Invalid Command Operation Code" },
|
||||
{ 0x20, 0x01, "Access Denied - Initiator Pending-Enrolled" },
|
||||
{ 0x20, 0x02, "Access Denied - No Access Rights" },
|
||||
{ 0x20, 0x03, "Access Denied - Invalid Mgmt ID Key" },
|
||||
{ 0x20, 0x04, "Illegal Command While In Write Capable State" },
|
||||
{ 0x20, 0x06, "Illegal Command While In Explicit Address Mode" },
|
||||
{ 0x20, 0x07, "Illegal Command While In Implicit Address Mode" },
|
||||
{ 0x20, 0x08, "Access Denied - Enrollment Conflict" },
|
||||
{ 0x20, 0x09, "Access Denied - Invalid LU Identifer" },
|
||||
{ 0x20, 0x0A, "Access Denied - Invalid Proxy Token" },
|
||||
{ 0x20, 0x0B, "Access Denied - ACL LUN Conflict" },
|
||||
{ 0x21, 0x00, "Logical Block Address Out of Range" },
|
||||
{ 0x21, 0x01, "Invalid Element Address" },
|
||||
{ 0x21, 0x02, "Invalid Address For Write" },
|
||||
{ 0x22, 0x00, "Illegal Function (Use 20 00, 24 00, or 26 00)" },
|
||||
{ 0x24, 0x00, "Illegal Field in CDB" },
|
||||
{ 0x24, 0x01, "CDB Decryption Error" },
|
||||
{ 0x24, 0x04, "Security Audit Value Frozen" },
|
||||
{ 0x24, 0x05, "Security Working Key Frozen" },
|
||||
{ 0x24, 0x06, "Nonce Not Unique" },
|
||||
{ 0x24, 0x07, "Nonce Timestamp Out Of Range" },
|
||||
{ 0x25, 0x00, "Logical Unit Not Supported" },
|
||||
{ 0x26, 0x00, "Invalid Field In Parameter List" },
|
||||
{ 0x26, 0x01, "Parameter Not Supported" },
|
||||
{ 0x26, 0x02, "Parameter Value Invalid" },
|
||||
{ 0x26, 0x03, "Threshold Parameters Not Supported" },
|
||||
{ 0x26, 0x04, "Invalid Release Of Persistent Reservation" },
|
||||
{ 0x26, 0x05, "Data Decryption Error" },
|
||||
{ 0x26, 0x06, "Too Many Target Descriptors" },
|
||||
{ 0x26, 0x07, "Unsupported Target Descriptor Type Code" },
|
||||
{ 0x26, 0x08, "Too Many Segment Descriptors" },
|
||||
{ 0x26, 0x09, "Unsupported Segment Descriptor Type Code" },
|
||||
{ 0x26, 0x0A, "Unexpected Inexact Segment" },
|
||||
{ 0x26, 0x0B, "Inline Data Length Exceeded" },
|
||||
{ 0x26, 0x0C, "Invalid Operation For Copy Source Or Destination" },
|
||||
{ 0x26, 0x0D, "Copy Segment Granularity Violation" },
|
||||
{ 0x26, 0x0E, "Invalid Parameter While Port Is Enabled" },
|
||||
{ 0x27, 0x00, "Write Protected" },
|
||||
{ 0x27, 0x01, "Hardware Write Protected" },
|
||||
{ 0x27, 0x02, "Logical Unit Software Write Protected" },
|
||||
{ 0x27, 0x03, "Associated Write Protect" },
|
||||
{ 0x27, 0x04, "Persistent Write Protect" },
|
||||
{ 0x27, 0x05, "Permanent Write Protect" },
|
||||
{ 0x27, 0x06, "Conditional Write Protect" },
|
||||
{ 0x28, 0x00, "Not Ready To Ready Transition (Medium May Have Changed)" },
|
||||
{ 0x28, 0x01, "Import Or Export Element Accessed" },
|
||||
{ 0x29, 0x00, "Power On, Reset, or Bus Device Reset Occurred" },
|
||||
{ 0x29, 0x01, "Power On Occurred" },
|
||||
{ 0x29, 0x02, "SCSI Bus Reset Occurred" },
|
||||
{ 0x29, 0x03, "Bus Device Reset Function Occurred" },
|
||||
{ 0x29, 0x04, "Device Internal Reset" },
|
||||
{ 0x29, 0x05, "Transceiver Mode Changed To Single-Ended" },
|
||||
{ 0x29, 0x06, "Transceiver Mode Changed To LVD" },
|
||||
{ 0x29, 0x07, "I_T Nexus Loss Occurred" },
|
||||
{ 0x2A, 0x00, "Parameters Changed" },
|
||||
{ 0x2A, 0x01, "Mode Parameters Changed" },
|
||||
{ 0x2A, 0x02, "Log Parameters Changed" },
|
||||
{ 0x2A, 0x03, "Reservations Preempted" },
|
||||
{ 0x2A, 0x04, "Reservations Released" },
|
||||
{ 0x2A, 0x05, "Registrations Preempted" },
|
||||
{ 0x2A, 0x06, "Asymmetric Access State Changed" },
|
||||
{ 0x2A, 0x07, "Implicit Asymmetric Access State Transition Failed" },
|
||||
{ 0x2B, 0x00, "Copy Cannot Execute Since Host Cannot Disconnect" },
|
||||
{ 0x2C, 0x00, "Command Sequence Error" },
|
||||
{ 0x2C, 0x01, "Too Many Windows Specified" },
|
||||
{ 0x2C, 0x02, "Invalid Combination of Windows Specified" },
|
||||
{ 0x2C, 0x03, "Current Program Area Is Not Empty" },
|
||||
{ 0x2C, 0x04, "Current Program Area Is Empty" },
|
||||
{ 0x2C, 0x05, "Illegal Power Condition Request" },
|
||||
{ 0x2C, 0x06, "Persistent Prevent Conflict" },
|
||||
{ 0x2C, 0x07, "Previous Busy Status" },
|
||||
{ 0x2C, 0x08, "Previous Task Set Full Status" },
|
||||
{ 0x2C, 0x09, "Previous Reservation Conflict Status" },
|
||||
{ 0x2C, 0x0A, "Partition or Collection Contains User Objects" },
|
||||
{ 0x2D, 0x00, "Overwrite Error On Update In Place" },
|
||||
{ 0x2E, 0x00, "Insufficient Time For Operation" },
|
||||
{ 0x2F, 0x00, "Commands Cleared By Another Initiator" },
|
||||
{ 0x30, 0x00, "Incompatible Medium Installed" },
|
||||
{ 0x30, 0x01, "Cannot Read Medium - Unknown Format" },
|
||||
{ 0x30, 0x02, "Cannot Read Medium - Incompatible Format" },
|
||||
{ 0x30, 0x03, "Cleaning Cartridge Installed" },
|
||||
{ 0x30, 0x04, "Cannot Write Medium - Unknown Format" },
|
||||
{ 0x30, 0x05, "Cannot Write Medium - Incompatible Format" },
|
||||
{ 0x30, 0x06, "Cannot Format Medium - Incompatible Medium" },
|
||||
{ 0x30, 0x07, "Cleaning Failure" },
|
||||
{ 0x30, 0x08, "Cannot Write - Application Code Mismatch" },
|
||||
{ 0x30, 0x09, "Current Session Not Fixated For Append" },
|
||||
{ 0x30, 0x0A, "Cleaning Request Rejected" },
|
||||
{ 0x30, 0x10, "Medium Not Formatted" },
|
||||
{ 0x31, 0x00, "Medium Format Corrupted" },
|
||||
{ 0x31, 0x01, "Format Command Failed" },
|
||||
{ 0x31, 0x02, "Zoned Formatting Failed Due To Spare Linking" },
|
||||
{ 0x32, 0x00, "No Defect Spare Location Available" },
|
||||
{ 0x32, 0x01, "Defect List Update Failure" },
|
||||
{ 0x33, 0x00, "Tape Length Error" },
|
||||
{ 0x34, 0x00, "Enclosure Failure" },
|
||||
{ 0x35, 0x00, "Enclosure Services Failure" },
|
||||
{ 0x35, 0x01, "Unsupported Enclosure Function" },
|
||||
{ 0x35, 0x02, "Enclosure Services Unavailable" },
|
||||
{ 0x35, 0x03, "Enclosure Services Transfer Failed" },
|
||||
{ 0x35, 0x04, "Enclosure Services Transfer Refused" },
|
||||
{ 0x36, 0x00, "Ribbon, Ink, or Toner Failure" },
|
||||
{ 0x37, 0x00, "Rounded Parameter" },
|
||||
{ 0x39, 0x00, "Saving Parameters Not Supported" },
|
||||
{ 0x3A, 0x00, "Medium Not Present" },
|
||||
{ 0x3A, 0x01, "Medium Not Present - Tray Closed" },
|
||||
{ 0x3A, 0x02, "Medium Not Present - Tray Open" },
|
||||
{ 0x3A, 0x03, "Medium Not Present - Loadable" },
|
||||
{ 0x3A, 0x04, "Medium Not Present - Medium Auxilliary Memory Accessible" },
|
||||
{ 0x3B, 0x00, "Sequential Positioning Error" },
|
||||
{ 0x3B, 0x01, "Tape Position Error At Beginning-of-Medium" },
|
||||
{ 0x3B, 0x02, "Tape Position Error At End-of-Medium" },
|
||||
{ 0x3B, 0x03, "Tape or Electronic Vertical Forms Unit Not Ready" },
|
||||
{ 0x3B, 0x04, "Slew Failure" },
|
||||
{ 0x3B, 0x05, "Paper Jam" },
|
||||
{ 0x3B, 0x06, "Failed To Sense Top-Of-Form" },
|
||||
{ 0x3B, 0x07, "Failed To Sense Bottom-Of-Form" },
|
||||
{ 0x3B, 0x08, "Reposition Error" },
|
||||
{ 0x3B, 0x09, "Read Past End Of Medium" },
|
||||
{ 0x3B, 0x0A, "Read Past Begining Of Medium" },
|
||||
{ 0x3B, 0x0B, "Position Past End Of Medium" },
|
||||
{ 0x3B, 0x0C, "Position Past Beginning Of Medium" },
|
||||
{ 0x3B, 0x0D, "Medium Destination Element Full" },
|
||||
{ 0x3B, 0x0E, "Medium Source Element Empty" },
|
||||
{ 0x3B, 0x0F, "End Of Medium Reached" },
|
||||
{ 0x3B, 0x11, "Medium Magazine Not Accessible" },
|
||||
{ 0x3B, 0x12, "Medium Magazine Removed" },
|
||||
{ 0x3B, 0x13, "Medium Magazine Inserted" },
|
||||
{ 0x3B, 0x14, "Medium Magazine Locked" },
|
||||
{ 0x3B, 0x15, "Medium Magazine Unlocked" },
|
||||
{ 0x3B, 0x16, "Mechanical Positioning Or Changer Error" },
|
||||
{ 0x3D, 0x00, "Invalid Bits In IDENTIFY Message" },
|
||||
{ 0x3E, 0x00, "Logical Unit Has Not Self-Configured Yet" },
|
||||
{ 0x3E, 0x01, "Logical Unit Failure" },
|
||||
{ 0x3E, 0x02, "Timeout On Logical Unit" },
|
||||
{ 0x3E, 0x03, "Logical Unit Failed Self-Test" },
|
||||
{ 0x3E, 0x04, "Logical Unit Unable To Update Self-Test Log" },
|
||||
{ 0x3F, 0x00, "Target Operating Conditions Have Changed" },
|
||||
{ 0x3F, 0x01, "Microcode Has Been Changed" },
|
||||
{ 0x3F, 0x02, "Changed Operating Definition" },
|
||||
{ 0x3F, 0x03, "INQUIRY Data Has Changed" },
|
||||
{ 0x3F, 0x04, "Component Device Attached" },
|
||||
{ 0x3F, 0x05, "Device Identifier Changed" },
|
||||
{ 0x3F, 0x06, "Redundancy Group Created Or Modified" },
|
||||
{ 0x3F, 0x07, "Redundancy Group Deleted" },
|
||||
{ 0x3F, 0x08, "Spare Created Or Modified" },
|
||||
{ 0x3F, 0x09, "Spare Deleted" },
|
||||
{ 0x3F, 0x0A, "Volume Set Created Or Modified" },
|
||||
{ 0x3F, 0x0B, "Volume Set Deleted" },
|
||||
{ 0x3F, 0x0C, "Volume Set Deassigned" },
|
||||
{ 0x3F, 0x0D, "Volume Set Reassigned" },
|
||||
{ 0x3F, 0x0E, "Reported LUNs Data Has Changed" },
|
||||
{ 0x3F, 0x0F, "Echo Buffer Overwritten" },
|
||||
{ 0x3F, 0x10, "Medium Loadable" },
|
||||
{ 0x3F, 0x11, "Medium Auxiliary Memory Accessible" },
|
||||
{ 0x40, 0x00, "RAM FAILURE (Should Use 40 NN)" },
|
||||
{ 0x41, 0x00, "Data Path FAILURE (Should Use 40 NN)" },
|
||||
{ 0x42, 0x00, "Power-On or Self-Test FAILURE (Should Use 40 NN)" },
|
||||
{ 0x43, 0x00, "Message Error" },
|
||||
{ 0x44, 0x00, "Internal Target Failure" },
|
||||
{ 0x45, 0x00, "Select Or Reselect Failure" },
|
||||
{ 0x46, 0x00, "Unsuccessful Soft Reset" },
|
||||
{ 0x47, 0x00, "SCSI Parity Error" },
|
||||
{ 0x47, 0x01, "Data Phase CRC Error Detected" },
|
||||
{ 0x47, 0x02, "SCSI Parity Error Detected During ST Data Phase" },
|
||||
{ 0x47, 0x03, "Information Unit iuCRC Error Detected" },
|
||||
{ 0x47, 0x04, "Asynchronous Information Protection Error Detected" },
|
||||
{ 0x47, 0x05, "Protocol Service CRC Error" },
|
||||
{ 0x47, 0x7F, "Some Commands Cleared by iSCSI Protocol Event" },
|
||||
{ 0x48, 0x00, "INITIATOR DETECTED ERROR Message Received" },
|
||||
{ 0x49, 0x00, "Invalid Message Error" },
|
||||
{ 0x4A, 0x00, "Command Phase Error" },
|
||||
{ 0x4B, 0x00, "Data Phase Error" },
|
||||
{ 0x4B, 0x01, "Illegal Target Port Transfer Tag Received" },
|
||||
{ 0x4B, 0x02, "Too Much Write Data" },
|
||||
{ 0x4B, 0x03, "ACK/NAK Timeout" },
|
||||
{ 0x4B, 0x04, "NAK Reveived" },
|
||||
{ 0x4B, 0x05, "Data Offset Error" },
|
||||
{ 0x4B, 0x06, "Initiator Response Timeout" },
|
||||
{ 0x4C, 0x00, "Logical Unit Failed Self-Configuration" },
|
||||
{ 0x4D, 0x00, "Tagged Overlapped Commands (NN = Queue Tag)" },
|
||||
{ 0x4E, 0x00, "Overlapped Commands Attempted" },
|
||||
{ 0x50, 0x00, "Write Append Error" },
|
||||
{ 0x50, 0x01, "Write Append Position Error" },
|
||||
{ 0x50, 0x02, "Position Error Related To Timing" },
|
||||
{ 0x51, 0x00, "Erase Failure" },
|
||||
{ 0x51, 0x01, "Erase Failure - Incomplete Erase Operation Detected" },
|
||||
{ 0x52, 0x00, "Cartridge Fault" },
|
||||
{ 0x53, 0x00, "Media Load or Eject Failed" },
|
||||
{ 0x53, 0x01, "Unload Tape Failure" },
|
||||
{ 0x53, 0x02, "Medium Removal Prevented" },
|
||||
{ 0x54, 0x00, "SCSI To Host System Interface Failure" },
|
||||
{ 0x55, 0x00, "System Resource Failure" },
|
||||
{ 0x55, 0x01, "System Buffer Full" },
|
||||
{ 0x55, 0x02, "Insufficient Reservation Resources" },
|
||||
{ 0x55, 0x03, "Insufficient Resources" },
|
||||
{ 0x55, 0x04, "Insufficient Registration Resources" },
|
||||
{ 0x55, 0x05, "Insufficient Access Control Resources" },
|
||||
{ 0x55, 0x06, "Auxiliary Memory Out Of Space" },
|
||||
{ 0x57, 0x00, "Unable To Recover Table-Of-Contents" },
|
||||
{ 0x58, 0x00, "Generation Does Not Exist" },
|
||||
{ 0x59, 0x00, "Updated Block Read" },
|
||||
{ 0x5A, 0x00, "Operator Request or State Change Input (Unspecified)" },
|
||||
{ 0x5A, 0x01, "Operator Medium Removal Requested" },
|
||||
{ 0x5A, 0x02, "Operator Selected Write Protect" },
|
||||
{ 0x5A, 0x03, "Operator Selected Write Permit" },
|
||||
{ 0x5B, 0x00, "Log Exception" },
|
||||
{ 0x5B, 0x01, "Threshold Condition Met" },
|
||||
{ 0x5B, 0x02, "Log Counter At Maximum" },
|
||||
{ 0x5B, 0x03, "Log List Codes Exhausted" },
|
||||
{ 0x5C, 0x00, "RPL Status Change" },
|
||||
{ 0x5C, 0x01, "Spindles Synchronized" },
|
||||
{ 0x5C, 0x02, "Spindles Not Synchronized" },
|
||||
{ 0x5D, 0x00, "Failure Prediction Threshold Exceeded" },
|
||||
{ 0x5D, 0x01, "Media Failure Prediction Threshold Exceeded" },
|
||||
{ 0x5D, 0x02, "Logical Unit Failure Prediction Threshold Exceeded" },
|
||||
{ 0x5D, 0x03, "Spare Area Exhaustion Prediction Threshold Exceeded" },
|
||||
{ 0x5D, 0x10, "Hardware Impending Failure General Hard Drive Failure" },
|
||||
{ 0x5D, 0x11, "Hardware Impending Failure Drive Error Rate Too High" },
|
||||
{ 0x5D, 0x12, "Hardware Impending Failure Data Error Rate Too High" },
|
||||
{ 0x5D, 0x13, "Hardware Impending Failure Seek Error Rate Too High" },
|
||||
{ 0x5D, 0x14, "Hardware Impending Failure Too Many Block Reassigns" },
|
||||
{ 0x5D, 0x15, "Hardware Impending Failure Access Times Too High" },
|
||||
{ 0x5D, 0x16, "Hardware Impending Failure Start Unit Times Too High" },
|
||||
{ 0x5D, 0x17, "Hardware Impending Failure Channel Parametrics" },
|
||||
{ 0x5D, 0x18, "Hardware Impending Failure Controller Detected" },
|
||||
{ 0x5D, 0x19, "Hardware Impending Failure Throughput Performance" },
|
||||
{ 0x5D, 0x1A, "Hardware Impending Failure Seek Time Performance" },
|
||||
{ 0x5D, 0x1B, "Hardware Impending Failure Spin-Up Retry Count" },
|
||||
{ 0x5D, 0x1C, "Hardware Impending Failure Drive Calibration Retry Count" },
|
||||
{ 0x5D, 0x20, "Controller Impending Failure General Hard Drive Failure" },
|
||||
{ 0x5D, 0x21, "Controller Impending Failure Drive Error Rate Too High" },
|
||||
{ 0x5D, 0x22, "Controller Impending Failure Data Error Rate Too High" },
|
||||
{ 0x5D, 0x23, "Controller Impending Failure Seek Error Rate Too High" },
|
||||
{ 0x5D, 0x24, "Controller Impending Failure Too Many Block Reassigns" },
|
||||
{ 0x5D, 0x25, "Controller Impending Failure Access Times Too High" },
|
||||
{ 0x5D, 0x26, "Controller Impending Failure Start Unit Times Too High" },
|
||||
{ 0x5D, 0x27, "Controller Impending Failure Channel Parametrics" },
|
||||
{ 0x5D, 0x28, "Controller Impending Failure Controller Detected" },
|
||||
{ 0x5D, 0x29, "Controller Impending Failure Throughput Performance" },
|
||||
{ 0x5D, 0x2A, "Controller Impending Failure Seek Time Performance" },
|
||||
{ 0x5D, 0x2B, "Controller Impending Failure Spin-Up Retry Count" },
|
||||
{ 0x5D, 0x2C, "Controller Impending Failure Drive Calibration Retry Count" },
|
||||
{ 0x5D, 0x30, "Data Channel Impending Failure General Hard Drive Failure" },
|
||||
{ 0x5D, 0x31, "Data Channel Impending Failure Drive Error Rate Too High" },
|
||||
{ 0x5D, 0x32, "Data Channel Impending Failure Data Error Rate Too High" },
|
||||
{ 0x5D, 0x33, "Data Channel Impending Failure Seek Error Rate Too High" },
|
||||
{ 0x5D, 0x34, "Data Channel Impending Failure Too Many Block Reassigns" },
|
||||
{ 0x5D, 0x35, "Data Channel Impending Failure Access Times Too High" },
|
||||
{ 0x5D, 0x36, "Data Channel Impending Failure Start Unit Times Too High" },
|
||||
{ 0x5D, 0x37, "Data Channel Impending Failure Channel Parametrics" },
|
||||
{ 0x5D, 0x38, "Data Channel Impending Failure Controller Detected" },
|
||||
{ 0x5D, 0x39, "Data Channel Impending Failure Throughput Performance" },
|
||||
{ 0x5D, 0x3A, "Data Channel Impending Failure Seek Time Performance" },
|
||||
{ 0x5D, 0x3B, "Data Channel Impending Failure Spin-Up Retry Count" },
|
||||
{ 0x5D, 0x3C, "Data Channel Impending Failure Drive Calibration Retry Count" },
|
||||
{ 0x5D, 0x40, "Servo Impending Failure General Hard Drive Failure" },
|
||||
{ 0x5D, 0x41, "Servo Impending Failure Drive Error Rate Too High" },
|
||||
{ 0x5D, 0x42, "Servo Impending Failure Data Error Rate Too High" },
|
||||
{ 0x5D, 0x43, "Servo Impending Failure Seek Error Rate Too High" },
|
||||
{ 0x5D, 0x44, "Servo Impending Failure Too Many Block Reassigns" },
|
||||
{ 0x5D, 0x45, "Servo Impending Failure Access Times Too High" },
|
||||
{ 0x5D, 0x46, "Servo Impending Failure Start Unit Times Too High" },
|
||||
{ 0x5D, 0x47, "Servo Impending Failure Channel Parametrics" },
|
||||
{ 0x5D, 0x48, "Servo Impending Failure Controller Detected" },
|
||||
{ 0x5D, 0x49, "Servo Impending Failure Throughput Performance" },
|
||||
{ 0x5D, 0x4A, "Servo Impending Failure Seek Time Performance" },
|
||||
{ 0x5D, 0x4B, "Servo Impending Failure Spin-Up Retry Count" },
|
||||
{ 0x5D, 0x4C, "Servo Impending Failure Drive Calibration Retry Count" },
|
||||
{ 0x5D, 0x50, "Spindle Impending Failure General Hard Drive Failure" },
|
||||
{ 0x5D, 0x51, "Spindle Impending Failure Drive Error Rate Too High" },
|
||||
{ 0x5D, 0x52, "Spindle Impending Failure Data Error Rate Too High" },
|
||||
{ 0x5D, 0x53, "Spindle Impending Failure Seek Error Rate Too High" },
|
||||
{ 0x5D, 0x54, "Spindle Impending Failure Too Many Block Reassigns" },
|
||||
{ 0x5D, 0x55, "Spindle Impending Failure Access Times Too High" },
|
||||
{ 0x5D, 0x56, "Spindle Impending Failure Start Unit Times Too High" },
|
||||
{ 0x5D, 0x57, "Spindle Impending Failure Channel Parametrics" },
|
||||
{ 0x5D, 0x58, "Spindle Impending Failure Controller Detected" },
|
||||
{ 0x5D, 0x59, "Spindle Impending Failure Throughput Performance" },
|
||||
{ 0x5D, 0x5A, "Spindle Impending Failure Seek Time Performance" },
|
||||
{ 0x5D, 0x5B, "Spindle Impending Failure Spin-Up Retry Count" },
|
||||
{ 0x5D, 0x5C, "Spindle Impending Failure Drive Calibration Retry Count" },
|
||||
{ 0x5D, 0x60, "Firmware Impending Failure General Hard Drive Failure" },
|
||||
{ 0x5D, 0x61, "Firmware Impending Failure Drive Error Rate Too High" },
|
||||
{ 0x5D, 0x62, "Firmware Impending Failure Data Error Rate Too High" },
|
||||
{ 0x5D, 0x63, "Firmware Impending Failure Seek Error Rate Too High" },
|
||||
{ 0x5D, 0x64, "Firmware Impending Failure Too Many Block Reassigns" },
|
||||
{ 0x5D, 0x65, "Firmware Impending Failure Access Times Too High" },
|
||||
{ 0x5D, 0x66, "Firmware Impending Failure Start Unit Times Too High" },
|
||||
{ 0x5D, 0x67, "Firmware Impending Failure Channel Parametrics" },
|
||||
{ 0x5D, 0x68, "Firmware Impending Failure Controller Detected" },
|
||||
{ 0x5D, 0x69, "Firmware Impending Failure Throughput Performance" },
|
||||
{ 0x5D, 0x6A, "Firmware Impending Failure Seek Time Performance" },
|
||||
{ 0x5D, 0x6B, "Firmware Impending Failure Spin-Up Retry Count" },
|
||||
{ 0x5D, 0x6C, "Firmware Impending Failure Drive Calibration Retry Count" },
|
||||
{ 0x5D, 0xFF, "Failure Prediction Threshold Exceeded (False)" },
|
||||
{ 0x5E, 0x00, "Low Power Condition On" },
|
||||
{ 0x5E, 0x01, "Idle Condition Activated By Timer" },
|
||||
{ 0x5E, 0x02, "Standby Condition Activated By Timer" },
|
||||
{ 0x5E, 0x03, "Idle Condition Activated By Command" },
|
||||
{ 0x5E, 0x04, "Standby Condition Activated By Command" },
|
||||
{ 0x5E, 0x41, "Power State Change To Active" },
|
||||
{ 0x5E, 0x42, "Power State Change To Idle" },
|
||||
{ 0x5E, 0x43, "Power State Change To Standby" },
|
||||
{ 0x5E, 0x45, "Power State Change To Sleep" },
|
||||
{ 0x5E, 0x47, "Power State Change To Device Control" },
|
||||
{ 0x60, 0x00, "Lamp Failure" },
|
||||
{ 0x61, 0x00, "Video Acquisition Error" },
|
||||
{ 0x61, 0x01, "Unable To Acquire Video" },
|
||||
{ 0x61, 0x02, "Out Of Focus" },
|
||||
{ 0x62, 0x00, "Scan Head Positioning Error" },
|
||||
{ 0x63, 0x00, "End Of User Area Encountered On This Track" },
|
||||
{ 0x63, 0x01, "Packet Does Not Fit In Available Space" },
|
||||
{ 0x64, 0x00, "Illegal Mode For This Track" },
|
||||
{ 0x64, 0x01, "Invalid Packet Size" },
|
||||
{ 0x65, 0x00, "Voltage Fault" },
|
||||
{ 0x66, 0x00, "Automatic Document Feeder Cover Up" },
|
||||
{ 0x66, 0x01, "Automatic Document Feeder Lift Up" },
|
||||
{ 0x66, 0x02, "Document Jam In Automatic Document Feeder" },
|
||||
{ 0x66, 0x03, "Document Misfeed In Automatic Document Feeder" },
|
||||
{ 0x67, 0x00, "Configuration Failure" },
|
||||
{ 0x67, 0x01, "Configuration Of Incapable Logical Units Failed" },
|
||||
{ 0x67, 0x02, "Add Logical Unit Failed" },
|
||||
{ 0x67, 0x03, "Modification Of Logical Unit Failed" },
|
||||
{ 0x67, 0x04, "Exchange Of Logical Unit Failed" },
|
||||
{ 0x67, 0x05, "Remove Of Logical Unit Failed" },
|
||||
{ 0x67, 0x06, "Attachment Of Logical Unit Failed" },
|
||||
{ 0x67, 0x07, "Creation of Logical Unit Failed" },
|
||||
{ 0x67, 0x08, "Assign Failure Occurred" },
|
||||
{ 0x67, 0x09, "Multiply Assigned Logical Unit" },
|
||||
{ 0x67, 0x0A, "Set Target Port Groups Command Failed" },
|
||||
{ 0x68, 0x00, "Logical Unit Not Configured" },
|
||||
{ 0x69, 0x00, "Data Loss On Logical Unit" },
|
||||
{ 0x69, 0x01, "Multiple Logical Unit Failures" },
|
||||
{ 0x69, 0x02, "Parity/Data Mismatch" },
|
||||
{ 0x6A, 0x00, "Informational, Refer To Log" },
|
||||
{ 0x6B, 0x00, "State Change Has Occurred" },
|
||||
{ 0x6B, 0x01, "Redundancy Level Got Better" },
|
||||
{ 0x6B, 0x02, "Redundancy Level Got Worse" },
|
||||
{ 0x6C, 0x00, "Rebuild Failure Occurred" },
|
||||
{ 0x6D, 0x00, "Recalculate Failure Occurred" },
|
||||
{ 0x6E, 0x00, "Command To Logical Unit Failed" },
|
||||
{ 0x6F, 0x00, "Copy Protection Key Exchange Failure - Authentication Failure" },
|
||||
{ 0x6F, 0x01, "Copy Protection Key Exchange Failure - Key Not Present" },
|
||||
{ 0x6F, 0x02, "Copy Protection Key Exchange Failure - Key Not Established" },
|
||||
{ 0x6F, 0x03, "Read Of Scrambled Sector Without Authentication" },
|
||||
{ 0x6F, 0x04, "Media Region Code Is Mismatched To Logical Unit Region" },
|
||||
{ 0x6F, 0x05, "Drive Region Must Be Permanent/Region Reset Count Error" },
|
||||
{ 0x70, 0x00, "Decompression Exception Short Algorithm ID Of NN" },
|
||||
{ 0x71, 0x00, "Decompression Exception Long Algorithm ID" },
|
||||
{ 0x72, 0x00, "Session Fixation Error" },
|
||||
{ 0x72, 0x01, "Session Fixation Error Writing Lead-In" },
|
||||
{ 0x72, 0x02, "Session Fixation Error Writing Lead-Out" },
|
||||
{ 0x72, 0x03, "Session Fixation Error - Incomplete Track In Session" },
|
||||
{ 0x72, 0x04, "Empty Or Partially Written Reserved Track" },
|
||||
{ 0x72, 0x05, "No More Track Reservations Allowed" },
|
||||
{ 0x73, 0x00, "CD Control Error" },
|
||||
{ 0x73, 0x01, "Power Calibration Area Almost Full" },
|
||||
{ 0x73, 0x02, "Power Calibration Area Is Full" },
|
||||
{ 0x73, 0x03, "Power Calibration Area Error" },
|
||||
{ 0x73, 0x04, "Program Memory Area Update Failure" },
|
||||
{ 0x73, 0x05, "Program Memory Area Is Full" },
|
||||
{ 0x73, 0x06, "RMA/PMA Is Almost Full" },
|
||||
{ 0x00, 0x00, NULL }
|
||||
};
|
||||
|
||||
|
||||
/* needs to move to a compat.c one day */
|
||||
#ifdef NO_STRLCPY
|
||||
|
||||
size_t
|
||||
strlcpy(char *dst, const char *src, size_t size)
|
||||
{
|
||||
strncpy(dst, src, size-1);
|
||||
dst[size] = '\0';
|
||||
|
||||
return strlen(src);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
asc2ascii(u_char asc, u_char ascq, char *result, size_t l)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (adesc[i].description != NULL) {
|
||||
if (adesc[i].asc == asc && adesc[i].ascq == ascq)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (adesc[i].description == NULL) {
|
||||
if (asc == 0x40 && ascq != 0)
|
||||
(void) snprintf(result, l,
|
||||
"Diagnostic Failure on Component 0x%02x",
|
||||
ascq & 0xff);
|
||||
else
|
||||
(void) snprintf(result, l, "ASC 0x%02x ASCQ 0x%02x",
|
||||
asc & 0xff, ascq & 0xff);
|
||||
} else
|
||||
(void) strlcpy(result, adesc[i].description, l);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uscsi_print_sense_data(uint8_t *s, int slen, int verbosity)
|
||||
{
|
||||
int32_t info;
|
||||
int i, j, k;
|
||||
char *sbs;
|
||||
|
||||
/*
|
||||
* Basics - print out SENSE KEY
|
||||
*/
|
||||
printf(" SENSE KEY: %s", uscsi_decode_sense(s, 0));
|
||||
|
||||
/*
|
||||
* Print out, unqualified but aligned, FMK, EOM and ILI status.
|
||||
*/
|
||||
if (s[2] & 0xe0) {
|
||||
char pad;
|
||||
printf("\n ");
|
||||
pad = ' ';
|
||||
if (s[2] & SSD_FILEMARK) {
|
||||
printf("%c Filemark Detected", pad);
|
||||
pad = ',';
|
||||
}
|
||||
if (s[2] & SSD_EOM) {
|
||||
printf("%c EOM Detected", pad);
|
||||
pad = ',';
|
||||
}
|
||||
if (s[2] & SSD_ILI)
|
||||
printf("%c Incorrect Length Indicator Set", pad);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we should figure out, based upon device type, how
|
||||
* to format the information field. Unfortunately, that's
|
||||
* not convenient here, so we'll print it as a signed
|
||||
* 32 bit integer.
|
||||
*/
|
||||
//info = _4btol(&s[3]);
|
||||
info = (s[3] << 24) | (s[4] << 16) | (s[5] << 8) | s[6];
|
||||
if (info)
|
||||
printf("\n INFO FIELD: %d", info);
|
||||
|
||||
/*
|
||||
* Now we check additional length to see whether there is
|
||||
* more information to extract.
|
||||
*/
|
||||
|
||||
/* enough for command specific information? */
|
||||
if (((unsigned int) s[7]) < 4) {
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
// info = _4btol(&s[8]);
|
||||
info = (s[8] << 24) | (s[9] << 16) | (s[10] << 8) | s[11];
|
||||
if (info)
|
||||
printf("\n COMMAND INFO: %d (0x%x)", info, info);
|
||||
|
||||
/*
|
||||
* Decode ASC && ASCQ info, plus FRU, plus the rest...
|
||||
*/
|
||||
|
||||
sbs = uscsi_decode_sense(s, 1);
|
||||
if (sbs)
|
||||
printf("\n ASC/ASCQ: %s", sbs);
|
||||
if (s[14] != 0)
|
||||
printf("\n FRU CODE: 0x%x", s[14] & 0xff);
|
||||
sbs = uscsi_decode_sense(s, 3);
|
||||
if (sbs)
|
||||
printf("\n SKSV: %s", sbs);
|
||||
printf("\n");
|
||||
if (verbosity == 0) {
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now figure whether we should print any additional informtion.
|
||||
*
|
||||
* Where should we start from? If we had SKSV data,
|
||||
* start from offset 18, else from offset 15.
|
||||
*
|
||||
* From that point until the end of the buffer, check for any
|
||||
* nonzero data. If we have some, go back and print the lot,
|
||||
* otherwise we're done.
|
||||
*/
|
||||
if (sbs)
|
||||
i = 18;
|
||||
else
|
||||
i = 15;
|
||||
for (j = i; j < slen; j++)
|
||||
if (s[j])
|
||||
break;
|
||||
if (j == slen)
|
||||
return;
|
||||
|
||||
printf("\n Additional Sense Information (byte %d out...):\n", i);
|
||||
if (i == 15) {
|
||||
printf("\n\t%2d:", i);
|
||||
k = 7;
|
||||
} else {
|
||||
printf("\n\t%2d:", i);
|
||||
k = 2;
|
||||
j -= 2;
|
||||
}
|
||||
while (j > 0) {
|
||||
if (i >= slen)
|
||||
break;
|
||||
if (k == 8) {
|
||||
k = 0;
|
||||
printf("\n\t%2d:", i);
|
||||
}
|
||||
printf(" 0x%02x", s[i] & 0xff);
|
||||
k++;
|
||||
j--;
|
||||
i++;
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
uscsi_decode_sense(void *sinfo, int flag)
|
||||
{
|
||||
unsigned char *snsbuf;
|
||||
unsigned char skey;
|
||||
static char rqsbuf[132];
|
||||
|
||||
skey = 0;
|
||||
|
||||
snsbuf = (unsigned char *) sinfo;
|
||||
if (flag == 0 || flag == 2 || flag == 3)
|
||||
skey = snsbuf[2] & 0xf;
|
||||
if (flag == 0) { /* Sense Key Only */
|
||||
(void) strlcpy(rqsbuf, sense_keys[skey], sizeof(rqsbuf));
|
||||
return (rqsbuf);
|
||||
} else if (flag == 1) { /* ASC/ASCQ Only */
|
||||
asc2ascii(snsbuf[12], snsbuf[13], rqsbuf, sizeof(rqsbuf));
|
||||
return (rqsbuf);
|
||||
} else if (flag == 2) { /* Sense Key && ASC/ASCQ */
|
||||
auto char localbuf[64];
|
||||
asc2ascii(snsbuf[12], snsbuf[13], localbuf, sizeof(localbuf));
|
||||
(void) snprintf(rqsbuf, sizeof(rqsbuf), "%s, %s",
|
||||
sense_keys[skey], localbuf);
|
||||
return (rqsbuf);
|
||||
} else if (flag == 3 && snsbuf[7] >= 9 && (snsbuf[15] & 0x80)) {
|
||||
/*
|
||||
* SKSV Data
|
||||
*/
|
||||
switch (skey) {
|
||||
case SKEY_ILLEGAL_REQUEST:
|
||||
if (snsbuf[15] & 0x8)
|
||||
(void)snprintf(rqsbuf, sizeof(rqsbuf),
|
||||
"Error in %s, Offset %d, bit %d",
|
||||
(snsbuf[15] & 0x40)? "CDB" : "Parameters",
|
||||
(snsbuf[16] & 0xff) << 8 |
|
||||
(snsbuf[17] & 0xff), snsbuf[15] & 0x7);
|
||||
else
|
||||
(void)snprintf(rqsbuf, sizeof(rqsbuf),
|
||||
"Error in %s, Offset %d",
|
||||
(snsbuf[15] & 0x40)? "CDB" : "Parameters",
|
||||
(snsbuf[16] & 0xff) << 8 |
|
||||
(snsbuf[17] & 0xff));
|
||||
return (rqsbuf);
|
||||
|
||||
case SKEY_RECOVERED_ERROR:
|
||||
case SKEY_MEDIUM_ERROR:
|
||||
case SKEY_HARDWARE_ERROR:
|
||||
(void)snprintf(rqsbuf, sizeof(rqsbuf),
|
||||
"Actual Retry Count: %d",
|
||||
(snsbuf[16] & 0xff) << 8 | (snsbuf[17] & 0xff));
|
||||
return (rqsbuf);
|
||||
|
||||
case SKEY_NOT_READY:
|
||||
(void)snprintf(rqsbuf, sizeof(rqsbuf),
|
||||
"Progress Indicator: %d",
|
||||
(snsbuf[16] & 0xff) << 8 | (snsbuf[17] & 0xff));
|
||||
return (rqsbuf);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uscsi_print_sense(const char *name, u_char *req_cmd, int req_cmdlen,
|
||||
u_char *req_sense, int req_senselen_used, int verbosity)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("%s: Check Condition on CDB:", name);
|
||||
for (i = 0; i < req_cmdlen; i++)
|
||||
printf(" %02x", req_cmd[i]);
|
||||
printf("\n");
|
||||
uscsi_print_sense_data(req_sense, req_senselen_used, verbosity);
|
||||
}
|
||||
|
580
usr.sbin/mmcformat/uscsi_subr.c
Normal file
580
usr.sbin/mmcformat/uscsi_subr.c
Normal file
@ -0,0 +1,580 @@
|
||||
/* $NetBSD: uscsi_subr.c,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
|
||||
* Simulation Facility, NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Small changes, generalisations and Linux support by Reinoud Zandijk
|
||||
* <reinoud@netbsd.org>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* SCSI support subroutines.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "uscsilib.h"
|
||||
|
||||
|
||||
int uscsilib_verbose = 0;
|
||||
|
||||
|
||||
#ifdef USCSI_SCSIPI
|
||||
/*
|
||||
* scsipi is a integrated SCSI and ATAPI layer under NetBSD and exists
|
||||
* in a modified form under OpenBSD and possibly also under other
|
||||
* operating systems.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/scsiio.h>
|
||||
#ifdef __OpenBSD__
|
||||
#include <scsi/uscsi_all.h>
|
||||
#else
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
uscsi_open(struct uscsi_dev *disc)
|
||||
{
|
||||
struct stat dstat;
|
||||
|
||||
disc->fhandle = open(disc->dev_name, O_RDWR, 0); /* no create */
|
||||
if (disc->fhandle<0) {
|
||||
perror("Failure to open device or file");
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
if (fstat(disc->fhandle, &dstat) < 0) {
|
||||
perror("Can't stat device or file");
|
||||
uscsi_close(disc);
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_close(struct uscsi_dev * disc)
|
||||
{
|
||||
close(disc->fhandle);
|
||||
disc->fhandle = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_command(int flags, struct uscsi_dev *disc,
|
||||
void *cmd, size_t cmdlen, void *data, size_t datalen,
|
||||
uint32_t timeout, struct uscsi_sense *uscsi_sense)
|
||||
{
|
||||
scsireq_t req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
if (uscsi_sense)
|
||||
bzero(uscsi_sense, sizeof(struct uscsi_sense));
|
||||
|
||||
memcpy(req.cmd, cmd, cmdlen);
|
||||
req.cmdlen = cmdlen;
|
||||
req.databuf = data;
|
||||
req.datalen = datalen;
|
||||
req.timeout = timeout;
|
||||
req.flags = flags;
|
||||
req.senselen = SENSEBUFLEN;
|
||||
|
||||
if (ioctl(disc->fhandle, SCIOCCOMMAND, &req) == -1)
|
||||
err(1, "SCIOCCOMMAND");
|
||||
|
||||
if (req.retsts == SCCMD_OK)
|
||||
return 0;
|
||||
|
||||
/* Some problem; report it and exit. */
|
||||
if (req.retsts == SCCMD_TIMEOUT) {
|
||||
if (uscsilib_verbose)
|
||||
fprintf(stderr, "%s: SCSI command timed out\n",
|
||||
disc->dev_name);
|
||||
return EAGAIN;
|
||||
} else if (req.retsts == SCCMD_BUSY) {
|
||||
if (uscsilib_verbose)
|
||||
fprintf(stderr, "%s: device is busy\n",
|
||||
disc->dev_name);
|
||||
return EBUSY;
|
||||
} else if (req.retsts == SCCMD_SENSE) {
|
||||
if (uscsi_sense) {
|
||||
uscsi_sense->asc = req.sense[12];
|
||||
uscsi_sense->ascq = req.sense[13];
|
||||
uscsi_sense->skey_valid = req.sense[15] & 128;
|
||||
uscsi_sense->sense_key = (req.sense[16] << 8) |
|
||||
(req.sense[17]);
|
||||
}
|
||||
if (uscsilib_verbose)
|
||||
uscsi_print_sense((char *) disc->dev_name,
|
||||
req.cmd, req.cmdlen,
|
||||
req.sense, req.senselen_used, 1);
|
||||
return EIO;
|
||||
} else
|
||||
if (uscsilib_verbose)
|
||||
fprintf(stderr, "%s: device had unknown status %x\n",
|
||||
disc->dev_name,
|
||||
req.retsts);
|
||||
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The reasoning behind this explicit copy is for compatibility with changes
|
||||
* in our uscsi_addr structure.
|
||||
*/
|
||||
int
|
||||
uscsi_identify(struct uscsi_dev *disc, struct uscsi_addr *saddr)
|
||||
{
|
||||
struct scsi_addr raddr;
|
||||
int error;
|
||||
|
||||
bzero(saddr, sizeof(struct scsi_addr));
|
||||
error = ioctl(disc->fhandle, SCIOCIDENTIFY, &raddr);
|
||||
if (error) return error;
|
||||
|
||||
#ifdef __NetBSD__
|
||||
/* scsi and atapi are split up like in uscsi_addr */
|
||||
if (raddr.type == 0) {
|
||||
saddr->type = USCSI_TYPE_SCSI;
|
||||
saddr->addr.scsi.scbus = raddr.addr.scsi.scbus;
|
||||
saddr->addr.scsi.target = raddr.addr.scsi.target;
|
||||
saddr->addr.scsi.lun = raddr.addr.scsi.lun;
|
||||
} else {
|
||||
saddr->type = USCSI_TYPE_ATAPI;
|
||||
saddr->addr.atapi.atbus = raddr.addr.atapi.atbus;
|
||||
saddr->addr.atapi.drive = raddr.addr.atapi.drive;
|
||||
}
|
||||
#endif
|
||||
#ifdef __OpenBSD__
|
||||
/* atapi's are shown as SCSI devices */
|
||||
if (raddr.type == 0) {
|
||||
saddr->type = USCSI_TYPE_SCSI;
|
||||
saddr->addr.scsi.scbus = raddr.scbus;
|
||||
saddr->addr.scsi.target = raddr.target;
|
||||
saddr->addr.scsi.lun = raddr.lun;
|
||||
} else {
|
||||
saddr->type = USCSI_TYPE_ATAPI;
|
||||
saddr->addr.atapi.atbus = raddr.scbus; /* overload */
|
||||
saddr->addr.atapi.drive = raddr.target; /* overload */
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_check_for_scsi(struct uscsi_dev *disc)
|
||||
{
|
||||
struct uscsi_addr saddr;
|
||||
|
||||
return uscsi_identify(disc, &saddr);
|
||||
}
|
||||
#endif /* SCSILIB_SCSIPI */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USCSI_LINUX_SCSI
|
||||
/*
|
||||
* Support code for Linux SCSI code. It uses the ioctl() way of
|
||||
* communicating since this is more close to the origional NetBSD
|
||||
* scsipi implementation.
|
||||
*/
|
||||
#include <scsi/sg.h>
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#define SENSEBUFLEN 48
|
||||
|
||||
|
||||
int
|
||||
uscsi_open(struct uscsi_dev * disc)
|
||||
{
|
||||
int flags;
|
||||
struct stat stat;
|
||||
|
||||
/* in Linux we are NOT allowed to open it blocking */
|
||||
/* no create! */
|
||||
disc->fhandle = open(disc->dev_name, O_RDWR | O_NONBLOCK, 0);
|
||||
if (disc->fhandle<0) {
|
||||
perror("Failure to open device or file");
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
/* explicitly mark it non blocking (again) (silly Linux) */
|
||||
flags = fcntl(disc->fhandle, F_GETFL);
|
||||
flags &= ~O_NONBLOCK;
|
||||
fcntl(disc->fhandle, F_SETFL, flags);
|
||||
|
||||
if (fstat(disc->fhandle, &stat) < 0) {
|
||||
perror("Can't stat device or file");
|
||||
uscsi_close(disc);
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_close(struct uscsi_dev * disc)
|
||||
{
|
||||
close(disc->fhandle);
|
||||
disc->fhandle = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_command(int flags, struct uscsi_dev *disc,
|
||||
void *cmd, size_t cmdlen,
|
||||
void *data, size_t datalen,
|
||||
uint32_t timeout, struct uscsi_sense *uscsi_sense)
|
||||
{
|
||||
struct sg_io_hdr req;
|
||||
uint8_t sense_buffer[SENSEBUFLEN];
|
||||
int error;
|
||||
|
||||
bzero(&req, sizeof(req));
|
||||
if (flags == SG_DXFER_FROM_DEV) bzero(data, datalen);
|
||||
|
||||
req.interface_id = 'S';
|
||||
req.dxfer_direction = flags;
|
||||
req.cmd_len = cmdlen;
|
||||
req.mx_sb_len = SENSEBUFLEN;
|
||||
req.iovec_count = 0;
|
||||
req.dxfer_len = datalen;
|
||||
req.dxferp = data;
|
||||
req.cmdp = cmd;
|
||||
req.sbp = sense_buffer;
|
||||
req.flags = 0;
|
||||
req.timeout = timeout;
|
||||
|
||||
error = ioctl(disc->fhandle, SG_IO, &req);
|
||||
|
||||
if (req.status) {
|
||||
/* Is this OK? */
|
||||
if (uscsi_sense) {
|
||||
uscsi_sense->asc = sense_buffer[12];
|
||||
uscsi_sense->ascq = sense_buffer[13];
|
||||
uscsi_sense->skey_valid = sense_buffer[15] & 128;
|
||||
uscsi_sense->sense_key = (sense_buffer[16] << 8) |
|
||||
(sense_buffer[17]);
|
||||
}
|
||||
if (uscsilib_verbose) {
|
||||
uscsi_print_sense((char *) disc->dev_name,
|
||||
cmd, cmdlen, sense_buffer, req.sb_len_wr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_identify(struct uscsi_dev *disc, struct uscsi_addr *saddr)
|
||||
{
|
||||
struct sg_scsi_id sg_scsi_id;
|
||||
struct sg_id {
|
||||
/* target | lun << 8 | channel << 16 | low_ino << 24 */
|
||||
uint32_t tlci;
|
||||
uint32_t uniq_id;
|
||||
} sg_id;
|
||||
int emulated;
|
||||
int error;
|
||||
|
||||
/* clean result */
|
||||
bzero(saddr, sizeof(struct uscsi_addr));
|
||||
|
||||
/* check if its really SCSI or emulated SCSI (ATAPI f.e.) */
|
||||
saddr->type = USCSI_TYPE_SCSI;
|
||||
ioctl(disc->fhandle, SG_EMULATED_HOST, &emulated);
|
||||
if (emulated) saddr->type = USCSI_TYPE_ATAPI;
|
||||
|
||||
/* try 2.4 kernel or older */
|
||||
error = ioctl(disc->fhandle, SG_GET_SCSI_ID, &sg_scsi_id);
|
||||
if (!error) {
|
||||
saddr->addr.scsi.target = sg_scsi_id.scsi_id;
|
||||
saddr->addr.scsi.lun = sg_scsi_id.lun;
|
||||
saddr->addr.scsi.scbus = sg_scsi_id.channel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 2.6 kernel or newer */
|
||||
error = ioctl(disc->fhandle, SCSI_IOCTL_GET_IDLUN, &sg_id);
|
||||
if (error) return error;
|
||||
|
||||
saddr->addr.scsi.target = (sg_id.tlci ) & 0xff;
|
||||
saddr->addr.scsi.lun = (sg_id.tlci >> 8) & 0xff;
|
||||
saddr->addr.scsi.scbus = (sg_id.tlci >> 16) & 0xff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uscsi_check_for_scsi(struct uscsi_dev *disc) {
|
||||
struct uscsi_addr saddr;
|
||||
|
||||
return uscsi_identify(disc, &saddr);
|
||||
}
|
||||
#endif /* USCSI_LINUX_SCSI */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USCSI_FREEBSD_CAM
|
||||
|
||||
int
|
||||
uscsi_open(struct uscsi_dev *disc)
|
||||
{
|
||||
disc->devhandle = cam_open_device(disc->dev_name, O_RDWR);
|
||||
|
||||
if (disc->devhandle == NULL) {
|
||||
disc->fhandle = open(disc->dev_name, O_RDWR | O_NONBLOCK, 0);
|
||||
if (disc->fhandle < 0) {
|
||||
perror("Failure to open device or file");
|
||||
return ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_close(struct uscsi_dev *disc)
|
||||
{
|
||||
if (disc->devhandle != NULL) {
|
||||
cam_close_device(disc->devhandle);
|
||||
disc->devhandle = NULL;
|
||||
} else {
|
||||
close(disc->fhandle);
|
||||
disc->fhandle = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_command(int flags, struct uscsi_dev *disc,
|
||||
void *cmd, size_t cmdlen,
|
||||
void *data, size_t datalen,
|
||||
uint32_t timeout, struct uscsi_sense *uscsi_sense)
|
||||
{
|
||||
struct cam_device *cam_dev;
|
||||
struct scsi_sense_data *cam_sense_data;
|
||||
union ccb ccb;
|
||||
uint32_t cam_sense;
|
||||
uint8_t *keypos;
|
||||
int camflags;
|
||||
|
||||
memset(&ccb, 0, sizeof(ccb));
|
||||
cam_dev = (struct cam_device *) disc->devhandle;
|
||||
|
||||
if (datalen == 0) flags = SCSI_NODATACMD;
|
||||
/* optional : */
|
||||
/* if (data) assert(flags == SCSI_NODATACMD); */
|
||||
|
||||
camflags = CAM_DIR_NONE;
|
||||
if (flags & SCSI_READCMD)
|
||||
camflags = CAM_DIR_IN;
|
||||
if (flags & SCSI_WRITECMD)
|
||||
camflags = CAM_DIR_OUT;
|
||||
|
||||
cam_fill_csio(
|
||||
&ccb.csio,
|
||||
0, /* retries */
|
||||
NULL, /* cbfcnp */
|
||||
camflags, /* flags */
|
||||
MSG_SIMPLE_Q_TAG, /* tag_action */
|
||||
(u_int8_t *) data, /* data_ptr */
|
||||
datalen, /* dxfer_len */
|
||||
SSD_FULL_SIZE, /* sense_len */
|
||||
cmdlen, /* cdb_len */
|
||||
timeout /* timeout */
|
||||
);
|
||||
|
||||
/* Disable freezing the device queue */
|
||||
ccb.ccb_h.flags |= CAM_DEV_QFRZDIS;
|
||||
|
||||
memcpy(ccb.csio.cdb_io.cdb_bytes, cmd, cmdlen);
|
||||
|
||||
/* Send the command down via the CAM interface */
|
||||
if (cam_send_ccb(cam_dev, &ccb) < 0) {
|
||||
err(1, "cam_send_ccb");
|
||||
}
|
||||
|
||||
if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
|
||||
return 0;
|
||||
|
||||
/* print error using the uscsi_sense routines? */
|
||||
|
||||
cam_sense = (ccb.ccb_h.status & (CAM_STATUS_MASK | CAM_AUTOSNS_VALID));
|
||||
if (cam_sense != (CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID))
|
||||
return EFAULT;
|
||||
|
||||
/* drive responds with sense information */
|
||||
if (!uscsilib_verbose)
|
||||
return EFAULT;
|
||||
|
||||
/* print sense info */
|
||||
cam_sense_data = &ccb.csio.sense_data;
|
||||
if (uscsi_sense) {
|
||||
uscsi_sense->asc = cam_sense_data->add_sense_code;
|
||||
uscsi_sense->ascq = cam_sense_data->add_sense_code_qual;
|
||||
keypos = cam_sense_data->sense_key_spec;
|
||||
uscsi_sense->skey_valid = keypos[0] & 128;
|
||||
uscsi_sense->sense_key = (keypos[1] << 8) | (keypos[2]);
|
||||
}
|
||||
|
||||
uscsi_print_sense((char *) disc->dev_name,
|
||||
cmd, cmdlen,
|
||||
(uint8_t *) cam_sense_data, 8 + cam_sense_data->extra_len, 1);
|
||||
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_identify(struct uscsi_dev *disc, struct uscsi_addr *saddr)
|
||||
{
|
||||
struct cam_device *cam_dev;
|
||||
|
||||
/* clean result */
|
||||
bzero(saddr, sizeof(struct uscsi_addr));
|
||||
|
||||
cam_dev = (struct cam_device *) disc->devhandle;
|
||||
if (!cam_dev) return ENODEV;
|
||||
|
||||
/* check if its really SCSI or emulated SCSI (ATAPI f.e.) ? */
|
||||
saddr->type = USCSI_TYPE_SCSI;
|
||||
saddr->addr.scsi.target = cam_dev->target_id;
|
||||
saddr->addr.scsi.lun = cam_dev->target_lun;
|
||||
saddr->addr.scsi.scbus = cam_dev->bus_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_check_for_scsi(struct uscsi_dev *disc)
|
||||
{
|
||||
struct uscsi_addr saddr;
|
||||
|
||||
return uscsi_identify(disc, &saddr);
|
||||
}
|
||||
|
||||
#endif /* USCSI_FREEBSD_CAM */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Generic SCSI funtions also used by the sense printing functionality.
|
||||
* FreeBSD support has it allready asked for by the CAM.
|
||||
*/
|
||||
|
||||
int
|
||||
uscsi_mode_sense(struct uscsi_dev *dev,
|
||||
uint8_t pgcode, uint8_t pctl, void *buf, size_t len)
|
||||
{
|
||||
scsicmd cmd;
|
||||
|
||||
bzero(buf, len); /* initialise recieving buffer */
|
||||
|
||||
bzero(cmd, SCSI_CMD_LEN);
|
||||
cmd[ 0] = 0x1a; /* MODE SENSE */
|
||||
cmd[ 1] = 0; /* - */
|
||||
cmd[ 2] = pgcode | pctl; /* page code and control flags */
|
||||
cmd[ 3] = 0; /* - */
|
||||
cmd[ 4] = len; /* length of recieve buffer */
|
||||
cmd[ 5] = 0; /* control */
|
||||
|
||||
return uscsi_command(SCSI_READCMD, dev, &cmd, 6, buf, len, 10000, NULL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_mode_select(struct uscsi_dev *dev,
|
||||
uint8_t byte2, void *buf, size_t len)
|
||||
{
|
||||
scsicmd cmd;
|
||||
|
||||
bzero(cmd, SCSI_CMD_LEN);
|
||||
cmd[ 0] = 0x15; /* MODE SELECT */
|
||||
cmd[ 1] = 0x10 | byte2; /* SCSI-2 page format select */
|
||||
cmd[ 4] = len; /* length of page settings */
|
||||
cmd[ 5] = 0; /* control */
|
||||
|
||||
return uscsi_command(SCSI_WRITECMD, dev, &cmd, 6, buf, len,
|
||||
10000, NULL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
uscsi_request_sense(struct uscsi_dev *dev, void *buf, size_t len)
|
||||
{
|
||||
scsicmd cmd;
|
||||
|
||||
bzero(buf, len); /* initialise recieving buffer */
|
||||
|
||||
bzero(cmd, SCSI_CMD_LEN);
|
||||
cmd[ 0] = 0x03; /* REQUEST SENSE */
|
||||
cmd[ 4] = len; /* length of data to be read */
|
||||
cmd[ 5] = 0; /* control */
|
||||
|
||||
return uscsi_command(SCSI_WRITECMD, dev, &cmd, 6, buf, len,
|
||||
10000, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* end of uscsi_subr.c */
|
||||
|
108
usr.sbin/mmcformat/uscsilib.h
Normal file
108
usr.sbin/mmcformat/uscsilib.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* $NetBSD: uscsilib.h,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Small changes made by Reinoud Zandijk <reinoud@netbsd.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SCSILIB_H_
|
||||
#define _SCSILIB_H_
|
||||
|
||||
|
||||
#define SCSI_CMD_LEN 12
|
||||
typedef unsigned char scsicmd[SCSI_CMD_LEN];
|
||||
|
||||
#include "defs.h"
|
||||
#include "uscsilib_machdep.h"
|
||||
extern int uscsilib_verbose;
|
||||
|
||||
|
||||
/*
|
||||
* Unified structure copied and modified from NetBSD's <sys/scsiio.h> for ease
|
||||
*/
|
||||
|
||||
struct uscsi_addr {
|
||||
int type; /* bus type */
|
||||
#define USCSI_TYPE_SCSI 0
|
||||
#define USCSI_TYPE_ATAPI 1
|
||||
union {
|
||||
struct {
|
||||
int scbus; /* -1 if wildcard */
|
||||
int target; /* -1 if wildcard */
|
||||
int lun; /* -1 if wildcard */
|
||||
} scsi;
|
||||
struct {
|
||||
int atbus; /* -1 if wildcard */
|
||||
int drive; /* -1 if wildcard */
|
||||
} atapi;
|
||||
} addr;
|
||||
};
|
||||
|
||||
|
||||
struct uscsi_sense {
|
||||
int asc; /* Additional sense code */
|
||||
int ascq; /* Additional sense code quality */
|
||||
int skey_valid; /* sense key valid */
|
||||
int sense_key; /* sense key; interpret on (asc, ascq) pair */
|
||||
};
|
||||
|
||||
|
||||
struct uscsi_dev {
|
||||
char *dev_name;
|
||||
int fhandle;
|
||||
void *devhandle; /* for if a fhandle is not enough */
|
||||
};
|
||||
|
||||
|
||||
/* uscsi_sense.c */
|
||||
extern char *uscsi_decode_sense(void *sinfo, int flag);
|
||||
extern void uscsi_print_sense(const char *name, u_char *req_cmd,
|
||||
int req_cmdlen, u_char *req_sense, int req_senselen_used,
|
||||
int verbosity);
|
||||
|
||||
|
||||
/* scsi_subr.c */
|
||||
extern int uscsi_open(struct uscsi_dev *);
|
||||
extern int uscsi_close(struct uscsi_dev *);
|
||||
extern int uscsi_command(int flags, struct uscsi_dev *disc,
|
||||
void *cmd, size_t cmdlen, void *data, size_t datalen,
|
||||
uint32_t timeout, struct uscsi_sense *uscsi_sense);
|
||||
extern int uscsi_check_for_scsi(struct uscsi_dev *);
|
||||
extern int uscsi_identify(struct uscsi_dev *, struct uscsi_addr *saddr);
|
||||
|
||||
extern int uscsi_mode_sense(struct uscsi_dev *, u_int8_t, u_int8_t,
|
||||
void *, size_t);
|
||||
extern int uscsi_mode_select(struct uscsi_dev *, u_int8_t, void *, size_t);
|
||||
extern int uscsi_request_sense(struct uscsi_dev *, void *, size_t);
|
||||
|
||||
|
||||
#endif /* _SCSILIB_H_ */
|
||||
|
90
usr.sbin/mmcformat/uscsilib_machdep.h
Normal file
90
usr.sbin/mmcformat/uscsilib_machdep.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* $NetBSD: uscsilib_machdep.h,v 1.1 2008/05/14 16:49:48 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2008 Reinoud Zandijk
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _USCSILIB_MACHDEP_H_
|
||||
#define _USCSILIB_MACHDEP_H_
|
||||
|
||||
#ifndef _DEV_SCSIPI_SCSIPI_ALL_H_
|
||||
# define SSD_KEY 0x0F
|
||||
# define SSD_ILI 0x20
|
||||
# define SSD_EOM 0x40
|
||||
# define SSD_FILEMARK 0x80
|
||||
# define SKEY_NO_SENSE 0x00
|
||||
# define SKEY_RECOVERED_ERROR 0x01
|
||||
# define SKEY_NOT_READY 0x02
|
||||
# define SKEY_MEDIUM_ERROR 0x03
|
||||
# define SKEY_HARDWARE_ERROR 0x04
|
||||
# define SKEY_ILLEGAL_REQUEST 0x05
|
||||
# define SKEY_UNIT_ATTENTION 0x06
|
||||
# define SKEY_WRITE_PROTECT 0x07
|
||||
# define SKEY_BLANK_CHECK 0x08
|
||||
# define SKEY_VENDOR_UNIQUE 0x09
|
||||
# define SKEY_COPY_ABORTED 0x0A
|
||||
# define SKEY_ABORTED_COMMAND 0x0B
|
||||
# define SKEY_EQUAL 0x0C
|
||||
# define SKEY_VOLUME_OVERFLOW 0x0D
|
||||
# define SKEY_MISCOMPARE 0x0E
|
||||
# define SKEY_RESERVED 0x0F
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SCSI
|
||||
# define SCSI_READCMD 0
|
||||
# define SCSI_WRITECMD 0
|
||||
struct scsi_addr;
|
||||
int scsilib_verbose;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USCSI_SCSIPI
|
||||
# include <sys/scsiio.h>
|
||||
# define SCSI_READCMD SCCMD_READ
|
||||
# define SCSI_WRITECMD SCCMD_WRITE
|
||||
# define SCSI_NODATACMD SCCMD_WRITE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USCSI_LINUX_SCSI
|
||||
# include <scsi/sg.h>
|
||||
# define SCSI_READCMD SG_DXFER_FROM_DEV
|
||||
# define SCSI_WRITECMD SG_DXFER_TO_DEV
|
||||
# define SCSI_NODATACMD SC_DXFER_NONE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USCSI_FREEBSD_CAM
|
||||
# include <camlib.h>
|
||||
# include <cam/scsi/scsi_message.h>
|
||||
# define SCSI_READCMD 1
|
||||
# define SCSI_WRITECMD 2
|
||||
# define SCSI_NODATACMD 0
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _USCSILIB_MACHDEP_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user