r2780 - in trunk: BOOK BOOK/introduction/welcome BOOK/multimedia/cdwriteutils patches

igor at linuxfromscratch.org igor at linuxfromscratch.org
Fri Oct 8 13:14:43 PDT 2004


Author: igor
Date: 2004-10-08 14:14:41 -0600 (Fri, 08 Oct 2004)
New Revision: 2780

Removed:
   trunk/BOOK/multimedia/cdwriteutils/kernel.xml
   trunk/patches/linux-2.4.26-packet-1.patch
Modified:
   trunk/BOOK/general.ent
   trunk/BOOK/introduction/welcome/changelog.xml
   trunk/BOOK/multimedia/cdwriteutils/cdrtools.xml
   trunk/BOOK/multimedia/cdwriteutils/cdwriteutils.xml
   trunk/BOOK/multimedia/cdwriteutils/udftools.xml
Log:
Updated to Cdrtools-2.01 and UDFtools-1.0.0b3 and removed obsolete kernel configuration for CD writing section.

Modified: trunk/BOOK/general.ent
===================================================================
--- trunk/BOOK/general.ent	2004-10-08 15:03:57 UTC (rev 2779)
+++ trunk/BOOK/general.ent	2004-10-08 20:14:41 UTC (rev 2780)
@@ -422,9 +422,9 @@
 <!ENTITY transcode-version            "0.6.12"> 
 
 <!-- Chapter 40 -->
-<!ENTITY cdrtools-version             "2.00.3">  
+<!ENTITY cdrtools-version             "2.01">  
 <!ENTITY cdrdao-version               "1.1.9">  
-<!ENTITY udftools-version             "1.0.0b2">   
+<!ENTITY udftools-version             "1.0.0b3">   
 
 <!-- Part XIII -->
 <!-- Chapter 41 --> 

Modified: trunk/BOOK/introduction/welcome/changelog.xml
===================================================================
--- trunk/BOOK/introduction/welcome/changelog.xml	2004-10-08 15:03:57 UTC (rev 2779)
+++ trunk/BOOK/introduction/welcome/changelog.xml	2004-10-08 20:14:41 UTC (rev 2780)
@@ -22,6 +22,10 @@
 
 <itemizedlist>
 
+<listitem><para>October 8th, 2004 [igor]: Updated to Cdrtools-2.01 and
+UDFtools-1.0.0b3 and removed obsolete kernel configuration for CD
+writing section.</para></listitem>
+
 <listitem><para>October 8th, 2004 [randy]: Updated to
 w3m-0.5.1.</para></listitem>
     

Modified: trunk/BOOK/multimedia/cdwriteutils/cdrtools.xml
===================================================================
--- trunk/BOOK/multimedia/cdwriteutils/cdrtools.xml	2004-10-08 15:03:57 UTC (rev 2779)
+++ trunk/BOOK/multimedia/cdwriteutils/cdrtools.xml	2004-10-08 20:14:41 UTC (rev 2780)
@@ -3,10 +3,10 @@
   <!ENTITY % general-entities SYSTEM "../../general.ent">
   %general-entities;
 
-  <!ENTITY cdrtools-download-http "http://gd.tuwien.ac.at/utils/schilling/cdrtools/cdrtools-&cdrtools-version;.tar.gz">
-  <!ENTITY cdrtools-download-ftp  "ftp://ftp.berlios.de/pub/cdrecord/cdrtools-&cdrtools-version;.tar.gz">
-  <!ENTITY cdrtools-size          "1.6 MB">
-  <!ENTITY cdrtools-buildsize     "19.1 MB">
+  <!ENTITY cdrtools-download-http "http://gd.tuwien.ac.at/utils/schilling/cdrtools/cdrtools-&cdrtools-version;.tar.bz2">
+  <!ENTITY cdrtools-download-ftp "ftp://ftp.berlios.de/pub/cdrecord/cdrtools-&cdrtools-version;.tar.bz2">
+  <!ENTITY cdrtools-size          "1.4 MB">
+  <!ENTITY cdrtools-buildsize     "21 MB">
   <!ENTITY cdrtools-time          "0.44 SBU">
 ]>
 
@@ -34,13 +34,6 @@
 <listitem><para>Estimated build time: &cdrtools-time;</para></listitem></itemizedlist>
 </sect3>
 
-<!-- <sect3><title>Additional downloads</title>
-<itemizedlist spacing='compact'>
-<listitem><para>Required Patch: <ulink 
-url="&patch-root;/cdrtools-&cdrtools-version;-kernel_2.6-1.patch"/></para>
-</listitem></itemizedlist>
-</sect3> -->
-
 </sect2>
 
 <sect2>
@@ -71,13 +64,20 @@
 <title>Contents</title>
 
 <para>The <application>Cdrtools</application> package contains 
-<command>cdrecord</command>, <command>cdda2wav</command>, 
-<command>mkisofs</command>,  <command>mkhybrid</command>, 
-<command>readcd</command>, <command>scgcheck</command>, 
-<command>isoinfo</command>, <command>isodump</command>, 
-<command>isovfy</command>, <command>isodebug</command>, 
-<command>devdump</command>, <command>rscsi</command> and support 
-libraries.</para>
+<command>cdda2wav</command>, 
+<command>cdrecord</command>,
+<command>devdump</command>,
+<command>isodebug</command>, 
+<command>isodump</command>, 
+<command>isoinfo</command>,
+<command>isovfy</command>,
+<command>mkhybrid</command>, 
+<command>mkisofs</command>,
+<command>readcd</command>,
+<command>rscsi</command>,
+<command>scgcheck</command>, 
+<command>skel</command>
+and support libraries.</para>
 
 </sect2>
 
@@ -91,7 +91,7 @@
 <para><command>cdda2wav</command> dumps Compact Disc audio into
 <filename>WAV</filename> sound files.</para></sect3>
 
-<sect3><title>mkisofs</title>
+<sect3><title>mkisofs, mkhybrid</title>
 <para><command>mkisofs</command> and <command>mkhybrid</command>
 generate an <acronym>ISO</acronym>9660/JOLIET/<acronym>HFS</acronym> hybrid 
 file system.</para></sect3>
@@ -129,4 +129,3 @@
 </sect2>
 
 </sect1>
-

Modified: trunk/BOOK/multimedia/cdwriteutils/cdwriteutils.xml
===================================================================
--- trunk/BOOK/multimedia/cdwriteutils/cdwriteutils.xml	2004-10-08 15:03:57 UTC (rev 2779)
+++ trunk/BOOK/multimedia/cdwriteutils/cdwriteutils.xml	2004-10-08 20:14:41 UTC (rev 2780)
@@ -8,12 +8,10 @@
 <?dbhtml filename="cdwriteutils.html"?>
 <title>CD-Writing utilities</title>
 
-<para>This chapter contains information on <acronym>CD</acronym>-writing in 
-Linux.  You will first have to configure your kernel for
-<acronym>CD</acronym>-writing, which is discussed first.  After that,
-installing the acutal utilities is presented.</para>
+<para>This chapter contains information on <acronym>CD</acronym>-writing
+utilities in Linux.</para>
 
-<para>Additional sources of information on <acronym>CD</acronym>-writing include:</para>
+<para>Additional sources of information include:</para>
 
 <itemizedlist>
 
@@ -26,7 +24,6 @@
 
 </itemizedlist>
 
-<xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="kernel.xml"/>  
 <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="cdrtools.xml"/>  
 <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="cdrdao.xml"/>  
 <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="udftools.xml"/>  

Deleted: trunk/BOOK/multimedia/cdwriteutils/kernel.xml
===================================================================
--- trunk/BOOK/multimedia/cdwriteutils/kernel.xml	2004-10-08 15:03:57 UTC (rev 2779)
+++ trunk/BOOK/multimedia/cdwriteutils/kernel.xml	2004-10-08 20:14:41 UTC (rev 2780)
@@ -1,60 +0,0 @@
-<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
-   "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
-  <!ENTITY % general-entities SYSTEM "../../general.ent">
-  %general-entities;
-]>
-
-<sect1 id="kernel" xreflabel="kernel">
-<sect1info>
-<othername>$LastChangedBy$</othername>
-<date>$Date$</date>
-</sect1info>
-<?dbhtml filename="kernel.html"?>
-<title>Configuring your kernel for CD-Writing</title>
-
-<para>In the kernel configuration, check your settings with those listed
-below for your <acronym>CD</acronym>-<acronym>ROM</acronym> interface type:</para>
-
-<para><acronym>SCSI</acronym> <acronym>CD</acronym>-writer:</para>
-<screen>SCSI support menu
-  SCSI support:           Y or M
-  SCSI CD-ROM support:    Y or M
-  SCSI generic support:   Y or M
-  Vendor-specific extensions:  [1]
-Also include the low-level driver for your SCSI card if
-applicable.</screen>
-
-
-<para><acronym>IDE</acronym> <acronym>CD</acronym>-writer:</para>
-<screen>ATA/IDE/MFM/RLL support menu
-  IDE/ATAPI CDROM support:     N
-  SCSI emulation support: Y or M
-SCSI support menu
-  SCSI support:           Y or M
-  SCSI CD-ROM support:    Y or M
-  SCSI generic support:   Y or M
-  Vendor-specific extensions:  [1]</screen>
-
-<para>[1] Read the help to determine if this selection is applicable for
-your hardware.</para>
-
-<para>If necessary, recompile the kernel with</para>
-<screen>make CC=/opt/gcc-2.95.3/bin/gcc dep &&
-make CC=/opt/gcc-2.95.3/bin/gcc bzImage &&
-make CC=/opt/gcc-2.95.3/bin/gcc modules &&
-make CC=/opt/gcc-2.95.3/bin/gcc modules_install</screen>
-<para>
-Copy <filename>/usr/src/linux/arch/i386/boot/bzImage</filename> and
-<filename>/usr/src/linux/System.map</filename> to
-<filename>/boot</filename>. If you utilize
-<application>LILO</application>,  edit <filename>/etc/lilo.conf</filename>
-appropriately and run <command>lilo</command>.
-</para>
-
-<para>For more information about these settings and the drivers they
-install, read <ulink
-url="http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO/sr.html">The Linux 2.4
-SCSI subsystem HOWTO</ulink>.</para>
-
-</sect1>
-

Modified: trunk/BOOK/multimedia/cdwriteutils/udftools.xml
===================================================================
--- trunk/BOOK/multimedia/cdwriteutils/udftools.xml	2004-10-08 15:03:57 UTC (rev 2779)
+++ trunk/BOOK/multimedia/cdwriteutils/udftools.xml	2004-10-08 20:14:41 UTC (rev 2780)
@@ -5,10 +5,9 @@
 
   <!ENTITY udftools-download-http "http://prdownloads.sourceforge.net/linux-udf/udftools-&udftools-version;.tar.gz">
   <!ENTITY udftools-download-ftp  " ">
-  <!ENTITY udftools-size          "236 Kb">
-  <!ENTITY udftools-buildsize     "2.7 MB">
-  <!ENTITY udftools-time          " ">
-  <!ENTITY linux-kernel-version   "2.4.26">
+  <!ENTITY udftools-size          "287 KB">
+  <!ENTITY udftools-buildsize     "3.5 MB">
+  <!ENTITY udftools-time          "0.10 SBU">
 ]>
 
 <sect1 id="udftools" xreflabel="UDFtools-&udftools-version;">
@@ -38,16 +37,16 @@
 <listitem><para>Download (HTTP): <ulink url="&udftools-download-http;"/></para></listitem>
 <listitem><para>Download (FTP): <ulink url="&udftools-download-ftp;"/></para></listitem>
 <listitem><para>Download size: &udftools-size;</para></listitem>
-<listitem><para>Estimated Disk space required: &udftools-buildsize;</para></listitem>
+<listitem><para>Estimated disk space required: &udftools-buildsize;</para></listitem>
 <listitem><para>Estimated build time: &udftools-time;</para></listitem></itemizedlist>
 </sect3>
 
 <sect3><title>Additional downloads</title>
 <itemizedlist spacing='compact'>
-<listitem><para>Required Patch: <ulink
-url="&patch-root;/linux-&linux-kernel-version;-packet-1.patch"/></para></listitem>
-<listitem><para>Patches for other kernel versions:
-<ulink url="http://w1.894.telia.com/~u89404340/patches/packet/"/></para></listitem>
+<listitem><para>Required patch: <ulink
+url="http://w1.894.telia.com/~u89404340/patches/packet/2.6/packet-2.6.8-2.patch.bz2"/></para></listitem>
+<listitem><para>Required patch: <ulink
+url="http://w1.894.telia.com/~u89404340/patches/packet/udftools-1.0.0b3.patch.bz2"/></para></listitem>
 </itemizedlist></sect3>
 
 </sect2>
@@ -65,31 +64,19 @@
 <para>Install the kernel patch by running the following commands from
 the kernel source directory:</para>
 
-<screen><userinput><command>patch -Np1 -i ../linux-&linux-kernel-version;-packet-1.patch</command></userinput></screen>
+<screen><userinput><command>bzcat ../packet-2.6.8-2.patch.bz2 |patch -Np1</command></userinput></screen>
 
-<para>In the kernel configuration, check your setting with those listed
+<para>In the kernel configuration, modify your settings to match those listed
 here:</para>
 
 <screen>Block devices
-   Packet writing on CD/DVD media:       Y or M
-File Systems
-   UDF filesystems support (read only):  Y
-     UDF write support (DANGEROUS)       Y</screen>
+    Packet writing on CD/DVD media:       Y or M
+CD-ROM/DVD Filesystems
+    UDF file system support               Y or M</screen>
 
-<para>If necessary, recompile the kernel with:</para>
+<para>Recompile and install the new kernel.</para>
 
-<screen><userinput><command>make CC=/opt/gcc-2.95.3/bin/gcc dep &&
-make CC=/opt/gcc-2.95.3/bin/gcc bzImage &&
-make CC=/opt/gcc-2.95.3/bin/gcc modules &&
-make CC=/opt/gcc-2.95.3/bin/gcc modules_install</command></userinput></screen>
-
-<para>
-Copy <filename>/usr/src/linux/arch/i386/boot/bzImage</filename> and
-<filename>/usr/src/linux/System.map</filename> to
-<filename class="directory">/boot</filename>. If you utilize
-<application>LILO</application>, edit <filename>/etc/lilo.conf</filename>
-appropriately and run <command>lilo</command>.</para>
-
+<!--
 <para>If you built packet writer as a module, add the following to
 <filename>/etc/modules.conf</filename>:</para>
 
@@ -102,6 +89,7 @@
 
 <screen><userinput><command>mknod /dev/pktcdvd0 b 97 0
 mknod /dev/pktcdvd1 b 97 1</command></userinput></screen>
+-->
 
 </sect2>
 
@@ -112,7 +100,8 @@
 <para>Install <application><acronym>UDF</acronym>tools</application> by 
 running the following commands:</para>
 
-<screen><userinput><command>./configure --prefix=/usr &&
+<screen><userinput><command>bzcat ../udftools-1.0.0b3.patch.bz2 |patch -Np1 &&
+./configure --prefix=/usr &&
 make &&
 make install</command></userinput></screen>
 
@@ -122,8 +111,13 @@
 <title>Contents</title>
 
 <para>The <application><acronym>UDF</acronym>tools</application> package 
-contains <command>pktsetup</command>, <command>cdrwtool</command>, and
-<command>mkudffs</command>.</para>
+contains
+<command>cdrwtool</command>,
+<command>mkudffs</command>,
+<command>pktsetup</command>,
+<command>udffsck</command>,
+<command>wrudf</command> and
+<filename class="libraryfile">libudffs</filename>.</para>
 
 </sect2>
 
@@ -163,4 +157,3 @@
 </sect2>
 
 </sect1>
-

Deleted: trunk/patches/linux-2.4.26-packet-1.patch
===================================================================
--- trunk/patches/linux-2.4.26-packet-1.patch	2004-10-08 15:03:57 UTC (rev 2779)
+++ trunk/patches/linux-2.4.26-packet-1.patch	2004-10-08 20:14:41 UTC (rev 2780)
@@ -1,6759 +0,0 @@
-Submitted By: BLFS BOOK <blfs-book at linuxfromscratch.org>
-Date: 2003-10-09
-Initial Package Version: 2.4.22
-Origin: http://w1.894.telia.com/~u89404340/patches/packet/2.4/packet-2.4.20.patch.bz2
-Description: Allow packet writing for CDROMs.
-
-$LastChangedBy$
-$Date$
-
-diff -u -r -N ../../linus/2.4/linux/Documentation/Configure.help linux/Documentation/Configure.help
---- ../../linus/2.4/linux/Documentation/Configure.help	2003-08-23 21:25:25.000000000 +0200
-+++ linux/Documentation/Configure.help	2003-08-23 22:25:44.000000000 +0200
-@@ -750,6 +750,27 @@
-   say M here and read <file:Documentation/modules.txt>.  The module
-   will be called ide-cd.o.
- 
-+
-+Packet writing on CD/DVD media (EXPERIMENTAL)
-+CONFIG_CDROM_PKTCDVD
-+  If you have a CDROM drive that supports packet writing, say Y to
-+  include preliminary support. It should work with any MMC/Mt Fuji
-+  compliant ATAPI or SCSI drive, which is just about any newer CD
-+  writer.
-+
-+  Currently only writing to CD-RW discs is possible.
-+
-+  If you want to compile the driver as a module ( = code which can be
-+  inserted in and removed from the running kernel whenever you want),
-+  say M here and read Documentation/modules.txt. The module will be
-+  called pktcdvd.o
-+
-+Write caching
-+CONFIG_CDROM_PKTCDVD_WCACHE
-+  If enabled, write caching will be set for the CD-R/W device. For now
-+  this option is dangerous unless the CD-RW media is known good, as we
-+  don't do deferred write error handling yet.
-+
- Include IDE/ATAPI TAPE support
- CONFIG_BLK_DEV_IDETAPE
-   If you have an IDE tape drive using the ATAPI protocol, say Y.
-diff -u -r -N ../../linus/2.4/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
---- ../../linus/2.4/linux/arch/sparc64/kernel/ioctl32.c	2003-08-03 23:21:54.000000000 +0200
-+++ linux/arch/sparc64/kernel/ioctl32.c	2003-08-03 23:30:02.000000000 +0200
-@@ -92,6 +92,7 @@
- #include <linux/atm_tcp.h>
- #include <linux/sonet.h>
- #include <linux/atm_suni.h>
-+#include <linux/pktcdvd.h>
- #include <linux/mtd/mtd.h>
- 
- #include <net/bluetooth/bluetooth.h>
-@@ -819,6 +820,41 @@
- 	return ret;
- }
- 
-+struct packet_stats32 {
-+	u32	bh_s;
-+	u32	bh_e;
-+	u32	bh_cache_hits;
-+	u32	page_cache_hits;
-+	u32	bh_w;
-+	u32	bh_r;
-+};
-+
-+static inline int pkt_getstats(unsigned int fd, unsigned int cmd, unsigned long arg)
-+{
-+	struct packet_stats p;
-+	struct packet_stats32 p32;
-+	mm_segment_t old_fs = get_fs();
-+	int ret;
-+
-+	ret = copy_from_user (&p32, (struct packet_stats32 *)arg, sizeof(struct packet_stats32));
-+	if (ret)
-+		return -EFAULT;
-+#define P(x) (p.x = (unsigned long)p32.x)
-+	P(bh_s);
-+	P(bh_e);
-+	P(bh_cache_hits);
-+	P(page_cache_hits);
-+	P(bh_w);
-+	P(bh_r);
-+#undef P
-+
-+	set_fs (KERNEL_DS);
-+	ret = sys_ioctl (fd, cmd, (long)&p);
-+	set_fs (old_fs);
-+
-+        return ret;
-+}
-+
- struct hd_geometry32 {
- 	unsigned char heads;
- 	unsigned char sectors;
-@@ -5012,6 +5048,12 @@
- COMPATIBLE_IOCTL(RNDADDENTROPY)
- COMPATIBLE_IOCTL(RNDZAPENTCNT)
- COMPATIBLE_IOCTL(RNDCLEARPOOL)
-+/* Big X, CDRW Packet Driver */
-+#if defined(CONFIG_CDROM_PKTCDVD)
-+COMPATIBLE_IOCTL(PACKET_SETUP_DEV)
-+COMPATIBLE_IOCTL(PACKET_TEARDOWN_DEV)
-+HANDLE_IOCTL(PACKET_GET_STATS, pkt_getstats)
-+#endif /* CONFIG_CDROM_PKTCDVD */
- /* Bluetooth ioctls */
- COMPATIBLE_IOCTL(HCIDEVUP)
- COMPATIBLE_IOCTL(HCIDEVDOWN)
-diff -u -r -N ../../linus/2.4/linux/drivers/block/Config.in linux/drivers/block/Config.in
---- ../../linus/2.4/linux/drivers/block/Config.in	2003-08-03 23:22:00.000000000 +0200
-+++ linux/drivers/block/Config.in	2003-08-03 23:30:13.000000000 +0200
-@@ -39,6 +39,11 @@
- dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
- dep_tristate 'Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)' CONFIG_BLK_DEV_UMEM $CONFIG_PCI $CONFIG_EXPERIMENTAL
- 
-+tristate 'Packet writing on CD/DVD media' CONFIG_CDROM_PKTCDVD
-+if [ "$CONFIG_CDROM_PKTCDVD" != "n" ]; then
-+    bool '   Enable write caching' CONFIG_CDROM_PKTCDVD_WCACHE n
-+fi
-+   
- tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
- dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
- 
-diff -u -r -N ../../linus/2.4/linux/drivers/block/Makefile linux/drivers/block/Makefile
---- ../../linus/2.4/linux/drivers/block/Makefile	2003-08-03 23:22:00.000000000 +0200
-+++ linux/drivers/block/Makefile	2003-08-03 23:30:13.000000000 +0200
-@@ -10,7 +10,7 @@
- 
- O_TARGET := block.o
- 
--export-objs	:= ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o acsi.o
-+export-objs	:= ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o acsi.o elevator.o
- 
- obj-y	:= ll_rw_blk.o blkpg.o genhd.o elevator.o
- 
-@@ -31,6 +31,7 @@
- obj-$(CONFIG_BLK_DEV_DAC960)	+= DAC960.o
- obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
- obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
-+obj-$(CONFIG_CDROM_PKTCDVD)	+= pktcdvd.o
- 
- subdir-$(CONFIG_PARIDE) += paride
- 
-diff -u -r -N ../../linus/2.4/linux/drivers/block/elevator.c linux/drivers/block/elevator.c
---- ../../linus/2.4/linux/drivers/block/elevator.c	2003-08-03 23:22:00.000000000 +0200
-+++ linux/drivers/block/elevator.c	2003-08-03 23:30:14.000000000 +0200
-@@ -219,3 +219,5 @@
- 	*elevator = type;
- 	elevator->queue_ID = queue_ID++;
- }
-+
-+EXPORT_SYMBOL(elevator_init);
-diff -u -r -N ../../linus/2.4/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
---- ../../linus/2.4/linux/drivers/block/ll_rw_blk.c	2003-08-03 23:22:00.000000000 +0200
-+++ linux/drivers/block/ll_rw_blk.c	2003-08-23 22:25:48.000000000 +0200
-@@ -1210,6 +1210,7 @@
- 	/* Test device size, when known. */
- 	if (blk_size[major])
- 		minorsize = blk_size[major][MINOR(bh->b_rdev)];
-+#if 0
- 	if (minorsize) {
- 		unsigned long maxsector = (minorsize << 1) + 1;
- 		unsigned long sector = bh->b_rsector;
-@@ -1232,6 +1233,7 @@
- 			return;
- 		}
- 	}
-+#endif
- 
- 	/*
- 	 * Resolve the mapping until finished. (drivers are
-@@ -1440,8 +1442,8 @@
- 
- 	req->errors = 0;
- 	if (!uptodate)
--		printk("end_request: I/O error, dev %s (%s), sector %lu\n",
--			kdevname(req->rq_dev), name, req->sector);
-+		printk("end_request: I/O error, cmd %d dev %s (%s), sector %lu\n",
-+			req->cmd, kdevname(req->rq_dev), name, req->sector);
- 
- 	if ((bh = req->bh) != NULL) {
- 		nsect = bh->b_size >> 9;
-diff -u -r -N ../../linus/2.4/linux/drivers/block/pktcdvd.c linux/drivers/block/pktcdvd.c
---- ../../linus/2.4/linux/drivers/block/pktcdvd.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux/drivers/block/pktcdvd.c	2003-08-03 23:30:14.000000000 +0200
-@@ -0,0 +1,2679 @@
-+/*
-+ * Copyright (C) 2000 Jens Axboe <axboe at suse.de>
-+ *
-+ * May be copied or modified under the terms of the GNU General Public
-+ * License.  See linux/COPYING for more information.
-+ *
-+ * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
-+ * DVD-RW devices (aka an exercise in block layer masturbation)
-+ *
-+ *
-+ * TODO: (circa order of when I will fix it)
-+ * - Only able to write on CD-RW media right now.
-+ * - check host application code on media and set it in write page
-+ * - Generic interface for UDF to submit large packets for variable length
-+ *   packet writing
-+ * - interface for UDF <-> packet to negotiate a new location when a write
-+ *   fails.
-+ * - handle OPC, especially for -RW media
-+ *
-+ * ------------------------------------------------------------------------
-+ *
-+ * Newer changes -- see ChangeLog
-+ *
-+ * 0.0.2d (26/10/2000)
-+ * - (scsi) use implicit segment recounting for all hba's
-+ * - fix speed setting, was consistenly off on most drives
-+ * - only print capacity when opening for write
-+ * - fix off-by-two error in getting/setting write+read speed (affected
-+ *   reporting as well as actual speed used)
-+ * - possible to enable write caching on drive
-+ * - do ioctl marshalling on sparc64 from Ben Collins <bcollins at debian.org>
-+ * - avoid unaligned access on flags, should have been unsigned long of course
-+ * - fixed missed wakeup in kpacketd
-+ * - b_dev error (two places)
-+ * - fix buffer head b_count bugs
-+ * - fix hole merge bug, where tail could be added twice
-+ * - fsync and invalidate buffers on close
-+ * - check hash table for buffers first before using our own
-+ * - add read-ahead
-+ * - fixed several list races
-+ * - fix proc reporting for more than one device
-+ * - change to O_CREAT for creating devices
-+ * - added media_change hook
-+ * - added free buffers config option
-+ * - pkt_lock_tray fails on failed open (and oopses), remove it. unlock
-+ *   is done explicitly in pkt_remove dev anyway.
-+ * - added proper elevator insertion (should probably be part of elevator.c)
-+ * - moved kernel thread info to private device, spawn one for each writer
-+ * - added separate buffer list for dirty packet buffers
-+ * - fixed nasty data corruption bug
-+ * - remember to account request even when we don't gather data for it
-+ * - add ioctl to force wakeup of kernel thread (for debug)
-+ * - fixed packet size setting bug on zero detected
-+ * - changed a lot of the proc reporting to be more readable to "humans"
-+ * - set full speed for read-only opens
-+ *
-+ * 0.0.2c (08/09/2000)
-+ * - inc usage count of buffer heads
-+ * - add internal buffer pool to avoid deadlock on oom
-+ * - gather data for as many buffers as we have, before initiating write. this
-+ *   allows the laser to stay on longer, giving better performance.
-+ * - fix always busy when tray can't be locked
-+ * - remove request duplication nastiness, inject directly into the target
-+ * - adapted to devfs and elevator changes
-+ * - added proc interface
-+ *
-+ * 0.0.2b (21/06/2000)
-+ * - fix io_request_lock typos (missing '&')
-+ * - grab pkt_sem before invoking pkt_handle_queue
-+ * - SCSI uses queuedata too, mirror that in pd->queuedata (hack)
-+ * - remove SCSI sr debug messages
-+ * - really activate empty block querying (requires cvs UDF, CDRW branch)
-+ * - make sure sync_buffers doesn't consider us, or we can deadlock
-+ * - make sure people don't swap on us (for now ;)
-+ *
-+ * 0.0.2a (19/06/2000)
-+ * - add kpacketd kernel thread to handle actual data gathering
-+ * - pd->pkt_dev is now real device, not just minor
-+ * - add support for super_operations block_empty fn, to query fs for
-+ *   unused blocks that don't need reading
-+ * - "cache" blocks that are contained in the UDF file/dir packet
-+ * - rewrite pkt_gather_data to a one-step solution
-+ * - add private pktcdvd elevator
-+ * - shutdown write access to device upon write failure
-+ * - fix off-by-one bug in capacity
-+ * - setup sourceforge project (packet-cd.sourceforge.net)
-+ * - add more blk ioctls to pkt_ioctl
-+ * - set inactive request queue head
-+ * - change panic calls to BUG, better with kdb
-+ * - have pkt_gather_data check correct block size and kill rq if wrong
-+ * - rework locking
-+ * - introduce per-pd queues, simplifies pkt_request
-+ * - store pd in queuedata
-+ *
-+ *************************************************************************/
-+
-+#define VERSION_CODE	"v0.0.2p 03/03/2002 Jens Axboe (axboe at suse.de)"
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h>
-+#include <linux/locks.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/file.h>
-+#include <linux/blk.h>
-+#include <linux/blkpg.h>
-+#include <linux/cdrom.h>
-+#include <linux/ide.h>
-+#include <linux/smp_lock.h>
-+#include <linux/pktcdvd.h>
-+#include <linux/kernel_stat.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/unaligned.h>
-+#include <asm/uaccess.h>
-+
-+/*
-+ * remove for next version -- for now, disable the mention option in the
-+ * SCSI section
-+ */
-+#if defined(CONFIG_SCSI_DEBUG_QUEUES)
-+#error "Don't compile with 'Enable extra checks in new queueing code' enabled"
-+#endif
-+
-+#define SCSI_IOCTL_SEND_COMMAND	1
-+
-+/*
-+ * 32 buffers of 2048 bytes
-+ */
-+#define PACKET_MAX_SIZE		32
-+
-+#define NEXT_BH(bh, nbh)	\
-+	 (((bh)->b_rsector + ((bh)->b_size >> 9)) == (nbh)->b_rsector)
-+
-+#define BH_IN_ORDER(b1, b2)	\
-+	((b1)->b_rsector < (b2)->b_rsector)
-+
-+#define CONTIG_BH(b1, b2)	\
-+	((b1)->b_data + (b1)->b_size == (b2)->b_data)
-+
-+#define ZONE(sector, pd)	\
-+	(((sector) + ((pd)->offset)) - (((sector) + ((pd)->offset)) & (((pd)->settings.size - 1))))
-+
-+static int *pkt_sizes;
-+static int *pkt_blksize;
-+static int *pkt_readahead;
-+static struct pktcdvd_device *pkt_devs;
-+static struct proc_dir_entry *pkt_proc;
-+static DECLARE_WAIT_QUEUE_HEAD(pd_bh_wait);
-+
-+/*
-+ * a bit of a kludge, but we want to be able to pass both real and packet
-+ * dev and get the right one.
-+ */
-+static inline struct pktcdvd_device *pkt_find_dev(kdev_t dev)
-+{
-+	int i;
-+
-+	for (i = 0; i < MAX_WRITERS; i++)
-+		if (pkt_devs[i].dev == dev || pkt_devs[i].pkt_dev == dev)
-+			return &pkt_devs[i];
-+
-+	return NULL;
-+}
-+
-+/*
-+ * The following functions are the plugins to the ll_rw_blk
-+ * layer and decides whether a given request / buffer head can be
-+ * merged. We differ in a couple of ways from "normal" block
-+ * devices:
-+ *
-+ * - don't merge when the buffer / request crosses a packet block
-+ *   boundary
-+ * - merge buffer head even though it can't be added directly to the
-+ *   front or back of the list. this gives us better performance, since
-+ *   what would otherwise require multiple requests can now be handled
-+ *   in one (hole merging)
-+ * - at this point its just writes, reads have already been remapped
-+ *
-+ * The device original merge_ functions are stored in the packet device
-+ * queue (pd->q)
-+ *
-+ */
-+static inline int pkt_do_merge(request_queue_t *q, struct request *rq,
-+			       struct buffer_head *bh, int max_segs,
-+			       merge_request_fn *merge_fn,
-+			       struct pktcdvd_device *pd)
-+{
-+	void *ptr = q->queuedata;
-+	int ret;
-+
-+	if (rq->cmd != WRITE)
-+		BUG();
-+
-+	if (ZONE(rq->sector, pd) != ZONE(bh->b_rsector, pd))
-+		return ELEVATOR_NO_MERGE;
-+
-+	/*
-+	 * NOTE: this is done under the io_request_lock/queue_lock, hence
-+	 * it is safe
-+	 */
-+	q->queuedata = pd->cdrw.queuedata;
-+	ret = merge_fn(q, rq, bh, max_segs);
-+	q->queuedata = ptr;
-+	return ret;
-+}
-+
-+static int pkt_front_merge_fn(request_queue_t *q, struct request *rq,
-+			      struct buffer_head *bh, int max_segs)
-+{
-+	struct pktcdvd_device *pd = &pkt_devs[MINOR(bh->b_rdev)];
-+
-+	return pkt_do_merge(q, rq, bh, max_segs, pd->cdrw.front_merge_fn, pd);
-+}
-+
-+static int pkt_back_merge_fn(request_queue_t *q, struct request *rq,
-+			     struct buffer_head *bh, int max_segs)
-+{
-+	struct pktcdvd_device *pd = &pkt_devs[MINOR(bh->b_rdev)];
-+
-+	return pkt_do_merge(q, rq, bh, max_segs, pd->cdrw.back_merge_fn, pd);
-+}
-+
-+/*
-+ * rules similar to above
-+ */
-+static int pkt_merge_requests_fn(request_queue_t *q, struct request *rq,
-+				 struct request *nxt, int max_segs)
-+{
-+	struct pktcdvd_device *pd = pkt_find_dev(rq->rq_dev);
-+	struct packet_cdrw *cdrw = &pd->cdrw;
-+	void *ptr = q->queuedata;
-+	int ret;
-+
-+	if (ZONE(rq->sector, pd) != ZONE(nxt->sector + nxt->nr_sectors - 1, pd))
-+		return 0;
-+
-+	q->queuedata = cdrw->queuedata;
-+	ret = cdrw->merge_requests_fn(q, rq, nxt, max_segs);
-+	q->queuedata = ptr;
-+	return ret;
-+}
-+
-+static int pkt_grow_bhlist(struct pktcdvd_device *pd, int count)
-+{
-+	struct packet_cdrw *cdrw = &pd->cdrw;
-+	struct buffer_head *bh;
-+	int i = 0;
-+
-+	VPRINTK("grow_bhlist: count=%d\n", count);
-+
-+	while (i < count) {
-+		bh = kmem_cache_alloc(bh_cachep, SLAB_KERNEL);
-+		if (!bh)
-+			break;
-+
-+		bh->b_data = kmalloc(CD_FRAMESIZE, GFP_KERNEL);
-+		if (!bh->b_data) {
-+			kmem_cache_free(bh_cachep, bh);
-+			break;
-+		}
-+		bh->b_page = virt_to_page(bh->b_data);
-+
-+		spin_lock_irq(&pd->lock);
-+		bh->b_pprev = &cdrw->bhlist;
-+		bh->b_next = cdrw->bhlist;
-+		cdrw->bhlist = bh;
-+		spin_unlock_irq(&pd->lock);
-+
-+		bh->b_size = CD_FRAMESIZE;
-+		bh->b_list = PKT_BUF_LIST;
-+		atomic_inc(&cdrw->free_bh);
-+		i++;
-+	}
-+
-+	return i;
-+}
-+
-+static int pkt_shrink_bhlist(struct pktcdvd_device *pd, int count)
-+{
-+	struct packet_cdrw *cdrw = &pd->cdrw;
-+	struct buffer_head *bh;
-+	int i = 0;
-+
-+	VPRINTK("shrink_bhlist: count=%d\n", count);
-+
-+	while ((i < count) && cdrw->bhlist) {
-+		spin_lock_irq(&pd->lock);
-+		bh = cdrw->bhlist;
-+		cdrw->bhlist = bh->b_next;
-+		spin_unlock_irq(&pd->lock);
-+		if (bh->b_list != PKT_BUF_LIST)
-+			BUG();
-+		kfree(bh->b_data);
-+		kmem_cache_free(bh_cachep, bh);
-+		atomic_dec(&cdrw->free_bh);
-+		i++;
-+	}
-+
-+	return i;
-+}
-+
-+/*
-+ * These functions manage a simple pool of buffer_heads.
-+ */
-+static struct buffer_head *pkt_get_stacked_bh(struct pktcdvd_device *pd)
-+{
-+	unsigned long flags;
-+	struct buffer_head *bh;
-+
-+	spin_lock_irqsave(&pd->lock, flags);
-+	bh = pd->stacked_bhlist;
-+	if (bh) {
-+		pd->stacked_bhlist = bh->b_next;
-+		bh->b_next = NULL;
-+		pd->stacked_bhcnt--;
-+		BUG_ON(pd->stacked_bhcnt < 0);
-+	}
-+	spin_unlock_irqrestore(&pd->lock, flags);
-+
-+	return bh;
-+}
-+
-+static void pkt_put_stacked_bh(struct pktcdvd_device *pd, struct buffer_head *bh)
-+{
-+	unsigned long flags;
-+
-+	spin_lock_irqsave(&pd->lock, flags);
-+	if (pd->stacked_bhcnt < STACKED_BH_POOL_SIZE) {
-+		bh->b_next = pd->stacked_bhlist;
-+		pd->stacked_bhlist = bh;
-+		pd->stacked_bhcnt++;
-+		bh = NULL;
-+	}
-+	spin_unlock_irqrestore(&pd->lock, flags);
-+	if (bh) {
-+		kmem_cache_free(bh_cachep, bh);
-+	}
-+}
-+
-+static void pkt_shrink_stacked_bhlist(struct pktcdvd_device *pd)
-+{
-+	struct buffer_head *bh;
-+
-+	while ((bh = pkt_get_stacked_bh(pd)) != NULL) {
-+		kmem_cache_free(bh_cachep, bh);
-+	}
-+}
-+
-+static int pkt_grow_stacked_bhlist(struct pktcdvd_device *pd)
-+{
-+	struct buffer_head *bh;
-+	int i;
-+
-+	for (i = 0; i < STACKED_BH_POOL_SIZE; i++) {
-+		bh = kmem_cache_alloc(bh_cachep, GFP_KERNEL);
-+		if (!bh) {
-+			pkt_shrink_stacked_bhlist(pd);
-+			return 0;
-+		}
-+		pkt_put_stacked_bh(pd, bh);
-+	}
-+	return 1;
-+}
-+
-+
-+static request_queue_t *pkt_get_queue(kdev_t dev)
-+{
-+	struct pktcdvd_device *pd = pkt_find_dev(dev);
-+	if (!pd)
-+		return NULL;
-+	return &pd->cdrw.r_queue;
-+}
-+
-+static void pkt_put_buffer(struct buffer_head *bh)
-+{
-+	struct pktcdvd_device *pd = &pkt_devs[MINOR(bh->b_dev)];
-+	unsigned long flags;
-+
-+	if (bh->b_list != PKT_BUF_LIST)
-+		return;
-+
-+	bh->b_state = 0;
-+	bh->b_reqnext = NULL;
-+	bh->b_end_io = NULL;
-+
-+	spin_lock_irqsave(&pd->lock, flags);
-+	bh->b_next = pd->cdrw.bhlist;
-+	pd->cdrw.bhlist = bh;
-+	spin_unlock_irqrestore(&pd->lock, flags);
-+	atomic_inc(&pd->cdrw.free_bh);
-+}
-+
-+static inline void __pkt_inject_request(request_queue_t *q, struct request *rq)
-+{
-+	struct list_head *head =  &q->queue_head;
-+
-+	VPRINTK("__pkt_inject_request: list_empty == %d, size=%d, cmd=%d\n",
-+		list_empty(&q->queue_head), rq->bh->b_size >> 9, rq->cmd);
-+
-+	if (list_empty(&q->queue_head))
-+		q->plug_device_fn(q, rq->rq_dev);
-+
-+	list_add_tail(&rq->queue, head);
-+}
-+
-+static void pkt_inject_request(request_queue_t *q, struct request *rq)
-+{
-+	spin_lock_irq(&io_request_lock);
-+	__pkt_inject_request(q, rq);
-+	spin_unlock_irq(&io_request_lock);
-+}
-+
-+static inline void __pkt_end_request(struct pktcdvd_device *pd)
-+{
-+	pd->rq = NULL;
-+	clear_bit(PACKET_RQ, &pd->flags);
-+	clear_bit(PACKET_BUSY, &pd->flags);
-+}
-+
-+/*
-+ * io_request_lock must be held and interrupts disabled
-+ */
-+static void pkt_end_request(struct pktcdvd_device *pd)
-+{
-+	unsigned long flags;
-+
-+	spin_lock_irqsave(&pd->lock, flags);
-+	__pkt_end_request(pd);
-+	spin_unlock_irqrestore(&pd->lock, flags);
-+}
-+
-+
-+static inline void __pkt_kill_request(struct request *rq, int uptodate, char *name)
-+{
-+	struct buffer_head *bh = rq->bh, *nbh;
-+
-+	while (bh) {
-+		nbh = bh->b_reqnext;
-+		bh->b_reqnext = NULL;
-+
-+		if (bh->b_end_io) {
-+			bh->b_end_io(bh, uptodate);
-+		} else {
-+			mark_buffer_clean(bh);
-+			mark_buffer_uptodate(bh, uptodate);
-+			unlock_buffer(bh);
-+		}
-+
-+		bh = nbh;
-+	}
-+
-+	end_that_request_last(rq);
-+}
-+
-+
-+void pkt_kill_request(struct pktcdvd_device *pd, struct request *rq, int ok)
-+{
-+	printk("pktcdvd: killing request\n");
-+	spin_lock_irq(&io_request_lock);
-+	__pkt_kill_request(rq, ok, pd->name);
-+	spin_unlock_irq(&io_request_lock);
-+	pkt_end_request(pd);
-+}
-+
-+static void pkt_end_io_read(struct buffer_head *bh, int uptodate)
-+{
-+	if (!uptodate) {
-+		/* Obviously not correct, but it avoids locking up the kernel */
-+		printk("Ignoring read error on sector:%ld\n", bh->b_rsector);
-+		uptodate = 1;
-+	}
-+
-+	mark_buffer_uptodate(bh, uptodate);
-+	unlock_buffer(bh);
-+}
-+
-+/*
-+ * if the buffer is already in the buffer cache, grab it if we can lock
-+ * it down
-+ */
-+static struct buffer_head *pkt_get_hash(kdev_t dev, unsigned long block, int size)
-+{
-+	struct buffer_head *bh = NULL;
-+
-+	bh = get_hash_table(dev, block, size);
-+	if (bh) {
-+		if (!test_and_set_bit(BH_Lock, &bh->b_state)) {
-+			brelse(bh);
-+			if (atomic_set_buffer_clean(bh))
-+				refile_buffer(bh);
-+			SetPageReferenced(bh->b_page);
-+		} else {
-+			brelse(bh);
-+			bh = NULL;
-+		}
-+	}
-+
-+	return bh;
-+}
-+
-+static inline struct buffer_head *__pkt_get_buffer(struct pktcdvd_device *pd,
-+						   unsigned long sector)
-+{
-+	struct buffer_head *bh;
-+
-+	if (!atomic_read(&pd->cdrw.free_bh))
-+		BUG();
-+
-+	atomic_dec(&pd->cdrw.free_bh);
-+
-+	spin_lock_irq(&pd->lock);
-+	bh = pd->cdrw.bhlist;
-+	pd->cdrw.bhlist = bh->b_next;
-+	bh->b_next = NULL;
-+	spin_unlock_irq(&pd->lock);
-+
-+	bh->b_next_free = NULL;
-+	bh->b_prev_free = NULL;
-+	bh->b_this_page = NULL;
-+	bh->b_pprev = NULL;
-+	bh->b_reqnext = NULL;
-+
-+	init_waitqueue_head(&bh->b_wait);
-+	atomic_set(&bh->b_count, 1);
-+	bh->b_list = PKT_BUF_LIST;
-+	bh->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | (1 << BH_Req);
-+	bh->b_dev = pd->pkt_dev;
-+
-+	return bh;
-+}
-+
-+static void pkt_end_io_write(struct buffer_head *, int);
-+
-+static struct buffer_head *pkt_get_buffer(struct pktcdvd_device *pd,
-+					  unsigned long sector, int size)
-+{
-+	unsigned long block = sector / (size >> 9);
-+	struct buffer_head *bh;
-+
-+	VPRINTK("get_buffer: sector=%ld, size=%d\n", sector, size);
-+
-+	bh = pkt_get_hash(pd->pkt_dev, block, size);
-+	if (bh)
-+		pd->stats.bh_cache_hits += (size >> 9);
-+	else
-+		bh = __pkt_get_buffer(pd, sector);
-+
-+	blk_started_io(bh->b_size >> 9);
-+	bh->b_blocknr = block;
-+	bh->b_end_io = pkt_end_io_write;
-+	bh->b_rsector = sector;
-+	bh->b_rdev = pd->dev;
-+	return bh;
-+}
-+
-+/*
-+ * this rq is done -- io_request_lock must be held and interrupts disabled
-+ */
-+static void pkt_rq_end_io(struct pktcdvd_device *pd)
-+{
-+	unsigned long flags;
-+
-+	VPRINTK("pkt_rq_end_io: rq=%p, cmd=%d, q=%p\n", pd->rq, pd->rq->cmd, pd->rq->q);
-+
-+	spin_lock_irqsave(&pd->lock, flags);
-+
-+	/*
-+	 * debug checks
-+	 */
-+	if (!test_bit(PACKET_RQ, &pd->flags))
-+		printk("pktcdvd: rq_end_io: RQ not set\n");
-+	if (!test_bit(PACKET_BUSY, &pd->flags))
-+		printk("pktcdvd: rq_end_io: BUSY not set\n");
-+
-+	__pkt_end_request(pd);
-+	wake_up(&pd->wqueue);
-+	spin_unlock_irqrestore(&pd->lock, flags);
-+}
-+
-+static inline void pkt_mark_readonly(struct pktcdvd_device *pd, int on)
-+{
-+	if (on)
-+		set_bit(PACKET_READONLY, &pd->flags);
-+	else
-+		clear_bit(PACKET_READONLY, &pd->flags);
-+}
-+
-+static inline void __pkt_end_io_write(struct pktcdvd_device *pd,
-+				      struct buffer_head *bh, int uptodate)
-+{
-+	VPRINTK("end_io_write: bh=%ld, uptodate=%d\n", bh->b_blocknr, uptodate);
-+
-+	/*
-+	 * general Linux bug, noone should clear the BH_Uptodate flag for
-+	 * a failed write...
-+	 */
-+	if (uptodate)
-+		mark_buffer_uptodate(bh, uptodate);
-+	else {
-+		printk("pktcdvd: %s: WRITE error sector %lu\n", pd->name, bh->b_rsector);
-+#if 0
-+		set_bit(PACKET_RECOVERY, &pd->flags);
-+		wake_up(&pd->wqueue);
-+#endif
-+	}
-+
-+	pd->stats.bh_e++;
-+
-+	atomic_dec(&pd->wrqcnt);
-+	if (atomic_read(&pd->wrqcnt) == 0) {
-+		pkt_rq_end_io(pd);
-+	}
-+
-+	unlock_buffer(bh);
-+}
-+
-+/*
-+ * we use this as our default b_end_io handler, since we need to take
-+ * the entire request off the list if just one of the clusters fail.
-+ * later on this should also talk to UDF about relocating blocks -- for
-+ * now we just drop the rq entirely. when doing the relocating we must also
-+ * lock the bh down to ensure that we can easily reconstruct the write should
-+ * it fail.
-+ */
-+static void pkt_end_io_write(struct buffer_head *bh, int uptodate)
-+{
-+	struct pktcdvd_device *pd = &pkt_devs[MINOR(bh->b_rdev)];
-+
-+	__pkt_end_io_write(pd, bh, uptodate);
-+	pkt_put_buffer(bh);
-+}
-+
-+static void pkt_end_io_write_stacked(struct buffer_head *bh, int uptodate)
-+{
-+	struct pktcdvd_device *pd = &pkt_devs[MINOR(bh->b_rdev)];
-+	struct buffer_head *rbh = bh->b_private;
-+
-+	__pkt_end_io_write(pd, bh, uptodate);
-+	rbh->b_end_io(rbh, uptodate);
-+	pkt_put_stacked_bh(pd, bh);
-+	wake_up(&pd_bh_wait);
-+}
-+
-+static int pkt_init_rq(struct pktcdvd_device *pd, struct request *rq)
-+{
-+	struct buffer_head *bh;
-+	unsigned int cnt, nr_segments;
-+
-+	cnt = 0;
-+	nr_segments = 1;
-+	bh = rq->bh;
-+	while (bh) {
-+		struct buffer_head *nbh = bh->b_reqnext;
-+
-+		bh->b_rdev = pd->pkt_dev;
-+
-+		/*
-+		 * the buffer better be mapped and locked!
-+		 */
-+		if (!buffer_locked(bh) || !buffer_mapped(bh)) {
-+			printk("%lu, state %lx\n", bh->b_rsector, bh->b_state);
-+			BUG();
-+		}
-+
-+		if (nbh) {
-+			if (!CONTIG_BH(bh, nbh))
-+				nr_segments++;
-+
-+			/*
-+			 * if this happens, do report
-+			 */
-+			if ((bh->b_rsector + (bh->b_size >> 9))!=nbh->b_rsector) {
-+				printk("%lu (%p)-> %lu (%p) (%lu in all)\n",
-+				bh->b_rsector, bh, nbh->b_rsector, nbh,
-+				rq->nr_sectors);
-+				return 1;
-+			}
-+		}
-+
-+		cnt += bh->b_size >> 9;
-+		bh = nbh;
-+	}
-+
-+	rq->nr_segments = rq->nr_hw_segments = nr_segments;
-+
-+	if (cnt != rq->nr_sectors) {
-+		printk("botched request %u (%lu)\n", cnt, rq->nr_sectors);
-+		return 1;
-+	}
-+
-+	return 0;
-+}
-+
-+/*
-+ * really crude stats for now...
-+ */
-+static void pkt_account_rq(struct pktcdvd_device *pd, int read, int written,
-+			   int bs)
-+{
-+	pd->stats.bh_s += (written / bs);
-+	pd->stats.secs_w += written;
-+	pd->stats.secs_r += read;
-+}
-+
-+/*
-+ * does request span two packets? 0 == yes, 1 == no
-+ */
-+static int pkt_one_zone(struct pktcdvd_device *pd, struct request *rq)
-+{
-+	if (!pd->settings.size)
-+		return 0;
-+
-+	if (!(rq->cmd & WRITE))
-+		return 1;
-+
-+	return ZONE(rq->sector, pd) == ZONE(rq->sector + rq->nr_sectors -1, pd);
-+}
-+
-+#if defined(CONFIG_CDROM_PKTCDVD_BEMPTY)
-+static void pkt_init_buffer(struct buffer_head *bh)
-+{
-+	set_bit(BH_Uptodate, &bh->b_state);
-+	set_bit(BH_Dirty, &bh->b_state);
-+	memset(bh->b_data, 0, bh->b_size);
-+}
-+
-+static int pkt_sb_empty(struct pktcdvd_device *pd, struct buffer_head *bh)
-+{
-+	struct super_block *sb;
-+	struct super_operations *sop;
-+	unsigned long packet;
-+	int ret;
-+
-+	ret = 0;
-+	if ((sb = get_super(pd->pkt_dev)) == NULL)
-+		goto out;
-+	if ((sop = sb->s_op) == NULL)
-+		goto out;
-+	if (sop->block_empty == NULL)
-+		goto out;
-+
-+	packet = 0;
-+	if (sop->block_empty(sb, bh->b_blocknr, &packet))  {
-+		pkt_init_buffer(pd, bh);
-+		ret = 1;
-+	}
-+
-+out:
-+	return ret;
-+}
-+
-+#else /* defined(CONFIG_CDROM_PKTCDVD_BEMPTY) */
-+
-+static int pkt_sb_empty(struct pktcdvd_device *pd, struct buffer_head *bh)
-+{
-+	return 0;
-+}
-+
-+#endif /* defined(CONFIG_CDROM_PKTCDVD_BEMPTY) */
-+
-+static int pkt_flush_cache(struct pktcdvd_device *pd);
-+
-+static void pkt_flush_writes(struct pktcdvd_device *pd)
-+{
-+	if (pd->unflushed_writes) {
-+		pd->unflushed_writes = 0;
-+		pkt_flush_cache(pd);
-+	}
-+}
-+
-+/*
-+ * basically just does a ll_rw_block for the bhs given to use, but we
-+ * don't return until we have them.
-+ */
-+static void pkt_read_bh(struct pktcdvd_device *pd, struct buffer_head *bh)
-+{
-+	/*
-+	 * UDF says it's empty, woohoo
-+	 */
-+	if (pkt_sb_empty(pd, bh))
-+		return;
-+
-+	down(&pd->cache_sync_mutex);
-+	pkt_flush_writes(pd);
-+	generic_make_request(READ, bh);
-+	up(&pd->cache_sync_mutex);
-+}
-+
-+static int pkt_index_bhs(struct buffer_head **bhs)
-+{
-+	struct buffer_head *bh;
-+	int index;
-+	int error = 0;
-+
-+	/*
-+	 * now finish pending reads and connect the chain of buffers
-+	 */
-+	index = 0;
-+	while (index < PACKET_MAX_SIZE) {
-+		bh = bhs[index];
-+
-+		/*
-+		 * pin down private buffers (ie, force I/O to complete)
-+		 */
-+		if (bh->b_end_io == pkt_end_io_read) {
-+			lock_buffer(bh);
-+			bh->b_end_io = pkt_end_io_write;
-+			if (!buffer_uptodate(bh)) {
-+				printk("pktcdvd: read failure (%s, sec %lu)\n",
-+				       kdevname(bh->b_rdev), bh->b_rsector);
-+				error = 1;
-+			}
-+		}
-+
-+		if (!buffer_locked(bh))
-+			BUG();
-+
-+		/*
-+		 * attach previous
-+		 */
-+		if (index) {
-+			struct buffer_head *pbh = bhs[index - 1];
-+
-+			if ((pbh->b_rsector + (pbh->b_size >> 9)) != bh->b_rsector) {
-+				printk("%lu -> %lu\n", pbh->b_rsector, bh->b_rsector);
-+				index = 0;
-+				break;
-+			}
-+			pbh->b_reqnext = bh;
-+		}
-+		index++;
-+	}
-+
-+	if (error)
-+		return 0;
-+
-+	if (index) {
-+		index--;
-+		bhs[index]->b_reqnext = NULL;
-+	}
-+
-+	return index;
-+}
-+
-+/*
-+ * fill in the holes of a request
-+ *
-+ * Returns: 0, keep 'em coming -- 1, stop queueing
-+ */
-+static int pkt_gather_data(struct pktcdvd_device *pd, struct request *rq)
-+{
-+	unsigned long start_s, end_s, sector;
-+	struct buffer_head *bh;
-+	unsigned int sectors, index;
-+	struct buffer_head *bhs[PACKET_MAX_SIZE];
-+
-+	memset(bhs, 0, sizeof(bhs));
-+
-+	/*
-+	 * all calculations are done with 512 byte sectors
-+	 */
-+	sectors = pd->settings.size - rq->nr_sectors;
-+	start_s = rq->sector - (rq->sector & (pd->settings.size - 1));
-+	end_s = start_s + pd->settings.size;
-+
-+	VPRINTK("pkt_gather_data: cmd=%d\n", rq->cmd);
-+	VPRINTK("need %d sectors for %s\n", sectors, kdevname(pd->dev));
-+	VPRINTK("from %lu to %lu ", start_s, end_s);
-+	VPRINTK("(%lu - %lu)\n", rq->bh->b_rsector, rq->bhtail->b_rsector +
-+				 rq->current_nr_sectors);
-+
-+	/*
-+	 * first fill-out map of the buffers we have
-+	 */
-+	bh = rq->bh;
-+	while (bh) {
-+		index = (bh->b_rsector & (pd->settings.size - 1)) / (bh->b_size >> 9);
-+
-+		bhs[index] = bh;
-+		bh = bh->b_reqnext;
-+
-+		/*
-+		 * make sure to detach from list!
-+		 */
-+		bhs[index]->b_reqnext = NULL;
-+	}
-+
-+	/*
-+	 * now get buffers for missing blocks, and schedule reads for them
-+	 */
-+	for (index = 0, sector = start_s; sector < end_s; index++) {
-+		if (bhs[index]) {
-+			bh = bhs[index];
-+			goto next;
-+		}
-+
-+		bh = pkt_get_buffer(pd, sector, CD_FRAMESIZE);
-+
-+		bhs[index] = bh;
-+		rq->nr_sectors += bh->b_size >> 9;
-+		rq->nr_segments++;
-+
-+		if (!buffer_uptodate(bh)) {
-+			bh->b_end_io = pkt_end_io_read;
-+			pkt_read_bh(pd, bh);
-+		}
-+
-+	next:
-+		sector += bh->b_size >> 9;
-+	}
-+
-+	index = pkt_index_bhs(bhs);
-+#if 0
-+	if (!index)
-+		goto kill_it;
-+#endif
-+
-+	rq->bh = bhs[0];
-+	rq->bhtail = bhs[index];
-+	rq->buffer = rq->bh->b_data;
-+	rq->current_nr_sectors = rq->bh->b_size >> 9;
-+	rq->hard_nr_sectors = rq->nr_sectors;
-+	rq->sector = rq->hard_sector = start_s;
-+
-+	VPRINTK("unlocked last %lu\n", rq->bhtail->b_rsector);
-+	if (pkt_init_rq(pd, rq)) {
-+		for (index = 0; index < PACKET_MAX_SIZE; index++) {
-+			bh = bhs[index];
-+			printk("[%d] %lu %d (%p -> %p)\n", index, bh->b_rsector,
-+					bh->b_size, bh, bh->b_reqnext);
-+		}
-+		goto kill_it;
-+	}
-+
-+	pkt_account_rq(pd, sectors, rq->nr_sectors, rq->current_nr_sectors);
-+
-+	/*
-+	 * sanity check
-+	 */
-+	if (rq->nr_sectors != pd->settings.size) {
-+		printk("pktcdvd: request mismatch %lu (should be %u)\n",
-+					rq->nr_sectors, pd->settings.size);
-+		BUG();
-+	}
-+
-+	return 0;
-+
-+	/*
-+	 * for now, just kill entire request and hope for the best...
-+	 */
-+kill_it:
-+	for (index = 0; index < PACKET_MAX_SIZE; index++) {
-+		bh = bhs[index];
-+		buffer_IO_error(bh);
-+		if (bh->b_list == PKT_BUF_LIST)
-+			pkt_put_buffer(bh);
-+	}
-+	end_that_request_last(pd->rq);
-+	return 1;
-+}
-+
-+/*
-+ * Returns: 1, keep 'em coming -- 0, wait for wakeup
-+ */
-+static int pkt_do_request(struct pktcdvd_device *pd, struct request *rq)
-+{
-+	VPRINTK("do_request: bh=%ld, nr_sectors=%ld, size=%d, cmd=%d\n", rq->bh->b_blocknr, rq->nr_sectors, pd->settings.size, rq->cmd);
-+
-+	/*
-+	 * perfect match. the merge_* functions have already made sure that
-+	 * a request doesn't cross a packet boundary, so if the sector
-+	 * count matches it's good.
-+	 */
-+	if (rq->nr_sectors == pd->settings.size) {
-+		if (pkt_init_rq(pd, rq)) {
-+			pkt_kill_request(pd, rq, 0);
-+			return 1;
-+		}
-+
-+		pkt_account_rq(pd, 0, rq->nr_sectors, rq->current_nr_sectors);
-+		return 0;
-+	}
-+
-+	/*
-+	 * paranoia...
-+	 */
-+	if (rq->nr_sectors > pd->settings.size) {
-+		printk("pktcdvd: request too big! BUG! %lu\n", rq->nr_sectors);
-+		BUG();
-+	}
-+
-+	return pkt_gather_data(pd, rq);
-+}
-+
-+/*
-+ * recover a failed write, query for relocation if possible
-+ */
-+static int pkt_start_recovery(struct pktcdvd_device *pd, struct request *rq)
-+{
-+#if 0
-+	struct super_block *sb = get_super(pd->pkt_dev);
-+	struct buffer_head *bhs[PACKET_MAX_SIZE], *bh, *obh;
-+	unsigned long old_block, new_block, sector;
-+	int i, sectors;
-+
-+	if (!sb || !sb->s_op || !sb->s_op->relocate_blocks)
-+		goto fail;
-+
-+	old_block = (rq->sector & ~(pd->settings.size - 1)) / (rq->bh->b_size >> 9);
-+	if (sb->s_op->relocate_blocks(sb, old_block, &new_block))
-+		goto fail;
-+
-+	memset(bhs, 0, sizeof(bhs));
-+	bh = rq->bh;
-+	while (bh) {
-+		i = (bh->b_rsector & (pd->settings.size - 1)) / (bh->b_size >> 9);
-+
-+		bhs[i] = bh;
-+		bh = bh->b_reqnext;
-+		bhs[i]->b_reqnext = NULL;
-+	}
-+
-+	sectors = 0;
-+	sector = new_block * (rq->bh->b_size >> 9);
-+	for (i = 0; i < PACKET_MAX_SIZE; i++) {
-+		bh = bhs[i];
-+
-+		/*
-+		 * three cases -->
-+		 *	1) bh is not there at all
-+		 *	2) bh is there and not ours, get a new one and
-+		 *	   invalidate this block for the future
-+		 *	3) bh is there and ours, just change the sector
-+		 */
-+		if (!bh) {
-+			obh = pkt_get_hash(pd->pkt_dev, new_block,CD_FRAMESIZE);
-+			bh = __pkt_get_buffer(pd, sector);
-+			if (obh) {
-+				if (buffer_uptodate(obh)) {
-+					memcpy(bh->b_data, obh->b_data, obh->b_size);
-+					set_bit(BH_Uptodate, &bh->b_state);
-+				}
-+				unlock_buffer(obh);
-+				bforget(obh);
-+			}
-+			bhs[i] = bh;
-+		} else if (bh->b_list != PKT_BUF_LIST) {
-+			bhs[i] = pkt_get_buffer(pd, sector, CD_FRAMESIZE);
-+			memcpy(bhs[i]->b_data, bh->b_data, CD_FRAMESIZE);
-+			unlock_buffer(bh);
-+			bforget(bh);
-+			bh = bhs[i];
-+			set_bit(BH_Uptodate, &bh->b_state);
-+		} else {
-+			bh->b_rsector = sector;
-+			bh->b_blocknr = new_block;
-+		}
-+
-+		sector += (bh->b_size >> 9);
-+		new_block++;
-+		sectors +=  (bh->b_size >> 9);
-+	}
-+
-+	i = pkt_index_bhs(bhs);
-+	if (!i)
-+		goto fail;
-+
-+	rq->bh = bhs[0];
-+	rq->bhtail = bhs[i];
-+	rq->buffer = rq->bh->b_data;
-+	rq->current_nr_sectors = rq->bh->b_size >> 9;
-+	rq->hard_nr_sectors = rq->nr_sectors = sectors;
-+	rq->sector = rq->hard_sector = rq->bh->b_rsector;
-+	rq->errors = 0;
-+	clear_bit(PACKET_RECOVERY, &pd->flags);
-+	clear_bit(PACKET_BUSY, &pd->flags);
-+	return 0;
-+
-+fail:
-+#endif
-+	printk("pktcdvd: rq recovery not possible\n");
-+	pkt_kill_request(pd, rq, 0);
-+	clear_bit(PACKET_RECOVERY, &pd->flags);
-+	return 1;
-+}
-+
-+/*
-+ * handle the requests that got queued for this writer
-+ *
-+ * returns 0 for busy (already doing something), or 1 for queue new one
-+ *
-+ */
-+static int pkt_handle_queue(struct pktcdvd_device *pd, request_queue_t *q)
-+{
-+	struct request *rq;
-+	int ret;
-+
-+	VPRINTK("handle_queue\n");
-+
-+	/*
-+	 * nothing for us to do
-+	 */
-+	if (!test_bit(PACKET_RQ, &pd->flags))
-+		return 1;
-+
-+	spin_lock_irq(&pd->lock);
-+	rq = pd->rq;
-+	spin_unlock_irq(&pd->lock);
-+
-+	if (test_bit(PACKET_RECOVERY, &pd->flags))
-+		if (pkt_start_recovery(pd, rq))
-+			return 1;
-+
-+	/*
-+	 * already being processed
-+	 */
-+	if (test_and_set_bit(PACKET_BUSY, &pd->flags))
-+		return 0;
-+
-+	/*
-+	 * nothing to do
-+	 */
-+	ret = 1;
-+	if (rq == NULL) {
-+		printk("handle_queue: pd BUSY+RQ, but no rq\n");
-+		clear_bit(PACKET_RQ, &pd->flags);
-+		goto out;
-+	}
-+
-+	/*
-+	 * reads are shipped directly to cd-rom, so they should not
-+	 * pop up here
-+	 */
-+	if (rq->cmd == READ)
-+		BUG();
-+
-+	if ((rq->current_nr_sectors << 9) != CD_FRAMESIZE) {
-+		pkt_kill_request(pd, rq, 0);
-+		goto out;
-+	}
-+
-+	if (!pkt_do_request(pd, rq)) {
-+		atomic_add(PACKET_MAX_SIZE, &pd->wrqcnt);
-+		down(&pd->cache_sync_mutex);
-+		pkt_inject_request(q, rq);
-+		pd->unflushed_writes = 1;
-+		up(&pd->cache_sync_mutex);
-+		return 0;
-+	}
-+
-+out:
-+	clear_bit(PACKET_BUSY, &pd->flags);
-+	return ret;
-+}
-+
-+/*
-+ * kpacketd is woken up, when writes have been queued for one of our
-+ * registered devices
-+ */
-+static int kcdrwd(void *foobar)
-+{
-+	struct pktcdvd_device *pd = foobar;
-+	request_queue_t *q, *my_queue;
-+
-+	/*
-+	 * exit_files, mm (move to lazy-tlb, so context switches are come
-+	 * extremely cheap) etc
-+	 */
-+	daemonize();
-+
-+	current->policy = SCHED_OTHER;
-+	current->nice = -20;
-+	sprintf(current->comm, pd->name);
-+
-+	spin_lock_irq(&current->sigmask_lock);
-+	siginitsetinv(&current->blocked, sigmask(SIGKILL));
-+	flush_signals(current);
-+	spin_unlock_irq(&current->sigmask_lock);
-+
-+	q = blk_get_queue(pd->dev);
-+	my_queue = blk_get_queue(pd->pkt_dev);
-+
-+	for (;;) {
-+		DECLARE_WAITQUEUE(wait, current);
-+
-+		add_wait_queue(&pd->wqueue, &wait);
-+
-+		/*
-+		 * if PACKET_BUSY is cleared, we can queue
-+		 * another request. otherwise we need to unplug the
-+		 * cd-rom queue and wait for buffers to be flushed
-+		 * (which will then wake us up again when done).
-+		 */
-+		do {
-+			pkt_handle_queue(pd, q);
-+
-+			set_current_state(TASK_INTERRUPTIBLE);
-+
-+			if (test_bit(PACKET_BUSY, &pd->flags))
-+				break;
-+
-+			spin_lock_irq(&io_request_lock);
-+			if (list_empty(&my_queue->queue_head)) {
-+				spin_unlock_irq(&io_request_lock);
-+				break;
-+			}
-+			set_current_state(TASK_RUNNING);
-+
-+			my_queue->request_fn(my_queue);
-+			spin_unlock_irq(&io_request_lock);
-+		} while (1);
-+
-+		generic_unplug_device(q);
-+
-+		schedule();
-+		remove_wait_queue(&pd->wqueue, &wait);
-+
-+		if (signal_pending(current)) {
-+			flush_signals(current);
-+		}
-+		if (pd->cdrw.time_to_die)
-+			break;
-+	}
-+
-+	complete_and_exit(&pd->cdrw.thr_compl, 0);
-+	return 0;
-+}
-+
-+static void pkt_attempt_remerge(struct pktcdvd_device *pd, request_queue_t *q,
-+				struct request *rq)
-+{
-+	struct request *nxt;
-+
-+	while (!list_empty(&q->queue_head)) {
-+		if (rq->nr_sectors == pd->settings.size)
-+			break;
-+
-+		nxt = blkdev_entry_next_request(&q->queue_head);
-+
-+		if (ZONE(rq->sector, pd) != ZONE(nxt->sector, pd))
-+			break;
-+		else if (rq->sector + rq->nr_sectors > nxt->sector)
-+			break;
-+
-+		rq->nr_sectors = rq->hard_nr_sectors += nxt->nr_sectors;
-+		rq->bhtail->b_reqnext = nxt->bh;
-+		rq->bhtail = nxt->bhtail;
-+		list_del(&nxt->queue);
-+		blkdev_release_request(nxt);
-+	}
-+}
-+
-+/*
-+ * our request function.
-+ *
-+ * - reads are just tossed directly to the device, we don't care.
-+ * - writes, regardless of size, are added as the current pd rq and
-+ *   kcdrwd is woken up to handle it. kcdrwd will also make sure to
-+ *   reinvoke this request handler, once the given request has been
-+ *   processed.
-+ *
-+ * Locks: io_request_lock held
-+ *
-+ * Notes: all writers have their own queue, so all requests are for the
-+ *	  the same device
-+ */
-+static void pkt_request(request_queue_t *q)
-+{
-+	struct pktcdvd_device *pd = (struct pktcdvd_device *) q->queuedata;
-+	unsigned long flags;
-+
-+	if (list_empty(&q->queue_head))
-+		return;
-+
-+	while (!list_empty(&q->queue_head)) {
-+		struct request *rq = blkdev_entry_next_request(&q->queue_head);
-+
-+		VPRINTK("pkt_request: cmd=%d, rq=%p, rq->sector=%ld, rq->nr_sectors=%ld\n", rq->cmd, rq, rq->sector, rq->nr_sectors);
-+
-+		blkdev_dequeue_request(rq);
-+
-+		rq->rq_dev = pd->dev;
-+
-+		if (rq->cmd == READ)
-+			BUG();
-+
-+		if (test_bit(PACKET_RECOVERY, &pd->flags))
-+			break;
-+
-+		/*
-+		 * paranoia, shouldn't trigger...
-+		 */
-+		if (!pkt_one_zone(pd, rq)) {
-+			printk("rq->cmd=%d, rq->sector=%ld, rq->nr_sectors=%ld\n",
-+				rq->cmd, rq->sector, rq->nr_sectors);
-+			BUG();
-+		}
-+
-+		pkt_attempt_remerge(pd, q, rq);
-+
-+		spin_lock_irqsave(&pd->lock, flags);
-+
-+		/*
-+		 * already gathering data for another read. the
-+		 * rfn will be reinvoked once that is done
-+		 */
-+		if (test_and_set_bit(PACKET_RQ, &pd->flags)) {
-+			list_add(&rq->queue, &q->queue_head);
-+			spin_unlock_irqrestore(&pd->lock, flags);
-+			break;
-+		}
-+
-+		if (pd->rq)
-+			BUG();
-+
-+		pd->rq = rq;
-+		spin_unlock_irqrestore(&pd->lock, flags);
-+		break;
-+	}
-+	VPRINTK("wake up wait queue\n");
-+	wake_up(&pd->wqueue);
-+}
-+
-+static void pkt_print_settings(struct pktcdvd_device *pd)
-+{
-+	printk("pktcdvd: %s packets, ", pd->settings.fp ? "Fixed" : "Variable");
-+	printk("%u blocks, ", pd->settings.size >> 2);
-+	printk("Mode-%c disc\n", pd->settings.block_mode == 8 ? '1' : '2');
-+}
-+
-+/*
-+ * A generic sense dump / resolve mechanism should be implemented across
-+ * all ATAPI + SCSI devices.
-+ */
-+static void pkt_dump_sense(struct cdrom_generic_command *cgc)
-+{
-+	static char *info[9] = { "No sense", "Recovered error", "Not ready",
-+				 "Medium error", "Hardware error", "Illegal request",
-+				 "Unit attention", "Data protect", "Blank check" };
-+	int i;
-+	struct request_sense *sense = cgc->sense;
-+
-+	printk("pktcdvd:");
-+	for (i = 0; i < CDROM_PACKET_SIZE; i++)
-+		printk(" %02x", cgc->cmd[i]);
-+	printk(" - ");
-+
-+	if (sense == NULL) {
-+		printk("no sense\n");
-+		return;
-+	}
-+
-+	printk("sense %02x.%02x.%02x", sense->sense_key, sense->asc, sense->ascq);
-+
-+	if (sense->sense_key > 8) {
-+		printk(" (INVALID)\n");
-+		return;
-+	}
-+
-+	printk(" (%s)\n", info[sense->sense_key]);
-+}
-+
-+/*
-+ * write mode select package based on pd->settings
-+ */
-+static int pkt_set_write_settings(struct pktcdvd_device *pd)
-+{
-+	struct cdrom_device_info *cdi = pd->cdi;
-+	struct cdrom_generic_command cgc;
-+	struct request_sense sense;
-+	write_param_page *wp;
-+	char buffer[128];
-+	int ret, size;
-+
-+	memset(buffer, 0, sizeof(buffer));
-+	init_cdrom_command(&cgc, buffer, sizeof(*wp), CGC_DATA_READ);
-+	cgc.sense = &sense;
-+	if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) {
-+		pkt_dump_sense(&cgc);
-+		return ret;
-+	}
-+
-+	size = 2 + ((buffer[0] << 8) | (buffer[1] & 0xff));
-+	pd->mode_offset = (buffer[6] << 8) | (buffer[7] & 0xff);
-+	if (size > sizeof(buffer))
-+		size = sizeof(buffer);
-+
-+	/*
-+	 * now get it all
-+	 */
-+	init_cdrom_command(&cgc, buffer, size, CGC_DATA_READ);
-+	cgc.sense = &sense;
-+	if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) {
-+		pkt_dump_sense(&cgc);
-+		return ret;
-+	}
-+
-+	/*
-+	 * write page is offset header + block descriptor length
-+	 */
-+	wp = (write_param_page *) &buffer[sizeof(struct mode_page_header) + pd->mode_offset];
-+
-+	wp->fp = pd->settings.fp;
-+	wp->track_mode = pd->settings.track_mode;
-+	wp->write_type = pd->settings.write_type;
-+	wp->data_block_type = pd->settings.block_mode;
-+
-+	wp->multi_session = 0;
-+
-+#ifdef PACKET_USE_LS
-+	wp->link_size = 7;
-+	wp->ls_v = 1;
-+#endif
-+
-+	if (wp->data_block_type == PACKET_BLOCK_MODE1) {
-+		wp->session_format = 0;
-+		wp->subhdr2 = 0x20;
-+	} else if (wp->data_block_type == PACKET_BLOCK_MODE2) {
-+		wp->session_format = 0x20;
-+		wp->subhdr2 = 8;
-+#if 0
-+		wp->mcn[0] = 0x80;
-+		memcpy(&wp->mcn[1], PACKET_MCN, sizeof(wp->mcn) - 1);
-+#endif
-+	} else {
-+		/*
-+		 * paranoia
-+		 */
-+		printk("pktcdvd: write mode wrong %d\n", wp->data_block_type);
-+		return 1;
-+	}
-+	wp->packet_size = cpu_to_be32(pd->settings.size >> 2);
-+
-+	cgc.buflen = cgc.cmd[8] = size;
-+	if ((ret = cdrom_mode_select(cdi, &cgc))) {
-+		pkt_dump_sense(&cgc);
-+		return ret;
-+	}
-+
-+	pkt_print_settings(pd);
-+	return 0;
-+}
-+
-+/*
-+ * 0 -- we can write to this track, 1 -- we can't
-+ */
-+static int pkt_good_track(track_information *ti)
-+{
-+	/*
-+	 * only good for CD-RW at the moment, not DVD-RW
-+	 */
-+
-+	/*
-+	 * FIXME: only for FP
-+	 */
-+	if (ti->fp == 0)
-+		return 0;
-+
-+	/*
-+	 * "good" settings as per Mt Fuji.
-+	 */
-+	if (ti->rt == 0 && ti->blank == 0 && ti->packet == 1)
-+		return 0;
-+
-+	if (ti->rt == 0 && ti->blank == 1 && ti->packet == 1)
-+		return 0;
-+
-+	if (ti->rt == 1 && ti->blank == 0 && ti->packet == 1)
-+		return 0;
-+
-+	printk("pktcdvd: bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
-+	return 1;
-+}
-+
-+/*
-+ * 0 -- we can write to this disc, 1 -- we can't
-+ */
-+static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
-+{
-+	/*
-+	 * for disc type 0xff we should probably reserve a new track.
-+	 * but i'm not sure, should we leave this to user apps? probably.
-+	 */
-+	if (di->disc_type == 0xff) {
-+		printk("pktcdvd: Unknown disc. No track?\n");
-+		return 1;
-+	}
-+
-+	if (di->disc_type != 0x20 && di->disc_type != 0) {
-+		printk("pktcdvd: Wrong disc type (%x)\n", di->disc_type);
-+		return 1;
-+	}
-+
-+	if (di->erasable == 0) {
-+		printk("pktcdvd: Disc not erasable\n");
-+		return 1;
-+	}
-+
-+	if (pd->track_status == PACKET_SESSION_RESERVED) {
-+		printk("pktcdvd: Can't write to last track (reserved)\n");
-+		return 1;
-+	}
-+
-+	return 0;
-+}
-+
-+static int pkt_probe_settings(struct pktcdvd_device *pd)
-+{
-+	disc_information di;
-+	track_information ti;
-+	int ret, track;
-+
-+	memset(&di, 0, sizeof(disc_information));
-+	memset(&ti, 0, sizeof(track_information));
-+
-+	if ((ret = cdrom_get_disc_info(pd->dev, &di))) {
-+		printk("failed get_disc\n");
-+		return ret;
-+	}
-+
-+	pd->disc_status = di.disc_status;
-+	pd->track_status = di.border_status;
-+
-+	if (pkt_good_disc(pd, &di))
-+		return -ENXIO;
-+
-+	printk("pktcdvd: inserted media is CD-R%s\n", di.erasable ? "W" : "");
-+	pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR;
-+
-+	track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
-+	if ((ret = cdrom_get_track_info(pd->dev, track, 1, &ti))) {
-+		printk("pktcdvd: failed get_track\n");
-+		return ret;
-+	}
-+
-+	if (pkt_good_track(&ti)) {
-+		printk("pktcdvd: can't write to this track\n");
-+		return -ENXIO;
-+	}
-+
-+	/*
-+	 * we keep packet size in 512 byte units, makes it easier to
-+	 * deal with request calculations.
-+	 */
-+	pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
-+	if (pd->settings.size == 0) {
-+		printk("pktcdvd: detected zero packet size!\n");
-+		pd->settings.size = 128;
-+	}
-+	pd->settings.fp = ti.fp;
-+	pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
-+
-+	if (ti.nwa_v) {
-+		pd->nwa = be32_to_cpu(ti.next_writable);
-+		set_bit(PACKET_NWA_VALID, &pd->flags);
-+	}
-+
-+	/*
-+	 * in theory we could use lra on -RW media as well and just zero
-+	 * blocks that haven't been written yet, but in practice that
-+	 * is just a no-go. we'll use that for -R, naturally.
-+	 */
-+	if (ti.lra_v) {
-+		pd->lra = be32_to_cpu(ti.last_rec_address);
-+		set_bit(PACKET_LRA_VALID, &pd->flags);
-+	} else {
-+		pd->lra = 0xffffffff;
-+		set_bit(PACKET_LRA_VALID, &pd->flags);
-+	}
-+
-+	/*
-+	 * fine for now
-+	 */
-+	pd->settings.link_loss = 7;
-+	pd->settings.write_type = 0;	/* packet */
-+	pd->settings.track_mode = ti.track_mode;
-+
-+	/*
-+	 * mode1 or mode2 disc
-+	 */
-+	switch (ti.data_mode) {
-+		case PACKET_MODE1:
-+			pd->settings.block_mode = PACKET_BLOCK_MODE1;
-+			break;
-+		case PACKET_MODE2:
-+			pd->settings.block_mode = PACKET_BLOCK_MODE2;
-+			break;
-+		default:
-+			printk("pktcdvd: unknown data mode\n");
-+			return 1;
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * enable/disable write caching on drive
-+ */
-+static int pkt_write_caching(struct pktcdvd_device *pd, int set)
-+{
-+	struct cdrom_generic_command cgc;
-+	struct request_sense sense;
-+	unsigned char buf[64];
-+	int ret;
-+
-+	memset(buf, 0, sizeof(buf));
-+	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
-+	cgc.sense = &sense;
-+	cgc.buflen = pd->mode_offset + 12;
-+
-+	/*
-+	 * caching mode page might not be there, so quiet this command
-+	 */
-+	cgc.quiet = 1;
-+
-+	if ((ret = cdrom_mode_sense(pd->cdi, &cgc, GPMODE_WCACHING_PAGE, 0)))
-+		return ret;
-+
-+	buf[pd->mode_offset + 10] |= (!!set << 2);
-+
-+	cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff));
-+	ret = cdrom_mode_select(pd->cdi, &cgc);
-+	if (ret) {
-+		printk("pktcdvd: write caching control failed\n");
-+		pkt_dump_sense(&cgc);
-+	} else if (!ret && set)
-+		printk("pktcdvd: enabled write caching on %s\n", pd->name);
-+	return ret;
-+}
-+
-+/*
-+ * flush the drive cache to media
-+ */
-+static int pkt_flush_cache(struct pktcdvd_device *pd)
-+{
-+	struct cdrom_generic_command cgc;
-+
-+	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
-+	cgc.cmd[0] = GPCMD_FLUSH_CACHE;
-+	cgc.quiet = 1;
-+	cgc.timeout = 60*HZ;
-+
-+	/*
-+	 * the IMMED bit -- we default to not setting it, although that
-+	 * would allow a much faster close, this is safer
-+	 */
-+#if 0
-+	cgc.cmd[1] = 1 << 1;
-+#endif
-+	return pd->cdi->ops->generic_packet(pd->cdi, &cgc);
-+}
-+
-+/*
-+ * Returns drive current write speed
-+ */
-+static int pkt_get_speed(struct pktcdvd_device *pd)
-+{
-+	struct cdrom_generic_command cgc;
-+	struct request_sense sense;
-+	unsigned char buf[64];
-+	int ret, offset;
-+
-+	memset(buf, 0, sizeof(buf));
-+	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_UNKNOWN);
-+	cgc.sense = &sense;
-+
-+	ret = cdrom_mode_sense(pd->cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
-+	if (ret) {
-+		cgc.buflen = pd->mode_offset + buf[pd->mode_offset + 9] + 2 +
-+			     sizeof(struct mode_page_header);
-+		ret = cdrom_mode_sense(pd->cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
-+		if (ret) {
-+			pkt_dump_sense(&cgc);
-+			return ret;
-+		}
-+	}
-+
-+	/* find out the current write speed selected
-+	 * there are an obsoleted field for older drives (offset 20),
-+	 * and a new field for newer (high-speed) drives (offset 28).
-+	 */
-+
-+	if (buf[pd->mode_offset+9] >= 28)
-+		offset = pd->mode_offset + 36;
-+	else
-+		offset = pd->mode_offset + 28;
-+
-+	pd->speed = ((buf[offset] << 8) | buf[offset + 1]) / 0xb0;
-+	return 0;
-+}
-+
-+/* These tables from cdrecord - I don't have orange book */
-+/* standard speed CD-RW (1-4x) */
-+static char clv_to_speed[16] = {
-+	/* 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 */
-+	   0, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-+};
-+/* high speed CD-RW (-10x) */
-+static char hs_clv_to_speed[16] = {
-+	/* 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 */
-+	   0, 2, 4, 6, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-+};
-+/* ultra high speed CD-RW */
-+static char us_clv_to_speed[16] = {
-+	/* 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 */
-+	   0, 2, 4, 8, 0, 0,16, 0,24,32,40,48, 0, 0, 0, 0
-+};
-+
-+/*
-+ * reads the maximum media speed from ATIP
-+ */
-+static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed)
-+{
-+	struct cdrom_generic_command cgc;
-+	struct request_sense sense;
-+	unsigned char buf[64];
-+	unsigned int size, st, sp;
-+	int ret;
-+
-+	init_cdrom_command(&cgc, buf, 2, CGC_DATA_READ);
-+	cgc.sense = &sense;
-+	cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-+	cgc.cmd[1] = 2;
-+	cgc.cmd[2] = 4; /* READ ATIP */
-+	cgc.cmd[8] = 2;
-+	ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc);
-+	if (ret) {
-+		pkt_dump_sense(&cgc);
-+		return ret;
-+	}
-+	size = ((unsigned int) buf[0]<<8) + buf[1] + 2;
-+	if (size > sizeof(buf))
-+		size = sizeof(buf);
-+
-+	init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
-+	cgc.sense = &sense;
-+	cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-+	cgc.cmd[1] = 2;
-+	cgc.cmd[2] = 4;
-+	cgc.cmd[8] = size;
-+	ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc);
-+	if (ret) {
-+		pkt_dump_sense(&cgc);
-+		return ret;
-+	}
-+
-+	if (!buf[6] & 0x40) {
-+		printk("pktcdvd: Disc type is not CD-RW\n");
-+		return 1;
-+	}
-+	if (!buf[6] & 0x4) {
-+		printk("pktcdvd: A1 values on media are not valid, maybe not CDRW?\n");
-+		return 1;
-+	}
-+
-+	st = (buf[6] >> 3) & 0x7; /* disc sub-type */
-+
-+	sp = buf[16] & 0xf; /* max speed from ATIP A1 field */
-+
-+	/* Info from cdrecord */
-+	switch (st) {
-+		case 0: /* standard speed */
-+			*speed = clv_to_speed[sp];
-+			break;
-+		case 1: /* high speed */
-+			*speed = hs_clv_to_speed[sp];
-+			break;
-+		case 2: /* ultra high speed */
-+			*speed = us_clv_to_speed[sp];
-+			break;
-+		default:
-+			printk("pktcdvd: Unknown disc sub-type %d\n",st);
-+			return 1;
-+	}
-+	if (*speed) {
-+		printk("pktcdvd: Max. media speed: %d\n",*speed);
-+		return 0;
-+	} else {
-+		printk("pktcdvd: Unknown speed %d for sub-type %d\n",sp,st);
-+		return 1;
-+	}
-+}
-+
-+/*
-+ * speed is given as the normal factor, e.g. 4 for 4x
-+ */
-+static int pkt_set_speed(struct pktcdvd_device *pd, unsigned write_speed)
-+{
-+	struct cdrom_generic_command cgc;
-+	struct request_sense sense;
-+	unsigned read_speed;
-+	int ret;
-+
-+	/*
-+	 * we set read and write time so that read spindle speed is one and
-+	 * a half as fast as write. although a drive can typically read much
-+	 * faster than write, this minimizes the spin up/down when we write
-+	 * and gather data. maybe 1/1 factor is faster, needs a bit of testing.
-+	 */
-+	write_speed = write_speed * 0xb1; /* should be 176.4, but CD-RWs rounds down */
-+	write_speed = min_t(unsigned, write_speed, 0xffff);
-+	read_speed = (write_speed * 3) >> 1;
-+	read_speed = min_t(unsigned, read_speed, 0xffff);
-+
-+	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
-+	cgc.sense = &sense;
-+	cgc.cmd[0] = GPCMD_SET_SPEED;
-+	cgc.cmd[2] = (read_speed >> 8) & 0xff;
-+	cgc.cmd[3] = read_speed & 0xff;
-+	cgc.cmd[4] = (write_speed >> 8) & 0xff;
-+	cgc.cmd[5] = write_speed & 0xff;
-+
-+	if ((ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc)))
-+		pkt_dump_sense(&cgc);
-+	return ret;
-+}
-+
-+/*
-+ * Give me full power, Captain
-+ */
-+static int pkt_adjust_speed(struct pktcdvd_device *pd, int speed)
-+{
-+	disc_information dummy;
-+	int ret;
-+
-+	/*
-+	 * FIXME: do proper unified cap page, also, this isn't proper
-+	 * Mt Fuji, but I think we can safely assume all drives support
-+	 * it. A hell of a lot more than support the GET_PERFORMANCE
-+	 * command (besides, we also use the old set speed command,
-+	 * not the streaming feature).
-+	 */
-+	if ((ret = pkt_set_speed(pd, speed)))
-+		return ret;
-+
-+	/*
-+	 * just do something with the disc -- next read will contain the
-+	 * maximum speed with this media
-+	 */
-+	if ((ret = cdrom_get_disc_info(pd->dev, &dummy)))
-+		return ret;
-+
-+	if ((ret = pkt_get_speed(pd))) {
-+		printk("pktcdvd: failed get speed\n");
-+		return ret;
-+	}
-+
-+	DPRINTK("pktcdvd: speed (R/W) %u/%u\n", (pd->speed * 3) / 2, pd->speed);
-+	return 0;
-+}
-+
-+static int pkt_perform_opc(struct pktcdvd_device *pd)
-+{
-+	struct cdrom_generic_command cgc;
-+	struct request_sense sense;
-+	int ret;
-+
-+	VPRINTK("pktcdvd: Performing OPC\n");
-+
-+	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
-+	cgc.sense = &sense;
-+	cgc.timeout = 60*HZ;
-+	cgc.cmd[0] = GPCMD_SEND_OPC;
-+	cgc.cmd[1] = 1;
-+	if ((ret = pd->cdi->ops->generic_packet(pd->cdi, &cgc)))
-+		pkt_dump_sense(&cgc);
-+	return ret;
-+}
-+
-+static int pkt_open_write(struct pktcdvd_device *pd)
-+{
-+	int ret;
-+	unsigned int speed;
-+
-+	if ((ret = pkt_probe_settings(pd))) {
-+		DPRINTK("pktcdvd: %s failed probe\n", pd->name);
-+		return -EIO;
-+	}
-+
-+	if ((ret = pkt_set_write_settings(pd))) {
-+		DPRINTK("pktcdvd: %s failed saving write settings\n", pd->name);
-+		return -EIO;
-+	}
-+
-+	(void) pkt_write_caching(pd, USE_WCACHING);
-+
-+	ret = pkt_media_speed(pd, &speed);
-+	speed = ret ? 16 : speed;
-+
-+	if ((ret = pkt_adjust_speed(pd, speed))) {
-+		DPRINTK("pktcdvd: %s couldn't set write speed\n", pd->name);
-+		return -EIO;
-+	}
-+
-+	if ((ret = pkt_perform_opc(pd))) {
-+		DPRINTK("pktcdvd: %s Optimum Power Calibration failed\n", pd->name);
-+	}
-+
-+	return 0;
-+}
-+
-+/*
-+ * called at open time.
-+ */
-+static int pkt_open_dev(struct pktcdvd_device *pd, int write)
-+{
-+	int ret;
-+	long lba;
-+
-+	if (!pd->dev)
-+		return -ENXIO;
-+
-+	pd->bdev = bdget(kdev_t_to_nr(pd->dev));
-+	if (!pd->bdev) {
-+		printk("pktcdvd: can't find cdrom block device\n");
-+		return -ENXIO;
-+	}
-+
-+	if ((ret = blkdev_get(pd->bdev, FMODE_READ, 0, BDEV_FILE))) {
-+		pd->bdev = NULL;
-+		return ret;
-+	}
-+
-+	if ((ret = cdrom_get_last_written(pd->dev, &lba))) {
-+		printk("pktcdvd: cdrom_get_last_written failed\n");
-+		return ret;
-+	}
-+
-+	pkt_sizes[MINOR(pd->pkt_dev)] = lba << 1;
-+
-+	if (write) {
-+		if ((ret = pkt_open_write(pd)))
-+			return ret;
-+		pkt_mark_readonly(pd, 0);
-+	} else {
-+		(void) pkt_adjust_speed(pd, 0xffff);
-+		pkt_mark_readonly(pd, 1);
-+	}
-+
-+	if (write)
-+		printk("pktcdvd: %lukB available on disc\n", lba << 1);
-+
-+	return 0;
-+}
-+
-+/*
-+ * called when the device is closed. makes sure that the device flushes
-+ * the internal cache before we close.
-+ */
-+static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
-+{
-+	atomic_dec(&pd->refcnt);
-+	if (atomic_read(&pd->refcnt) > 0)
-+		return;
-+
-+	fsync_dev(pd->pkt_dev);
-+
-+	if (flush && pkt_flush_cache(pd))
-+		DPRINTK("pktcdvd: %s not flushing cache\n", pd->name);
-+
-+	pkt_set_speed(pd, 0xffff);
-+
-+	if (pd->bdev) {
-+		blkdev_put(pd->bdev, BDEV_FILE);
-+		pd->bdev = NULL;
-+	}
-+}
-+
-+static int pkt_open(struct inode *inode, struct file *file)
-+{
-+	struct pktcdvd_device *pd = NULL;
-+	int ret;
-+
-+	VPRINTK("pktcdvd: entering open\n");
-+
-+	if (MINOR(inode->i_rdev) >= MAX_WRITERS) {
-+		printk("pktcdvd: max %d writers supported\n", MAX_WRITERS);
-+		ret = -ENODEV;
-+		goto out;
-+	}
-+
-+	/*
-+	 * either device is not configured, or pktsetup is old and doesn't
-+	 * use O_CREAT to create device
-+	 */
-+	pd = &pkt_devs[MINOR(inode->i_rdev)];
-+	if (!pd->dev && !(file->f_flags & O_CREAT)) {
-+		VPRINTK("pktcdvd: not configured and O_CREAT not set\n");
-+		ret = -ENXIO;
-+		goto out;
-+	}
-+
-+	atomic_inc(&pd->refcnt);
-+	if (atomic_read(&pd->refcnt) > 1) {
-+		if (file->f_mode & FMODE_WRITE) {
-+			VPRINTK("pktcdvd: busy open for write\n");
-+			ret = -EBUSY;
-+			goto out_dec;
-+		}
-+
-+		/*
-+		 * Not first open, everything is already set up
-+		 */
-+		return 0;
-+	}
-+
-+	if (((file->f_flags & O_ACCMODE) != O_RDONLY) || !(file->f_flags & O_CREAT)) {
-+		if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) {
-+			ret = -EIO;
-+			goto out_dec;
-+		}
-+	}
-+
-+	/*
-+	 * needed here as well, since ext2 (among others) may change
-+	 * the blocksize at mount time
-+	 */
-+	set_blocksize(pd->pkt_dev, CD_FRAMESIZE);
-+	return 0;
-+
-+out_dec:
-+	atomic_dec(&pd->refcnt);
-+	if (atomic_read(&pd->refcnt) == 0) {
-+		if (pd->bdev) {
-+			blkdev_put(pd->bdev, BDEV_FILE);
-+			pd->bdev = NULL;
-+		}
-+	}
-+out:
-+	VPRINTK("pktcdvd: failed open (%d)\n", ret);
-+	return ret;
-+}
-+
-+static int pkt_close(struct inode *inode, struct file *file)
-+{
-+	struct pktcdvd_device *pd = &pkt_devs[MINOR(inode->i_rdev)];
-+	int ret = 0;
-+
-+	if (pd->dev) {
-+		int flush = !test_bit(PACKET_READONLY, &pd->flags);
-+		pkt_release_dev(pd, flush);
-+	}
-+
-+	return ret;
-+}
-+
-+/*
-+ * pktcdvd i/o elevator parts
-+ */
-+static inline int pkt_bh_rq_ordered(struct buffer_head *bh, struct request *rq,
-+				    struct list_head *head)
-+{
-+	struct list_head *next;
-+	struct request *next_rq;
-+
-+	next = rq->queue.next;
-+	if (next == head)
-+		return 0;
-+
-+	next_rq = blkdev_entry_to_request(next);
-+	if (next_rq->rq_dev != rq->rq_dev)
-+		return bh->b_rsector > rq->sector;
-+
-+	if (bh->b_rsector < next_rq->sector && bh->b_rsector > rq->sector)
-+		return 1;
-+
-+	if (next_rq->sector > rq->sector)
-+		return 0;
-+
-+	if (bh->b_rsector > rq->sector || bh->b_rsector < next_rq->sector)
-+		return 1;
-+
-+	return 0;
-+}
-+
-+static int pkt_elevator_merge(request_queue_t *q, struct request **req,
-+			      struct list_head *head,
-+			      struct buffer_head *bh, int rw,
-+			      int max_sectors)
-+{
-+	struct list_head *entry = &q->queue_head;
-+	unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
-+
-+	if (bh->b_reqnext)
-+		BUG();
-+
-+	VPRINTK("pkt_elevator_merge: rw=%d, ms=%d, bh=%lu, dev=%d\n", rw, max_sectors, bh->b_rsector, bh->b_rdev);
-+
-+	while ((entry = entry->prev) != head) {
-+		struct request *__rq = blkdev_entry_to_request(entry);
-+		if (__rq->waiting)
-+			continue;
-+		if (__rq->rq_dev != bh->b_rdev)
-+			continue;
-+		if (!*req && pkt_bh_rq_ordered(bh, __rq, &q->queue_head))
-+			*req = __rq;
-+		if (__rq->cmd != rw)
-+			continue;
-+		if (__rq->nr_sectors + count > max_sectors)
-+			continue;
-+		if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
-+			ret = ELEVATOR_BACK_MERGE;
-+			*req = __rq;
-+			break;
-+		} else if (__rq->sector - count == bh->b_rsector) {
-+			ret = ELEVATOR_FRONT_MERGE;
-+			*req = __rq;
-+			break;
-+		}
-+#if 0 /* makes sense, chance of two matches probably slim */
-+		else if (*req)
-+			break;
-+#endif
-+	}
-+	VPRINTK("*req=%p, ret=%d\n", *req, ret);
-+
-+	return ret;
-+}
-+
-+static int pkt_make_request(request_queue_t *q, int rw, struct buffer_head *bh)
-+{
-+	struct pktcdvd_device *pd;
-+	struct buffer_head *new_bh;
-+
-+	if (MINOR(bh->b_rdev) >= MAX_WRITERS) {
-+		printk("pktcdvd: %s out of range\n", kdevname(bh->b_rdev));
-+		goto end_io;
-+	}
-+
-+	pd = &pkt_devs[MINOR(bh->b_rdev)];
-+	if (!pd->dev) {
-+		printk("pktcdvd: request received for non-active pd\n");
-+		goto end_io;
-+	}
-+
-+	/*
-+	 * quick remap a READ
-+	 */
-+	if (rw == READ || rw == READA) {
-+		down(&pd->cache_sync_mutex);
-+		pkt_flush_writes(pd);
-+		bh->b_rdev = pd->dev;
-+		generic_make_request(rw, bh);
-+		up(&pd->cache_sync_mutex);
-+		return 0;
-+	}
-+
-+	if (!(rw & WRITE))
-+		BUG();
-+
-+	if (test_bit(PACKET_READONLY, &pd->flags)) {
-+		printk("pktcdvd: WRITE for ro device %s (%lu)\n",
-+			pd->name, bh->b_rsector);
-+		goto end_io;
-+	}
-+
-+	VPRINTK("pkt_make_request: bh:%p block:%ld size:%d\n",
-+		bh, bh->b_blocknr, bh->b_size);
-+
-+	if (bh->b_size != CD_FRAMESIZE) {
-+		printk("pktcdvd: wrong bh size\n");
-+		goto end_io;
-+	}
-+
-+	/*
-+	 * This is deadlock safe, since pkt_get_stacked_bh can only
-+	 * fail if there are already buffers in flight for this
-+	 * packet device. When the in-flight buffers finish, we
-+	 * will be woken up and try again.
-+	 */
-+	new_bh = kmem_cache_alloc(bh_cachep, GFP_ATOMIC);
-+	while (!new_bh) {
-+		DECLARE_WAITQUEUE(wait, current);
-+
-+		generic_unplug_device(q);
-+
-+		add_wait_queue(&pd_bh_wait, &wait);
-+		set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+		new_bh = pkt_get_stacked_bh(pd);
-+		if (!new_bh)
-+			schedule();
-+
-+		set_current_state(TASK_RUNNING);
-+		remove_wait_queue(&pd_bh_wait, &wait);
-+	}
-+
-+	new_bh->b_size = bh->b_size;
-+	new_bh->b_list = PKT_BUF_LIST + 1;
-+	new_bh->b_dev = bh->b_dev;
-+	atomic_set(&new_bh->b_count, 1);
-+	new_bh->b_rdev = bh->b_rdev;
-+	new_bh->b_state = bh->b_state;
-+	new_bh->b_page = bh->b_page;
-+	new_bh->b_data = bh->b_data;
-+	new_bh->b_private = bh;
-+	new_bh->b_end_io = pkt_end_io_write_stacked;
-+	new_bh->b_rsector = bh->b_rsector;
-+
-+	return pd->make_request_fn(q, rw, new_bh);
-+
-+end_io:
-+	buffer_IO_error(bh);
-+	return 0;
-+}
-+
-+static void show_requests(request_queue_t *q)
-+{
-+	struct list_head *entry;
-+
-+	spin_lock_irq(&io_request_lock);
-+
-+	list_for_each(entry, &q->queue_head) {
-+		struct request *rq = blkdev_entry_to_request(entry);
-+		int zone = rq->sector & ~127;
-+		int hole;
-+
-+		hole = 0;
-+		if ((rq->sector + rq->nr_sectors - (rq->bhtail->b_size >> 9))
-+		    != rq->bhtail->b_rsector)
-+			hole = 1;
-+
-+		printk("rq: cmd %d, sector %lu (-> %lu), zone %u, hole %d, nr_sectors %lu\n", rq->cmd, rq->sector, rq->sector + rq->nr_sectors - 1, zone, hole, rq->nr_sectors);
-+	}
-+
-+	spin_unlock_irq(&io_request_lock);
-+}
-+
-+static void sysrq_handle_show_requests(int key, struct pt_regs *pt_regs,
-+		struct kbd_struct *kbd, struct tty_struct *tty)
-+{
-+	/*
-+	 * quick hack to show pending requests in /dev/pktcdvd0 queue
-+	 */
-+	queue_proc *qp = blk_dev[PACKET_MAJOR].queue;
-+	if (qp) {
-+		request_queue_t *q = qp(MKDEV(PACKET_MAJOR, 0));
-+		if (q)
-+			show_requests(q);
-+	}
-+}
-+static struct sysrq_key_op sysrq_show_requests_op = {
-+	handler:	sysrq_handle_show_requests,
-+	help_msg:	"showreQuests",
-+	action_msg:	"Show requests",
-+};
-+
-+static void pkt_init_queue(struct pktcdvd_device *pd)
-+{
-+	request_queue_t *q = &pd->cdrw.r_queue;
-+
-+	blk_init_queue(q, pkt_request);
-+	elevator_init(&q->elevator, ELEVATOR_PKTCDVD);
-+	pd->make_request_fn = q->make_request_fn;
-+	blk_queue_make_request(q, pkt_make_request);
-+	blk_queue_headactive(q, 0);
-+	q->front_merge_fn = pkt_front_merge_fn;
-+	q->back_merge_fn = pkt_back_merge_fn;
-+	q->merge_requests_fn = pkt_merge_requests_fn;
-+	q->queuedata = pd;
-+}
-+
-+static int pkt_proc_device(struct pktcdvd_device *pd, char *buf)
-+{
-+	char *b = buf, *msg;
-+	struct list_head *foo;
-+	int i;
-+
-+	b += sprintf(b, "\nWriter %s (%s):\n", pd->name, kdevname(pd->dev));
-+
-+	b += sprintf(b, "\nSettings:\n");
-+	b += sprintf(b, "\tpacket size:\t\t%dkB\n", pd->settings.size / 2);
-+
-+	if (pd->settings.write_type == 0)
-+		msg = "Packet";
-+	else
-+		msg = "Unknown";
-+	b += sprintf(b, "\twrite type:\t\t%s\n", msg);
-+
-+	b += sprintf(b, "\tpacket type:\t\t%s\n", pd->settings.fp ? "Fixed" : "Variable");
-+	b += sprintf(b, "\tlink loss:\t\t%d\n", pd->settings.link_loss);
-+
-+	b += sprintf(b, "\ttrack mode:\t\t%d\n", pd->settings.track_mode);
-+
-+	if (pd->settings.block_mode == PACKET_BLOCK_MODE1)
-+		msg = "Mode 1";
-+	else if (pd->settings.block_mode == PACKET_BLOCK_MODE2)
-+		msg = "Mode 2";
-+	else
-+		msg = "Unknown";
-+	b += sprintf(b, "\tblock mode:\t\t%s\n", msg);
-+
-+	b += sprintf(b, "\nStatistics:\n");
-+	b += sprintf(b, "\tbuffers started:\t%lu\n", pd->stats.bh_s);
-+	b += sprintf(b, "\tbuffers ended:\t\t%lu\n", pd->stats.bh_e);
-+	b += sprintf(b, "\tsectors written:\t%lu\n", pd->stats.secs_w);
-+	b += sprintf(b, "\tsectors read:\t\t%lu\n", pd->stats.secs_r);
-+	b += sprintf(b, "\tbuffer cache hits:\t%lu\n", pd->stats.bh_cache_hits);
-+	b += sprintf(b, "\tpage cache hits:\t%lu\n", pd->stats.page_cache_hits);
-+
-+	b += sprintf(b, "\nMisc:\n");
-+	b += sprintf(b, "\treference count:\t%d\n", atomic_read(&pd->refcnt));
-+	b += sprintf(b, "\tflags:\t\t\t0x%lx\n", pd->flags);
-+	b += sprintf(b, "\twrite speed:\t\t%ukB/s\n", pd->speed * 150);
-+	b += sprintf(b, "\tstart offset:\t\t%lu\n", pd->offset);
-+	b += sprintf(b, "\tmode page offset:\t%u\n", pd->mode_offset);
-+
-+	b += sprintf(b, "\nQueue state:\n");
-+	b += sprintf(b, "\tfree buffers:\t\t%u\n", atomic_read(&pd->cdrw.free_bh));
-+	b += sprintf(b, "\trequest active:\t\t%s\n", pd->rq ? "yes" : "no");
-+	b += sprintf(b, "\twrite rq depth:\t\t%d\n", atomic_read(&pd->wrqcnt));
-+
-+	spin_lock_irq(&io_request_lock);
-+	i = 0;
-+	list_for_each(foo, &pd->cdrw.r_queue.queue_head)
-+		i++;
-+	spin_unlock_irq(&io_request_lock);
-+	b += sprintf(b, "\tqueue requests:\t\t%u\n", i);
-+
-+	return b - buf;
-+}
-+
-+static int pkt_read_proc(char *page, char **start, off_t off, int count,
-+			 int *eof, void *data)
-+{
-+	struct pktcdvd_device *pd = data;
-+	char *buf = page;
-+	int len;
-+
-+	len = pkt_proc_device(pd, buf);
-+	buf += len;
-+
-+	if (len <= off + count)
-+		*eof = 1;
-+
-+	*start = page + off;
-+	len -= off;
-+	if (len > count)
-+		len = count;
-+	if (len < 0)
-+		len = 0;
-+
-+	return len;
-+}
-+
-+static int pkt_new_dev(struct pktcdvd_device *pd, kdev_t dev)
-+{
-+	struct cdrom_device_info *cdi;
-+	request_queue_t *q;
-+	int i;
-+
-+	for (i = 0; i < MAX_WRITERS; i++) {
-+		if (pkt_devs[i].dev == dev) {
-+			printk("pktcdvd: %s already setup\n", kdevname(dev));
-+			return -EBUSY;
-+		}
-+	}
-+
-+	for (i = 0; i < MAX_WRITERS; i++)
-+		if (pd == &pkt_devs[i])
-+			break;
-+	BUG_ON(i == MAX_WRITERS);
-+
-+	cdi = cdrom_find_device(dev);
-+	if (cdi == NULL) {
-+		printk("pktcdvd: %s is not a CD-ROM\n", kdevname(dev));
-+		return -ENXIO;
-+	}
-+
-+	MOD_INC_USE_COUNT;
-+
-+	memset(pd, 0, sizeof(struct pktcdvd_device));
-+	atomic_set(&pd->cdrw.free_bh, 0);
-+
-+	spin_lock_init(&pd->lock);
-+	if (pkt_grow_bhlist(pd, PACKET_MAX_SIZE) < PACKET_MAX_SIZE) {
-+		MOD_DEC_USE_COUNT;
-+		printk("pktcdvd: not enough memory for buffers\n");
-+		return -ENOMEM;
-+	}
-+
-+	pd->stacked_bhcnt = 0;
-+	if (!pkt_grow_stacked_bhlist(pd)) {
-+		MOD_DEC_USE_COUNT;
-+		printk("pktcdvd: not enough memory for buffer heads\n");
-+		return -ENOMEM;
-+	}
-+
-+	set_blocksize(dev, CD_FRAMESIZE);
-+	pd->cdi = cdi;
-+	pd->dev = dev;
-+	pd->bdev = NULL;
-+	pd->pkt_dev = MKDEV(PACKET_MAJOR, i);
-+	sprintf(pd->name, "pktcdvd%d", i);
-+	atomic_set(&pd->refcnt, 0);
-+	atomic_set(&pd->wrqcnt, 0);
-+	init_MUTEX(&pd->cache_sync_mutex);
-+	pd->unflushed_writes = 0;
-+	init_waitqueue_head(&pd->wqueue);
-+	init_completion(&pd->cdrw.thr_compl);
-+
-+	/*
-+	 * store device merge functions (SCSI uses their own to build
-+	 * scatter-gather tables)
-+	 */
-+	q = blk_get_queue(dev);
-+	pkt_init_queue(pd);
-+	pd->cdrw.front_merge_fn = q->front_merge_fn;
-+	pd->cdrw.back_merge_fn = q->back_merge_fn;
-+	pd->cdrw.merge_requests_fn = q->merge_requests_fn;
-+	pd->cdrw.queuedata = q->queuedata;
-+
-+	pd->cdrw.time_to_die = 0;
-+	pd->cdrw.pid = kernel_thread(kcdrwd, pd, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-+	if (pd->cdrw.pid < 0) {
-+		MOD_DEC_USE_COUNT;
-+		printk("pktcdvd: can't start kernel thread\n");
-+		blk_cleanup_queue(&pd->cdrw.r_queue);
-+		pkt_shrink_stacked_bhlist(pd);
-+		pkt_shrink_bhlist(pd, PACKET_MAX_SIZE);
-+		memset(pd, 0, sizeof(*pd));
-+		return -EBUSY;
-+	}
-+
-+	create_proc_read_entry(pd->name, 0, pkt_proc, pkt_read_proc, pd);
-+	DPRINTK("pktcdvd: writer %s sucessfully registered\n", cdi->name);
-+	return 0;
-+}
-+
-+/*
-+ * arg contains file descriptor of CD-ROM device.
-+ */
-+static int pkt_setup_dev(struct pktcdvd_device *pd, unsigned int arg)
-+{
-+	struct inode *inode;
-+	struct file *file;
-+	int ret;
-+
-+	if ((file = fget(arg)) == NULL) {
-+		printk("pktcdvd: bad file descriptor passed\n");
-+		return -EBADF;
-+	}
-+
-+	ret = -EINVAL;
-+	if ((inode = file->f_dentry->d_inode) == NULL) {
-+		printk("pktcdvd: huh? file descriptor contains no inode?\n");
-+		goto out;
-+	}
-+	ret = -ENOTBLK;
-+	if (!S_ISBLK(inode->i_mode)) {
-+		printk("pktcdvd: device is not a block device (duh)\n");
-+		goto out;
-+	}
-+	ret = -EROFS;
-+	if (IS_RDONLY(inode)) {
-+		printk("pktcdvd: Can't write to read-only dev\n");
-+		goto out;
-+	}
-+	if ((ret = pkt_new_dev(pd, inode->i_rdev))) {
-+		printk("pktcdvd: all booked up\n");
-+		goto out;
-+	}
-+
-+	atomic_inc(&pd->refcnt);
-+
-+out:
-+	fput(file);
-+	return ret;
-+}
-+
-+static int pkt_remove_dev(struct pktcdvd_device *pd)
-+{
-+	int ret;
-+
-+	if (pd->cdrw.pid >= 0) {
-+		pd->cdrw.time_to_die = 1;
-+		wmb();
-+		ret = kill_proc(pd->cdrw.pid, SIGKILL, 1);
-+		if (ret) {
-+			printk("pkt_exit: can't kill kernel thread\n");
-+			return ret;
-+		}
-+		wait_for_completion(&pd->cdrw.thr_compl);
-+	}
-+
-+	/*
-+	 * will also invalidate buffers for CD-ROM
-+	 */
-+	invalidate_device(pd->pkt_dev, 1);
-+
-+	pkt_shrink_stacked_bhlist(pd);
-+	if ((ret = pkt_shrink_bhlist(pd, PACKET_MAX_SIZE)) != PACKET_MAX_SIZE)
-+		printk("pktcdvd: leaked %d buffers\n", PACKET_MAX_SIZE - ret);
-+
-+	blk_cleanup_queue(&pd->cdrw.r_queue);
-+	remove_proc_entry(pd->name, pkt_proc);
-+	DPRINTK("pktcdvd: writer %s unregistered\n", pd->cdi->name);
-+	memset(pd, 0, sizeof(struct pktcdvd_device));
-+	MOD_DEC_USE_COUNT;
-+	return 0;
-+}
-+
-+static int pkt_media_change(kdev_t dev)
-+{
-+	struct pktcdvd_device *pd = pkt_find_dev(dev);
-+	if (!pd)
-+		return 0;
-+	return cdrom_media_changed(pd->dev);
-+}
-+
-+static int pkt_ioctl(struct inode *inode, struct file *file,
-+		     unsigned int cmd, unsigned long arg)
-+{
-+	struct pktcdvd_device *pd = &pkt_devs[MINOR(inode->i_rdev)];
-+
-+	VPRINTK("pkt_ioctl: cmd %d, dev %x\n", cmd, inode->i_rdev);
-+
-+	if ((cmd != PACKET_SETUP_DEV) && !pd->dev) {
-+		DPRINTK("pktcdvd: dev not setup\n");
-+		return -ENXIO;
-+	}
-+
-+	switch (cmd) {
-+	case PACKET_GET_STATS:
-+		if (copy_to_user(&arg, &pd->stats, sizeof(struct packet_stats)))
-+			return -EFAULT;
-+		break;
-+
-+	case PACKET_SETUP_DEV:
-+		if (!capable(CAP_SYS_ADMIN))
-+			return -EPERM;
-+		if (pd->dev) {
-+			printk("pktcdvd: dev already setup\n");
-+			return -EBUSY;
-+		}
-+		return pkt_setup_dev(pd, arg);
-+
-+	case PACKET_TEARDOWN_DEV:
-+		if (!capable(CAP_SYS_ADMIN))
-+			return -EPERM;
-+		if (atomic_read(&pd->refcnt) != 1)
-+			return -EBUSY;
-+		return pkt_remove_dev(pd);
-+
-+	case BLKGETSIZE:
-+		return put_user(blk_size[PACKET_MAJOR][MINOR(inode->i_rdev)] << 1, (unsigned long *)arg);
-+
-+	case BLKGETSIZE64:
-+		return put_user((u64)blk_size[PACKET_MAJOR][MINOR(inode->i_rdev)] << 10,
-+				(u64 *)arg);
-+
-+	case BLKROSET:
-+		if (capable(CAP_SYS_ADMIN))
-+			set_bit(PACKET_READONLY, &pd->flags);
-+	case BLKROGET:
-+	case BLKSSZGET:
-+	case BLKRASET:
-+	case BLKRAGET:
-+	case BLKFLSBUF:
-+		if (!pd->bdev)
-+			return -ENXIO;
-+		return blk_ioctl(inode->i_rdev, cmd, arg);
-+
-+	/*
-+	 * forward selected CDROM ioctls to CD-ROM, for UDF
-+	 */
-+	case CDROMMULTISESSION:
-+	case CDROMREADTOCENTRY:
-+	case CDROM_LAST_WRITTEN:
-+	case CDROM_SEND_PACKET:
-+	case SCSI_IOCTL_SEND_COMMAND:
-+		if (!pd->bdev)
-+			return -ENXIO;
-+		return ioctl_by_bdev(pd->bdev, cmd, arg);
-+
-+	default:
-+		printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
-+		return -ENOTTY;
-+	}
-+
-+	return 0;
-+}
-+
-+static struct block_device_operations pktcdvd_ops = {
-+	owner:			THIS_MODULE,
-+	open:			pkt_open,
-+	release:		pkt_close,
-+	ioctl:			pkt_ioctl,
-+	check_media_change:	pkt_media_change,
-+};
-+
-+int pkt_init(void)
-+{
-+	int i;
-+
-+	devfs_register(NULL, "pktcdvd", DEVFS_FL_DEFAULT, PACKET_MAJOR, 0,
-+		       S_IFBLK | S_IRUSR | S_IWUSR, &pktcdvd_ops, NULL);
-+	if (devfs_register_blkdev(PACKET_MAJOR, "pktcdvd", &pktcdvd_ops)) {
-+		printk("unable to register pktcdvd device\n");
-+		return -EIO;
-+	}
-+
-+	pkt_sizes = kmalloc(MAX_WRITERS * sizeof(int), GFP_KERNEL);
-+	if (pkt_sizes == NULL)
-+		goto err;
-+
-+	pkt_blksize = kmalloc(MAX_WRITERS * sizeof(int), GFP_KERNEL);
-+	if (pkt_blksize == NULL)
-+		goto err;
-+
-+	pkt_readahead = kmalloc(MAX_WRITERS * sizeof(int), GFP_KERNEL);
-+	if (pkt_readahead == NULL)
-+		goto err;
-+
-+	pkt_devs = kmalloc(MAX_WRITERS * sizeof(struct pktcdvd_device), GFP_KERNEL);
-+	if (pkt_devs == NULL)
-+		goto err;
-+
-+	memset(pkt_devs, 0, MAX_WRITERS * sizeof(struct pktcdvd_device));
-+	memset(pkt_sizes, 0, MAX_WRITERS * sizeof(int));
-+	memset(pkt_blksize, 0, MAX_WRITERS * sizeof(int));
-+
-+	for (i = 0; i < MAX_WRITERS; i++)
-+		pkt_readahead[i] = vm_max_readahead;
-+
-+	blk_size[PACKET_MAJOR] = pkt_sizes;
-+	blksize_size[PACKET_MAJOR] = pkt_blksize;
-+	max_readahead[PACKET_MAJOR] = pkt_readahead;
-+	read_ahead[PACKET_MAJOR] = 128;
-+	set_blocksize(MKDEV(PACKET_MAJOR, 0), CD_FRAMESIZE);
-+
-+	blk_dev[PACKET_MAJOR].queue = pkt_get_queue;
-+
-+	pkt_proc = proc_mkdir("pktcdvd", proc_root_driver);
-+
-+	register_sysrq_key('q', &sysrq_show_requests_op);
-+
-+	DPRINTK("pktcdvd: %s\n", VERSION_CODE);
-+	return 0;
-+
-+err:
-+	printk("pktcdvd: out of memory\n");
-+	devfs_unregister(devfs_find_handle(NULL, "pktcdvd", 0, 0,
-+		 	 DEVFS_SPECIAL_BLK, 0));
-+	devfs_unregister_blkdev(PACKET_MAJOR, "pktcdvd");
-+	kfree(pkt_devs);
-+	kfree(pkt_sizes);
-+	kfree(pkt_blksize);
-+	kfree(pkt_readahead);
-+	return -ENOMEM;
-+}
-+
-+void pkt_exit(void)
-+{
-+	unregister_sysrq_key('q', &sysrq_show_requests_op);
-+
-+	devfs_unregister(devfs_find_handle(NULL, "pktcdvd", 0, 0,
-+		 	 DEVFS_SPECIAL_BLK, 0));
-+	devfs_unregister_blkdev(PACKET_MAJOR, "pktcdvd");
-+	blk_dev[PACKET_MAJOR].queue = NULL;
-+
-+	remove_proc_entry("pktcdvd", proc_root_driver);
-+	kfree(pkt_sizes);
-+	kfree(pkt_blksize);
-+	kfree(pkt_devs);
-+	kfree(pkt_readahead);
-+}
-+
-+MODULE_DESCRIPTION("Packet writing layer for CD/DVD drives");
-+MODULE_AUTHOR("Jens Axboe <axboe at suse.de>");
-+MODULE_LICENSE("GPL");
-+
-+module_init(pkt_init);
-+module_exit(pkt_exit);
-diff -u -r -N ../../linus/2.4/linux/drivers/cdrom/Makefile linux/drivers/cdrom/Makefile
---- ../../linus/2.4/linux/drivers/cdrom/Makefile	2003-08-03 23:22:01.000000000 +0200
-+++ linux/drivers/cdrom/Makefile	2003-08-03 23:30:14.000000000 +0200
-@@ -27,6 +27,7 @@
- obj-$(CONFIG_BLK_DEV_IDECD)	+=              cdrom.o
- obj-$(CONFIG_BLK_DEV_SR)	+=              cdrom.o
- obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
-+obj-$(CONFIG_CDROM_PKTCDVD)	+=		cdrom.o
- 
- obj-$(CONFIG_AZTCD)		+= aztcd.o
- obj-$(CONFIG_CDU31A)		+= cdu31a.o     cdrom.o
-diff -u -r -N ../../linus/2.4/linux/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
---- ../../linus/2.4/linux/drivers/ide/ide-cd.c	2003-08-23 21:25:25.000000000 +0200
-+++ linux/drivers/ide/ide-cd.c	2003-08-23 22:26:42.000000000 +0200
-@@ -292,9 +292,11 @@
-  *			  correctly reporting tray status -- from
-  *			  Michael D Johnson <johnsom at orst.edu>
-  *
-+ * 4.99			- Added write support for packet writing.
-+ *
-  *************************************************************************/
-  
--#define IDECD_VERSION "4.59-ac1"
-+#define IDECD_VERSION "4.99"
- 
- #include <linux/config.h>
- #include <linux/module.h>
-@@ -526,7 +528,7 @@
- 
- 	memset(pc, 0, sizeof(struct packet_command));
- 	pc->c[0] = GPCMD_REQUEST_SENSE;
--	pc->c[4] = pc->buflen = 18;
-+	pc->c[4] = pc->buflen = 14;
- 	pc->buffer = (char *) sense;
- 	pc->sense = (struct request_sense *) failed_command;
- 
-@@ -774,7 +776,7 @@
- 			cdrom_saw_media_change (drive);
- 
- 			/* Fail the request. */
--			printk ("%s: tray open\n", drive->name);
-+			/* printk ("%s: tray open\n", drive->name); */
- 			do_end_request = 1;
- 		} else if (sense_key == UNIT_ATTENTION) {
- 			/* Media change. */
-@@ -1351,6 +1353,8 @@
- 	 * partitions not really working, but better check anyway...
- 	 */
- 	if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) {
-+		if (rq->cmd == WRITE)
-+			printk("merged write\n");
- 		rq->nr_sectors += nxt->nr_sectors;
- 		rq->hard_nr_sectors += nxt->nr_sectors;
- 		rq->bhtail->b_reqnext = nxt->bh;
-@@ -2657,6 +2661,12 @@
- static
- void ide_cdrom_release_real (struct cdrom_device_info *cdi)
- {
-+	struct cdrom_generic_command cgc;
-+
-+	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
-+	cgc.cmd[0] = GPCMD_FLUSH_CACHE;
-+	cgc.quiet = 1;
-+	(void) ide_cdrom_packet(cdi, &cgc);
- }
- 
- 
-@@ -2844,15 +2854,10 @@
- 		printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
- 	printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
- 
--	if (CDROM_CONFIG_FLAGS(drive)->dvd_r|CDROM_CONFIG_FLAGS(drive)->dvd_ram)
--        	printk(" DVD%s%s", 
--        	(CDROM_CONFIG_FLAGS(drive)->dvd_r)? "-R" : "", 
--        	(CDROM_CONFIG_FLAGS(drive)->dvd_ram)? "-RAM" : "");
--
--        if (CDROM_CONFIG_FLAGS(drive)->cd_r|CDROM_CONFIG_FLAGS(drive)->cd_rw) 
--        	printk(" CD%s%s", 
--        	(CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", 
--        	(CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
-+	if (CDROM_CONFIG_FLAGS(drive)->dvd_r || CDROM_CONFIG_FLAGS(drive)->dvd_ram)
-+		printk (" DVD-R%s", (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : "");
-+	if (CDROM_CONFIG_FLAGS(drive)->cd_r ||CDROM_CONFIG_FLAGS(drive)->cd_rw)
-+		printk (" CD-R%s", (CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
- 
-         if (CDROM_CONFIG_FLAGS(drive)->is_changer) 
-         	printk(" changer w/%d slots", nslots);
-@@ -2875,7 +2880,7 @@
- 	int major = HWIF(drive)->major;
- 	int minor = drive->select.b.unit << PARTN_BITS;
- 
--	ide_add_setting(drive,	"breada_readahead",	SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
-+	ide_add_setting(drive,	"breada_readahead",	SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 1024, &read_ahead[major], NULL);
- 	ide_add_setting(drive,	"file_readahead",	SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor],	NULL);
- 	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
- 	ide_add_setting(drive,	"dsc_overlap",		SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1,	1, &drive->dsc_overlap, NULL);
-@@ -2892,7 +2897,7 @@
- 	/*
- 	 * default to read-only always and fix latter at the bottom
- 	 */
--	set_device_ro(MKDEV(HWIF(drive)->major, minor), 1);
-+	set_device_ro(MKDEV(HWIF(drive)->major, minor), 0);
- 	set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
- 
- 	drive->special.all	= 0;
-diff -u -r -N ../../linus/2.4/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
---- ../../linus/2.4/linux/drivers/scsi/Config.in	2003-08-23 21:25:26.000000000 +0200
-+++ linux/drivers/scsi/Config.in	2003-08-23 22:26:59.000000000 +0200
-@@ -20,10 +20,6 @@
- 
- comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
- 
--#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
--   bool '  Enable extra checks in new queueing code' CONFIG_SCSI_DEBUG_QUEUES
--#fi
--
- bool '  Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
-   
- bool '  Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
-diff -u -r -N ../../linus/2.4/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c
---- ../../linus/2.4/linux/drivers/scsi/scsi_merge.c	2003-08-03 23:22:55.000000000 +0200
-+++ linux/drivers/scsi/scsi_merge.c	2003-08-03 23:31:05.000000000 +0200
-@@ -77,11 +77,6 @@
-  */
- #define DMA_SEGMENT_SIZE_LIMITED
- 
--#ifdef CONFIG_SCSI_DEBUG_QUEUES
--/*
-- * Enable a bunch of additional consistency checking.   Turn this off
-- * if you are benchmarking.
-- */
- static int dump_stats(struct request *req,
- 		      int use_clustering,
- 		      int dma_host,
-@@ -106,22 +101,6 @@
- 	panic("Ththththaats all folks.  Too dangerous to continue.\n");
- }
- 
--
--/*
-- * Simple sanity check that we will use for the first go around
-- * in order to ensure that we are doing the counting correctly.
-- * This can be removed for optimization.
-- */
--#define SANITY_CHECK(req, _CLUSTER, _DMA)				\
--    if( req->nr_segments != __count_segments(req, _CLUSTER, _DMA, NULL) )	\
--    {									\
--	printk("Incorrect segment count at 0x%p", current_text_addr());	\
--	dump_stats(req, _CLUSTER, _DMA, __count_segments(req, _CLUSTER, _DMA, NULL)); \
--    }
--#else
--#define SANITY_CHECK(req, _CLUSTER, _DMA)
--#endif
--
- static void dma_exhausted(Scsi_Cmnd * SCpnt, int i)
- {
- 	int jj;
-@@ -537,7 +516,6 @@
- 		     int max_segments)					\
- {									\
-     int ret;								\
--    SANITY_CHECK(req, _CLUSTER, _DMA);					\
-     ret =  __scsi_ ## _BACK_FRONT ## _merge_fn(q,			\
- 					       req,			\
- 					       bh,			\
-@@ -747,7 +725,6 @@
- 		     int max_segments)			\
- {							\
-     int ret;						\
--    SANITY_CHECK(req, _CLUSTER, _DMA);			\
-     ret =  __scsi_merge_requests_fn(q, req, next, max_segments, _CLUSTER, _DMA); \
-     return ret;						\
- }
-@@ -810,11 +787,7 @@
- 	/*
- 	 * First we need to know how many scatter gather segments are needed.
- 	 */
--	if (!sg_count_valid) {
--		count = __count_segments(req, use_clustering, dma_host, NULL);
--	} else {
--		count = req->nr_segments;
--	}
-+	count = __count_segments(req, use_clustering, dma_host, NULL);
- 
- 	/*
- 	 * If the dma pool is nearly empty, then queue a minimal request
-@@ -956,9 +929,7 @@
- 	 */
- 	if (count != SCpnt->use_sg) {
- 		printk("Incorrect number of segments after building list\n");
--#ifdef CONFIG_SCSI_DEBUG_QUEUES
- 		dump_stats(req, use_clustering, dma_host, count);
--#endif
- 	}
- 	if (!dma_host) {
- 		return 1;
-diff -u -r -N ../../linus/2.4/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
---- ../../linus/2.4/linux/drivers/scsi/sr.c	2003-08-03 23:22:55.000000000 +0200
-+++ linux/drivers/scsi/sr.c	2003-08-03 23:31:05.000000000 +0200
-@@ -28,12 +28,16 @@
-  *       Modified by Jens Axboe <axboe at suse.de> - support DVD-RAM
-  *	 transparently and loose the GHOST hack
-  *
-+ *          Modified by Jens Axboe <axboe at suse.de> - support packet writing
-+ *          through generic packet layer.
-+ *
-  *	 Modified by Arnaldo Carvalho de Melo <acme at conectiva.com.br>
-  *	 check resource allocation in sr_init and some cleanups
-  *
-  */
- 
- #include <linux/module.h>
-+#include <linux/config.h>
- 
- #include <linux/fs.h>
- #include <linux/kernel.h>
-@@ -719,7 +723,7 @@
- 	cmd[2] = 0x2a;
- 	cmd[4] = 128;
- 	cmd[3] = cmd[5] = 0;
--	rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL);
-+	rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL, SR_TIMEOUT);
- 
- 	if (rc) {
- 		/* failed, drive doesn't have capabilities mode page */
-@@ -751,16 +755,13 @@
- 	if ((buffer[n + 2] & 0x8) == 0)
- 		/* not a DVD drive */
- 		scsi_CDs[i].cdi.mask |= CDC_DVD;
--	if ((buffer[n + 3] & 0x20) == 0) {
-+	if ((buffer[n + 3] & 0x20) == 0)
- 		/* can't write DVD-RAM media */
- 		scsi_CDs[i].cdi.mask |= CDC_DVD_RAM;
--	} else {
--		scsi_CDs[i].device->writeable = 1;
--	}
- 	if ((buffer[n + 3] & 0x10) == 0)
- 		/* can't write DVD-R media */
- 		scsi_CDs[i].cdi.mask |= CDC_DVD_R;
--	if ((buffer[n + 3] & 0x2) == 0)
-+	if ((buffer[n + 3] & 0x02) == 0)
- 		/* can't write CD-RW media */
- 		scsi_CDs[i].cdi.mask |= CDC_CD_RW;
- 	if ((buffer[n + 3] & 0x1) == 0)
-@@ -780,6 +781,10 @@
- 	/*else    I don't think it can close its tray
- 	   scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */
- 
-+	if (~scsi_CDs[i].cdi.mask & (CDC_DVD_RAM | CDC_CD_RW))
-+		/* can write to DVD-RAM or CD-RW */
-+		scsi_CDs[i].device->writeable = 1;
-+
- 	scsi_free(buffer, 512);
- }
- 
-@@ -795,7 +800,10 @@
- 	if (device->scsi_level <= SCSI_2)
- 		cgc->cmd[1] |= device->lun << 5;
- 
--	cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
-+	if (cgc->timeout <= 0)
-+		cgc->timeout = 5 * HZ;
-+
-+	cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense, cgc->timeout);
- 
- 	return cgc->stat;
- }
-diff -u -r -N ../../linus/2.4/linux/drivers/scsi/sr.h linux/drivers/scsi/sr.h
---- ../../linus/2.4/linux/drivers/scsi/sr.h	2003-08-03 23:22:55.000000000 +0200
-+++ linux/drivers/scsi/sr.h	2003-08-03 23:31:05.000000000 +0200
-@@ -36,7 +36,7 @@
- 
- extern Scsi_CD *scsi_CDs;
- 
--int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int, struct request_sense *);
-+int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int, struct request_sense *, int);
- 
- int sr_lock_door(struct cdrom_device_info *, int);
- int sr_tray_move(struct cdrom_device_info *, int);
-diff -u -r -N ../../linus/2.4/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
---- ../../linus/2.4/linux/drivers/scsi/sr_ioctl.c	2003-08-03 23:22:55.000000000 +0200
-+++ linux/drivers/scsi/sr_ioctl.c	2003-08-03 23:31:05.000000000 +0200
-@@ -68,14 +68,14 @@
- 	sr_cmd[6] = trk1_te.cdte_addr.msf.minute;
- 	sr_cmd[7] = trk1_te.cdte_addr.msf.second;
- 	sr_cmd[8] = trk1_te.cdte_addr.msf.frame;
--	return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
-+	return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, IOCTL_TIMEOUT);
- }
- 
- /* We do our own retries because we want to know what the specific
-    error code is.  Normally the UNIT_ATTENTION code will automatically
-    clear after one error */
- 
--int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense)
-+int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense, int timeout)
- {
- 	Scsi_Request *SRpnt;
- 	Scsi_Device *SDev;
-@@ -109,7 +109,7 @@
- 
- 
- 	scsi_wait_req(SRpnt, (void *) sr_cmd, (void *) buffer, buflength,
--		      IOCTL_TIMEOUT, IOCTL_RETRIES);
-+		      timeout, IOCTL_RETRIES);
- 
- 	req = &SRpnt->sr_request;
- 	if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) {
-@@ -196,7 +196,7 @@
- 	sr_cmd[1] = (scsi_CDs[minor].device->scsi_level <= SCSI_2) ?
- 	            ((scsi_CDs[minor].device->lun) << 5) : 0;
- 	sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
--	return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL);
-+	return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL, IOCTL_TIMEOUT);
- }
- 
- int sr_tray_move(struct cdrom_device_info *cdi, int pos)
-@@ -209,7 +209,7 @@
- 	sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
- 	sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
- 
--	return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
-+	return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, IOCTL_TIMEOUT);
- }
- 
- int sr_lock_door(struct cdrom_device_info *cdi, int lock)
-@@ -287,7 +287,7 @@
- 	sr_cmd[8] = 24;
- 	sr_cmd[9] = 0;
- 
--	result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
-+	result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL, IOCTL_TIMEOUT);
- 
- 	memcpy(mcn->medium_catalog_number, buffer + 9, 13);
- 	mcn->medium_catalog_number[13] = 0;
-@@ -317,7 +317,7 @@
- 	sr_cmd[2] = (speed >> 8) & 0xff;	/* MSB for speed (in kbytes/sec) */
- 	sr_cmd[3] = speed & 0xff;	/* LSB */
- 
--	if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
-+	if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, IOCTL_TIMEOUT))
- 		return -EIO;
- 	return 0;
- }
-@@ -347,7 +347,7 @@
- 			sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
- 			sr_cmd[8] = 12;		/* LSB of length */
- 
--			result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
-+			result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL, IOCTL_TIMEOUT);
- 
- 			tochdr->cdth_trk0 = buffer[2];
- 			tochdr->cdth_trk1 = buffer[3];
-@@ -367,7 +367,7 @@
- 			sr_cmd[6] = tocentry->cdte_track;
- 			sr_cmd[8] = 12;		/* LSB of length */
- 
--			result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL);
-+			result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL, IOCTL_TIMEOUT);
- 
- 			tocentry->cdte_ctrl = buffer[5] & 0xf;
- 			tocentry->cdte_adr = buffer[5] >> 4;
-@@ -394,7 +394,7 @@
- 		sr_cmd[7] = ti->cdti_trk1;
- 		sr_cmd[8] = ti->cdti_ind1;
- 
--		result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
-+		result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, IOCTL_TIMEOUT);
- 		if (result == -EDRIVE_CANT_DO_THIS)
- 			result = sr_fake_playtrkind(cdi, ti);
- 
-@@ -460,7 +460,7 @@
- 		cmd[9] = 0x10;
- 		break;
- 	}
--	return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
-+	return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL, IOCTL_TIMEOUT);
- }
- 
- /*
-@@ -499,7 +499,7 @@
- 	cmd[4] = (unsigned char) (lba >> 8) & 0xff;
- 	cmd[5] = (unsigned char) lba & 0xff;
- 	cmd[8] = 1;
--	rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
-+	rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL, IOCTL_TIMEOUT);
- 
- 	return rc;
- }
-diff -u -r -N ../../linus/2.4/linux/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c
---- ../../linus/2.4/linux/drivers/scsi/sr_vendor.c	2003-08-03 23:22:55.000000000 +0200
-+++ linux/drivers/scsi/sr_vendor.c	2003-08-03 23:31:05.000000000 +0200
-@@ -60,6 +60,8 @@
- 
- #define VENDOR_ID (scsi_CDs[minor].vendor)
- 
-+#define VENDOR_TIMEOUT	30*HZ
-+
- void sr_vendor_init(int minor)
- {
- #ifndef CONFIG_BLK_DEV_SR_VENDOR
-@@ -134,7 +136,7 @@
- 	modesel->density = density;
- 	modesel->block_length_med = (blocklength >> 8) & 0xff;
- 	modesel->block_length_lo = blocklength & 0xff;
--	if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) {
-+	if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL, VENDOR_TIMEOUT))) {
- 		scsi_CDs[minor].device->sector_size = blocklength;
- 	}
- #ifdef DEBUG
-@@ -179,7 +181,7 @@
- 		         (scsi_CDs[minor].device->lun << 5) : 0;
- 		cmd[8] = 12;
- 		cmd[9] = 0x40;
--		rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
-+		rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL, VENDOR_TIMEOUT);
- 		if (rc != 0)
- 			break;
- 		if ((buffer[0] << 8) + buffer[1] < 0x0a) {
-@@ -205,7 +207,7 @@
- 			         (scsi_CDs[minor].device->lun << 5) : 0;
- 			cmd[1] |= 0x03;
- 			cmd[2] = 0xb0;
--			rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL);
-+			rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL, VENDOR_TIMEOUT);
- 			if (rc != 0)
- 				break;
- 			if (buffer[14] != 0 && buffer[14] != 0xb0) {
-@@ -231,7 +233,7 @@
- 			cmd[1] = (scsi_CDs[minor].device->scsi_level <= SCSI_2) ?
- 			         (scsi_CDs[minor].device->lun << 5) : 0;
- 			cmd[1] |= 0x03;
--			rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL);
-+			rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL, VENDOR_TIMEOUT);
- 			if (rc == -EINVAL) {
- 				printk(KERN_INFO "sr%d: Hmm, seems the drive "
- 				       "doesn't support multisession CD's\n", minor);
-@@ -257,7 +259,7 @@
- 		         (scsi_CDs[minor].device->lun << 5) : 0;
- 		cmd[8] = 0x04;
- 		cmd[9] = 0x40;
--		rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL);
-+		rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL, VENDOR_TIMEOUT);
- 		if (rc != 0) {
- 			break;
- 		}
-@@ -272,7 +274,7 @@
- 		cmd[6] = rc & 0x7f;	/* number of last session */
- 		cmd[8] = 0x0c;
- 		cmd[9] = 0x40;
--		rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
-+		rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL, VENDOR_TIMEOUT);
- 		if (rc != 0) {
- 			break;
- 		}
-diff -u -r -N ../../linus/2.4/linux/fs/udf/balloc.c linux/fs/udf/balloc.c
---- ../../linus/2.4/linux/fs/udf/balloc.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/balloc.c	2003-08-03 23:31:41.000000000 +0200
-@@ -144,7 +144,11 @@
- }
- 
- static void udf_bitmap_free_blocks(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	struct udf_bitmap *bitmap, lb_addr bloc, uint32_t offset, uint32_t count)
- {
- 	struct buffer_head * bh = NULL;
-@@ -195,7 +199,11 @@
- 		else
- 		{
- 			if (inode)
-+#ifndef OLD_QUOTA
- 				DQUOT_FREE_BLOCK(inode, 1);
-+#else
-+				DQUOT_FREE_BLOCK(sb, inode, 1);
-+#endif
- 			if (UDF_SB_LVIDBH(sb))
- 			{
- 				UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
-@@ -219,7 +227,11 @@
- }
- 
- static int udf_bitmap_prealloc_blocks(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	struct udf_bitmap *bitmap, uint16_t partition, uint32_t first_block,
- 	uint32_t block_count)
- {
-@@ -254,12 +266,20 @@
- 	{
- 		if (!udf_test_bit(bit, bh->b_data))
- 			goto out;
-+#ifndef OLD_QUOTA
- 		else if (DQUOT_PREALLOC_BLOCK(inode, 1))
-+#else
-+		else if (DQUOT_PREALLOC_BLOCK(sb, inode, 1))
-+#endif
- 			goto out;
- 		else if (!udf_clear_bit(bit, bh->b_data))
- 		{
- 			udf_debug("bit already cleared for block %d\n", bit);
-+#ifndef OLD_QUOTA
- 			DQUOT_FREE_BLOCK(inode, 1);
-+#else
-+			DQUOT_FREE_BLOCK(sb, inode, 1);
-+#endif
- 			goto out;
- 		}
- 		block_count --;
-@@ -283,7 +303,11 @@
- }
- 
- static int udf_bitmap_new_block(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	struct udf_bitmap *bitmap, uint16_t partition, uint32_t goal, int *err)
- {
- 	int newbit, bit=0, block, block_group, group_start;
-@@ -387,7 +411,11 @@
- 	/*
- 	 * Check quota for allocation of this block.
- 	 */
-+#ifndef OLD_QUOTA
- 	if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
-+#else
-+	if (inode && DQUOT_ALLOC_BLOCK(sb, inode, 1))
-+#endif
- 	{
- 		unlock_super(sb);
- 		*err = -EDQUOT;
-@@ -423,7 +451,11 @@
- }
- 
- static void udf_table_free_blocks(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	struct inode * table, lb_addr bloc, uint32_t offset, uint32_t count)
- {
- 	uint32_t start, end;
-@@ -446,7 +478,11 @@
- 	/* We do this up front - There are some error conditions that could occure,
- 	   but.. oh well */
- 	if (inode)
-+#ifndef OLD_QUOTA
- 		DQUOT_FREE_BLOCK(inode, count);
-+#else
-+		DQUOT_FREE_BLOCK(sb, inode, count);
-+#endif
- 	if (UDF_SB_LVIDBH(sb))
- 	{
- 		UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
-@@ -461,8 +497,7 @@
- 	elen = 0;
- 	obloc = nbloc = UDF_I_LOCATION(table);
- 
--	obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0));
--	atomic_inc(&nbh->b_count);
-+	obh = nbh = NULL;
- 
- 	while (count && (etype =
- 		udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
-@@ -506,7 +541,7 @@
- 			udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
- 		}
- 
--		if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
-+		if (nbh != obh)
- 		{
- 			i = -1;
- 			obloc = nbloc;
-@@ -580,7 +615,10 @@
- 			{
- 				loffset = nextoffset;
- 				aed->lengthAllocDescs = cpu_to_le32(adsize);
--				sptr = (obh)->b_data + nextoffset - adsize;
-+				if (obh)
-+					sptr = UDF_I_DATA(inode) + nextoffset -  udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;
-+				else
-+					sptr = obh->b_data + nextoffset - adsize;
- 				dptr = nbh->b_data + sizeof(struct allocExtDesc);
- 				memcpy(dptr, sptr, adsize);
- 				nextoffset = sizeof(struct allocExtDesc) + adsize;
-@@ -591,8 +629,8 @@
- 				aed->lengthAllocDescs = cpu_to_le32(0);
- 				sptr = (obh)->b_data + nextoffset;
- 				nextoffset = sizeof(struct allocExtDesc);
--	
--				if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr)))
-+
-+				if (obh)
- 				{
- 					aed = (struct allocExtDesc *)(obh)->b_data;
- 					aed->lengthAllocDescs =
-@@ -631,15 +669,20 @@
- 					break;
- 				}
- 			}
--			udf_update_tag(obh->b_data, loffset);
--			mark_buffer_dirty(obh);
-+			if (obh)
-+			{
-+				udf_update_tag(obh->b_data, loffset);
-+				mark_buffer_dirty(obh);
-+			}
-+			else
-+				mark_inode_dirty(table);
- 		}
- 
- 		if (elen) /* It's possible that stealing the block emptied the extent */
- 		{
- 			udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
- 
--			if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr)))
-+			if (!nbh)
- 			{
- 				UDF_I_LENALLOC(table) += adsize;
- 				mark_inode_dirty(table);
-@@ -665,7 +708,11 @@
- }
- 
- static int udf_table_prealloc_blocks(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	struct inode *table, uint16_t partition, uint32_t first_block,
- 	uint32_t block_count)
- {
-@@ -690,7 +737,7 @@
- 	extoffset = sizeof(struct unallocSpaceEntry);
- 	bloc = UDF_I_LOCATION(table);
- 
--	bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
-+	bh = NULL;
- 	eloc.logicalBlockNum = 0xFFFFFFFF;
- 
- 	while (first_block != eloc.logicalBlockNum && (etype =
-@@ -706,7 +753,11 @@
- 		extoffset -= adsize;
- 
- 		alloc_count = (elen >> sb->s_blocksize_bits);
-+#ifndef OLD_QUOTA
- 		if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count))
-+#else
-+		if (inode && DQUOT_PREALLOC_BLOCK(sb, inode, alloc_count > block_count ? block_count : alloc_count))
-+#endif
- 			alloc_count = 0;
- 		else if (alloc_count > block_count)
- 		{
-@@ -735,7 +786,11 @@
- }
- 
- static int udf_table_new_block(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	struct inode *table, uint16_t partition, uint32_t goal, int *err)
- {
- 	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
-@@ -768,8 +823,7 @@
- 	extoffset = sizeof(struct unallocSpaceEntry);
- 	bloc = UDF_I_LOCATION(table);
- 
--	goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
--	atomic_inc(&goal_bh->b_count);
-+	goal_bh = bh = NULL;
- 
- 	while (spread && (etype =
- 		udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
-@@ -819,7 +873,11 @@
- 	goal_eloc.logicalBlockNum ++;
- 	goal_elen -= sb->s_blocksize;
- 
-+#ifndef OLD_QUOTA
- 	if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
-+#else
-+	if (inode && DQUOT_ALLOC_BLOCK(sb, inode, 1))
-+#endif
- 	{
- 		udf_release_data(goal_bh);
- 		unlock_super(sb);
-@@ -847,7 +905,11 @@
- }
- 
- inline void udf_free_blocks(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	lb_addr bloc, uint32_t offset, uint32_t count)
- {
- 	uint16_t partition = bloc.partitionReferenceNum;
-@@ -881,7 +943,11 @@
- }
- 
- inline int udf_prealloc_blocks(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	uint16_t partition, uint32_t first_block, uint32_t block_count)
- {
- 	if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
-@@ -913,7 +979,11 @@
- }
- 
- inline int udf_new_block(struct super_block * sb,
-+#ifndef OLD_QUOTA
- 	struct inode * inode,
-+#else
-+	const struct inode * inode,
-+#endif
- 	uint16_t partition, uint32_t goal, int *err)
- {
- 	if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)
-diff -u -r -N ../../linus/2.4/linux/fs/udf/dir.c linux/fs/udf/dir.c
---- ../../linus/2.4/linux/fs/udf/dir.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/dir.c	2003-08-03 23:31:41.000000000 +0200
-@@ -104,7 +104,7 @@
- 	int block, iblock;
- 	loff_t nf_pos = filp->f_pos - 1;
- 	int flen;
--	char fname[255];
-+	char fname[UDF_NAME_LEN];
- 	char *nameptr;
- 	uint16_t liu;
- 	uint8_t lfi;
-@@ -122,7 +122,9 @@
- 		nf_pos = (udf_ext0_offset(dir) >> 2);
- 
- 	fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
--	if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
-+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-+		fibh.sbh = fibh.ebh = NULL;
-+	else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
- 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
- 	{
- 		offset >>= dir->i_sb->s_blocksize_bits;
-@@ -136,6 +138,34 @@
- 		}
- 		else
- 			offset = 0;
-+
-+		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
-+		{
-+			udf_release_data(bh);
-+			return -EIO;
-+		}
-+	
-+		if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
-+		{
-+			i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
-+			if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
-+				i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
-+			for (num=0; i>0; i--)
-+			{
-+				block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
-+				tmp = udf_tgetblk(dir->i_sb, block);
-+				if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
-+					bha[num++] = tmp;
-+				else
-+					brelse(tmp);
-+			}
-+			if (num)
-+			{
-+				ll_rw_block(READA, num, bha);
-+				for (i=0; i<num; i++)
-+					brelse(bha[i]);
-+			}
-+		}
- 	}
- 	else
- 	{
-@@ -143,34 +173,6 @@
- 		return -ENOENT;
- 	}
- 
--	if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
--	{
--		udf_release_data(bh);
--		return -EIO;
--	}
--
--	if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
--	{
--		i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
--		if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
--			i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
--		for (num=0; i>0; i--)
--		{
--			block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
--			tmp = udf_tgetblk(dir->i_sb, block);
--			if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
--				bha[num++] = tmp;
--			else
--				brelse(tmp);
--		}
--		if (num)
--		{
--			ll_rw_block(READA, num, bha);
--			for (i=0; i<num; i++)
--				brelse(bha[i]);
--		}
--	}
--
- 	while ( nf_pos < size )
- 	{
- 		filp->f_pos = nf_pos + 1;
-diff -u -r -N ../../linus/2.4/linux/fs/udf/directory.c linux/fs/udf/directory.c
---- ../../linus/2.4/linux/fs/udf/directory.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/directory.c	2003-08-03 23:31:41.000000000 +0200
-@@ -17,6 +17,7 @@
-  */
- 
- #include "udfdecl.h"
-+#include "udf_i.h"
- 
- #include <linux/fs.h>
- #include <linux/string.h>
-@@ -84,6 +85,24 @@
- 
- 	fibh->soffset = fibh->eoffset;
- 
-+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-+	{
-+		fi = udf_get_fileident(UDF_I_DATA(dir) -
-+			(UDF_I_EFE(dir) ?
-+				sizeof(struct extendedFileEntry) :
-+				sizeof(struct fileEntry)),
-+			dir->i_sb->s_blocksize, &(fibh->eoffset));
-+
-+		if (!fi)
-+			return NULL;
-+
-+		*nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
-+
-+		memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
-+
-+		return fi;
-+	}
-+
- 	if (fibh->eoffset == dir->i_sb->s_blocksize)
- 	{
- 		int lextoffset = *extoffset;
-@@ -275,53 +294,43 @@
- }
- 
- short_ad *
--udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
-+udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
- {
--	short_ad * sa;
--	uint8_t * ptr;
-+	short_ad *sa;
- 
--	if ( (!buffer) || (!offset) )
-+	if ( (!ptr) || (!offset) )
- 	{
- 		printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
- 		return NULL;
- 	}
- 
--	ptr = (uint8_t *)buffer;
--
--	if ( (*offset > 0) && (*offset < maxoffset) )
--		ptr += *offset;
--	else
-+	if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) )
- 		return NULL;
--
--	if ((sa = (short_ad *)ptr)->extLength == 0)
-+	else if ((sa = (short_ad *)ptr)->extLength == 0)
- 		return NULL;
--	else if (inc)
--		(*offset) += sizeof(short_ad);
-+
-+	if (inc)
-+		*offset += sizeof(short_ad);
- 	return sa;
- }
- 
- long_ad *
--udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
-+udf_get_filelongad(uint8_t *ptr, int maxoffset, int * offset, int inc)
- {
--	long_ad * la;
--	uint8_t * ptr;
-+	long_ad *la;
- 
--	if ( (!buffer) || !(offset) ) 
-+	if ( (!ptr) || (!offset) ) 
- 	{
- 		printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
- 		return NULL;
- 	}
- 
--	ptr = (uint8_t *)buffer;
--
--	if ( (*offset > 0) && (*offset < maxoffset) )
--		ptr += *offset;
--	else
-+	if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) )
- 		return NULL;
--
--	if ((la = (long_ad *)ptr)->extLength == 0)
-+	else if ((la = (long_ad *)ptr)->extLength == 0)
- 		return NULL;
--	else if (inc)
--		(*offset) += sizeof(long_ad);
-+
-+	if (inc)
-+		*offset += sizeof(long_ad);
- 	return la;
- }
-diff -u -r -N ../../linus/2.4/linux/fs/udf/ecma_167.h linux/fs/udf/ecma_167.h
---- ../../linus/2.4/linux/fs/udf/ecma_167.h	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/ecma_167.h	2003-08-03 23:31:41.000000000 +0200
-@@ -606,7 +606,7 @@
- #define FE_RECORD_FMT_CRLF		0x0A
- #define FE_RECORD_FMT_LFCR		0x0B
- 
--#define Record Display Attributes (ECMA 167r3 4/14.9.8) */
-+/*  Record Display Attributes (ECMA 167r3 4/14.9.8) */
- #define FE_RECORD_DISPLAY_ATTR_UNDEF	0x00
- #define FE_RECORD_DISPLAY_ATTR_1	0x01
- #define FE_RECORD_DISPLAY_ATTR_2	0x02
-diff -u -r -N ../../linus/2.4/linux/fs/udf/file.c linux/fs/udf/file.c
---- ../../linus/2.4/linux/fs/udf/file.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/file.c	2003-08-03 23:31:41.000000000 +0200
-@@ -46,64 +46,36 @@
- static int udf_adinicb_readpage(struct file *file, struct page * page)
- {
- 	struct inode *inode = page->mapping->host;
--
--	struct buffer_head *bh;
--	int block;
- 	char *kaddr;
--	int err = 0;
- 
- 	if (!PageLocked(page))
- 		PAGE_BUG(page);
- 
- 	kaddr = kmap(page);
- 	memset(kaddr, 0, PAGE_CACHE_SIZE);
--	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
--	bh = sb_bread(inode->i_sb, block);
--	if (!bh)
--	{
--		SetPageError(page);
--		err = -EIO;
--		goto out;
--	}
--	memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
--	brelse(bh);
-+	memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size);
- 	flush_dcache_page(page);
- 	SetPageUptodate(page);
--out:
- 	kunmap(page);
- 	UnlockPage(page);
--	return err;
-+	return 0;
- }
- 
- static int udf_adinicb_writepage(struct page *page)
- {
- 	struct inode *inode = page->mapping->host;
--
--	struct buffer_head *bh;
--	int block;
- 	char *kaddr;
--	int err = 0;
- 
- 	if (!PageLocked(page))
- 		PAGE_BUG(page);
- 
- 	kaddr = kmap(page);
--	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
--	bh = sb_bread(inode->i_sb, block);
--	if (!bh)
--	{
--		SetPageError(page);
--		err = -EIO;
--		goto out;
--	}
--	memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
--	mark_buffer_dirty(bh);
--	brelse(bh);
-+	memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
-+	mark_inode_dirty(inode);
- 	SetPageUptodate(page);
--out:
- 	kunmap(page);
- 	UnlockPage(page);
--	return err;
-+	return 0;
- }
- 
- static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
-@@ -115,31 +87,17 @@
- static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
- {
- 	struct inode *inode = page->mapping->host;
--
--	struct buffer_head *bh;
--	int block;
- 	char *kaddr = page_address(page);
--	int err = 0;
- 
--	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
--	bh = sb_bread(inode->i_sb, block);
--	if (!bh)
--	{
--		SetPageError(page);
--		err = -EIO;
--		goto out;
--	}
--	memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
-+	memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
- 		kaddr + offset, to - offset);
--	mark_buffer_dirty(bh);
--	brelse(bh);
-+	mark_inode_dirty(inode);
- 	SetPageUptodate(page);
--out:
- 	kunmap(page);
- 	/* only one page here */
- 	if (to > inode->i_size)
- 		inode->i_size = to;
--	return err;
-+	return 0;
- }
- 
- struct address_space_operations udf_adinicb_aops = {
-@@ -231,9 +189,6 @@
- 	unsigned long arg)
- {
- 	int result = -EINVAL;
--	struct buffer_head *bh = NULL;
--	long_ad eaicb;
--	uint8_t *ea = NULL;
- 
- 	if ( permission(inode, MAY_READ) != 0 )
- 	{
-@@ -248,7 +203,6 @@
- 		return -EINVAL;
- 	}
- 
--	/* first, do ioctls that don't need to udf_read */
- 	switch (cmd)
- 	{
- 		case UDF_GETVOLIDENT:
-@@ -266,50 +220,16 @@
- 
- 			return result;
- 		}
--	}
--
--	/* ok, we need to read the inode */
--	bh = udf_tread(inode->i_sb,
--		udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
--
--	if (!bh)
--	{
--		udf_debug("bread failed (inode=%ld)\n", inode->i_ino);
--		return -EIO;
--	}
--
--	if (UDF_I_EXTENDED_FE(inode) == 0)
--	{
--		struct fileEntry *fe;
--
--		fe = (struct fileEntry *)bh->b_data;
--		eaicb = lela_to_cpu(fe->extendedAttrICB);
--		if (UDF_I_LENEATTR(inode))
--			ea = fe->extendedAttr;
--	}
--	else
--	{
--		struct extendedFileEntry *efe;
--
--		efe = (struct extendedFileEntry *)bh->b_data;
--		eaicb = lela_to_cpu(efe->extendedAttrICB);
--		if (UDF_I_LENEATTR(inode))
--			ea = efe->extendedAttr;
--	}
--
--	switch (cmd) 
--	{
- 		case UDF_GETEASIZE:
- 			result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
- 			break;
- 
- 		case UDF_GETEABLOCK:
--			result = copy_to_user((char *)arg, ea,
-+			result = copy_to_user((char *)arg, UDF_I_DATA(inode),
- 				UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
- 			break;
- 	}
- 
--	udf_release_data(bh);
- 	return result;
- }
- 
-diff -u -r -N ../../linus/2.4/linux/fs/udf/fsync.c linux/fs/udf/fsync.c
---- ../../linus/2.4/linux/fs/udf/fsync.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/fsync.c	2003-08-03 23:31:41.000000000 +0200
-@@ -45,7 +45,9 @@
- 	int err;
- 
- 	err = fsync_inode_buffers(inode);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,15)
- 	err |= fsync_inode_data_buffers(inode);
-+#endif
- 	if (!(inode->i_state & I_DIRTY))
- 		return err;
- 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
-diff -u -r -N ../../linus/2.4/linux/fs/udf/ialloc.c linux/fs/udf/ialloc.c
---- ../../linus/2.4/linux/fs/udf/ialloc.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/ialloc.c	2003-08-03 23:31:41.000000000 +0200
-@@ -28,6 +28,7 @@
- #include <linux/locks.h>
- #include <linux/quotaops.h>
- #include <linux/udf_fs.h>
-+#include <linux/slab.h>
- 
- #include "udf_i.h"
- #include "udf_sb.h"
-@@ -44,7 +45,12 @@
- 	 * Note: we must free any quota before locking the superblock,
- 	 * as writing the quota to disk may need the lock as well.
- 	 */
-+#ifndef OLD_QUOTA
- 	DQUOT_FREE_INODE(inode);
-+#else
-+	DQUOT_INIT(inode);
-+	DQUOT_FREE_INODE(sb, inode);
-+#endif
- 	DQUOT_DROP(inode);
- 
- 	lock_super(sb);
-@@ -69,7 +75,11 @@
- 	udf_free_blocks(sb, NULL, UDF_I_LOCATION(inode), 0, 1);
- }
- 
-+#ifndef OLD_QUOTA
- struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
-+#else
-+struct inode * udf_new_inode (const struct inode *dir, int mode, int * err)
-+#endif
- {
- 	struct super_block *sb;
- 	struct inode * inode;
-@@ -130,13 +140,20 @@
- 	inode->i_blocks = 0;
- 	UDF_I_LENEATTR(inode) = 0;
- 	UDF_I_LENALLOC(inode) = 0;
-+	UDF_I_USE(inode) = 0;
- 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
- 	{
--		UDF_I_EXTENDED_FE(inode) = 1;
-+		UDF_I_EFE(inode) = 1;
- 		UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
-+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
-+		memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
- 	}
- 	else
--		UDF_I_EXTENDED_FE(inode) = 0;
-+	{
-+		UDF_I_EFE(inode) = 0;
-+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
-+		memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry));
-+	}
- 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
- 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
- 	else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
-@@ -147,15 +164,20 @@
- 		UDF_I_CRTIME(inode) = CURRENT_TIME;
- 	UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
- 		UDF_I_UCRTIME(inode) = CURRENT_UTIME;
--	UDF_I_NEW_INODE(inode) = 1;
- 	insert_inode_hash(inode);
- 	mark_inode_dirty(inode);
- 
- 	unlock_super(sb);
-+#ifndef OLD_QUOTA
- 	if (DQUOT_ALLOC_INODE(inode))
-+#else
-+	if (DQUOT_ALLOC_INODE(sb, inode))
-+#endif
- 	{
- 		DQUOT_DROP(inode);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
- 		inode->i_flags |= S_NOQUOTA;
-+#endif
- 		inode->i_nlink = 0;
- 		iput(inode);
- 		*err = -EDQUOT;
-diff -u -r -N ../../linus/2.4/linux/fs/udf/inode.c linux/fs/udf/inode.c
---- ../../linus/2.4/linux/fs/udf/inode.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/inode.c	2003-08-03 23:31:41.000000000 +0200
-@@ -38,13 +38,16 @@
- #include <linux/mm.h>
- #include <linux/smp_lock.h>
- #include <linux/module.h>
-+#include <linux/slab.h>
- 
- #include "udf_i.h"
- #include "udf_sb.h"
- 
- MODULE_AUTHOR("Ben Fennema");
- MODULE_DESCRIPTION("Universal Disk Format Filesystem");
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
- MODULE_LICENSE("GPL");
-+#endif
- 
- #define EXTENT_MERGE_SIZE 5
- 
-@@ -122,6 +125,11 @@
- 	clear_inode(inode);
- }
- 
-+void udf_clear_inode(struct inode *inode)
-+{
-+	kfree(UDF_I_DATA(inode));
-+}
-+
- void udf_discard_prealloc(struct inode * inode)
- {
- 	if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
-@@ -162,10 +170,8 @@
- 
- void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
- {
--	struct buffer_head *bh = NULL;
- 	struct page *page;
- 	char *kaddr;
--	int block;
- 
- 	/* from now on we have normal address_space methods */
- 	inode->i_data.a_ops = &udf_aops;
-@@ -180,10 +186,6 @@
- 		return;
- 	}
- 
--	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
--	bh = udf_tread(inode->i_sb, block);
--	if (!bh)
--		return;
- 	page = grab_cache_page(inode->i_mapping, 0);
- 	if (!PageLocked(page))
- 		PAGE_BUG(page);
-@@ -192,21 +194,19 @@
- 		kaddr = kmap(page);
- 		memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
- 			PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
--		memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
-+		memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode),
- 			UDF_I_LENALLOC(inode));
- 		flush_dcache_page(page);
- 		SetPageUptodate(page);
- 		kunmap(page);
- 	}
--	memset(bh->b_data + udf_file_entry_alloc_offset(inode),
--		0, UDF_I_LENALLOC(inode));
-+	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
-+		UDF_I_LENALLOC(inode));
- 	UDF_I_LENALLOC(inode) = 0;
- 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
- 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
- 	else
- 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
--	mark_buffer_dirty_inode(bh, inode);
--	udf_release_data(bh);
- 
- 	inode->i_data.a_ops->writepage(page);
- 	page_cache_release(page);
-@@ -221,18 +221,21 @@
- 	struct buffer_head *sbh = NULL, *dbh = NULL;
- 	lb_addr bloc, eloc;
- 	uint32_t elen, extoffset;
-+	uint8_t alloctype;
- 
- 	struct udf_fileident_bh sfibh, dfibh;
- 	loff_t f_pos = udf_ext0_offset(inode) >> 2;
- 	int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
- 	struct fileIdentDesc cfi, *sfi, *dfi;
- 
-+	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
-+		alloctype = ICBTAG_FLAG_AD_SHORT;
-+	else
-+		alloctype = ICBTAG_FLAG_AD_LONG;
-+
- 	if (!inode->i_size)
- 	{
--		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
--			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
--		else
--			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
-+		UDF_I_ALLOCTYPE(inode) = alloctype;
- 		mark_inode_dirty(inode);
- 		return NULL;
- 	}
-@@ -248,9 +251,6 @@
- 		UDF_I_LOCATION(inode).partitionReferenceNum, 0);
- 	if (!newblock)
- 		return NULL;
--	sbh = udf_tread(inode->i_sb, inode->i_ino);
--	if (!sbh)
--		return NULL;
- 	dbh = udf_tgetblk(inode->i_sb, newblock);
- 	if (!dbh)
- 		return NULL;
-@@ -261,18 +261,19 @@
- 	mark_buffer_dirty_inode(dbh, inode);
- 
- 	sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
--	sfibh.sbh = sfibh.ebh = sbh;
-+	sbh = sfibh.sbh = sfibh.ebh = NULL;
- 	dfibh.soffset = dfibh.eoffset = 0;
- 	dfibh.sbh = dfibh.ebh = dbh;
- 	while ( (f_pos < size) )
- 	{
-+		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
- 		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
- 		if (!sfi)
- 		{
--			udf_release_data(sbh);
- 			udf_release_data(dbh);
- 			return NULL;
- 		}
-+		UDF_I_ALLOCTYPE(inode) = alloctype;
- 		sfi->descTag.tagLocation = *block;
- 		dfibh.soffset = dfibh.eoffset;
- 		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
-@@ -280,21 +281,15 @@
- 		if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
- 			sfi->fileIdent + sfi->lengthOfImpUse))
- 		{
--			udf_release_data(sbh);
-+			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
- 			udf_release_data(dbh);
- 			return NULL;
- 		}
- 	}
- 	mark_buffer_dirty_inode(dbh, inode);
- 
--	memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
--		0, UDF_I_LENALLOC(inode));
--
-+	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
- 	UDF_I_LENALLOC(inode) = 0;
--	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
--		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
--	else
--		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
- 	bloc = UDF_I_LOCATION(inode);
- 	eloc.logicalBlockNum = *block;
- 	eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
-@@ -304,7 +299,9 @@
- 	udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
- 	/* UniqueID stuff */
- 
--	mark_buffer_dirty(sbh);
-+#ifdef OLD_QUOTA
-+	inode->i_blocks = inode->i_sb->s_blocksize / 512;
-+#endif
- 	udf_release_data(sbh);
- 	mark_inode_dirty(inode);
- 	inode->i_version ++;
-@@ -589,6 +586,9 @@
- 	UDF_I_NEXT_ALLOC_GOAL(inode) = newblocknum;
- 	inode->i_ctime = CURRENT_TIME;
- 	UDF_I_UCTIME(inode) = CURRENT_UTIME;
-+#ifdef OLD_QUOTA
-+	inode->i_blocks += inode->i_sb->s_blocksize / 512;
-+#endif
- 
- 	if (IS_SYNC(inode))
- 		udf_sync_inode(inode);
-@@ -732,7 +732,7 @@
- 
- 				if (elen > numalloc)
- 				{
--					laarr[c].extLength -=
-+					laarr[i].extLength -=
- 						(numalloc << inode->i_sb->s_blocksize_bits);
- 					numalloc = 0;
- 				}
-@@ -854,7 +854,6 @@
- void udf_truncate(struct inode * inode)
- {
- 	int offset;
--	struct buffer_head *bh;
- 	int err;
- 
- 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-@@ -879,16 +878,8 @@
- 		}
- 		else
- 		{
--			offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
--				udf_file_entry_alloc_offset(inode);
--
--			if ((bh = udf_tread(inode->i_sb,
--				udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0))))
--			{
--				memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
--				mark_buffer_dirty(bh);
--				udf_release_data(bh);
--			}
-+			offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
-+			memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 0x00, inode->i_sb->s_blocksize - offset - udf_file_entry_alloc_offset(inode));
- 			UDF_I_LENALLOC(inode) = inode->i_size;
- 		}
- 	}
-@@ -1034,10 +1025,9 @@
- 	struct extendedFileEntry *efe;
- 	time_t convtime;
- 	long convtime_usec;
--	int offset, alen;
-+	int offset;
- 
- 	inode->i_version = ++event;
--	UDF_I_NEW_INODE(inode) = 0;
- 
- 	fe = (struct fileEntry *)bh->b_data;
- 	efe = (struct extendedFileEntry *)bh->b_data;
-@@ -1049,14 +1039,28 @@
- 
- 	UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK;
- 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE)
--		UDF_I_EXTENDED_FE(inode) = 1;
-+	{
-+		UDF_I_EFE(inode) = 1;
-+		UDF_I_USE(inode) = 0;
-+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
-+		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
-+	}
- 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
--		UDF_I_EXTENDED_FE(inode) = 0;
-+	{
-+		UDF_I_EFE(inode) = 0;
-+		UDF_I_USE(inode) = 0;
-+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
-+		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
-+	}
- 	else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
- 	{
-+		UDF_I_EFE(inode) = 0;
-+		UDF_I_USE(inode) = 1;
- 		UDF_I_LENALLOC(inode) =
- 			le32_to_cpu(
- 				((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
-+		UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
-+		memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
- 		return;
- 	}
- 
-@@ -1079,7 +1083,7 @@
- 	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
- 	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
- 
--	if (UDF_I_EXTENDED_FE(inode) == 0)
-+	if (UDF_I_EFE(inode) == 0)
- 	{
- 		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
- 			(inode->i_sb->s_blocksize_bits - 9);
-@@ -1122,7 +1126,6 @@
- 		UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
- 		UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs);
- 		offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
--		alen = offset + UDF_I_LENALLOC(inode);
- 	}
- 	else
- 	{
-@@ -1179,7 +1182,6 @@
- 		UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
- 		UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs);
- 		offset = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
--		alen = offset + UDF_I_LENALLOC(inode);
- 	}
- 
- 	switch (fe->icbTag.fileType)
-@@ -1220,6 +1222,11 @@
- 			init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
- 			break;
- 		}
-+		case ICBTAG_FILE_TYPE_SOCKET:
-+		{
-+			init_special_inode(inode, inode->i_mode | S_IFSOCK, 0);
-+			break;
-+		}
- 		case ICBTAG_FILE_TYPE_SYMLINK:
- 		{
- 			inode->i_data.a_ops = &udf_symlink_aops;
-@@ -1237,10 +1244,9 @@
- 	}
- 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- 	{
--		struct buffer_head *tbh = NULL;
- 		struct deviceSpec *dsea =
- 			(struct deviceSpec *)
--				udf_get_extendedattr(inode, 12, 1, &tbh);
-+				udf_get_extendedattr(inode, 12, 1);
- 
- 		if (dsea)
- 		{
-@@ -1248,7 +1254,6 @@
- 				((le32_to_cpu(dsea->majorDeviceIdent)) << 8) |
- 				(le32_to_cpu(dsea->minorDeviceIdent) & 0xFF));
- 			/* Developer ID ??? */
--			udf_release_data(tbh);
- 		}
- 		else
- 		{
-@@ -1325,19 +1330,11 @@
- 		udf_debug("bread failure\n");
- 		return -EIO;
- 	}
-+
-+	memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
-+
- 	fe = (struct fileEntry *)bh->b_data;
- 	efe = (struct extendedFileEntry *)bh->b_data;
--	if (UDF_I_NEW_INODE(inode) == 1)
--	{
--		if (UDF_I_EXTENDED_FE(inode) == 0)
--			memset(bh->b_data, 0x00, sizeof(struct fileEntry));
--		else
--			memset(bh->b_data, 0x00, sizeof(struct extendedFileEntry));
--		memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
--			UDF_I_LENALLOC(inode), 0x0, inode->i_sb->s_blocksize -
--			udf_file_entry_alloc_offset(inode) - UDF_I_LENALLOC(inode));
--		UDF_I_NEW_INODE(inode) = 0;
--	}
- 
- 	if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
- 	{
-@@ -1345,6 +1342,7 @@
- 			(struct unallocSpaceEntry *)bh->b_data;
- 
- 		use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
-+		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
- 		crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
- 			sizeof(tag);
- 		use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
-@@ -1387,17 +1385,16 @@
- 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- 	{
- 		regid *eid;
--		struct buffer_head *tbh = NULL;
- 		struct deviceSpec *dsea =
- 			(struct deviceSpec *)
--				udf_get_extendedattr(inode, 12, 1, &tbh);	
-+				udf_get_extendedattr(inode, 12, 1);	
- 
- 		if (!dsea)
- 		{
- 			dsea = (struct deviceSpec *)
- 				udf_add_extendedattr(inode,
- 					sizeof(struct deviceSpec) +
--					sizeof(regid), 12, 0x3, &tbh);
-+					sizeof(regid), 12, 0x3);
- 			dsea->attrType = 12;
- 			dsea->attrSubtype = 1;
- 			dsea->attrLength = sizeof(struct deviceSpec) +
-@@ -1411,12 +1408,11 @@
- 		eid->identSuffix[1] = UDF_OS_ID_LINUX;
- 		dsea->majorDeviceIdent = kdev_t_to_nr(inode->i_rdev) >> 8;
- 		dsea->minorDeviceIdent = kdev_t_to_nr(inode->i_rdev) & 0xFF;
--		mark_buffer_dirty_inode(tbh, inode);
--		udf_release_data(tbh);
- 	}
- 
--	if (UDF_I_EXTENDED_FE(inode) == 0)
-+	if (UDF_I_EFE(inode) == 0)
- 	{
-+		memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
- 		fe->logicalBlocksRecorded = cpu_to_le64(
- 			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
- 			(inode->i_sb->s_blocksize_bits - 9));
-@@ -1439,6 +1435,7 @@
- 	}
- 	else
- 	{
-+		memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
- 		efe->objectSize = cpu_to_le64(inode->i_size);
- 		efe->logicalBlocksRecorded = cpu_to_le64(
- 			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
-@@ -1507,6 +1504,8 @@
- 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR;
- 	else if (S_ISFIFO(inode->i_mode))
- 		fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO;
-+	else if (S_ISSOCK(inode->i_mode))
-+		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET;
- 
- 	icbflags =	UDF_I_ALLOCTYPE(inode) |
- 			((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) |
-@@ -1619,17 +1618,12 @@
- 	long_ad *lad = NULL;
- 	struct allocExtDesc *aed;
- 	int8_t etype;
-+	uint8_t *ptr;
- 
--	if (!(*bh))
--	{
--		if (!(*bh = udf_tread(inode->i_sb,
--			udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
--		{
--			udf_debug("reading block %d failed!\n",
--				udf_get_lb_pblock(inode->i_sb, *bloc, 0));
--			return -1;
--		}
--	}
-+	if (!*bh)
-+		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
-+	else
-+		ptr = (*bh)->b_data + *extoffset;
- 
- 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
- 		adsize = sizeof(short_ad);
-@@ -1668,7 +1662,7 @@
- 		{
- 			loffset = *extoffset;
- 			aed->lengthAllocDescs = cpu_to_le32(adsize);
--			sptr = (*bh)->b_data + *extoffset - adsize;
-+			sptr = ptr - adsize;
- 			dptr = nbh->b_data + sizeof(struct allocExtDesc);
- 			memcpy(dptr, sptr, adsize);
- 			*extoffset = sizeof(struct allocExtDesc) + adsize;
-@@ -1677,10 +1671,10 @@
- 		{
- 			loffset = *extoffset + adsize;
- 			aed->lengthAllocDescs = cpu_to_le32(0);
--			sptr = (*bh)->b_data + *extoffset;
-+			sptr = ptr;
- 			*extoffset = sizeof(struct allocExtDesc);
- 
--			if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
-+			if (*bh)
- 			{
- 				aed = (struct allocExtDesc *)(*bh)->b_data;
- 				aed->lengthAllocDescs =
-@@ -1720,18 +1714,23 @@
- 				break;
- 			}
- 		}
--		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
--			udf_update_tag((*bh)->b_data, loffset);
-+		if (*bh)
-+		{
-+			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-+				udf_update_tag((*bh)->b_data, loffset);
-+			else
-+				udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
-+			mark_buffer_dirty_inode(*bh, inode);
-+			udf_release_data(*bh);
-+		}
- 		else
--			udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
--		mark_buffer_dirty_inode(*bh, inode);
--		udf_release_data(*bh);
-+			mark_inode_dirty(inode);
- 		*bh = nbh;
- 	}
- 
- 	etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
- 
--	if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
-+	if (!*bh)
- 	{
- 		UDF_I_LENALLOC(inode) += adsize;
- 		mark_inode_dirty(inode);
-@@ -1755,49 +1754,40 @@
-     lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
- {
- 	int adsize;
--	short_ad *sad = NULL;
--	long_ad *lad = NULL;
-+	uint8_t *ptr;
- 
--	if (!(bh))
--	{
--		if (!(bh = udf_tread(inode->i_sb,
--			udf_get_lb_pblock(inode->i_sb, bloc, 0))))
--		{
--			udf_debug("reading block %d failed!\n",
--				udf_get_lb_pblock(inode->i_sb, bloc, 0));
--			return -1;
--		}
--	}
-+	if (!bh)
-+		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
- 	else
-+	{
-+		ptr = bh->b_data + *extoffset;
- 		atomic_inc(&bh->b_count);
--
--	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
--		adsize = sizeof(short_ad);
--	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
--		adsize = sizeof(long_ad);
--	else
--		return -1;
-+	}
- 
- 	switch (UDF_I_ALLOCTYPE(inode))
- 	{
- 		case ICBTAG_FLAG_AD_SHORT:
- 		{
--			sad = (short_ad *)((bh)->b_data + *extoffset);
-+			short_ad *sad = (short_ad *)ptr;
- 			sad->extLength = cpu_to_le32(elen);
- 			sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
-+			adsize = sizeof(short_ad);
- 			break;
- 		}
- 		case ICBTAG_FLAG_AD_LONG:
- 		{
--			lad = (long_ad *)((bh)->b_data + *extoffset);
-+			long_ad *lad = (long_ad *)ptr;
- 			lad->extLength = cpu_to_le32(elen);
- 			lad->extLocation = cpu_to_lelb(eloc);
- 			memset(lad->impUse, 0x00, sizeof(lad->impUse));
-+			adsize = sizeof(long_ad);
- 			break;
- 		}
-+		default:
-+			return -1;
- 	}
- 
--	if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-+	if (bh)
- 	{
- 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
- 		{
-@@ -1806,30 +1796,28 @@
- 				le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
- 		}
- 		mark_buffer_dirty_inode(bh, inode);
-+		udf_release_data(bh);
- 	}
- 	else
--	{
- 		mark_inode_dirty(inode);
--		mark_buffer_dirty(bh);
--	}
- 
- 	if (inc)
- 		*extoffset += adsize;
--	udf_release_data(bh);
- 	return (elen >> 30);
- }
- 
- int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
- 	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
- {
--	uint16_t tagIdent;
--	int pos, alen;
- 	int8_t etype;
- 
--	if (!(*bh))
-+	while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
-+		(EXT_NEXT_EXTENT_ALLOCDECS >> 30))
- 	{
--		if (!(*bh = udf_tread(inode->i_sb,
--			udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
-+		*bloc = *eloc;
-+		*extoffset = sizeof(struct allocExtDesc);
-+		udf_release_data(*bh);
-+		if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
- 		{
- 			udf_debug("reading block %d failed!\n",
- 				udf_get_lb_pblock(inode->i_sb, *bloc, 0));
-@@ -1837,154 +1825,38 @@
- 		}
- 	}
- 
--	tagIdent = le16_to_cpu(((tag *)(*bh)->b_data)->tagIdent);
--
--	if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
--	{
--		if (tagIdent == TAG_IDENT_FE || tagIdent == TAG_IDENT_EFE ||
--			UDF_I_NEW_INODE(inode))
--		{
--			pos = udf_file_entry_alloc_offset(inode);
--			alen = UDF_I_LENALLOC(inode) + pos;
--		}
--		else if (tagIdent == TAG_IDENT_USE)
--		{
--			pos = sizeof(struct unallocSpaceEntry);
--			alen = UDF_I_LENALLOC(inode) + pos;
--		}
--		else
--			return -1;
--	}
--	else if (tagIdent == TAG_IDENT_AED)
--	{
--		struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
--
--		pos = sizeof(struct allocExtDesc);
--		alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
--	}
--	else
--		return -1;
--
--	if (!(*extoffset))
--		*extoffset = pos;
--
--	switch (UDF_I_ALLOCTYPE(inode))
--	{
--		case ICBTAG_FLAG_AD_SHORT:
--		{
--			short_ad *sad;
--
--			if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
--				return -1;
--
--			if ((etype = le32_to_cpu(sad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
--			{
--				bloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
--				*extoffset = 0;
--				udf_release_data(*bh);
--				*bh = NULL;
--				return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
--			}
--			else
--			{
--				eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
--				eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
--				*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
--			}
--			break;
--		}
--		case ICBTAG_FLAG_AD_LONG:
--		{
--			long_ad *lad;
--
--			if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
--				return -1;
--
--			if ((etype = le32_to_cpu(lad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
--			{
--				*bloc = lelb_to_cpu(lad->extLocation);
--				*extoffset = 0;
--				udf_release_data(*bh);
--				*bh = NULL;
--				return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
--			}
--			else
--			{
--				*eloc = lelb_to_cpu(lad->extLocation);
--				*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
--			}
--			break;
--		}
--		case ICBTAG_FLAG_AD_IN_ICB:
--		{
--			if (UDF_I_LENALLOC(inode) == 0)
--				return -1;
--			etype = (EXT_RECORDED_ALLOCATED >> 30);
--			*eloc = UDF_I_LOCATION(inode);
--			*elen = UDF_I_LENALLOC(inode);
--			break;
--		}
--		default:
--		{
--			udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
--			return -1;
--		}
--	}
--	if (*elen)
--		return etype;
--
--	udf_debug("Empty Extent, inode=%ld, alloctype=%d, eloc=%d, elen=%d, etype=%d, extoffset=%d\n",
--		inode->i_ino, UDF_I_ALLOCTYPE(inode), eloc->logicalBlockNum, *elen, etype, *extoffset);
--	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
--		*extoffset -= sizeof(short_ad);
--	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
--		*extoffset -= sizeof(long_ad);
--	return -1;
-+	return etype;
- }
- 
- int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
- 	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
- {
--	int pos, alen;
-+	int alen;
- 	int8_t etype;
-+	uint8_t *ptr;
- 
--	if (!(*bh))
--	{
--		if (!(*bh = udf_tread(inode->i_sb,
--			udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
--		{
--			udf_debug("reading block %d failed!\n",
--				udf_get_lb_pblock(inode->i_sb, *bloc, 0));
--			return -1;
--		}
--	}
--
--	if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
-+	if (!*bh)
- 	{
--		if (!(UDF_I_EXTENDED_FE(inode)))
--			pos = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
--		else
--			pos = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
--		alen = UDF_I_LENALLOC(inode) + pos;
-+		if (!(*extoffset))
-+			*extoffset = udf_file_entry_alloc_offset(inode);
-+		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
-+		alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
- 	}
- 	else
- 	{
--		struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
--
--		pos = sizeof(struct allocExtDesc);
--		alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
-+		if (!(*extoffset))
-+			*extoffset = sizeof(struct allocExtDesc);
-+		ptr = (*bh)->b_data + *extoffset;
-+		alen = le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
- 	}
- 
--	if (!(*extoffset))
--		*extoffset = pos;
--
- 	switch (UDF_I_ALLOCTYPE(inode))
- 	{
- 		case ICBTAG_FLAG_AD_SHORT:
- 		{
- 			short_ad *sad;
- 
--			if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
-+			if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
- 				return -1;
- 
- 			etype = le32_to_cpu(sad->extLength) >> 30;
-@@ -1997,7 +1869,7 @@
- 		{
- 			long_ad *lad;
- 
--			if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
-+			if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
- 				return -1;
- 
- 			etype = le32_to_cpu(lad->extLength) >> 30;
-@@ -2011,15 +1883,8 @@
- 			return -1;
- 		}
- 	}
--	if (*elen)
--		return etype;
- 
--	udf_debug("Empty Extent!\n");
--	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
--		*extoffset -= sizeof(short_ad);
--	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
--		*extoffset -= sizeof(long_ad);
--	return -1;
-+	return etype;
- }
- 
- int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
-@@ -2029,17 +1894,7 @@
- 	uint32_t oelen;
- 	int8_t etype;
- 
--	if (!bh)
--	{
--		if (!(bh = udf_tread(inode->i_sb,
--			udf_get_lb_pblock(inode->i_sb, bloc, 0))))
--		{
--			udf_debug("reading block %d failed!\n",
--				udf_get_lb_pblock(inode->i_sb, bloc, 0));
--			return -1;
--		}
--	}
--	else
-+	if (bh)
- 		atomic_inc(&bh->b_count);
- 
- 	while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
-@@ -2063,19 +1918,11 @@
- 	int8_t etype;
- 	struct allocExtDesc *aed;
- 
--	if (!(nbh))
-+	if (nbh)
- 	{
--		if (!(nbh = udf_tread(inode->i_sb,
--			udf_get_lb_pblock(inode->i_sb, nbloc, 0))))
--		{
--			udf_debug("reading block %d failed!\n",
--				udf_get_lb_pblock(inode->i_sb, nbloc, 0));
--			return -1;
--		}
--	}
--	else
- 		atomic_inc(&nbh->b_count);
--	atomic_inc(&nbh->b_count);
-+		atomic_inc(&nbh->b_count);
-+	}
- 
- 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
- 		adsize = sizeof(short_ad);
-@@ -2094,7 +1941,7 @@
- 	while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
- 	{
- 		udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
--		if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
-+		if (obh != nbh)
- 		{
- 			obloc = nbloc;
- 			udf_release_data(obh);
-@@ -2106,12 +1953,12 @@
- 	memset(&eloc, 0x00, sizeof(lb_addr));
- 	elen = 0;
- 
--	if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
-+	if (nbh != obh)
- 	{
- 		udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
- 		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
- 		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
--		if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
-+		if (!obh)
- 		{
- 			UDF_I_LENALLOC(inode) -= (adsize * 2);
- 			mark_inode_dirty(inode);
-@@ -2131,7 +1978,7 @@
- 	else
- 	{
- 		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
--		if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
-+		if (!obh)
- 		{
- 			UDF_I_LENALLOC(inode) -= adsize;
- 			mark_inode_dirty(inode);
-@@ -2206,9 +2053,7 @@
- 		ret = 0;
- 
- 	unlock_kernel();
--
--	if (bh)
--		udf_release_data(bh);
-+	udf_release_data(bh);
- 
- 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
- 		return udf_fixed_to_variable(ret);
-diff -u -r -N ../../linus/2.4/linux/fs/udf/misc.c linux/fs/udf/misc.c
---- ../../linus/2.4/linux/fs/udf/misc.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/misc.c	2003-08-03 23:31:41.000000000 +0200
-@@ -33,18 +33,6 @@
- #include "udf_i.h"
- #include "udf_sb.h"
- 
--uint32_t
--udf64_low32(uint64_t indat)
--{
--	return indat & 0x00000000FFFFFFFFULL;
--}
--
--uint32_t
--udf64_high32(uint64_t indat)
--{
--	return indat >> 32;
--}
--
- extern struct buffer_head *
- udf_tgetblk(struct super_block *sb, int block)
- {
-@@ -65,42 +53,24 @@
- 
- extern struct genericFormat *
- udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
--	uint8_t loc, struct buffer_head **bh)
-+	uint8_t loc)
- {
- 	uint8_t *ea = NULL, *ad = NULL;
--	long_ad eaicb;
- 	int offset;
-+	uint16_t crclen;
-+	int i;
- 
--	*bh = udf_tread(inode->i_sb, inode->i_ino);
--
--	if (UDF_I_EXTENDED_FE(inode) == 0)
--	{
--		struct fileEntry *fe;
--
--		fe = (struct fileEntry *)(*bh)->b_data;
--		eaicb = lela_to_cpu(fe->extendedAttrICB);
--		offset = sizeof(struct fileEntry);
--	}
--	else
--	{
--		struct extendedFileEntry *efe;
--
--		efe = (struct extendedFileEntry *)(*bh)->b_data;
--		eaicb = lela_to_cpu(efe->extendedAttrICB);
--		offset = sizeof(struct extendedFileEntry);
--	}
--
--	ea = &(*bh)->b_data[offset];
-+	ea = UDF_I_DATA(inode);
- 	if (UDF_I_LENEATTR(inode))
--		offset += UDF_I_LENEATTR(inode);
-+		ad = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
- 	else
-+	{
-+		ad = ea;
- 		size += sizeof(struct extendedAttrHeaderDesc);
-+	}
- 
--	ad = &(*bh)->b_data[offset];
--	if (UDF_I_LENALLOC(inode))
--		offset += UDF_I_LENALLOC(inode);
--
--	offset = inode->i_sb->s_blocksize - offset;
-+	offset = inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode) -
-+		UDF_I_LENALLOC(inode);
- 
- 	/* TODO - Check for FreeEASpace */
- 
-@@ -120,7 +90,6 @@
- 			if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
- 				le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
- 			{
--				udf_release_data(*bh);
- 				return NULL;
- 			}
- 		}
-@@ -129,8 +98,11 @@
- 			size -= sizeof(struct extendedAttrHeaderDesc);
- 			UDF_I_LENEATTR(inode) += sizeof(struct extendedAttrHeaderDesc);
- 			eahd->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EAHD);
--			eahd->descTag.descVersion = cpu_to_le16(2);
--			eahd->descTag.tagSerialNum = cpu_to_le16(1);
-+			if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
-+				eahd->descTag.descVersion = cpu_to_le16(3);
-+			else
-+				eahd->descTag.descVersion = cpu_to_le16(2);
-+			eahd->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));
- 			eahd->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
- 			eahd->impAttrLocation = cpu_to_le32(0xFFFFFFFF);
- 			eahd->appAttrLocation = cpu_to_le32(0xFFFFFFFF);
-@@ -168,45 +140,30 @@
- 			}
- 		}
- 		/* rewrite CRC + checksum of eahd */
-+		crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
-+		eahd->descTag.descCRCLength = cpu_to_le16(crclen);
-+		eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd + sizeof(tag), crclen, 0));
-+		eahd->descTag.tagChecksum = 0;
-+		for (i=0; i<16; i++)
-+			if (i != 4)
-+				eahd->descTag.tagChecksum += ((uint8_t *)&(eahd->descTag))[i];
- 		UDF_I_LENEATTR(inode) += size;
- 		return (struct genericFormat *)&ea[offset];
- 	}
- 	if (loc & 0x02)
- 	{
- 	}
--	udf_release_data(*bh);
- 	return NULL;
- }
- 
- extern struct genericFormat *
--udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
--	struct buffer_head **bh)
-+udf_get_extendedattr(struct inode *inode, uint32_t type, uint8_t subtype)
- {
- 	struct genericFormat *gaf;
- 	uint8_t *ea = NULL;
--	long_ad eaicb;
- 	uint32_t offset;
- 
--	*bh = udf_tread(inode->i_sb, inode->i_ino);
--
--	if (UDF_I_EXTENDED_FE(inode) == 0)
--	{
--		struct fileEntry *fe;
--
--		fe = (struct fileEntry *)(*bh)->b_data;
--		eaicb = lela_to_cpu(fe->extendedAttrICB);
--		if (UDF_I_LENEATTR(inode))
--			ea = fe->extendedAttr;
--	}
--	else
--	{
--		struct extendedFileEntry *efe;
--
--		efe = (struct extendedFileEntry *)(*bh)->b_data;
--		eaicb = lela_to_cpu(efe->extendedAttrICB);
--		if (UDF_I_LENEATTR(inode))
--			ea = efe->extendedAttr;
--	}
-+	ea = UDF_I_DATA(inode);
- 
- 	if (UDF_I_LENEATTR(inode))
- 	{
-@@ -217,7 +174,6 @@
- 		if (le16_to_cpu(eahd->descTag.tagIdent) != TAG_IDENT_EAHD ||
- 			le32_to_cpu(eahd->descTag.tagLocation) != UDF_I_LOCATION(inode).logicalBlockNum)
- 		{
--			udf_release_data(*bh);
- 			return NULL;
- 		}
- 	
-@@ -237,12 +193,6 @@
- 				offset += le32_to_cpu(gaf->attrLength);
- 		}
- 	}
--
--	udf_release_data(*bh);
--	if (eaicb.extLength)
--	{
--		/* TODO */
--	}
- 	return NULL;
- }
- 
-@@ -268,10 +218,10 @@
- 	if (block == 0xFFFFFFFF)
- 		return NULL;
- 
--	bh = udf_tread(sb, block);
-+	bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
- 	if (!bh)
- 	{
--		udf_debug("block=%d, location=%d: read failed\n", block, location);
-+		udf_debug("block=%d, location=%d: read failed\n", block + UDF_SB_SESSION(sb), location);
- 		return NULL;
- 	}
- 
-@@ -282,7 +232,7 @@
- 	if ( location != le32_to_cpu(tag_p->tagLocation) )
- 	{
- 		udf_debug("location mismatch block %u, tag %u != %u\n",
--			block, le32_to_cpu(tag_p->tagLocation), location);
-+			block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
- 		goto error_out;
- 	}
- 	
-@@ -314,7 +264,7 @@
- 		return bh;
- 	}
- 	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
--		block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
-+		block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
- 
- error_out:
- 	brelse(bh);
-diff -u -r -N ../../linus/2.4/linux/fs/udf/namei.c linux/fs/udf/namei.c
---- ../../linus/2.4/linux/fs/udf/namei.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/namei.c	2003-08-03 23:31:41.000000000 +0200
-@@ -56,12 +56,16 @@
- 	uint8_t lfi = cfi->lengthFileIdent;
- 	int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
- 		sizeof(struct fileIdentDesc);
-+	int adinicb = 0;
-+
-+	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
-+		adinicb = 1;
- 
- 	offset = fibh->soffset + sizeof(struct fileIdentDesc);
- 
- 	if (impuse)
- 	{
--		if (offset + liu < 0)
-+		if (adinicb || (offset + liu < 0))
- 			memcpy((uint8_t *)sfi->impUse, impuse, liu);
- 		else if (offset >= 0)
- 			memcpy(fibh->ebh->b_data + offset, impuse, liu);
-@@ -76,7 +80,7 @@
- 
- 	if (fileident)
- 	{
--		if (offset + lfi < 0)
-+		if (adinicb || (offset + lfi < 0))
- 			memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
- 		else if (offset >= 0)
- 			memcpy(fibh->ebh->b_data + offset, fileident, lfi);
-@@ -89,7 +93,7 @@
- 
- 	offset += lfi;
- 
--	if (offset + padlen < 0)
-+	if (adinicb || (offset + padlen < 0))
- 		memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
- 	else if (offset >= 0)
- 		memset(fibh->ebh->b_data + offset, 0x00, padlen);
-@@ -123,7 +127,7 @@
- 			checksum += ((uint8_t *)&cfi->descTag)[i];
- 
- 	cfi->descTag.tagChecksum = checksum;
--	if (sizeof(struct fileIdentDesc) <= -fibh->soffset)
-+	if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset))
- 		memcpy((uint8_t *)sfi, (uint8_t *)cfi, sizeof(struct fileIdentDesc));
- 	else
- 	{
-@@ -132,9 +136,14 @@
- 			sizeof(struct fileIdentDesc) + fibh->soffset);
- 	}
- 
--	if (fibh->sbh != fibh->ebh)
--		mark_buffer_dirty_inode(fibh->ebh, inode);
--	mark_buffer_dirty_inode(fibh->sbh, inode);
-+	if (adinicb)
-+		mark_inode_dirty(inode);
-+	else
-+	{
-+		if (fibh->sbh != fibh->ebh)
-+			mark_buffer_dirty_inode(fibh->ebh, inode);
-+		mark_buffer_dirty_inode(fibh->sbh, inode);
-+	}
- 	return 0;
- }
- 
-@@ -146,7 +155,7 @@
- 	struct fileIdentDesc *fi=NULL;
- 	loff_t f_pos;
- 	int block, flen;
--	char fname[255];
-+	char fname[UDF_NAME_LEN];
- 	char *nameptr;
- 	uint8_t lfi;
- 	uint16_t liu;
-@@ -161,7 +170,9 @@
- 	f_pos = (udf_ext0_offset(dir) >> 2);
- 
- 	fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
--	if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
-+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-+		fibh->sbh = fibh->ebh = NULL;
-+	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
- 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
- 	{
- 		offset >>= dir->i_sb->s_blocksize_bits;
-@@ -175,6 +186,12 @@
- 		}
- 		else
- 			offset = 0;
-+
-+		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
-+		{
-+			udf_release_data(bh);
-+			return NULL;
-+		}
- 	}
- 	else
- 	{
-@@ -182,12 +199,6 @@
- 		return NULL;
- 	}
- 
--	if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
--	{
--		udf_release_data(bh);
--		return NULL;
--	}
--
- 	while ( (f_pos < size) )
- 	{
- 		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
-@@ -294,7 +305,7 @@
- 	struct fileIdentDesc cfi, *fi;
- 	struct udf_fileident_bh fibh;
- 
--	if (dentry->d_name.len > UDF_NAME_LEN)
-+	if (dentry->d_name.len > UDF_NAME_LEN-2)
- 		return ERR_PTR(-ENAMETOOLONG);
- 
- #ifdef UDF_RECOVERY
-@@ -330,7 +341,6 @@
- {
- 	struct super_block *sb;
- 	struct fileIdentDesc *fi=NULL;
--	struct ustr unifilename;
- 	char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
- 	int namelen;
- 	loff_t f_pos;
-@@ -355,30 +365,11 @@
- 			return NULL;
- 		}
- 
--		if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
-+		if ( !(namelen = udf_put_filename(sb, dentry->d_name.name, name, dentry->d_name.len)))
- 		{
- 			*err = -ENAMETOOLONG;
- 			return NULL;
- 		}
--
--		if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
--		{
--			if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
--			{
--				*err = -ENAMETOOLONG;
--				return NULL;
--			}
--		}
--		else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
--		{
--			if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, name, &unifilename, UDF_NAME_LEN)) )
--			{
--				*err = -ENAMETOOLONG;
--				return NULL;
--			}
--		}
--		else
--			return NULL;
- 	}
- 	else
- 		namelen = 0;
-@@ -388,7 +379,9 @@
- 	f_pos = (udf_ext0_offset(dir) >> 2);
- 
- 	fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
--	if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
-+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-+		fibh->sbh = fibh->ebh = NULL;
-+	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
- 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
- 	{
- 		offset >>= dir->i_sb->s_blocksize_bits;
-@@ -409,94 +402,89 @@
- 			*err = -EIO;
- 			return NULL;
- 		}
--	
-+
- 		block = UDF_I_LOCATION(dir).logicalBlockNum;
--	
--		while ( (f_pos < size) )
-+
-+	}
-+	else
-+	{
-+		block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
-+		fibh->sbh = fibh->ebh = NULL;
-+		fibh->soffset = fibh->eoffset = sb->s_blocksize;
-+		goto add;
-+	}
-+
-+	while ( (f_pos < size) )
-+	{
-+		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
-+
-+		if (!fi)
- 		{
--			fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
--	
--			if (!fi)
--			{
--				if (fibh->sbh != fibh->ebh)
--					udf_release_data(fibh->ebh);
--				udf_release_data(fibh->sbh);
--				udf_release_data(bh);
--				*err = -EIO;
--				return NULL;
--			}
--	
--			liu = le16_to_cpu(cfi->lengthOfImpUse);
--			lfi = cfi->lengthFileIdent;
--	
--			if (fibh->sbh == fibh->ebh)
--				nameptr = fi->fileIdent + liu;
-+			if (fibh->sbh != fibh->ebh)
-+				udf_release_data(fibh->ebh);
-+			udf_release_data(fibh->sbh);
-+			udf_release_data(bh);
-+			*err = -EIO;
-+			return NULL;
-+		}
-+
-+		liu = le16_to_cpu(cfi->lengthOfImpUse);
-+		lfi = cfi->lengthFileIdent;
-+
-+		if (fibh->sbh == fibh->ebh)
-+			nameptr = fi->fileIdent + liu;
-+		else
-+		{
-+			int poffset;	/* Unpaded ending offset */
-+
-+			poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
-+
-+			if (poffset >= lfi)
-+				nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
- 			else
- 			{
--				int poffset;	/* Unpaded ending offset */
--	
--				poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
--	
--				if (poffset >= lfi)
--					nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
--				else
--				{
--					nameptr = fname;
--					memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
--					memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
--				}
-+				nameptr = fname;
-+				memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
-+				memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
- 			}
--	
--			if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
-+		}
-+
-+		if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
-+		{
-+			if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
- 			{
--				if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
-+				udf_release_data(bh);
-+				cfi->descTag.tagSerialNum = cpu_to_le16(1);
-+				cfi->fileVersionNum = cpu_to_le16(1);
-+				cfi->fileCharacteristics = 0;
-+				cfi->lengthFileIdent = namelen;
-+				cfi->lengthOfImpUse = cpu_to_le16(0);
-+				if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
-+					return fi;
-+				else
- 				{
--					udf_release_data(bh);
--					cfi->descTag.tagSerialNum = cpu_to_le16(1);
--					cfi->fileVersionNum = cpu_to_le16(1);
--					cfi->fileCharacteristics = 0;
--					cfi->lengthFileIdent = namelen;
--					cfi->lengthOfImpUse = cpu_to_le16(0);
--					if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
--						return fi;
--					else
--					{
--						*err = -EIO;
--						return NULL;
--					}
-+					*err = -EIO;
-+					return NULL;
- 				}
- 			}
-+		}
- 
--			if (!lfi || !dentry)
--				continue;
-+		if (!lfi || !dentry)
-+			continue;
- 
--			if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
--				udf_match(flen, fname, &(dentry->d_name)))
--			{
--				if (fibh->sbh != fibh->ebh)
--					udf_release_data(fibh->ebh);
--				udf_release_data(fibh->sbh);
--				udf_release_data(bh);
--				*err = -EEXIST;
--				return NULL;
--			}
--		}
--	}
--	else
--	{
--		block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
--		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-+		if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
-+			udf_match(flen, fname, &(dentry->d_name)))
- 		{
--			fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
--			fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir);
--		}
--		else
--		{
--			fibh->sbh = fibh->ebh = NULL;
--			fibh->soffset = fibh->eoffset = sb->s_blocksize;
-+			if (fibh->sbh != fibh->ebh)
-+				udf_release_data(fibh->ebh);
-+			udf_release_data(fibh->sbh);
-+			udf_release_data(bh);
-+			*err = -EEXIST;
-+			return NULL;
- 		}
- 	}
- 
-+add:
- 	f_pos += nfidlen;
- 
- 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
-@@ -533,13 +521,17 @@
- 			fibh->sbh = fibh->ebh;
- 		}
- 
--		if (UDF_I_ALLOCTYPE(dir) != ICBTAG_FLAG_AD_IN_ICB)
-+		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-+		{
-+			block = UDF_I_LOCATION(dir).logicalBlockNum;
-+			fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset - udf_ext0_offset(dir) + UDF_I_LENEATTR(dir));
-+		}
-+		else
-+		{
- 			block = eloc.logicalBlockNum + ((elen - 1) >>
- 				dir->i_sb->s_blocksize_bits);
--		else
--			block = UDF_I_LOCATION(dir).logicalBlockNum;
--				
--		fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
-+			fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
-+		}
- 	}
- 	else
- 	{
-@@ -784,7 +776,10 @@
- 	f_pos = (udf_ext0_offset(dir) >> 2);
- 
- 	fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
--	if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
-+
-+	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
-+		fibh.sbh = fibh.ebh = NULL;
-+	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
- 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
- 	{
- 		offset >>= dir->i_sb->s_blocksize_bits;
-@@ -798,6 +793,12 @@
- 		}
- 		else
- 			offset = 0;
-+
-+		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
-+		{
-+			udf_release_data(bh);
-+			return 0;
-+		}
- 	}
- 	else
- 	{
-@@ -805,8 +806,6 @@
- 		return 0;
- 	}
- 
--	if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
--		return 0;
- 
- 	while ( (f_pos < size) )
- 	{
-@@ -823,6 +822,9 @@
- 
- 		if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0)
- 		{
-+			if (fibh.sbh != fibh.ebh)
-+				udf_release_data(fibh.ebh);
-+			udf_release_data(fibh.sbh);
- 			udf_release_data(bh);
- 			return 0;
- 		}
-@@ -936,6 +938,8 @@
- 	char *ea;
- 	int err;
- 	int block;
-+	char name[UDF_NAME_LEN];
-+	int namelen;
- 
- 	if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
- 		goto out;
-@@ -964,6 +968,9 @@
- 		udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0);
- 		udf_release_data(bh);
- 
-+#ifdef OLD_QUOTA
-+		inode->i_blocks = inode->i_sb->s_blocksize / 512;
-+#endif
- 		block = udf_get_pblock(inode->i_sb, block,
- 			UDF_I_LOCATION(inode).partitionReferenceNum, 0);
- 		bh = udf_tread(inode->i_sb, block);
-@@ -972,13 +979,10 @@
- 		mark_buffer_uptodate(bh, 1);
- 		unlock_buffer(bh);
- 		mark_buffer_dirty_inode(bh, inode);
-+		ea = bh->b_data + udf_ext0_offset(inode);
- 	}
- 	else
--	{
--		block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
--		bh = udf_tread(inode->i_sb, block);
--	}
--	ea = bh->b_data + udf_ext0_offset(inode);
-+		ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
- 
- 	eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
- 	pc = (struct pathComponent *)ea;
-@@ -1016,22 +1020,25 @@
- 		pc->componentType = 5;
- 		pc->lengthComponentIdent = 0;
- 		pc->componentFileVersionNum = 0;
--		if (pc->componentIdent[0] == '.')
-+		if (compstart[0] == '.')
- 		{
--			if (pc->lengthComponentIdent == 1)
-+			if ((symname-compstart) == 1)
- 				pc->componentType = 4;
--			else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.')
-+			else if ((symname-compstart) == 2 && compstart[1] == '.')
- 				pc->componentType = 3;
- 		}
- 
- 		if (pc->componentType == 5)
- 		{
--			if (elen + sizeof(struct pathComponent) + symname - compstart > eoffset)
-+			if ( !(namelen = udf_put_filename(inode->i_sb, compstart, name, symname-compstart)))
-+				goto out_no_entry;
-+
-+			if (elen + sizeof(struct pathComponent) + namelen > eoffset)
- 				goto out_no_entry;
- 			else
--				pc->lengthComponentIdent = symname - compstart;
-+				pc->lengthComponentIdent = namelen;
- 
--			memcpy(pc->componentIdent, compstart, pc->lengthComponentIdent);
-+			memcpy(pc->componentIdent, name, namelen);
- 		}
- 
- 		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
-@@ -1186,10 +1193,21 @@
- 				goto end_rename;
- 		}
- 		retval = -EIO;
--		dir_bh = udf_bread(old_inode, 0, 0, &retval);
--		if (!dir_bh)
--			goto end_rename;
--		dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
-+		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
-+		{
-+			dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
-+				(UDF_I_EFE(old_inode) ?
-+					sizeof(struct extendedFileEntry) :
-+					sizeof(struct fileEntry)),
-+				old_inode->i_sb->s_blocksize, &offset);
-+		}
-+		else
-+		{
-+			dir_bh = udf_bread(old_inode, 0, 0, &retval);
-+			if (!dir_bh)
-+				goto end_rename;
-+			dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
-+		}
- 		if (!dir_fi)
- 			goto end_rename;
- 		if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
-@@ -1241,7 +1259,7 @@
- 	UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
- 	mark_inode_dirty(old_dir);
- 
--	if (dir_bh)
-+	if (dir_fi)
- 	{
- 		dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
- 		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
-diff -u -r -N ../../linus/2.4/linux/fs/udf/super.c linux/fs/udf/super.c
---- ../../linus/2.4/linux/fs/udf/super.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/super.c	2003-08-03 23:31:41.000000000 +0200
-@@ -49,6 +49,7 @@
- #include <linux/version.h>
- #include <linux/blkdev.h>
- #include <linux/slab.h>
-+#include <linux/vmalloc.h>
- #include <linux/kernel.h>
- #include <linux/locks.h>
- #include <linux/module.h>
-@@ -104,6 +105,7 @@
- 	write_inode:		udf_write_inode,
- 	put_inode:		udf_put_inode,
- 	delete_inode:		udf_delete_inode,
-+	clear_inode:		udf_clear_inode,
- 	put_super:		udf_put_super,
- 	write_super:		udf_write_super,
- 	statfs:			udf_statfs,
-@@ -313,10 +315,6 @@
- 	UDF_SB(sb)->s_gid   = uopt.gid;
- 	UDF_SB(sb)->s_umask = uopt.umask;
- 
--#if UDFFS_RW != 1
--	*flags |= MS_RDONLY;
--#endif
--
- 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
- 		return 0;
- 	if (*flags & MS_RDONLY)
-@@ -540,14 +538,14 @@
- 			{
- 				if (location == last[i] - UDF_SB_SESSION(sb))
- 				{
--					lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
--					UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
-+					lastblock = UDF_SB_ANCHOR(sb)[0] = last[i] - UDF_SB_SESSION(sb);
-+					UDF_SB_ANCHOR(sb)[1] = last[i] - 256 - UDF_SB_SESSION(sb);
- 				}
- 				else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
- 				{
- 					UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
--					lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
--					UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
-+					lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb);
-+					UDF_SB_ANCHOR(sb)[1] = lastblock - 256 - UDF_SB_SESSION(sb);
- 				}
- 				else
- 					udf_debug("Anchor found at block %d, location mismatch %d.\n",
-@@ -556,7 +554,7 @@
- 			else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE)
- 			{
- 				lastblock = last[i];
--				UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb);
-+				UDF_SB_ANCHOR(sb)[3] = 512;
- 			}
- 			else
- 			{
-@@ -801,7 +799,7 @@
- 		if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber))
- 		{
- 			UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */
--			UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb);
-+			UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation);
- 			if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY)
- 				UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY;
- 			if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_WRITE_ONCE)
-@@ -1373,10 +1371,6 @@
- 
- 	memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
- 
--#if UDFFS_RW != 1
--	sb->s_flags |= MS_RDONLY;
--#endif
--
- 	if (!udf_parse_options((char *)options, &uopt))
- 		goto error_out;
- 
-@@ -1423,7 +1417,7 @@
- 	UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
- 	UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0;
- 	UDF_SB_ANCHOR(sb)[2] = uopt.anchor;
--	UDF_SB_ANCHOR(sb)[3] = UDF_SB_SESSION(sb) + 256;
-+	UDF_SB_ANCHOR(sb)[3] = 256;
- 
- 	if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
- 	{
-@@ -1488,8 +1482,8 @@
- 	{
- 		timestamp ts;
- 		udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
--		udf_info("UDF %s-%s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
--			UDFFS_VERSION, UDFFS_RW ? "rw" : "ro", UDFFS_DATE,
-+		udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
-+			UDFFS_VERSION, UDFFS_DATE,
- 			UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
- 			ts.typeAndTimezone);
- 	}
-@@ -1515,7 +1509,11 @@
- 		iput(inode);
- 		goto error_out;
- 	}
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
- 	sb->s_maxbytes = MAX_LFS_FILESIZE;
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
-+	sb->s_maxbytes = ~0ULL;
-+#endif
- 	return sb;
- 
- error_out:
-@@ -1528,23 +1526,9 @@
- 		if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
- 			iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
- 		if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
--		{
--			for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_uspace); i++)
--			{
--				if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i))
--					udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i));
--			}
--			kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
--		}
-+			UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace);
- 		if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
--		{
--			for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_fspace); i++)
--			{
--				if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i))
--					udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i));
--			}
--			kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
--		}
-+			UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace);
- 		if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
- 		{
- 			for (i=0; i<4; i++)
-@@ -1618,23 +1602,9 @@
- 		if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE)
- 			iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table);
- 		if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP)
--		{
--			for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_uspace); i++)
--			{
--				if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i))
--					udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace,i));
--			}
--			kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap);
--		}
-+			UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_uspace);
- 		if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP)
--		{
--			for (i=0; i<UDF_SB_BITMAP_NR_GROUPS(sb,UDF_SB_PARTITION(sb),s_fspace); i++)
--			{
--				if (UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i))
--					udf_release_data(UDF_SB_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace,i));
--			}
--			kfree(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap);
--		}
-+			UDF_SB_FREE_BITMAP(sb,UDF_SB_PARTITION(sb),s_fspace);
- 		if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15)
- 		{
- 			for (i=0; i<4; i++)
-@@ -1677,7 +1647,7 @@
- 		le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + buf->f_bfree;
- 	buf->f_ffree = buf->f_bfree;
- 	/* __kernel_fsid_t f_fsid */
--	buf->f_namelen = UDF_NAME_LEN;
-+	buf->f_namelen = UDF_NAME_LEN-2;
- 
- 	return 0;
- }
-diff -u -r -N ../../linus/2.4/linux/fs/udf/symlink.c linux/fs/udf/symlink.c
---- ../../linus/2.4/linux/fs/udf/symlink.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/symlink.c	2003-08-03 23:31:41.000000000 +0200
-@@ -37,7 +37,7 @@
- #include <linux/smp_lock.h>
- #include "udf_i.h"
- 
--static void udf_pc_to_char(char *from, int fromlen, char *to)
-+static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen, char *to)
- {
- 	struct pathComponent *pc;
- 	int elen = 0;
-@@ -65,9 +65,9 @@
- 				/* that would be . - just ignore */
- 				break;
- 			case 5:
--				memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
--				p += pc->lengthComponentIdent;
-+				p += udf_get_filename(sb, pc->componentIdent, p, pc->lengthComponentIdent);
- 				*p++ = '/';
-+				break;
- 		}
- 		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
- 	}
-@@ -84,17 +84,10 @@
- 	char *symlink;
- 	int err = -EIO;
- 	char *p = kmap(page);
--	
-+
- 	lock_kernel();
- 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
--	{
--		bh = udf_tread(inode->i_sb, inode->i_ino);
--
--		if (!bh)
--			goto out;
--
--		symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
--	}
-+		symlink = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
- 	else
- 	{
- 		bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
-@@ -105,7 +98,7 @@
- 		symlink = bh->b_data;
- 	}
- 
--	udf_pc_to_char(symlink, inode->i_size, p);
-+	udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
- 	udf_release_data(bh);
- 
- 	unlock_kernel();
-diff -u -r -N ../../linus/2.4/linux/fs/udf/truncate.c linux/fs/udf/truncate.c
---- ../../linus/2.4/linux/fs/udf/truncate.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/truncate.c	2003-08-03 23:31:41.000000000 +0200
-@@ -57,7 +57,12 @@
- 		if (last_block - first_block > 0)
- 		{
- 			if (etype == (EXT_RECORDED_ALLOCATED >> 30))
-+			{
-+#ifdef OLD_QUOTA
-+				inode->i_blocks -= ((inode->i_sb->s_blocksize / 512) * (last_block - first_block));
-+#endif
- 				mark_inode_dirty(inode);
-+			}
- 
- 			if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
- 				udf_free_blocks(inode->i_sb, inode, eloc, first_block, last_block - first_block);
-@@ -94,7 +99,7 @@
- 		else
- 			lenalloc = extoffset - adsize;
- 
--		if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-+		if (!bh)
- 			lenalloc -= udf_file_entry_alloc_offset(inode);
- 		else
- 			lenalloc -= sizeof(struct allocExtDesc);
-@@ -107,15 +112,15 @@
- 				extoffset = 0;
- 				if (lelen)
- 				{
--					if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
--						memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
-+					if (!bh)
-+						BUG();
- 					else
- 						memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
- 					udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
- 				}
- 				else
- 				{
--					if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-+					if (!bh)
- 					{
- 						UDF_I_LENALLOC(inode) = lenalloc;
- 						mark_inode_dirty(inode);
-@@ -134,9 +139,9 @@
- 				}
- 
- 				udf_release_data(bh);
--				bh = NULL;
--
-+				extoffset = sizeof(struct allocExtDesc);
- 				bloc = eloc;
-+				bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
- 				if (elen)
- 					lelen = (elen + inode->i_sb->s_blocksize - 1) >>
- 						inode->i_sb->s_blocksize_bits;
-@@ -152,15 +157,15 @@
- 
- 		if (lelen)
- 		{
--			if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
--				memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
-+			if (!bh)
-+				BUG();
- 			else
- 				memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
- 			udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
- 		}
- 		else
- 		{
--			if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-+			if (!bh)
- 			{
- 				UDF_I_LENALLOC(inode) = lenalloc;
- 				mark_inode_dirty(inode);
-diff -u -r -N ../../linus/2.4/linux/fs/udf/udf_i.h linux/fs/udf/udf_i.h
---- ../../linus/2.4/linux/fs/udf/udf_i.h	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/udf_i.h	2003-08-03 23:31:41.000000000 +0200
-@@ -9,14 +9,17 @@
- #define UDF_I_LENEXTENTS(X)	( UDF_I(X)->i_lenExtents )
- #define UDF_I_UNIQUE(X)		( UDF_I(X)->i_unique )
- #define UDF_I_ALLOCTYPE(X)	( UDF_I(X)->i_alloc_type )
--#define UDF_I_EXTENDED_FE(X)	( UDF_I(X)->i_extended_fe )
--#define UDF_I_STRAT4096(X)	( UDF_I(X)->i_strat_4096 )
--#define UDF_I_NEW_INODE(X)	( UDF_I(X)->i_new_inode )
-+#define UDF_I_EFE(X)		( UDF_I(X)->i_efe )
-+#define UDF_I_USE(X)		( UDF_I(X)->i_use )
-+#define UDF_I_STRAT4096(X)	( UDF_I(X)->i_strat4096 )
- #define UDF_I_NEXT_ALLOC_BLOCK(X)	( UDF_I(X)->i_next_alloc_block )
- #define UDF_I_NEXT_ALLOC_GOAL(X)	( UDF_I(X)->i_next_alloc_goal )
- #define UDF_I_UMTIME(X)		( UDF_I(X)->i_umtime )
- #define UDF_I_UCTIME(X)		( UDF_I(X)->i_uctime )
- #define UDF_I_CRTIME(X)		( UDF_I(X)->i_crtime )
- #define UDF_I_UCRTIME(X)	( UDF_I(X)->i_ucrtime )
-+#define UDF_I_SAD(X)		( UDF_I(X)->i_ext.i_sad )
-+#define UDF_I_LAD(X)		( UDF_I(X)->i_ext.i_lad )
-+#define UDF_I_DATA(X)		( UDF_I(X)->i_ext.i_data )
- 
- #endif /* !defined(_LINUX_UDF_I_H) */
-diff -u -r -N ../../linus/2.4/linux/fs/udf/udf_sb.h linux/fs/udf/udf_sb.h
---- ../../linus/2.4/linux/fs/udf/udf_sb.h	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/udf_sb.h	2003-08-03 23:31:41.000000000 +0200
-@@ -60,13 +60,14 @@
- {\
- 	int nr_groups = ((UDF_SB_PARTLEN((X),(Y)) + (sizeof(struct spaceBitmapDesc) << 3) +\
- 		((X)->s_blocksize * 8) - 1) / ((X)->s_blocksize * 8));\
--	UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(sizeof(struct udf_bitmap) +\
--		sizeof(struct buffer_head *) * nr_groups,\
--		GFP_KERNEL);\
-+	int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * nr_groups);\
-+	if (size <= PAGE_SIZE)\
-+		UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(size, GFP_KERNEL);\
-+	else\
-+		UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = vmalloc(size);\
- 	if (UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap != NULL)\
- 	{\
--		memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00,\
--			sizeof(struct udf_bitmap) + sizeof(struct buffer_head *) * nr_groups);\
-+		memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00, size);\
- 		UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap =\
- 			(struct buffer_head **)(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap + 1);\
- 		UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups = nr_groups;\
-@@ -77,6 +78,21 @@
- 	}\
- }
- 
-+#define UDF_SB_FREE_BITMAP(X,Y,Z)\
-+{\
-+	int i;\
-+	int nr_groups = UDF_SB_BITMAP_NR_GROUPS(X,Y,Z);\
-+	int size = sizeof(struct udf_bitmap) + (sizeof(struct buffer_head *) * nr_groups);\
-+	for (i=0; i<nr_groups; i++)\
-+	{\
-+		if (UDF_SB_BITMAP(X,Y,Z,i))\
-+			udf_release_data(UDF_SB_BITMAP(X,Y,Z,i));\
-+	}\
-+	if (size <= PAGE_SIZE)\
-+		kfree(UDF_SB_PARTMAPS(X)[Y].Z.s_bitmap);\
-+	else\
-+		vfree(UDF_SB_PARTMAPS(X)[Y].Z.s_bitmap);\
-+}
- 
- #define UDF_QUERY_FLAG(X,Y)			( UDF_SB(X)->s_flags & ( 1 << (Y) ) )
- #define UDF_SET_FLAG(X,Y)			( UDF_SB(X)->s_flags |= ( 1 << (Y) ) )
-@@ -95,7 +111,7 @@
- #define UDF_SB_PARTFUNC(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_partition_func )
- #define UDF_SB_PARTFLAGS(X,Y)			( UDF_SB_PARTMAPS(X)[(Y)].s_partition_flags )
- #define UDF_SB_BITMAP(X,Y,Z,I)			( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap[I] )
--#define UDF_SB_BITMAP_NR_GROUPS(X,Y,Z)	( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups )
-+#define UDF_SB_BITMAP_NR_GROUPS(X,Y,Z)		( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups )
- 
- #define UDF_SB_VOLIDENT(X)			( UDF_SB(X)->s_volident )
- #define UDF_SB_NUMPARTS(X)			( UDF_SB(X)->s_partitions )
-diff -u -r -N ../../linus/2.4/linux/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h
---- ../../linus/2.4/linux/fs/udf/udfdecl.h	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/udfdecl.h	2003-08-03 23:31:41.000000000 +0200
-@@ -28,15 +28,17 @@
- #define UDF_EXTENT_FLAG_MASK	0xC0000000
- 
- #define UDF_NAME_PAD		4
--#define UDF_NAME_LEN		255
-+#define UDF_NAME_LEN		256
- #define UDF_PATH_LEN		1023
- 
- #define CURRENT_UTIME	(xtime.tv_usec)
- 
- #define udf_file_entry_alloc_offset(inode)\
--	((UDF_I_EXTENDED_FE(inode) ?\
--		sizeof(struct extendedFileEntry) :\
--		sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode))
-+	(UDF_I_USE(inode) ?\
-+		sizeof(struct unallocSpaceEntry) :\
-+		((UDF_I_EFE(inode) ?\
-+			sizeof(struct extendedFileEntry) :\
-+			sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode)))
- 
- #define udf_ext0_offset(inode)\
- 	(UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ?\
-@@ -66,13 +68,6 @@
- 	int eoffset;
- };
- 
--struct udf_directory_record
--{
--	uint32_t	d_parent;
--	uint32_t	d_inode;
--	uint32_t	d_name[255];
--};
--
- struct udf_vds_record
- {
- 	uint32_t block;
-@@ -88,7 +83,7 @@
- struct ustr
- {
- 	uint8_t u_cmpID;
--	uint8_t u_name[UDF_NAME_LEN];
-+	uint8_t u_name[UDF_NAME_LEN-2];
- 	uint8_t u_len;
- };
- 
-@@ -113,6 +108,7 @@
- extern void udf_read_inode(struct inode *);
- extern void udf_put_inode(struct inode *);
- extern void udf_delete_inode(struct inode *);
-+extern void udf_clear_inode(struct inode *);
- extern void udf_write_inode(struct inode *, int);
- extern long udf_block_map(struct inode *, long);
- extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-@@ -128,11 +124,13 @@
- extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref);
- extern struct buffer_head *udf_tgetblk(struct super_block *, int);
- extern struct buffer_head *udf_tread(struct super_block *, int);
--extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t, struct buffer_head **);
--extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t, struct buffer_head **);
-+extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t);
-+extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t);
- extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
- extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
- extern void udf_release_data(struct buffer_head *);
-+extern void udf_update_tag(char *, int);
-+extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
- 
- /* lowlevel.c */
- extern unsigned int udf_get_last_session(struct super_block *);
-@@ -147,18 +145,31 @@
- 
- /* unicode.c */
- extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
-+extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, int);
-+extern int udf_build_ustr(struct ustr *, dstring *, int);
-+extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
- 
- /* ialloc.c */
- extern void udf_free_inode(struct inode *);
-+#ifndef OLD_QUOTA
- extern struct inode * udf_new_inode (struct inode *, int, int *);
-+#else
-+extern struct inode * udf_new_inode (const struct inode *, int, int *);
-+#endif
- 
- /* truncate.c */
- extern void udf_truncate_extents(struct inode *);
- 
- /* balloc.c */
-+#ifndef OLD_QUOTA
- extern void udf_free_blocks(struct super_block *, struct inode *, lb_addr, uint32_t, uint32_t);
- extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, uint32_t, uint32_t);
- extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_t, int *);
-+#else
-+extern void udf_free_blocks(struct super_block *, const struct inode *, lb_addr, uint32_t, uint32_t);
-+extern int udf_prealloc_blocks(struct super_block *, const struct inode *, uint16_t, uint32_t, uint32_t);
-+extern int udf_new_block(struct super_block *, const struct inode *, uint16_t, uint32_t, int *);
-+#endif
- 
- /* fsync.c */
- extern int udf_fsync_file(struct file *, struct dentry *, int);
-@@ -167,40 +178,28 @@
- /* directory.c */
- extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
- extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
--
--/* unicode.c */
--extern int udf_ustr_to_dchars(uint8_t *, const struct ustr *, int);
--extern int udf_ustr_to_char(uint8_t *, const struct ustr *, int);
--extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
--extern int udf_dchars_to_ustr(struct ustr *, const uint8_t *, int);
--extern int udf_char_to_ustr(struct ustr *, const uint8_t *, int);
--extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
--extern int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
--extern int udf_build_ustr(struct ustr *, dstring *, int);
--extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
--extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
--extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
--extern int udf_CS0toNLS(struct nls_table *, struct ustr *, struct ustr *);
--extern int udf_NLStoCS0(struct nls_table *, dstring *, struct ustr *, int);
-+extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
-+extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
-+extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
-+extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
-+extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
- 
- /* crc.c */
- extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
- 
--/* misc.c */
--extern uint32_t udf64_low32(uint64_t);
--extern uint32_t udf64_high32(uint64_t);
--extern void udf_update_tag(char *, int);
--extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
--
- /* udftime.c */
- extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
- extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
- 
--/* directory.c */
--extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
--extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
--extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
--extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
--extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
-+static inline struct buffer_head * sb_bread(struct super_block *sb, int block)
-+{
-+	return bread(sb->s_dev, block, sb->s_blocksize);
-+}
-+static inline struct buffer_head * sb_getblk(struct super_block *sb, int block)
-+{
-+	return getblk(sb->s_dev, block, sb->s_blocksize);
-+}
-+#endif
- 
- #endif /* __UDF_DECL_H */
-diff -u -r -N ../../linus/2.4/linux/fs/udf/udftime.c linux/fs/udf/udftime.c
---- ../../linus/2.4/linux/fs/udf/udftime.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/udftime.c	2003-08-03 23:31:41.000000000 +0200
-@@ -33,7 +33,6 @@
-  */
- 
- #include <linux/types.h>
--#include <linux/kernel.h>
- #include "udfdecl.h"
- 
- #define EPOCH_YEAR 1970
-diff -u -r -N ../../linus/2.4/linux/fs/udf/unicode.c linux/fs/udf/unicode.c
---- ../../linus/2.4/linux/fs/udf/unicode.c	2003-08-03 23:23:24.000000000 +0200
-+++ linux/fs/udf/unicode.c	2003-08-03 23:31:41.000000000 +0200
-@@ -32,48 +32,11 @@
- 
- #include "udf_sb.h"
- 
--int udf_ustr_to_dchars(uint8_t *dest, const struct ustr *src, int strlen)
--{
--	if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
--		return 0;
--	memcpy(dest+1, src->u_name, src->u_len);
--	dest[0] = src->u_cmpID;
--	return src->u_len + 1;
--}
-+static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
- 
--int udf_ustr_to_char(uint8_t *dest, const struct ustr *src, int strlen)
-+static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
- {
--	if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
--		return 0;
--	memcpy(dest, src->u_name, src->u_len);
--	return src->u_len;
--}
--
--int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
--{
--	if ( udf_ustr_to_dchars(dest, src, dlength-1) )
--	{
--		dest[dlength-1] = src->u_len + 1;
--		return dlength;
--	}
--	else
--		return 0;
--}
--
--int udf_dchars_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
--{
--	if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
--		return 0;
--	memset(dest, 0, sizeof(struct ustr));
--	memcpy(dest->u_name, src+1, strlen-1);
--	dest->u_cmpID = src[0];
--	dest->u_len = strlen-1;
--	return strlen-1;
--}
--
--int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
--{
--	if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
-+	if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN-2) )
- 		return 0;
- 	memset(dest, 0, sizeof(struct ustr));
- 	memcpy(dest->u_name, src, strlen);
-@@ -82,15 +45,6 @@
- 	return strlen;
- }
- 
--
--int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
--{
--	if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
--		return dlength;
--	else
--		return 0;
--}
--
- /*
-  * udf_build_ustr
-  */
-@@ -112,7 +66,7 @@
- /*
-  * udf_build_ustr_exact
-  */
--int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
-+static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
- {
- 	if ( (!dest) || (!ptr) || (!exactsize) )
- 		return -1;
-@@ -224,17 +178,17 @@
-  *	November 12, 1997 - Andrew E. Mileski
-  *	Written, tested, and released.
-  */
--int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
-+static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
- {
- 	unsigned c, i, max_val, utf_char;
--	int utf_cnt;
--	int u_len = 0;
-+	int utf_cnt, u_len;
- 
- 	memset(ocu, 0, sizeof(dstring) * length);
- 	ocu[0] = 8;
- 	max_val = 0xffU;
- 
- try_again:
-+	u_len = 0U;
- 	utf_char = 0U;
- 	utf_cnt = 0U;
- 	for (i = 0U; i < utf->u_len; i++)
-@@ -318,7 +272,7 @@
- 	return u_len + 1;
- }
- 
--int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
-+static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
- {
- 	uint8_t *ocu;
- 	uint32_t c;
-@@ -360,25 +314,25 @@
- 	return utf_o->u_len;
- }
- 
--int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
-+static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
- {
- 	unsigned len, i, max_val;
- 	uint16_t uni_char;
--	int uni_cnt;
--	int u_len = 0;
-+	int u_len;
- 
- 	memset(ocu, 0, sizeof(dstring) * length);
- 	ocu[0] = 8;
- 	max_val = 0xffU;
- 
- try_again:
--	uni_char = 0U;
--	uni_cnt = 0U;
-+	u_len = 0U;
- 	for (i = 0U; i < uni->u_len; i++)
- 	{
- 		len = nls->char2uni(&uni->u_name[i], uni->u_len-i, &uni_char);
-+		if (len <= 0)
-+			continue;
- 
--		if (len == 2 && max_val == 0xff)
-+		if (uni_char > max_val)
- 		{
- 			max_val = 0xffffU;
- 			ocu[0] = (uint8_t)0x10U;
-@@ -386,11 +340,9 @@
- 		}
- 		
- 		if (max_val == 0xffffU)
--		{
- 			ocu[++u_len] = (uint8_t)(uni_char >> 8);
--			i++;
--		}
- 		ocu[++u_len] = (uint8_t)(uni_char & 0xffU);
-+		i += len - 1;
- 	}
- 
- 	ocu[length - 1] = (uint8_t)u_len + 1;
-@@ -434,12 +386,42 @@
- 	return 0;
- }
- 
-+int udf_put_filename(struct super_block *sb, const uint8_t *sname, uint8_t *dname, int flen)
-+{
-+	struct ustr unifilename;
-+	int namelen;
-+
-+	if ( !(udf_char_to_ustr(&unifilename, sname, flen)) )
-+	{
-+		return 0;
-+	}
-+
-+	if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
-+	{
-+		if ( !(namelen = udf_UTF8toCS0(dname, &unifilename, UDF_NAME_LEN)) )
-+		{
-+			return 0;
-+		}
-+	}
-+	else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
-+	{
-+		if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, dname, &unifilename, UDF_NAME_LEN)) )
-+		{
-+			return 0;
-+		}
-+	}
-+	else
-+		return 0;
-+
-+	return namelen;
-+}
-+
- #define ILLEGAL_CHAR_MARK	'_'
- #define EXT_MARK			'.'
- #define CRC_MARK			'#'
- #define EXT_SIZE			5
- 
--int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
-+static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
- {
- 	int index, newIndex = 0, needsCRC = 0;	
- 	int extIndex = 0, newExtIndex = 0, hasExt = 0;
-diff -u -r -N ../../linus/2.4/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
---- ../../linus/2.4/linux/include/linux/cdrom.h	2003-08-03 23:24:05.000000000 +0200
-+++ linux/include/linux/cdrom.h	2003-08-03 23:32:18.000000000 +0200
-@@ -494,6 +494,7 @@
- /* Mode page codes for mode sense/set */
- #define GPMODE_R_W_ERROR_PAGE		0x01
- #define GPMODE_WRITE_PARMS_PAGE		0x05
-+#define GPMODE_WCACHING_PAGE		0x08
- #define GPMODE_AUDIO_CTL_PAGE		0x0e
- #define GPMODE_POWER_PAGE		0x1a
- #define GPMODE_FAULT_FAIL_PAGE		0x1c
-@@ -504,6 +505,11 @@
-  * of MODE_SENSE_POWER_PAGE */
- #define GPMODE_CDROM_PAGE		0x0d
- 
-+#define GPMODE_PAGE_CURRENT		0
-+#define GPMODE_PAGE_CHANGE		1
-+#define GPMODE_PAGE_DEFAULT		2
-+#define GPMODE_PAGE_SAVE		3
-+
- 
- 
- /* DVD struct types */
-diff -u -r -N ../../linus/2.4/linux/include/linux/major.h linux/include/linux/major.h
---- ../../linus/2.4/linux/include/linux/major.h	2003-08-03 23:24:07.000000000 +0200
-+++ linux/include/linux/major.h	2003-08-03 23:32:19.000000000 +0200
-@@ -109,6 +109,8 @@
- #define SPECIALIX_NORMAL_MAJOR 75
- #define SPECIALIX_CALLOUT_MAJOR 76
- 
-+#define PACKET_MAJOR		97
-+
- #define COMPAQ_CISS_MAJOR 	104
- #define COMPAQ_CISS_MAJOR1	105
- #define COMPAQ_CISS_MAJOR2      106
-diff -u -r -N ../../linus/2.4/linux/include/linux/pktcdvd.h linux/include/linux/pktcdvd.h
---- ../../linus/2.4/linux/include/linux/pktcdvd.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux/include/linux/pktcdvd.h	2003-08-03 23:32:25.000000000 +0200
-@@ -0,0 +1,214 @@
-+/*
-+ * Copyright (C) 2000 Jens Axboe <axboe at suse.de>
-+ *
-+ * May be copied or modified under the terms of the GNU General Public
-+ * License.  See linux/COPYING for more information.
-+ *
-+ * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
-+ * DVD-RW devices.
-+ *
-+ */
-+#ifndef __PKTCDVD_H
-+#define __PKTCDVD_H
-+
-+/*
-+ * 1 for normal debug messages, 2 is very verbose. 0 to turn it off.
-+ */
-+#define PACKET_DEBUG		1
-+
-+#define	MAX_WRITERS		8
-+
-+#define STACKED_BH_POOL_SIZE	64
-+
-+/*
-+ * use drive write caching -- we need deferred error handling to be
-+ * able to sucessfully recover with this option (drive will return good
-+ * status as soon as the cdb is validated).
-+ */
-+#if defined(CONFIG_CDROM_PKTCDVD_WCACHE)
-+#warning Enabling write caching, use at your own risk
-+#define USE_WCACHING		1
-+#else
-+#define USE_WCACHING		0
-+#endif
-+
-+/*
-+ * No user-servicable parts beyond this point ->
-+ */
-+
-+#if PACKET_DEBUG
-+#define DPRINTK(fmt, args...) printk(KERN_NOTICE fmt, ##args)
-+#else
-+#define DPRINTK(fmt, args...)
-+#endif
-+
-+#if PACKET_DEBUG > 1
-+#define VPRINTK(fmt, args...) printk(KERN_NOTICE fmt, ##args)
-+#else
-+#define VPRINTK(fmt, args...)
-+#endif
-+
-+#define PKT_BUF_LIST		0x89
-+
-+/*
-+ * device types
-+ */
-+#define PACKET_CDR		1
-+#define	PACKET_CDRW		2
-+#define PACKET_DVDR		3
-+#define PACKET_DVDRW		4
-+
-+/*
-+ * flags
-+ */
-+#define PACKET_WRITEABLE	1	/* pd is writeable */
-+#define PACKET_NWA_VALID	2	/* next writeable address valid */
-+#define PACKET_LRA_VALID	3	/* last recorded address valid */
-+#define PACKET_READONLY		4	/* read only pd */
-+#define PACKET_RECOVERY		5	/* rq recovery in progress */
-+#define PACKET_RQ		6	/* current rq is set */
-+#define PACKET_BUSY		7	/* current rq is being processed */
-+
-+/*
-+ * Disc status -- from READ_DISC_INFO
-+ */
-+#define PACKET_DISC_EMPTY	0
-+#define PACKET_DISC_INCOMPLETE	1
-+#define PACKET_DISC_COMPLETE	2
-+#define PACKET_DISC_OTHER	3
-+
-+/*
-+ * write type, and corresponding data block type
-+ */
-+#define PACKET_MODE1		1
-+#define PACKET_MODE2		2
-+#define PACKET_BLOCK_MODE1	8
-+#define PACKET_BLOCK_MODE2	10
-+
-+/*
-+ * Last session/border status
-+ */
-+#define PACKET_SESSION_EMPTY		0
-+#define PACKET_SESSION_INCOMPLETE	1
-+#define PACKET_SESSION_RESERVED		2
-+#define PACKET_SESSION_COMPLETE		3
-+
-+#define PACKET_MCN			"4a656e734178626f65323030300000"
-+
-+#undef PACKET_USE_LS
-+
-+/*
-+ * special requests
-+ */
-+#define PKT_THROTTLE_SPEED	1
-+
-+#define PKT_TRAY_UNLOCK		0
-+#define PKT_TRAY_LOCK		1
-+
-+/*
-+ * Very crude stats for now
-+ */
-+struct packet_stats
-+{
-+	unsigned long		bh_s;
-+	unsigned long		bh_e;
-+	unsigned long		bh_cache_hits;
-+	unsigned long		page_cache_hits;
-+	unsigned long		secs_w;
-+	unsigned long		secs_r;
-+};
-+
-+/*
-+ * packet ioctls
-+ */
-+#define PACKET_IOCTL_MAGIC	('X')
-+#define PACKET_GET_STATS	_IOR(PACKET_IOCTL_MAGIC, 0, struct packet_stats)
-+#define PACKET_SETUP_DEV	_IOW(PACKET_IOCTL_MAGIC, 1, unsigned int)
-+#define PACKET_TEARDOWN_DEV	_IOW(PACKET_IOCTL_MAGIC, 2, unsigned int)
-+
-+#ifdef __KERNEL__
-+#include <linux/blkdev.h>
-+#include <linux/completion.h>
-+
-+struct packet_settings
-+{
-+	__u8			size;		/* packet size in frames */
-+	__u8			fp;		/* fixed packets */
-+	__u8			link_loss;	/* the rest is specified
-+						 * as per Mt Fuji */
-+	__u8			write_type;
-+	__u8			track_mode;
-+	__u8			block_mode;
-+};
-+
-+struct packet_cdrw
-+{
-+	struct buffer_head		*bhlist;	/* string of bhs */
-+	atomic_t			free_bh;
-+	merge_request_fn		*front_merge_fn;
-+	merge_request_fn		*back_merge_fn;
-+	merge_requests_fn		*merge_requests_fn;
-+	request_queue_t			r_queue;
-+	void				*queuedata;
-+	pid_t				pid;
-+	int				time_to_die;
-+	struct completion		thr_compl;
-+};
-+
-+struct pktcdvd_device
-+{
-+	struct block_device		*bdev;
-+	kdev_t				dev;		/* dev attached */
-+	kdev_t				pkt_dev;	/* our dev */
-+	char				name[20];
-+	struct cdrom_device_info	*cdi;		/* cdrom matching dev */
-+	struct packet_settings		settings;
-+	struct packet_stats		stats;
-+	atomic_t			refcnt;
-+	__u8				speed;		/* cur write speed */
-+	unsigned long			offset;		/* start offset */
-+	__u8				mode_offset;	/* 0 / 8 */
-+	__u8				type;
-+	unsigned long			flags;
-+	__u8				disc_status;
-+	__u8				track_status;	/* last one */
-+	__u32				nwa;	/* next writable address */
-+	__u32				lra;	/* last recorded address */
-+	spinlock_t			lock;
-+	struct packet_cdrw		cdrw;
-+	wait_queue_head_t		wqueue;
-+	struct request			*rq;
-+	atomic_t			wrqcnt;
-+	struct buffer_head		*stacked_bhlist;
-+	int				stacked_bhcnt;
-+
-+	struct semaphore		cache_sync_mutex;
-+	int				unflushed_writes;
-+
-+	make_request_fn			*make_request_fn;
-+};
-+
-+/*
-+ * following possibly belongs in cdrom.h
-+ */
-+
-+struct cdvd_capacity
-+{
-+	__u32 lba;
-+	__u32 block_length;
-+};
-+
-+void pkt_elevator_merge_req(struct request *rq, struct request *nxt) {}
-+
-+#define ELEVATOR_PKTCDVD					\
-+((elevator_t) {							\
-+	0,				/* not used */		\
-+	0,				/* not used */		\
-+								\
-+	pkt_elevator_merge,		/* elevator_merge_fn */ \
-+	pkt_elevator_merge_req,					\
-+	})
-+
-+#endif /* __KERNEL__ */
-+
-+#endif /* __PKTCDVD_H */
-diff -u -r -N ../../linus/2.4/linux/include/linux/udf_fs.h linux/include/linux/udf_fs.h
---- ../../linus/2.4/linux/include/linux/udf_fs.h	2003-08-03 23:24:12.000000000 +0200
-+++ linux/include/linux/udf_fs.h	2003-08-03 23:32:26.000000000 +0200
-@@ -30,7 +30,6 @@
-  * HISTORY
-  *
-  */
--#include <linux/config.h>
- 
- #ifndef _UDF_FS_H
- #define _UDF_FS_H 1
-@@ -38,18 +37,8 @@
- #define UDF_PREALLOCATE
- #define UDF_DEFAULT_PREALLOC_BLOCKS	8
- 
--#define UDFFS_DATE			"2002/03/11"
--#define UDFFS_VERSION			"0.9.6"
--
--#if !defined(UDFFS_RW)
--
--#if defined(CONFIG_UDF_RW)
--#define UDFFS_RW			1
--#else /* !defined(CONFIG_UDF_RW) */
--#define UDFFS_RW			0
--#endif /* defined(CONFIG_UDF_RW) */
--
--#endif /* !defined(UDFFS_RW) */
-+#define UDFFS_DATE			"2003/01/05"
-+#define UDFFS_VERSION			"0.9.7"
- 
- #define UDFFS_DEBUG
- 
-@@ -67,4 +56,12 @@
- #define udf_info(f, a...) \
- 		printk (KERN_INFO "UDF-fs INFO " f, ##a);
- 
-+#ifdef __KERNEL__
-+
-+#ifndef LINUX_VERSION_CODE
-+#include <linux/version.h>
-+#endif
-+
-+#endif /* __KERNEL__ */
-+
- #endif /* _UDF_FS_H */
-diff -u -r -N ../../linus/2.4/linux/include/linux/udf_fs_i.h linux/include/linux/udf_fs_i.h
---- ../../linus/2.4/linux/include/linux/udf_fs_i.h	2003-08-03 23:24:12.000000000 +0200
-+++ linux/include/linux/udf_fs_i.h	2003-08-03 23:32:26.000000000 +0200
-@@ -23,30 +23,49 @@
- #ifndef _ECMA_167_H
- typedef struct
- {
--	__u32 logicalBlockNum;
--	__u16 partitionReferenceNum;
-+	__u32			logicalBlockNum;
-+	__u16			partitionReferenceNum;
- } __attribute__ ((packed)) lb_addr;
-+
-+typedef struct
-+{
-+	__u32			extLength;
-+	__u32			extPosition;
-+} __attribute__ ((packed)) short_ad;
-+
-+typedef struct
-+{
-+	__u32			extLength;
-+	lb_addr			extLocation;
-+	__u8			impUse[6];
-+} __attribute__ ((packed)) long_ad;
- #endif
- 
- struct udf_inode_info
- {
--	long i_umtime;
--	long i_uctime;
--	long i_crtime;
--	long i_ucrtime;
-+	long			i_umtime;
-+	long			i_uctime;
-+	long			i_crtime;
-+	long			i_ucrtime;
- 	/* Physical address of inode */
--	lb_addr i_location;
--	__u64 i_unique;
--	__u32 i_lenEAttr;
--	__u32 i_lenAlloc;
--	__u64 i_lenExtents;
--	__u32 i_next_alloc_block;
--	__u32 i_next_alloc_goal;
--	unsigned i_alloc_type : 3;
--	unsigned i_extended_fe : 1;
--	unsigned i_strat_4096 : 1;
--	unsigned i_new_inode : 1;
--	unsigned reserved : 26;
-+	lb_addr			i_location;
-+	__u64			i_unique;
-+	__u32			i_lenEAttr;
-+	__u32			i_lenAlloc;
-+	__u64			i_lenExtents;
-+	__u32			i_next_alloc_block;
-+	__u32			i_next_alloc_goal;
-+	unsigned		i_alloc_type : 3;
-+	unsigned		i_efe : 1;
-+	unsigned		i_use : 1;
-+	unsigned		i_strat4096 : 1;
-+	unsigned		reserved : 26;
-+	union
-+	{
-+		short_ad	*i_sad;
-+		long_ad		*i_lad;
-+		__u8		*i_data;
-+	} i_ext;
- };
- 
- #endif




More information about the blfs-book mailing list