## Automatically generated incremental diff
## From:   linux-2.4.25-pre8
## To:     linux-2.4.25-rc1
## Robot:  $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $

diff -urN linux-2.4.25-pre8/CREDITS linux-2.4.25-rc1/CREDITS
--- linux-2.4.25-pre8/CREDITS	2004-02-05 04:40:30.000000000 -0800
+++ linux-2.4.25-rc1/CREDITS	2004-02-05 04:40:35.000000000 -0800
@@ -848,8 +848,8 @@
 W: http://www.pi.se/blox/
 D: Extended support for loadable modules
 D: D-Link pocket adapter drivers
-S: Grevgatan 11
-S: S-114 53 Stockholm
+S: Brevia 1043
+S: S-114 79 Stockholm
 S: Sweden
 
 N: Michael Engel
diff -urN linux-2.4.25-pre8/Documentation/Configure.help linux-2.4.25-rc1/Documentation/Configure.help
--- linux-2.4.25-pre8/Documentation/Configure.help	2004-02-05 04:40:30.000000000 -0800
+++ linux-2.4.25-rc1/Documentation/Configure.help	2004-02-05 04:40:35.000000000 -0800
@@ -10647,6 +10647,15 @@
   whenever you want).  If you want to compile it as a module, say M
   here and read <file:Documentation/modules.txt>.
 
+CONFIG_NET_SCH_HFSC
+  Say Y here if you want to use the Hierarchical Fair Service Curve
+  (HFSC) packet scheduling algorithm for some of your network devices.
+
+  This code is also available as a module called sch_hfsc.o ( = code
+  which can be inserted in and removed from the running kernel
+  whenever you want).  If you want to compile it as a module, say M
+  here and read <file:Documentation/modules.txt>.
+
 CSZ packet scheduler
 CONFIG_NET_SCH_CSZ
   Say Y here if you want to use the Clark-Shenker-Zhang (CSZ) packet
diff -urN linux-2.4.25-pre8/Makefile linux-2.4.25-rc1/Makefile
--- linux-2.4.25-pre8/Makefile	2004-02-05 04:40:30.000000000 -0800
+++ linux-2.4.25-rc1/Makefile	2004-02-05 04:40:35.000000000 -0800
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 25
-EXTRAVERSION = -pre8
+EXTRAVERSION = -rc1
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.25-pre8/arch/sparc64/kernel/head.S linux-2.4.25-rc1/arch/sparc64/kernel/head.S
--- linux-2.4.25-pre8/arch/sparc64/kernel/head.S	2004-02-05 04:40:31.000000000 -0800
+++ linux-2.4.25-rc1/arch/sparc64/kernel/head.S	2004-02-05 04:40:35.000000000 -0800
@@ -57,10 +57,11 @@
 
 	/* History:
 	 *
-	 * 0x0202 : Supports kernel params string
 	 * 0x0300 : Supports being located at other than 0x4000
+	 * 0x0202 : Supports kernel params string
+	 * 0x0201 : Supports reboot_command
 	 */
-        .half   0x0300          /* HdrS version */
+	.half   0x0300          /* HdrS version */
 
 root_flags:
         .half   1
@@ -158,6 +159,21 @@
 	blu,pt	%xcc, 1b
 	 add	%l0, (1 << 3), %l0
 
+	/* Search the small TLB.  OBP never maps us like that but
+	 * newer SILO can.
+	 */
+	clr	%l0
+
+1:	ldxa	[%l0] ASI_ITLB_TAG_READ, %g1
+	membar	#Sync
+	andn	%g1, %l2, %g1
+	cmp	%g1, %g2
+	be,pn	%xcc, cheetah_got_tlbentry
+	 nop
+	cmp	%l0, (15 << 3)
+	blu,pt	%xcc, 1b
+	 add	%l0, (1 << 3), %l0
+
 	/* BUG() if we get here... */
 	ta	0x5
 
@@ -166,7 +182,8 @@
 	ldxa	[%l0] ASI_ITLB_DATA_ACCESS, %g1
 	membar	#Sync
 	and	%g1, %g3, %g1
-	sub	%g1, %g2, %g1
+	set	0x5fff, %l0
+	andn	%g1, %l0, %g1
 	or	%g5, %g1, %g5
 
 	/* Clear out any KERNBASE area entries. */
diff -urN linux-2.4.25-pre8/arch/sparc64/kernel/ioctl32.c linux-2.4.25-rc1/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.25-pre8/arch/sparc64/kernel/ioctl32.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.25-rc1/arch/sparc64/kernel/ioctl32.c	2004-02-05 04:40:35.000000000 -0800
@@ -4524,7 +4524,6 @@
 /* Big T */
 COMPATIBLE_IOCTL(TUNSETNOCSUM)
 COMPATIBLE_IOCTL(TUNSETDEBUG)
-COMPATIBLE_IOCTL(TUNSETIFF)
 COMPATIBLE_IOCTL(TUNSETPERSIST)
 COMPATIBLE_IOCTL(TUNSETOWNER)
 /* Big V */
@@ -5146,6 +5145,7 @@
 HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
 HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
+HANDLE_IOCTL(TUNSETIFF, dev_ifsioc)
 HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl)
 HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl)
 HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl)
diff -urN linux-2.4.25-pre8/arch/sparc64/kernel/setup.c linux-2.4.25-rc1/arch/sparc64/kernel/setup.c
--- linux-2.4.25-pre8/arch/sparc64/kernel/setup.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.25-rc1/arch/sparc64/kernel/setup.c	2004-02-05 04:40:35.000000000 -0800
@@ -40,6 +40,7 @@
 #include <asm/head.h>
 #include <asm/starfire.h>
 #include <asm/hardirq.h>
+#include <asm/sections.h>
 
 #ifdef CONFIG_IP_PNP
 #include <net/ipconfig.h>
@@ -456,7 +457,7 @@
 char saved_command_line[256];
 char reboot_command[256];
 
-extern unsigned long phys_base;
+extern unsigned long phys_base, kern_base, kern_size;
 
 static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
 
@@ -527,6 +528,22 @@
 			highest_paddr = top;
 	}
 
+	switch (tlb_type) {
+	default:
+	case spitfire:
+		kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent());
+		kern_base &= _PAGE_PADDR_SF;
+		break;
+
+	case cheetah:
+	case cheetah_plus:
+		kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
+		kern_base &= _PAGE_PADDR;
+		break;
+	};
+
+	kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
+
 	if (!root_flags)
 		root_mountflags &= ~MS_RDONLY;
 	ROOT_DEV = to_kdev_t(root_dev);
diff -urN linux-2.4.25-pre8/arch/sparc64/mm/init.c linux-2.4.25-rc1/arch/sparc64/mm/init.c
--- linux-2.4.25-pre8/arch/sparc64/mm/init.c	2004-02-05 04:40:31.000000000 -0800
+++ linux-2.4.25-rc1/arch/sparc64/mm/init.c	2004-02-05 04:40:35.000000000 -0800
@@ -34,6 +34,7 @@
 #include <asm/starfire.h>
 #include <asm/tlb.h>
 #include <asm/spitfire.h>
+#include <asm/sections.h>
 
 mmu_gather_t mmu_gathers[NR_CPUS];
 
@@ -44,7 +45,16 @@
 unsigned long *sparc64_valid_addr_bitmap;
 
 /* Ugly, but necessary... -DaveM */
-unsigned long phys_base;
+unsigned long phys_base, kern_base, kern_size;
+
+/* This is even uglier. We have a problem where the kernel may not be
+ * located at phys_base. However, initial __alloc_bootmem() calls need to
+ * be adjusted to be within the 4-8Megs that the kernel is mapped to, else
+ * those page mappings wont work. Things are ok after inherit_prom_mappings
+ * is called though. Dave says he'll clean this up some other time.
+ * -- BenC
+ */
+static unsigned long bootmap_base;
 
 /* get_new_mmu_context() uses "cache + 1".  */
 spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
@@ -52,9 +62,6 @@
 #define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
 unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
 
-/* References to section boundaries */
-extern char __init_begin, __init_end, _start, _end, etext, edata;
-
 /* Initial ramdisk setup */
 extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
@@ -344,7 +351,7 @@
 	n += 5 * sizeof(struct linux_prom_translation);
 	for (tsz = 1; tsz < n; tsz <<= 1)
 		/* empty */;
-	trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, 0UL);
+	trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base);
 	if (trans == NULL) {
 		prom_printf("inherit_prom_mappings: Cannot alloc translations.\n");
 		prom_halt();
@@ -364,7 +371,7 @@
 	 * in inherit_locked_prom_mappings()).
 	 */
 #define OBP_PMD_SIZE 2048
-	prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, 0UL);
+	prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base);
 	if (prompmd == NULL)
 		early_pgtable_allocfail("pmd");
 	memset(prompmd, 0, OBP_PMD_SIZE);
@@ -382,7 +389,7 @@
 				if (pmd_none(*pmdp)) {
 					ptep = __alloc_bootmem(BASE_PAGE_SIZE,
 							       BASE_PAGE_SIZE,
-							       0UL);
+							       bootmap_base);
 					if (ptep == NULL)
 						early_pgtable_allocfail("pte");
 					memset(ptep, 0, BASE_PAGE_SIZE);
@@ -1236,15 +1243,8 @@
 	 * image.  The kernel is hard mapped below PAGE_OFFSET in a
 	 * 4MB locked TLB translation.
 	 */
-	start_pfn  = PAGE_ALIGN((unsigned long) &_end) -
-		((unsigned long) KERNBASE);
+	start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT;
 
-	/* Adjust up to the physical address where the kernel begins. */
-	start_pfn += phys_base;
-
-	/* Now shift down to get the real physical page frame number. */
-	start_pfn >>= PAGE_SHIFT;
-	
 	bootmap_pfn = start_pfn;
 
 	end_pfn = end_of_phys_memory >> PAGE_SHIFT;
@@ -1274,10 +1274,12 @@
 	min_low_pfn = phys_base >> PAGE_SHIFT;
 
 #ifdef CONFIG_DEBUG_BOOTMEM
-	prom_printf("init_bootmem(spfn[%lx], bpfn[%lx], mlpfn[%lx])\n",
-		    start_pfn, bootmap_pfn, max_low_pfn);
+	prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n",
+		    min_low_pfn, bootmap_pfn, max_low_pfn);
 #endif
-	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, phys_base>>PAGE_SHIFT, end_pfn);
+	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, min_low_pfn, end_pfn);
+
+	bootmap_base = bootmap_pfn << PAGE_SHIFT;
 
 	/* Now register the available physical memory with the
 	 * allocator.
@@ -1287,8 +1289,7 @@
 		prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n",
 			    i, sp_banks[i].base_addr, sp_banks[i].num_bytes);
 #endif
-		free_bootmem(sp_banks[i].base_addr,
-			     sp_banks[i].num_bytes);
+		free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes);
 	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -1307,12 +1308,11 @@
 	}
 #endif
 	/* Reserve the kernel text/data/bss. */
-	size = (start_pfn << PAGE_SHIFT) - phys_base;
 #ifdef CONFIG_DEBUG_BOOTMEM
-	prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", phys_base, size);
+	prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size);
 #endif
-	reserve_bootmem(phys_base, size);
-	*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+	reserve_bootmem(kern_base, kern_size);
+	*pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
 
 	/* Reserve the bootmem map.   We do not account for it
 	 * in pages_avail because we will release that memory
@@ -1341,7 +1341,7 @@
 	extern pmd_t swapper_pmd_dir[1024];
 	extern unsigned int sparc64_vpte_patchme1[1];
 	extern unsigned int sparc64_vpte_patchme2[1];
-	unsigned long alias_base = phys_base + PAGE_OFFSET;
+	unsigned long alias_base = kern_base + PAGE_OFFSET;
 	unsigned long second_alias_page = 0;
 	unsigned long pt, flags, end_pfn, pages_avail;
 	unsigned long shift = alias_base - ((unsigned long)KERNBASE);
@@ -1361,7 +1361,7 @@
 	 * if this were not true we wouldn't boot up to this point
 	 * anyways.
 	 */
-	pt  = phys_base | _PAGE_VALID | _PAGE_SZ4MB;
+	pt  = kern_base | _PAGE_VALID | _PAGE_SZ4MB;
 	pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
 	__save_and_cli(flags);
 	if (tlb_type == spitfire) {
@@ -1441,14 +1441,6 @@
 	pages_avail = 0;
 	last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
 
-#ifdef CONFIG_SUN_SERIAL
-	/* This does not logically belong here, but we need to
-	 * call it at the moment we are able to use the bootmem
-	 * allocator.
-	 */
-	sun_serial_setup();
-#endif
-
 	/* Inherit non-locked OBP mappings. */
 	inherit_prom_mappings();
 	
@@ -1463,7 +1455,16 @@
 	}
 
 	inherit_locked_prom_mappings(1);
-	
+
+#ifdef CONFIG_SUN_SERIAL
+	/* This does not logically belong here, but we need to call it at
+	 * the moment we are able to use the bootmem allocator. This _has_
+	 * to be done after the prom_mappings above so since
+	 * __alloc_bootmem() doesn't work correctly until then.
+	 */
+	sun_serial_setup();
+#endif
+
 	/* We only created DTLB mapping of this stuff. */
 	spitfire_flush_dtlb_nucleus_page(alias_base);
 	if (second_alias_page)
@@ -1633,17 +1634,15 @@
 	i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
 	i += 1;
 	sparc64_valid_addr_bitmap = (unsigned long *)
-		__alloc_bootmem(i << 3, SMP_CACHE_BYTES, 0UL);
+		__alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base);
 	if (sparc64_valid_addr_bitmap == NULL) {
 		prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
 		prom_halt();
 	}
 	memset(sparc64_valid_addr_bitmap, 0, i << 3);
 
-	addr = PAGE_OFFSET + phys_base;
-	last = PAGE_ALIGN((unsigned long)&_end) -
-		((unsigned long) KERNBASE);
-	last += PAGE_OFFSET + phys_base;
+	addr = PAGE_OFFSET + kern_base;
+	last = PAGE_ALIGN(kern_size) + addr;
 	while (addr < last) {
 		set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
 		addr += PAGE_SIZE;
@@ -1683,7 +1682,7 @@
 		/* Put empty_pg_dir on pgd_quicklist */
 		extern pgd_t empty_pg_dir[1024];
 		unsigned long addr = (unsigned long)empty_pg_dir;
-		unsigned long alias_base = phys_base + PAGE_OFFSET -
+		unsigned long alias_base = kern_base + PAGE_OFFSET -
 			(long)(KERNBASE);
 		
 		memset(empty_pg_dir, 0, sizeof(empty_pg_dir));
@@ -1718,7 +1717,7 @@
 		struct page *p;
 
 		page = (addr +
-			((unsigned long) __va(phys_base)) -
+			((unsigned long) __va(kern_base)) -
 			((unsigned long) KERNBASE));
 		p = virt_to_page(page);
 
diff -urN linux-2.4.25-pre8/crypto/sha256.c linux-2.4.25-rc1/crypto/sha256.c
--- linux-2.4.25-pre8/crypto/sha256.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.25-rc1/crypto/sha256.c	2004-02-05 04:40:35.000000000 -0800
@@ -34,12 +34,12 @@
 
 static inline u32 Ch(u32 x, u32 y, u32 z)
 {
-	return ((x & y) ^ (~x & z));
+	return z ^ (x & (y ^ z));
 }
 
 static inline u32 Maj(u32 x, u32 y, u32 z)
 {
-	return ((x & y) ^ (x & z) ^ (y & z));
+	return (x & y) | (z & (x | y));
 }
 
 static inline u32 RORu32(u32 x, u32 y)
@@ -295,7 +295,7 @@
 	u8 bits[8];
 	unsigned int index, pad_len, t;
 	int i, j;
-	const u8 padding[64] = { 0x80, };
+	static u8 padding[64] = { 0x80, };
 
 	/* Save number of bits */
 	t = sctx->count[0];
diff -urN linux-2.4.25-pre8/crypto/sha512.c linux-2.4.25-rc1/crypto/sha512.c
--- linux-2.4.25-pre8/crypto/sha512.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.25-rc1/crypto/sha512.c	2004-02-05 04:40:35.000000000 -0800
@@ -34,12 +34,12 @@
 
 static inline u64 Ch(u64 x, u64 y, u64 z)
 {
-        return ((x & y) ^ (~x & z));
+        return z ^ (x & (y ^ z));
 }
 
 static inline u64 Maj(u64 x, u64 y, u64 z)
 {
-        return ((x & y) ^ (x & z) ^ (y & z));
+        return (x & y) | (z & (x | y));
 }
 
 static inline u64 RORu64(u64 x, u64 y)
@@ -249,7 +249,7 @@
 {
         struct sha512_ctx *sctx = ctx;
 	
-        const static u8 padding[128] = { 0x80, };
+        static u8 padding[128] = { 0x80, };
 
         u32 t;
 	u64 t2;
diff -urN linux-2.4.25-pre8/drivers/atm/idt77252.c linux-2.4.25-rc1/drivers/atm/idt77252.c
--- linux-2.4.25-pre8/drivers/atm/idt77252.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.25-rc1/drivers/atm/idt77252.c	2004-02-05 04:40:35.000000000 -0800
@@ -665,8 +665,8 @@
 	skb_queue_head_init(&scq->transmit);
 	skb_queue_head_init(&scq->pending);
 
-	TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08x\n",
-		 scq->base, scq->next, scq->last, scq->paddr);
+	TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08llx\n",
+		 scq->base, scq->next, scq->last, (unsigned long long)scq->paddr);
 
 	return scq;
 }
diff -urN linux-2.4.25-pre8/drivers/char/agp/agpgart_be.c linux-2.4.25-rc1/drivers/char/agp/agpgart_be.c
--- linux-2.4.25-pre8/drivers/char/agp/agpgart_be.c	2004-02-05 04:40:31.000000000 -0800
+++ linux-2.4.25-rc1/drivers/char/agp/agpgart_be.c	2004-02-05 04:40:35.000000000 -0800
@@ -5644,7 +5644,7 @@
 #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
 	GET_PAGE_DIR_OFF(agp_bridge.gart_bus_addr))
 #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
-#undef  GET_GATT(addr)
+#undef  GET_GATT
 #define GET_GATT(addr) (ati_generic_private.gatt_pages[\
 	GET_PAGE_DIR_IDX(addr)]->remapped)
 
diff -urN linux-2.4.25-pre8/drivers/char/amd76x_pm.c linux-2.4.25-rc1/drivers/char/amd76x_pm.c
--- linux-2.4.25-pre8/drivers/char/amd76x_pm.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/char/amd76x_pm.c	2004-02-05 04:40:35.000000000 -0800
@@ -474,7 +474,7 @@
 }
 #endif
 
-
+#ifdef AMD76X_POS
 /*
  * Activate sleep state via its ACPI register (PM1_CNT).
  */
@@ -489,8 +489,6 @@
 	outw(regshort, amd76x_pm_cfg.slp_reg);
 }
 
-
-#ifdef AMD76X_POS
 /*
  * Wrapper function to activate POS sleep state.
  */
diff -urN linux-2.4.25-pre8/drivers/char/tipar.c linux-2.4.25-rc1/drivers/char/tipar.c
--- linux-2.4.25-pre8/drivers/char/tipar.c	2003-06-13 07:51:33.000000000 -0700
+++ linux-2.4.25-rc1/drivers/char/tipar.c	2004-02-05 04:40:36.000000000 -0800
@@ -71,9 +71,11 @@
 #define DRIVER_DESC    "Device driver for TI/PC parallel link cables"
 #define DRIVER_LICENSE "GPL"
 
-#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
-#if LINUX_VERSION_CODE < VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
 # define minor(x) MINOR(x)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 # define need_resched() (current->need_resched)
 #endif
 
diff -urN linux-2.4.25-pre8/drivers/char/vac-serial.c linux-2.4.25-rc1/drivers/char/vac-serial.c
--- linux-2.4.25-pre8/drivers/char/vac-serial.c	2003-08-25 04:44:41.000000000 -0700
+++ linux-2.4.25-rc1/drivers/char/vac-serial.c	2004-02-05 04:40:36.000000000 -0800
@@ -10,7 +10,9 @@
 #define CONFIG_SERIAL_NOPAUSE_IO
 #define SERIAL_DO_RESTART
 
+#ifndef CONFIG_SERIAL_SHARE_IRQ
 #define CONFIG_SERIAL_SHARE_IRQ
+#endif
 
 /* Set of debugging defines */
 
diff -urN linux-2.4.25-pre8/drivers/ieee1394/csr.c linux-2.4.25-rc1/drivers/ieee1394/csr.c
--- linux-2.4.25-pre8/drivers/ieee1394/csr.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/ieee1394/csr.c	2004-02-05 04:40:36.000000000 -0800
@@ -117,7 +117,7 @@
 	/* Just to keep from rounding low */
 	csr->expire++;
 
-	HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%lu", csr->expire, HZ);
+	HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%d", csr->expire, HZ);
 }
 
 
diff -urN linux-2.4.25-pre8/drivers/isdn/hisax/amd7930_fn.c linux-2.4.25-rc1/drivers/isdn/hisax/amd7930_fn.c
--- linux-2.4.25-pre8/drivers/isdn/hisax/amd7930_fn.c	2002-11-28 15:53:13.000000000 -0800
+++ linux-2.4.25-rc1/drivers/isdn/hisax/amd7930_fn.c	2004-02-05 04:40:36.000000000 -0800
@@ -61,6 +61,40 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
+static WORD initAMD[] __devinit = {
+	0x0100,
+
+	0x00A5, 3, 0x01, 0x40, 0x58,				// LPR, LMR1, LMR2
+	0x0086, 1, 0x0B,					// DMR1 (D-Buffer TH-Interrupts on)
+	0x0087, 1, 0xFF,					// DMR2
+	0x0092, 1, 0x03,					// EFCR (extended mode d-channel-fifo on)
+	0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F,			// FRAR4, SRAR4, DMR3, DMR4 (address recognition )
+	0x0084, 2, 0x80, 0x00,					// DRLR
+	0x00C0, 1, 0x47,					// PPCR1
+	0x00C8, 1, 0x01,					// PPCR2
+
+	0x0102,
+	0x0107,
+	0x01A1, 1,
+	0x0121, 1,
+	0x0189, 2,
+
+	0x0045, 4, 0x61, 0x72, 0x00, 0x00,			// MCR1, MCR2, MCR3, MCR4
+	0x0063, 2, 0x08, 0x08,					// GX
+	0x0064, 2, 0x08, 0x08,					// GR
+	0x0065, 2, 0x99, 0x00,					// GER
+	0x0066, 2, 0x7C, 0x8B,					// STG
+	0x0067, 2, 0x00, 0x00,					// FTGR1, FTGR2
+	0x0068, 2, 0x20, 0x20,					// ATGR1, ATGR2
+	0x0069, 1, 0x4F,					// MMR1
+	0x006A, 1, 0x00,					// MMR2
+	0x006C, 1, 0x40,					// MMR3
+	0x0021, 1, 0x02,					// INIT
+	0x00A3, 1, 0x40,					// LMR1
+
+	0xFFFF};
+
+
 static void Amd7930_new_ph(struct IsdnCardState *cs);
 
 
diff -urN linux-2.4.25-pre8/drivers/isdn/hisax/amd7930_fn.h linux-2.4.25-rc1/drivers/isdn/hisax/amd7930_fn.h
--- linux-2.4.25-pre8/drivers/isdn/hisax/amd7930_fn.h	2002-11-28 15:53:13.000000000 -0800
+++ linux-2.4.25-rc1/drivers/isdn/hisax/amd7930_fn.h	2004-02-05 04:40:36.000000000 -0800
@@ -32,38 +32,5 @@
 
 #define DBUSY_TIMER_VALUE 80
 
-static WORD initAMD[] = {
-	0x0100,
-
-	0x00A5, 3, 0x01, 0x40, 0x58,				// LPR, LMR1, LMR2
-	0x0086, 1, 0x0B,					// DMR1 (D-Buffer TH-Interrupts on)
-	0x0087, 1, 0xFF,					// DMR2
-	0x0092, 1, 0x03,					// EFCR (extended mode d-channel-fifo on)
-	0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F,			// FRAR4, SRAR4, DMR3, DMR4 (address recognition )
-	0x0084, 2, 0x80, 0x00,					// DRLR
-	0x00C0, 1, 0x47,					// PPCR1
-	0x00C8, 1, 0x01,					// PPCR2
-
-	0x0102,
-	0x0107,
-	0x01A1, 1,
-	0x0121, 1,
-	0x0189, 2,
-
-	0x0045, 4, 0x61, 0x72, 0x00, 0x00,			// MCR1, MCR2, MCR3, MCR4
-	0x0063, 2, 0x08, 0x08,					// GX
-	0x0064, 2, 0x08, 0x08,					// GR
-	0x0065, 2, 0x99, 0x00,					// GER
-	0x0066, 2, 0x7C, 0x8B,					// STG
-	0x0067, 2, 0x00, 0x00,					// FTGR1, FTGR2
-	0x0068, 2, 0x20, 0x20,					// ATGR1, ATGR2
-	0x0069, 1, 0x4F,					// MMR1
-	0x006A, 1, 0x00,					// MMR2
-	0x006C, 1, 0x40,					// MMR3
-	0x0021, 1, 0x02,					// INIT
-	0x00A3, 1, 0x40,					// LMR1
-
-	0xFFFF};
-
 extern void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags);
 extern void Amd7930_init(struct IsdnCardState *cs);
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100.h linux-2.4.25-rc1/drivers/net/e100/e100.h
--- linux-2.4.25-pre8/drivers/net/e100/e100.h	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/e100/e100.h	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_config.c linux-2.4.25-rc1/drivers/net/e100/e100_config.c
--- linux-2.4.25-pre8/drivers/net/e100/e100_config.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/e100/e100_config.c	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -60,7 +60,7 @@
  * All other init functions will only set values that are
  * different from the 82557 default.
  */
-void __devinit
+void
 e100_config_init_82557(struct e100_private *bdp)
 {
 	/* initialize config block */
@@ -104,7 +104,7 @@
 	e100_config_mulcast_enbl(bdp, false);
 }
 
-static void __devinit
+static void
 e100_config_init_82558(struct e100_private *bdp)
 {
 	/* MWI enable. This should be turned on only if the adapter is a 82558/9
@@ -136,7 +136,7 @@
 	e100_config_long_rx(bdp, true);
 }
 
-static void __devinit
+static void
 e100_config_init_82550(struct e100_private *bdp)
 {
 	/* The D102 chip allows for 32 config bytes.  This value is
@@ -160,7 +160,7 @@
 }
 
 /* Initialize the adapter's configure block */
-void __devinit
+void
 e100_config_init(struct e100_private *bdp)
 {
 	e100_config_init_82557(bdp);
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_config.h linux-2.4.25-rc1/drivers/net/e100/e100_config.h
--- linux-2.4.25-pre8/drivers/net/e100/e100_config.h	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/e100/e100_config.h	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_eeprom.c linux-2.4.25-rc1/drivers/net/e100/e100_eeprom.c
--- linux-2.4.25-pre8/drivers/net/e100/e100_eeprom.c	2003-06-13 07:51:34.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/e100/e100_eeprom.c	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_main.c linux-2.4.25-rc1/drivers/net/e100/e100_main.c
--- linux-2.4.25-pre8/drivers/net/e100/e100_main.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/e100/e100_main.c	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -46,20 +46,20 @@
 
 /* Change Log
  * 
- * 2.3.30       09/21/03
+ * 2.3.38       12/14/03
+ * o Added netpoll support.
+ * o Added ICH6 device ID support
+ * o Moved to 2.6 APIs: pci_name() and free_netdev().
+ * o Removed some __devinit from some functions that shouldn't be marked
+ *   as such (Anton Blanchard [anton@samba.org]).
+ * 
+ * 2.3.33       10/21/03
  * o Bug fix (Bugzilla 97908): Loading e100 was causing crash on Itanium2
  *   with HP chipset
  * o Bug fix (Bugzilla 101583): e100 can't pass traffic with ipv6
  * o Bug fix (Bugzilla 101360): PRO/10+ can't pass traffic
  * 
  * 2.3.27       08/08/03
- * o Bug fix: read skb->len after freeing skb
- *   [Andrew Morton] akpm@zip.com.au
- * o Bug fix: 82557 (with National PHY) timeout during init
- *   [Adam Kropelin] akropel1@rochester.rr.com
- * o Feature add: allow to change Wake On LAN when EEPROM disabled
- * 
- * 2.3.13       05/08/03
  */
  
 #include <linux/config.h>
@@ -80,7 +80,14 @@
 	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
 	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
 	"tx_heartbeat_errors", "tx_window_errors",
+	/* device-specific stats */
+	"tx_late_collision_errors", "tx_deferred", 
+	"tx_single_collisions", "tx_multi_collisions", 
+	"rx_collision_detected_errors", "tx_flow_control_pause",
+	"rx_flow_control_pause", "rx_flow_control_unsupported",
+	"tx_tco_packets", "rx_tco_packets",
 };
+#define E100_NET_STATS_LEN	21
 #define E100_STATS_LEN	sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN
 
 static int e100_do_ethtool_ioctl(struct net_device *, struct ifreq *);
@@ -124,8 +131,8 @@
 static void e100_non_tx_background(unsigned long);
 static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
 /* Global Data structures and variables */
-char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";
-char e100_driver_version[]="2.3.30-k1";
+char e100_copyright[] __devinitdata = "Copyright (c) 2004 Intel Corporation";
+char e100_driver_version[]="2.3.38-k1";
 const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
 char e100_short_driver_name[] = "e100";
 static int e100nics = 0;
@@ -134,6 +141,11 @@
 static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
 static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/* for netdump / net console */
+static void e100_netpoll (struct net_device *dev);
+#endif
+
 #ifdef CONFIG_PM
 static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
 static int e100_suspend(struct pci_dev *pcid, u32 state);
@@ -598,6 +610,8 @@
 	       && (bdp->pdev->device < 0x103F))
 	    || ((bdp->pdev->device >= 0x1050)
 	       && (bdp->pdev->device <= 0x1057))
+	    || ((bdp->pdev->device >= 0x1064)
+	       && (bdp->pdev->device <= 0x106B))
 	    || (bdp->pdev->device == 0x2449)
 	    || (bdp->pdev->device == 0x2459)
 	    || (bdp->pdev->device == 0x245D)) {
@@ -631,6 +645,10 @@
 	dev->set_mac_address = &e100_set_mac;
 	dev->do_ioctl = &e100_ioctl;
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = e100_netpoll;
+#endif
+
 	if (bdp->flags & USE_IPCB)
 	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
 			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
@@ -695,7 +713,7 @@
 	pci_disable_device(pcid);
 err_dev:
 	pci_set_drvdata(pcid, NULL);
-	kfree(dev);
+	free_netdev(dev);
 out:
 	return rc;
 }
@@ -717,7 +735,7 @@
 
 	e100_dealloc_space(bdp);
 	pci_set_drvdata(bdp->pdev, NULL);
-	kfree(dev);
+	free_netdev(dev);
 }
 
 static void __devexit
@@ -746,7 +764,7 @@
 	--e100nics;
 }
 
-static struct pci_device_id e100_id_table[] __devinitdata = {
+static struct pci_device_id e100_id_table[] = {
 	{0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -770,6 +788,14 @@
 	{0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1066, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1067, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1069, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x106A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x106B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0,} /* This has to be the last entry*/
@@ -1317,7 +1343,7 @@
 	return 1;
 }
 
-static void __devinit
+static void
 e100_tco_workaround(struct e100_private *bdp)
 {
 	int i;
@@ -2507,7 +2533,7 @@
  *      true: if successfully cleared stat counters
  *      false: otherwise
  */
-static unsigned char __devinit
+static unsigned char
 e100_clr_cntrs(struct e100_private *bdp)
 {
 	volatile u32 *pcmd_complete;
@@ -3176,9 +3202,19 @@
 		void *addr = ifr->ifr_data;
 		int i;
 
-		for(i = 0; i < E100_STATS_LEN; i++)
+		for(i = 0; i < E100_NET_STATS_LEN; i++)
 			stats.data[i] =
 				((unsigned long *)&bdp->drv_stats.net_stats)[i];
+		stats.data[i++] = bdp->drv_stats.tx_late_col;
+		stats.data[i++] = bdp->drv_stats.tx_ok_defrd;
+		stats.data[i++] = bdp->drv_stats.tx_one_retry;
+		stats.data[i++] = bdp->drv_stats.tx_mt_one_retry;
+		stats.data[i++] = bdp->drv_stats.rcv_cdt_frames;
+		stats.data[i++] = bdp->drv_stats.xmt_fc_pkts;
+		stats.data[i++] = bdp->drv_stats.rcv_fc_pkts;
+		stats.data[i++] = bdp->drv_stats.rcv_fc_unsupported;
+		stats.data[i++] = bdp->drv_stats.xmt_tco_pkts;
+		stats.data[i++] = bdp->drv_stats.rcv_tco_pkts;
 		if(copy_to_user(addr, &stats, sizeof(stats)))
 			return -EFAULT;
 		return 0;
@@ -3582,7 +3618,7 @@
 	strncpy(info.version, e100_driver_version, sizeof (info.version) - 1);
 	strncpy(info.fw_version, "N/A",
 		sizeof (info.fw_version) - 1);
-	strncpy(info.bus_info, bdp->pdev->slot_name,
+	strncpy(info.bus_info, pci_name(bdp->pdev),
 		sizeof (info.bus_info) - 1);
 	info.n_stats = E100_STATS_LEN;
 	info.regdump_len  = E100_REGS_LEN * sizeof(u32);
@@ -4340,3 +4376,18 @@
 }
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void e100_netpoll (struct net_device *dev)
+{
+	struct e100_private *adapter = dev->priv;
+	disable_irq(adapter->pdev->irq);
+	e100intr (adapter->pdev->irq, dev, NULL);
+	enable_irq(adapter->pdev->irq);
+}
+#endif
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_phy.c linux-2.4.25-rc1/drivers/net/e100/e100_phy.c
--- linux-2.4.25-pre8/drivers/net/e100/e100_phy.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/e100/e100_phy.c	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -132,7 +132,7 @@
 	}
 }
 
-static unsigned char __devinit
+static unsigned char
 e100_phy_valid(struct e100_private *bdp, unsigned int phy_address)
 {
 	u16 ctrl_reg, stat_reg;
@@ -150,7 +150,7 @@
 	return true;
 }
 
-static void __devinit
+static void
 e100_phy_address_detect(struct e100_private *bdp)
 {
 	unsigned int addr;
@@ -180,7 +180,7 @@
 	}
 }
 
-static void __devinit
+static void
 e100_phy_id_detect(struct e100_private *bdp)
 {
 	u16 low_id_reg, high_id_reg;
@@ -204,7 +204,7 @@
 		      ((unsigned int) high_id_reg << 16));
 }
 
-static void __devinit
+static void
 e100_phy_isolate(struct e100_private *bdp)
 {
 	unsigned int phy_address;
@@ -227,7 +227,7 @@
 	}
 }
 
-static unsigned char __devinit
+static unsigned char
 e100_phy_specific_setup(struct e100_private *bdp)
 {
 	u16 misc_reg;
@@ -380,7 +380,7 @@
  * Returns:
  *	NOTHING
  */
-static void __devinit
+static void
 e100_fix_polarity(struct e100_private *bdp)
 {
 	u16 status;
@@ -916,7 +916,7 @@
 	schedule_timeout(HZ / 2);
 }
 
-unsigned char __devinit
+unsigned char
 e100_phy_init(struct e100_private *bdp)
 {
 	e100_phy_reset(bdp);
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_phy.h linux-2.4.25-rc1/drivers/net/e100/e100_phy.h
--- linux-2.4.25-pre8/drivers/net/e100/e100_phy.h	2003-06-13 07:51:34.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/e100/e100_phy.h	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_test.c linux-2.4.25-rc1/drivers/net/e100/e100_test.c
--- linux-2.4.25-pre8/drivers/net/e100/e100_test.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/e100/e100_test.c	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff -urN linux-2.4.25-pre8/drivers/net/e100/e100_ucode.h linux-2.4.25-rc1/drivers/net/e100/e100_ucode.h
--- linux-2.4.25-pre8/drivers/net/e100/e100_ucode.h	2003-06-13 07:51:34.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/e100/e100_ucode.h	2004-02-05 04:40:36.000000000 -0800
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff -urN linux-2.4.25-pre8/drivers/net/irda/act200l.c linux-2.4.25-rc1/drivers/net/irda/act200l.c
--- linux-2.4.25-pre8/drivers/net/irda/act200l.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/irda/act200l.c	2004-02-05 04:40:36.000000000 -0800
@@ -94,12 +94,12 @@
 	act200l_change_speed,
 };
 
-int __init act200l_init(void)
+static int __init act200l_init(void)
 {
 	return irda_device_register_dongle(&dongle);
 }
 
-void __exit act200l_cleanup(void)
+static void __exit act200l_cleanup(void)
 {
 	irda_device_unregister_dongle(&dongle);
 }
diff -urN linux-2.4.25-pre8/drivers/net/irda/irda-usb.c linux-2.4.25-rc1/drivers/net/irda/irda-usb.c
--- linux-2.4.25-pre8/drivers/net/irda/irda-usb.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/irda/irda-usb.c	2004-02-05 04:40:36.000000000 -0800
@@ -1584,7 +1584,7 @@
 /*
  * Module insertion
  */
-int __init usb_irda_init(void)
+static int __init usb_irda_init(void)
 {
 	if (usb_register(&irda_driver) < 0)
 		return -1;
@@ -1598,7 +1598,7 @@
 /*
  * Module removal
  */
-void __exit usb_irda_cleanup(void)
+static void __exit usb_irda_cleanup(void)
 {
 	struct irda_usb_cb *irda = NULL;
 	int	i;
diff -urN linux-2.4.25-pre8/drivers/net/irda/ma600.c linux-2.4.25-rc1/drivers/net/irda/ma600.c
--- linux-2.4.25-pre8/drivers/net/irda/ma600.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/irda/ma600.c	2004-02-05 04:40:36.000000000 -0800
@@ -84,13 +84,13 @@
 	ma600_change_speed,
 };
 
-int __init ma600_init(void)
+static int __init ma600_init(void)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 	return irda_device_register_dongle(&dongle);
 }
 
-void __exit ma600_cleanup(void)
+static void __exit ma600_cleanup(void)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 	irda_device_unregister_dongle(&dongle);
diff -urN linux-2.4.25-pre8/drivers/net/irda/smc-ircc.c linux-2.4.25-rc1/drivers/net/irda/smc-ircc.c
--- linux-2.4.25-pre8/drivers/net/irda/smc-ircc.c	2003-06-13 07:51:35.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/irda/smc-ircc.c	2004-02-05 04:40:36.000000000 -0800
@@ -1210,7 +1210,7 @@
 	return ircc_init();
 }
 
-void __exit smc_cleanup(void)
+static void __exit smc_cleanup(void)
 {
 	int i;
 
diff -urN linux-2.4.25-pre8/drivers/net/irda/via-ircc.c linux-2.4.25-rc1/drivers/net/irda/via-ircc.c
--- linux-2.4.25-pre8/drivers/net/irda/via-ircc.c	2004-02-05 04:40:31.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/irda/via-ircc.c	2004-02-05 04:40:36.000000000 -0800
@@ -146,7 +146,7 @@
  *
  *    Initialize chip. Just find out chip type and resource.
  */
-int __devinit via_ircc_init(void)
+static int __devinit via_ircc_init(void)
 {
 	int rc;
 
diff -urN linux-2.4.25-pre8/drivers/net/sk98lin/h/skversion.h linux-2.4.25-rc1/drivers/net/sk98lin/h/skversion.h
--- linux-2.4.25-pre8/drivers/net/sk98lin/h/skversion.h	2004-02-05 04:40:31.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/sk98lin/h/skversion.h	2004-02-05 04:40:36.000000000 -0800
@@ -61,14 +61,14 @@
 #ifdef	lint
 static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
 static const char SysKonnectBuildNumber[] =
-	"@(#)SK-BUILD: 6.21 PL: 01"; 
+	"@(#)SK-BUILD: 6.22 PL: 01"; 
 #endif	/* !defined(lint) */
 
-#define BOOT_STRING	"sk98lin: Network Device Driver v6.21\n" \
-			"(C)Copyright 1999-2003 Marvell(R)."
+#define BOOT_STRING	"sk98lin: Network Device Driver v6.22\n" \
+			"(C)Copyright 1999-2004 Marvell(R)."
 
-#define VER_STRING	"6.21"
+#define VER_STRING	"6.22"
 #define DRIVER_FILE_NAME	"sk98lin"
-#define DRIVER_REL_DATE		"Dec-15-2003"
+#define DRIVER_REL_DATE		"Jan-30-2004"
 
 
diff -urN linux-2.4.25-pre8/drivers/net/sk98lin/skge.c linux-2.4.25-rc1/drivers/net/sk98lin/skge.c
--- linux-2.4.25-pre8/drivers/net/sk98lin/skge.c	2004-02-05 04:40:31.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/sk98lin/skge.c	2004-02-05 04:40:36.000000000 -0800
@@ -2,8 +2,8 @@
  *
  * Name:	skge.c
  * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.42 $
- * Date:       	$Date: 2003/12/12 10:05:43 $
+ * Version:	$Revision: 1.43 $
+ * Date:       	$Date: 2004/01/29 15:47:07 $
  * Purpose:	The main driver source module
  *
  ******************************************************************************/
@@ -41,6 +41,9 @@
  * History:
  *
  *	$Log: skge.c,v $
+ *	Revision 1.43  2004/01/29 15:47:07  mlindner
+ *	Fix: Reset Xmac when stopping the port
+ *	
  *	Revision 1.42  2003/12/12 10:05:43  mlindner
  *	Fix: Format of error message corrected
  *	
@@ -2147,6 +2150,7 @@
 		EvPara.Para32[0] = pNet->NetNr;
 		EvPara.Para32[1] = -1;
 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+		SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
 		SkEventDispatcher(pAC, pAC->IoBase);
 		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
 		
@@ -4995,6 +4999,7 @@
 		spin_lock_irqsave(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
+
 		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
 		pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
 		spin_unlock_irqrestore(
diff -urN linux-2.4.25-pre8/drivers/net/tg3.c linux-2.4.25-rc1/drivers/net/tg3.c
--- linux-2.4.25-pre8/drivers/net/tg3.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/drivers/net/tg3.c	2004-02-05 04:40:36.000000000 -0800
@@ -55,8 +55,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"2.5"
-#define DRV_MODULE_RELDATE	"December 22, 2003"
+#define DRV_MODULE_VERSION	"2.6"
+#define DRV_MODULE_RELDATE	"February 3, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -5903,7 +5903,8 @@
 	GET_REG32_LOOP(MSGINT_MODE, 0x0c);
 	GET_REG32_1(DMAC_MODE);
 	GET_REG32_LOOP(GRC_MODE, 0x4c);
-	GET_REG32_LOOP(NVRAM_CMD, 0x24);
+	if (tp->tg3_flags & TG3_FLAG_NVRAM)
+		GET_REG32_LOOP(NVRAM_CMD, 0x24);
 
 #undef __GET_REG32
 #undef GET_REG32_LOOP
@@ -7190,26 +7191,33 @@
 	test_desc.addr_lo = buf_dma & 0xffffffff;
 	test_desc.nic_mbuf = 0x00002100;
 	test_desc.len = size;
+
+	/*
+	 * HP ZX1 was seeing test failures for 5701 cards running at 33Mhz
+	 * the *second* time the tg3 driver was getting loaded after an
+	 * initial scan.
+	 *
+	 * Broadcom tells me:
+	 *   ...the DMA engine is connected to the GRC block and a DMA
+	 *   reset may affect the GRC block in some unpredictable way...
+	 *   The behavior of resets to individual blocks has not been tested.
+	 *
+	 * Broadcom noted the GRC reset will also reset all sub-components.
+	 */
 	if (to_device) {
 		test_desc.cqid_sqid = (13 << 8) | 2;
-		tw32(RDMAC_MODE, RDMAC_MODE_RESET);
-		tr32(RDMAC_MODE);
-		udelay(40);
 
 		tw32(RDMAC_MODE, RDMAC_MODE_ENABLE);
 		tr32(RDMAC_MODE);
 		udelay(40);
 	} else {
 		test_desc.cqid_sqid = (16 << 8) | 7;
-		tw32(WDMAC_MODE, WDMAC_MODE_RESET);
-		tr32(WDMAC_MODE);
-		udelay(40);
 
 		tw32(WDMAC_MODE, WDMAC_MODE_ENABLE);
 		tr32(WDMAC_MODE);
 		udelay(40);
 	}
-	test_desc.flags = 0x00000004;
+	test_desc.flags = 0x00000005;
 
 	for (i = 0; i < (sizeof(test_desc) / sizeof(u32)); i++) {
 		u32 val;
@@ -7368,9 +7376,19 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 		/* Remove this if it causes problems for some boards. */
 		tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT;
-	}
 
-	tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
+		/* On 5700/5701 chips, we need to set this bit.
+		 * Otherwise the chip will issue cacheline transactions
+		 * to streamable DMA memory with not all the byte
+		 * enables turned on.  This is an error on several
+		 * RISC PCI controllers, in particular sparc64.
+		 *
+		 * On 5703/5704 chips, this bit has been reassigned
+		 * a different meaning.  In particular, it is used
+		 * on those chips to enable a PCI-X workaround.
+		 */
+		tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
+	}
 
 	tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
 
@@ -7385,28 +7403,38 @@
 		goto out;
 
 	while (1) {
-		u32 *p, i;
+		u32 *p = buf, i;
 
-		p = buf;
 		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++)
 			p[i] = i;
 
 		/* Send the buffer to the chip. */
 		ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1);
-		if (ret)
+		if (ret) {
+			printk(KERN_ERR "tg3_test_dma() Write the buffer failed %d\n", ret);
 			break;
+		}
 
-		p = buf;
-		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++)
+		/* validate data reached card RAM correctly. */
+		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
+			u32 val;
+			tg3_read_mem(tp, 0x2100 + (i*4), &val);
+			if (val != p[i]) {
+				printk( KERN_ERR "  tg3_test_dma()  Card buffer currupted on write! (%d != %d)\n", val, i);
+				/* ret = -ENODEV here? */
+			}
 			p[i] = 0;
+		}
 
 		/* Now read it back. */
 		ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
-		if (ret)
+		if (ret) {
+			printk(KERN_ERR "tg3_test_dma() Read the buffer failed %d\n", ret);
+
 			break;
+		}
 
 		/* Verify it. */
-		p = buf;
 		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
 			if (p[i] == i)
 				continue;
@@ -7417,6 +7445,7 @@
 				tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
 				break;
 			} else {
+				printk(KERN_ERR "tg3_test_dma() buffer corrupted on read back! (%d != %d)\n", p[i], i);
 				ret = -ENODEV;
 				goto out;
 			}
diff -urN linux-2.4.25-pre8/drivers/net/wan/8253x/crc32dcl.h linux-2.4.25-rc1/drivers/net/wan/8253x/crc32dcl.h
--- linux-2.4.25-pre8/drivers/net/wan/8253x/crc32dcl.h	2002-08-02 17:39:44.000000000 -0700
+++ linux-2.4.25-rc1/drivers/net/wan/8253x/crc32dcl.h	2004-02-05 04:40:36.000000000 -0800
@@ -29,7 +29,6 @@
 /****************************************************/
 
 extern void	fn_init_crc_table(void);
-extern unsigned int	fn_calc_memory_chunk_crc32(void *p, unsigned int n_bytes, unsigned int crc);
 extern unsigned int	fn_calc_memory_crc32(void *p, unsigned int n_bytes);
 extern unsigned int	fn_check_memory_crc32(void *p, unsigned int n_bytes, unsigned int crc);
 
diff -urN linux-2.4.25-pre8/drivers/scsi/aha1542.c linux-2.4.25-rc1/drivers/scsi/aha1542.c
--- linux-2.4.25-pre8/drivers/scsi/aha1542.c	2001-10-12 15:35:53.000000000 -0700
+++ linux-2.4.25-rc1/drivers/scsi/aha1542.c	2004-02-05 04:40:36.000000000 -0800
@@ -111,8 +111,6 @@
 static int setup_busoff[MAXBOARDS];
 static int setup_dmaspeed[MAXBOARDS] __initdata = { -1, -1, -1, -1 };
 
-static char *setup_str[MAXBOARDS] __initdata;
-
 /*
  * LILO/Module params:  aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]
  *
@@ -960,6 +958,7 @@
 
 #ifndef MODULE
 static int setup_idx = 0;
+static char *setup_str[MAXBOARDS] __initdata;
 
 void __init aha1542_setup(char *str, int *ints)
 {
diff -urN linux-2.4.25-pre8/drivers/scsi/cpqfcTSi2c.c linux-2.4.25-rc1/drivers/scsi/cpqfcTSi2c.c
--- linux-2.4.25-pre8/drivers/scsi/cpqfcTSi2c.c	2003-06-13 07:51:36.000000000 -0700
+++ linux-2.4.25-rc1/drivers/scsi/cpqfcTSi2c.c	2004-02-05 04:40:36.000000000 -0800
@@ -59,7 +59,6 @@
 #define SLAVE_WRITE_ADDRESS	0xA0
 
 
-static void i2c_delay(u32 mstime);
 static void tl_i2c_clock_pulse(u8, void *GPIOout);
 static u8 tl_read_i2c_data(void *);
 
diff -urN linux-2.4.25-pre8/drivers/sound/ac97_plugin_ad1980.c linux-2.4.25-rc1/drivers/sound/ac97_plugin_ad1980.c
--- linux-2.4.25-pre8/drivers/sound/ac97_plugin_ad1980.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/drivers/sound/ac97_plugin_ad1980.c	2004-02-05 04:40:36.000000000 -0800
@@ -45,7 +45,7 @@
  *	use of the codec after the probe function.
  */
  
-static void ad1980_remove(struct ac97_codec *codec)
+static void ad1980_remove(struct ac97_codec *codec, struct ac97_driver *driver)
 {
 	/* Nothing to do in the simple example */
 }
diff -urN linux-2.4.25-pre8/drivers/usb/gadget/file_storage.c linux-2.4.25-rc1/drivers/usb/gadget/file_storage.c
--- linux-2.4.25-pre8/drivers/usb/gadget/file_storage.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/drivers/usb/gadget/file_storage.c	2004-02-05 04:40:36.000000000 -0800
@@ -415,7 +415,7 @@
 /*-------------------------------------------------------------------------*/
 
 #define fakedev_printk(level, dev, format, args...) \
-	printk(level "%s %s: " format, DRIVER_NAME, (dev)->name, ##args)
+	printk(level "%s %s: " format , DRIVER_NAME , (dev)->name , ## args)
 
 #define xprintk(f,level,fmt,args...) \
 	fakedev_printk(level , (f)->gadget , fmt , ## args)
@@ -428,7 +428,7 @@
 #define LDBG(lun,fmt,args...) \
 	yprintk(lun , KERN_DEBUG , fmt , ## args)
 #define MDBG(fmt,args...) \
-	printk(KERN_DEBUG DRIVER_NAME ": " fmt, ## args)
+	printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args)
 #else
 #define DBG(fsg,fmt,args...) \
 	do { } while (0)
@@ -466,7 +466,7 @@
 	yprintk(lun , KERN_INFO , fmt , ## args)
 
 #define MINFO(fmt,args...) \
-	printk(KERN_INFO DRIVER_NAME ": " fmt, ## args)
+	printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
 
 
 /*-------------------------------------------------------------------------*/
diff -urN linux-2.4.25-pre8/fs/binfmt_elf.c linux-2.4.25-rc1/fs/binfmt_elf.c
--- linux-2.4.25-pre8/fs/binfmt_elf.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/fs/binfmt_elf.c	2004-02-05 04:40:36.000000000 -0800
@@ -577,6 +577,10 @@
 			// printk(KERN_WARNING "ELF: Ambiguous type, using ELF\n");
 			interpreter_type = INTERPRETER_ELF;
 		}
+		/* Verify the interpreter has a valid arch */
+		if ((interpreter_type == INTERPRETER_ELF) &&
+		    !elf_check_arch(&interp_elf_ex))
+			goto out_free_dentry;
 	} else {
 		/* Executables without an interpreter also need a personality  */
 		SET_PERSONALITY(elf_ex, ibcs2_interpreter);
diff -urN linux-2.4.25-pre8/fs/intermezzo/file.c linux-2.4.25-rc1/fs/intermezzo/file.c
--- linux-2.4.25-pre8/fs/intermezzo/file.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.25-rc1/fs/intermezzo/file.c	2004-02-05 04:40:36.000000000 -0800
@@ -61,7 +61,7 @@
 
 static int presto_open_upcall(int minor, struct dentry *de)
 {
-        int rc;
+        int rc = 0;
         char *path, *buffer;
         struct presto_file_set *fset;
         int pathlen;
diff -urN linux-2.4.25-pre8/fs/namespace.c linux-2.4.25-rc1/fs/namespace.c
--- linux-2.4.25-pre8/fs/namespace.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/fs/namespace.c	2004-02-05 04:40:36.000000000 -0800
@@ -715,6 +715,9 @@
 	if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
 		return -EINVAL;
 
+	if (data_page)
+		((char *)data_page)[PAGE_SIZE - 1] = 0;
+
 	/* Separate the per-mountpoint flags */
 	if (flags & MS_NOSUID)
 		mnt_flags |= MNT_NOSUID;
diff -urN linux-2.4.25-pre8/fs/ntfs/fs.c linux-2.4.25-rc1/fs/ntfs/fs.c
--- linux-2.4.25-pre8/fs/ntfs/fs.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/fs/ntfs/fs.c	2004-02-05 04:40:36.000000000 -0800
@@ -199,7 +199,7 @@
 		ntfs_debug(DEBUG_OTHER, "%s(): Skipping unrepresentable "
 				"file.\n", __FUNCTION__);
 		err = 0;
-		goto err_ret;
+		goto err_noname;
 	}
 	if (!show_sys_files && inum < 0x10UL) {
 		ntfs_debug(DEBUG_OTHER, "%s(): Skipping system file (%s).\n",
@@ -233,8 +233,9 @@
 	if (err)
 		nf->ret_code = err;
 err_ret:
-	nf->namelen = 0;
 	ntfs_free(nf->name);
+err_noname:
+	nf->namelen = 0;
 	nf->name = NULL;
 	return err;
 }
diff -urN linux-2.4.25-pre8/fs/xfs/Makefile linux-2.4.25-rc1/fs/xfs/Makefile
--- linux-2.4.25-pre8/fs/xfs/Makefile	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/Makefile	2004-02-05 04:40:36.000000000 -0800
@@ -30,7 +30,7 @@
 # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 #
 
-EXTRA_CFLAGS +=  -I. -funsigned-char
+EXTRA_CFLAGS +=  -I. -I linux -funsigned-char
 
 ifeq ($(CONFIG_XFS_DEBUG),y)
 	EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG -DXFSDEBUG
@@ -52,21 +52,8 @@
 	# EXTRA_CFLAGS += -DXFS_VNODE_TRACE
 endif
 
-# fs/Makefile enters fs/xfs twice if CONFIG_XFS_FS is y, once for kernel and
-# once for modules.  This is necessary because xfsidbg can be built as a module
-# even if xfs is in kernel.  Alas the shorthand form
-#   O_TARGET := xfs.o
-#   obj-m := $(O_TARGET)
-# fails when the makefile is run more than once, code gets compiled as both
-# kernel and as module, which one gets linked depends on the phase of the moon.
-# I just love these layer violations where a makefile behaves differently
-# depending on changes to its parent.  Work around by only setting obj-m when
-# xfs is selected as a module.  Keith Owens.
-
 O_TARGET			:= xfs.o
-ifeq ($(CONFIG_XFS_FS),m)
-  obj-m				:= $(O_TARGET)
-endif
+obj-m				:= $(O_TARGET)
 
 obj-$(CONFIG_XFS_RT)		+= xfs_rtalloc.o
 obj-$(CONFIG_XFS_POSIX_ACL)	+= xfs_acl.o
@@ -79,6 +66,7 @@
 				   xfs_alloc_btree.o \
 				   xfs_attr.o \
 				   xfs_attr_leaf.o \
+				   xfs_behavior.o \
 				   xfs_bit.o \
 				   xfs_bmap.o \
 				   xfs_bmap_btree.o \
@@ -102,6 +90,7 @@
 				   xfs_inode.o \
 				   xfs_inode_item.o \
 				   xfs_iocore.o \
+				   xfs_iomap.o \
 				   xfs_itable.o \
 				   xfs_dfrag.o \
 				   xfs_log.o \
@@ -122,11 +111,10 @@
 				   xfs_rw.o
 
 # Objects not built in this directory
-obj-y				+= pagebuf/pagebuf.o \
-				   linux/linux_xfs.o \
+obj-y				+= linux/linux_xfs.o \
 				   support/support_xfs.o
 
-subdir-$(CONFIG_XFS_FS)		+= pagebuf linux support
+subdir-$(CONFIG_XFS_FS)		+= linux support
 
 ifeq ($(CONFIG_XFS_DMAPI),y)
   subdir-$(CONFIG_XFS_FS)	+= dmapi
@@ -142,21 +130,6 @@
   obj-y				+= xfs_qmops.o
 endif
 
-# If both xfs and kdb modules are built in then xfsidbg is built in.  If xfs is
-# a module and kdb modules are being compiled then xfsidbg must be a module, to
-# follow xfs.  If xfs is built in then xfsidbg tracks the kdb module state.
-# This must come after the main xfs code so xfs initialises before xfsidbg.
-# KAO
-ifneq ($(CONFIG_KDB_MODULES),)
-  ifeq ($(CONFIG_XFS_FS),y)
-    obj-$(CONFIG_KDB_MODULES)	+= xfsidbg.o
-  else
-    obj-$(CONFIG_XFS_FS)	+= xfsidbg.o
-  endif
-endif
-
-CFLAGS_xfsidbg.o += -I $(TOPDIR)/arch/$(ARCH)/kdb
-
 include $(TOPDIR)/Rules.make
 
 # This is really nasty, but Rules.make was never designed for multi directory
diff -urN linux-2.4.25-pre8/fs/xfs/linux/Makefile linux-2.4.25-rc1/fs/xfs/linux/Makefile
--- linux-2.4.25-pre8/fs/xfs/linux/Makefile	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/Makefile	2004-02-05 04:40:36.000000000 -0800
@@ -31,14 +31,14 @@
 #
 # Makefile for XFS on Linux.
 
-EXTRA_CFLAGS += -I.. -funsigned-char
+EXTRA_CFLAGS += -I.. -I. -funsigned-char
 
 ifeq ($(CONFIG_XFS_DEBUG),y)
 	EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG -DXFSDEBUG
 	EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING
 endif
 ifeq ($(CONFIG_XFS_TRACE),y)
-	EXTRA_CFLAGS += -DXFS_RW_TRACE
+	EXTRA_CFLAGS += -DXFS_RW_TRACE -DPAGEBUF_TRACE
 	# EXTRA_CFLAGS += -DXFS_VNODE_TRACE
 endif
 
@@ -47,21 +47,20 @@
   obj-m				:= $(O_TARGET)
 endif
 
-export-objs			:= xfs_globals.o
-
 obj-$(CONFIG_PROC_FS)		+= xfs_stats.o
 obj-$(CONFIG_SYSCTL)		+= xfs_sysctl.o
 obj-y				+= xfs_aops.o \
-				   xfs_behavior.o \
 				   xfs_file.o \
 				   xfs_fs_subr.o \
 				   xfs_globals.o \
 				   xfs_ioctl.o \
-				   xfs_iomap.o \
 				   xfs_iops.o \
 				   xfs_lrw.o \
 				   xfs_super.o \
 				   xfs_vfs.o \
-				   xfs_vnode.o
+				   xfs_vnode.o	\
+				   xfs_buf.o \
+				   mrlock.o \
+				   kmem.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.25-pre8/fs/xfs/linux/kmem.c linux-2.4.25-rc1/fs/xfs/linux/kmem.c
--- linux-2.4.25-pre8/fs/xfs/linux/kmem.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/kmem.c	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include "time.h"
+#include "kmem.h"
+
+#define DEF_PRIORITY	(6)
+#define MAX_SLAB_SIZE	0x10000
+#define MAX_SHAKE	8
+
+static kmem_shake_func_t	shake_list[MAX_SHAKE];
+static DECLARE_MUTEX(shake_sem);
+
+kmem_shaker_t
+kmem_shake_register(kmem_shake_func_t sfunc)
+{
+	int	i;
+
+	down(&shake_sem);
+	for (i = 0; i < MAX_SHAKE; i++) {
+		if (shake_list[i] == NULL) {
+			shake_list[i] = sfunc;
+			break;
+		}
+	}
+	if (i == MAX_SHAKE)
+		BUG();
+	up(&shake_sem);
+
+	return (kmem_shaker_t)sfunc;
+}
+
+void
+kmem_shake_deregister(kmem_shaker_t sfunc)
+{
+	int	i;
+
+	down(&shake_sem);
+	for (i = 0; i < MAX_SHAKE; i++) {
+		if (shake_list[i] == (kmem_shake_func_t)sfunc)
+			break;
+	}
+	if (i == MAX_SHAKE)
+		BUG();
+	for (; i < MAX_SHAKE - 1; i++) {
+		shake_list[i] = shake_list[i+1];
+	}
+	shake_list[i] = NULL;
+	up(&shake_sem);
+}
+
+static __inline__ void kmem_shake(void)
+{
+	int	i;
+
+	down(&shake_sem);
+	for (i = 0; i < MAX_SHAKE && shake_list[i]; i++)
+		(*shake_list[i])(0, 0);
+	up(&shake_sem);
+	delay(10);
+}
+
+void *
+kmem_alloc(size_t size, int flags)
+{
+	int	shrink  = DEF_PRIORITY;	/* # times to try to shrink cache */
+        int     lflags  = kmem_flags_convert(flags);
+        int     nosleep = flags & KM_NOSLEEP;
+	void	*rval;
+
+repeat:
+	if (MAX_SLAB_SIZE < size) {
+		/* Avoid doing filesystem sensitive stuff to get this */
+		rval = __vmalloc(size, lflags, PAGE_KERNEL);
+	} else {
+		rval = kmalloc(size, lflags);
+	}
+
+	if (rval || nosleep)
+		return rval;
+
+	/*
+	 * KM_SLEEP callers don't expect a failure
+	 */
+	if (shrink) {
+		kmem_shake();
+
+		shrink--;
+		goto repeat;
+	}
+
+	rval = __vmalloc(size, lflags, PAGE_KERNEL);
+	if (!rval && !nosleep)
+		panic("kmem_alloc: NULL memory on KM_SLEEP request!");
+
+	return rval;
+}
+
+void *
+kmem_zalloc(size_t size, int flags)
+{
+	void	*ptr;
+
+	ptr = kmem_alloc(size, flags);
+
+	if (ptr)
+		memset((char *)ptr, 0, (int)size);
+
+	return (ptr);
+}
+
+void
+kmem_free(void *ptr, size_t size)
+{
+	if (((unsigned long)ptr < VMALLOC_START) ||
+	    ((unsigned long)ptr >= VMALLOC_END)) {
+		kfree(ptr);
+	} else {
+		vfree(ptr);
+	}
+}
+
+void *
+kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
+{
+	void *new;
+
+	new = kmem_alloc(newsize, flags);
+	if (ptr) {
+		if (new)
+			memcpy(new, ptr,
+				((oldsize < newsize) ? oldsize : newsize));
+		kmem_free(ptr, oldsize);
+	}
+
+	return new;
+}
+
+kmem_zone_t *
+kmem_zone_init(int size, char *zone_name)
+{
+	return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL);
+}
+
+void *
+kmem_zone_alloc(kmem_zone_t *zone, int flags)
+{
+	int	shrink = DEF_PRIORITY;	/* # times to try to shrink cache */
+	void	*ptr = NULL;
+
+repeat:
+	ptr = kmem_cache_alloc(zone, kmem_flags_convert(flags));
+
+	if (ptr || (flags & KM_NOSLEEP))
+		return ptr;
+
+	/*
+	 * KM_SLEEP callers don't expect a failure
+	 */
+	if (shrink) {
+		kmem_shake();
+
+		shrink--;
+		goto repeat;
+	}
+
+	if (flags & KM_SLEEP)
+		panic("kmem_zone_alloc: NULL memory on KM_SLEEP request!");
+
+	return NULL;
+}
+
+void *
+kmem_zone_zalloc(kmem_zone_t *zone, int flags)
+{
+	int	shrink = DEF_PRIORITY;	/* # times to try to shrink cache */
+	void	*ptr = NULL;
+
+repeat:
+	ptr = kmem_cache_alloc(zone, kmem_flags_convert(flags));
+
+	if (ptr) {
+		memset(ptr, 0, kmem_cache_size(zone));
+		return ptr;
+	}
+
+	if (flags & KM_NOSLEEP)
+		return ptr;
+
+	/*
+	 * KM_SLEEP callers don't expect a failure
+	 */
+	if (shrink) {
+		kmem_shake();
+
+		shrink--;
+		goto repeat;
+	}
+
+	if (flags & KM_SLEEP)
+		panic("kmem_zone_zalloc: NULL memory on KM_SLEEP request!");
+
+	return NULL;
+}
+
+void
+kmem_zone_free(kmem_zone_t *zone, void *ptr)
+{
+	kmem_cache_free(zone, ptr);
+}
diff -urN linux-2.4.25-pre8/fs/xfs/linux/kmem.h linux-2.4.25-rc1/fs/xfs/linux/kmem.h
--- linux-2.4.25-pre8/fs/xfs/linux/kmem.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/kmem.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_SUPPORT_KMEM_H__
+#define __XFS_SUPPORT_KMEM_H__
+
+#include <linux/slab.h>
+
+/*
+ * memory management routines
+ */
+#define KM_SLEEP	0x0001
+#define KM_NOSLEEP	0x0002
+#define KM_NOFS		0x0004
+
+#define	kmem_zone	kmem_cache_s
+#define kmem_zone_t	kmem_cache_t
+
+typedef unsigned long xfs_pflags_t;
+
+#define PFLAGS_TEST_NOIO()              (current->flags & PF_NOIO)
+#define PFLAGS_TEST_FSTRANS()           (current->flags & PF_FSTRANS)
+
+#define PFLAGS_SET_NOIO(STATEP) do {    \
+	*(STATEP) = current->flags;     \
+        current->flags |= PF_NOIO;      \
+} while (0)
+
+#define PFLAGS_SET_FSTRANS(STATEP) do { \
+	*(STATEP) = current->flags;     \
+        current->flags |= PF_FSTRANS;   \
+} while (0)
+
+#define PFLAGS_RESTORE(STATEP) do {     \
+	current->flags = *(STATEP);     \
+} while (0)
+
+#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \
+	*(NSTATEP) = *(OSTATEP);	\
+} while (0);
+
+static __inline unsigned int kmem_flags_convert(int flags)
+{
+        int lflags;
+        
+#if DEBUG
+	if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) {
+		printk(KERN_WARNING
+		    "XFS: memory allocation with wrong flags (%x)\n", flags);
+		BUG();
+	}
+#endif
+        
+        lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : GFP_KERNEL;
+        
+        /* avoid recusive callbacks to filesystem during transactions */
+	if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS))
+		lflags &= ~__GFP_FS;
+        
+        return lflags;
+}
+
+extern kmem_zone_t  *kmem_zone_init(int, char *);
+extern void	    *kmem_zone_zalloc(kmem_zone_t *, int);
+extern void	    *kmem_zone_alloc(kmem_zone_t *, int);
+extern void         kmem_zone_free(kmem_zone_t *, void *);
+
+extern void	    *kmem_alloc(size_t, int);
+extern void	    *kmem_realloc(void *, size_t, size_t, int);
+extern void	    *kmem_zalloc(size_t, int);
+extern void         kmem_free(void *, size_t);
+
+typedef void	    *kmem_shaker_t;
+typedef int	    (*kmem_shake_func_t)(int, unsigned int);
+
+extern kmem_shaker_t	kmem_shake_register(kmem_shake_func_t);
+extern void	    kmem_shake_deregister(kmem_shaker_t);
+static __inline int	kmem_shake_allow(unsigned int mask) { return 1; }
+
+#endif /* __XFS_SUPPORT_KMEM_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/mrlock.c linux-2.4.25-rc1/fs/xfs/linux/mrlock.c
--- linux-2.4.25-pre8/fs/xfs/linux/mrlock.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/mrlock.c	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <asm/system.h>
+#include <linux/interrupt.h>
+#include <asm/current.h>
+
+#include "mrlock.h"
+
+
+#if USE_RW_WAIT_QUEUE_SPINLOCK
+# define wq_write_lock	write_lock
+#else
+# define wq_write_lock	spin_lock
+#endif
+
+/*
+ * We don't seem to need lock_type (only one supported), name, or
+ * sequence. But, XFS will pass it so let's leave them here for now.
+ */
+/* ARGSUSED */
+void
+mrlock_init(mrlock_t *mrp, int lock_type, char *name, long sequence)
+{
+	mrp->mr_count = 0;
+	mrp->mr_reads_waiting = 0;
+	mrp->mr_writes_waiting = 0;
+	init_waitqueue_head(&mrp->mr_readerq);
+	init_waitqueue_head(&mrp->mr_writerq);
+	mrp->mr_lock = SPIN_LOCK_UNLOCKED;
+}
+
+/*
+ * Macros to lock/unlock the mrlock_t.
+ */
+
+#define MRLOCK(m)		spin_lock(&(m)->mr_lock);
+#define MRUNLOCK(m)		spin_unlock(&(m)->mr_lock);
+
+
+/*
+ * lock_wait should never be called in an interrupt thread.
+ *
+ * mrlocks can sleep (i.e. call schedule) and so they can't ever
+ * be called from an interrupt thread.
+ *
+ * threads that wake-up should also never be invoked from interrupt threads.
+ *
+ * But, waitqueue_lock is locked from interrupt threads - and we are
+ * called with interrupts disabled, so it is all OK.
+ */
+
+/* ARGSUSED */
+void
+lock_wait(wait_queue_head_t *q, spinlock_t *lock, int rw)
+{
+	DECLARE_WAITQUEUE( wait, current );
+
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+
+	wq_write_lock(&q->lock);
+	if (rw) {
+		__add_wait_queue_tail(q, &wait);
+	} else {
+		__add_wait_queue(q, &wait);
+	}
+
+	wq_write_unlock(&q->lock);
+	spin_unlock(lock);
+
+	schedule();
+
+	wq_write_lock(&q->lock);
+	__remove_wait_queue(q, &wait);
+	wq_write_unlock(&q->lock);
+
+	spin_lock(lock);
+
+	/* return with lock held */
+}
+
+/* ARGSUSED */
+void
+mrfree(mrlock_t *mrp)
+{
+}
+
+/* ARGSUSED */
+void
+mrlock(mrlock_t *mrp, int type, int flags)
+{
+	if (type == MR_ACCESS)
+		mraccess(mrp);
+	else
+		mrupdate(mrp);
+}
+
+/* ARGSUSED */
+void
+mraccessf(mrlock_t *mrp, int flags)
+{
+	MRLOCK(mrp);
+	if(mrp->mr_writes_waiting > 0) {
+		mrp->mr_reads_waiting++;
+		lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0);
+		mrp->mr_reads_waiting--;
+	}
+	while (mrp->mr_count < 0) {
+		mrp->mr_reads_waiting++;
+		lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0);
+		mrp->mr_reads_waiting--;
+	}
+	mrp->mr_count++;
+	MRUNLOCK(mrp);
+}
+
+/* ARGSUSED */
+void
+mrupdatef(mrlock_t *mrp, int flags)
+{
+	MRLOCK(mrp);
+	while(mrp->mr_count) {
+		mrp->mr_writes_waiting++;
+		lock_wait(&mrp->mr_writerq, &mrp->mr_lock, 1);
+		mrp->mr_writes_waiting--;
+	}
+
+	mrp->mr_count = -1; /* writer on it */
+	MRUNLOCK(mrp);
+}
+
+int
+mrtryaccess(mrlock_t *mrp)
+{
+	MRLOCK(mrp);
+	/*
+	 * If anyone is waiting for update access or the lock is held for update
+	 * fail the request.
+	 */
+	if(mrp->mr_writes_waiting > 0 || mrp->mr_count < 0) {
+		MRUNLOCK(mrp);
+		return 0;
+	}
+	mrp->mr_count++;
+	MRUNLOCK(mrp);
+	return 1;
+}
+
+int
+mrtrypromote(mrlock_t *mrp)
+{
+	MRLOCK(mrp);
+
+	if(mrp->mr_count == 1) { /* We are the only thread with the lock */
+		mrp->mr_count = -1; /* writer on it */
+		MRUNLOCK(mrp);
+		return 1;
+	}
+
+	MRUNLOCK(mrp);
+	return 0;
+}
+
+int
+mrtryupdate(mrlock_t *mrp)
+{
+	MRLOCK(mrp);
+
+	if(mrp->mr_count) {
+		MRUNLOCK(mrp);
+		return 0;
+	}
+
+	mrp->mr_count = -1; /* writer on it */
+	MRUNLOCK(mrp);
+	return 1;
+}
+
+static __inline__ void mrwake(mrlock_t *mrp)
+{
+	/*
+	 * First, if the count is now 0, we need to wake-up anyone waiting.
+	 */
+	if (!mrp->mr_count) {
+		if (mrp->mr_writes_waiting) {	/* Wake-up first writer waiting */
+			wake_up(&mrp->mr_writerq);
+		} else if (mrp->mr_reads_waiting) {	/* Wakeup any readers waiting */
+			wake_up(&mrp->mr_readerq);
+		}
+	}
+}
+
+void
+mraccunlock(mrlock_t *mrp)
+{
+	MRLOCK(mrp);
+	mrp->mr_count--;
+	mrwake(mrp);
+	MRUNLOCK(mrp);
+}
+
+void
+mrunlock(mrlock_t *mrp)
+{
+	MRLOCK(mrp);
+	if (mrp->mr_count < 0) {
+		mrp->mr_count = 0;
+	} else {
+		mrp->mr_count--;
+	}
+	mrwake(mrp);
+	MRUNLOCK(mrp);
+}
+
+int
+ismrlocked(mrlock_t *mrp, int type)	/* No need to lock since info can change */
+{
+	if (type == MR_ACCESS)
+		return (mrp->mr_count > 0); /* Read lock */
+	else if (type == MR_UPDATE)
+		return (mrp->mr_count < 0); /* Write lock */
+	else if (type == (MR_UPDATE | MR_ACCESS))
+		return (mrp->mr_count);	/* Any type of lock held */
+	else /* Any waiters */
+		return (mrp->mr_reads_waiting | mrp->mr_writes_waiting);
+}
+
+/*
+ * Demote from update to access. We better be the only thread with the
+ * lock in update mode so it should be easy to set to 1.
+ * Wake-up any readers waiting.
+ */
+
+void
+mrdemote(mrlock_t *mrp)
+{
+	MRLOCK(mrp);
+	mrp->mr_count = 1;
+	if (mrp->mr_reads_waiting) {	/* Wakeup all readers waiting */
+		wake_up(&mrp->mr_readerq);
+	}
+	MRUNLOCK(mrp);
+}
diff -urN linux-2.4.25-pre8/fs/xfs/linux/mrlock.h linux-2.4.25-rc1/fs/xfs/linux/mrlock.h
--- linux-2.4.25-pre8/fs/xfs/linux/mrlock.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/mrlock.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_SUPPORT_MRLOCK_H__
+#define __XFS_SUPPORT_MRLOCK_H__
+
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+/*
+ * Implement mrlocks on Linux that work for XFS.
+ *
+ * These are sleep locks and not spinlocks. If one wants read/write spinlocks,
+ * use read_lock, write_lock, ... see spinlock.h.
+ */
+
+typedef struct mrlock_s {
+	int			mr_count;
+	unsigned short		mr_reads_waiting;
+	unsigned short		mr_writes_waiting;
+	wait_queue_head_t	mr_readerq;
+	wait_queue_head_t	mr_writerq;
+	spinlock_t		mr_lock;
+} mrlock_t;
+
+#define MR_ACCESS	1
+#define MR_UPDATE	2
+
+#define MRLOCK_BARRIER		0x1
+#define MRLOCK_ALLOW_EQUAL_PRI	0x8
+
+/*
+ * mraccessf/mrupdatef take flags to be passed in while sleeping;
+ * only PLTWAIT is currently supported.
+ */
+
+extern void	mraccessf(mrlock_t *, int);
+extern void	mrupdatef(mrlock_t *, int);
+extern void     mrlock(mrlock_t *, int, int);
+extern void     mrunlock(mrlock_t *);
+extern void     mraccunlock(mrlock_t *);
+extern int      mrtryupdate(mrlock_t *);
+extern int      mrtryaccess(mrlock_t *);
+extern int	mrtrypromote(mrlock_t *);
+extern void     mrdemote(mrlock_t *);
+
+extern int	ismrlocked(mrlock_t *, int);
+extern void     mrlock_init(mrlock_t *, int type, char *name, long sequence);
+extern void     mrfree(mrlock_t *);
+
+#define mrinit(mrp, name)	mrlock_init(mrp, MRLOCK_BARRIER, name, -1)
+#define mraccess(mrp)		mraccessf(mrp, 0) /* grab for READ/ACCESS */
+#define mrupdate(mrp)		mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */
+#define mrislocked_access(mrp)	((mrp)->mr_count > 0)
+#define mrislocked_update(mrp)	((mrp)->mr_count < 0)
+
+#endif /* __XFS_SUPPORT_MRLOCK_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/mutex.h linux-2.4.25-rc1/fs/xfs/linux/mutex.h
--- linux-2.4.25-pre8/fs/xfs/linux/mutex.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/mutex.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_SUPPORT_MUTEX_H__
+#define __XFS_SUPPORT_MUTEX_H__
+
+#include <linux/spinlock.h>
+#include <asm/semaphore.h>
+
+/*
+ * Map the mutex'es from IRIX to Linux semaphores.
+ *
+ * Destroy just simply initializes to -99 which should block all other
+ * callers.
+ */
+#define MUTEX_DEFAULT		0x0
+typedef struct semaphore	mutex_t;
+
+#define mutex_init(lock, type, name)		sema_init(lock, 1)
+#define mutex_destroy(lock)			sema_init(lock, -99)
+#define mutex_lock(lock, num)			down(lock)
+#define mutex_trylock(lock)			(down_trylock(lock) ? 0 : 1)
+#define mutex_unlock(lock)			up(lock)
+
+#endif /* __XFS_SUPPORT_MUTEX_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/sema.h linux-2.4.25-rc1/fs/xfs/linux/sema.h
--- linux-2.4.25-pre8/fs/xfs/linux/sema.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/sema.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_SUPPORT_SEMA_H__
+#define __XFS_SUPPORT_SEMA_H__
+
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+/*
+ * sema_t structure just maps to struct semaphore in Linux kernel.
+ */
+
+typedef struct semaphore sema_t;
+
+#define init_sema(sp, val, c, d)	sema_init(sp, val)
+#define initsema(sp, val)		sema_init(sp, val)
+#define initnsema(sp, val, name)	sema_init(sp, val)
+#define psema(sp, b)			down(sp)
+#define vsema(sp)			up(sp)
+#define valusema(sp)			(atomic_read(&(sp)->count))
+#define freesema(sema)
+
+/*
+ * Map cpsema (try to get the sema) to down_trylock. We need to switch
+ * the return values since cpsema returns 1 (acquired) 0 (failed) and
+ * down_trylock returns the reverse 0 (acquired) 1 (failed).
+ */
+
+#define cpsema(sp)			(down_trylock(sp) ? 0 : 1)
+
+/*
+ * Didn't do cvsema(sp). Not sure how to map this to up/down/...
+ * It does a vsema if the values is < 0 other wise nothing.
+ */
+
+#endif /* __XFS_SUPPORT_SEMA_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/spin.h linux-2.4.25-rc1/fs/xfs/linux/spin.h
--- linux-2.4.25-pre8/fs/xfs/linux/spin.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/spin.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_SUPPORT_SPIN_H__
+#define __XFS_SUPPORT_SPIN_H__
+
+#include <linux/sched.h>	/* preempt needs this */
+#include <linux/spinlock.h>
+
+/*
+ * Map lock_t from IRIX to Linux spinlocks.
+ *
+ * Note that linux turns on/off spinlocks depending on CONFIG_SMP.
+ * We don't need to worry about SMP or not here.
+ */
+
+#define SPLDECL(s)		unsigned long s
+
+typedef spinlock_t lock_t;
+
+#define spinlock_init(lock, name)	spin_lock_init(lock)
+#define	spinlock_destroy(lock)
+
+static inline unsigned long mutex_spinlock(lock_t *lock)
+{
+	spin_lock(lock);
+	return 0;
+}
+
+/*ARGSUSED*/
+static inline void mutex_spinunlock(lock_t *lock, unsigned long s)
+{
+	spin_unlock(lock);
+}
+
+static inline void nested_spinlock(lock_t *lock)
+{
+	spin_lock(lock);
+}
+
+static inline void nested_spinunlock(lock_t *lock)
+{
+	spin_unlock(lock);
+}
+
+#endif /* __XFS_SUPPORT_SPIN_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/sv.h linux-2.4.25-rc1/fs/xfs/linux/sv.h
--- linux-2.4.25-pre8/fs/xfs/linux/sv.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/sv.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_SUPPORT_SV_H__
+#define __XFS_SUPPORT_SV_H__
+
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+/*
+ * Synchronisation variables.
+ *
+ * (Parameters "pri", "svf" and "rts" are not implemented)
+ */
+
+typedef struct sv_s {
+	wait_queue_head_t waiters;
+} sv_t;
+
+#define SV_FIFO		0x0		/* sv_t is FIFO type */
+#define SV_LIFO		0x2		/* sv_t is LIFO type */
+#define SV_PRIO		0x4		/* sv_t is PRIO type */
+#define SV_KEYED	0x6		/* sv_t is KEYED type */
+#define SV_DEFAULT      SV_FIFO
+
+
+static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state,
+			     unsigned long timeout)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue_exclusive(&sv->waiters, &wait);
+	__set_current_state(state);
+	spin_unlock(lock);
+
+	schedule_timeout(timeout);
+
+	remove_wait_queue(&sv->waiters, &wait);
+}
+
+#define init_sv(sv,type,name,flag) \
+	init_waitqueue_head(&(sv)->waiters)
+#define sv_init(sv,flag,name) \
+	init_waitqueue_head(&(sv)->waiters)
+#define sv_destroy(sv) \
+	/*NOTHING*/
+#define sv_wait(sv, pri, lock, s) \
+	_sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)
+#define sv_wait_sig(sv, pri, lock, s)   \
+	_sv_wait(sv, lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)
+#define sv_timedwait(sv, pri, lock, s, svf, ts, rts) \
+	_sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, timespec_to_jiffies(ts))
+#define sv_timedwait_sig(sv, pri, lock, s, svf, ts, rts) \
+	_sv_wait(sv, lock, TASK_INTERRUPTIBLE, timespec_to_jiffies(ts))
+#define sv_signal(sv) \
+	wake_up(&(sv)->waiters)
+#define sv_broadcast(sv) \
+	wake_up_all(&(sv)->waiters)
+
+#endif /* __XFS_SUPPORT_SV_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/time.h linux-2.4.25-rc1/fs/xfs/linux/time.h
--- linux-2.4.25-pre8/fs/xfs/linux/time.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/time.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_SUPPORT_TIME_H__
+#define __XFS_SUPPORT_TIME_H__
+
+#include <linux/sched.h>
+#include <linux/time.h>
+
+typedef struct timespec timespec_t;
+
+static inline void delay(long ticks)
+{
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout(ticks);
+}
+
+static inline void nanotime(struct timespec *tvp)
+{
+	struct timeval tv;
+
+	do_gettimeofday(&tv);
+	tvp->tv_sec = tv.tv_sec;
+	tvp->tv_nsec = tv.tv_usec * 1000;
+}
+
+#endif /* __XFS_SUPPORT_TIME_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_behavior.c linux-2.4.25-rc1/fs/xfs/linux/xfs_behavior.c
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_behavior.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_behavior.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- *
- */
-#include "xfs.h"
-
-/*
- * Source file used to associate/disassociate behaviors with virtualized
- * objects.  See xfs_behavior.h for more information about behaviors, etc.
- *
- * The implementation is split between functions in this file and macros
- * in xfs_behavior.h.
- */
-
-/*
- * Insert a new behavior descriptor into a behavior chain.
- *
- * The behavior chain is ordered based on the 'position' number which
- * lives in the first field of the ops vector (higher numbers first).
- *
- * Attemps to insert duplicate ops result in an EINVAL return code.
- * Otherwise, return 0 to indicate success.
- */
-int
-bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
-{
-	bhv_desc_t	*curdesc, *prev;
-	int		position;
-
-	/*
-	 * Validate the position value of the new behavior.
-	 */
-	position = BHV_POSITION(bdp);
-	ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
-
-	/*
-	 * Find location to insert behavior.  Check for duplicates.
-	 */
-	prev = NULL;
-	for (curdesc = bhp->bh_first;
-	     curdesc != NULL;
-	     curdesc = curdesc->bd_next) {
-
-		/* Check for duplication. */
-		if (curdesc->bd_ops == bdp->bd_ops) {
-			ASSERT(0);
-			return EINVAL;
-		}
-
-		/* Find correct position */
-		if (position >= BHV_POSITION(curdesc)) {
-			ASSERT(position != BHV_POSITION(curdesc));
-			break;		/* found it */
-		}
-
-		prev = curdesc;
-	}
-
-	if (prev == NULL) {
-		/* insert at front of chain */
-		bdp->bd_next = bhp->bh_first;
-		bhp->bh_first = bdp;
-	} else {
-		/* insert after prev */
-		bdp->bd_next = prev->bd_next;
-		prev->bd_next = bdp;
-	}
-
-	return 0;
-}
-
-/*
- * Remove a behavior descriptor from a position in a behavior chain;
- * the postition is guaranteed not to be the first position.
- * Should only be called by the bhv_remove() macro.
- */
-void
-bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
-{
-	bhv_desc_t	*curdesc, *prev;
-
-	ASSERT(bhp->bh_first != NULL);
-	ASSERT(bhp->bh_first->bd_next != NULL);
-
-	prev = bhp->bh_first;
-	for (curdesc = bhp->bh_first->bd_next;
-	     curdesc != NULL;
-	     curdesc = curdesc->bd_next) {
-
-		if (curdesc == bdp)
-			break;		/* found it */
-		prev = curdesc;
-	}
-
-	ASSERT(curdesc == bdp);
-	prev->bd_next = bdp->bd_next;	/* remove from after prev */
-}
-
-/*
- * Look for a specific ops vector on the specified behavior chain.
- * Return the associated behavior descriptor.  Or NULL, if not found.
- */
-bhv_desc_t *
-bhv_lookup(bhv_head_t *bhp, void *ops)
-{
-	bhv_desc_t	*curdesc;
-
-	for (curdesc = bhp->bh_first;
-	     curdesc != NULL;
-	     curdesc = curdesc->bd_next) {
-
-		if (curdesc->bd_ops == ops)
-			return curdesc;
-	}
-
-	return NULL;
-}
-
-/*
- * Looks for the first behavior within a specified range of positions.
- * Return the associated behavior descriptor.  Or NULL, if none found.
- */
-bhv_desc_t *
-bhv_lookup_range(bhv_head_t *bhp, int low, int high)
-{
-	bhv_desc_t	*curdesc;
-
-	for (curdesc = bhp->bh_first;
-	     curdesc != NULL;
-	     curdesc = curdesc->bd_next) {
-
-		int	position = BHV_POSITION(curdesc);
-
-		if (position <= high) {
-			if (position >= low)
-				return curdesc;
-			return NULL;
-		}
-	}
-
-	return NULL;
-}
-
-/*
- * Return the base behavior in the chain, or NULL if the chain
- * is empty.
- *
- * The caller has not read locked the behavior chain, so acquire the
- * lock before traversing the chain.
- */
-bhv_desc_t *
-bhv_base(bhv_head_t *bhp)
-{
-	bhv_desc_t	*curdesc;
-
-	for (curdesc = bhp->bh_first;
-	     curdesc != NULL;
-	     curdesc = curdesc->bd_next) {
-
-		if (curdesc->bd_next == NULL) {
-			return curdesc;
-		}
-	}
-
-	return NULL;
-}
-
-void
-bhv_head_init(
-	bhv_head_t *bhp,
-	char *name)
-{
-	bhp->bh_first = NULL;
-}
-
-void
-bhv_insert_initial(
-	bhv_head_t *bhp,
-	bhv_desc_t *bdp)
-{
-	ASSERT(bhp->bh_first == NULL);
-	(bhp)->bh_first = bdp;
-}
-
-void
-bhv_head_destroy(
-	bhv_head_t *bhp)
-{
-	ASSERT(bhp->bh_first == NULL);
-}
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_behavior.h linux-2.4.25-rc1/fs/xfs/linux/xfs_behavior.h
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_behavior.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_behavior.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_BEHAVIOR_H__
-#define __XFS_BEHAVIOR_H__
-
-/*
- * Header file used to associate behaviors with virtualized objects.
- *
- * A virtualized object is an internal, virtualized representation of
- * OS entities such as persistent files, processes, or sockets.  Examples
- * of virtualized objects include vnodes, vprocs, and vsockets.  Often
- * a virtualized object is referred to simply as an "object."
- *
- * A behavior is essentially an implementation layer associated with
- * an object.  Multiple behaviors for an object are chained together,
- * the order of chaining determining the order of invocation.  Each
- * behavior of a given object implements the same set of interfaces
- * (e.g., the VOP interfaces).
- *
- * Behaviors may be dynamically inserted into an object's behavior chain,
- * such that the addition is transparent to consumers that already have
- * references to the object.  Typically, a given behavior will be inserted
- * at a particular location in the behavior chain.  Insertion of new
- * behaviors is synchronized with operations-in-progress (oip's) so that
- * the oip's always see a consistent view of the chain.
- *
- * The term "interpostion" is used to refer to the act of inserting
- * a behavior such that it interposes on (i.e., is inserted in front
- * of) a particular other behavior.  A key example of this is when a
- * system implementing distributed single system image wishes to
- * interpose a distribution layer (providing distributed coherency)
- * in front of an object that is otherwise only accessed locally.
- *
- * Note that the traditional vnode/inode combination is simply a virtualized
- * object that has exactly one associated behavior.
- *
- * Behavior synchronization is logic which is necessary under certain
- * circumstances that there is no conflict between ongoing operations
- * traversing the behavior chain and those dunamically modifying the
- * behavior chain.  Because behavior synchronization adds extra overhead
- * to virtual operation invocation, we want to restrict, as much as
- * we can, the requirement for this extra code, to those situations
- * in which it is truly necessary.
- *
- * Behavior synchronization is needed whenever there's at least one class
- * of object in the system for which:
- * 1) multiple behaviors for a given object are supported,
- * -- AND --
- * 2a) insertion of a new behavior can happen dynamically at any time during
- *     the life of an active object,
- *	-- AND --
- *	3a) insertion of a new behavior needs to synchronize with existing
- *	    ops-in-progress.
- *	-- OR --
- *	3b) multiple different behaviors can be dynamically inserted at
- *	    any time during the life of an active object
- *	-- OR --
- *	3c) removal of a behavior can occur at any time during the life of
- *	    an active object.
- * -- OR --
- * 2b) removal of a behavior can occur at any time during the life of an
- *     active object
- *
- */
-
-struct bhv_head_lock;
-
-/*
- * Behavior head.  Head of the chain of behaviors.
- * Contained within each virtualized object data structure.
- */
-typedef struct bhv_head {
-	struct bhv_desc *bh_first;	/* first behavior in chain */
-	struct bhv_head_lock *bh_lockp;	/* pointer to lock info struct */
-} bhv_head_t;
-
-/*
- * Behavior descriptor.	 Descriptor associated with each behavior.
- * Contained within the behavior's private data structure.
- */
-typedef struct bhv_desc {
-	void		*bd_pdata;	/* private data for this behavior */
-	void		*bd_vobj;	/* virtual object associated with */
-	void		*bd_ops;	/* ops for this behavior */
-	struct bhv_desc *bd_next;	/* next behavior in chain */
-} bhv_desc_t;
-
-/*
- * Behavior identity field.  A behavior's identity determines the position
- * where it lives within a behavior chain, and it's always the first field
- * of the behavior's ops vector. The optional id field further identifies the
- * subsystem responsible for the behavior.
- */
-typedef struct bhv_identity {
-	__u16	bi_id;		/* owning subsystem id */
-	__u16	bi_position;	/* position in chain */
-} bhv_identity_t;
-
-typedef bhv_identity_t bhv_position_t;
-
-#define BHV_IDENTITY_INIT(id,pos)	{id, pos}
-#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos)
-
-/*
- * Define boundaries of position values.
- */
-#define BHV_POSITION_INVALID	0	/* invalid position number */
-#define BHV_POSITION_BASE	1	/* base (last) implementation layer */
-#define BHV_POSITION_TOP	63	/* top (first) implementation layer */
-
-/*
- * Plumbing macros.
- */
-#define BHV_HEAD_FIRST(bhp)	(ASSERT((bhp)->bh_first), (bhp)->bh_first)
-#define BHV_NEXT(bdp)		(ASSERT((bdp)->bd_next), (bdp)->bd_next)
-#define BHV_NEXTNULL(bdp)	((bdp)->bd_next)
-#define BHV_VOBJ(bdp)		(ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj)
-#define BHV_VOBJNULL(bdp)	((bdp)->bd_vobj)
-#define BHV_PDATA(bdp)		(bdp)->bd_pdata
-#define BHV_OPS(bdp)		(bdp)->bd_ops
-#define BHV_IDENTITY(bdp)	((bhv_identity_t *)(bdp)->bd_ops)
-#define BHV_POSITION(bdp)	(BHV_IDENTITY(bdp)->bi_position)
-
-extern void bhv_head_init(bhv_head_t *, char *);
-extern void bhv_head_destroy(bhv_head_t *);
-extern int  bhv_insert(bhv_head_t *, bhv_desc_t *);
-extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
-
-/*
- * Initialize a new behavior descriptor.
- * Arguments:
- *   bdp - pointer to behavior descriptor
- *   pdata - pointer to behavior's private data
- *   vobj - pointer to associated virtual object
- *   ops - pointer to ops for this behavior
- */
-#define bhv_desc_init(bdp, pdata, vobj, ops)		\
- {							\
-	(bdp)->bd_pdata = pdata;			\
-	(bdp)->bd_vobj = vobj;				\
-	(bdp)->bd_ops = ops;				\
-	(bdp)->bd_next = NULL;				\
- }
-
-/*
- * Remove a behavior descriptor from a behavior chain.
- */
-#define bhv_remove(bhp, bdp)				\
- {							\
-	if ((bhp)->bh_first == (bdp)) {			\
-		/*					\
-		* Remove from front of chain.		\
-		* Atomic wrt oip's.			\
-		*/					\
-	       (bhp)->bh_first = (bdp)->bd_next;	\
-	} else {					\
-	       /* remove from non-front of chain */	\
-	       bhv_remove_not_first(bhp, bdp);		\
-	}						\
-	(bdp)->bd_vobj = NULL;				\
- }
-
-/*
- * Behavior module prototypes.
- */
-extern void		bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
-extern bhv_desc_t *	bhv_lookup(bhv_head_t *bhp, void *ops);
-extern bhv_desc_t *	bhv_lookup_range(bhv_head_t *bhp, int low, int high);
-extern bhv_desc_t *	bhv_base(bhv_head_t *bhp);
-
-/* No bhv locking on Linux */
-#define bhv_lookup_unlocked	bhv_lookup
-#define bhv_base_unlocked	bhv_base
-
-#endif /* __XFS_BEHAVIOR_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_buf.c linux-2.4.25-rc1/fs/xfs/linux/xfs_buf.c
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_buf.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_buf.c	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,2558 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/*
+ *	page_buf.c
+ *
+ *	The page_buf module provides an abstract buffer cache model on top of
+ *	the Linux page cache.  Cached metadata blocks for a file system are
+ *	hashed to the inode for the block device.  The page_buf module
+ *	assembles buffer (page_buf_t) objects on demand to aggregate such
+ *	cached pages for I/O.
+ *
+ *
+ *      Written by Steve Lord, Jim Mostek, Russell Cattelan
+ *		    and Rajagopal Ananthanarayanan ("ananth") at SGI.
+ *
+ */
+
+#include <linux/stddef.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/blkdev.h>
+#include <linux/locks.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+
+#include <support/ktrace.h>
+#include <support/debug.h>
+#include "kmem.h"
+
+#include "xfs_types.h"
+#include "xfs_cred.h"
+#include "xfs_lrw.h"
+#include "xfs_buf.h"
+
+#define NBBY		8
+#define BBSHIFT		9
+#define BBMASK		((1 << BBSHIFT) - 1)
+#define BN_ALIGN_MASK	((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)
+
+#ifndef GFP_READAHEAD
+#define GFP_READAHEAD	0
+#endif
+
+/*
+ * A backport of the 2.5 scheduler is used by many vendors of 2.4-based
+ * distributions.
+ * We can only guess it's presences by the lack of the SCHED_YIELD flag.
+ * If the heuristic doesn't work, change this define by hand.
+ */
+#ifndef SCHED_YIELD
+#define __HAVE_NEW_SCHEDULER	1
+#endif
+
+/*
+ * cpumask_t is used for supporting NR_CPUS > BITS_PER_LONG.
+ * If support for this is present, migrate_to_cpu exists and provides
+ * a wrapper around the set_cpus_allowed routine.
+ */
+#ifdef copy_cpumask
+#define __HAVE_CPUMASK_T	1
+#endif
+
+#ifndef __HAVE_CPUMASK_T
+# ifndef __HAVE_NEW_SCHEDULER
+#  define migrate_to_cpu(cpu)	\
+	do { current->cpus_allowed = 1UL << (cpu); } while (0)
+# else
+#  define migrate_to_cpu(cpu)	\
+	set_cpus_allowed(current, 1UL << (cpu))
+# endif
+#endif
+
+/*
+ * File wide globals
+ */
+
+STATIC kmem_cache_t *pagebuf_cache;
+
+#define MAX_IO_DAEMONS		NR_CPUS
+#define CPU_TO_DAEMON(cpu)	(cpu)
+STATIC int pb_logio_daemons[MAX_IO_DAEMONS];
+STATIC struct list_head pagebuf_logiodone_tq[MAX_IO_DAEMONS];
+STATIC wait_queue_head_t pagebuf_logiodone_wait[MAX_IO_DAEMONS];
+STATIC int pb_dataio_daemons[MAX_IO_DAEMONS];
+STATIC struct list_head pagebuf_dataiodone_tq[MAX_IO_DAEMONS];
+STATIC wait_queue_head_t pagebuf_dataiodone_wait[MAX_IO_DAEMONS];
+
+/*
+ * For pre-allocated buffer head pool
+ */
+
+#define NR_RESERVED_BH	64
+static wait_queue_head_t	pb_resv_bh_wait;
+static spinlock_t		pb_resv_bh_lock = SPIN_LOCK_UNLOCKED;
+struct buffer_head		*pb_resv_bh = NULL;	/* list of bh */
+int				pb_resv_bh_cnt = 0;	/* # of bh available */
+
+STATIC void pagebuf_daemon_wakeup(int);
+STATIC void _pagebuf_ioapply(page_buf_t *);
+STATIC void pagebuf_delwri_queue(page_buf_t *, int);
+STATIC void pagebuf_runall_queues(struct list_head[]);
+
+/*
+ * Pagebuf module configuration parameters, exported via
+ * /proc/sys/vm/pagebuf
+ */
+
+typedef struct pb_sysctl_val {
+	int	min;
+	int	val;
+	int	max;
+} pb_sysctl_val_t;
+
+struct {
+	pb_sysctl_val_t	flush_interval;	/* interval between runs of the
+					 * delwri flush daemon.  */
+	pb_sysctl_val_t	age_buffer;	/* time for buffer to age before
+					 * we flush it.  */
+	pb_sysctl_val_t	stats_clear;	/* clear the pagebuf stats */
+	pb_sysctl_val_t	debug;		/* debug tracing on or off */
+} pb_params = {
+			  /*	MIN	DFLT	MAX	*/
+	.flush_interval	= {	HZ/2,	HZ,	30*HZ	},
+	.age_buffer	= {	1*HZ,	15*HZ,	300*HZ	},
+	.stats_clear	= {	0,	0,	1	},
+	.debug		= {	0,	0,	1	},
+};
+
+enum {
+	PB_FLUSH_INT = 1,
+	PB_FLUSH_AGE = 2,
+	PB_STATS_CLEAR = 3,
+	PB_DEBUG = 4,
+};
+
+/*
+ * Pagebuf statistics variables
+ */
+
+struct {
+	u_int32_t	pb_get;
+	u_int32_t	pb_create;
+	u_int32_t	pb_get_locked;
+	u_int32_t	pb_get_locked_waited;
+	u_int32_t	pb_busy_locked;
+	u_int32_t	pb_miss_locked;
+	u_int32_t	pb_page_retries;
+	u_int32_t	pb_page_found;
+	u_int32_t	pb_get_read;
+} pbstats;
+
+#define PB_STATS_INC(count)	( pbstats.count++ )
+
+/*
+ * Pagebuf debugging
+ */
+
+#ifdef PAGEBUF_TRACE
+void
+pagebuf_trace(
+	page_buf_t	*pb,
+	char		*id,
+	void		*data,
+	void		*ra)
+{
+	if (!pb_params.debug.val)
+		return;
+	ktrace_enter(pagebuf_trace_buf,
+		pb, id,
+		(void *)(unsigned long)pb->pb_flags,
+		(void *)(unsigned long)pb->pb_hold.counter,
+		(void *)(unsigned long)pb->pb_sema.count.counter,
+		(void *)current,
+		data, ra,
+		(void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff),
+		(void *)(unsigned long)(pb->pb_file_offset & 0xffffffff),
+		(void *)(unsigned long)pb->pb_buffer_length,
+		NULL, NULL, NULL, NULL, NULL);
+}
+ktrace_t *pagebuf_trace_buf;
+#define PAGEBUF_TRACE_SIZE	4096
+#define PB_TRACE(pb, id, data)	\
+	pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0))
+#else
+#define PB_TRACE(pb, id, data)	do { } while (0)
+#endif
+
+#ifdef PAGEBUF_LOCK_TRACKING
+# define PB_SET_OWNER(pb)	((pb)->pb_last_holder = current->pid)
+# define PB_CLEAR_OWNER(pb)	((pb)->pb_last_holder = -1)
+# define PB_GET_OWNER(pb)	((pb)->pb_last_holder)
+#else
+# define PB_SET_OWNER(pb)	do { } while (0)
+# define PB_CLEAR_OWNER(pb)	do { } while (0)
+# define PB_GET_OWNER(pb)	do { } while (0)
+#endif
+
+/*
+ * Pagebuf allocation / freeing.
+ */
+
+#define pb_to_gfp(flags) \
+	(((flags) & PBF_READ_AHEAD) ? GFP_READAHEAD : \
+	 ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL)
+
+#define pb_to_km(flags) \
+	 (((flags) & PBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP)
+
+
+#define pagebuf_allocate(flags) \
+	kmem_zone_alloc(pagebuf_cache, pb_to_km(flags))
+#define pagebuf_deallocate(pb) \
+	kmem_zone_free(pagebuf_cache, (pb));
+
+/*
+ * Pagebuf hashing
+ */
+
+#define NBITS	8
+#define NHASH	(1<<NBITS)
+
+typedef struct {
+	struct list_head	pb_hash;
+	int			pb_count;
+	spinlock_t		pb_hash_lock;
+} pb_hash_t;
+
+STATIC pb_hash_t	pbhash[NHASH];
+#define pb_hash(pb)	&pbhash[pb->pb_hash_index]
+
+STATIC int
+_bhash(
+	struct block_device *bdev,
+	loff_t		base)
+{
+	int		bit, hval;
+
+	base >>= 9;
+	base ^= (unsigned long)bdev / L1_CACHE_BYTES;
+	for (bit = hval = 0; base && bit < sizeof(base) * 8; bit += NBITS) {
+		hval ^= (int)base & (NHASH-1);
+		base >>= NBITS;
+	}
+	return hval;
+}
+
+/*
+ * Mapping of multi-page buffers into contiguous virtual space
+ */
+
+STATIC void *pagebuf_mapout_locked(page_buf_t *);
+
+typedef struct a_list {
+	void		*vm_addr;
+	struct a_list	*next;
+} a_list_t;
+
+STATIC a_list_t		*as_free_head;
+STATIC int		as_list_len;
+STATIC spinlock_t	as_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Try to batch vunmaps because they are costly.
+ */
+STATIC void
+free_address(
+	void		*addr)
+{
+	a_list_t	*aentry;
+
+	aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC);
+	if (aentry) {
+		spin_lock(&as_lock);
+		aentry->next = as_free_head;
+		aentry->vm_addr = addr;
+		as_free_head = aentry;
+		as_list_len++;
+		spin_unlock(&as_lock);
+	} else {
+		vunmap(addr);
+	}
+}
+
+STATIC void
+purge_addresses(void)
+{
+	a_list_t	*aentry, *old;
+
+	if (as_free_head == NULL)
+		return;
+
+	spin_lock(&as_lock);
+	aentry = as_free_head;
+	as_free_head = NULL;
+	as_list_len = 0;
+	spin_unlock(&as_lock);
+
+	while ((old = aentry) != NULL) {
+		vunmap(aentry->vm_addr);
+		aentry = aentry->next;
+		kfree(old);
+	}
+}
+
+/*
+ *	Internal pagebuf object manipulation
+ */
+
+STATIC void
+_pagebuf_initialize(
+	page_buf_t		*pb,
+	pb_target_t		*target,
+	loff_t			range_base,
+	size_t			range_length,
+	page_buf_flags_t	flags)
+{
+	/*
+	 * We don't want certain flags to appear in pb->pb_flags.
+	 */
+	flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD);
+
+	memset(pb, 0, sizeof(page_buf_t));
+	atomic_set(&pb->pb_hold, 1);
+	init_MUTEX_LOCKED(&pb->pb_iodonesema);
+	INIT_LIST_HEAD(&pb->pb_list);
+	INIT_LIST_HEAD(&pb->pb_hash_list);
+	init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */
+	PB_SET_OWNER(pb);
+	pb->pb_target = target;
+	pb->pb_file_offset = range_base;
+	/*
+	 * Set buffer_length and count_desired to the same value initially.
+	 * IO routines should use count_desired, which will be the same in
+	 * most cases but may be reset (e.g. XFS recovery).
+	 */
+	pb->pb_buffer_length = pb->pb_count_desired = range_length;
+	pb->pb_flags = flags | PBF_NONE;
+	pb->pb_bn = PAGE_BUF_DADDR_NULL;
+	atomic_set(&pb->pb_pin_count, 0);
+	init_waitqueue_head(&pb->pb_waiters);
+
+	PB_STATS_INC(pb_create);
+	PB_TRACE(pb, "initialize", target);
+}
+
+/*
+ * Allocate a page array capable of holding a specified number
+ * of pages, and point the page buf at it.
+ */
+STATIC int
+_pagebuf_get_pages(
+	page_buf_t		*pb,
+	int			page_count,
+	page_buf_flags_t	flags)
+{
+	int			gpf_mask = pb_to_gfp(flags);
+
+	/* Make sure that we have a page list */
+	if (pb->pb_pages == NULL) {
+		pb->pb_offset = page_buf_poff(pb->pb_file_offset);
+		pb->pb_page_count = page_count;
+		if (page_count <= PB_PAGES) {
+			pb->pb_pages = pb->pb_page_array;
+		} else {
+			pb->pb_pages = kmalloc(sizeof(struct page *) *
+					page_count, gpf_mask);
+			if (pb->pb_pages == NULL)
+				return -ENOMEM;
+		}
+		memset(pb->pb_pages, 0, sizeof(struct page *) * page_count);
+	}
+	return 0;
+}
+
+/*
+ * Walk a pagebuf releasing all the pages contained within it.
+ */
+STATIC inline void
+_pagebuf_freepages(
+	page_buf_t		*pb)
+{
+	int			buf_index;
+
+	for (buf_index = 0; buf_index < pb->pb_page_count; buf_index++) {
+		struct page	*page = pb->pb_pages[buf_index];
+
+		if (page) {
+			pb->pb_pages[buf_index] = NULL;
+			page_cache_release(page);
+		}
+	}
+}
+
+/*
+ *	_pagebuf_free_object
+ *
+ *	_pagebuf_free_object releases the contents specified buffer.
+ *	The modification state of any associated pages is left unchanged.
+ */
+void
+_pagebuf_free_object(
+	pb_hash_t		*hash,	/* hash bucket for buffer */
+	page_buf_t		*pb)	/* buffer to deallocate	*/
+{
+	page_buf_flags_t	pb_flags = pb->pb_flags;
+
+	PB_TRACE(pb, "free_object", 0);
+	pb->pb_flags |= PBF_FREED;
+
+	if (hash) {
+		if (!list_empty(&pb->pb_hash_list)) {
+			hash->pb_count--;
+			list_del_init(&pb->pb_hash_list);
+		}
+		spin_unlock(&hash->pb_hash_lock);
+	}
+
+	if (!(pb_flags & PBF_FREED)) {
+		/* release any virtual mapping */ ;
+		if (pb->pb_flags & _PBF_ADDR_ALLOCATED) {
+			void *vaddr = pagebuf_mapout_locked(pb);
+			if (vaddr) {
+				free_address(vaddr);
+			}
+		}
+
+		if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
+			if (pb->pb_pages) {
+				/* release the pages in the address list */
+				if ((pb->pb_pages[0]) &&
+				    (pb->pb_flags & _PBF_MEM_SLAB)) {
+					kfree(pb->pb_addr);
+				} else {
+					_pagebuf_freepages(pb);
+				}
+				if (pb->pb_pages != pb->pb_page_array)
+					kfree(pb->pb_pages);
+				pb->pb_pages = NULL;
+			}
+			pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
+		}
+	}
+
+	pagebuf_deallocate(pb);
+}
+
+/*
+ *	_pagebuf_lookup_pages
+ *
+ *	_pagebuf_lookup_pages finds all pages which match the buffer
+ *	in question and the range of file offsets supplied,
+ *	and builds the page list for the buffer, if the
+ *	page list is not already formed or if not all of the pages are
+ *	already in the list. Invalid pages (pages which have not yet been
+ *	read in from disk) are assigned for any pages which are not found.
+ */
+STATIC int
+_pagebuf_lookup_pages(
+	page_buf_t		*pb,
+	struct address_space	*aspace,
+	page_buf_flags_t	flags)
+{
+	loff_t			next_buffer_offset;
+	unsigned long		page_count, pi, index;
+	struct page		*page;
+	int			gfp_mask, retry_count = 5, rval = 0;
+	int			all_mapped, good_pages;
+	size_t			blocksize;
+
+	/* For pagebufs where we want to map an address, do not use
+	 * highmem pages - so that we do not need to use kmap resources
+	 * to access the data.
+	 *
+	 * For pages where the caller has indicated there may be resource
+	 * contention (e.g. called from a transaction) do not flush
+	 * delalloc pages to obtain memory.
+	 */
+
+	if (flags & PBF_READ_AHEAD) {
+		gfp_mask = GFP_READAHEAD;
+		retry_count = 0;
+	} else if (flags & PBF_DONT_BLOCK) {
+		gfp_mask = GFP_NOFS;
+	} else if (flags & PBF_MAPPABLE) {
+		gfp_mask = GFP_KERNEL;
+	} else {
+		gfp_mask = GFP_HIGHUSER;
+	}
+
+	next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length;
+
+	good_pages = page_count = (page_buf_btoc(next_buffer_offset) -
+				   page_buf_btoct(pb->pb_file_offset));
+
+	if (pb->pb_flags & _PBF_ALL_PAGES_MAPPED) {
+		/* Bring pages forward in cache */
+		for (pi = 0; pi < page_count; pi++) {
+			mark_page_accessed(pb->pb_pages[pi]);
+		}
+		if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) {
+			all_mapped = 1;
+			goto mapit;
+		}
+		return 0;
+	}
+
+	/* Ensure pb_pages field has been initialised */
+	rval = _pagebuf_get_pages(pb, page_count, flags);
+	if (rval)
+		return rval;
+
+	all_mapped = 1;
+	blocksize = pb->pb_target->pbr_bsize;
+
+	/* Enter the pages in the page list */
+	index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT;
+	for (pi = 0; pi < page_count; pi++, index++) {
+		if (pb->pb_pages[pi] == 0) {
+		      retry:
+			page = find_or_create_page(aspace, index, gfp_mask);
+			if (!page) {
+				if (--retry_count > 0) {
+					PB_STATS_INC(pb_page_retries);
+					pagebuf_daemon_wakeup(1);
+					current->state = TASK_UNINTERRUPTIBLE;
+					schedule_timeout(10);
+					goto retry;
+				}
+				rval = -ENOMEM;
+				all_mapped = 0;
+				continue;
+			}
+			PB_STATS_INC(pb_page_found);
+			mark_page_accessed(page);
+			pb->pb_pages[pi] = page;
+		} else {
+			page = pb->pb_pages[pi];
+			lock_page(page);
+		}
+
+		/* If we need to do I/O on a page record the fact */
+		if (!Page_Uptodate(page)) {
+			good_pages--;
+			if ((blocksize == PAGE_CACHE_SIZE) &&
+			    (flags & PBF_READ))
+				pb->pb_locked = 1;
+		}
+	}
+
+	if (!pb->pb_locked) {
+		for (pi = 0; pi < page_count; pi++) {
+			if (pb->pb_pages[pi])
+				unlock_page(pb->pb_pages[pi]);
+		}
+	}
+
+mapit:
+	pb->pb_flags |= _PBF_MEM_ALLOCATED;
+	if (all_mapped) {
+		pb->pb_flags |= _PBF_ALL_PAGES_MAPPED;
+
+		/* A single page buffer is always mappable */
+		if (page_count == 1) {
+			pb->pb_addr = (caddr_t)
+				page_address(pb->pb_pages[0]) + pb->pb_offset;
+			pb->pb_flags |= PBF_MAPPED;
+		} else if (flags & PBF_MAPPED) {
+			if (as_list_len > 64)
+				purge_addresses();
+			pb->pb_addr = vmap(pb->pb_pages, page_count,
+					VM_ALLOC, PAGE_KERNEL);
+			if (pb->pb_addr == NULL)
+				return -ENOMEM;
+			pb->pb_addr += pb->pb_offset;
+			pb->pb_flags |= PBF_MAPPED | _PBF_ADDR_ALLOCATED;
+		}
+	}
+	/* If some pages were found with data in them
+	 * we are not in PBF_NONE state.
+	 */
+	if (good_pages != 0) {
+		pb->pb_flags &= ~(PBF_NONE);
+		if (good_pages != page_count) {
+			pb->pb_flags |= PBF_PARTIAL;
+		}
+	}
+
+	PB_TRACE(pb, "lookup_pages", (long)good_pages);
+
+	return rval;
+}
+
+
+/*
+ *	Pre-allocation of a pool of buffer heads for use in
+ *	low-memory situations.
+ */
+
+/*
+ *	_pagebuf_prealloc_bh
+ *
+ *	Pre-allocate a pool of "count" buffer heads at startup.
+ *	Puts them on a list at "pb_resv_bh"
+ *	Returns number of bh actually allocated to pool.
+ */
+STATIC int
+_pagebuf_prealloc_bh(
+	int			count)
+{
+	struct buffer_head	*bh;
+	int			i;
+
+	for (i = 0; i < count; i++) {
+		bh = kmem_cache_alloc(bh_cachep, SLAB_KERNEL);
+		if (!bh)
+			break;
+		bh->b_pprev = &pb_resv_bh;
+		bh->b_next = pb_resv_bh;
+		pb_resv_bh = bh;
+		pb_resv_bh_cnt++;
+	}
+	return i;
+}
+
+/*
+ *	_pagebuf_get_prealloc_bh
+ *
+ *	Get one buffer head from our pre-allocated pool.
+ *	If pool is empty, sleep 'til one comes back in.
+ *	Returns aforementioned buffer head.
+ */
+STATIC struct buffer_head *
+_pagebuf_get_prealloc_bh(void)
+{
+	unsigned long		flags;
+	struct buffer_head	*bh;
+	DECLARE_WAITQUEUE	(wait, current);
+
+	spin_lock_irqsave(&pb_resv_bh_lock, flags);
+
+	if (pb_resv_bh_cnt < 1) {
+		add_wait_queue(&pb_resv_bh_wait, &wait);
+		do {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			spin_unlock_irqrestore(&pb_resv_bh_lock, flags);
+			blk_run_queues();
+			schedule();
+			spin_lock_irqsave(&pb_resv_bh_lock, flags);
+		} while (pb_resv_bh_cnt < 1);
+		__set_current_state(TASK_RUNNING);
+		remove_wait_queue(&pb_resv_bh_wait, &wait);
+	}
+
+	BUG_ON(pb_resv_bh_cnt < 1);
+	BUG_ON(!pb_resv_bh);
+
+	bh = pb_resv_bh;
+	pb_resv_bh = bh->b_next;
+	pb_resv_bh_cnt--;
+
+	spin_unlock_irqrestore(&pb_resv_bh_lock, flags);
+	return bh;
+}
+
+/*
+ *	_pagebuf_free_bh
+ *
+ *	Take care of buffer heads that we're finished with.
+ *	Call this instead of just kmem_cache_free(bh_cachep, bh)
+ *	when you're done with a bh.
+ *
+ *	If our pre-allocated pool is full, just free the buffer head.
+ *	Otherwise, put it back in the pool, and wake up anybody
+ *	waiting for one.
+ */
+STATIC inline void
+_pagebuf_free_bh(
+	struct buffer_head	*bh)
+{
+	unsigned long		flags;
+	int			free;
+
+	if (! (free = pb_resv_bh_cnt >= NR_RESERVED_BH)) {
+		spin_lock_irqsave(&pb_resv_bh_lock, flags);
+
+		if (! (free = pb_resv_bh_cnt >= NR_RESERVED_BH)) {
+			bh->b_pprev = &pb_resv_bh;
+			bh->b_next = pb_resv_bh;
+			pb_resv_bh = bh;
+			pb_resv_bh_cnt++;
+
+			if (waitqueue_active(&pb_resv_bh_wait)) {
+				wake_up(&pb_resv_bh_wait);
+			}
+		}
+
+		spin_unlock_irqrestore(&pb_resv_bh_lock, flags);
+	}
+	if (free) {
+		kmem_cache_free(bh_cachep, bh);
+	}
+}
+
+/*
+ *	Finding and Reading Buffers
+ */
+
+/*
+ *	_pagebuf_find
+ *
+ *	Looks up, and creates if absent, a lockable buffer for
+ *	a given range of an inode.  The buffer is returned
+ *	locked.	 If other overlapping buffers exist, they are
+ *	released before the new buffer is created and locked,
+ *	which may imply that this call will block until those buffers
+ *	are unlocked.  No I/O is implied by this call.
+ */
+STATIC page_buf_t *
+_pagebuf_find(				/* find buffer for block	*/
+	pb_target_t		*target,/* target for block		*/
+	loff_t			ioff,	/* starting offset of range	*/
+	size_t			isize,	/* length of range		*/
+	page_buf_flags_t	flags,	/* PBF_TRYLOCK			*/
+	page_buf_t		*new_pb)/* newly allocated buffer	*/
+{
+	loff_t			range_base;
+	size_t			range_length;
+	int			hval;
+	pb_hash_t		*h;
+	struct list_head	*p;
+	page_buf_t		*pb;
+	int			not_locked;
+
+	range_base = (ioff << BBSHIFT);
+	range_length = (isize << BBSHIFT);
+
+	/* Ensure we never do IOs smaller than the sector size */
+	BUG_ON(range_length < (1 << target->pbr_sshift));
+
+	/* Ensure we never do IOs that are not sector aligned */
+	BUG_ON(range_base & (loff_t)target->pbr_smask);
+
+	hval = _bhash(target->pbr_bdev, range_base);
+	h = &pbhash[hval];
+
+	spin_lock(&h->pb_hash_lock);
+	list_for_each(p, &h->pb_hash) {
+		pb = list_entry(p, page_buf_t, pb_hash_list);
+
+		if ((target == pb->pb_target) &&
+		    (pb->pb_file_offset == range_base) &&
+		    (pb->pb_buffer_length == range_length)) {
+			if (pb->pb_flags & PBF_FREED)
+				break;
+			/* If we look at something bring it to the
+			 * front of the list for next time
+			 */
+			list_del(&pb->pb_hash_list);
+			list_add(&pb->pb_hash_list, &h->pb_hash);
+			goto found;
+		}
+	}
+
+	/* No match found */
+	if (new_pb) {
+		_pagebuf_initialize(new_pb, target, range_base,
+				range_length, flags | _PBF_LOCKABLE);
+		new_pb->pb_hash_index = hval;
+		h->pb_count++;
+		list_add(&new_pb->pb_hash_list, &h->pb_hash);
+	} else {
+		PB_STATS_INC(pb_miss_locked);
+	}
+
+	spin_unlock(&h->pb_hash_lock);
+	return (new_pb);
+
+found:
+	atomic_inc(&pb->pb_hold);
+	spin_unlock(&h->pb_hash_lock);
+
+	/* Attempt to get the semaphore without sleeping,
+	 * if this does not work then we need to drop the
+	 * spinlock and do a hard attempt on the semaphore.
+	 */
+	not_locked = down_trylock(&pb->pb_sema);
+	if (not_locked) {
+		if (!(flags & PBF_TRYLOCK)) {
+			/* wait for buffer ownership */
+			PB_TRACE(pb, "get_lock", 0);
+			pagebuf_lock(pb);
+			PB_STATS_INC(pb_get_locked_waited);
+		} else {
+			/* We asked for a trylock and failed, no need
+			 * to look at file offset and length here, we
+			 * know that this pagebuf at least overlaps our
+			 * pagebuf and is locked, therefore our buffer
+			 * either does not exist, or is this buffer
+			 */
+
+			pagebuf_rele(pb);
+			PB_STATS_INC(pb_busy_locked);
+			return (NULL);
+		}
+	} else {
+		/* trylock worked */
+		PB_SET_OWNER(pb);
+	}
+
+	if (pb->pb_flags & PBF_STALE)
+		pb->pb_flags &= PBF_MAPPABLE | \
+				PBF_MAPPED | \
+				_PBF_LOCKABLE | \
+				_PBF_ALL_PAGES_MAPPED | \
+				_PBF_ADDR_ALLOCATED | \
+				_PBF_MEM_ALLOCATED | \
+				_PBF_MEM_SLAB;
+	PB_TRACE(pb, "got_lock", 0);
+	PB_STATS_INC(pb_get_locked);
+	return (pb);
+}
+
+
+/*
+ *	pagebuf_find
+ *
+ *	pagebuf_find returns a buffer matching the specified range of
+ *	data for the specified target, if any of the relevant blocks
+ *	are in memory.  The buffer may have unallocated holes, if
+ *	some, but not all, of the blocks are in memory.  Even where
+ *	pages are present in the buffer, not all of every page may be
+ *	valid.
+ */
+page_buf_t *
+pagebuf_find(				/* find buffer for block	*/
+					/* if the block is in memory	*/
+	pb_target_t		*target,/* target for block		*/
+	loff_t			ioff,	/* starting offset of range	*/
+	size_t			isize,	/* length of range		*/
+	page_buf_flags_t	flags)	/* PBF_TRYLOCK			*/
+{
+	return _pagebuf_find(target, ioff, isize, flags, NULL);
+}
+
+/*
+ *	pagebuf_get
+ *
+ *	pagebuf_get assembles a buffer covering the specified range.
+ *	Some or all of the blocks in the range may be valid.  Storage
+ *	in memory for all portions of the buffer will be allocated,
+ *	although backing storage may not be.  If PBF_READ is set in
+ *	flags, pagebuf_iostart is called also.
+ */
+page_buf_t *
+pagebuf_get(				/* allocate a buffer		*/
+	pb_target_t		*target,/* target for buffer		*/
+	loff_t			ioff,	/* starting offset of range	*/
+	size_t			isize,	/* length of range		*/
+	page_buf_flags_t	flags)	/* PBF_TRYLOCK			*/
+{
+	page_buf_t		*pb, *new_pb;
+	int			error;
+
+	new_pb = pagebuf_allocate(flags);
+	if (unlikely(!new_pb))
+		return (NULL);
+
+	pb = _pagebuf_find(target, ioff, isize, flags, new_pb);
+	if (pb != new_pb) {
+		pagebuf_deallocate(new_pb);
+		if (unlikely(!pb))
+			return (NULL);
+	}
+
+	PB_STATS_INC(pb_get);
+
+	/* fill in any missing pages */
+	error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags);
+	if (unlikely(error)) {
+		pagebuf_free(pb);
+		return (NULL);
+	}
+
+	/*
+	 * Always fill in the block number now, the mapped cases can do
+	 * their own overlay of this later.
+	 */
+	pb->pb_bn = ioff;
+	pb->pb_count_desired = pb->pb_buffer_length;
+
+	if (flags & PBF_READ) {
+		if (PBF_NOT_DONE(pb)) {
+			PB_TRACE(pb, "get_read", (unsigned long)flags);
+			PB_STATS_INC(pb_get_read);
+			pagebuf_iostart(pb, flags);
+		} else if (flags & PBF_ASYNC) {
+			PB_TRACE(pb, "get_read_async", (unsigned long)flags);
+			/*
+			 * Read ahead call which is already satisfied,
+			 * drop the buffer
+			 */
+			if (flags & (PBF_LOCK | PBF_TRYLOCK))
+				pagebuf_unlock(pb);
+			pagebuf_rele(pb);
+			return NULL;
+		} else {
+			PB_TRACE(pb, "get_read_done", (unsigned long)flags);
+			/* We do not want read in the flags */
+			pb->pb_flags &= ~PBF_READ;
+		}
+	} else {
+		PB_TRACE(pb, "get_write", (unsigned long)flags);
+	}
+	return (pb);
+}
+
+/*
+ * Create a skeletal pagebuf (no pages associated with it).
+ */
+page_buf_t *
+pagebuf_lookup(
+	struct pb_target	*target,
+	loff_t			ioff,
+	size_t			isize,
+	page_buf_flags_t	flags)
+{
+	page_buf_t		*pb;
+
+	flags |= _PBF_PRIVATE_BH | _PBF_LOCKABLE;
+	pb = pagebuf_allocate(flags);
+	if (pb) {
+		_pagebuf_initialize(pb, target, ioff, isize, flags);
+	}
+	return pb;
+}
+
+/*
+ * If we are not low on memory then do the readahead in a deadlock
+ * safe manner.
+ */
+void
+pagebuf_readahead(
+	pb_target_t		*target,
+	loff_t			ioff,
+	size_t			isize,
+	page_buf_flags_t	flags)
+{
+	flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD);
+	pagebuf_get(target, ioff, isize, flags);
+}
+
+page_buf_t *
+pagebuf_get_empty(
+	size_t			len,
+	pb_target_t		*target)
+{
+	page_buf_t		*pb;
+
+	pb = pagebuf_allocate(_PBF_LOCKABLE);
+	if (pb)
+		_pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE);
+	return pb;
+}
+
+static inline struct page *
+mem_to_page(
+	void			*addr)
+{
+	if (((unsigned long)addr < VMALLOC_START) ||
+	    ((unsigned long)addr >= VMALLOC_END)) {
+		return virt_to_page(addr);
+	} else {
+		return vmalloc_to_page(addr);
+	}
+}
+
+int
+pagebuf_associate_memory(
+	page_buf_t		*pb,
+	void			*mem,
+	size_t			len)
+{
+	int			rval;
+	int			i = 0;
+	size_t			ptr;
+	size_t			end, end_cur;
+	off_t			offset;
+	int			page_count;
+
+	page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT;
+	offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK);
+	if (offset && (len > PAGE_CACHE_SIZE))
+		page_count++;
+
+	/* Free any previous set of page pointers */
+	if (pb->pb_pages && (pb->pb_pages != pb->pb_page_array)) {
+		kfree(pb->pb_pages);
+	}
+	pb->pb_pages = NULL;
+	pb->pb_addr = mem;
+
+	rval = _pagebuf_get_pages(pb, page_count, 0);
+	if (rval)
+		return rval;
+
+	pb->pb_offset = offset;
+	ptr = (size_t) mem & PAGE_CACHE_MASK;
+	end = PAGE_CACHE_ALIGN((size_t) mem + len);
+	end_cur = end;
+	/* set up first page */
+	pb->pb_pages[0] = mem_to_page(mem);
+
+	ptr += PAGE_CACHE_SIZE;
+	pb->pb_page_count = ++i;
+	while (ptr < end) {
+		pb->pb_pages[i] = mem_to_page((void *)ptr);
+		pb->pb_page_count = ++i;
+		ptr += PAGE_CACHE_SIZE;
+	}
+	pb->pb_locked = 0;
+
+	pb->pb_count_desired = pb->pb_buffer_length = len;
+	pb->pb_flags |= PBF_MAPPED | _PBF_PRIVATE_BH;
+
+	return 0;
+}
+
+page_buf_t *
+pagebuf_get_no_daddr(
+	size_t			len,
+	pb_target_t		*target)
+{
+	int			rval;
+	void			*rmem = NULL;
+	page_buf_flags_t	flags = _PBF_LOCKABLE | PBF_FORCEIO;
+	page_buf_t		*pb;
+	size_t			tlen = 0;
+
+	if (unlikely(len > 0x20000))
+		return NULL;
+
+	pb = pagebuf_allocate(flags);
+	if (!pb)
+		return NULL;
+
+	_pagebuf_initialize(pb, target, 0, len, flags);
+
+	do {
+		if (tlen == 0) {
+			tlen = len; /* first time */
+		} else {
+			kfree(rmem); /* free the mem from the previous try */
+			tlen <<= 1; /* double the size and try again */
+		}
+		if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) {
+			pagebuf_free(pb);
+			return NULL;
+		}
+	} while ((size_t)rmem != ((size_t)rmem & ~target->pbr_smask));
+
+	if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) {
+		kfree(rmem);
+		pagebuf_free(pb);
+		return NULL;
+	}
+	/* otherwise pagebuf_free just ignores it */
+	pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB);
+	PB_CLEAR_OWNER(pb);
+	up(&pb->pb_sema);	/* Return unlocked pagebuf */
+
+	PB_TRACE(pb, "no_daddr", rmem);
+
+	return pb;
+}
+
+
+/*
+ *	pagebuf_hold
+ *
+ *	Increment reference count on buffer, to hold the buffer concurrently
+ *	with another thread which may release (free) the buffer asynchronously.
+ *
+ *	Must hold the buffer already to call this function.
+ */
+void
+pagebuf_hold(
+	page_buf_t		*pb)
+{
+	atomic_inc(&pb->pb_hold);
+	PB_TRACE(pb, "hold", 0);
+}
+
+/*
+ *	pagebuf_free
+ *
+ *	pagebuf_free releases the specified buffer.  The modification
+ *	state of any associated pages is left unchanged.
+ */
+void
+pagebuf_free(
+	page_buf_t		*pb)
+{
+	if (pb->pb_flags & _PBF_LOCKABLE) {
+		pb_hash_t	*h = pb_hash(pb);
+
+		spin_lock(&h->pb_hash_lock);
+		_pagebuf_free_object(h, pb);
+	} else {
+		_pagebuf_free_object(NULL, pb);
+	}
+}
+
+/*
+ *	pagebuf_rele
+ *
+ *	pagebuf_rele releases a hold on the specified buffer.  If the
+ *	the hold count is 1, pagebuf_rele calls pagebuf_free.
+ */
+void
+pagebuf_rele(
+	page_buf_t		*pb)
+{
+	pb_hash_t		*h;
+
+	PB_TRACE(pb, "rele", pb->pb_relse);
+	if (pb->pb_flags & _PBF_LOCKABLE) {
+		h = pb_hash(pb);
+		spin_lock(&h->pb_hash_lock);
+	} else {
+		h = NULL;
+	}
+
+	if (atomic_dec_and_test(&pb->pb_hold)) {
+		int		do_free = 1;
+
+		if (pb->pb_relse) {
+			atomic_inc(&pb->pb_hold);
+			if (h)
+				spin_unlock(&h->pb_hash_lock);
+			(*(pb->pb_relse)) (pb);
+			do_free = 0;
+		}
+		if (pb->pb_flags & PBF_DELWRI) {
+			pb->pb_flags |= PBF_ASYNC;
+			atomic_inc(&pb->pb_hold);
+			if (h && do_free)
+				spin_unlock(&h->pb_hash_lock);
+			pagebuf_delwri_queue(pb, 0);
+			do_free = 0;
+		} else if (pb->pb_flags & PBF_FS_MANAGED) {
+			if (h)
+				spin_unlock(&h->pb_hash_lock);
+			do_free = 0;
+		}
+
+		if (do_free) {
+			_pagebuf_free_object(h, pb);
+		}
+	} else if (h) {
+		spin_unlock(&h->pb_hash_lock);
+	}
+}
+
+
+/*
+ *	Mutual exclusion on buffers.  Locking model:
+ *
+ *	Buffers associated with inodes for which buffer locking
+ *	is not enabled are not protected by semaphores, and are
+ *	assumed to be exclusively owned by the caller.  There is a
+ *	spinlock in the buffer, used by the caller when concurrent
+ *	access is possible.
+ */
+
+/*
+ *	pagebuf_cond_lock
+ *
+ *	pagebuf_cond_lock locks a buffer object, if it is not already locked.
+ *	Note that this in no way
+ *	locks the underlying pages, so it is only useful for synchronizing
+ *	concurrent use of page buffer objects, not for synchronizing independent
+ *	access to the underlying pages.
+ */
+int
+pagebuf_cond_lock(			/* lock buffer, if not locked	*/
+					/* returns -EBUSY if locked)	*/
+	page_buf_t		*pb)
+{
+	int			locked;
+
+	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
+	locked = down_trylock(&pb->pb_sema) == 0;
+	if (locked) {
+		PB_SET_OWNER(pb);
+	}
+	PB_TRACE(pb, "cond_lock", (long)locked);
+	return(locked ? 0 : -EBUSY);
+}
+
+/*
+ *	pagebuf_lock_value
+ *
+ *	Return lock value for a pagebuf
+ */
+int
+pagebuf_lock_value(
+	page_buf_t		*pb)
+{
+	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
+	return(atomic_read(&pb->pb_sema.count));
+}
+
+/*
+ *	pagebuf_lock
+ *
+ *	pagebuf_lock locks a buffer object.  Note that this in no way
+ *	locks the underlying pages, so it is only useful for synchronizing
+ *	concurrent use of page buffer objects, not for synchronizing independent
+ *	access to the underlying pages.
+ */
+int
+pagebuf_lock(
+	page_buf_t		*pb)
+{
+	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
+
+	PB_TRACE(pb, "lock", 0);
+	if (atomic_read(&pb->pb_io_remaining))
+		blk_run_queues();
+	down(&pb->pb_sema);
+	PB_SET_OWNER(pb);
+	PB_TRACE(pb, "locked", 0);
+	return 0;
+}
+
+/*
+ *	pagebuf_unlock
+ *
+ *	pagebuf_unlock releases the lock on the buffer object created by
+ *	pagebuf_lock or pagebuf_cond_lock (not any
+ *	pinning of underlying pages created by pagebuf_pin).
+ */
+void
+pagebuf_unlock(				/* unlock buffer		*/
+	page_buf_t		*pb)	/* buffer to unlock		*/
+{
+	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
+	PB_CLEAR_OWNER(pb);
+	up(&pb->pb_sema);
+	PB_TRACE(pb, "unlock", 0);
+}
+
+
+/*
+ *	Pinning Buffer Storage in Memory
+ */
+
+/*
+ *	pagebuf_pin
+ *
+ *	pagebuf_pin locks all of the memory represented by a buffer in
+ *	memory.  Multiple calls to pagebuf_pin and pagebuf_unpin, for
+ *	the same or different buffers affecting a given page, will
+ *	properly count the number of outstanding "pin" requests.  The
+ *	buffer may be released after the pagebuf_pin and a different
+ *	buffer used when calling pagebuf_unpin, if desired.
+ *	pagebuf_pin should be used by the file system when it wants be
+ *	assured that no attempt will be made to force the affected
+ *	memory to disk.	 It does not assure that a given logical page
+ *	will not be moved to a different physical page.
+ */
+void
+pagebuf_pin(
+	page_buf_t		*pb)
+{
+	atomic_inc(&pb->pb_pin_count);
+	PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter);
+}
+
+/*
+ *	pagebuf_unpin
+ *
+ *	pagebuf_unpin reverses the locking of memory performed by
+ *	pagebuf_pin.  Note that both functions affected the logical
+ *	pages associated with the buffer, not the buffer itself.
+ */
+void
+pagebuf_unpin(
+	page_buf_t		*pb)
+{
+	if (atomic_dec_and_test(&pb->pb_pin_count)) {
+		wake_up_all(&pb->pb_waiters);
+	}
+	PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter);
+}
+
+int
+pagebuf_ispin(
+	page_buf_t		*pb)
+{
+	return atomic_read(&pb->pb_pin_count);
+}
+
+/*
+ *	pagebuf_wait_unpin
+ *
+ *	pagebuf_wait_unpin waits until all of the memory associated
+ *	with the buffer is not longer locked in memory.  It returns
+ *	immediately if none of the affected pages are locked.
+ */
+static inline void
+_pagebuf_wait_unpin(
+	page_buf_t		*pb)
+{
+	DECLARE_WAITQUEUE	(wait, current);
+
+	if (atomic_read(&pb->pb_pin_count) == 0)
+		return;
+
+	add_wait_queue(&pb->pb_waiters, &wait);
+	for (;;) {
+		current->state = TASK_UNINTERRUPTIBLE;
+		if (atomic_read(&pb->pb_pin_count) == 0)
+			break;
+		if (atomic_read(&pb->pb_io_remaining))
+			blk_run_queues();
+		schedule();
+	}
+	remove_wait_queue(&pb->pb_waiters, &wait);
+	current->state = TASK_RUNNING;
+}
+
+
+/*
+ *	Buffer Utility Routines
+ */
+
+/*
+ *	pagebuf_iodone
+ *
+ *	pagebuf_iodone marks a buffer for which I/O is in progress
+ *	done with respect to that I/O.	The pb_iodone routine, if
+ *	present, will be called as a side-effect.
+ */
+void
+pagebuf_iodone_sched(
+	void			*v)
+{
+	page_buf_t		*pb = (page_buf_t *)v;
+
+	if (pb->pb_iodone) {
+		(*(pb->pb_iodone)) (pb);
+		return;
+	}
+
+	if (pb->pb_flags & PBF_ASYNC) {
+		if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse)
+			pagebuf_unlock(pb);
+		pagebuf_rele(pb);
+	}
+}
+
+void
+pagebuf_iodone(
+	page_buf_t		*pb,
+	int			dataio,
+	int			schedule)
+{
+	pb->pb_flags &= ~(PBF_READ | PBF_WRITE);
+	if (pb->pb_error == 0) {
+		pb->pb_flags &= ~(PBF_PARTIAL | PBF_NONE);
+	}
+
+	PB_TRACE(pb, "iodone", pb->pb_iodone);
+
+	if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
+		if (schedule) {
+			int	daemon = CPU_TO_DAEMON(smp_processor_id());
+
+			INIT_TQUEUE(&pb->pb_iodone_sched,
+				pagebuf_iodone_sched, (void *)pb);
+			queue_task(&pb->pb_iodone_sched, dataio ?
+				&pagebuf_dataiodone_tq[daemon] :
+				&pagebuf_logiodone_tq[daemon]);
+			wake_up(dataio ?
+				&pagebuf_dataiodone_wait[daemon] :
+				&pagebuf_logiodone_wait[daemon]);
+		} else {
+			pagebuf_iodone_sched(pb);
+		}
+	} else {
+		up(&pb->pb_iodonesema);
+	}
+}
+
+/*
+ *	pagebuf_ioerror
+ *
+ *	pagebuf_ioerror sets the error code for a buffer.
+ */
+void
+pagebuf_ioerror(			/* mark/clear buffer error flag */
+	page_buf_t		*pb,	/* buffer to mark		*/
+	unsigned int		error)	/* error to store (0 if none)	*/
+{
+	pb->pb_error = error;
+	PB_TRACE(pb, "ioerror", (unsigned long)error);
+}
+
+/*
+ *	pagebuf_iostart
+ *
+ *	pagebuf_iostart initiates I/O on a buffer, based on the flags supplied.
+ *	If necessary, it will arrange for any disk space allocation required,
+ *	and it will break up the request if the block mappings require it.
+ *	The pb_iodone routine in the buffer supplied will only be called
+ *	when all of the subsidiary I/O requests, if any, have been completed.
+ *	pagebuf_iostart calls the pagebuf_ioinitiate routine or
+ *	pagebuf_iorequest, if the former routine is not defined, to start
+ *	the I/O on a given low-level request.
+ */
+int
+pagebuf_iostart(			/* start I/O on a buffer	  */
+	page_buf_t		*pb,	/* buffer to start		  */
+	page_buf_flags_t	flags)	/* PBF_LOCK, PBF_ASYNC, PBF_READ, */
+					/* PBF_WRITE, PBF_DELWRI,	  */
+					/* PBF_SYNC, PBF_DONT_BLOCK	  */
+{
+	int			status = 0;
+
+	PB_TRACE(pb, "iostart", (unsigned long)flags);
+
+	if (flags & PBF_DELWRI) {
+		pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC);
+		pb->pb_flags |= flags &
+				(PBF_DELWRI | PBF_ASYNC | PBF_SYNC);
+		pagebuf_delwri_queue(pb, 1);
+		return status;
+	}
+
+	pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \
+			PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES);
+	pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \
+			PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES);
+
+	BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL);
+
+	/* For writes allow an alternate strategy routine to precede
+	 * the actual I/O request (which may not be issued at all in
+	 * a shutdown situation, for example).
+	 */
+	status = (flags & PBF_WRITE) ?
+		pagebuf_iostrategy(pb) : pagebuf_iorequest(pb);
+
+	/* Wait for I/O if we are not an async request.
+	 * Note: async I/O request completion will release the buffer,
+	 * and that can already be done by this point.  So using the
+	 * buffer pointer from here on, after async I/O, is invalid.
+	 */
+	if (!status && !(flags & PBF_ASYNC))
+		status = pagebuf_iowait(pb);
+
+	return status;
+}
+
+
+/*
+ * Helper routines for pagebuf_iorequest (pagebuf I/O completion)
+ */
+
+STATIC __inline__ int
+_pagebuf_iolocked(
+	page_buf_t		*pb)
+{
+	ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE));
+	if (pb->pb_target->pbr_bsize < PAGE_CACHE_SIZE)
+		return pb->pb_locked;
+	if (pb->pb_flags & PBF_READ)
+		return pb->pb_locked;
+	return (!(pb->pb_flags & _PBF_LOCKABLE));
+}
+
+STATIC void
+_pagebuf_iodone(
+	page_buf_t		*pb,
+	int			schedule)
+{
+	int			i;
+
+	if (atomic_dec_and_test(&pb->pb_io_remaining) != 1)
+		return;
+
+	if (_pagebuf_iolocked(pb))
+		for (i = 0; i < pb->pb_page_count; i++)
+			unlock_page(pb->pb_pages[i]);
+	pb->pb_locked = 0;
+	pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), schedule);
+}
+
+STATIC void
+_end_io_pagebuf(
+	struct buffer_head	*bh,
+	int			uptodate,
+	int			fullpage)
+{
+	struct page		*page = bh->b_page;
+	page_buf_t		*pb = (page_buf_t *)bh->b_private;
+
+	mark_buffer_uptodate(bh, uptodate);
+	put_bh(bh);
+
+	if (!uptodate) {
+		SetPageError(page);
+		pb->pb_error = EIO;
+	}
+
+	if (fullpage) {
+		unlock_buffer(bh);
+		_pagebuf_free_bh(bh);
+		if (!PageError(page))
+			SetPageUptodate(page);
+	} else {
+		static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
+		struct buffer_head *bp;
+		unsigned long flags;
+
+		ASSERT(PageLocked(page));
+		spin_lock_irqsave(&page_uptodate_lock, flags);
+		clear_buffer_async(bh);
+		unlock_buffer(bh);
+		for (bp = bh->b_this_page; bp != bh; bp = bp->b_this_page) {
+			if (buffer_locked(bp)) {
+				if (buffer_async(bp))
+					break;
+			} else if (!buffer_uptodate(bp))
+				break;
+		}
+		spin_unlock_irqrestore(&page_uptodate_lock, flags);
+		if (bp == bh && !PageError(page))
+			SetPageUptodate(page);
+	}
+
+	_pagebuf_iodone(pb, 1);
+}
+
+STATIC void
+_pagebuf_end_io_complete_pages(
+	struct buffer_head	*bh,
+	int			uptodate)
+{
+	_end_io_pagebuf(bh, uptodate, 1);
+}
+
+STATIC void
+_pagebuf_end_io_partial_pages(
+	struct buffer_head	*bh,
+	int			uptodate)
+{
+	_end_io_pagebuf(bh, uptodate, 0);
+}
+
+
+/*
+ * Initiate I/O on part of a page we are interested in
+ */
+STATIC int
+_pagebuf_page_io(
+	struct page		*page,	/* Page structure we are dealing with */
+	pb_target_t		*pbr,	/* device parameters (bsz, ssz, dev) */
+	page_buf_t		*pb,	/* pagebuf holding it, can be NULL */
+	page_buf_daddr_t	bn,	/* starting block number */
+	size_t			pg_offset,	/* starting offset in page */
+	size_t			pg_length,	/* count of data to process */
+	int			rw,	/* read/write operation */
+	int			flush)
+{
+	size_t			sector;
+	size_t			blk_length = 0;
+	struct buffer_head	*bh, *head, *bufferlist[MAX_BUF_PER_PAGE];
+	int			sector_shift = pbr->pbr_sshift;
+	int			i = 0, cnt = 0;
+	int			public_bh = 0;
+	int			multi_ok;
+
+	if ((pbr->pbr_bsize < PAGE_CACHE_SIZE) &&
+	    !(pb->pb_flags & _PBF_PRIVATE_BH)) {
+		int		cache_ok;
+
+		cache_ok = !((pb->pb_flags & PBF_FORCEIO) || (rw == WRITE));
+		public_bh = multi_ok = 1;
+		sector = 1 << sector_shift;
+
+		ASSERT(PageLocked(page));
+		if (!page_has_buffers(page))
+			create_empty_buffers(page, pbr->pbr_kdev, sector);
+
+		i = sector >> BBSHIFT;
+		bn -= (pg_offset >> BBSHIFT);
+
+		/* Find buffer_heads belonging to just this pagebuf */
+		bh = head = page_buffers(page);
+		do {
+			if (buffer_uptodate(bh) && cache_ok)
+				continue;
+			if (blk_length < pg_offset)
+				continue;
+			if (blk_length >= pg_offset + pg_length)
+				break;
+
+			lock_buffer(bh);
+			get_bh(bh);
+			bh->b_size = sector;
+			bh->b_blocknr = bn;
+			bufferlist[cnt++] = bh;
+
+		} while ((bn += i),
+			 (blk_length += sector),
+			  (bh = bh->b_this_page) != head);
+
+		goto request;
+	}
+
+	/* Calculate the block offsets and length we will be using */
+	if (pg_offset) {
+		size_t		block_offset;
+
+		block_offset = pg_offset >> sector_shift;
+		block_offset = pg_offset - (block_offset << sector_shift);
+		blk_length = (pg_length + block_offset + pbr->pbr_smask) >>
+								sector_shift;
+	} else {
+		blk_length = (pg_length + pbr->pbr_smask) >> sector_shift;
+	}
+
+	/* This will attempt to make a request bigger than the sector
+	 * size if we are well aligned.
+	 */
+	switch (pb->pb_target->pbr_flags) {
+	case 0:
+		sector = blk_length << sector_shift;
+		blk_length = 1;
+		break;
+	case PBR_ALIGNED_ONLY:
+		if ((pg_offset == 0) && (pg_length == PAGE_CACHE_SIZE) &&
+		    (((unsigned int) bn) & BN_ALIGN_MASK) == 0) {
+			sector = blk_length << sector_shift;
+			blk_length = 1;
+			break;
+		}
+	case PBR_SECTOR_ONLY:
+		/* Fallthrough, same as default */
+	default:
+		sector = 1 << sector_shift;
+	}
+
+	/* If we are doing I/O larger than the bh->b_size field then
+	 * we need to split this request up.
+	 */
+	while (sector > ((1ULL << NBBY * sizeof(bh->b_size)) - 1)) {
+		sector >>= 1;
+		blk_length++;
+	}
+
+	multi_ok = (blk_length != 1);
+	i = sector >> BBSHIFT;
+
+	for (; blk_length > 0; bn += i, blk_length--, pg_offset += sector) {
+		bh = kmem_cache_alloc(bh_cachep, SLAB_NOFS);
+		if (!bh)
+			bh = _pagebuf_get_prealloc_bh();
+		memset(bh, 0, sizeof(*bh));
+		bh->b_blocknr = bn;
+		bh->b_size = sector;
+		bh->b_dev = pbr->pbr_kdev;
+		set_buffer_locked(bh);
+		set_bh_page(bh, page, pg_offset);
+		init_waitqueue_head(&bh->b_wait);
+		atomic_set(&bh->b_count, 1);
+		bufferlist[cnt++] = bh;
+	}
+
+request:
+	if (cnt) {
+		void	(*callback)(struct buffer_head *, int);
+
+		callback = (multi_ok && public_bh) ?
+				_pagebuf_end_io_partial_pages :
+				_pagebuf_end_io_complete_pages;
+
+		/* Account for additional buffers in progress */
+		atomic_add(cnt, &pb->pb_io_remaining);
+
+#ifdef RQ_WRITE_ORDERED
+		if (flush)
+			set_bit(BH_Ordered_Flush, &bufferlist[cnt-1]->b_state);
+#endif
+
+		for (i = 0; i < cnt; i++) {
+			bh = bufferlist[i];
+			init_buffer(bh, callback, pb);
+			bh->b_rdev = bh->b_dev;
+			bh->b_rsector = bh->b_blocknr;
+			set_buffer_mapped(bh);
+			set_buffer_async(bh);
+			set_buffer_req(bh);
+			if (rw == WRITE)
+				set_buffer_uptodate(bh);
+			generic_make_request(rw, bh);
+		}
+		return 0;
+	}
+
+	/*
+	 * We have no I/O to submit, let the caller know that
+	 * we have skipped over this page entirely.
+	 */
+	return 1;
+}
+
+STATIC void
+_pagebuf_page_apply(
+	page_buf_t		*pb,
+	loff_t			offset,
+	struct page		*page,
+	size_t			pg_offset,
+	size_t			pg_length,
+	int			last)
+{
+	page_buf_daddr_t	bn = pb->pb_bn;
+	pb_target_t		*pbr = pb->pb_target;
+	loff_t			pb_offset;
+	int			status, locking;
+
+	ASSERT(page);
+	ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE));
+
+	if ((pbr->pbr_bsize == PAGE_CACHE_SIZE) &&
+	    (pb->pb_buffer_length < PAGE_CACHE_SIZE) &&
+	    (pb->pb_flags & PBF_READ) && pb->pb_locked) {
+		bn -= (pb->pb_offset >> BBSHIFT);
+		pg_offset = 0;
+		pg_length = PAGE_CACHE_SIZE;
+	} else {
+		pb_offset = offset - pb->pb_file_offset;
+		if (pb_offset) {
+			bn += (pb_offset + BBMASK) >> BBSHIFT;
+		}
+	}
+
+	locking = _pagebuf_iolocked(pb);
+	if (pb->pb_flags & PBF_WRITE) {
+		if (locking && !pb->pb_locked)
+			lock_page(page);
+		status = _pagebuf_page_io(page, pbr, pb, bn,
+				pg_offset, pg_length, WRITE,
+				last && (pb->pb_flags & PBF_FLUSH));
+	} else {
+		status = _pagebuf_page_io(page, pbr, pb, bn,
+				pg_offset, pg_length, READ, 0);
+	}
+	if (status && locking && !(pb->pb_target->pbr_bsize < PAGE_CACHE_SIZE))
+		unlock_page(page);
+}
+
+/*
+ *	pagebuf_iorequest
+ *
+ *	pagebuf_iorequest is the core I/O request routine.
+ *	It assumes that the buffer is well-formed and
+ *	mapped and ready for physical I/O, unlike
+ *	pagebuf_iostart() and pagebuf_iophysio().  Those
+ *	routines call the pagebuf_ioinitiate routine to start I/O,
+ *	if it is present, or else call pagebuf_iorequest()
+ *	directly if the pagebuf_ioinitiate routine is not present.
+ *
+ *	This function will be responsible for ensuring access to the
+ *	pages is restricted whilst I/O is in progress - for locking
+ *	pagebufs the pagebuf lock is the mediator, for non-locking
+ *	pagebufs the pages will be locked. In the locking case we
+ *	need to use the pagebuf lock as multiple meta-data buffers
+ *	will reference the same page.
+ */
+int
+pagebuf_iorequest(			/* start real I/O		*/
+	page_buf_t		*pb)	/* buffer to convey to device	*/
+{
+	PB_TRACE(pb, "iorequest", 0);
+
+	if (pb->pb_flags & PBF_DELWRI) {
+		pagebuf_delwri_queue(pb, 1);
+		return 0;
+	}
+
+	if (pb->pb_flags & PBF_WRITE) {
+		_pagebuf_wait_unpin(pb);
+	}
+
+	pagebuf_hold(pb);
+
+	/* Set the count to 1 initially, this will stop an I/O
+	 * completion callout which happens before we have started
+	 * all the I/O from calling pagebuf_iodone too early.
+	 */
+	atomic_set(&pb->pb_io_remaining, 1);
+	_pagebuf_ioapply(pb);
+	_pagebuf_iodone(pb, 0);
+
+	pagebuf_rele(pb);
+	return 0;
+}
+
+/*
+ *	pagebuf_iowait
+ *
+ *	pagebuf_iowait waits for I/O to complete on the buffer supplied.
+ *	It returns immediately if no I/O is pending.  In any case, it returns
+ *	the error code, if any, or 0 if there is no error.
+ */
+int
+pagebuf_iowait(
+	page_buf_t		*pb)
+{
+	PB_TRACE(pb, "iowait", 0);
+	if (atomic_read(&pb->pb_io_remaining))
+		blk_run_queues();
+	if ((pb->pb_flags & PBF_FS_DATAIOD))
+		pagebuf_runall_queues(pagebuf_dataiodone_tq);
+	down(&pb->pb_iodonesema);
+	PB_TRACE(pb, "iowaited", (long)pb->pb_error);
+	return pb->pb_error;
+}
+
+STATIC void *
+pagebuf_mapout_locked(
+	page_buf_t		*pb)
+{
+	void			*old_addr = NULL;
+
+	if (pb->pb_flags & PBF_MAPPED) {
+		if (pb->pb_flags & _PBF_ADDR_ALLOCATED)
+			old_addr = pb->pb_addr - pb->pb_offset;
+		pb->pb_addr = NULL;
+		pb->pb_flags &= ~(PBF_MAPPED | _PBF_ADDR_ALLOCATED);
+	}
+
+	return old_addr;	/* Caller must free the address space,
+				 * we are under a spin lock, probably
+				 * not safe to do vfree here
+				 */
+}
+
+caddr_t
+pagebuf_offset(
+	page_buf_t		*pb,
+	size_t			offset)
+{
+	struct page		*page;
+
+	offset += pb->pb_offset;
+
+	page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT];
+	return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1));
+}
+
+/*
+ *	pagebuf_iomove
+ *
+ *	Move data into or out of a buffer.
+ */
+void
+pagebuf_iomove(
+	page_buf_t		*pb,	/* buffer to process		*/
+	size_t			boff,	/* starting buffer offset	*/
+	size_t			bsize,	/* length to copy		*/
+	caddr_t			data,	/* data address			*/
+	page_buf_rw_t		mode)	/* read/write flag		*/
+{
+	size_t			bend, cpoff, csize;
+	struct page		*page;
+
+	bend = boff + bsize;
+	while (boff < bend) {
+		page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)];
+		cpoff = page_buf_poff(boff + pb->pb_offset);
+		csize = min_t(size_t,
+			      PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff);
+
+		ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
+
+		switch (mode) {
+		case PBRW_ZERO:
+			memset(page_address(page) + cpoff, 0, csize);
+			break;
+		case PBRW_READ:
+			memcpy(data, page_address(page) + cpoff, csize);
+			break;
+		case PBRW_WRITE:
+			memcpy(page_address(page) + cpoff, data, csize);
+		}
+
+		boff += csize;
+		data += csize;
+	}
+}
+
+/*
+ *	_pagebuf_ioapply
+ *
+ *	Applies _pagebuf_page_apply to each page of the page_buf_t.
+ */
+STATIC void
+_pagebuf_ioapply(			/* apply function to pages	*/
+	page_buf_t		*pb)	/* buffer to examine		*/
+{
+	int			index;
+	loff_t			buffer_offset = pb->pb_file_offset;
+	size_t			buffer_len = pb->pb_count_desired;
+	size_t			page_offset, len;
+	size_t			cur_offset, cur_len;
+
+	cur_offset = pb->pb_offset;
+	cur_len = buffer_len;
+
+	if (!pb->pb_locked &&
+	    (pb->pb_target->pbr_bsize < PAGE_CACHE_SIZE)) {
+		for (index = 0; index < pb->pb_page_count; index++)
+			lock_page(pb->pb_pages[index]);
+		pb->pb_locked = 1;
+	}
+
+	for (index = 0; index < pb->pb_page_count; index++) {
+		if (cur_len == 0)
+			break;
+		if (cur_offset >= PAGE_CACHE_SIZE) {
+			cur_offset -= PAGE_CACHE_SIZE;
+			continue;
+		}
+
+		page_offset = cur_offset;
+		cur_offset = 0;
+
+		len = PAGE_CACHE_SIZE - page_offset;
+		if (len > cur_len)
+			len = cur_len;
+		cur_len -= len;
+
+		_pagebuf_page_apply(pb, buffer_offset,
+				pb->pb_pages[index], page_offset, len,
+				index + 1 == pb->pb_page_count);
+		buffer_offset += len;
+		buffer_len -= len;
+	}
+
+	/*
+	 * Run the block device task queue here, while we have
+	 * a hold on the pagebuf (important to have that hold).
+	 */
+	if (pb->pb_flags & PBF_RUN_QUEUES) {
+		pb->pb_flags &= ~PBF_RUN_QUEUES;
+		if (atomic_read(&pb->pb_io_remaining) > 1)
+			blk_run_queues();
+	}
+}
+
+
+/*
+ * Pagebuf delayed write buffer handling
+ */
+
+STATIC int pbd_active = 1;
+STATIC LIST_HEAD(pbd_delwrite_queue);
+STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED;
+
+STATIC void
+pagebuf_delwri_queue(
+	page_buf_t		*pb,
+	int			unlock)
+{
+	PB_TRACE(pb, "delwri_q", (long)unlock);
+	spin_lock(&pbd_delwrite_lock);
+	/* If already in the queue, dequeue and place at tail */
+	if (!list_empty(&pb->pb_list)) {
+		if (unlock) {
+			atomic_dec(&pb->pb_hold);
+		}
+		list_del(&pb->pb_list);
+	}
+
+	list_add_tail(&pb->pb_list, &pbd_delwrite_queue);
+	pb->pb_flushtime = jiffies + pb_params.age_buffer.val;
+	spin_unlock(&pbd_delwrite_lock);
+
+	if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) {
+		pagebuf_unlock(pb);
+	}
+}
+
+void
+pagebuf_delwri_dequeue(
+	page_buf_t		*pb)
+{
+	PB_TRACE(pb, "delwri_uq", 0);
+	spin_lock(&pbd_delwrite_lock);
+	list_del_init(&pb->pb_list);
+	pb->pb_flags &= ~PBF_DELWRI;
+	spin_unlock(&pbd_delwrite_lock);
+}
+
+
+/*
+ * The pagebuf iodone daemons
+ */
+
+STATIC int
+pagebuf_iodone_daemon(
+	void			*__bind_cpu,
+	const char		*name,
+	int			pagebuf_daemons[],
+	struct list_head	pagebuf_iodone_tq[],
+	wait_queue_head_t	pagebuf_iodone_wait[])
+{
+	int			bind_cpu, cpu;
+	DECLARE_WAITQUEUE	(wait, current);
+
+	bind_cpu = (int) (long)__bind_cpu;
+	cpu = CPU_TO_DAEMON(cpu_logical_map(bind_cpu));
+
+	/*  Set up the thread  */
+	daemonize();
+
+	/* Avoid signals */
+	spin_lock_irq(&current->sigmask_lock);
+	sigfillset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	/* Migrate to the right CPU */
+	migrate_to_cpu(cpu);
+#ifdef __HAVE_NEW_SCHEDULER
+	if (smp_processor_id() != cpu)
+		BUG();
+#else
+	while (smp_processor_id() != cpu)
+		schedule();
+#endif
+
+	sprintf(current->comm, "%s/%d", name, bind_cpu);
+	INIT_LIST_HEAD(&pagebuf_iodone_tq[cpu]);
+	init_waitqueue_head(&pagebuf_iodone_wait[cpu]);
+	__set_current_state(TASK_INTERRUPTIBLE);
+	mb();
+
+	pagebuf_daemons[cpu] = 1;
+
+	for (;;) {
+		add_wait_queue(&pagebuf_iodone_wait[cpu], &wait);
+
+		if (TQ_ACTIVE(pagebuf_iodone_tq[cpu]))
+			__set_task_state(current, TASK_RUNNING);
+		schedule();
+		remove_wait_queue(&pagebuf_iodone_wait[cpu], &wait);
+		run_task_queue(&pagebuf_iodone_tq[cpu]);
+		if (pagebuf_daemons[cpu] == 0)
+			break;
+		__set_current_state(TASK_INTERRUPTIBLE);
+	}
+
+	pagebuf_daemons[cpu] = -1;
+	wake_up_interruptible(&pagebuf_iodone_wait[cpu]);
+	return 0;
+}
+
+STATIC void
+pagebuf_runall_queues(
+	struct list_head	pagebuf_iodone_tq[])
+{
+	int	pcpu, cpu;
+
+	for (cpu = 0; cpu < min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
+		pcpu = CPU_TO_DAEMON(cpu_logical_map(cpu));
+
+		run_task_queue(&pagebuf_iodone_tq[pcpu]);
+	}
+}
+
+STATIC int
+pagebuf_logiodone_daemon(
+	void			*__bind_cpu)
+{
+	return pagebuf_iodone_daemon(__bind_cpu, "xfslogd", pb_logio_daemons,
+			pagebuf_logiodone_tq, pagebuf_logiodone_wait);
+}
+
+STATIC int
+pagebuf_dataiodone_daemon(
+	void			*__bind_cpu)
+{
+	return pagebuf_iodone_daemon(__bind_cpu, "xfsdatad", pb_dataio_daemons,
+			pagebuf_dataiodone_tq, pagebuf_dataiodone_wait);
+}
+
+
+/* Defines for pagebuf daemon */
+DECLARE_WAIT_QUEUE_HEAD(pbd_waitq);
+STATIC int force_flush;
+
+STATIC void
+pagebuf_daemon_wakeup(
+	int			flag)
+{
+	force_flush = flag;
+	if (waitqueue_active(&pbd_waitq)) {
+		wake_up_interruptible(&pbd_waitq);
+	}
+}
+
+typedef void (*timeout_fn)(unsigned long);
+
+STATIC int
+pagebuf_daemon(
+	void			*data)
+{
+	int			count;
+	page_buf_t		*pb;
+	struct list_head	*curr, *next, tmp;
+	struct timer_list	pb_daemon_timer =
+		{ {NULL, NULL}, 0, 0, (timeout_fn)pagebuf_daemon_wakeup };
+
+	/*  Set up the thread  */
+	daemonize();
+
+	/* Avoid signals */
+	spin_lock_irq(&current->sigmask_lock);
+	sigfillset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	strcpy(current->comm, "pagebufd");
+	current->flags |= PF_MEMALLOC;
+
+	INIT_LIST_HEAD(&tmp);
+	do {
+		if (pbd_active == 1) {
+			mod_timer(&pb_daemon_timer,
+				  jiffies + pb_params.flush_interval.val);
+			interruptible_sleep_on(&pbd_waitq);
+		}
+
+		if (pbd_active == 0) {
+			del_timer_sync(&pb_daemon_timer);
+		}
+
+		spin_lock(&pbd_delwrite_lock);
+
+		count = 0;
+		list_for_each_safe(curr, next, &pbd_delwrite_queue) {
+			pb = list_entry(curr, page_buf_t, pb_list);
+
+			PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
+
+			if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) &&
+			    (((pb->pb_flags & _PBF_LOCKABLE) == 0) ||
+			     !pagebuf_cond_lock(pb))) {
+
+				if (!force_flush &&
+				    time_before(jiffies, pb->pb_flushtime)) {
+					pagebuf_unlock(pb);
+					break;
+				}
+
+				pb->pb_flags &= ~PBF_DELWRI;
+				pb->pb_flags |= PBF_WRITE;
+
+				list_del(&pb->pb_list);
+				list_add(&pb->pb_list, &tmp);
+
+				count++;
+			}
+		}
+
+		spin_unlock(&pbd_delwrite_lock);
+		while (!list_empty(&tmp)) {
+			pb = list_entry(tmp.next, page_buf_t, pb_list);
+			list_del_init(&pb->pb_list);
+
+			pagebuf_iostrategy(pb);
+		}
+
+		if (as_list_len > 0)
+			purge_addresses();
+		if (count)
+			blk_run_queues();
+
+		force_flush = 0;
+	} while (pbd_active == 1);
+
+	pbd_active = -1;
+	wake_up_interruptible(&pbd_waitq);
+
+	return 0;
+}
+
+void
+pagebuf_delwri_flush(
+	pb_target_t		*target,
+	u_long			flags,
+	int			*pinptr)
+{
+	page_buf_t		*pb;
+	struct list_head	*curr, *next, tmp;
+	int			pincount = 0;
+	int			flush_cnt = 0;
+
+	pagebuf_runall_queues(pagebuf_dataiodone_tq);
+	pagebuf_runall_queues(pagebuf_logiodone_tq);
+
+	spin_lock(&pbd_delwrite_lock);
+	INIT_LIST_HEAD(&tmp);
+
+	list_for_each_safe(curr, next, &pbd_delwrite_queue) {
+		pb = list_entry(curr, page_buf_t, pb_list);
+
+		/*
+		 * Skip other targets, markers and in progress buffers
+		 */
+
+		if ((pb->pb_flags == 0) || (pb->pb_target != target) ||
+		    !(pb->pb_flags & PBF_DELWRI)) {
+			continue;
+		}
+
+		PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb));
+		if (pagebuf_ispin(pb)) {
+			pincount++;
+			continue;
+		}
+
+		pb->pb_flags &= ~PBF_DELWRI;
+		pb->pb_flags |= PBF_WRITE;
+		list_move(&pb->pb_list, &tmp);
+
+	}
+	
+	/* ok found all the items that can be worked on 
+	 * drop the lock and process the private list */
+	spin_unlock(&pbd_delwrite_lock);
+	
+	list_for_each_safe(curr, next, &tmp) {
+		pb = list_entry(curr, page_buf_t, pb_list);
+		
+		if (flags & PBDF_WAIT)
+			pb->pb_flags &= ~PBF_ASYNC;
+		else
+			list_del_init(curr);
+
+		pagebuf_lock(pb);
+		pagebuf_iostrategy(pb);
+
+		if (++flush_cnt > 32) {
+			blk_run_queues();
+			flush_cnt = 0;
+		}
+	}
+
+	blk_run_queues();
+
+	/* must run list the second time even if PBDF_WAIT isn't
+	 * to reset all the pb_list pointers 
+	 */
+	while (!list_empty(&tmp)) {
+		pb = list_entry(tmp.next, page_buf_t, pb_list);
+
+		list_del_init(&pb->pb_list);
+		
+		pagebuf_iowait(pb);
+		if (!pb->pb_relse)
+			pagebuf_unlock(pb);
+		pagebuf_rele(pb);
+	}
+
+	if (pinptr)
+		*pinptr = pincount;
+}
+
+STATIC int
+pagebuf_daemon_start(void)
+{
+	int		cpu, pcpu;
+
+	kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES|CLONE_VM);
+
+	for (cpu = 0; cpu < min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
+		pcpu = CPU_TO_DAEMON(cpu_logical_map(cpu));
+
+		if (kernel_thread(pagebuf_logiodone_daemon,
+				(void *)(long) cpu,
+				CLONE_FS|CLONE_FILES|CLONE_VM) < 0) {
+			printk("pagebuf_logiodone daemon failed to start\n");
+		} else {
+			while (!pb_logio_daemons[pcpu])
+				yield();
+		}
+	}
+	for (cpu = 0; cpu < min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
+		pcpu = CPU_TO_DAEMON(cpu_logical_map(cpu));
+
+		if (kernel_thread(pagebuf_dataiodone_daemon,
+				(void *)(long) cpu,
+				CLONE_FS|CLONE_FILES|CLONE_VM) < 0) {
+			printk("pagebuf_dataiodone daemon failed to start\n");
+		} else {
+			while (!pb_dataio_daemons[pcpu])
+				yield();
+		}
+	}
+	return 0;
+}
+
+/*
+ * pagebuf_daemon_stop
+ *
+ * Note: do not mark as __exit, it is called from pagebuf_terminate.
+ */
+STATIC void
+pagebuf_daemon_stop(void)
+{
+	int		cpu, pcpu;
+
+	pbd_active = 0;
+
+	wake_up_interruptible(&pbd_waitq);
+	wait_event_interruptible(pbd_waitq, pbd_active);
+
+	for (pcpu = 0; pcpu < min(smp_num_cpus, MAX_IO_DAEMONS); pcpu++) {
+		cpu = CPU_TO_DAEMON(cpu_logical_map(pcpu));
+
+		pb_logio_daemons[cpu] = 0;
+		wake_up(&pagebuf_logiodone_wait[cpu]);
+		wait_event_interruptible(pagebuf_logiodone_wait[cpu],
+				pb_logio_daemons[cpu] == -1);
+
+		pb_dataio_daemons[cpu] = 0;
+		wake_up(&pagebuf_dataiodone_wait[cpu]);
+		wait_event_interruptible(pagebuf_dataiodone_wait[cpu],
+				pb_dataio_daemons[cpu] == -1);
+	}
+}
+
+
+/*
+ * Pagebuf sysctl interface
+ */
+
+STATIC int
+pb_stats_clear_handler(
+	ctl_table		*ctl,
+	int			write,
+	struct file		*filp,
+	void			*buffer,
+	size_t			*lenp)
+{
+	int			ret;
+	int			*valp = ctl->data;
+
+	ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp);
+
+	if (!ret && write && *valp) {
+		printk("XFS Clearing pbstats\n");
+		memset(&pbstats, 0, sizeof(pbstats));
+		pb_params.stats_clear.val = 0;
+	}
+
+	return ret;
+}
+
+STATIC struct ctl_table_header *pagebuf_table_header;
+
+STATIC ctl_table pagebuf_table[] = {
+	{PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&pb_params.flush_interval.min, &pb_params.flush_interval.max},
+
+	{PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL, 
+	&pb_params.age_buffer.min, &pb_params.age_buffer.max},
+
+	{PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val,
+	sizeof(int), 0644, NULL, &pb_stats_clear_handler,
+	&sysctl_intvec, NULL, 
+	&pb_params.stats_clear.min, &pb_params.stats_clear.max},
+
+#ifdef PAGEBUF_TRACE
+	{PB_DEBUG, "debug", &pb_params.debug.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL, 
+	&pb_params.debug.min, &pb_params.debug.max},
+#endif
+	{0}
+};
+
+STATIC ctl_table pagebuf_dir_table[] = {
+	{VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table},
+	{0}
+};
+
+STATIC ctl_table pagebuf_root_table[] = {
+	{CTL_VM, "vm",  NULL, 0, 0555, pagebuf_dir_table},
+	{0}
+};
+
+#ifdef CONFIG_PROC_FS
+STATIC int
+pagebuf_readstats(
+	char			*buffer,
+	char			**start,
+	off_t			offset,
+	int			count,
+	int			*eof,
+	void			*data)
+{
+	int			i, len;
+
+	len = 0;
+	len += sprintf(buffer + len, "pagebuf");
+	for (i = 0; i < sizeof(pbstats) / sizeof(u_int32_t); i++) {
+		len += sprintf(buffer + len, " %u",
+			*(((u_int32_t*)&pbstats) + i));
+	}
+	buffer[len++] = '\n';
+
+	if (offset >= len) {
+		*start = buffer;
+		*eof = 1;
+		return 0;
+	}
+	*start = buffer + offset;
+	if ((len -= offset) > count)
+		return count;
+	*eof = 1;
+
+	return len;
+}
+#endif  /* CONFIG_PROC_FS */
+
+STATIC int
+pagebuf_shaker(int number, unsigned int mask)
+{
+	pagebuf_daemon_wakeup(1);
+	return 0;
+}
+
+
+/*
+ *	Initialization and Termination
+ */
+
+int __init
+pagebuf_init(void)
+{
+	int			i;
+
+	pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1);
+
+#ifdef CONFIG_PROC_FS
+	if (proc_mkdir("fs/pagebuf", 0))
+		create_proc_read_entry(
+			"fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL);
+#endif
+
+	pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0,
+			SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (pagebuf_cache == NULL) {
+		printk("pagebuf: couldn't init pagebuf cache\n");
+		pagebuf_terminate();
+		return -ENOMEM;
+	}
+
+	if (_pagebuf_prealloc_bh(NR_RESERVED_BH) < NR_RESERVED_BH) {
+		printk("pagebuf: couldn't pre-allocate %d buffer heads\n",
+			NR_RESERVED_BH);
+		pagebuf_terminate();
+		return -ENOMEM;
+	}
+
+	init_waitqueue_head(&pb_resv_bh_wait);
+
+	for (i = 0; i < NHASH; i++) {
+		spin_lock_init(&pbhash[i].pb_hash_lock);
+		INIT_LIST_HEAD(&pbhash[i].pb_hash);
+	}
+
+#ifdef PAGEBUF_TRACE
+	pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
+#endif
+
+	pagebuf_daemon_start();
+	kmem_shake_register(pagebuf_shaker);
+	return 0;
+}
+
+/*
+ *	pagebuf_terminate.
+ *
+ *	Note: do not mark as __exit, this is also called from the __init code.
+ */
+void
+pagebuf_terminate(void)
+{
+	pagebuf_daemon_stop();
+
+#ifdef PAGEBUF_TRACE
+	ktrace_free(pagebuf_trace_buf);
+#endif
+
+	kmem_cache_destroy(pagebuf_cache);
+	kmem_shake_deregister(pagebuf_shaker);
+
+	unregister_sysctl_table(pagebuf_table_header);
+#ifdef  CONFIG_PROC_FS
+	remove_proc_entry("fs/pagebuf/stat", NULL);
+	remove_proc_entry("fs/pagebuf", NULL);
+#endif
+}
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_buf.h linux-2.4.25-rc1/fs/xfs/linux/xfs_buf.h
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_buf.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_buf.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/*
+ * Written by Steve Lord, Jim Mostek, Russell Cattelan at SGI
+ */
+
+#ifndef __XFS_BUF_H__
+#define __XFS_BUF_H__
+
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/uio.h>
+
+/*
+ *	Base types
+ */
+
+/* daddr must be signed since -1 is used for bmaps that are not yet allocated */
+typedef loff_t page_buf_daddr_t;
+
+#define PAGE_BUF_DADDR_NULL ((page_buf_daddr_t) (-1LL))
+
+#define page_buf_ctob(pp)	((pp) * PAGE_CACHE_SIZE)
+#define page_buf_btoc(dd)	(((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+#define page_buf_btoct(dd)	((dd) >> PAGE_CACHE_SHIFT)
+#define page_buf_poff(aa)	((aa) & ~PAGE_CACHE_MASK)
+
+typedef enum page_buf_rw_e {
+	PBRW_READ = 1,			/* transfer into target memory */
+	PBRW_WRITE = 2,			/* transfer from target memory */
+	PBRW_ZERO = 3			/* Zero target memory */
+} page_buf_rw_t;
+
+
+typedef enum page_buf_flags_e {		/* pb_flags values */
+	PBF_READ = (1 << 0),	/* buffer intended for reading from device */
+	PBF_WRITE = (1 << 1),	/* buffer intended for writing to device   */
+	PBF_MAPPED = (1 << 2),  /* buffer mapped (pb_addr valid)           */
+	PBF_PARTIAL = (1 << 3), /* buffer partially read                   */
+	PBF_ASYNC = (1 << 4),   /* initiator will not wait for completion  */
+	PBF_NONE = (1 << 5),    /* buffer not read at all                  */
+	PBF_DELWRI = (1 << 6),  /* buffer has dirty pages                  */
+	PBF_FREED = (1 << 7),   /* buffer has been freed and is invalid    */
+	PBF_SYNC = (1 << 8),    /* force updates to disk                   */
+	PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages          */
+	PBF_STALE = (1 << 10),	/* buffer has been staled, do not find it  */
+	PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory  */
+	PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad  */
+
+	/* flags used only as arguments to access routines */
+	PBF_LOCK = (1 << 13),	/* lock requested			   */
+	PBF_TRYLOCK = (1 << 14), /* lock requested, but do not wait	   */
+	PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread	   */
+
+	/* flags used only internally */
+	_PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked		   */
+	_PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads	   */
+	_PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped	   */
+	_PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated	   */
+	_PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated  */
+	_PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated  */
+
+	PBF_FORCEIO = (1 << 22), /* ignore any cache state		   */
+	PBF_FLUSH = (1 << 23),	/* flush disk write cache		   */
+	PBF_READ_AHEAD = (1 << 24), /* asynchronous read-ahead		   */
+	PBF_RUN_QUEUES = (1 << 25), /* run block device task queue	   */
+	PBF_DIRECTIO = (1 << 26), /* used for a direct IO mapping	   */
+
+} page_buf_flags_t;
+
+#define PBF_UPDATE (PBF_READ | PBF_WRITE)
+#define PBF_NOT_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) != 0)
+#define PBF_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) == 0)
+
+#define PBR_SECTOR_ONLY	1	/* only use sector size buffer heads */
+#define PBR_ALIGNED_ONLY 2	/* only use aligned I/O */
+
+typedef struct pb_target {
+	int			pbr_flags;
+	dev_t			pbr_dev;
+	kdev_t			pbr_kdev;
+	struct block_device	*pbr_bdev;
+	struct address_space	*pbr_mapping;
+	unsigned int		pbr_bsize;
+	unsigned int		pbr_sshift;
+	size_t			pbr_smask;
+} pb_target_t;
+
+/*
+ *	page_buf_t:  Buffer structure for page cache-based buffers
+ *
+ * This buffer structure is used by the page cache buffer management routines
+ * to refer to an assembly of pages forming a logical buffer.  The actual
+ * I/O is performed with buffer_head or bio structures, as required by drivers,
+ * for drivers which do not understand this structure.  The buffer structure is
+ * used on temporary basis only, and discarded when released.
+ *
+ * The real data storage is recorded in the page cache.  Metadata is
+ * hashed to the inode for the block device on which the file system resides.
+ * File data is hashed to the inode for the file.  Pages which are only
+ * partially filled with data have bits set in their block_map entry
+ * to indicate which disk blocks in the page are not valid.
+ */
+
+struct page_buf_s;
+typedef void (*page_buf_iodone_t)(struct page_buf_s *);
+			/* call-back function on I/O completion */
+typedef void (*page_buf_relse_t)(struct page_buf_s *);
+			/* call-back function on I/O completion */
+typedef int (*page_buf_bdstrat_t)(struct page_buf_s *);
+
+#define PB_PAGES	4
+
+typedef struct page_buf_s {
+	struct semaphore	pb_sema;	/* semaphore for lockables  */
+	unsigned long		pb_flushtime;	/* time to flush pagebuf    */
+	atomic_t		pb_pin_count;	/* pin count		    */
+	wait_queue_head_t	pb_waiters;	/* unpin waiters	    */
+	struct list_head	pb_list;
+	page_buf_flags_t	pb_flags;	/* status flags */
+	struct list_head	pb_hash_list;
+	struct pb_target	*pb_target;	/* logical object */
+	atomic_t		pb_hold;	/* reference count */
+	page_buf_daddr_t	pb_bn;		/* block number for I/O */
+	loff_t			pb_file_offset;	/* offset in file */
+	size_t			pb_buffer_length; /* size of buffer in bytes */
+	size_t			pb_count_desired; /* desired transfer size */
+	void			*pb_addr;	/* virtual address of buffer */
+	struct tq_struct	pb_iodone_sched;
+	atomic_t		pb_io_remaining;/* #outstanding I/O requests */
+	page_buf_iodone_t	pb_iodone;	/* I/O completion function */
+	page_buf_relse_t	pb_relse;	/* releasing function */
+	page_buf_bdstrat_t	pb_strat;	/* pre-write function */
+	struct semaphore	pb_iodonesema;	/* Semaphore for I/O waiters */
+	void			*pb_fspriv;
+	void			*pb_fspriv2;
+	void			*pb_fspriv3;
+	unsigned short		pb_error;	/* error code on I/O */
+	unsigned short		pb_page_count;	/* size of page array */
+	unsigned short		pb_offset;	/* page offset in first page */
+	unsigned char		pb_locked;	/* page array is locked */
+	unsigned char		pb_hash_index;	/* hash table index	*/
+	struct page		**pb_pages;	/* array of page pointers */
+	struct page		*pb_page_array[PB_PAGES]; /* inline pages */
+#ifdef PAGEBUF_LOCK_TRACKING
+	int			pb_last_holder;
+#endif
+} page_buf_t;
+
+
+/* Finding and Reading Buffers */
+
+extern page_buf_t *pagebuf_find(	/* find buffer for block if	*/
+					/* the block is in memory	*/
+		struct pb_target *,	/* inode for block		*/
+		loff_t,			/* starting offset of range	*/
+		size_t,			/* length of range		*/
+		page_buf_flags_t);	/* PBF_LOCK			*/
+
+extern page_buf_t *pagebuf_get(		/* allocate a buffer		*/
+		struct pb_target *,	/* inode for buffer		*/
+		loff_t,			/* starting offset of range     */
+		size_t,			/* length of range              */
+		page_buf_flags_t);	/* PBF_LOCK, PBF_READ,		*/
+					/* PBF_ASYNC			*/
+
+extern page_buf_t *pagebuf_lookup(
+		struct pb_target *,
+		loff_t,			/* starting offset of range	*/
+		size_t,			/* length of range		*/
+		page_buf_flags_t);	/* PBF_READ, PBF_WRITE,		*/
+					/* PBF_FORCEIO, _PBF_LOCKABLE	*/
+
+extern page_buf_t *pagebuf_get_empty(	/* allocate pagebuf struct with	*/
+					/*  no memory or disk address	*/
+		size_t len,
+		struct pb_target *);	/* mount point "fake" inode	*/
+
+extern page_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct	*/
+					/* without disk address		*/
+		size_t len,
+		struct pb_target *);	/* mount point "fake" inode	*/
+
+extern int pagebuf_associate_memory(
+		page_buf_t *,
+		void *,
+		size_t);
+
+extern void pagebuf_hold(		/* increment reference count	*/
+		page_buf_t *);		/* buffer to hold		*/
+
+extern void pagebuf_readahead(		/* read ahead into cache	*/
+		struct pb_target  *,	/* target for buffer (or NULL)	*/
+		loff_t,			/* starting offset of range     */
+		size_t,			/* length of range              */
+		page_buf_flags_t);	/* additional read flags	*/
+
+/* Releasing Buffers */
+
+extern void pagebuf_free(		/* deallocate a buffer		*/
+		page_buf_t *);		/* buffer to deallocate		*/
+
+extern void pagebuf_rele(		/* release hold on a buffer	*/
+		page_buf_t *);		/* buffer to release		*/
+
+/* Locking and Unlocking Buffers */
+
+extern int pagebuf_cond_lock(		/* lock buffer, if not locked	*/
+					/* (returns -EBUSY if locked)	*/
+		page_buf_t *);		/* buffer to lock		*/
+
+extern int pagebuf_lock_value(		/* return count on lock		*/
+		page_buf_t *);          /* buffer to check              */
+
+extern int pagebuf_lock(		/* lock buffer                  */
+		page_buf_t *);          /* buffer to lock               */
+
+extern void pagebuf_unlock(		/* unlock buffer		*/
+		page_buf_t *);		/* buffer to unlock		*/
+
+/* Buffer Read and Write Routines */
+
+extern void pagebuf_iodone(		/* mark buffer I/O complete	*/
+		page_buf_t *,		/* buffer to mark		*/
+		int,			/* use data/log helper thread.	*/
+		int);			/* run completion locally, or in
+					 * a helper thread.		*/
+
+extern void pagebuf_ioerror(		/* mark buffer in error	(or not) */
+		page_buf_t *,		/* buffer to mark		*/
+		unsigned int);		/* error to store (0 if none)	*/
+
+extern int pagebuf_iostart(		/* start I/O on a buffer	*/
+		page_buf_t *,		/* buffer to start		*/
+		page_buf_flags_t);	/* PBF_LOCK, PBF_ASYNC,		*/
+					/* PBF_READ, PBF_WRITE,		*/
+					/* PBF_DELWRI, PBF_SYNC		*/
+
+extern int pagebuf_iorequest(		/* start real I/O		*/
+		page_buf_t *);		/* buffer to convey to device	*/
+
+extern int pagebuf_iowait(		/* wait for buffer I/O done	*/
+		page_buf_t *);		/* buffer to wait on		*/
+
+extern void pagebuf_iomove(		/* move data in/out of pagebuf	*/
+		page_buf_t *,		/* buffer to manipulate		*/
+		size_t,			/* starting buffer offset	*/
+		size_t,			/* length in buffer		*/
+		caddr_t,		/* data pointer			*/
+		page_buf_rw_t);		/* direction			*/
+
+static inline int pagebuf_iostrategy(page_buf_t *pb)
+{
+	return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb);
+}
+
+static inline int pagebuf_geterror(page_buf_t *pb)
+{
+	return pb ? pb->pb_error : ENOMEM;
+}
+
+/* Buffer Utility Routines */
+
+extern caddr_t pagebuf_offset(		/* pointer at offset in buffer	*/
+		page_buf_t *,		/* buffer to offset into	*/
+		size_t);		/* offset			*/
+
+/* Pinning Buffer Storage in Memory */
+
+extern void pagebuf_pin(		/* pin buffer in memory		*/
+		page_buf_t *);		/* buffer to pin		*/
+
+extern void pagebuf_unpin(		/* unpin buffered data		*/
+		page_buf_t *);		/* buffer to unpin		*/
+
+extern int pagebuf_ispin(		/* check if buffer is pinned	*/
+		page_buf_t *);		/* buffer to check		*/
+
+/* Delayed Write Buffer Routines */
+
+#define PBDF_WAIT    0x01
+extern void pagebuf_delwri_flush(
+		pb_target_t *,
+		unsigned long,
+		int *);
+
+extern void pagebuf_delwri_dequeue(
+		page_buf_t *);
+
+/* Buffer Daemon Setup Routines */
+
+extern int pagebuf_init(void);
+extern void pagebuf_terminate(void);
+
+
+#ifdef PAGEBUF_TRACE
+extern ktrace_t *pagebuf_trace_buf;
+extern void pagebuf_trace(
+		page_buf_t *,		/* buffer being traced		*/
+		char *,			/* description of operation	*/
+		void *,			/* arbitrary diagnostic value	*/
+		void *);		/* return address		*/
+#else
+# define pagebuf_trace(pb, id, ptr, ra)	do { } while (0)
+#endif
+
+#define pagebuf_target_name(target)	bdevname((target)->pbr_kdev)
+
+/*
+ * Kernel version compatibility macros
+ */
+
+#define page_buffers(page)	((page)->buffers)
+#define page_has_buffers(page)	((page)->buffers)
+#define PageUptodate(x)		Page_Uptodate(x)
+/*
+ * macro tricks to expand the set_buffer_foo() and clear_buffer_foo()
+ * functions.
+ */
+#define BUFFER_FNS(bit, name)						\
+static inline void set_buffer_##name(struct buffer_head *bh)		\
+{									\
+	set_bit(BH_##bit, &(bh)->b_state);				\
+}									\
+static inline void clear_buffer_##name(struct buffer_head *bh)		\
+{									\
+	clear_bit(BH_##bit, &(bh)->b_state);				\
+}									\
+
+/*
+ * Emit the buffer bitops functions.   Note that there are also functions
+ * of the form "mark_buffer_foo()".  These are higher-level functions which
+ * do something in addition to setting a b_state bit.
+ */
+BUFFER_FNS(Uptodate, uptodate)
+BUFFER_FNS(Dirty, dirty)
+BUFFER_FNS(Lock, locked)
+BUFFER_FNS(Req, req)
+BUFFER_FNS(Mapped, mapped)
+BUFFER_FNS(New, new)
+BUFFER_FNS(Async, async)
+BUFFER_FNS(Wait_IO, wait_io)
+BUFFER_FNS(Launder, launder)
+BUFFER_FNS(Sync, sync)
+BUFFER_FNS(Delay, delay)
+
+#define get_seconds()		CURRENT_TIME
+#define blk_run_queues()	run_task_queue(&tq_disk)
+#define i_size_read(inode)	((inode)->i_size)
+#define i_size_write(inode, sz)	((inode)->i_size = (sz))
+
+/* These are just for xfs_syncsub... it sets an internal variable
+ * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t
+ */
+#define XFS_B_ASYNC		PBF_ASYNC
+#define XFS_B_DELWRI		PBF_DELWRI
+#define XFS_B_READ		PBF_READ
+#define XFS_B_WRITE		PBF_WRITE
+#define XFS_B_STALE		PBF_STALE
+
+#define XFS_BUF_TRYLOCK		PBF_TRYLOCK
+#define XFS_INCORE_TRYLOCK	PBF_TRYLOCK
+#define XFS_BUF_LOCK		PBF_LOCK
+#define XFS_BUF_MAPPED		PBF_MAPPED
+
+#define BUF_BUSY		PBF_DONT_BLOCK
+
+#define XFS_BUF_BFLAGS(x)	((x)->pb_flags)
+#define XFS_BUF_ZEROFLAGS(x)	\
+	((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI))
+
+#define XFS_BUF_STALE(x)	((x)->pb_flags |= XFS_B_STALE)
+#define XFS_BUF_UNSTALE(x)	((x)->pb_flags &= ~XFS_B_STALE)
+#define XFS_BUF_ISSTALE(x)	((x)->pb_flags & XFS_B_STALE)
+#define XFS_BUF_SUPER_STALE(x)	do {				\
+					XFS_BUF_STALE(x);	\
+					xfs_buf_undelay(x);	\
+					XFS_BUF_DONE(x);	\
+				} while (0)
+
+#define XFS_BUF_MANAGE		PBF_FS_MANAGED
+#define XFS_BUF_UNMANAGE(x)	((x)->pb_flags &= ~PBF_FS_MANAGED)
+
+static inline void xfs_buf_undelay(page_buf_t *pb)
+{
+	if (pb->pb_flags & PBF_DELWRI) {
+		if (pb->pb_list.next != &pb->pb_list) {
+			pagebuf_delwri_dequeue(pb);
+			pagebuf_rele(pb);
+		} else {
+			pb->pb_flags &= ~PBF_DELWRI;
+		}
+	}
+}
+
+#define XFS_BUF_DELAYWRITE(x)	 ((x)->pb_flags |= PBF_DELWRI)
+#define XFS_BUF_UNDELAYWRITE(x)	 xfs_buf_undelay(x)
+#define XFS_BUF_ISDELAYWRITE(x)	 ((x)->pb_flags & PBF_DELWRI)
+
+#define XFS_BUF_ERROR(x,no)	 pagebuf_ioerror(x,no)
+#define XFS_BUF_GETERROR(x)	 pagebuf_geterror(x)
+#define XFS_BUF_ISERROR(x)	 (pagebuf_geterror(x)?1:0)
+
+#define XFS_BUF_DONE(x)		 ((x)->pb_flags &= ~(PBF_PARTIAL|PBF_NONE))
+#define XFS_BUF_UNDONE(x)	 ((x)->pb_flags |= PBF_PARTIAL|PBF_NONE)
+#define XFS_BUF_ISDONE(x)	 (!(PBF_NOT_DONE(x)))
+
+#define XFS_BUF_BUSY(x)		 ((x)->pb_flags |= PBF_FORCEIO)
+#define XFS_BUF_UNBUSY(x)	 ((x)->pb_flags &= ~PBF_FORCEIO)
+#define XFS_BUF_ISBUSY(x)	 (1)
+
+#define XFS_BUF_ASYNC(x)	 ((x)->pb_flags |= PBF_ASYNC)
+#define XFS_BUF_UNASYNC(x)	 ((x)->pb_flags &= ~PBF_ASYNC)
+#define XFS_BUF_ISASYNC(x)	 ((x)->pb_flags & PBF_ASYNC)
+
+#define XFS_BUF_FLUSH(x)	 ((x)->pb_flags |= PBF_FLUSH)
+#define XFS_BUF_UNFLUSH(x)	 ((x)->pb_flags &= ~PBF_FLUSH)
+#define XFS_BUF_ISFLUSH(x)	 ((x)->pb_flags & PBF_FLUSH)
+
+#define XFS_BUF_SHUT(x)		 printk("XFS_BUF_SHUT not implemented yet\n")
+#define XFS_BUF_UNSHUT(x)	 printk("XFS_BUF_UNSHUT not implemented yet\n")
+#define XFS_BUF_ISSHUT(x)	 (0)
+
+#define XFS_BUF_HOLD(x)		pagebuf_hold(x)
+#define XFS_BUF_READ(x)		((x)->pb_flags |= PBF_READ)
+#define XFS_BUF_UNREAD(x)	((x)->pb_flags &= ~PBF_READ)
+#define XFS_BUF_ISREAD(x)	((x)->pb_flags & PBF_READ)
+
+#define XFS_BUF_WRITE(x)	((x)->pb_flags |= PBF_WRITE)
+#define XFS_BUF_UNWRITE(x)	((x)->pb_flags &= ~PBF_WRITE)
+#define XFS_BUF_ISWRITE(x)	((x)->pb_flags & PBF_WRITE)
+
+#define XFS_BUF_ISUNINITIAL(x)	 (0)
+#define XFS_BUF_UNUNINITIAL(x)	 (0)
+
+#define XFS_BUF_BP_ISMAPPED(bp)	 1
+
+typedef struct page_buf_s xfs_buf_t;
+#define xfs_buf page_buf_s
+
+typedef struct pb_target xfs_buftarg_t;
+#define xfs_buftarg pb_target
+
+#define XFS_BUF_DATAIO(x)	((x)->pb_flags |= PBF_FS_DATAIOD)
+#define XFS_BUF_UNDATAIO(x)	((x)->pb_flags &= ~PBF_FS_DATAIOD)
+
+#define XFS_BUF_IODONE_FUNC(buf)	(buf)->pb_iodone
+#define XFS_BUF_SET_IODONE_FUNC(buf, func)	\
+			(buf)->pb_iodone = (func)
+#define XFS_BUF_CLR_IODONE_FUNC(buf)		\
+			(buf)->pb_iodone = NULL
+#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func)	\
+			(buf)->pb_strat = (func)
+#define XFS_BUF_CLR_BDSTRAT_FUNC(buf)		\
+			(buf)->pb_strat = NULL
+
+#define XFS_BUF_FSPRIVATE(buf, type)		\
+			((type)(buf)->pb_fspriv)
+#define XFS_BUF_SET_FSPRIVATE(buf, value)	\
+			(buf)->pb_fspriv = (void *)(value)
+#define XFS_BUF_FSPRIVATE2(buf, type)		\
+			((type)(buf)->pb_fspriv2)
+#define XFS_BUF_SET_FSPRIVATE2(buf, value)	\
+			(buf)->pb_fspriv2 = (void *)(value)
+#define XFS_BUF_FSPRIVATE3(buf, type)		\
+			((type)(buf)->pb_fspriv3)
+#define XFS_BUF_SET_FSPRIVATE3(buf, value)	\
+			(buf)->pb_fspriv3  = (void *)(value)
+#define XFS_BUF_SET_START(buf)
+
+#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \
+			(buf)->pb_relse = (value)
+
+#define XFS_BUF_PTR(bp)		(xfs_caddr_t)((bp)->pb_addr)
+
+extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset)
+{
+	if (bp->pb_flags & PBF_MAPPED)
+		return XFS_BUF_PTR(bp) + offset;
+	return (xfs_caddr_t) pagebuf_offset(bp, offset);
+}
+
+#define XFS_BUF_SET_PTR(bp, val, count)		\
+				pagebuf_associate_memory(bp, val, count)
+#define XFS_BUF_ADDR(bp)	((bp)->pb_bn)
+#define XFS_BUF_SET_ADDR(bp, blk)		\
+			((bp)->pb_bn = (page_buf_daddr_t)(blk))
+#define XFS_BUF_OFFSET(bp)	((bp)->pb_file_offset)
+#define XFS_BUF_SET_OFFSET(bp, off)		\
+			((bp)->pb_file_offset = (off))
+#define XFS_BUF_COUNT(bp)	((bp)->pb_count_desired)
+#define XFS_BUF_SET_COUNT(bp, cnt)		\
+			((bp)->pb_count_desired = (cnt))
+#define XFS_BUF_SIZE(bp)	((bp)->pb_buffer_length)
+#define XFS_BUF_SET_SIZE(bp, cnt)		\
+			((bp)->pb_buffer_length = (cnt))
+#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
+#define XFS_BUF_SET_VTYPE(bp, type)
+#define XFS_BUF_SET_REF(bp, ref)
+
+#define XFS_BUF_ISPINNED(bp)	pagebuf_ispin(bp)
+
+#define XFS_BUF_VALUSEMA(bp)	pagebuf_lock_value(bp)
+#define XFS_BUF_CPSEMA(bp)	(pagebuf_cond_lock(bp) == 0)
+#define XFS_BUF_VSEMA(bp)	pagebuf_unlock(bp)
+#define XFS_BUF_PSEMA(bp,x)	pagebuf_lock(bp)
+#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema);
+
+/* setup the buffer target from a buftarg structure */
+#define XFS_BUF_SET_TARGET(bp, target)	\
+		(bp)->pb_target = (target)
+#define XFS_BUF_TARGET(bp)	((bp)->pb_target)
+#define XFS_BUFTARG_NAME(target)	\
+		pagebuf_target_name(target)
+
+#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
+#define XFS_BUF_SET_VTYPE(bp, type)
+#define XFS_BUF_SET_REF(bp, ref)
+
+#define xfs_buf_read(target, blkno, len, flags) \
+		pagebuf_get((target), (blkno), (len), \
+			PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE)
+#define xfs_buf_get(target, blkno, len, flags) \
+		pagebuf_get((target), (blkno), (len), \
+			PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE)
+
+#define xfs_buf_read_flags(target, blkno, len, flags) \
+		pagebuf_get((target), (blkno), (len), \
+			PBF_READ | PBF_MAPPABLE | flags)
+#define xfs_buf_get_flags(target, blkno, len, flags) \
+		pagebuf_get((target), (blkno), (len), \
+			PBF_MAPPABLE | flags)
+
+static inline int	xfs_bawrite(void *mp, page_buf_t *bp)
+{
+	bp->pb_fspriv3 = mp;
+	bp->pb_strat = xfs_bdstrat_cb;
+	xfs_buf_undelay(bp);
+	return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | PBF_RUN_QUEUES);
+}
+
+static inline void	xfs_buf_relse(page_buf_t *bp)
+{
+	if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse)
+		pagebuf_unlock(bp);
+	pagebuf_rele(bp);
+}
+
+#define xfs_bpin(bp)		pagebuf_pin(bp)
+#define xfs_bunpin(bp)		pagebuf_unpin(bp)
+
+#define xfs_buftrace(id, bp)	\
+	    pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0))
+
+#define xfs_biodone(pb)		    \
+	    pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 0)
+
+#define xfs_incore(buftarg,blkno,len,lockit) \
+	    pagebuf_find(buftarg, blkno ,len, lockit)
+
+
+#define xfs_biomove(pb, off, len, data, rw) \
+	    pagebuf_iomove((pb), (off), (len), (data), \
+		((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ)
+
+#define xfs_biozero(pb, off, len) \
+	    pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO)
+
+
+static inline int	XFS_bwrite(page_buf_t *pb)
+{
+	int	iowait = (pb->pb_flags & PBF_ASYNC) == 0;
+	int	error = 0;
+
+	pb->pb_flags |= PBF_SYNC;
+	if (!iowait)
+		pb->pb_flags |= PBF_RUN_QUEUES;
+
+	xfs_buf_undelay(pb);
+	pagebuf_iostrategy(pb);
+	if (iowait) {
+		error = pagebuf_iowait(pb);
+		xfs_buf_relse(pb);
+	}
+	return error;
+}
+
+#define XFS_bdwrite(pb)		     \
+	    pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC)
+
+static inline int xfs_bdwrite(void *mp, page_buf_t *bp)
+{
+	bp->pb_strat = xfs_bdstrat_cb;
+	bp->pb_fspriv3 = mp;
+
+	return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC);
+}
+
+#define XFS_bdstrat(bp) pagebuf_iorequest(bp)
+
+#define xfs_iowait(pb)	pagebuf_iowait(pb)
+
+
+/*
+ * Go through all incore buffers, and release buffers
+ * if they belong to the given device. This is used in
+ * filesystem error handling to preserve the consistency
+ * of its metadata.
+ */
+
+#define xfs_binval(buftarg)	xfs_flush_buftarg(buftarg)
+
+#define XFS_bflush(buftarg)	xfs_flush_buftarg(buftarg)
+
+#define xfs_incore_relse(buftarg,delwri_only,wait)	\
+	xfs_relse_buftarg(buftarg)
+
+#define xfs_baread(target, rablkno, ralen)  \
+	pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK)
+
+#define xfs_buf_get_empty(len, target)	pagebuf_get_empty((len), (target))
+#define xfs_buf_get_noaddr(len, target)	pagebuf_get_no_daddr((len), (target))
+#define xfs_buf_free(bp)		pagebuf_free(bp)
+
+#endif	/* __XFS_BUF_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_globals.c linux-2.4.25-rc1/fs/xfs/linux/xfs_globals.c
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_globals.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_globals.c	2004-02-05 04:40:36.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -36,59 +36,9 @@
  */
 
 #include "xfs.h"
-
-#include "xfs_fs.h"
-#include "xfs_buf.h"
-#include "xfs_macros.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_clnt.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_imap.h"
-#include "xfs_alloc.h"
-#include "xfs_dmapi.h"
-#include "xfs_quota.h"
-#include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_bmap.h"
-#include "xfs_bit.h"
-#include "xfs_rtalloc.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
+#include "xfs_cred.h"
+#include "xfs_sysctl.h"
 #include "xfs_refcache.h"
-#include "xfs_da_btree.h"
-#include "xfs_dir_leaf.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
-#include "xfs_dir2_node.h"
-#include "xfs_dir2_trace.h"
-#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
-#include "xfs_attr.h"
-#include "xfs_attr_leaf.h"
-#include "xfs_inode_item.h"
-#include "xfs_buf_item.h"
-#include "xfs_extfree_item.h"
-#include "xfs_log_priv.h"
-#include "xfs_trans_priv.h"
-#include "xfs_trans_space.h"
-#include "xfs_utils.h"
 
 /*
  * System memory size - used to scale certain data structures in XFS.
@@ -121,69 +71,3 @@
  */
 cred_t sys_cred_val, *sys_cred = &sys_cred_val;
 
-/*
- * Export symbols used for XFS debugging
- */
-EXPORT_SYMBOL(xfs_next_bit);
-EXPORT_SYMBOL(xfs_contig_bits);
-EXPORT_SYMBOL(xfs_bmbt_get_all);
-#if ARCH_CONVERT != ARCH_NOCONVERT
-EXPORT_SYMBOL(xfs_bmbt_disk_get_all);
-#endif
-
-#if defined(CONFIG_XFS_DEBUG)
-EXPORT_SYMBOL(xfs_fsb_to_agbno);
-EXPORT_SYMBOL(xfs_dir2_data_unused_tag_p_arch);
-EXPORT_SYMBOL(xfs_attr_leaf_name_remote);
-EXPORT_SYMBOL(xfs_lic_slot);
-EXPORT_SYMBOL(xfs_dir2_sf_firstentry);
-EXPORT_SYMBOL(xfs_ino_to_agno);
-EXPORT_SYMBOL(xfs_dir2_sf_get_inumber_arch);
-EXPORT_SYMBOL(xfs_ifork_q);
-EXPORT_SYMBOL(xfs_dir2_data_entry_tag_p);
-EXPORT_SYMBOL(xfs_dir2_sf_inumberp);
-EXPORT_SYMBOL(xfs_dir2_data_entsize);
-EXPORT_SYMBOL(xfs_lic_isfree);
-EXPORT_SYMBOL(xfs_attr_leaf_name_local);
-EXPORT_SYMBOL(xfs_bmap_broot_ptr_addr);
-EXPORT_SYMBOL(xfs_dir_sf_get_dirino_arch);
-EXPORT_SYMBOL(xfs_ino_to_agbno);
-EXPORT_SYMBOL(xfs_fsb_to_agno);
-EXPORT_SYMBOL(xfs_dir2_leaf_bests_p_arch);
-EXPORT_SYMBOL(xfs_dir2_sf_get_offset_arch);
-EXPORT_SYMBOL(startblockval);
-EXPORT_SYMBOL(xfs_attr_sf_nextentry);
-EXPORT_SYMBOL(xfs_bmap_broot_key_addr);
-EXPORT_SYMBOL(xfs_dir2_block_leaf_p_arch);
-EXPORT_SYMBOL(xfs_mtovfs);
-EXPORT_SYMBOL(xfs_dir_leaf_namestruct);
-EXPORT_SYMBOL(xfs_ino_to_offset);
-EXPORT_SYMBOL(xfs_itobhv);
-EXPORT_SYMBOL(xfs_ifork_ptr);
-EXPORT_SYMBOL(isnullstartblock);
-EXPORT_SYMBOL(xfs_lic_are_all_free);
-EXPORT_SYMBOL(xfs_dir_sf_nextentry);
-EXPORT_SYMBOL(xfs_dir2_sf_nextentry);
-#endif
-
-/*
- * Export symbols used for XFS tracing
- */
-#ifdef XFS_ALLOC_TRACE
-EXPORT_SYMBOL(xfs_alloc_trace_buf);
-#endif
-#ifdef XFS_BMAP_TRACE
-EXPORT_SYMBOL(xfs_bmap_trace_buf);
-#endif
-#ifdef XFS_BMBT_TRACE
-EXPORT_SYMBOL(xfs_bmbt_trace_buf);
-#endif
-#ifdef XFS_ATTR_TRACE
-EXPORT_SYMBOL(xfs_attr_trace_buf);
-#endif  
-#ifdef XFS_DIR2_TRACE
-EXPORT_SYMBOL(xfs_dir2_trace_buf);
-#endif   
-#ifdef XFS_DIR_TRACE
-EXPORT_SYMBOL(xfs_dir_trace_buf);
-#endif
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_iomap.c linux-2.4.25-rc1/fs/xfs/linux/xfs_iomap.c
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_iomap.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_iomap.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,795 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.	 Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-#include "xfs.h"
-
-#include "xfs_fs.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_alloc.h"
-#include "xfs_dmapi.h"
-#include "xfs_quota.h"
-#include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_bmap.h"
-#include "xfs_bit.h"
-#include "xfs_rtalloc.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
-#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
-#include "xfs_attr.h"
-#include "xfs_buf_item.h"
-#include "xfs_trans_space.h"
-#include "xfs_utils.h"
-#include "xfs_iomap.h"
-
-#define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
-						<< mp->m_writeio_log)
-#define XFS_STRAT_WRITE_IMAPS	2
-#define XFS_WRITE_IMAPS		XFS_BMAP_MAX_NMAP
-
-STATIC int
-xfs_imap_to_bmap(
-	xfs_iocore_t	*io,
-	xfs_off_t	offset,
-	xfs_bmbt_irec_t *imap,
-	xfs_iomap_t	*iomapp,
-	int		imaps,			/* Number of imap entries */
-	int		iomaps,			/* Number of iomap entries */
-	int		flags)
-{
-	xfs_mount_t	*mp;
-	xfs_fsize_t	nisize;
-	int		pbm;
-	xfs_fsblock_t	start_block;
-
-	mp = io->io_mount;
-	nisize = XFS_SIZE(mp, io);
-	if (io->io_new_size > nisize)
-		nisize = io->io_new_size;
-
-	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
-		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
-			mp->m_rtdev_targp : mp->m_ddev_targp;
-		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
-		iomapp->iomap_delta = offset - iomapp->iomap_offset;
-		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
-		iomapp->iomap_flags = flags;
-
-		start_block = imap->br_startblock;
-		if (start_block == HOLESTARTBLOCK) {
-			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_HOLE;
-		} else if (start_block == DELAYSTARTBLOCK) {
-			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_DELAY;
-		} else {
-			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
-			if (ISUNWRITTEN(imap))
-				iomapp->iomap_flags |= IOMAP_UNWRITTEN;
-		}
-
-		if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) {
-			iomapp->iomap_flags |= IOMAP_EOF;
-		}
-
-		offset += iomapp->iomap_bsize - iomapp->iomap_delta;
-	}
-	return pbm;	/* Return the number filled */
-}
-
-int
-xfs_iomap(
-	xfs_iocore_t	*io,
-	xfs_off_t	offset,
-	ssize_t		count,
-	int		flags,
-	xfs_iomap_t	*iomapp,
-	int		*niomaps)
-{
-	xfs_mount_t	*mp = io->io_mount;
-	xfs_fileoff_t	offset_fsb, end_fsb;
-	int		error = 0;
-	int		lockmode = 0;
-	xfs_bmbt_irec_t	imap;
-	int		nimaps = 1;
-	int		bmapi_flags = 0;
-	int		iomap_flags = 0;
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return XFS_ERROR(EIO);
-
-	switch (flags &
-		(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
-		 BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
-	case BMAPI_READ:
-		lockmode = XFS_LCK_MAP_SHARED(mp, io);
-		bmapi_flags = XFS_BMAPI_ENTIRE;
-		if (flags & BMAPI_IGNSTATE)
-			bmapi_flags |= XFS_BMAPI_IGSTATE;
-		break;
-	case BMAPI_WRITE:
-		lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
-		bmapi_flags = 0;
-		XFS_ILOCK(mp, io, lockmode);
-		break;
-	case BMAPI_ALLOCATE:
-		lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
-		bmapi_flags = XFS_BMAPI_ENTIRE;
-		/* Attempt non-blocking lock */
-		if (flags & BMAPI_TRYLOCK) {
-			if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))
-				return XFS_ERROR(EAGAIN);
-		} else {
-			XFS_ILOCK(mp, io, lockmode);
-		}
-		break;
-	case BMAPI_UNWRITTEN:
-		goto phase2;
-	case BMAPI_DEVICE:
-		lockmode = XFS_LCK_MAP_SHARED(mp, io);
-		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
-			mp->m_rtdev_targp : mp->m_ddev_targp;
-		error = 0;
-		*niomaps = 1;
-		goto out;
-	default:
-		BUG();
-	}
-
-	ASSERT(offset <= mp->m_maxioffset);
-	if ((xfs_fsize_t)offset + count > mp->m_maxioffset)
-		count = mp->m_maxioffset - offset;
-	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
-	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-
-	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
-			(xfs_filblks_t)(end_fsb - offset_fsb),
-			bmapi_flags,  NULL, 0, &imap,
-			&nimaps, NULL);
-
-	if (error)
-		goto out;
-
-phase2:
-	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
-	case BMAPI_WRITE:
-		/* If we found an extent, return it */
-		if (nimaps && (imap.br_startblock != HOLESTARTBLOCK))
-			break;
-
-		if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
-			error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
-					count, flags, &imap, &nimaps, nimaps);
-		} else {
-			error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
-					flags, &imap, &nimaps);
-		}
-		iomap_flags = IOMAP_NEW;
-		break;
-	case BMAPI_ALLOCATE:
-		/* If we found an extent, return it */
-		XFS_IUNLOCK(mp, io, lockmode);
-		lockmode = 0;
-
-		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock))
-			break;
-
-		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
-		break;
-	case BMAPI_UNWRITTEN:
-		lockmode = 0;
-		error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count);
-		nimaps = 0;
-		break;
-	}
-
-	if (nimaps) {
-		*niomaps = xfs_imap_to_bmap(io, offset, &imap,
-					    iomapp, nimaps, *niomaps, iomap_flags);
-	} else if (niomaps) {
-		*niomaps = 0;
-	}
-
-out:
-	if (lockmode)
-		XFS_IUNLOCK(mp, io, lockmode);
-	return XFS_ERROR(error);
-}
-
-STATIC int
-xfs_flush_space(
-	xfs_inode_t	*ip,
-	int		*fsynced,
-	int		*ioflags)
-{
-	switch (*fsynced) {
-	case 0:
-		if (ip->i_delayed_blks) {
-			xfs_iunlock(ip, XFS_ILOCK_EXCL);
-			xfs_flush_inode(ip);
-			xfs_ilock(ip, XFS_ILOCK_EXCL);
-			*fsynced = 1;
-		} else {
-			*ioflags |= BMAPI_SYNC;
-			*fsynced = 2;
-		}
-		return 0;
-	case 1:
-		*fsynced = 2;
-		*ioflags |= BMAPI_SYNC;
-		return 0;
-	case 2:
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		xfs_flush_device(ip);
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		*fsynced = 3;
-		return 0;
-	}
-	return 1;
-}
-
-int
-xfs_iomap_write_direct(
-	xfs_inode_t	*ip,
-	loff_t		offset,
-	size_t		count,
-	int		flags,
-	xfs_bmbt_irec_t *ret_imap,
-	int		*nmaps,
-	int		found)
-{
-	xfs_mount_t	*mp = ip->i_mount;
-	xfs_iocore_t	*io = &ip->i_iocore;
-	xfs_fileoff_t	offset_fsb;
-	xfs_fileoff_t	last_fsb;
-	xfs_filblks_t	count_fsb;
-	xfs_fsize_t	isize;
-	xfs_fsblock_t	firstfsb;
-	int		nimaps, maps;
-	int		error;
-	int		bmapi_flag;
-	int		rt;
-	xfs_trans_t	*tp;
-	xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
-	xfs_bmap_free_t free_list;
-	int		aeof;
-	xfs_filblks_t	datablocks;
-	int		committed;
-	int		numrtextents;
-	uint		resblks;
-
-	/*
-	 * Make sure that the dquots are there. This doesn't hold
-	 * the ilock across a disk read.
-	 */
-
-	error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
-	if (error)
-		return XFS_ERROR(error);
-
-	maps = min(XFS_WRITE_IMAPS, *nmaps);
-	nimaps = maps;
-
-	isize = ip->i_d.di_size;
-	aeof = (offset + count) > isize;
-
-	if (io->io_new_size > isize)
-		isize = io->io_new_size;
-
-	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
-	count_fsb = last_fsb - offset_fsb;
-	if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) {
-		xfs_fileoff_t	map_last_fsb;
-
-		map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
-
-		if (map_last_fsb < last_fsb) {
-			last_fsb = map_last_fsb;
-			count_fsb = last_fsb - offset_fsb;
-		}
-		ASSERT(count_fsb > 0);
-	}
-
-	/*
-	 * determine if reserving space on
-	 * the data or realtime partition.
-	 */
-	if ((rt = XFS_IS_REALTIME_INODE(ip))) {
-		int	sbrtextsize, iprtextsize;
-
-		sbrtextsize = mp->m_sb.sb_rextsize;
-		iprtextsize =
-			ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize;
-		numrtextents = (count_fsb + iprtextsize - 1);
-		do_div(numrtextents, sbrtextsize);
-		datablocks = 0;
-	} else {
-		datablocks = count_fsb;
-		numrtextents = 0;
-	}
-
-	/*
-	 * allocate and setup the transaction
-	 */
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
-
-	resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
-
-	error = xfs_trans_reserve(tp, resblks,
-			XFS_WRITE_LOG_RES(mp), numrtextents,
-			XFS_TRANS_PERM_LOG_RES,
-			XFS_WRITE_LOG_COUNT);
-
-	/*
-	 * check for running out of space
-	 */
-	if (error)
-		/*
-		 * Free the transaction structure.
-		 */
-		xfs_trans_cancel(tp, 0);
-
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-	if (error)
-		goto error_out; /* Don't return in above if .. trans ..,
-					need lock to return */
-
-	if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
-		error = (EDQUOT);
-		goto error1;
-	}
-	nimaps = 1;
-
-	bmapi_flag = XFS_BMAPI_WRITE;
-	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-	xfs_trans_ihold(tp, ip);
-
-	if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt))
-		bmapi_flag |= XFS_BMAPI_PREALLOC;
-
-	/*
-	 * issue the bmapi() call to allocate the blocks
-	 */
-	XFS_BMAP_INIT(&free_list, &firstfsb);
-	imapp = &imap[0];
-	error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
-		bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
-	if (error) {
-		goto error0;
-	}
-
-	/*
-	 * complete the transaction
-	 */
-
-	error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
-	if (error) {
-		goto error0;
-	}
-
-	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
-	if (error) {
-		goto error_out;
-	}
-
-	/* copy any maps to caller's array and return any error. */
-	if (nimaps == 0) {
-		error = (ENOSPC);
-		goto error_out;
-	}
-
-	*ret_imap = imap[0];
-	*nmaps = 1;
-	return 0;
-
- error0:	/* Cancel bmap, unlock inode, and cancel trans */
-	xfs_bmap_cancel(&free_list);
-
- error1:	/* Just cancel transaction */
-	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
-	*nmaps = 0;	/* nothing set-up here */
-
-error_out:
-	return XFS_ERROR(error);
-}
-
-int
-xfs_iomap_write_delay(
-	xfs_inode_t	*ip,
-	loff_t		offset,
-	size_t		count,
-	int		ioflag,
-	xfs_bmbt_irec_t *ret_imap,
-	int		*nmaps)
-{
-	xfs_mount_t	*mp = ip->i_mount;
-	xfs_iocore_t	*io = &ip->i_iocore;
-	xfs_fileoff_t	offset_fsb;
-	xfs_fileoff_t	last_fsb;
-	xfs_fsize_t	isize;
-	xfs_fsblock_t	firstblock;
-	int		nimaps;
-	int		error;
-	xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
-	int		aeof;
-	int		fsynced = 0;
-
-	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
-
-	/*
-	 * Make sure that the dquots are there. This doesn't hold
-	 * the ilock across a disk read.
-	 */
-
-	error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
-	if (error)
-		return XFS_ERROR(error);
-
-retry:
-	isize = ip->i_d.di_size;
-	if (io->io_new_size > isize) {
-		isize = io->io_new_size;
-	}
-
-	aeof = 0;
-	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
-	/*
-	 * If the caller is doing a write at the end of the file,
-	 * then extend the allocation (and the buffer used for the write)
-	 * out to the file system's write iosize.  We clean up any extra
-	 * space left over when the file is closed in xfs_inactive().
-	 *
-	 * We don't bother with this for sync writes, because we need
-	 * to minimize the amount we write for good performance.
-	 */
-	if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) {
-		xfs_off_t	aligned_offset;
-		unsigned int	iosize;
-		xfs_fileoff_t	ioalign;
-
-		iosize = mp->m_writeio_blocks;
-		aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1));
-		ioalign = XFS_B_TO_FSBT(mp, aligned_offset);
-		last_fsb = ioalign + iosize;
-		aeof = 1;
-	}
-
-	nimaps = XFS_WRITE_IMAPS;
-	firstblock = NULLFSBLOCK;
-
-	/*
-	 * roundup the allocation request to m_dalign boundary if file size
-	 * is greater that 512K and we are allocating past the allocation eof
-	 */
-	if (mp->m_dalign && (isize >= mp->m_dalign) && aeof) {
-		int eof;
-		xfs_fileoff_t new_last_fsb;
-		new_last_fsb = roundup_64(last_fsb, mp->m_dalign);
-		error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof);
-		if (error) {
-			return error;
-		}
-		if (eof) {
-			last_fsb = new_last_fsb;
-		}
-	}
-
-	error = xfs_bmapi(NULL, ip, offset_fsb,
-			  (xfs_filblks_t)(last_fsb - offset_fsb),
-			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
-			  XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
-			  &nimaps, NULL);
-	/*
-	 * This can be EDQUOT, if nimaps == 0
-	 */
-	if (error && (error != ENOSPC)) {
-		return XFS_ERROR(error);
-	}
-	/*
-	 * If bmapi returned us nothing, and if we didn't get back EDQUOT,
-	 * then we must have run out of space.
-	 */
-
-	if (nimaps == 0) {
-		if (xfs_flush_space(ip, &fsynced, &ioflag))
-			return XFS_ERROR(ENOSPC);
-
-		error = 0;
-		goto retry;
-	}
-
-	*ret_imap = imap[0];
-	*nmaps = 1;
-	return 0;
-}
-
-/*
- * Pass in a delayed allocate extent, convert it to real extents;
- * return to the caller the extent we create which maps on top of
- * the originating callers request.
- *
- * Called without a lock on the inode.
- */
-int
-xfs_iomap_write_allocate(
-	xfs_inode_t	*ip,
-	xfs_bmbt_irec_t *map,
-	int		*retmap)
-{
-	xfs_mount_t	*mp = ip->i_mount;
-	xfs_fileoff_t	offset_fsb, last_block;
-	xfs_fileoff_t	end_fsb, map_start_fsb;
-	xfs_fsblock_t	first_block;
-	xfs_bmap_free_t	free_list;
-	xfs_filblks_t	count_fsb;
-	xfs_bmbt_irec_t	imap[XFS_STRAT_WRITE_IMAPS];
-	xfs_trans_t	*tp;
-	int		i, nimaps, committed;
-	int		error = 0;
-	int		nres;
-
-	*retmap = 0;
-
-	/*
-	 * Make sure that the dquots are there.
-	 */
-
-	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
-		return XFS_ERROR(error);
-
-	offset_fsb = map->br_startoff;
-	count_fsb = map->br_blockcount;
-	map_start_fsb = offset_fsb;
-
-	XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
-
-	while (count_fsb != 0) {
-		/*
-		 * Set up a transaction with which to allocate the
-		 * backing store for the file.  Do allocations in a
-		 * loop until we get some space in the range we are
-		 * interested in.  The other space that might be allocated
-		 * is in the delayed allocation extent on which we sit
-		 * but before our buffer starts.
-		 */
-
-		nimaps = 0;
-		while (nimaps == 0) {
-			tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
-			nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
-			error = xfs_trans_reserve(tp, nres,
-					XFS_WRITE_LOG_RES(mp),
-					0, XFS_TRANS_PERM_LOG_RES,
-					XFS_WRITE_LOG_COUNT);
-
-			if (error == ENOSPC) {
-				error = xfs_trans_reserve(tp, 0,
-						XFS_WRITE_LOG_RES(mp),
-						0,
-						XFS_TRANS_PERM_LOG_RES,
-						XFS_WRITE_LOG_COUNT);
-			}
-			if (error) {
-				xfs_trans_cancel(tp, 0);
-				return XFS_ERROR(error);
-			}
-			xfs_ilock(ip, XFS_ILOCK_EXCL);
-			xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-			xfs_trans_ihold(tp, ip);
-
-			XFS_BMAP_INIT(&free_list, &first_block);
-
-			nimaps = XFS_STRAT_WRITE_IMAPS;
-			/*
-			 * Ensure we don't go beyond eof - it is possible
-			 * the extents changed since we did the read call,
-			 * we dropped the ilock in the interim.
-			 */
-
-			end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size);
-			xfs_bmap_last_offset(NULL, ip, &last_block,
-				XFS_DATA_FORK);
-			last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
-			if ((map_start_fsb + count_fsb) > last_block) {
-				count_fsb = last_block - map_start_fsb;
-				if (count_fsb == 0) {
-					error = EAGAIN;
-					goto trans_cancel;
-				}
-			}
-
-			/* Go get the actual blocks */
-			error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
-					XFS_BMAPI_WRITE, &first_block, 1,
-					imap, &nimaps, &free_list);
-
-			if (error)
-				goto trans_cancel;
-
-			error = xfs_bmap_finish(&tp, &free_list,
-					first_block, &committed);
-
-			if (error)
-				goto trans_cancel;
-
-			error = xfs_trans_commit(tp,
-					XFS_TRANS_RELEASE_LOG_RES, NULL);
-
-			if (error)
-				goto error0;
-
-			xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		}
-
-		/*
-		 * See if we were able to allocate an extent that
-		 * covers at least part of the callers request
-		 */
-
-		for (i = 0; i < nimaps; i++) {
-			if ((map->br_startoff >= imap[i].br_startoff) &&
-			    (map->br_startoff < (imap[i].br_startoff +
-						 imap[i].br_blockcount))) {
-				*map = imap[i];
-				*retmap = 1;
-				XFS_STATS_INC(xs_xstrat_quick);
-				return 0;
-			}
-			count_fsb -= imap[i].br_blockcount;
-		}
-
-		/* So far we have not mapped the requested part of the
-		 * file, just surrounding data, try again.
-		 */
-		nimaps--;
-		offset_fsb = imap[nimaps].br_startoff +
-			     imap[nimaps].br_blockcount;
-		map_start_fsb = offset_fsb;
-	}
-
-trans_cancel:
-	xfs_bmap_cancel(&free_list);
-	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
-error0:
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	return XFS_ERROR(error);
-}
-
-int
-xfs_iomap_write_unwritten(
-	xfs_inode_t	*ip,
-	loff_t		offset,
-	size_t		count)
-{
-	xfs_mount_t	*mp = ip->i_mount;
-	xfs_trans_t	*tp;
-	xfs_fileoff_t	offset_fsb;
-	xfs_filblks_t	count_fsb;
-	xfs_filblks_t	numblks_fsb;
-	xfs_bmbt_irec_t	imap;
-	int		committed;
-	int		error;
-	int		nres;
-	int		nimaps;
-	xfs_fsblock_t	firstfsb;
-	xfs_bmap_free_t	free_list;
-
-	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-	count_fsb = XFS_B_TO_FSB(mp, count);
-
-	do {
-		nres = XFS_DIOSTRAT_SPACE_RES(mp, 0);
-
-		/*
-		 * set up a transaction to convert the range of extents
-		 * from unwritten to real. Do allocations in a loop until
-		 * we have covered the range passed in.
-		 */
-
-		tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
-		error = xfs_trans_reserve(tp, nres,
-				XFS_WRITE_LOG_RES(mp), 0,
-				XFS_TRANS_PERM_LOG_RES,
-				XFS_WRITE_LOG_COUNT);
-		if (error) {
-			xfs_trans_cancel(tp, 0);
-			goto error0;
-		}
-
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-		xfs_trans_ihold(tp, ip);
-
-		/*
-		 * Modify the unwritten extent state of the buffer.
-		 */
-		XFS_BMAP_INIT(&free_list, &firstfsb);
-		nimaps = 1;
-		error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
-				  XFS_BMAPI_WRITE, &firstfsb,
-				  1, &imap, &nimaps, &free_list);
-		if (error)
-			goto error_on_bmapi_transaction;
-
-		error = xfs_bmap_finish(&(tp), &(free_list),
-				firstfsb, &committed);
-		if (error)
-			goto error_on_bmapi_transaction;
-
-		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		if (error)
-			goto error0;
-
-		if ((numblks_fsb = imap.br_blockcount) == 0) {
-			/*
-			 * The numblks_fsb value should always get
-			 * smaller, otherwise the loop is stuck.
-			 */
-			ASSERT(imap.br_blockcount);
-			break;
-		}
-		offset_fsb += numblks_fsb;
-		count_fsb -= numblks_fsb;
-	} while (count_fsb > 0);
-
-	return 0;
-
-error_on_bmapi_transaction:
-	xfs_bmap_cancel(&free_list);
-	xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT));
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-error0:
-	return XFS_ERROR(error);
-}
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_linux.h linux-2.4.25-rc1/fs/xfs/linux/xfs_linux.h
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_linux.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_linux.h	2004-02-05 04:40:36.000000000 -0800
@@ -47,18 +47,19 @@
 #include <xfs_types.h>
 #include <xfs_arch.h>
 
-#include <support/kmem.h>
-#include <support/mrlock.h>
+#include <kmem.h>
+#include <mrlock.h>
+#include <spin.h>
+#include <sv.h>
+#include <mutex.h>
+#include <sema.h>
+#include <time.h>
+
 #include <support/qsort.h>
-#include <support/spin.h>
-#include <support/sv.h>
 #include <support/ktrace.h>
-#include <support/mutex.h>
-#include <support/sema.h>
 #include <support/debug.h>
 #include <support/move.h>
 #include <support/uuid.h>
-#include <support/time.h>
 
 #include <linux/mm.h>
 #include <linux/kernel.h>
@@ -83,19 +84,18 @@
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
-#include <linux/xfs_behavior.h>
-#include <linux/xfs_vfs.h>
-#include <linux/xfs_cred.h>
-#include <linux/xfs_vnode.h>
-#include <linux/xfs_stats.h>
-#include <linux/xfs_sysctl.h>
-#include <linux/xfs_iops.h>
-#include <linux/xfs_super.h>
-#include <linux/xfs_globals.h>
-#include <linux/xfs_fs_subr.h>
-#include <linux/xfs_lrw.h>
-
-#include <pagebuf/page_buf.h>
+#include <xfs_behavior.h>
+#include <xfs_vfs.h>
+#include <xfs_cred.h>
+#include <xfs_vnode.h>
+#include <xfs_stats.h>
+#include <xfs_sysctl.h>
+#include <xfs_iops.h>
+#include <xfs_super.h>
+#include <xfs_globals.h>
+#include <xfs_fs_subr.h>
+#include <xfs_lrw.h>
+#include <xfs_buf.h>
 
 /*
  * Feature macros (disable/enable)
diff -urN linux-2.4.25-pre8/fs/xfs/linux/xfs_super.h linux-2.4.25-rc1/fs/xfs/linux/xfs_super.h
--- linux-2.4.25-pre8/fs/xfs/linux/xfs_super.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/linux/xfs_super.h	2004-02-05 04:40:36.000000000 -0800
@@ -60,6 +60,14 @@
 # define set_posix_acl_flag(sb)	do { } while (0)
 #endif
 
+#ifdef CONFIG_XFS_SECURITY
+# define XFS_SECURITY_STRING	"security attributes, "
+# define ENOSECURITY		0
+#else
+# define XFS_SECURITY_STRING
+# define ENOSECURITY		EOPNOTSUPP
+#endif
+
 #ifdef CONFIG_XFS_RT
 # define XFS_REALTIME_STRING	"realtime, "
 #else
@@ -89,6 +97,7 @@
 #endif
 
 #define XFS_BUILD_OPTIONS	XFS_ACL_STRING \
+				XFS_SECURITY_STRING \
 				XFS_REALTIME_STRING \
 				XFS_BIGFS_STRING \
 				XFS_TRACE_STRING \
diff -urN linux-2.4.25-pre8/fs/xfs/pagebuf/Makefile linux-2.4.25-rc1/fs/xfs/pagebuf/Makefile
--- linux-2.4.25-pre8/fs/xfs/pagebuf/Makefile	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/pagebuf/Makefile	1969-12-31 16:00:00.000000000 -0800
@@ -1,52 +0,0 @@
-#
-# Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of version 2 of the GNU General Public License as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it would be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#
-# Further, this software is distributed without any warranty that it is
-# free of the rightful claim of any third person regarding infringement
-# or the like.  Any license provided herein, whether implied or
-# otherwise, applies only to this software file.  Patent licenses, if
-# any, provided herein do not apply to combinations of this program with
-# other software, or any other product whatsoever.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write the Free Software Foundation, Inc., 59
-# Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
-# Mountain View, CA  94043, or:
-#
-# http://www.sgi.com
-#
-# For further information regarding this notice, see:
-#
-# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
-#
-# Makefile for the linux pagebuf routines.
-#
-
-ifeq ($(CONFIG_XFS_DEBUG),y)
-	EXTRA_CFLAGS += -g -DDEBUG -DSTATIC="" -DPAGEBUF_LOCK_TRACKING
-endif
-ifeq ($(CONFIG_XFS_TRACE),y)
-	EXTRA_CFLAGS += -DPAGEBUF_TRACE
-endif
-EXTRA_CFLAGS += -I..
-
-O_TARGET			:= pagebuf.o
-
-ifneq ($(MAKECMDGOALS),modules_install)
-  obj-m                         := $(O_TARGET)
-endif
-
-export-objs			+= page_buf.o
-obj-y				+= page_buf.o
-
-include $(TOPDIR)/Rules.make
diff -urN linux-2.4.25-pre8/fs/xfs/pagebuf/page_buf.c linux-2.4.25-rc1/fs/xfs/pagebuf/page_buf.c
--- linux-2.4.25-pre8/fs/xfs/pagebuf/page_buf.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/pagebuf/page_buf.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,2558 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-/*
- *	page_buf.c
- *
- *	The page_buf module provides an abstract buffer cache model on top of
- *	the Linux page cache.  Cached metadata blocks for a file system are
- *	hashed to the inode for the block device.  The page_buf module
- *	assembles buffer (page_buf_t) objects on demand to aggregate such
- *	cached pages for I/O.
- *
- *
- *      Written by Steve Lord, Jim Mostek, Russell Cattelan
- *		    and Rajagopal Ananthanarayanan ("ananth") at SGI.
- *
- */
-
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-#include <linux/blkdev.h>
-#include <linux/locks.h>
-#include <linux/sysctl.h>
-#include <linux/proc_fs.h>
-
-#include <support/ktrace.h>
-#include <support/debug.h>
-#include <support/kmem.h>
-
-#include "page_buf.h"
-
-#define NBBY		8
-#define BBSHIFT		9
-#define BBMASK		((1 << BBSHIFT) - 1)
-#define BN_ALIGN_MASK	((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)
-
-#ifndef GFP_READAHEAD
-#define GFP_READAHEAD	0
-#endif
-
-/*
- * A backport of the 2.5 scheduler is used by many vendors of 2.4-based
- * distributions.
- * We can only guess it's presences by the lack of the SCHED_YIELD flag.
- * If the heuristic doesn't work, change this define by hand.
- */
-#ifndef SCHED_YIELD
-#define __HAVE_NEW_SCHEDULER	1
-#endif
-
-/*
- * cpumask_t is used for supporting NR_CPUS > BITS_PER_LONG.
- * If support for this is present, migrate_to_cpu exists and provides
- * a wrapper around the set_cpus_allowed routine.
- */
-#ifdef copy_cpumask
-#define __HAVE_CPUMASK_T	1
-#endif
-
-#ifndef __HAVE_CPUMASK_T
-# ifndef __HAVE_NEW_SCHEDULER
-#  define migrate_to_cpu(cpu)	\
-	do { current->cpus_allowed = 1UL << (cpu); } while (0)
-# else
-#  define migrate_to_cpu(cpu)	\
-	set_cpus_allowed(current, 1UL << (cpu))
-# endif
-#endif
-
-/*
- * File wide globals
- */
-
-STATIC kmem_cache_t *pagebuf_cache;
-
-#define MAX_IO_DAEMONS		NR_CPUS
-#define CPU_TO_DAEMON(cpu)	(cpu)
-STATIC int pb_logio_daemons[MAX_IO_DAEMONS];
-STATIC struct list_head pagebuf_logiodone_tq[MAX_IO_DAEMONS];
-STATIC wait_queue_head_t pagebuf_logiodone_wait[MAX_IO_DAEMONS];
-STATIC int pb_dataio_daemons[MAX_IO_DAEMONS];
-STATIC struct list_head pagebuf_dataiodone_tq[MAX_IO_DAEMONS];
-STATIC wait_queue_head_t pagebuf_dataiodone_wait[MAX_IO_DAEMONS];
-
-/*
- * For pre-allocated buffer head pool
- */
-
-#define NR_RESERVED_BH	64
-static wait_queue_head_t	pb_resv_bh_wait;
-static spinlock_t		pb_resv_bh_lock = SPIN_LOCK_UNLOCKED;
-struct buffer_head		*pb_resv_bh = NULL;	/* list of bh */
-int				pb_resv_bh_cnt = 0;	/* # of bh available */
-
-STATIC void pagebuf_daemon_wakeup(int);
-STATIC void _pagebuf_ioapply(page_buf_t *);
-STATIC void pagebuf_delwri_queue(page_buf_t *, int);
-STATIC void pagebuf_runall_queues(struct list_head[]);
-
-/*
- * Pagebuf module configuration parameters, exported via
- * /proc/sys/vm/pagebuf
- */
-
-typedef struct pb_sysctl_val {
-	int	min;
-	int	val;
-	int	max;
-} pb_sysctl_val_t;
-
-struct {
-	pb_sysctl_val_t	flush_interval;	/* interval between runs of the
-					 * delwri flush daemon.  */
-	pb_sysctl_val_t	age_buffer;	/* time for buffer to age before
-					 * we flush it.  */
-	pb_sysctl_val_t	stats_clear;	/* clear the pagebuf stats */
-	pb_sysctl_val_t	debug;		/* debug tracing on or off */
-} pb_params = {
-			  /*	MIN	DFLT	MAX	*/
-	.flush_interval	= {	HZ/2,	HZ,	30*HZ	},
-	.age_buffer	= {	1*HZ,	15*HZ,	300*HZ	},
-	.stats_clear	= {	0,	0,	1	},
-	.debug		= {	0,	0,	1	},
-};
-
-enum {
-	PB_FLUSH_INT = 1,
-	PB_FLUSH_AGE = 2,
-	PB_STATS_CLEAR = 3,
-	PB_DEBUG = 4,
-};
-
-/*
- * Pagebuf statistics variables
- */
-
-struct {
-	u_int32_t	pb_get;
-	u_int32_t	pb_create;
-	u_int32_t	pb_get_locked;
-	u_int32_t	pb_get_locked_waited;
-	u_int32_t	pb_busy_locked;
-	u_int32_t	pb_miss_locked;
-	u_int32_t	pb_page_retries;
-	u_int32_t	pb_page_found;
-	u_int32_t	pb_get_read;
-} pbstats;
-
-#define PB_STATS_INC(count)	( pbstats.count++ )
-
-/*
- * Pagebuf debugging
- */
-
-#ifdef PAGEBUF_TRACE
-void
-pagebuf_trace(
-	page_buf_t	*pb,
-	char		*id,
-	void		*data,
-	void		*ra)
-{
-	if (!pb_params.debug.val)
-		return;
-	ktrace_enter(pagebuf_trace_buf,
-		pb, id,
-		(void *)(unsigned long)pb->pb_flags,
-		(void *)(unsigned long)pb->pb_hold.counter,
-		(void *)(unsigned long)pb->pb_sema.count.counter,
-		(void *)current,
-		data, ra,
-		(void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff),
-		(void *)(unsigned long)(pb->pb_file_offset & 0xffffffff),
-		(void *)(unsigned long)pb->pb_buffer_length,
-		NULL, NULL, NULL, NULL, NULL);
-}
-ktrace_t *pagebuf_trace_buf;
-EXPORT_SYMBOL(pagebuf_trace_buf);
-#define PAGEBUF_TRACE_SIZE	4096
-#define PB_TRACE(pb, id, data)	\
-	pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0))
-#else
-#define PB_TRACE(pb, id, data)	do { } while (0)
-#endif
-
-#ifdef PAGEBUF_LOCK_TRACKING
-# define PB_SET_OWNER(pb)	((pb)->pb_last_holder = current->pid)
-# define PB_CLEAR_OWNER(pb)	((pb)->pb_last_holder = -1)
-# define PB_GET_OWNER(pb)	((pb)->pb_last_holder)
-#else
-# define PB_SET_OWNER(pb)	do { } while (0)
-# define PB_CLEAR_OWNER(pb)	do { } while (0)
-# define PB_GET_OWNER(pb)	do { } while (0)
-#endif
-
-/*
- * Pagebuf allocation / freeing.
- */
-
-#define pb_to_gfp(flags) \
-	(((flags) & PBF_READ_AHEAD) ? GFP_READAHEAD : \
-	 ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL)
-
-#define pagebuf_allocate(flags) \
-	kmem_cache_alloc(pagebuf_cache, pb_to_gfp(flags))
-#define pagebuf_deallocate(pb) \
-	kmem_cache_free(pagebuf_cache, (pb));
-
-/*
- * Pagebuf hashing
- */
-
-#define NBITS	8
-#define NHASH	(1<<NBITS)
-
-typedef struct {
-	struct list_head	pb_hash;
-	int			pb_count;
-	spinlock_t		pb_hash_lock;
-} pb_hash_t;
-
-STATIC pb_hash_t	pbhash[NHASH];
-#define pb_hash(pb)	&pbhash[pb->pb_hash_index]
-
-STATIC int
-_bhash(
-	struct block_device *bdev,
-	loff_t		base)
-{
-	int		bit, hval;
-
-	base >>= 9;
-	base ^= (unsigned long)bdev / L1_CACHE_BYTES;
-	for (bit = hval = 0; base && bit < sizeof(base) * 8; bit += NBITS) {
-		hval ^= (int)base & (NHASH-1);
-		base >>= NBITS;
-	}
-	return hval;
-}
-
-/*
- * Mapping of multi-page buffers into contiguous virtual space
- */
-
-STATIC void *pagebuf_mapout_locked(page_buf_t *);
-
-typedef struct a_list {
-	void		*vm_addr;
-	struct a_list	*next;
-} a_list_t;
-
-STATIC a_list_t		*as_free_head;
-STATIC int		as_list_len;
-STATIC spinlock_t	as_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * Try to batch vunmaps because they are costly.
- */
-STATIC void
-free_address(
-	void		*addr)
-{
-	a_list_t	*aentry;
-
-	aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC);
-	if (aentry) {
-		spin_lock(&as_lock);
-		aentry->next = as_free_head;
-		aentry->vm_addr = addr;
-		as_free_head = aentry;
-		as_list_len++;
-		spin_unlock(&as_lock);
-	} else {
-		vunmap(addr);
-	}
-}
-
-STATIC void
-purge_addresses(void)
-{
-	a_list_t	*aentry, *old;
-
-	if (as_free_head == NULL)
-		return;
-
-	spin_lock(&as_lock);
-	aentry = as_free_head;
-	as_free_head = NULL;
-	as_list_len = 0;
-	spin_unlock(&as_lock);
-
-	while ((old = aentry) != NULL) {
-		vunmap(aentry->vm_addr);
-		aentry = aentry->next;
-		kfree(old);
-	}
-}
-
-/*
- *	Internal pagebuf object manipulation
- */
-
-STATIC void
-_pagebuf_initialize(
-	page_buf_t		*pb,
-	pb_target_t		*target,
-	loff_t			range_base,
-	size_t			range_length,
-	page_buf_flags_t	flags)
-{
-	/*
-	 * We don't want certain flags to appear in pb->pb_flags.
-	 */
-	flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD);
-
-	memset(pb, 0, sizeof(page_buf_t));
-	atomic_set(&pb->pb_hold, 1);
-	init_MUTEX_LOCKED(&pb->pb_iodonesema);
-	INIT_LIST_HEAD(&pb->pb_list);
-	INIT_LIST_HEAD(&pb->pb_hash_list);
-	init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */
-	PB_SET_OWNER(pb);
-	pb->pb_target = target;
-	pb->pb_file_offset = range_base;
-	/*
-	 * Set buffer_length and count_desired to the same value initially.
-	 * IO routines should use count_desired, which will be the same in
-	 * most cases but may be reset (e.g. XFS recovery).
-	 */
-	pb->pb_buffer_length = pb->pb_count_desired = range_length;
-	pb->pb_flags = flags | PBF_NONE;
-	pb->pb_bn = PAGE_BUF_DADDR_NULL;
-	atomic_set(&pb->pb_pin_count, 0);
-	init_waitqueue_head(&pb->pb_waiters);
-
-	PB_STATS_INC(pb_create);
-	PB_TRACE(pb, "initialize", target);
-}
-
-/*
- * Allocate a page array capable of holding a specified number
- * of pages, and point the page buf at it.
- */
-STATIC int
-_pagebuf_get_pages(
-	page_buf_t		*pb,
-	int			page_count,
-	page_buf_flags_t	flags)
-{
-	int			gpf_mask = pb_to_gfp(flags);
-
-	/* Make sure that we have a page list */
-	if (pb->pb_pages == NULL) {
-		pb->pb_offset = page_buf_poff(pb->pb_file_offset);
-		pb->pb_page_count = page_count;
-		if (page_count <= PB_PAGES) {
-			pb->pb_pages = pb->pb_page_array;
-		} else {
-			pb->pb_pages = kmalloc(sizeof(struct page *) *
-					page_count, gpf_mask);
-			if (pb->pb_pages == NULL)
-				return -ENOMEM;
-		}
-		memset(pb->pb_pages, 0, sizeof(struct page *) * page_count);
-	}
-	return 0;
-}
-
-/*
- * Walk a pagebuf releasing all the pages contained within it.
- */
-STATIC inline void
-_pagebuf_freepages(
-	page_buf_t		*pb)
-{
-	int			buf_index;
-
-	for (buf_index = 0; buf_index < pb->pb_page_count; buf_index++) {
-		struct page	*page = pb->pb_pages[buf_index];
-
-		if (page) {
-			pb->pb_pages[buf_index] = NULL;
-			page_cache_release(page);
-		}
-	}
-}
-
-/*
- *	_pagebuf_free_object
- *
- *	_pagebuf_free_object releases the contents specified buffer.
- *	The modification state of any associated pages is left unchanged.
- */
-void
-_pagebuf_free_object(
-	pb_hash_t		*hash,	/* hash bucket for buffer */
-	page_buf_t		*pb)	/* buffer to deallocate	*/
-{
-	page_buf_flags_t	pb_flags = pb->pb_flags;
-
-	PB_TRACE(pb, "free_object", 0);
-	pb->pb_flags |= PBF_FREED;
-
-	if (hash) {
-		if (!list_empty(&pb->pb_hash_list)) {
-			hash->pb_count--;
-			list_del_init(&pb->pb_hash_list);
-		}
-		spin_unlock(&hash->pb_hash_lock);
-	}
-
-	if (!(pb_flags & PBF_FREED)) {
-		/* release any virtual mapping */ ;
-		if (pb->pb_flags & _PBF_ADDR_ALLOCATED) {
-			void *vaddr = pagebuf_mapout_locked(pb);
-			if (vaddr) {
-				free_address(vaddr);
-			}
-		}
-
-		if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
-			if (pb->pb_pages) {
-				/* release the pages in the address list */
-				if ((pb->pb_pages[0]) &&
-				    (pb->pb_flags & _PBF_MEM_SLAB)) {
-					kfree(pb->pb_addr);
-				} else {
-					_pagebuf_freepages(pb);
-				}
-				if (pb->pb_pages != pb->pb_page_array)
-					kfree(pb->pb_pages);
-				pb->pb_pages = NULL;
-			}
-			pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
-		}
-	}
-
-	pagebuf_deallocate(pb);
-}
-
-/*
- *	_pagebuf_lookup_pages
- *
- *	_pagebuf_lookup_pages finds all pages which match the buffer
- *	in question and the range of file offsets supplied,
- *	and builds the page list for the buffer, if the
- *	page list is not already formed or if not all of the pages are
- *	already in the list. Invalid pages (pages which have not yet been
- *	read in from disk) are assigned for any pages which are not found.
- */
-STATIC int
-_pagebuf_lookup_pages(
-	page_buf_t		*pb,
-	struct address_space	*aspace,
-	page_buf_flags_t	flags)
-{
-	loff_t			next_buffer_offset;
-	unsigned long		page_count, pi, index;
-	struct page		*page;
-	int			gfp_mask, retry_count = 5, rval = 0;
-	int			all_mapped, good_pages;
-	size_t			blocksize;
-
-	/* For pagebufs where we want to map an address, do not use
-	 * highmem pages - so that we do not need to use kmap resources
-	 * to access the data.
-	 *
-	 * For pages where the caller has indicated there may be resource
-	 * contention (e.g. called from a transaction) do not flush
-	 * delalloc pages to obtain memory.
-	 */
-
-	if (flags & PBF_READ_AHEAD) {
-		gfp_mask = GFP_READAHEAD;
-		retry_count = 0;
-	} else if (flags & PBF_DONT_BLOCK) {
-		gfp_mask = GFP_NOFS;
-	} else if (flags & PBF_MAPPABLE) {
-		gfp_mask = GFP_KERNEL;
-	} else {
-		gfp_mask = GFP_HIGHUSER;
-	}
-
-	next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length;
-
-	good_pages = page_count = (page_buf_btoc(next_buffer_offset) -
-				   page_buf_btoct(pb->pb_file_offset));
-
-	if (pb->pb_flags & _PBF_ALL_PAGES_MAPPED) {
-		/* Bring pages forward in cache */
-		for (pi = 0; pi < page_count; pi++) {
-			mark_page_accessed(pb->pb_pages[pi]);
-		}
-		if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) {
-			all_mapped = 1;
-			goto mapit;
-		}
-		return 0;
-	}
-
-	/* Ensure pb_pages field has been initialised */
-	rval = _pagebuf_get_pages(pb, page_count, flags);
-	if (rval)
-		return rval;
-
-	all_mapped = 1;
-	blocksize = pb->pb_target->pbr_bsize;
-
-	/* Enter the pages in the page list */
-	index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT;
-	for (pi = 0; pi < page_count; pi++, index++) {
-		if (pb->pb_pages[pi] == 0) {
-		      retry:
-			page = find_or_create_page(aspace, index, gfp_mask);
-			if (!page) {
-				if (--retry_count > 0) {
-					PB_STATS_INC(pb_page_retries);
-					pagebuf_daemon_wakeup(1);
-					current->state = TASK_UNINTERRUPTIBLE;
-					schedule_timeout(10);
-					goto retry;
-				}
-				rval = -ENOMEM;
-				all_mapped = 0;
-				continue;
-			}
-			PB_STATS_INC(pb_page_found);
-			mark_page_accessed(page);
-			pb->pb_pages[pi] = page;
-		} else {
-			page = pb->pb_pages[pi];
-			lock_page(page);
-		}
-
-		/* If we need to do I/O on a page record the fact */
-		if (!Page_Uptodate(page)) {
-			good_pages--;
-			if ((blocksize == PAGE_CACHE_SIZE) &&
-			    (flags & PBF_READ))
-				pb->pb_locked = 1;
-		}
-	}
-
-	if (!pb->pb_locked) {
-		for (pi = 0; pi < page_count; pi++) {
-			if (pb->pb_pages[pi])
-				unlock_page(pb->pb_pages[pi]);
-		}
-	}
-
-mapit:
-	pb->pb_flags |= _PBF_MEM_ALLOCATED;
-	if (all_mapped) {
-		pb->pb_flags |= _PBF_ALL_PAGES_MAPPED;
-
-		/* A single page buffer is always mappable */
-		if (page_count == 1) {
-			pb->pb_addr = (caddr_t)
-				page_address(pb->pb_pages[0]) + pb->pb_offset;
-			pb->pb_flags |= PBF_MAPPED;
-		} else if (flags & PBF_MAPPED) {
-			if (as_list_len > 64)
-				purge_addresses();
-			pb->pb_addr = vmap(pb->pb_pages, page_count,
-					VM_ALLOC, PAGE_KERNEL);
-			if (pb->pb_addr == NULL)
-				return -ENOMEM;
-			pb->pb_addr += pb->pb_offset;
-			pb->pb_flags |= PBF_MAPPED | _PBF_ADDR_ALLOCATED;
-		}
-	}
-	/* If some pages were found with data in them
-	 * we are not in PBF_NONE state.
-	 */
-	if (good_pages != 0) {
-		pb->pb_flags &= ~(PBF_NONE);
-		if (good_pages != page_count) {
-			pb->pb_flags |= PBF_PARTIAL;
-		}
-	}
-
-	PB_TRACE(pb, "lookup_pages", (long)good_pages);
-
-	return rval;
-}
-
-
-/*
- *	Pre-allocation of a pool of buffer heads for use in
- *	low-memory situations.
- */
-
-/*
- *	_pagebuf_prealloc_bh
- *
- *	Pre-allocate a pool of "count" buffer heads at startup.
- *	Puts them on a list at "pb_resv_bh"
- *	Returns number of bh actually allocated to pool.
- */
-STATIC int
-_pagebuf_prealloc_bh(
-	int			count)
-{
-	struct buffer_head	*bh;
-	int			i;
-
-	for (i = 0; i < count; i++) {
-		bh = kmem_cache_alloc(bh_cachep, SLAB_KERNEL);
-		if (!bh)
-			break;
-		bh->b_pprev = &pb_resv_bh;
-		bh->b_next = pb_resv_bh;
-		pb_resv_bh = bh;
-		pb_resv_bh_cnt++;
-	}
-	return i;
-}
-
-/*
- *	_pagebuf_get_prealloc_bh
- *
- *	Get one buffer head from our pre-allocated pool.
- *	If pool is empty, sleep 'til one comes back in.
- *	Returns aforementioned buffer head.
- */
-STATIC struct buffer_head *
-_pagebuf_get_prealloc_bh(void)
-{
-	unsigned long		flags;
-	struct buffer_head	*bh;
-	DECLARE_WAITQUEUE	(wait, current);
-
-	spin_lock_irqsave(&pb_resv_bh_lock, flags);
-
-	if (pb_resv_bh_cnt < 1) {
-		add_wait_queue(&pb_resv_bh_wait, &wait);
-		do {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			spin_unlock_irqrestore(&pb_resv_bh_lock, flags);
-			blk_run_queues();
-			schedule();
-			spin_lock_irqsave(&pb_resv_bh_lock, flags);
-		} while (pb_resv_bh_cnt < 1);
-		__set_current_state(TASK_RUNNING);
-		remove_wait_queue(&pb_resv_bh_wait, &wait);
-	}
-
-	BUG_ON(pb_resv_bh_cnt < 1);
-	BUG_ON(!pb_resv_bh);
-
-	bh = pb_resv_bh;
-	pb_resv_bh = bh->b_next;
-	pb_resv_bh_cnt--;
-
-	spin_unlock_irqrestore(&pb_resv_bh_lock, flags);
-	return bh;
-}
-
-/*
- *	_pagebuf_free_bh
- *
- *	Take care of buffer heads that we're finished with.
- *	Call this instead of just kmem_cache_free(bh_cachep, bh)
- *	when you're done with a bh.
- *
- *	If our pre-allocated pool is full, just free the buffer head.
- *	Otherwise, put it back in the pool, and wake up anybody
- *	waiting for one.
- */
-STATIC inline void
-_pagebuf_free_bh(
-	struct buffer_head	*bh)
-{
-	unsigned long		flags;
-	int			free;
-
-	if (! (free = pb_resv_bh_cnt >= NR_RESERVED_BH)) {
-		spin_lock_irqsave(&pb_resv_bh_lock, flags);
-
-		if (! (free = pb_resv_bh_cnt >= NR_RESERVED_BH)) {
-			bh->b_pprev = &pb_resv_bh;
-			bh->b_next = pb_resv_bh;
-			pb_resv_bh = bh;
-			pb_resv_bh_cnt++;
-
-			if (waitqueue_active(&pb_resv_bh_wait)) {
-				wake_up(&pb_resv_bh_wait);
-			}
-		}
-
-		spin_unlock_irqrestore(&pb_resv_bh_lock, flags);
-	}
-	if (free) {
-		kmem_cache_free(bh_cachep, bh);
-	}
-}
-
-/*
- *	Finding and Reading Buffers
- */
-
-/*
- *	_pagebuf_find
- *
- *	Looks up, and creates if absent, a lockable buffer for
- *	a given range of an inode.  The buffer is returned
- *	locked.	 If other overlapping buffers exist, they are
- *	released before the new buffer is created and locked,
- *	which may imply that this call will block until those buffers
- *	are unlocked.  No I/O is implied by this call.
- */
-STATIC page_buf_t *
-_pagebuf_find(				/* find buffer for block	*/
-	pb_target_t		*target,/* target for block		*/
-	loff_t			ioff,	/* starting offset of range	*/
-	size_t			isize,	/* length of range		*/
-	page_buf_flags_t	flags,	/* PBF_TRYLOCK			*/
-	page_buf_t		*new_pb)/* newly allocated buffer	*/
-{
-	loff_t			range_base;
-	size_t			range_length;
-	int			hval;
-	pb_hash_t		*h;
-	struct list_head	*p;
-	page_buf_t		*pb;
-	int			not_locked;
-
-	range_base = (ioff << BBSHIFT);
-	range_length = (isize << BBSHIFT);
-
-	/* Ensure we never do IOs smaller than the sector size */
-	BUG_ON(range_length < (1 << target->pbr_sshift));
-
-	/* Ensure we never do IOs that are not sector aligned */
-	BUG_ON(range_base & (loff_t)target->pbr_smask);
-
-	hval = _bhash(target->pbr_bdev, range_base);
-	h = &pbhash[hval];
-
-	spin_lock(&h->pb_hash_lock);
-	list_for_each(p, &h->pb_hash) {
-		pb = list_entry(p, page_buf_t, pb_hash_list);
-
-		if ((target == pb->pb_target) &&
-		    (pb->pb_file_offset == range_base) &&
-		    (pb->pb_buffer_length == range_length)) {
-			if (pb->pb_flags & PBF_FREED)
-				break;
-			/* If we look at something bring it to the
-			 * front of the list for next time
-			 */
-			list_del(&pb->pb_hash_list);
-			list_add(&pb->pb_hash_list, &h->pb_hash);
-			goto found;
-		}
-	}
-
-	/* No match found */
-	if (new_pb) {
-		_pagebuf_initialize(new_pb, target, range_base,
-				range_length, flags | _PBF_LOCKABLE);
-		new_pb->pb_hash_index = hval;
-		h->pb_count++;
-		list_add(&new_pb->pb_hash_list, &h->pb_hash);
-	} else {
-		PB_STATS_INC(pb_miss_locked);
-	}
-
-	spin_unlock(&h->pb_hash_lock);
-	return (new_pb);
-
-found:
-	atomic_inc(&pb->pb_hold);
-	spin_unlock(&h->pb_hash_lock);
-
-	/* Attempt to get the semaphore without sleeping,
-	 * if this does not work then we need to drop the
-	 * spinlock and do a hard attempt on the semaphore.
-	 */
-	not_locked = down_trylock(&pb->pb_sema);
-	if (not_locked) {
-		if (!(flags & PBF_TRYLOCK)) {
-			/* wait for buffer ownership */
-			PB_TRACE(pb, "get_lock", 0);
-			pagebuf_lock(pb);
-			PB_STATS_INC(pb_get_locked_waited);
-		} else {
-			/* We asked for a trylock and failed, no need
-			 * to look at file offset and length here, we
-			 * know that this pagebuf at least overlaps our
-			 * pagebuf and is locked, therefore our buffer
-			 * either does not exist, or is this buffer
-			 */
-
-			pagebuf_rele(pb);
-			PB_STATS_INC(pb_busy_locked);
-			return (NULL);
-		}
-	} else {
-		/* trylock worked */
-		PB_SET_OWNER(pb);
-	}
-
-	if (pb->pb_flags & PBF_STALE)
-		pb->pb_flags &= PBF_MAPPABLE | \
-				PBF_MAPPED | \
-				_PBF_LOCKABLE | \
-				_PBF_ALL_PAGES_MAPPED | \
-				_PBF_ADDR_ALLOCATED | \
-				_PBF_MEM_ALLOCATED | \
-				_PBF_MEM_SLAB;
-	PB_TRACE(pb, "got_lock", 0);
-	PB_STATS_INC(pb_get_locked);
-	return (pb);
-}
-
-
-/*
- *	pagebuf_find
- *
- *	pagebuf_find returns a buffer matching the specified range of
- *	data for the specified target, if any of the relevant blocks
- *	are in memory.  The buffer may have unallocated holes, if
- *	some, but not all, of the blocks are in memory.  Even where
- *	pages are present in the buffer, not all of every page may be
- *	valid.
- */
-page_buf_t *
-pagebuf_find(				/* find buffer for block	*/
-					/* if the block is in memory	*/
-	pb_target_t		*target,/* target for block		*/
-	loff_t			ioff,	/* starting offset of range	*/
-	size_t			isize,	/* length of range		*/
-	page_buf_flags_t	flags)	/* PBF_TRYLOCK			*/
-{
-	return _pagebuf_find(target, ioff, isize, flags, NULL);
-}
-
-/*
- *	pagebuf_get
- *
- *	pagebuf_get assembles a buffer covering the specified range.
- *	Some or all of the blocks in the range may be valid.  Storage
- *	in memory for all portions of the buffer will be allocated,
- *	although backing storage may not be.  If PBF_READ is set in
- *	flags, pagebuf_iostart is called also.
- */
-page_buf_t *
-pagebuf_get(				/* allocate a buffer		*/
-	pb_target_t		*target,/* target for buffer		*/
-	loff_t			ioff,	/* starting offset of range	*/
-	size_t			isize,	/* length of range		*/
-	page_buf_flags_t	flags)	/* PBF_TRYLOCK			*/
-{
-	page_buf_t		*pb, *new_pb;
-	int			error;
-
-	new_pb = pagebuf_allocate(flags);
-	if (unlikely(!new_pb))
-		return (NULL);
-
-	pb = _pagebuf_find(target, ioff, isize, flags, new_pb);
-	if (pb != new_pb) {
-		pagebuf_deallocate(new_pb);
-		if (unlikely(!pb))
-			return (NULL);
-	}
-
-	PB_STATS_INC(pb_get);
-
-	/* fill in any missing pages */
-	error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags);
-	if (unlikely(error)) {
-		pagebuf_free(pb);
-		return (NULL);
-	}
-
-	/*
-	 * Always fill in the block number now, the mapped cases can do
-	 * their own overlay of this later.
-	 */
-	pb->pb_bn = ioff;
-	pb->pb_count_desired = pb->pb_buffer_length;
-
-	if (flags & PBF_READ) {
-		if (PBF_NOT_DONE(pb)) {
-			PB_TRACE(pb, "get_read", (unsigned long)flags);
-			PB_STATS_INC(pb_get_read);
-			pagebuf_iostart(pb, flags);
-		} else if (flags & PBF_ASYNC) {
-			PB_TRACE(pb, "get_read_async", (unsigned long)flags);
-			/*
-			 * Read ahead call which is already satisfied,
-			 * drop the buffer
-			 */
-			if (flags & (PBF_LOCK | PBF_TRYLOCK))
-				pagebuf_unlock(pb);
-			pagebuf_rele(pb);
-			return NULL;
-		} else {
-			PB_TRACE(pb, "get_read_done", (unsigned long)flags);
-			/* We do not want read in the flags */
-			pb->pb_flags &= ~PBF_READ;
-		}
-	} else {
-		PB_TRACE(pb, "get_write", (unsigned long)flags);
-	}
-	return (pb);
-}
-
-/*
- * Create a skeletal pagebuf (no pages associated with it).
- */
-page_buf_t *
-pagebuf_lookup(
-	struct pb_target	*target,
-	loff_t			ioff,
-	size_t			isize,
-	page_buf_flags_t	flags)
-{
-	page_buf_t		*pb;
-
-	flags |= _PBF_PRIVATE_BH | _PBF_LOCKABLE;
-	pb = pagebuf_allocate(flags);
-	if (pb) {
-		_pagebuf_initialize(pb, target, ioff, isize, flags);
-	}
-	return pb;
-}
-
-/*
- * If we are not low on memory then do the readahead in a deadlock
- * safe manner.
- */
-void
-pagebuf_readahead(
-	pb_target_t		*target,
-	loff_t			ioff,
-	size_t			isize,
-	page_buf_flags_t	flags)
-{
-	flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD);
-	pagebuf_get(target, ioff, isize, flags);
-}
-
-page_buf_t *
-pagebuf_get_empty(
-	size_t			len,
-	pb_target_t		*target)
-{
-	page_buf_t		*pb;
-
-	pb = pagebuf_allocate(_PBF_LOCKABLE);
-	if (pb)
-		_pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE);
-	return pb;
-}
-
-static inline struct page *
-mem_to_page(
-	void			*addr)
-{
-	if (((unsigned long)addr < VMALLOC_START) ||
-	    ((unsigned long)addr >= VMALLOC_END)) {
-		return virt_to_page(addr);
-	} else {
-		return vmalloc_to_page(addr);
-	}
-}
-
-int
-pagebuf_associate_memory(
-	page_buf_t		*pb,
-	void			*mem,
-	size_t			len)
-{
-	int			rval;
-	int			i = 0;
-	size_t			ptr;
-	size_t			end, end_cur;
-	off_t			offset;
-	int			page_count;
-
-	page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT;
-	offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK);
-	if (offset && (len > PAGE_CACHE_SIZE))
-		page_count++;
-
-	/* Free any previous set of page pointers */
-	if (pb->pb_pages && (pb->pb_pages != pb->pb_page_array)) {
-		kfree(pb->pb_pages);
-	}
-	pb->pb_pages = NULL;
-	pb->pb_addr = mem;
-
-	rval = _pagebuf_get_pages(pb, page_count, 0);
-	if (rval)
-		return rval;
-
-	pb->pb_offset = offset;
-	ptr = (size_t) mem & PAGE_CACHE_MASK;
-	end = PAGE_CACHE_ALIGN((size_t) mem + len);
-	end_cur = end;
-	/* set up first page */
-	pb->pb_pages[0] = mem_to_page(mem);
-
-	ptr += PAGE_CACHE_SIZE;
-	pb->pb_page_count = ++i;
-	while (ptr < end) {
-		pb->pb_pages[i] = mem_to_page((void *)ptr);
-		pb->pb_page_count = ++i;
-		ptr += PAGE_CACHE_SIZE;
-	}
-	pb->pb_locked = 0;
-
-	pb->pb_count_desired = pb->pb_buffer_length = len;
-	pb->pb_flags |= PBF_MAPPED | _PBF_PRIVATE_BH;
-
-	return 0;
-}
-
-page_buf_t *
-pagebuf_get_no_daddr(
-	size_t			len,
-	pb_target_t		*target)
-{
-	int			rval;
-	void			*rmem = NULL;
-	page_buf_flags_t	flags = _PBF_LOCKABLE | PBF_FORCEIO;
-	page_buf_t		*pb;
-	size_t			tlen = 0;
-
-	if (unlikely(len > 0x20000))
-		return NULL;
-
-	pb = pagebuf_allocate(flags);
-	if (!pb)
-		return NULL;
-
-	_pagebuf_initialize(pb, target, 0, len, flags);
-
-	do {
-		if (tlen == 0) {
-			tlen = len; /* first time */
-		} else {
-			kfree(rmem); /* free the mem from the previous try */
-			tlen <<= 1; /* double the size and try again */
-		}
-		if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) {
-			pagebuf_free(pb);
-			return NULL;
-		}
-	} while ((size_t)rmem != ((size_t)rmem & ~target->pbr_smask));
-
-	if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) {
-		kfree(rmem);
-		pagebuf_free(pb);
-		return NULL;
-	}
-	/* otherwise pagebuf_free just ignores it */
-	pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB);
-	PB_CLEAR_OWNER(pb);
-	up(&pb->pb_sema);	/* Return unlocked pagebuf */
-
-	PB_TRACE(pb, "no_daddr", rmem);
-
-	return pb;
-}
-
-
-/*
- *	pagebuf_hold
- *
- *	Increment reference count on buffer, to hold the buffer concurrently
- *	with another thread which may release (free) the buffer asynchronously.
- *
- *	Must hold the buffer already to call this function.
- */
-void
-pagebuf_hold(
-	page_buf_t		*pb)
-{
-	atomic_inc(&pb->pb_hold);
-	PB_TRACE(pb, "hold", 0);
-}
-
-/*
- *	pagebuf_free
- *
- *	pagebuf_free releases the specified buffer.  The modification
- *	state of any associated pages is left unchanged.
- */
-void
-pagebuf_free(
-	page_buf_t		*pb)
-{
-	if (pb->pb_flags & _PBF_LOCKABLE) {
-		pb_hash_t	*h = pb_hash(pb);
-
-		spin_lock(&h->pb_hash_lock);
-		_pagebuf_free_object(h, pb);
-	} else {
-		_pagebuf_free_object(NULL, pb);
-	}
-}
-
-/*
- *	pagebuf_rele
- *
- *	pagebuf_rele releases a hold on the specified buffer.  If the
- *	the hold count is 1, pagebuf_rele calls pagebuf_free.
- */
-void
-pagebuf_rele(
-	page_buf_t		*pb)
-{
-	pb_hash_t		*h;
-
-	PB_TRACE(pb, "rele", pb->pb_relse);
-	if (pb->pb_flags & _PBF_LOCKABLE) {
-		h = pb_hash(pb);
-		spin_lock(&h->pb_hash_lock);
-	} else {
-		h = NULL;
-	}
-
-	if (atomic_dec_and_test(&pb->pb_hold)) {
-		int		do_free = 1;
-
-		if (pb->pb_relse) {
-			atomic_inc(&pb->pb_hold);
-			if (h)
-				spin_unlock(&h->pb_hash_lock);
-			(*(pb->pb_relse)) (pb);
-			do_free = 0;
-		}
-		if (pb->pb_flags & PBF_DELWRI) {
-			pb->pb_flags |= PBF_ASYNC;
-			atomic_inc(&pb->pb_hold);
-			if (h && do_free)
-				spin_unlock(&h->pb_hash_lock);
-			pagebuf_delwri_queue(pb, 0);
-			do_free = 0;
-		} else if (pb->pb_flags & PBF_FS_MANAGED) {
-			if (h)
-				spin_unlock(&h->pb_hash_lock);
-			do_free = 0;
-		}
-
-		if (do_free) {
-			_pagebuf_free_object(h, pb);
-		}
-	} else if (h) {
-		spin_unlock(&h->pb_hash_lock);
-	}
-}
-
-
-/*
- *	Mutual exclusion on buffers.  Locking model:
- *
- *	Buffers associated with inodes for which buffer locking
- *	is not enabled are not protected by semaphores, and are
- *	assumed to be exclusively owned by the caller.  There is a
- *	spinlock in the buffer, used by the caller when concurrent
- *	access is possible.
- */
-
-/*
- *	pagebuf_cond_lock
- *
- *	pagebuf_cond_lock locks a buffer object, if it is not already locked.
- *	Note that this in no way
- *	locks the underlying pages, so it is only useful for synchronizing
- *	concurrent use of page buffer objects, not for synchronizing independent
- *	access to the underlying pages.
- */
-int
-pagebuf_cond_lock(			/* lock buffer, if not locked	*/
-					/* returns -EBUSY if locked)	*/
-	page_buf_t		*pb)
-{
-	int			locked;
-
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
-	locked = down_trylock(&pb->pb_sema) == 0;
-	if (locked) {
-		PB_SET_OWNER(pb);
-	}
-	PB_TRACE(pb, "cond_lock", (long)locked);
-	return(locked ? 0 : -EBUSY);
-}
-
-/*
- *	pagebuf_lock_value
- *
- *	Return lock value for a pagebuf
- */
-int
-pagebuf_lock_value(
-	page_buf_t		*pb)
-{
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
-	return(atomic_read(&pb->pb_sema.count));
-}
-
-/*
- *	pagebuf_lock
- *
- *	pagebuf_lock locks a buffer object.  Note that this in no way
- *	locks the underlying pages, so it is only useful for synchronizing
- *	concurrent use of page buffer objects, not for synchronizing independent
- *	access to the underlying pages.
- */
-int
-pagebuf_lock(
-	page_buf_t		*pb)
-{
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
-
-	PB_TRACE(pb, "lock", 0);
-	if (atomic_read(&pb->pb_io_remaining))
-		blk_run_queues();
-	down(&pb->pb_sema);
-	PB_SET_OWNER(pb);
-	PB_TRACE(pb, "locked", 0);
-	return 0;
-}
-
-/*
- *	pagebuf_unlock
- *
- *	pagebuf_unlock releases the lock on the buffer object created by
- *	pagebuf_lock or pagebuf_cond_lock (not any
- *	pinning of underlying pages created by pagebuf_pin).
- */
-void
-pagebuf_unlock(				/* unlock buffer		*/
-	page_buf_t		*pb)	/* buffer to unlock		*/
-{
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
-	PB_CLEAR_OWNER(pb);
-	up(&pb->pb_sema);
-	PB_TRACE(pb, "unlock", 0);
-}
-
-
-/*
- *	Pinning Buffer Storage in Memory
- */
-
-/*
- *	pagebuf_pin
- *
- *	pagebuf_pin locks all of the memory represented by a buffer in
- *	memory.  Multiple calls to pagebuf_pin and pagebuf_unpin, for
- *	the same or different buffers affecting a given page, will
- *	properly count the number of outstanding "pin" requests.  The
- *	buffer may be released after the pagebuf_pin and a different
- *	buffer used when calling pagebuf_unpin, if desired.
- *	pagebuf_pin should be used by the file system when it wants be
- *	assured that no attempt will be made to force the affected
- *	memory to disk.	 It does not assure that a given logical page
- *	will not be moved to a different physical page.
- */
-void
-pagebuf_pin(
-	page_buf_t		*pb)
-{
-	atomic_inc(&pb->pb_pin_count);
-	PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter);
-}
-
-/*
- *	pagebuf_unpin
- *
- *	pagebuf_unpin reverses the locking of memory performed by
- *	pagebuf_pin.  Note that both functions affected the logical
- *	pages associated with the buffer, not the buffer itself.
- */
-void
-pagebuf_unpin(
-	page_buf_t		*pb)
-{
-	if (atomic_dec_and_test(&pb->pb_pin_count)) {
-		wake_up_all(&pb->pb_waiters);
-	}
-	PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter);
-}
-
-int
-pagebuf_ispin(
-	page_buf_t		*pb)
-{
-	return atomic_read(&pb->pb_pin_count);
-}
-
-/*
- *	pagebuf_wait_unpin
- *
- *	pagebuf_wait_unpin waits until all of the memory associated
- *	with the buffer is not longer locked in memory.  It returns
- *	immediately if none of the affected pages are locked.
- */
-static inline void
-_pagebuf_wait_unpin(
-	page_buf_t		*pb)
-{
-	DECLARE_WAITQUEUE	(wait, current);
-
-	if (atomic_read(&pb->pb_pin_count) == 0)
-		return;
-
-	add_wait_queue(&pb->pb_waiters, &wait);
-	for (;;) {
-		current->state = TASK_UNINTERRUPTIBLE;
-		if (atomic_read(&pb->pb_pin_count) == 0)
-			break;
-		if (atomic_read(&pb->pb_io_remaining))
-			blk_run_queues();
-		schedule();
-	}
-	remove_wait_queue(&pb->pb_waiters, &wait);
-	current->state = TASK_RUNNING;
-}
-
-
-/*
- *	Buffer Utility Routines
- */
-
-/*
- *	pagebuf_iodone
- *
- *	pagebuf_iodone marks a buffer for which I/O is in progress
- *	done with respect to that I/O.	The pb_iodone routine, if
- *	present, will be called as a side-effect.
- */
-void
-pagebuf_iodone_sched(
-	void			*v)
-{
-	page_buf_t		*pb = (page_buf_t *)v;
-
-	if (pb->pb_iodone) {
-		(*(pb->pb_iodone)) (pb);
-		return;
-	}
-
-	if (pb->pb_flags & PBF_ASYNC) {
-		if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse)
-			pagebuf_unlock(pb);
-		pagebuf_rele(pb);
-	}
-}
-
-void
-pagebuf_iodone(
-	page_buf_t		*pb,
-	int			dataio,
-	int			schedule)
-{
-	pb->pb_flags &= ~(PBF_READ | PBF_WRITE);
-	if (pb->pb_error == 0) {
-		pb->pb_flags &= ~(PBF_PARTIAL | PBF_NONE);
-	}
-
-	PB_TRACE(pb, "iodone", pb->pb_iodone);
-
-	if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
-		if (schedule) {
-			int	daemon = CPU_TO_DAEMON(smp_processor_id());
-
-			INIT_TQUEUE(&pb->pb_iodone_sched,
-				pagebuf_iodone_sched, (void *)pb);
-			queue_task(&pb->pb_iodone_sched, dataio ?
-				&pagebuf_dataiodone_tq[daemon] :
-				&pagebuf_logiodone_tq[daemon]);
-			wake_up(dataio ?
-				&pagebuf_dataiodone_wait[daemon] :
-				&pagebuf_logiodone_wait[daemon]);
-		} else {
-			pagebuf_iodone_sched(pb);
-		}
-	} else {
-		up(&pb->pb_iodonesema);
-	}
-}
-
-/*
- *	pagebuf_ioerror
- *
- *	pagebuf_ioerror sets the error code for a buffer.
- */
-void
-pagebuf_ioerror(			/* mark/clear buffer error flag */
-	page_buf_t		*pb,	/* buffer to mark		*/
-	unsigned int		error)	/* error to store (0 if none)	*/
-{
-	pb->pb_error = error;
-	PB_TRACE(pb, "ioerror", (unsigned long)error);
-}
-
-/*
- *	pagebuf_iostart
- *
- *	pagebuf_iostart initiates I/O on a buffer, based on the flags supplied.
- *	If necessary, it will arrange for any disk space allocation required,
- *	and it will break up the request if the block mappings require it.
- *	The pb_iodone routine in the buffer supplied will only be called
- *	when all of the subsidiary I/O requests, if any, have been completed.
- *	pagebuf_iostart calls the pagebuf_ioinitiate routine or
- *	pagebuf_iorequest, if the former routine is not defined, to start
- *	the I/O on a given low-level request.
- */
-int
-pagebuf_iostart(			/* start I/O on a buffer	  */
-	page_buf_t		*pb,	/* buffer to start		  */
-	page_buf_flags_t	flags)	/* PBF_LOCK, PBF_ASYNC, PBF_READ, */
-					/* PBF_WRITE, PBF_DELWRI,	  */
-					/* PBF_SYNC, PBF_DONT_BLOCK	  */
-{
-	int			status = 0;
-
-	PB_TRACE(pb, "iostart", (unsigned long)flags);
-
-	if (flags & PBF_DELWRI) {
-		pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC);
-		pb->pb_flags |= flags &
-				(PBF_DELWRI | PBF_ASYNC | PBF_SYNC);
-		pagebuf_delwri_queue(pb, 1);
-		return status;
-	}
-
-	pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \
-			PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES);
-	pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \
-			PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES);
-
-	BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL);
-
-	/* For writes allow an alternate strategy routine to precede
-	 * the actual I/O request (which may not be issued at all in
-	 * a shutdown situation, for example).
-	 */
-	status = (flags & PBF_WRITE) ?
-		pagebuf_iostrategy(pb) : pagebuf_iorequest(pb);
-
-	/* Wait for I/O if we are not an async request.
-	 * Note: async I/O request completion will release the buffer,
-	 * and that can already be done by this point.  So using the
-	 * buffer pointer from here on, after async I/O, is invalid.
-	 */
-	if (!status && !(flags & PBF_ASYNC))
-		status = pagebuf_iowait(pb);
-
-	return status;
-}
-
-
-/*
- * Helper routines for pagebuf_iorequest (pagebuf I/O completion)
- */
-
-STATIC __inline__ int
-_pagebuf_iolocked(
-	page_buf_t		*pb)
-{
-	ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE));
-	if (pb->pb_target->pbr_bsize < PAGE_CACHE_SIZE)
-		return pb->pb_locked;
-	if (pb->pb_flags & PBF_READ)
-		return pb->pb_locked;
-	return (!(pb->pb_flags & _PBF_LOCKABLE));
-}
-
-STATIC void
-_pagebuf_iodone(
-	page_buf_t		*pb,
-	int			schedule)
-{
-	int			i;
-
-	if (atomic_dec_and_test(&pb->pb_io_remaining) != 1)
-		return;
-
-	if (_pagebuf_iolocked(pb))
-		for (i = 0; i < pb->pb_page_count; i++)
-			unlock_page(pb->pb_pages[i]);
-	pb->pb_locked = 0;
-	pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), schedule);
-}
-
-STATIC void
-_end_io_pagebuf(
-	struct buffer_head	*bh,
-	int			uptodate,
-	int			fullpage)
-{
-	struct page		*page = bh->b_page;
-	page_buf_t		*pb = (page_buf_t *)bh->b_private;
-
-	mark_buffer_uptodate(bh, uptodate);
-	put_bh(bh);
-
-	if (!uptodate) {
-		SetPageError(page);
-		pb->pb_error = EIO;
-	}
-
-	if (fullpage) {
-		unlock_buffer(bh);
-		_pagebuf_free_bh(bh);
-		if (!PageError(page))
-			SetPageUptodate(page);
-	} else {
-		static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
-		struct buffer_head *bp;
-		unsigned long flags;
-
-		ASSERT(PageLocked(page));
-		spin_lock_irqsave(&page_uptodate_lock, flags);
-		clear_buffer_async(bh);
-		unlock_buffer(bh);
-		for (bp = bh->b_this_page; bp != bh; bp = bp->b_this_page) {
-			if (buffer_locked(bp)) {
-				if (buffer_async(bp))
-					break;
-			} else if (!buffer_uptodate(bp))
-				break;
-		}
-		spin_unlock_irqrestore(&page_uptodate_lock, flags);
-		if (bp == bh && !PageError(page))
-			SetPageUptodate(page);
-	}
-
-	_pagebuf_iodone(pb, 1);
-}
-
-STATIC void
-_pagebuf_end_io_complete_pages(
-	struct buffer_head	*bh,
-	int			uptodate)
-{
-	_end_io_pagebuf(bh, uptodate, 1);
-}
-
-STATIC void
-_pagebuf_end_io_partial_pages(
-	struct buffer_head	*bh,
-	int			uptodate)
-{
-	_end_io_pagebuf(bh, uptodate, 0);
-}
-
-
-/*
- * Initiate I/O on part of a page we are interested in
- */
-STATIC int
-_pagebuf_page_io(
-	struct page		*page,	/* Page structure we are dealing with */
-	pb_target_t		*pbr,	/* device parameters (bsz, ssz, dev) */
-	page_buf_t		*pb,	/* pagebuf holding it, can be NULL */
-	page_buf_daddr_t	bn,	/* starting block number */
-	size_t			pg_offset,	/* starting offset in page */
-	size_t			pg_length,	/* count of data to process */
-	int			rw,	/* read/write operation */
-	int			flush)
-{
-	size_t			sector;
-	size_t			blk_length = 0;
-	struct buffer_head	*bh, *head, *bufferlist[MAX_BUF_PER_PAGE];
-	int			sector_shift = pbr->pbr_sshift;
-	int			i = 0, cnt = 0;
-	int			public_bh = 0;
-	int			multi_ok;
-
-	if ((pbr->pbr_bsize < PAGE_CACHE_SIZE) &&
-	    !(pb->pb_flags & _PBF_PRIVATE_BH)) {
-		int		cache_ok;
-
-		cache_ok = !((pb->pb_flags & PBF_FORCEIO) || (rw == WRITE));
-		public_bh = multi_ok = 1;
-		sector = 1 << sector_shift;
-
-		ASSERT(PageLocked(page));
-		if (!page_has_buffers(page))
-			create_empty_buffers(page, pbr->pbr_kdev, sector);
-
-		i = sector >> BBSHIFT;
-		bn -= (pg_offset >> BBSHIFT);
-
-		/* Find buffer_heads belonging to just this pagebuf */
-		bh = head = page_buffers(page);
-		do {
-			if (buffer_uptodate(bh) && cache_ok)
-				continue;
-			if (blk_length < pg_offset)
-				continue;
-			if (blk_length >= pg_offset + pg_length)
-				break;
-
-			lock_buffer(bh);
-			get_bh(bh);
-			bh->b_size = sector;
-			bh->b_blocknr = bn;
-			bufferlist[cnt++] = bh;
-
-		} while ((bn += i),
-			 (blk_length += sector),
-			  (bh = bh->b_this_page) != head);
-
-		goto request;
-	}
-
-	/* Calculate the block offsets and length we will be using */
-	if (pg_offset) {
-		size_t		block_offset;
-
-		block_offset = pg_offset >> sector_shift;
-		block_offset = pg_offset - (block_offset << sector_shift);
-		blk_length = (pg_length + block_offset + pbr->pbr_smask) >>
-								sector_shift;
-	} else {
-		blk_length = (pg_length + pbr->pbr_smask) >> sector_shift;
-	}
-
-	/* This will attempt to make a request bigger than the sector
-	 * size if we are well aligned.
-	 */
-	switch (pb->pb_target->pbr_flags) {
-	case 0:
-		sector = blk_length << sector_shift;
-		blk_length = 1;
-		break;
-	case PBR_ALIGNED_ONLY:
-		if ((pg_offset == 0) && (pg_length == PAGE_CACHE_SIZE) &&
-		    (((unsigned int) bn) & BN_ALIGN_MASK) == 0) {
-			sector = blk_length << sector_shift;
-			blk_length = 1;
-			break;
-		}
-	case PBR_SECTOR_ONLY:
-		/* Fallthrough, same as default */
-	default:
-		sector = 1 << sector_shift;
-	}
-
-	/* If we are doing I/O larger than the bh->b_size field then
-	 * we need to split this request up.
-	 */
-	while (sector > ((1ULL << NBBY * sizeof(bh->b_size)) - 1)) {
-		sector >>= 1;
-		blk_length++;
-	}
-
-	multi_ok = (blk_length != 1);
-	i = sector >> BBSHIFT;
-
-	for (; blk_length > 0; bn += i, blk_length--, pg_offset += sector) {
-		bh = kmem_cache_alloc(bh_cachep, SLAB_NOFS);
-		if (!bh)
-			bh = _pagebuf_get_prealloc_bh();
-		memset(bh, 0, sizeof(*bh));
-		bh->b_blocknr = bn;
-		bh->b_size = sector;
-		bh->b_dev = pbr->pbr_kdev;
-		set_buffer_locked(bh);
-		set_bh_page(bh, page, pg_offset);
-		init_waitqueue_head(&bh->b_wait);
-		atomic_set(&bh->b_count, 1);
-		bufferlist[cnt++] = bh;
-	}
-
-request:
-	if (cnt) {
-		void	(*callback)(struct buffer_head *, int);
-
-		callback = (multi_ok && public_bh) ?
-				_pagebuf_end_io_partial_pages :
-				_pagebuf_end_io_complete_pages;
-
-		/* Account for additional buffers in progress */
-		atomic_add(cnt, &pb->pb_io_remaining);
-
-#ifdef RQ_WRITE_ORDERED
-		if (flush)
-			set_bit(BH_Ordered_Flush, &bufferlist[cnt-1]->b_state);
-#endif
-
-		for (i = 0; i < cnt; i++) {
-			bh = bufferlist[i];
-			init_buffer(bh, callback, pb);
-			bh->b_rdev = bh->b_dev;
-			bh->b_rsector = bh->b_blocknr;
-			set_buffer_mapped(bh);
-			set_buffer_async(bh);
-			set_buffer_req(bh);
-			if (rw == WRITE)
-				set_buffer_uptodate(bh);
-			generic_make_request(rw, bh);
-		}
-		return 0;
-	}
-
-	/*
-	 * We have no I/O to submit, let the caller know that
-	 * we have skipped over this page entirely.
-	 */
-	return 1;
-}
-
-STATIC void
-_pagebuf_page_apply(
-	page_buf_t		*pb,
-	loff_t			offset,
-	struct page		*page,
-	size_t			pg_offset,
-	size_t			pg_length,
-	int			last)
-{
-	page_buf_daddr_t	bn = pb->pb_bn;
-	pb_target_t		*pbr = pb->pb_target;
-	loff_t			pb_offset;
-	int			status, locking;
-
-	ASSERT(page);
-	ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE));
-
-	if ((pbr->pbr_bsize == PAGE_CACHE_SIZE) &&
-	    (pb->pb_buffer_length < PAGE_CACHE_SIZE) &&
-	    (pb->pb_flags & PBF_READ) && pb->pb_locked) {
-		bn -= (pb->pb_offset >> BBSHIFT);
-		pg_offset = 0;
-		pg_length = PAGE_CACHE_SIZE;
-	} else {
-		pb_offset = offset - pb->pb_file_offset;
-		if (pb_offset) {
-			bn += (pb_offset + BBMASK) >> BBSHIFT;
-		}
-	}
-
-	locking = _pagebuf_iolocked(pb);
-	if (pb->pb_flags & PBF_WRITE) {
-		if (locking && !pb->pb_locked)
-			lock_page(page);
-		status = _pagebuf_page_io(page, pbr, pb, bn,
-				pg_offset, pg_length, WRITE,
-				last && (pb->pb_flags & PBF_FLUSH));
-	} else {
-		status = _pagebuf_page_io(page, pbr, pb, bn,
-				pg_offset, pg_length, READ, 0);
-	}
-	if (status && locking && !(pb->pb_target->pbr_bsize < PAGE_CACHE_SIZE))
-		unlock_page(page);
-}
-
-/*
- *	pagebuf_iorequest
- *
- *	pagebuf_iorequest is the core I/O request routine.
- *	It assumes that the buffer is well-formed and
- *	mapped and ready for physical I/O, unlike
- *	pagebuf_iostart() and pagebuf_iophysio().  Those
- *	routines call the pagebuf_ioinitiate routine to start I/O,
- *	if it is present, or else call pagebuf_iorequest()
- *	directly if the pagebuf_ioinitiate routine is not present.
- *
- *	This function will be responsible for ensuring access to the
- *	pages is restricted whilst I/O is in progress - for locking
- *	pagebufs the pagebuf lock is the mediator, for non-locking
- *	pagebufs the pages will be locked. In the locking case we
- *	need to use the pagebuf lock as multiple meta-data buffers
- *	will reference the same page.
- */
-int
-pagebuf_iorequest(			/* start real I/O		*/
-	page_buf_t		*pb)	/* buffer to convey to device	*/
-{
-	PB_TRACE(pb, "iorequest", 0);
-
-	if (pb->pb_flags & PBF_DELWRI) {
-		pagebuf_delwri_queue(pb, 1);
-		return 0;
-	}
-
-	if (pb->pb_flags & PBF_WRITE) {
-		_pagebuf_wait_unpin(pb);
-	}
-
-	pagebuf_hold(pb);
-
-	/* Set the count to 1 initially, this will stop an I/O
-	 * completion callout which happens before we have started
-	 * all the I/O from calling pagebuf_iodone too early.
-	 */
-	atomic_set(&pb->pb_io_remaining, 1);
-	_pagebuf_ioapply(pb);
-	_pagebuf_iodone(pb, 0);
-
-	pagebuf_rele(pb);
-	return 0;
-}
-
-/*
- *	pagebuf_iowait
- *
- *	pagebuf_iowait waits for I/O to complete on the buffer supplied.
- *	It returns immediately if no I/O is pending.  In any case, it returns
- *	the error code, if any, or 0 if there is no error.
- */
-int
-pagebuf_iowait(
-	page_buf_t		*pb)
-{
-	PB_TRACE(pb, "iowait", 0);
-	if (atomic_read(&pb->pb_io_remaining))
-		blk_run_queues();
-	if ((pb->pb_flags & PBF_FS_DATAIOD))
-		pagebuf_runall_queues(pagebuf_dataiodone_tq);
-	down(&pb->pb_iodonesema);
-	PB_TRACE(pb, "iowaited", (long)pb->pb_error);
-	return pb->pb_error;
-}
-
-STATIC void *
-pagebuf_mapout_locked(
-	page_buf_t		*pb)
-{
-	void			*old_addr = NULL;
-
-	if (pb->pb_flags & PBF_MAPPED) {
-		if (pb->pb_flags & _PBF_ADDR_ALLOCATED)
-			old_addr = pb->pb_addr - pb->pb_offset;
-		pb->pb_addr = NULL;
-		pb->pb_flags &= ~(PBF_MAPPED | _PBF_ADDR_ALLOCATED);
-	}
-
-	return old_addr;	/* Caller must free the address space,
-				 * we are under a spin lock, probably
-				 * not safe to do vfree here
-				 */
-}
-
-caddr_t
-pagebuf_offset(
-	page_buf_t		*pb,
-	size_t			offset)
-{
-	struct page		*page;
-
-	offset += pb->pb_offset;
-
-	page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT];
-	return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1));
-}
-
-/*
- *	pagebuf_iomove
- *
- *	Move data into or out of a buffer.
- */
-void
-pagebuf_iomove(
-	page_buf_t		*pb,	/* buffer to process		*/
-	size_t			boff,	/* starting buffer offset	*/
-	size_t			bsize,	/* length to copy		*/
-	caddr_t			data,	/* data address			*/
-	page_buf_rw_t		mode)	/* read/write flag		*/
-{
-	size_t			bend, cpoff, csize;
-	struct page		*page;
-
-	bend = boff + bsize;
-	while (boff < bend) {
-		page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)];
-		cpoff = page_buf_poff(boff + pb->pb_offset);
-		csize = min_t(size_t,
-			      PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff);
-
-		ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
-
-		switch (mode) {
-		case PBRW_ZERO:
-			memset(page_address(page) + cpoff, 0, csize);
-			break;
-		case PBRW_READ:
-			memcpy(data, page_address(page) + cpoff, csize);
-			break;
-		case PBRW_WRITE:
-			memcpy(page_address(page) + cpoff, data, csize);
-		}
-
-		boff += csize;
-		data += csize;
-	}
-}
-
-/*
- *	_pagebuf_ioapply
- *
- *	Applies _pagebuf_page_apply to each page of the page_buf_t.
- */
-STATIC void
-_pagebuf_ioapply(			/* apply function to pages	*/
-	page_buf_t		*pb)	/* buffer to examine		*/
-{
-	int			index;
-	loff_t			buffer_offset = pb->pb_file_offset;
-	size_t			buffer_len = pb->pb_count_desired;
-	size_t			page_offset, len;
-	size_t			cur_offset, cur_len;
-
-	cur_offset = pb->pb_offset;
-	cur_len = buffer_len;
-
-	if (!pb->pb_locked &&
-	    (pb->pb_target->pbr_bsize < PAGE_CACHE_SIZE)) {
-		for (index = 0; index < pb->pb_page_count; index++)
-			lock_page(pb->pb_pages[index]);
-		pb->pb_locked = 1;
-	}
-
-	for (index = 0; index < pb->pb_page_count; index++) {
-		if (cur_len == 0)
-			break;
-		if (cur_offset >= PAGE_CACHE_SIZE) {
-			cur_offset -= PAGE_CACHE_SIZE;
-			continue;
-		}
-
-		page_offset = cur_offset;
-		cur_offset = 0;
-
-		len = PAGE_CACHE_SIZE - page_offset;
-		if (len > cur_len)
-			len = cur_len;
-		cur_len -= len;
-
-		_pagebuf_page_apply(pb, buffer_offset,
-				pb->pb_pages[index], page_offset, len,
-				index + 1 == pb->pb_page_count);
-		buffer_offset += len;
-		buffer_len -= len;
-	}
-
-	/*
-	 * Run the block device task queue here, while we have
-	 * a hold on the pagebuf (important to have that hold).
-	 */
-	if (pb->pb_flags & PBF_RUN_QUEUES) {
-		pb->pb_flags &= ~PBF_RUN_QUEUES;
-		if (atomic_read(&pb->pb_io_remaining) > 1)
-			blk_run_queues();
-	}
-}
-
-
-/*
- * Pagebuf delayed write buffer handling
- */
-
-STATIC int pbd_active = 1;
-STATIC LIST_HEAD(pbd_delwrite_queue);
-STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED;
-
-STATIC void
-pagebuf_delwri_queue(
-	page_buf_t		*pb,
-	int			unlock)
-{
-	PB_TRACE(pb, "delwri_q", (long)unlock);
-	spin_lock(&pbd_delwrite_lock);
-	/* If already in the queue, dequeue and place at tail */
-	if (!list_empty(&pb->pb_list)) {
-		if (unlock) {
-			atomic_dec(&pb->pb_hold);
-		}
-		list_del(&pb->pb_list);
-	}
-
-	list_add_tail(&pb->pb_list, &pbd_delwrite_queue);
-	pb->pb_flushtime = jiffies + pb_params.age_buffer.val;
-	spin_unlock(&pbd_delwrite_lock);
-
-	if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) {
-		pagebuf_unlock(pb);
-	}
-}
-
-void
-pagebuf_delwri_dequeue(
-	page_buf_t		*pb)
-{
-	PB_TRACE(pb, "delwri_uq", 0);
-	spin_lock(&pbd_delwrite_lock);
-	list_del_init(&pb->pb_list);
-	pb->pb_flags &= ~PBF_DELWRI;
-	spin_unlock(&pbd_delwrite_lock);
-}
-
-
-/*
- * The pagebuf iodone daemons
- */
-
-STATIC int
-pagebuf_iodone_daemon(
-	void			*__bind_cpu,
-	const char		*name,
-	int			pagebuf_daemons[],
-	struct list_head	pagebuf_iodone_tq[],
-	wait_queue_head_t	pagebuf_iodone_wait[])
-{
-	int			bind_cpu, cpu;
-	DECLARE_WAITQUEUE	(wait, current);
-
-	bind_cpu = (int) (long)__bind_cpu;
-	cpu = CPU_TO_DAEMON(cpu_logical_map(bind_cpu));
-
-	/*  Set up the thread  */
-	daemonize();
-
-	/* Avoid signals */
-	spin_lock_irq(&current->sigmask_lock);
-	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
-
-	/* Migrate to the right CPU */
-	migrate_to_cpu(cpu);
-#ifdef __HAVE_NEW_SCHEDULER
-	if (smp_processor_id() != cpu)
-		BUG();
-#else
-	while (smp_processor_id() != cpu)
-		schedule();
-#endif
-
-	sprintf(current->comm, "%s/%d", name, bind_cpu);
-	INIT_LIST_HEAD(&pagebuf_iodone_tq[cpu]);
-	init_waitqueue_head(&pagebuf_iodone_wait[cpu]);
-	__set_current_state(TASK_INTERRUPTIBLE);
-	mb();
-
-	pagebuf_daemons[cpu] = 1;
-
-	for (;;) {
-		add_wait_queue(&pagebuf_iodone_wait[cpu], &wait);
-
-		if (TQ_ACTIVE(pagebuf_iodone_tq[cpu]))
-			__set_task_state(current, TASK_RUNNING);
-		schedule();
-		remove_wait_queue(&pagebuf_iodone_wait[cpu], &wait);
-		run_task_queue(&pagebuf_iodone_tq[cpu]);
-		if (pagebuf_daemons[cpu] == 0)
-			break;
-		__set_current_state(TASK_INTERRUPTIBLE);
-	}
-
-	pagebuf_daemons[cpu] = -1;
-	wake_up_interruptible(&pagebuf_iodone_wait[cpu]);
-	return 0;
-}
-
-STATIC void
-pagebuf_runall_queues(
-	struct list_head	pagebuf_iodone_tq[])
-{
-	int	pcpu, cpu;
-
-	for (cpu = 0; cpu < min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
-		pcpu = CPU_TO_DAEMON(cpu_logical_map(cpu));
-
-		run_task_queue(&pagebuf_iodone_tq[pcpu]);
-	}
-}
-
-STATIC int
-pagebuf_logiodone_daemon(
-	void			*__bind_cpu)
-{
-	return pagebuf_iodone_daemon(__bind_cpu, "xfslogd", pb_logio_daemons,
-			pagebuf_logiodone_tq, pagebuf_logiodone_wait);
-}
-
-STATIC int
-pagebuf_dataiodone_daemon(
-	void			*__bind_cpu)
-{
-	return pagebuf_iodone_daemon(__bind_cpu, "xfsdatad", pb_dataio_daemons,
-			pagebuf_dataiodone_tq, pagebuf_dataiodone_wait);
-}
-
-
-/* Defines for pagebuf daemon */
-DECLARE_WAIT_QUEUE_HEAD(pbd_waitq);
-STATIC int force_flush;
-
-STATIC void
-pagebuf_daemon_wakeup(
-	int			flag)
-{
-	force_flush = flag;
-	if (waitqueue_active(&pbd_waitq)) {
-		wake_up_interruptible(&pbd_waitq);
-	}
-}
-
-typedef void (*timeout_fn)(unsigned long);
-
-STATIC int
-pagebuf_daemon(
-	void			*data)
-{
-	int			count;
-	page_buf_t		*pb;
-	struct list_head	*curr, *next, tmp;
-	struct timer_list	pb_daemon_timer =
-		{ {NULL, NULL}, 0, 0, (timeout_fn)pagebuf_daemon_wakeup };
-
-	/*  Set up the thread  */
-	daemonize();
-
-	/* Avoid signals */
-	spin_lock_irq(&current->sigmask_lock);
-	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
-
-	strcpy(current->comm, "pagebufd");
-	current->flags |= PF_MEMALLOC;
-
-	INIT_LIST_HEAD(&tmp);
-	do {
-		if (pbd_active == 1) {
-			mod_timer(&pb_daemon_timer,
-				  jiffies + pb_params.flush_interval.val);
-			interruptible_sleep_on(&pbd_waitq);
-		}
-
-		if (pbd_active == 0) {
-			del_timer_sync(&pb_daemon_timer);
-		}
-
-		spin_lock(&pbd_delwrite_lock);
-
-		count = 0;
-		list_for_each_safe(curr, next, &pbd_delwrite_queue) {
-			pb = list_entry(curr, page_buf_t, pb_list);
-
-			PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
-
-			if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) &&
-			    (((pb->pb_flags & _PBF_LOCKABLE) == 0) ||
-			     !pagebuf_cond_lock(pb))) {
-
-				if (!force_flush &&
-				    time_before(jiffies, pb->pb_flushtime)) {
-					pagebuf_unlock(pb);
-					break;
-				}
-
-				pb->pb_flags &= ~PBF_DELWRI;
-				pb->pb_flags |= PBF_WRITE;
-
-				list_del(&pb->pb_list);
-				list_add(&pb->pb_list, &tmp);
-
-				count++;
-			}
-		}
-
-		spin_unlock(&pbd_delwrite_lock);
-		while (!list_empty(&tmp)) {
-			pb = list_entry(tmp.next, page_buf_t, pb_list);
-			list_del_init(&pb->pb_list);
-
-			pagebuf_iostrategy(pb);
-		}
-
-		if (as_list_len > 0)
-			purge_addresses();
-		if (count)
-			blk_run_queues();
-
-		force_flush = 0;
-	} while (pbd_active == 1);
-
-	pbd_active = -1;
-	wake_up_interruptible(&pbd_waitq);
-
-	return 0;
-}
-
-void
-pagebuf_delwri_flush(
-	pb_target_t		*target,
-	u_long			flags,
-	int			*pinptr)
-{
-	page_buf_t		*pb;
-	struct list_head	*curr, *next, tmp;
-	int			pincount = 0;
-	int			flush_cnt = 0;
-
-	pagebuf_runall_queues(pagebuf_dataiodone_tq);
-	pagebuf_runall_queues(pagebuf_logiodone_tq);
-
-	spin_lock(&pbd_delwrite_lock);
-	INIT_LIST_HEAD(&tmp);
-
-	list_for_each_safe(curr, next, &pbd_delwrite_queue) {
-		pb = list_entry(curr, page_buf_t, pb_list);
-
-		/*
-		 * Skip other targets, markers and in progress buffers
-		 */
-
-		if ((pb->pb_flags == 0) || (pb->pb_target != target) ||
-		    !(pb->pb_flags & PBF_DELWRI)) {
-			continue;
-		}
-
-		PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb));
-		if (pagebuf_ispin(pb)) {
-			pincount++;
-			continue;
-		}
-
-		pb->pb_flags &= ~PBF_DELWRI;
-		pb->pb_flags |= PBF_WRITE;
-		list_move(&pb->pb_list, &tmp);
-
-	}
-	
-	/* ok found all the items that can be worked on 
-	 * drop the lock and process the private list */
-	spin_unlock(&pbd_delwrite_lock);
-	
-	list_for_each_safe(curr, next, &tmp) {
-		pb = list_entry(curr, page_buf_t, pb_list);
-		
-		if (flags & PBDF_WAIT)
-			pb->pb_flags &= ~PBF_ASYNC;
-		else
-			list_del_init(curr);
-
-		pagebuf_lock(pb);
-		pagebuf_iostrategy(pb);
-
-		if (++flush_cnt > 32) {
-			blk_run_queues();
-			flush_cnt = 0;
-		}
-	}
-
-	blk_run_queues();
-
-	/* must run list the second time even if PBDF_WAIT isn't
-	 * to reset all the pb_list pointers 
-	 */
-	while (!list_empty(&tmp)) {
-		pb = list_entry(tmp.next, page_buf_t, pb_list);
-
-		list_del_init(&pb->pb_list);
-		
-		pagebuf_iowait(pb);
-		if (!pb->pb_relse)
-			pagebuf_unlock(pb);
-		pagebuf_rele(pb);
-	}
-
-	if (pinptr)
-		*pinptr = pincount;
-}
-
-STATIC int
-pagebuf_daemon_start(void)
-{
-	int		cpu, pcpu;
-
-	kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES|CLONE_VM);
-
-	for (cpu = 0; cpu < min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
-		pcpu = CPU_TO_DAEMON(cpu_logical_map(cpu));
-
-		if (kernel_thread(pagebuf_logiodone_daemon,
-				(void *)(long) cpu,
-				CLONE_FS|CLONE_FILES|CLONE_VM) < 0) {
-			printk("pagebuf_logiodone daemon failed to start\n");
-		} else {
-			while (!pb_logio_daemons[pcpu])
-				yield();
-		}
-	}
-	for (cpu = 0; cpu < min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
-		pcpu = CPU_TO_DAEMON(cpu_logical_map(cpu));
-
-		if (kernel_thread(pagebuf_dataiodone_daemon,
-				(void *)(long) cpu,
-				CLONE_FS|CLONE_FILES|CLONE_VM) < 0) {
-			printk("pagebuf_dataiodone daemon failed to start\n");
-		} else {
-			while (!pb_dataio_daemons[pcpu])
-				yield();
-		}
-	}
-	return 0;
-}
-
-/*
- * pagebuf_daemon_stop
- *
- * Note: do not mark as __exit, it is called from pagebuf_terminate.
- */
-STATIC void
-pagebuf_daemon_stop(void)
-{
-	int		cpu, pcpu;
-
-	pbd_active = 0;
-
-	wake_up_interruptible(&pbd_waitq);
-	wait_event_interruptible(pbd_waitq, pbd_active);
-
-	for (pcpu = 0; pcpu < min(smp_num_cpus, MAX_IO_DAEMONS); pcpu++) {
-		cpu = CPU_TO_DAEMON(cpu_logical_map(pcpu));
-
-		pb_logio_daemons[cpu] = 0;
-		wake_up(&pagebuf_logiodone_wait[cpu]);
-		wait_event_interruptible(pagebuf_logiodone_wait[cpu],
-				pb_logio_daemons[cpu] == -1);
-
-		pb_dataio_daemons[cpu] = 0;
-		wake_up(&pagebuf_dataiodone_wait[cpu]);
-		wait_event_interruptible(pagebuf_dataiodone_wait[cpu],
-				pb_dataio_daemons[cpu] == -1);
-	}
-}
-
-
-/*
- * Pagebuf sysctl interface
- */
-
-STATIC int
-pb_stats_clear_handler(
-	ctl_table		*ctl,
-	int			write,
-	struct file		*filp,
-	void			*buffer,
-	size_t			*lenp)
-{
-	int			ret;
-	int			*valp = ctl->data;
-
-	ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp);
-
-	if (!ret && write && *valp) {
-		printk("XFS Clearing pbstats\n");
-		memset(&pbstats, 0, sizeof(pbstats));
-		pb_params.stats_clear.val = 0;
-	}
-
-	return ret;
-}
-
-STATIC struct ctl_table_header *pagebuf_table_header;
-
-STATIC ctl_table pagebuf_table[] = {
-	{PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&pb_params.flush_interval.min, &pb_params.flush_interval.max},
-
-	{PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL, 
-	&pb_params.age_buffer.min, &pb_params.age_buffer.max},
-
-	{PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val,
-	sizeof(int), 0644, NULL, &pb_stats_clear_handler,
-	&sysctl_intvec, NULL, 
-	&pb_params.stats_clear.min, &pb_params.stats_clear.max},
-
-#ifdef PAGEBUF_TRACE
-	{PB_DEBUG, "debug", &pb_params.debug.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL, 
-	&pb_params.debug.min, &pb_params.debug.max},
-#endif
-	{0}
-};
-
-STATIC ctl_table pagebuf_dir_table[] = {
-	{VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table},
-	{0}
-};
-
-STATIC ctl_table pagebuf_root_table[] = {
-	{CTL_VM, "vm",  NULL, 0, 0555, pagebuf_dir_table},
-	{0}
-};
-
-#ifdef CONFIG_PROC_FS
-STATIC int
-pagebuf_readstats(
-	char			*buffer,
-	char			**start,
-	off_t			offset,
-	int			count,
-	int			*eof,
-	void			*data)
-{
-	int			i, len;
-
-	len = 0;
-	len += sprintf(buffer + len, "pagebuf");
-	for (i = 0; i < sizeof(pbstats) / sizeof(u_int32_t); i++) {
-		len += sprintf(buffer + len, " %u",
-			*(((u_int32_t*)&pbstats) + i));
-	}
-	buffer[len++] = '\n';
-
-	if (offset >= len) {
-		*start = buffer;
-		*eof = 1;
-		return 0;
-	}
-	*start = buffer + offset;
-	if ((len -= offset) > count)
-		return count;
-	*eof = 1;
-
-	return len;
-}
-#endif  /* CONFIG_PROC_FS */
-
-STATIC int
-pagebuf_shaker(int number, unsigned int mask)
-{
-	pagebuf_daemon_wakeup(1);
-	return 0;
-}
-
-
-/*
- *	Initialization and Termination
- */
-
-int __init
-pagebuf_init(void)
-{
-	int			i;
-
-	pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1);
-
-#ifdef CONFIG_PROC_FS
-	if (proc_mkdir("fs/pagebuf", 0))
-		create_proc_read_entry(
-			"fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL);
-#endif
-
-	pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0,
-			SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (pagebuf_cache == NULL) {
-		printk("pagebuf: couldn't init pagebuf cache\n");
-		pagebuf_terminate();
-		return -ENOMEM;
-	}
-
-	if (_pagebuf_prealloc_bh(NR_RESERVED_BH) < NR_RESERVED_BH) {
-		printk("pagebuf: couldn't pre-allocate %d buffer heads\n",
-			NR_RESERVED_BH);
-		pagebuf_terminate();
-		return -ENOMEM;
-	}
-
-	init_waitqueue_head(&pb_resv_bh_wait);
-
-	for (i = 0; i < NHASH; i++) {
-		spin_lock_init(&pbhash[i].pb_hash_lock);
-		INIT_LIST_HEAD(&pbhash[i].pb_hash);
-	}
-
-#ifdef PAGEBUF_TRACE
-	pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
-#endif
-
-	pagebuf_daemon_start();
-	kmem_shake_register(pagebuf_shaker);
-	return 0;
-}
-
-/*
- *	pagebuf_terminate.
- *
- *	Note: do not mark as __exit, this is also called from the __init code.
- */
-void
-pagebuf_terminate(void)
-{
-	pagebuf_daemon_stop();
-
-	kmem_cache_destroy(pagebuf_cache);
-	kmem_shake_deregister(pagebuf_shaker);
-
-	unregister_sysctl_table(pagebuf_table_header);
-#ifdef  CONFIG_PROC_FS
-	remove_proc_entry("fs/pagebuf/stat", NULL);
-	remove_proc_entry("fs/pagebuf", NULL);
-#endif
-}
-
-
-/*
- *	Module management (for kernel debugger module)
- */
-EXPORT_SYMBOL(pagebuf_offset);
-#ifdef DEBUG
-EXPORT_SYMBOL(pbd_delwrite_queue);
-#endif
diff -urN linux-2.4.25-pre8/fs/xfs/pagebuf/page_buf.h linux-2.4.25-rc1/fs/xfs/pagebuf/page_buf.h
--- linux-2.4.25-pre8/fs/xfs/pagebuf/page_buf.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/pagebuf/page_buf.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,406 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-/*
- * Written by Steve Lord, Jim Mostek, Russell Cattelan at SGI
- */
-
-#ifndef __PAGE_BUF_H__
-#define __PAGE_BUF_H__
-
-#include <linux/version.h>
-#include <linux/config.h>
-#include <linux/list.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/uio.h>
-
-/*
- *	Base types
- */
-
-/* daddr must be signed since -1 is used for bmaps that are not yet allocated */
-typedef loff_t page_buf_daddr_t;
-
-#define PAGE_BUF_DADDR_NULL ((page_buf_daddr_t) (-1LL))
-
-#define page_buf_ctob(pp)	((pp) * PAGE_CACHE_SIZE)
-#define page_buf_btoc(dd)	(((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
-#define page_buf_btoct(dd)	((dd) >> PAGE_CACHE_SHIFT)
-#define page_buf_poff(aa)	((aa) & ~PAGE_CACHE_MASK)
-
-typedef enum page_buf_rw_e {
-	PBRW_READ = 1,			/* transfer into target memory */
-	PBRW_WRITE = 2,			/* transfer from target memory */
-	PBRW_ZERO = 3			/* Zero target memory */
-} page_buf_rw_t;
-
-
-typedef enum page_buf_flags_e {		/* pb_flags values */
-	PBF_READ = (1 << 0),	/* buffer intended for reading from device */
-	PBF_WRITE = (1 << 1),	/* buffer intended for writing to device   */
-	PBF_MAPPED = (1 << 2),  /* buffer mapped (pb_addr valid)           */
-	PBF_PARTIAL = (1 << 3), /* buffer partially read                   */
-	PBF_ASYNC = (1 << 4),   /* initiator will not wait for completion  */
-	PBF_NONE = (1 << 5),    /* buffer not read at all                  */
-	PBF_DELWRI = (1 << 6),  /* buffer has dirty pages                  */
-	PBF_FREED = (1 << 7),   /* buffer has been freed and is invalid    */
-	PBF_SYNC = (1 << 8),    /* force updates to disk                   */
-	PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages          */
-	PBF_STALE = (1 << 10),	/* buffer has been staled, do not find it  */
-	PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory  */
-	PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad  */
-
-	/* flags used only as arguments to access routines */
-	PBF_LOCK = (1 << 13),	/* lock requested			   */
-	PBF_TRYLOCK = (1 << 14), /* lock requested, but do not wait	   */
-	PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread	   */
-
-	/* flags used only internally */
-	_PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked		   */
-	_PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads	   */
-	_PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped	   */
-	_PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated	   */
-	_PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated  */
-	_PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated  */
-
-	PBF_FORCEIO = (1 << 22), /* ignore any cache state		   */
-	PBF_FLUSH = (1 << 23),	/* flush disk write cache		   */
-	PBF_READ_AHEAD = (1 << 24), /* asynchronous read-ahead		   */
-	PBF_RUN_QUEUES = (1 << 25), /* run block device task queue	   */
-	PBF_DIRECTIO = (1 << 26), /* used for a direct IO mapping	   */
-
-} page_buf_flags_t;
-
-#define PBF_UPDATE (PBF_READ | PBF_WRITE)
-#define PBF_NOT_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) != 0)
-#define PBF_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) == 0)
-
-#define PBR_SECTOR_ONLY	1	/* only use sector size buffer heads */
-#define PBR_ALIGNED_ONLY 2	/* only use aligned I/O */
-
-typedef struct pb_target {
-	int			pbr_flags;
-	dev_t			pbr_dev;
-	kdev_t			pbr_kdev;
-	struct block_device	*pbr_bdev;
-	struct address_space	*pbr_mapping;
-	unsigned int		pbr_bsize;
-	unsigned int		pbr_sshift;
-	size_t			pbr_smask;
-} pb_target_t;
-
-/*
- *	page_buf_t:  Buffer structure for page cache-based buffers
- *
- * This buffer structure is used by the page cache buffer management routines
- * to refer to an assembly of pages forming a logical buffer.  The actual
- * I/O is performed with buffer_head or bio structures, as required by drivers,
- * for drivers which do not understand this structure.  The buffer structure is
- * used on temporary basis only, and discarded when released.
- *
- * The real data storage is recorded in the page cache.  Metadata is
- * hashed to the inode for the block device on which the file system resides.
- * File data is hashed to the inode for the file.  Pages which are only
- * partially filled with data have bits set in their block_map entry
- * to indicate which disk blocks in the page are not valid.
- */
-
-struct page_buf_s;
-typedef void (*page_buf_iodone_t)(struct page_buf_s *);
-			/* call-back function on I/O completion */
-typedef void (*page_buf_relse_t)(struct page_buf_s *);
-			/* call-back function on I/O completion */
-typedef int (*page_buf_bdstrat_t)(struct page_buf_s *);
-
-#define PB_PAGES	4
-
-typedef struct page_buf_s {
-	struct semaphore	pb_sema;	/* semaphore for lockables  */
-	unsigned long		pb_flushtime;	/* time to flush pagebuf    */
-	atomic_t		pb_pin_count;	/* pin count		    */
-	wait_queue_head_t	pb_waiters;	/* unpin waiters	    */
-	struct list_head	pb_list;
-	page_buf_flags_t	pb_flags;	/* status flags */
-	struct list_head	pb_hash_list;
-	struct pb_target	*pb_target;	/* logical object */
-	atomic_t		pb_hold;	/* reference count */
-	page_buf_daddr_t	pb_bn;		/* block number for I/O */
-	loff_t			pb_file_offset;	/* offset in file */
-	size_t			pb_buffer_length; /* size of buffer in bytes */
-	size_t			pb_count_desired; /* desired transfer size */
-	void			*pb_addr;	/* virtual address of buffer */
-	struct tq_struct	pb_iodone_sched;
-	atomic_t		pb_io_remaining;/* #outstanding I/O requests */
-	page_buf_iodone_t	pb_iodone;	/* I/O completion function */
-	page_buf_relse_t	pb_relse;	/* releasing function */
-	page_buf_bdstrat_t	pb_strat;	/* pre-write function */
-	struct semaphore	pb_iodonesema;	/* Semaphore for I/O waiters */
-	void			*pb_fspriv;
-	void			*pb_fspriv2;
-	void			*pb_fspriv3;
-	unsigned short		pb_error;	/* error code on I/O */
-	unsigned short		pb_page_count;	/* size of page array */
-	unsigned short		pb_offset;	/* page offset in first page */
-	unsigned char		pb_locked;	/* page array is locked */
-	unsigned char		pb_hash_index;	/* hash table index	*/
-	struct page		**pb_pages;	/* array of page pointers */
-	struct page		*pb_page_array[PB_PAGES]; /* inline pages */
-#ifdef PAGEBUF_LOCK_TRACKING
-	int			pb_last_holder;
-#endif
-} page_buf_t;
-
-
-/* Finding and Reading Buffers */
-
-extern page_buf_t *pagebuf_find(	/* find buffer for block if	*/
-					/* the block is in memory	*/
-		struct pb_target *,	/* inode for block		*/
-		loff_t,			/* starting offset of range	*/
-		size_t,			/* length of range		*/
-		page_buf_flags_t);	/* PBF_LOCK			*/
-
-extern page_buf_t *pagebuf_get(		/* allocate a buffer		*/
-		struct pb_target *,	/* inode for buffer		*/
-		loff_t,			/* starting offset of range     */
-		size_t,			/* length of range              */
-		page_buf_flags_t);	/* PBF_LOCK, PBF_READ,		*/
-					/* PBF_ASYNC			*/
-
-extern page_buf_t *pagebuf_lookup(
-		struct pb_target *,
-		loff_t,			/* starting offset of range	*/
-		size_t,			/* length of range		*/
-		page_buf_flags_t);	/* PBF_READ, PBF_WRITE,		*/
-					/* PBF_FORCEIO, _PBF_LOCKABLE	*/
-
-extern page_buf_t *pagebuf_get_empty(	/* allocate pagebuf struct with	*/
-					/*  no memory or disk address	*/
-		size_t len,
-		struct pb_target *);	/* mount point "fake" inode	*/
-
-extern page_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct	*/
-					/* without disk address		*/
-		size_t len,
-		struct pb_target *);	/* mount point "fake" inode	*/
-
-extern int pagebuf_associate_memory(
-		page_buf_t *,
-		void *,
-		size_t);
-
-extern void pagebuf_hold(		/* increment reference count	*/
-		page_buf_t *);		/* buffer to hold		*/
-
-extern void pagebuf_readahead(		/* read ahead into cache	*/
-		struct pb_target  *,	/* target for buffer (or NULL)	*/
-		loff_t,			/* starting offset of range     */
-		size_t,			/* length of range              */
-		page_buf_flags_t);	/* additional read flags	*/
-
-/* Releasing Buffers */
-
-extern void pagebuf_free(		/* deallocate a buffer		*/
-		page_buf_t *);		/* buffer to deallocate		*/
-
-extern void pagebuf_rele(		/* release hold on a buffer	*/
-		page_buf_t *);		/* buffer to release		*/
-
-/* Locking and Unlocking Buffers */
-
-extern int pagebuf_cond_lock(		/* lock buffer, if not locked	*/
-					/* (returns -EBUSY if locked)	*/
-		page_buf_t *);		/* buffer to lock		*/
-
-extern int pagebuf_lock_value(		/* return count on lock		*/
-		page_buf_t *);          /* buffer to check              */
-
-extern int pagebuf_lock(		/* lock buffer                  */
-		page_buf_t *);          /* buffer to lock               */
-
-extern void pagebuf_unlock(		/* unlock buffer		*/
-		page_buf_t *);		/* buffer to unlock		*/
-
-/* Buffer Read and Write Routines */
-
-extern void pagebuf_iodone(		/* mark buffer I/O complete	*/
-		page_buf_t *,		/* buffer to mark		*/
-		int,			/* use data/log helper thread.	*/
-		int);			/* run completion locally, or in
-					 * a helper thread.		*/
-
-extern void pagebuf_ioerror(		/* mark buffer in error	(or not) */
-		page_buf_t *,		/* buffer to mark		*/
-		unsigned int);		/* error to store (0 if none)	*/
-
-extern int pagebuf_iostart(		/* start I/O on a buffer	*/
-		page_buf_t *,		/* buffer to start		*/
-		page_buf_flags_t);	/* PBF_LOCK, PBF_ASYNC,		*/
-					/* PBF_READ, PBF_WRITE,		*/
-					/* PBF_DELWRI, PBF_SYNC		*/
-
-extern int pagebuf_iorequest(		/* start real I/O		*/
-		page_buf_t *);		/* buffer to convey to device	*/
-
-extern int pagebuf_iowait(		/* wait for buffer I/O done	*/
-		page_buf_t *);		/* buffer to wait on		*/
-
-extern void pagebuf_iomove(		/* move data in/out of pagebuf	*/
-		page_buf_t *,		/* buffer to manipulate		*/
-		size_t,			/* starting buffer offset	*/
-		size_t,			/* length in buffer		*/
-		caddr_t,		/* data pointer			*/
-		page_buf_rw_t);		/* direction			*/
-
-static inline int pagebuf_iostrategy(page_buf_t *pb)
-{
-	return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb);
-}
-
-static inline int pagebuf_geterror(page_buf_t *pb)
-{
-	return pb ? pb->pb_error : ENOMEM;
-}
-
-/* Buffer Utility Routines */
-
-extern caddr_t pagebuf_offset(		/* pointer at offset in buffer	*/
-		page_buf_t *,		/* buffer to offset into	*/
-		size_t);		/* offset			*/
-
-/* Pinning Buffer Storage in Memory */
-
-extern void pagebuf_pin(		/* pin buffer in memory		*/
-		page_buf_t *);		/* buffer to pin		*/
-
-extern void pagebuf_unpin(		/* unpin buffered data		*/
-		page_buf_t *);		/* buffer to unpin		*/
-
-extern int pagebuf_ispin(		/* check if buffer is pinned	*/
-		page_buf_t *);		/* buffer to check		*/
-
-/* Delayed Write Buffer Routines */
-
-#define PBDF_WAIT    0x01
-extern void pagebuf_delwri_flush(
-		pb_target_t *,
-		unsigned long,
-		int *);
-
-extern void pagebuf_delwri_dequeue(
-		page_buf_t *);
-
-/* Buffer Daemon Setup Routines */
-
-extern int pagebuf_init(void);
-extern void pagebuf_terminate(void);
-
-
-#ifdef PAGEBUF_TRACE
-extern ktrace_t *pagebuf_trace_buf;
-extern void pagebuf_trace(
-		page_buf_t *,		/* buffer being traced		*/
-		char *,			/* description of operation	*/
-		void *,			/* arbitrary diagnostic value	*/
-		void *);		/* return address		*/
-#else
-# define pagebuf_trace(pb, id, ptr, ra)	do { } while (0)
-#endif
-
-#define pagebuf_target_name(target)	bdevname((target)->pbr_kdev)
-
-/*
- * Kernel version compatibility macros
- */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,9)
-#define page_buffers(page)	((page)->buffers)
-#define page_has_buffers(page)	((page)->buffers)
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,12)
-#define PageUptodate(x)		Page_Uptodate(x)
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,17)
-/*
- * macro tricks to expand the set_buffer_foo() and clear_buffer_foo()
- * functions.
- */
-#define BUFFER_FNS(bit, name)						\
-static inline void set_buffer_##name(struct buffer_head *bh)		\
-{									\
-	set_bit(BH_##bit, &(bh)->b_state);				\
-}									\
-static inline void clear_buffer_##name(struct buffer_head *bh)		\
-{									\
-	clear_bit(BH_##bit, &(bh)->b_state);				\
-}									\
-
-/*
- * Emit the buffer bitops functions.   Note that there are also functions
- * of the form "mark_buffer_foo()".  These are higher-level functions which
- * do something in addition to setting a b_state bit.
- */
-BUFFER_FNS(Uptodate, uptodate)
-BUFFER_FNS(Dirty, dirty)
-BUFFER_FNS(Lock, locked)
-BUFFER_FNS(Req, req)
-BUFFER_FNS(Mapped, mapped)
-BUFFER_FNS(New, new)
-BUFFER_FNS(Async, async)
-BUFFER_FNS(Wait_IO, wait_io)
-BUFFER_FNS(Launder, launder)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)
-BUFFER_FNS(Sync, sync)
-#endif /* kernel >= 2.4.22 */
-BUFFER_FNS(Delay, delay)
-#endif /* kernel < 2.5.17 */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)
-#define get_seconds()		CURRENT_TIME
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,67)
-#define blk_run_queues()	run_task_queue(&tq_disk)
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#define i_size_read(inode)	((inode)->i_size)
-#define i_size_write(inode, sz)	((inode)->i_size = (sz))
-#endif
-
-#endif /* __PAGE_BUF_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/quota/Makefile linux-2.4.25-rc1/fs/xfs/quota/Makefile
--- linux-2.4.25-pre8/fs/xfs/quota/Makefile	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/quota/Makefile	2004-02-05 04:40:36.000000000 -0800
@@ -30,7 +30,7 @@
 # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 #
 
-EXTRA_CFLAGS += -I $(TOPDIR)/fs/xfs
+EXTRA_CFLAGS += -I $(TOPDIR)/fs/xfs -I $(TOPDIR)/fs/xfs/linux
 
 ifeq ($(CONFIG_XFS_DEBUG),y)
 	EXTRA_CFLAGS += -g -DDEBUG -DXFSDEBUG
@@ -54,6 +54,4 @@
 				   xfs_qm_bhv.o \
 				   xfs_qm.o
 
-export-objs			+= xfs_qm.o
-
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.25-pre8/fs/xfs/quota/xfs_qm.c linux-2.4.25-rc1/fs/xfs/quota/xfs_qm.c
--- linux-2.4.25-pre8/fs/xfs/quota/xfs_qm.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/quota/xfs_qm.c	2004-02-05 04:40:36.000000000 -0800
@@ -78,7 +78,6 @@
  */
 mutex_t xfs_Gqm_lock;
 struct xfs_qm	*xfs_Gqm;
-EXPORT_SYMBOL(xfs_Gqm);	/* used by xfsidbg */
 
 kmem_zone_t	*qm_dqzone;
 kmem_zone_t	*qm_dqtrxzone;
diff -urN linux-2.4.25-pre8/fs/xfs/support/Makefile linux-2.4.25-rc1/fs/xfs/support/Makefile
--- linux-2.4.25-pre8/fs/xfs/support/Makefile	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/Makefile	2004-02-05 04:40:36.000000000 -0800
@@ -30,7 +30,7 @@
 # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 #
 
-EXTRA_CFLAGS += -I..
+EXTRA_CFLAGS += -I.. -I $(TOPDIR)/fs/xfs/linux
 
 ifeq ($(CONFIG_XFS_DEBUG),y)
 	EXTRA_CFLAGS += -DDEBUG
@@ -41,12 +41,8 @@
   obj-m				:= $(O_TARGET)
 endif
 
-export-objs			:= ktrace.o
-
 obj-y				:= debug.o \
-				   kmem.o \
 				   move.o \
-				   mrlock.o \
 				   qsort.o \
 				   uuid.o
 
diff -urN linux-2.4.25-pre8/fs/xfs/support/kmem.c linux-2.4.25-rc1/fs/xfs/support/kmem.c
--- linux-2.4.25-pre8/fs/xfs/support/kmem.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/kmem.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-
-#include "time.h"
-#include "kmem.h"
-
-#define DEF_PRIORITY	(6)
-#define MAX_SLAB_SIZE	0x10000
-#define MAX_SHAKE	8
-
-static kmem_shake_func_t	shake_list[MAX_SHAKE];
-static DECLARE_MUTEX(shake_sem);
-
-kmem_shaker_t
-kmem_shake_register(kmem_shake_func_t sfunc)
-{
-	int	i;
-
-	down(&shake_sem);
-	for (i = 0; i < MAX_SHAKE; i++) {
-		if (shake_list[i] == NULL) {
-			shake_list[i] = sfunc;
-			break;
-		}
-	}
-	if (i == MAX_SHAKE)
-		BUG();
-	up(&shake_sem);
-
-	return (kmem_shaker_t)sfunc;
-}
-
-void
-kmem_shake_deregister(kmem_shaker_t sfunc)
-{
-	int	i;
-
-	down(&shake_sem);
-	for (i = 0; i < MAX_SHAKE; i++) {
-		if (shake_list[i] == (kmem_shake_func_t)sfunc)
-			break;
-	}
-	if (i == MAX_SHAKE)
-		BUG();
-	for (; i < MAX_SHAKE - 1; i++) {
-		shake_list[i] = shake_list[i+1];
-	}
-	shake_list[i] = NULL;
-	up(&shake_sem);
-}
-
-static __inline__ void kmem_shake(void)
-{
-	int	i;
-
-	down(&shake_sem);
-	for (i = 0; i < MAX_SHAKE && shake_list[i]; i++)
-		(*shake_list[i])(0, 0);
-	up(&shake_sem);
-	delay(10);
-}
-
-void *
-kmem_alloc(size_t size, int flags)
-{
-	int	shrink  = DEF_PRIORITY;	/* # times to try to shrink cache */
-        int     lflags  = kmem_flags_convert(flags);
-        int     nosleep = flags & KM_NOSLEEP;
-	void	*rval;
-
-repeat:
-	if (MAX_SLAB_SIZE < size) {
-		/* Avoid doing filesystem sensitive stuff to get this */
-		rval = __vmalloc(size, lflags, PAGE_KERNEL);
-	} else {
-		rval = kmalloc(size, lflags);
-	}
-
-	if (rval || nosleep)
-		return rval;
-
-	/*
-	 * KM_SLEEP callers don't expect a failure
-	 */
-	if (shrink) {
-		kmem_shake();
-
-		shrink--;
-		goto repeat;
-	}
-
-	rval = __vmalloc(size, lflags, PAGE_KERNEL);
-	if (!rval && !nosleep)
-		panic("kmem_alloc: NULL memory on KM_SLEEP request!");
-
-	return rval;
-}
-
-void *
-kmem_zalloc(size_t size, int flags)
-{
-	void	*ptr;
-
-	ptr = kmem_alloc(size, flags);
-
-	if (ptr)
-		memset((char *)ptr, 0, (int)size);
-
-	return (ptr);
-}
-
-void
-kmem_free(void *ptr, size_t size)
-{
-	if (((unsigned long)ptr < VMALLOC_START) ||
-	    ((unsigned long)ptr >= VMALLOC_END)) {
-		kfree(ptr);
-	} else {
-		vfree(ptr);
-	}
-}
-
-void *
-kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
-{
-	void *new;
-
-	new = kmem_alloc(newsize, flags);
-	if (ptr) {
-		if (new)
-			memcpy(new, ptr,
-				((oldsize < newsize) ? oldsize : newsize));
-		kmem_free(ptr, oldsize);
-	}
-
-	return new;
-}
-
-kmem_zone_t *
-kmem_zone_init(int size, char *zone_name)
-{
-	return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL);
-}
-
-void *
-kmem_zone_alloc(kmem_zone_t *zone, int flags)
-{
-	int	shrink = DEF_PRIORITY;	/* # times to try to shrink cache */
-	void	*ptr = NULL;
-
-repeat:
-	ptr = kmem_cache_alloc(zone, kmem_flags_convert(flags));
-
-	if (ptr || (flags & KM_NOSLEEP))
-		return ptr;
-
-	/*
-	 * KM_SLEEP callers don't expect a failure
-	 */
-	if (shrink) {
-		kmem_shake();
-
-		shrink--;
-		goto repeat;
-	}
-
-	if (flags & KM_SLEEP)
-		panic("kmem_zone_alloc: NULL memory on KM_SLEEP request!");
-
-	return NULL;
-}
-
-void *
-kmem_zone_zalloc(kmem_zone_t *zone, int flags)
-{
-	int	shrink = DEF_PRIORITY;	/* # times to try to shrink cache */
-	void	*ptr = NULL;
-
-repeat:
-	ptr = kmem_cache_alloc(zone, kmem_flags_convert(flags));
-
-	if (ptr) {
-		memset(ptr, 0, kmem_cache_size(zone));
-		return ptr;
-	}
-
-	if (flags & KM_NOSLEEP)
-		return ptr;
-
-	/*
-	 * KM_SLEEP callers don't expect a failure
-	 */
-	if (shrink) {
-		kmem_shake();
-
-		shrink--;
-		goto repeat;
-	}
-
-	if (flags & KM_SLEEP)
-		panic("kmem_zone_zalloc: NULL memory on KM_SLEEP request!");
-
-	return NULL;
-}
-
-void
-kmem_zone_free(kmem_zone_t *zone, void *ptr)
-{
-	kmem_cache_free(zone, ptr);
-}
diff -urN linux-2.4.25-pre8/fs/xfs/support/kmem.h linux-2.4.25-rc1/fs/xfs/support/kmem.h
--- linux-2.4.25-pre8/fs/xfs/support/kmem.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/kmem.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_SUPPORT_KMEM_H__
-#define __XFS_SUPPORT_KMEM_H__
-
-#include <linux/slab.h>
-
-/*
- * memory management routines
- */
-#define KM_SLEEP	0x0001
-#define KM_NOSLEEP	0x0002
-#define KM_NOFS		0x0004
-
-#define	kmem_zone	kmem_cache_s
-#define kmem_zone_t	kmem_cache_t
-
-typedef unsigned long xfs_pflags_t;
-
-#define PFLAGS_TEST_NOIO()              (current->flags & PF_NOIO)
-#define PFLAGS_TEST_FSTRANS()           (current->flags & PF_FSTRANS)
-
-#define PFLAGS_SET_NOIO(STATEP) do {    \
-	*(STATEP) = current->flags;     \
-        current->flags |= PF_NOIO;      \
-} while (0)
-
-#define PFLAGS_SET_FSTRANS(STATEP) do { \
-	*(STATEP) = current->flags;     \
-        current->flags |= PF_FSTRANS;   \
-} while (0)
-
-#define PFLAGS_RESTORE(STATEP) do {     \
-	current->flags = *(STATEP);     \
-} while (0)
-
-#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \
-	*(NSTATEP) = *(OSTATEP);	\
-} while (0);
-
-static __inline unsigned int kmem_flags_convert(int flags)
-{
-        int lflags;
-        
-#if DEBUG
-	if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) {
-		printk(KERN_WARNING
-		    "XFS: memory allocation with wrong flags (%x)\n", flags);
-		BUG();
-	}
-#endif
-        
-        lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : GFP_KERNEL;
-        
-        /* avoid recusive callbacks to filesystem during transactions */
-	if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS))
-		lflags &= ~__GFP_FS;
-        
-        return lflags;
-}
-
-extern kmem_zone_t  *kmem_zone_init(int, char *);
-extern void	    *kmem_zone_zalloc(kmem_zone_t *, int);
-extern void	    *kmem_zone_alloc(kmem_zone_t *, int);
-extern void         kmem_zone_free(kmem_zone_t *, void *);
-
-extern void	    *kmem_alloc(size_t, int);
-extern void	    *kmem_realloc(void *, size_t, size_t, int);
-extern void	    *kmem_zalloc(size_t, int);
-extern void         kmem_free(void *, size_t);
-
-typedef void	    *kmem_shaker_t;
-typedef int	    (*kmem_shake_func_t)(int, unsigned int);
-
-extern kmem_shaker_t	kmem_shake_register(kmem_shake_func_t);
-extern void	    kmem_shake_deregister(kmem_shaker_t);
-static __inline int	kmem_shake_allow(unsigned int mask) { return 1; }
-
-#endif /* __XFS_SUPPORT_KMEM_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/support/ktrace.c linux-2.4.25-rc1/fs/xfs/support/ktrace.c
--- linux-2.4.25-pre8/fs/xfs/support/ktrace.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/ktrace.c	2004-02-05 04:40:36.000000000 -0800
@@ -30,7 +30,6 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 
@@ -273,7 +272,6 @@
 	}
 	return ktep;
 }
-EXPORT_SYMBOL(ktrace_first);
 
 /*
  * ktrace_next()
@@ -308,7 +306,6 @@
 
 	return ktep;
 }
-EXPORT_SYMBOL(ktrace_next);
 
 /*
  * ktrace_skip()
diff -urN linux-2.4.25-pre8/fs/xfs/support/ktrace.h linux-2.4.25-rc1/fs/xfs/support/ktrace.h
--- linux-2.4.25-pre8/fs/xfs/support/ktrace.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/ktrace.h	2004-02-05 04:40:36.000000000 -0800
@@ -32,7 +32,7 @@
 #ifndef __XFS_SUPPORT_KTRACE_H__
 #define __XFS_SUPPORT_KTRACE_H__
 
-#include <support/spin.h>
+#include <spin.h>
 
 /*
  * Trace buffer entry structure.
diff -urN linux-2.4.25-pre8/fs/xfs/support/mrlock.c linux-2.4.25-rc1/fs/xfs/support/mrlock.c
--- linux-2.4.25-pre8/fs/xfs/support/mrlock.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/mrlock.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,274 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <asm/system.h>
-#include <linux/interrupt.h>
-#include <asm/current.h>
-
-#include "mrlock.h"
-
-
-#if USE_RW_WAIT_QUEUE_SPINLOCK
-# define wq_write_lock	write_lock
-#else
-# define wq_write_lock	spin_lock
-#endif
-
-/*
- * We don't seem to need lock_type (only one supported), name, or
- * sequence. But, XFS will pass it so let's leave them here for now.
- */
-/* ARGSUSED */
-void
-mrlock_init(mrlock_t *mrp, int lock_type, char *name, long sequence)
-{
-	mrp->mr_count = 0;
-	mrp->mr_reads_waiting = 0;
-	mrp->mr_writes_waiting = 0;
-	init_waitqueue_head(&mrp->mr_readerq);
-	init_waitqueue_head(&mrp->mr_writerq);
-	mrp->mr_lock = SPIN_LOCK_UNLOCKED;
-}
-
-/*
- * Macros to lock/unlock the mrlock_t.
- */
-
-#define MRLOCK(m)		spin_lock(&(m)->mr_lock);
-#define MRUNLOCK(m)		spin_unlock(&(m)->mr_lock);
-
-
-/*
- * lock_wait should never be called in an interrupt thread.
- *
- * mrlocks can sleep (i.e. call schedule) and so they can't ever
- * be called from an interrupt thread.
- *
- * threads that wake-up should also never be invoked from interrupt threads.
- *
- * But, waitqueue_lock is locked from interrupt threads - and we are
- * called with interrupts disabled, so it is all OK.
- */
-
-/* ARGSUSED */
-void
-lock_wait(wait_queue_head_t *q, spinlock_t *lock, int rw)
-{
-	DECLARE_WAITQUEUE( wait, current );
-
-	__set_current_state(TASK_UNINTERRUPTIBLE);
-
-	wq_write_lock(&q->lock);
-	if (rw) {
-		__add_wait_queue_tail(q, &wait);
-	} else {
-		__add_wait_queue(q, &wait);
-	}
-
-	wq_write_unlock(&q->lock);
-	spin_unlock(lock);
-
-	schedule();
-
-	wq_write_lock(&q->lock);
-	__remove_wait_queue(q, &wait);
-	wq_write_unlock(&q->lock);
-
-	spin_lock(lock);
-
-	/* return with lock held */
-}
-
-/* ARGSUSED */
-void
-mrfree(mrlock_t *mrp)
-{
-}
-
-/* ARGSUSED */
-void
-mrlock(mrlock_t *mrp, int type, int flags)
-{
-	if (type == MR_ACCESS)
-		mraccess(mrp);
-	else
-		mrupdate(mrp);
-}
-
-/* ARGSUSED */
-void
-mraccessf(mrlock_t *mrp, int flags)
-{
-	MRLOCK(mrp);
-	if(mrp->mr_writes_waiting > 0) {
-		mrp->mr_reads_waiting++;
-		lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0);
-		mrp->mr_reads_waiting--;
-	}
-	while (mrp->mr_count < 0) {
-		mrp->mr_reads_waiting++;
-		lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0);
-		mrp->mr_reads_waiting--;
-	}
-	mrp->mr_count++;
-	MRUNLOCK(mrp);
-}
-
-/* ARGSUSED */
-void
-mrupdatef(mrlock_t *mrp, int flags)
-{
-	MRLOCK(mrp);
-	while(mrp->mr_count) {
-		mrp->mr_writes_waiting++;
-		lock_wait(&mrp->mr_writerq, &mrp->mr_lock, 1);
-		mrp->mr_writes_waiting--;
-	}
-
-	mrp->mr_count = -1; /* writer on it */
-	MRUNLOCK(mrp);
-}
-
-int
-mrtryaccess(mrlock_t *mrp)
-{
-	MRLOCK(mrp);
-	/*
-	 * If anyone is waiting for update access or the lock is held for update
-	 * fail the request.
-	 */
-	if(mrp->mr_writes_waiting > 0 || mrp->mr_count < 0) {
-		MRUNLOCK(mrp);
-		return 0;
-	}
-	mrp->mr_count++;
-	MRUNLOCK(mrp);
-	return 1;
-}
-
-int
-mrtrypromote(mrlock_t *mrp)
-{
-	MRLOCK(mrp);
-
-	if(mrp->mr_count == 1) { /* We are the only thread with the lock */
-		mrp->mr_count = -1; /* writer on it */
-		MRUNLOCK(mrp);
-		return 1;
-	}
-
-	MRUNLOCK(mrp);
-	return 0;
-}
-
-int
-mrtryupdate(mrlock_t *mrp)
-{
-	MRLOCK(mrp);
-
-	if(mrp->mr_count) {
-		MRUNLOCK(mrp);
-		return 0;
-	}
-
-	mrp->mr_count = -1; /* writer on it */
-	MRUNLOCK(mrp);
-	return 1;
-}
-
-static __inline__ void mrwake(mrlock_t *mrp)
-{
-	/*
-	 * First, if the count is now 0, we need to wake-up anyone waiting.
-	 */
-	if (!mrp->mr_count) {
-		if (mrp->mr_writes_waiting) {	/* Wake-up first writer waiting */
-			wake_up(&mrp->mr_writerq);
-		} else if (mrp->mr_reads_waiting) {	/* Wakeup any readers waiting */
-			wake_up(&mrp->mr_readerq);
-		}
-	}
-}
-
-void
-mraccunlock(mrlock_t *mrp)
-{
-	MRLOCK(mrp);
-	mrp->mr_count--;
-	mrwake(mrp);
-	MRUNLOCK(mrp);
-}
-
-void
-mrunlock(mrlock_t *mrp)
-{
-	MRLOCK(mrp);
-	if (mrp->mr_count < 0) {
-		mrp->mr_count = 0;
-	} else {
-		mrp->mr_count--;
-	}
-	mrwake(mrp);
-	MRUNLOCK(mrp);
-}
-
-int
-ismrlocked(mrlock_t *mrp, int type)	/* No need to lock since info can change */
-{
-	if (type == MR_ACCESS)
-		return (mrp->mr_count > 0); /* Read lock */
-	else if (type == MR_UPDATE)
-		return (mrp->mr_count < 0); /* Write lock */
-	else if (type == (MR_UPDATE | MR_ACCESS))
-		return (mrp->mr_count);	/* Any type of lock held */
-	else /* Any waiters */
-		return (mrp->mr_reads_waiting | mrp->mr_writes_waiting);
-}
-
-/*
- * Demote from update to access. We better be the only thread with the
- * lock in update mode so it should be easy to set to 1.
- * Wake-up any readers waiting.
- */
-
-void
-mrdemote(mrlock_t *mrp)
-{
-	MRLOCK(mrp);
-	mrp->mr_count = 1;
-	if (mrp->mr_reads_waiting) {	/* Wakeup all readers waiting */
-		wake_up(&mrp->mr_readerq);
-	}
-	MRUNLOCK(mrp);
-}
diff -urN linux-2.4.25-pre8/fs/xfs/support/mrlock.h linux-2.4.25-rc1/fs/xfs/support/mrlock.h
--- linux-2.4.25-pre8/fs/xfs/support/mrlock.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/mrlock.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_SUPPORT_MRLOCK_H__
-#define __XFS_SUPPORT_MRLOCK_H__
-
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <asm/atomic.h>
-#include <asm/semaphore.h>
-
-/*
- * Implement mrlocks on Linux that work for XFS.
- *
- * These are sleep locks and not spinlocks. If one wants read/write spinlocks,
- * use read_lock, write_lock, ... see spinlock.h.
- */
-
-typedef struct mrlock_s {
-	int			mr_count;
-	unsigned short		mr_reads_waiting;
-	unsigned short		mr_writes_waiting;
-	wait_queue_head_t	mr_readerq;
-	wait_queue_head_t	mr_writerq;
-	spinlock_t		mr_lock;
-} mrlock_t;
-
-#define MR_ACCESS	1
-#define MR_UPDATE	2
-
-#define MRLOCK_BARRIER		0x1
-#define MRLOCK_ALLOW_EQUAL_PRI	0x8
-
-/*
- * mraccessf/mrupdatef take flags to be passed in while sleeping;
- * only PLTWAIT is currently supported.
- */
-
-extern void	mraccessf(mrlock_t *, int);
-extern void	mrupdatef(mrlock_t *, int);
-extern void     mrlock(mrlock_t *, int, int);
-extern void     mrunlock(mrlock_t *);
-extern void     mraccunlock(mrlock_t *);
-extern int      mrtryupdate(mrlock_t *);
-extern int      mrtryaccess(mrlock_t *);
-extern int	mrtrypromote(mrlock_t *);
-extern void     mrdemote(mrlock_t *);
-
-extern int	ismrlocked(mrlock_t *, int);
-extern void     mrlock_init(mrlock_t *, int type, char *name, long sequence);
-extern void     mrfree(mrlock_t *);
-
-#define mrinit(mrp, name)	mrlock_init(mrp, MRLOCK_BARRIER, name, -1)
-#define mraccess(mrp)		mraccessf(mrp, 0) /* grab for READ/ACCESS */
-#define mrupdate(mrp)		mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */
-#define mrislocked_access(mrp)	((mrp)->mr_count > 0)
-#define mrislocked_update(mrp)	((mrp)->mr_count < 0)
-
-#endif /* __XFS_SUPPORT_MRLOCK_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/support/mutex.h linux-2.4.25-rc1/fs/xfs/support/mutex.h
--- linux-2.4.25-pre8/fs/xfs/support/mutex.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/mutex.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- * Portions Copyright (c) 2002 Christoph Hellwig.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_SUPPORT_MUTEX_H__
-#define __XFS_SUPPORT_MUTEX_H__
-
-#include <linux/spinlock.h>
-#include <asm/semaphore.h>
-
-/*
- * Map the mutex'es from IRIX to Linux semaphores.
- *
- * Destroy just simply initializes to -99 which should block all other
- * callers.
- */
-#define MUTEX_DEFAULT		0x0
-typedef struct semaphore	mutex_t;
-
-#define mutex_init(lock, type, name)		sema_init(lock, 1)
-#define mutex_destroy(lock)			sema_init(lock, -99)
-#define mutex_lock(lock, num)			down(lock)
-#define mutex_trylock(lock)			(down_trylock(lock) ? 0 : 1)
-#define mutex_unlock(lock)			up(lock)
-
-#endif /* __XFS_SUPPORT_MUTEX_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/support/sema.h linux-2.4.25-rc1/fs/xfs/support/sema.h
--- linux-2.4.25-pre8/fs/xfs/support/sema.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/sema.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_SUPPORT_SEMA_H__
-#define __XFS_SUPPORT_SEMA_H__
-
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <asm/atomic.h>
-#include <asm/semaphore.h>
-
-/*
- * sema_t structure just maps to struct semaphore in Linux kernel.
- */
-
-typedef struct semaphore sema_t;
-
-#define init_sema(sp, val, c, d)	sema_init(sp, val)
-#define initsema(sp, val)		sema_init(sp, val)
-#define initnsema(sp, val, name)	sema_init(sp, val)
-#define psema(sp, b)			down(sp)
-#define vsema(sp)			up(sp)
-#define valusema(sp)			(atomic_read(&(sp)->count))
-#define freesema(sema)
-
-/*
- * Map cpsema (try to get the sema) to down_trylock. We need to switch
- * the return values since cpsema returns 1 (acquired) 0 (failed) and
- * down_trylock returns the reverse 0 (acquired) 1 (failed).
- */
-
-#define cpsema(sp)			(down_trylock(sp) ? 0 : 1)
-
-/*
- * Didn't do cvsema(sp). Not sure how to map this to up/down/...
- * It does a vsema if the values is < 0 other wise nothing.
- */
-
-#endif /* __XFS_SUPPORT_SEMA_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/support/spin.h linux-2.4.25-rc1/fs/xfs/support/spin.h
--- linux-2.4.25-pre8/fs/xfs/support/spin.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/spin.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
- * Portions Copyright (c) 2002 Christoph Hellwig.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_SUPPORT_SPIN_H__
-#define __XFS_SUPPORT_SPIN_H__
-
-#include <linux/sched.h>	/* preempt needs this */
-#include <linux/spinlock.h>
-
-/*
- * Map lock_t from IRIX to Linux spinlocks.
- *
- * Note that linux turns on/off spinlocks depending on CONFIG_SMP.
- * We don't need to worry about SMP or not here.
- */
-
-#define SPLDECL(s)		unsigned long s
-
-typedef spinlock_t lock_t;
-
-#define spinlock_init(lock, name)	spin_lock_init(lock)
-#define	spinlock_destroy(lock)
-
-static inline unsigned long mutex_spinlock(lock_t *lock)
-{
-	spin_lock(lock);
-	return 0;
-}
-
-/*ARGSUSED*/
-static inline void mutex_spinunlock(lock_t *lock, unsigned long s)
-{
-	spin_unlock(lock);
-}
-
-static inline void nested_spinlock(lock_t *lock)
-{
-	spin_lock(lock);
-}
-
-static inline void nested_spinunlock(lock_t *lock)
-{
-	spin_unlock(lock);
-}
-
-#endif /* __XFS_SUPPORT_SPIN_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/support/sv.h linux-2.4.25-rc1/fs/xfs/support/sv.h
--- linux-2.4.25-pre8/fs/xfs/support/sv.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/sv.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
- * Portions Copyright (c) 2002 Christoph Hellwig.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_SUPPORT_SV_H__
-#define __XFS_SUPPORT_SV_H__
-
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-
-/*
- * Synchronisation variables.
- *
- * (Parameters "pri", "svf" and "rts" are not implemented)
- */
-
-typedef struct sv_s {
-	wait_queue_head_t waiters;
-} sv_t;
-
-#define SV_FIFO		0x0		/* sv_t is FIFO type */
-#define SV_LIFO		0x2		/* sv_t is LIFO type */
-#define SV_PRIO		0x4		/* sv_t is PRIO type */
-#define SV_KEYED	0x6		/* sv_t is KEYED type */
-#define SV_DEFAULT      SV_FIFO
-
-
-static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state,
-			     unsigned long timeout)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue_exclusive(&sv->waiters, &wait);
-	__set_current_state(state);
-	spin_unlock(lock);
-
-	schedule_timeout(timeout);
-
-	remove_wait_queue(&sv->waiters, &wait);
-}
-
-#define init_sv(sv,type,name,flag) \
-	init_waitqueue_head(&(sv)->waiters)
-#define sv_init(sv,flag,name) \
-	init_waitqueue_head(&(sv)->waiters)
-#define sv_destroy(sv) \
-	/*NOTHING*/
-#define sv_wait(sv, pri, lock, s) \
-	_sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)
-#define sv_wait_sig(sv, pri, lock, s)   \
-	_sv_wait(sv, lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)
-#define sv_timedwait(sv, pri, lock, s, svf, ts, rts) \
-	_sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, timespec_to_jiffies(ts))
-#define sv_timedwait_sig(sv, pri, lock, s, svf, ts, rts) \
-	_sv_wait(sv, lock, TASK_INTERRUPTIBLE, timespec_to_jiffies(ts))
-#define sv_signal(sv) \
-	wake_up(&(sv)->waiters)
-#define sv_broadcast(sv) \
-	wake_up_all(&(sv)->waiters)
-
-#endif /* __XFS_SUPPORT_SV_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/support/time.h linux-2.4.25-rc1/fs/xfs/support/time.h
--- linux-2.4.25-pre8/fs/xfs/support/time.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/time.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_SUPPORT_TIME_H__
-#define __XFS_SUPPORT_TIME_H__
-
-#include <linux/sched.h>
-#include <linux/time.h>
-
-typedef struct timespec timespec_t;
-
-static inline void delay(long ticks)
-{
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout(ticks);
-}
-
-static inline void nanotime(struct timespec *tvp)
-{
-	struct timeval tv;
-
-	do_gettimeofday(&tv);
-	tvp->tv_sec = tv.tv_sec;
-	tvp->tv_nsec = tv.tv_usec * 1000;
-}
-
-#endif /* __XFS_SUPPORT_TIME_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/support/uuid.c linux-2.4.25-rc1/fs/xfs/support/uuid.c
--- linux-2.4.25-pre8/fs/xfs/support/uuid.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/support/uuid.c	2004-02-05 04:40:36.000000000 -0800
@@ -31,11 +31,6 @@
  */
 
 #include <xfs.h>
-#include "time.h"
-#include "uuid.h"
-#include "kmem.h"
-#include "debug.h"
-#include "mutex.h"
 
 static mutex_t	uuid_monitor;
 static int	uuid_table_size;
diff -urN linux-2.4.25-pre8/fs/xfs/xfs.h linux-2.4.25-rc1/fs/xfs/xfs.h
--- linux-2.4.25-pre8/fs/xfs/xfs.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs.h	2004-02-05 04:40:36.000000000 -0800
@@ -35,6 +35,5 @@
 #include <linux/xfs_linux.h>
 
 #include <xfs_fs.h> 
-#include <xfs_buf.h>
 
 #endif	/* __XFS_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_attr.c linux-2.4.25-rc1/fs/xfs/xfs_attr.c
--- linux-2.4.25-pre8/fs/xfs/xfs_attr.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_attr.c	2004-02-05 04:40:36.000000000 -0800
@@ -106,12 +106,11 @@
 #define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
 #define ATTR_RMTVALUE_TRANSBLKS	8	/* max # of blks in a transaction */
 
-#if defined(DEBUG)
+#if defined(XFS_ATTR_TRACE)
 ktrace_t *xfs_attr_trace_buf;
 #endif
 
 
-
 /*========================================================================
  * Overall external interface routines.
  *========================================================================*/
@@ -2589,6 +2588,14 @@
 }
 
 STATIC int
+attr_secure_capable(
+	struct vnode	*vp,
+	cred_t		*cred)
+{
+	return -ENOSECURITY;
+}
+
+STATIC int
 attr_system_set(
 	struct vnode *vp, char *name, void *data, size_t size, int xflags)
 {
@@ -2651,6 +2658,16 @@
 	.attr_capable	= attr_trusted_capable,
 };
 
+struct attrnames attr_secure = {
+	.attr_name	= "security.",
+	.attr_namelen	= sizeof("security.") - 1,
+	.attr_flag	= ATTR_SECURE,
+	.attr_get	= attr_generic_get,
+	.attr_set	= attr_generic_set,
+	.attr_remove	= attr_generic_remove,
+	.attr_capable	= attr_secure_capable,
+};
+
 struct attrnames attr_user = {
 	.attr_name	= "user.",
 	.attr_namelen	= sizeof("user.") - 1,
@@ -2661,4 +2678,4 @@
 };
 
 struct attrnames *attr_namespaces[] =
-	{ &attr_system, &attr_trusted, &attr_user };
+	{ &attr_system, &attr_trusted, &attr_secure, &attr_user };
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_attr.h linux-2.4.25-rc1/fs/xfs/xfs_attr.h
--- linux-2.4.25-pre8/fs/xfs/xfs_attr.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_attr.h	2004-02-05 04:40:36.000000000 -0800
@@ -69,8 +69,9 @@
 	attrcapable_t	attr_capable;
 } attrnames_t;
 
-#define ATTR_NAMECOUNT	3
+#define ATTR_NAMECOUNT	4
 extern struct attrnames attr_user;
+extern struct attrnames attr_secure;
 extern struct attrnames attr_system;
 extern struct attrnames attr_trusted;
 extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
@@ -86,6 +87,7 @@
 #define ATTR_DONTFOLLOW	0x0001	/* -- unused, from IRIX -- */
 #define ATTR_ROOT	0x0002	/* use attrs in root (trusted) namespace */
 #define ATTR_TRUST	0x0004	/* -- unused, from IRIX -- */
+#define ATTR_SECURE	0x0008	/* use attrs in security namespace */
 #define ATTR_CREATE	0x0010	/* pure create: fail if attr already exists */
 #define ATTR_REPLACE	0x0020	/* pure set: fail if attr does not exist */
 #define ATTR_SYSTEM	0x0100	/* use attrs in system (pseudo) namespace */
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_attr_leaf.c linux-2.4.25-rc1/fs/xfs/xfs_attr_leaf.c
--- linux-2.4.25-pre8/fs/xfs/xfs_attr_leaf.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_attr_leaf.c	2004-02-05 04:40:36.000000000 -0800
@@ -159,6 +159,9 @@
 			continue;
 		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
 			continue;
+		if (((args->flags & ATTR_SECURE) != 0) !=
+		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
+			continue;
 		if (((args->flags & ATTR_ROOT) != 0) !=
 		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
 			continue;
@@ -173,7 +176,8 @@
 
 	sfe->namelen = args->namelen;
 	INT_SET(sfe->valuelen, ARCH_CONVERT, args->valuelen);
-	sfe->flags = (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0;
+	sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
+			((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
 	memcpy(sfe->nameval, args->name, args->namelen);
 	memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen);
 	INT_MOD(sf->hdr.count, ARCH_CONVERT, 1);
@@ -209,6 +213,9 @@
 			continue;
 		if (memcmp(sfe->nameval, args->name, args->namelen) != 0)
 			continue;
+		if (((args->flags & ATTR_SECURE) != 0) !=
+		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
+			continue;
 		if (((args->flags & ATTR_ROOT) != 0) !=
 		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
 			continue;
@@ -253,6 +260,9 @@
 			continue;
 		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
 			continue;
+		if (((args->flags & ATTR_SECURE) != 0) !=
+		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
+			continue;
 		if (((args->flags & ATTR_ROOT) != 0) !=
 		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
 			continue;
@@ -281,6 +291,9 @@
 			continue;
 		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
 			continue;
+		if (((args->flags & ATTR_SECURE) != 0) !=
+		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
+			continue;
 		if (((args->flags & ATTR_ROOT) != 0) !=
 		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
 			continue;
@@ -369,7 +382,8 @@
 		nargs.valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT);
 		nargs.hashval = xfs_da_hashname((char *)sfe->nameval,
 						sfe->namelen);
-		nargs.flags = (sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0;
+		nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
+				((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
 		error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */
 		ASSERT(error == ENOATTR);
 		error = xfs_attr_leaf_add(bp, &nargs);
@@ -446,14 +460,15 @@
 				i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
 			attrnames_t	*namesp;
 
-			namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-				  &attr_user;
 			if (((context->flags & ATTR_ROOT) != 0) !=
 			    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
 			    !(context->flags & ATTR_KERNFULLS)) {
 				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 				continue;
 			}
+			namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure:
+				((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
+				  &attr_user);
 			if (context->flags & ATTR_KERNOVAL) {
 				ASSERT(context->flags & ATTR_KERNAMELS);
 				context->count += namesp->attr_namelen +
@@ -548,8 +563,9 @@
 	for ( ; i < nsbuf; i++, sbp++) {
 		attrnames_t	*namesp;
 
-		namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-			  &attr_user;
+		namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure :
+			((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
+			  &attr_user);
 
 		if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) {
 			cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT);
@@ -668,7 +684,8 @@
 		nargs.value = (char *)&name_loc->nameval[nargs.namelen];
 		nargs.valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT);
 		nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT);
-		nargs.flags = (entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0;
+		nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
+			      ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
 		xfs_attr_shortform_add(&nargs);
 	}
 	error = 0;
@@ -963,7 +980,8 @@
 				      + INT_GET(map->size, ARCH_CONVERT));
 	INT_SET(entry->hashval, ARCH_CONVERT, args->hashval);
 	entry->flags = tmp ? XFS_ATTR_LOCAL : 0;
-	entry->flags |= (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0;
+	entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
+			((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
 	if (args->rename) {
 		entry->flags |= XFS_ATTR_INCOMPLETE;
 		if ((args->blkno2 == args->blkno) &&
@@ -1881,6 +1899,9 @@
 			if (memcmp(args->name, (char *)name_loc->nameval,
 					     args->namelen) != 0)
 				continue;
+			if (((args->flags & ATTR_SECURE) != 0) !=
+			    ((entry->flags & XFS_ATTR_SECURE) != 0))
+				continue;
 			if (((args->flags & ATTR_ROOT) != 0) !=
 			    ((entry->flags & XFS_ATTR_ROOT) != 0))
 				continue;
@@ -1893,6 +1914,9 @@
 			if (memcmp(args->name, (char *)name_rmt->name,
 					     args->namelen) != 0)
 				continue;
+			if (((args->flags & ATTR_SECURE) != 0) !=
+			    ((entry->flags & XFS_ATTR_SECURE) != 0))
+				continue;
 			if (((args->flags & ATTR_ROOT) != 0) !=
 			    ((entry->flags & XFS_ATTR_ROOT) != 0))
 				continue;
@@ -2290,8 +2314,9 @@
 		    !(context->flags & ATTR_KERNFULLS))
 			continue;		/* skip non-matching entries */
 
-		namesp = (entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-			  &attr_user;
+		namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
+			((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
+			  &attr_user);
 
 		if (entry->flags & XFS_ATTR_LOCAL) {
 			name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_attr_leaf.h linux-2.4.25-rc1/fs/xfs/xfs_attr_leaf.h
--- linux-2.4.25-pre8/fs/xfs/xfs_attr_leaf.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_attr_leaf.h	2004-02-05 04:40:36.000000000 -0800
@@ -73,9 +73,9 @@
  * to work "forw"ard.  If none matches, continue with the "forw"ard leaf
  * nodes until the hash key changes or the attribute name is found.
  *
- * We store the fact that an attribute is a ROOT versus USER attribute in
+ * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
  * the leaf_entry.  The namespaces are independent only because we also look
- * at the root/user bit when we are looking for a matching attribute name.
+ * at the namespace bit when we are looking for a matching attribute name.
  *
  * We also store a "incomplete" bit in the leaf_entry.  It shows that an
  * attribute is in the middle of being created and should not be shown to
@@ -102,7 +102,7 @@
 	struct xfs_attr_leaf_entry {	/* sorted on key, not name */
 		xfs_dahash_t hashval;	/* hash value of name */
 		__uint16_t nameidx;	/* index into buffer of name/value */
-		__uint8_t flags;	/* LOCAL, ROOT and INCOMPLETE flags */
+		__uint8_t flags;	/* LOCAL/ROOT/SECURE/INCOMPLETE flag */
 		__uint8_t pad2;		/* unused pad byte */
 	} entries[1];			/* variable sized array */
 	struct xfs_attr_leaf_name_local {
@@ -130,9 +130,11 @@
  */
 #define	XFS_ATTR_LOCAL_BIT	0	/* attr is stored locally */
 #define	XFS_ATTR_ROOT_BIT	1	/* limit access to trusted attrs */
+#define	XFS_ATTR_SECURE_BIT	2	/* limit access to secure attrs */
 #define	XFS_ATTR_INCOMPLETE_BIT	7	/* attr in middle of create/delete */
 #define XFS_ATTR_LOCAL		(1 << XFS_ATTR_LOCAL_BIT)
 #define XFS_ATTR_ROOT		(1 << XFS_ATTR_ROOT_BIT)
+#define XFS_ATTR_SECURE		(1 << XFS_ATTR_SECURE_BIT)
 #define XFS_ATTR_INCOMPLETE	(1 << XFS_ATTR_INCOMPLETE_BIT)
 
 /*
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_behavior.c linux-2.4.25-rc1/fs/xfs/xfs_behavior.c
--- linux-2.4.25-pre8/fs/xfs/xfs_behavior.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_behavior.c	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ *
+ */
+#include "xfs.h"
+
+/*
+ * Source file used to associate/disassociate behaviors with virtualized
+ * objects.  See xfs_behavior.h for more information about behaviors, etc.
+ *
+ * The implementation is split between functions in this file and macros
+ * in xfs_behavior.h.
+ */
+
+/*
+ * Insert a new behavior descriptor into a behavior chain.
+ *
+ * The behavior chain is ordered based on the 'position' number which
+ * lives in the first field of the ops vector (higher numbers first).
+ *
+ * Attemps to insert duplicate ops result in an EINVAL return code.
+ * Otherwise, return 0 to indicate success.
+ */
+int
+bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
+{
+	bhv_desc_t	*curdesc, *prev;
+	int		position;
+
+	/*
+	 * Validate the position value of the new behavior.
+	 */
+	position = BHV_POSITION(bdp);
+	ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
+
+	/*
+	 * Find location to insert behavior.  Check for duplicates.
+	 */
+	prev = NULL;
+	for (curdesc = bhp->bh_first;
+	     curdesc != NULL;
+	     curdesc = curdesc->bd_next) {
+
+		/* Check for duplication. */
+		if (curdesc->bd_ops == bdp->bd_ops) {
+			ASSERT(0);
+			return EINVAL;
+		}
+
+		/* Find correct position */
+		if (position >= BHV_POSITION(curdesc)) {
+			ASSERT(position != BHV_POSITION(curdesc));
+			break;		/* found it */
+		}
+
+		prev = curdesc;
+	}
+
+	if (prev == NULL) {
+		/* insert at front of chain */
+		bdp->bd_next = bhp->bh_first;
+		bhp->bh_first = bdp;
+	} else {
+		/* insert after prev */
+		bdp->bd_next = prev->bd_next;
+		prev->bd_next = bdp;
+	}
+
+	return 0;
+}
+
+/*
+ * Remove a behavior descriptor from a position in a behavior chain;
+ * the postition is guaranteed not to be the first position.
+ * Should only be called by the bhv_remove() macro.
+ */
+void
+bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
+{
+	bhv_desc_t	*curdesc, *prev;
+
+	ASSERT(bhp->bh_first != NULL);
+	ASSERT(bhp->bh_first->bd_next != NULL);
+
+	prev = bhp->bh_first;
+	for (curdesc = bhp->bh_first->bd_next;
+	     curdesc != NULL;
+	     curdesc = curdesc->bd_next) {
+
+		if (curdesc == bdp)
+			break;		/* found it */
+		prev = curdesc;
+	}
+
+	ASSERT(curdesc == bdp);
+	prev->bd_next = bdp->bd_next;	/* remove from after prev */
+}
+
+/*
+ * Look for a specific ops vector on the specified behavior chain.
+ * Return the associated behavior descriptor.  Or NULL, if not found.
+ */
+bhv_desc_t *
+bhv_lookup(bhv_head_t *bhp, void *ops)
+{
+	bhv_desc_t	*curdesc;
+
+	for (curdesc = bhp->bh_first;
+	     curdesc != NULL;
+	     curdesc = curdesc->bd_next) {
+
+		if (curdesc->bd_ops == ops)
+			return curdesc;
+	}
+
+	return NULL;
+}
+
+/*
+ * Looks for the first behavior within a specified range of positions.
+ * Return the associated behavior descriptor.  Or NULL, if none found.
+ */
+bhv_desc_t *
+bhv_lookup_range(bhv_head_t *bhp, int low, int high)
+{
+	bhv_desc_t	*curdesc;
+
+	for (curdesc = bhp->bh_first;
+	     curdesc != NULL;
+	     curdesc = curdesc->bd_next) {
+
+		int	position = BHV_POSITION(curdesc);
+
+		if (position <= high) {
+			if (position >= low)
+				return curdesc;
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * Return the base behavior in the chain, or NULL if the chain
+ * is empty.
+ *
+ * The caller has not read locked the behavior chain, so acquire the
+ * lock before traversing the chain.
+ */
+bhv_desc_t *
+bhv_base(bhv_head_t *bhp)
+{
+	bhv_desc_t	*curdesc;
+
+	for (curdesc = bhp->bh_first;
+	     curdesc != NULL;
+	     curdesc = curdesc->bd_next) {
+
+		if (curdesc->bd_next == NULL) {
+			return curdesc;
+		}
+	}
+
+	return NULL;
+}
+
+void
+bhv_head_init(
+	bhv_head_t *bhp,
+	char *name)
+{
+	bhp->bh_first = NULL;
+}
+
+void
+bhv_insert_initial(
+	bhv_head_t *bhp,
+	bhv_desc_t *bdp)
+{
+	ASSERT(bhp->bh_first == NULL);
+	(bhp)->bh_first = bdp;
+}
+
+void
+bhv_head_destroy(
+	bhv_head_t *bhp)
+{
+	ASSERT(bhp->bh_first == NULL);
+}
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_behavior.h linux-2.4.25-rc1/fs/xfs/xfs_behavior.h
--- linux-2.4.25-pre8/fs/xfs/xfs_behavior.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_behavior.h	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_BEHAVIOR_H__
+#define __XFS_BEHAVIOR_H__
+
+/*
+ * Header file used to associate behaviors with virtualized objects.
+ *
+ * A virtualized object is an internal, virtualized representation of
+ * OS entities such as persistent files, processes, or sockets.  Examples
+ * of virtualized objects include vnodes, vprocs, and vsockets.  Often
+ * a virtualized object is referred to simply as an "object."
+ *
+ * A behavior is essentially an implementation layer associated with
+ * an object.  Multiple behaviors for an object are chained together,
+ * the order of chaining determining the order of invocation.  Each
+ * behavior of a given object implements the same set of interfaces
+ * (e.g., the VOP interfaces).
+ *
+ * Behaviors may be dynamically inserted into an object's behavior chain,
+ * such that the addition is transparent to consumers that already have
+ * references to the object.  Typically, a given behavior will be inserted
+ * at a particular location in the behavior chain.  Insertion of new
+ * behaviors is synchronized with operations-in-progress (oip's) so that
+ * the oip's always see a consistent view of the chain.
+ *
+ * The term "interpostion" is used to refer to the act of inserting
+ * a behavior such that it interposes on (i.e., is inserted in front
+ * of) a particular other behavior.  A key example of this is when a
+ * system implementing distributed single system image wishes to
+ * interpose a distribution layer (providing distributed coherency)
+ * in front of an object that is otherwise only accessed locally.
+ *
+ * Note that the traditional vnode/inode combination is simply a virtualized
+ * object that has exactly one associated behavior.
+ *
+ * Behavior synchronization is logic which is necessary under certain
+ * circumstances that there is no conflict between ongoing operations
+ * traversing the behavior chain and those dunamically modifying the
+ * behavior chain.  Because behavior synchronization adds extra overhead
+ * to virtual operation invocation, we want to restrict, as much as
+ * we can, the requirement for this extra code, to those situations
+ * in which it is truly necessary.
+ *
+ * Behavior synchronization is needed whenever there's at least one class
+ * of object in the system for which:
+ * 1) multiple behaviors for a given object are supported,
+ * -- AND --
+ * 2a) insertion of a new behavior can happen dynamically at any time during
+ *     the life of an active object,
+ *	-- AND --
+ *	3a) insertion of a new behavior needs to synchronize with existing
+ *	    ops-in-progress.
+ *	-- OR --
+ *	3b) multiple different behaviors can be dynamically inserted at
+ *	    any time during the life of an active object
+ *	-- OR --
+ *	3c) removal of a behavior can occur at any time during the life of
+ *	    an active object.
+ * -- OR --
+ * 2b) removal of a behavior can occur at any time during the life of an
+ *     active object
+ *
+ */
+
+struct bhv_head_lock;
+
+/*
+ * Behavior head.  Head of the chain of behaviors.
+ * Contained within each virtualized object data structure.
+ */
+typedef struct bhv_head {
+	struct bhv_desc *bh_first;	/* first behavior in chain */
+	struct bhv_head_lock *bh_lockp;	/* pointer to lock info struct */
+} bhv_head_t;
+
+/*
+ * Behavior descriptor.	 Descriptor associated with each behavior.
+ * Contained within the behavior's private data structure.
+ */
+typedef struct bhv_desc {
+	void		*bd_pdata;	/* private data for this behavior */
+	void		*bd_vobj;	/* virtual object associated with */
+	void		*bd_ops;	/* ops for this behavior */
+	struct bhv_desc *bd_next;	/* next behavior in chain */
+} bhv_desc_t;
+
+/*
+ * Behavior identity field.  A behavior's identity determines the position
+ * where it lives within a behavior chain, and it's always the first field
+ * of the behavior's ops vector. The optional id field further identifies the
+ * subsystem responsible for the behavior.
+ */
+typedef struct bhv_identity {
+	__u16	bi_id;		/* owning subsystem id */
+	__u16	bi_position;	/* position in chain */
+} bhv_identity_t;
+
+typedef bhv_identity_t bhv_position_t;
+
+#define BHV_IDENTITY_INIT(id,pos)	{id, pos}
+#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos)
+
+/*
+ * Define boundaries of position values.
+ */
+#define BHV_POSITION_INVALID	0	/* invalid position number */
+#define BHV_POSITION_BASE	1	/* base (last) implementation layer */
+#define BHV_POSITION_TOP	63	/* top (first) implementation layer */
+
+/*
+ * Plumbing macros.
+ */
+#define BHV_HEAD_FIRST(bhp)	(ASSERT((bhp)->bh_first), (bhp)->bh_first)
+#define BHV_NEXT(bdp)		(ASSERT((bdp)->bd_next), (bdp)->bd_next)
+#define BHV_NEXTNULL(bdp)	((bdp)->bd_next)
+#define BHV_VOBJ(bdp)		(ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj)
+#define BHV_VOBJNULL(bdp)	((bdp)->bd_vobj)
+#define BHV_PDATA(bdp)		(bdp)->bd_pdata
+#define BHV_OPS(bdp)		(bdp)->bd_ops
+#define BHV_IDENTITY(bdp)	((bhv_identity_t *)(bdp)->bd_ops)
+#define BHV_POSITION(bdp)	(BHV_IDENTITY(bdp)->bi_position)
+
+extern void bhv_head_init(bhv_head_t *, char *);
+extern void bhv_head_destroy(bhv_head_t *);
+extern int  bhv_insert(bhv_head_t *, bhv_desc_t *);
+extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
+
+/*
+ * Initialize a new behavior descriptor.
+ * Arguments:
+ *   bdp - pointer to behavior descriptor
+ *   pdata - pointer to behavior's private data
+ *   vobj - pointer to associated virtual object
+ *   ops - pointer to ops for this behavior
+ */
+#define bhv_desc_init(bdp, pdata, vobj, ops)		\
+ {							\
+	(bdp)->bd_pdata = pdata;			\
+	(bdp)->bd_vobj = vobj;				\
+	(bdp)->bd_ops = ops;				\
+	(bdp)->bd_next = NULL;				\
+ }
+
+/*
+ * Remove a behavior descriptor from a behavior chain.
+ */
+#define bhv_remove(bhp, bdp)				\
+ {							\
+	if ((bhp)->bh_first == (bdp)) {			\
+		/*					\
+		* Remove from front of chain.		\
+		* Atomic wrt oip's.			\
+		*/					\
+	       (bhp)->bh_first = (bdp)->bd_next;	\
+	} else {					\
+	       /* remove from non-front of chain */	\
+	       bhv_remove_not_first(bhp, bdp);		\
+	}						\
+	(bdp)->bd_vobj = NULL;				\
+ }
+
+/*
+ * Behavior module prototypes.
+ */
+extern void		bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
+extern bhv_desc_t *	bhv_lookup(bhv_head_t *bhp, void *ops);
+extern bhv_desc_t *	bhv_lookup_range(bhv_head_t *bhp, int low, int high);
+extern bhv_desc_t *	bhv_base(bhv_head_t *bhp);
+
+/* No bhv locking on Linux */
+#define bhv_lookup_unlocked	bhv_lookup
+#define bhv_base_unlocked	bhv_base
+
+#endif /* __XFS_BEHAVIOR_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_bmap_btree.c linux-2.4.25-rc1/fs/xfs/xfs_bmap_btree.c
--- linux-2.4.25-pre8/fs/xfs/xfs_bmap_btree.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_bmap_btree.c	2004-02-05 04:40:36.000000000 -0800
@@ -61,7 +61,7 @@
 #include "xfs_error.h"
 #include "xfs_quota.h"
 
-#ifdef DEBUG
+#if defined(XFS_BMBT_TRACE)
 ktrace_t	*xfs_bmbt_trace_buf;
 #endif
 
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_buf.h linux-2.4.25-rc1/fs/xfs/xfs_buf.h
--- linux-2.4.25-pre8/fs/xfs/xfs_buf.h	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_buf.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.	 Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-#ifndef __XFS_BUF_H__
-#define __XFS_BUF_H__
-
-/* These are just for xfs_syncsub... it sets an internal variable
- * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t
- */
-#define XFS_B_ASYNC		PBF_ASYNC
-#define XFS_B_DELWRI		PBF_DELWRI
-#define XFS_B_READ		PBF_READ
-#define XFS_B_WRITE		PBF_WRITE
-#define XFS_B_STALE		PBF_STALE
-
-#define XFS_BUF_TRYLOCK		PBF_TRYLOCK
-#define XFS_INCORE_TRYLOCK	PBF_TRYLOCK
-#define XFS_BUF_LOCK		PBF_LOCK
-#define XFS_BUF_MAPPED		PBF_MAPPED
-
-#define BUF_BUSY		PBF_DONT_BLOCK
-
-#define XFS_BUF_BFLAGS(x)	((x)->pb_flags)
-#define XFS_BUF_ZEROFLAGS(x)	\
-	((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI))
-
-#define XFS_BUF_STALE(x)	((x)->pb_flags |= XFS_B_STALE)
-#define XFS_BUF_UNSTALE(x)	((x)->pb_flags &= ~XFS_B_STALE)
-#define XFS_BUF_ISSTALE(x)	((x)->pb_flags & XFS_B_STALE)
-#define XFS_BUF_SUPER_STALE(x)	do {				\
-					XFS_BUF_STALE(x);	\
-					xfs_buf_undelay(x);	\
-					XFS_BUF_DONE(x);	\
-				} while (0)
-
-#define XFS_BUF_MANAGE		PBF_FS_MANAGED
-#define XFS_BUF_UNMANAGE(x)	((x)->pb_flags &= ~PBF_FS_MANAGED)
-
-static inline void xfs_buf_undelay(page_buf_t *pb)
-{
-	if (pb->pb_flags & PBF_DELWRI) {
-		if (pb->pb_list.next != &pb->pb_list) {
-			pagebuf_delwri_dequeue(pb);
-			pagebuf_rele(pb);
-		} else {
-			pb->pb_flags &= ~PBF_DELWRI;
-		}
-	}
-}
-
-#define XFS_BUF_DELAYWRITE(x)	 ((x)->pb_flags |= PBF_DELWRI)
-#define XFS_BUF_UNDELAYWRITE(x)	 xfs_buf_undelay(x)
-#define XFS_BUF_ISDELAYWRITE(x)	 ((x)->pb_flags & PBF_DELWRI)
-
-#define XFS_BUF_ERROR(x,no)	 pagebuf_ioerror(x,no)
-#define XFS_BUF_GETERROR(x)	 pagebuf_geterror(x)
-#define XFS_BUF_ISERROR(x)	 (pagebuf_geterror(x)?1:0)
-
-#define XFS_BUF_DONE(x)		 ((x)->pb_flags &= ~(PBF_PARTIAL|PBF_NONE))
-#define XFS_BUF_UNDONE(x)	 ((x)->pb_flags |= PBF_PARTIAL|PBF_NONE)
-#define XFS_BUF_ISDONE(x)	 (!(PBF_NOT_DONE(x)))
-
-#define XFS_BUF_BUSY(x)		 ((x)->pb_flags |= PBF_FORCEIO)
-#define XFS_BUF_UNBUSY(x)	 ((x)->pb_flags &= ~PBF_FORCEIO)
-#define XFS_BUF_ISBUSY(x)	 (1)
-
-#define XFS_BUF_ASYNC(x)	 ((x)->pb_flags |= PBF_ASYNC)
-#define XFS_BUF_UNASYNC(x)	 ((x)->pb_flags &= ~PBF_ASYNC)
-#define XFS_BUF_ISASYNC(x)	 ((x)->pb_flags & PBF_ASYNC)
-
-#define XFS_BUF_FLUSH(x)	 ((x)->pb_flags |= PBF_FLUSH)
-#define XFS_BUF_UNFLUSH(x)	 ((x)->pb_flags &= ~PBF_FLUSH)
-#define XFS_BUF_ISFLUSH(x)	 ((x)->pb_flags & PBF_FLUSH)
-
-#define XFS_BUF_SHUT(x)		 printk("XFS_BUF_SHUT not implemented yet\n")
-#define XFS_BUF_UNSHUT(x)	 printk("XFS_BUF_UNSHUT not implemented yet\n")
-#define XFS_BUF_ISSHUT(x)	 (0)
-
-#define XFS_BUF_HOLD(x)		pagebuf_hold(x)
-#define XFS_BUF_READ(x)		((x)->pb_flags |= PBF_READ)
-#define XFS_BUF_UNREAD(x)	((x)->pb_flags &= ~PBF_READ)
-#define XFS_BUF_ISREAD(x)	((x)->pb_flags & PBF_READ)
-
-#define XFS_BUF_WRITE(x)	((x)->pb_flags |= PBF_WRITE)
-#define XFS_BUF_UNWRITE(x)	((x)->pb_flags &= ~PBF_WRITE)
-#define XFS_BUF_ISWRITE(x)	((x)->pb_flags & PBF_WRITE)
-
-#define XFS_BUF_ISUNINITIAL(x)	 (0)
-#define XFS_BUF_UNUNINITIAL(x)	 (0)
-
-#define XFS_BUF_BP_ISMAPPED(bp)	 1
-
-typedef struct page_buf_s xfs_buf_t;
-#define xfs_buf page_buf_s
-
-typedef struct pb_target xfs_buftarg_t;
-#define xfs_buftarg pb_target
-
-#define XFS_BUF_DATAIO(x)	((x)->pb_flags |= PBF_FS_DATAIOD)
-#define XFS_BUF_UNDATAIO(x)	((x)->pb_flags &= ~PBF_FS_DATAIOD)
-
-#define XFS_BUF_IODONE_FUNC(buf)	(buf)->pb_iodone
-#define XFS_BUF_SET_IODONE_FUNC(buf, func)	\
-			(buf)->pb_iodone = (func)
-#define XFS_BUF_CLR_IODONE_FUNC(buf)		\
-			(buf)->pb_iodone = NULL
-#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func)	\
-			(buf)->pb_strat = (func)
-#define XFS_BUF_CLR_BDSTRAT_FUNC(buf)		\
-			(buf)->pb_strat = NULL
-
-#define XFS_BUF_FSPRIVATE(buf, type)		\
-			((type)(buf)->pb_fspriv)
-#define XFS_BUF_SET_FSPRIVATE(buf, value)	\
-			(buf)->pb_fspriv = (void *)(value)
-#define XFS_BUF_FSPRIVATE2(buf, type)		\
-			((type)(buf)->pb_fspriv2)
-#define XFS_BUF_SET_FSPRIVATE2(buf, value)	\
-			(buf)->pb_fspriv2 = (void *)(value)
-#define XFS_BUF_FSPRIVATE3(buf, type)		\
-			((type)(buf)->pb_fspriv3)
-#define XFS_BUF_SET_FSPRIVATE3(buf, value)	\
-			(buf)->pb_fspriv3  = (void *)(value)
-#define XFS_BUF_SET_START(buf)
-
-#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \
-			(buf)->pb_relse = (value)
-
-#define XFS_BUF_PTR(bp)		(xfs_caddr_t)((bp)->pb_addr)
-
-extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset)
-{
-	if (bp->pb_flags & PBF_MAPPED)
-		return XFS_BUF_PTR(bp) + offset;
-	return (xfs_caddr_t) pagebuf_offset(bp, offset);
-}
-
-#define XFS_BUF_SET_PTR(bp, val, count)		\
-				pagebuf_associate_memory(bp, val, count)
-#define XFS_BUF_ADDR(bp)	((bp)->pb_bn)
-#define XFS_BUF_SET_ADDR(bp, blk)		\
-			((bp)->pb_bn = (page_buf_daddr_t)(blk))
-#define XFS_BUF_OFFSET(bp)	((bp)->pb_file_offset)
-#define XFS_BUF_SET_OFFSET(bp, off)		\
-			((bp)->pb_file_offset = (off))
-#define XFS_BUF_COUNT(bp)	((bp)->pb_count_desired)
-#define XFS_BUF_SET_COUNT(bp, cnt)		\
-			((bp)->pb_count_desired = (cnt))
-#define XFS_BUF_SIZE(bp)	((bp)->pb_buffer_length)
-#define XFS_BUF_SET_SIZE(bp, cnt)		\
-			((bp)->pb_buffer_length = (cnt))
-#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
-#define XFS_BUF_SET_VTYPE(bp, type)
-#define XFS_BUF_SET_REF(bp, ref)
-
-#define XFS_BUF_ISPINNED(bp)	pagebuf_ispin(bp)
-
-#define XFS_BUF_VALUSEMA(bp)	pagebuf_lock_value(bp)
-#define XFS_BUF_CPSEMA(bp)	(pagebuf_cond_lock(bp) == 0)
-#define XFS_BUF_VSEMA(bp)	pagebuf_unlock(bp)
-#define XFS_BUF_PSEMA(bp,x)	pagebuf_lock(bp)
-#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema);
-
-/* setup the buffer target from a buftarg structure */
-#define XFS_BUF_SET_TARGET(bp, target)	\
-		(bp)->pb_target = (target)
-#define XFS_BUF_TARGET(bp)	((bp)->pb_target)
-#define XFS_BUFTARG_NAME(target)	\
-		pagebuf_target_name(target)
-
-#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
-#define XFS_BUF_SET_VTYPE(bp, type)
-#define XFS_BUF_SET_REF(bp, ref)
-
-#define xfs_buf_read(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE)
-#define xfs_buf_get(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE)
-
-#define xfs_buf_read_flags(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_READ | PBF_MAPPABLE | flags)
-#define xfs_buf_get_flags(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_MAPPABLE | flags)
-
-static inline int	xfs_bawrite(void *mp, page_buf_t *bp)
-{
-	bp->pb_fspriv3 = mp;
-	bp->pb_strat = xfs_bdstrat_cb;
-	xfs_buf_undelay(bp);
-	return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | PBF_RUN_QUEUES);
-}
-
-static inline void	xfs_buf_relse(page_buf_t *bp)
-{
-	if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse)
-		pagebuf_unlock(bp);
-	pagebuf_rele(bp);
-}
-
-#define xfs_bpin(bp)		pagebuf_pin(bp)
-#define xfs_bunpin(bp)		pagebuf_unpin(bp)
-
-#define xfs_buftrace(id, bp)	\
-	    pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0))
-
-#define xfs_biodone(pb)		    \
-	    pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 0)
-
-#define xfs_incore(buftarg,blkno,len,lockit) \
-	    pagebuf_find(buftarg, blkno ,len, lockit)
-
-
-#define xfs_biomove(pb, off, len, data, rw) \
-	    pagebuf_iomove((pb), (off), (len), (data), \
-		((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ)
-
-#define xfs_biozero(pb, off, len) \
-	    pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO)
-
-
-static inline int	XFS_bwrite(page_buf_t *pb)
-{
-	int	iowait = (pb->pb_flags & PBF_ASYNC) == 0;
-	int	error = 0;
-
-	pb->pb_flags |= PBF_SYNC;
-	if (!iowait)
-		pb->pb_flags |= PBF_RUN_QUEUES;
-
-	xfs_buf_undelay(pb);
-	pagebuf_iostrategy(pb);
-	if (iowait) {
-		error = pagebuf_iowait(pb);
-		xfs_buf_relse(pb);
-	}
-	return error;
-}
-
-#define XFS_bdwrite(pb)		     \
-	    pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC)
-
-static inline int xfs_bdwrite(void *mp, page_buf_t *bp)
-{
-	bp->pb_strat = xfs_bdstrat_cb;
-	bp->pb_fspriv3 = mp;
-
-	return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC);
-}
-
-#define XFS_bdstrat(bp) pagebuf_iorequest(bp)
-
-#define xfs_iowait(pb)	pagebuf_iowait(pb)
-
-
-/*
- * Go through all incore buffers, and release buffers
- * if they belong to the given device. This is used in
- * filesystem error handling to preserve the consistency
- * of its metadata.
- */
-
-#define xfs_binval(buftarg)	xfs_flush_buftarg(buftarg)
-
-#define XFS_bflush(buftarg)	xfs_flush_buftarg(buftarg)
-
-#define xfs_incore_relse(buftarg,delwri_only,wait)	\
-	xfs_relse_buftarg(buftarg)
-
-#define xfs_baread(target, rablkno, ralen)  \
-	pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK)
-
-#define xfs_buf_get_empty(len, target)	pagebuf_get_empty((len), (target))
-#define xfs_buf_get_noaddr(len, target)	pagebuf_get_no_daddr((len), (target))
-#define xfs_buf_free(bp)		pagebuf_free(bp)
-
-#endif	/* __XFS_BUF_H__ */
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_dir.c linux-2.4.25-rc1/fs/xfs/xfs_dir.c
--- linux-2.4.25-pre8/fs/xfs/xfs_dir.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_dir.c	2004-02-05 04:40:36.000000000 -0800
@@ -162,7 +162,7 @@
 					     xfs_dir_put_t put);
 STATIC int xfs_dir_node_replace(xfs_da_args_t *args);
 
-#if defined(DEBUG)
+#if defined(XFS_DIR_TRACE)
 ktrace_t *xfs_dir_trace_buf;
 #endif
 
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_dir2_trace.c linux-2.4.25-rc1/fs/xfs/xfs_dir2_trace.c
--- linux-2.4.25-pre8/fs/xfs/xfs_dir2_trace.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_dir2_trace.c	2004-02-05 04:40:36.000000000 -0800
@@ -49,11 +49,9 @@
 #include "xfs_da_btree.h"
 #include "xfs_dir2_trace.h"
 
-#ifdef DEBUG
+#ifdef XFS_DIR2_TRACE
 ktrace_t	*xfs_dir2_trace_buf;
-#endif /* DEBUG */
 
-#ifdef XFS_DIR2_TRACE
 /*
  * Enter something in the trace buffers.
  */
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_iomap.c linux-2.4.25-rc1/fs/xfs/xfs_iomap.c
--- linux-2.4.25-pre8/fs/xfs/xfs_iomap.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_iomap.c	2004-02-05 04:40:36.000000000 -0800
@@ -0,0 +1,795 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.	 Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include "xfs.h"
+
+#include "xfs_fs.h"
+#include "xfs_inum.h"
+#include "xfs_log.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dir.h"
+#include "xfs_dir2.h"
+#include "xfs_alloc.h"
+#include "xfs_dmapi.h"
+#include "xfs_quota.h"
+#include "xfs_mount.h"
+#include "xfs_alloc_btree.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_ialloc_btree.h"
+#include "xfs_btree.h"
+#include "xfs_ialloc.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir_sf.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_bmap.h"
+#include "xfs_bit.h"
+#include "xfs_rtalloc.h"
+#include "xfs_error.h"
+#include "xfs_itable.h"
+#include "xfs_rw.h"
+#include "xfs_acl.h"
+#include "xfs_cap.h"
+#include "xfs_mac.h"
+#include "xfs_attr.h"
+#include "xfs_buf_item.h"
+#include "xfs_trans_space.h"
+#include "xfs_utils.h"
+#include "xfs_iomap.h"
+
+#define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
+						<< mp->m_writeio_log)
+#define XFS_STRAT_WRITE_IMAPS	2
+#define XFS_WRITE_IMAPS		XFS_BMAP_MAX_NMAP
+
+STATIC int
+xfs_imap_to_bmap(
+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	xfs_bmbt_irec_t *imap,
+	xfs_iomap_t	*iomapp,
+	int		imaps,			/* Number of imap entries */
+	int		iomaps,			/* Number of iomap entries */
+	int		flags)
+{
+	xfs_mount_t	*mp;
+	xfs_fsize_t	nisize;
+	int		pbm;
+	xfs_fsblock_t	start_block;
+
+	mp = io->io_mount;
+	nisize = XFS_SIZE(mp, io);
+	if (io->io_new_size > nisize)
+		nisize = io->io_new_size;
+
+	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
+		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
+			mp->m_rtdev_targp : mp->m_ddev_targp;
+		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
+		iomapp->iomap_delta = offset - iomapp->iomap_offset;
+		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
+		iomapp->iomap_flags = flags;
+
+		start_block = imap->br_startblock;
+		if (start_block == HOLESTARTBLOCK) {
+			iomapp->iomap_bn = IOMAP_DADDR_NULL;
+			iomapp->iomap_flags = IOMAP_HOLE;
+		} else if (start_block == DELAYSTARTBLOCK) {
+			iomapp->iomap_bn = IOMAP_DADDR_NULL;
+			iomapp->iomap_flags = IOMAP_DELAY;
+		} else {
+			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
+			if (ISUNWRITTEN(imap))
+				iomapp->iomap_flags |= IOMAP_UNWRITTEN;
+		}
+
+		if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) {
+			iomapp->iomap_flags |= IOMAP_EOF;
+		}
+
+		offset += iomapp->iomap_bsize - iomapp->iomap_delta;
+	}
+	return pbm;	/* Return the number filled */
+}
+
+int
+xfs_iomap(
+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	ssize_t		count,
+	int		flags,
+	xfs_iomap_t	*iomapp,
+	int		*niomaps)
+{
+	xfs_mount_t	*mp = io->io_mount;
+	xfs_fileoff_t	offset_fsb, end_fsb;
+	int		error = 0;
+	int		lockmode = 0;
+	xfs_bmbt_irec_t	imap;
+	int		nimaps = 1;
+	int		bmapi_flags = 0;
+	int		iomap_flags = 0;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	switch (flags &
+		(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
+		 BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
+	case BMAPI_READ:
+		lockmode = XFS_LCK_MAP_SHARED(mp, io);
+		bmapi_flags = XFS_BMAPI_ENTIRE;
+		if (flags & BMAPI_IGNSTATE)
+			bmapi_flags |= XFS_BMAPI_IGSTATE;
+		break;
+	case BMAPI_WRITE:
+		lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
+		bmapi_flags = 0;
+		XFS_ILOCK(mp, io, lockmode);
+		break;
+	case BMAPI_ALLOCATE:
+		lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
+		bmapi_flags = XFS_BMAPI_ENTIRE;
+		/* Attempt non-blocking lock */
+		if (flags & BMAPI_TRYLOCK) {
+			if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))
+				return XFS_ERROR(EAGAIN);
+		} else {
+			XFS_ILOCK(mp, io, lockmode);
+		}
+		break;
+	case BMAPI_UNWRITTEN:
+		goto phase2;
+	case BMAPI_DEVICE:
+		lockmode = XFS_LCK_MAP_SHARED(mp, io);
+		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
+			mp->m_rtdev_targp : mp->m_ddev_targp;
+		error = 0;
+		*niomaps = 1;
+		goto out;
+	default:
+		BUG();
+	}
+
+	ASSERT(offset <= mp->m_maxioffset);
+	if ((xfs_fsize_t)offset + count > mp->m_maxioffset)
+		count = mp->m_maxioffset - offset;
+	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
+	offset_fsb = XFS_B_TO_FSBT(mp, offset);
+
+	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
+			(xfs_filblks_t)(end_fsb - offset_fsb),
+			bmapi_flags,  NULL, 0, &imap,
+			&nimaps, NULL);
+
+	if (error)
+		goto out;
+
+phase2:
+	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
+	case BMAPI_WRITE:
+		/* If we found an extent, return it */
+		if (nimaps && (imap.br_startblock != HOLESTARTBLOCK))
+			break;
+
+		if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
+			error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
+					count, flags, &imap, &nimaps, nimaps);
+		} else {
+			error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
+					flags, &imap, &nimaps);
+		}
+		iomap_flags = IOMAP_NEW;
+		break;
+	case BMAPI_ALLOCATE:
+		/* If we found an extent, return it */
+		XFS_IUNLOCK(mp, io, lockmode);
+		lockmode = 0;
+
+		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock))
+			break;
+
+		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
+		break;
+	case BMAPI_UNWRITTEN:
+		lockmode = 0;
+		error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count);
+		nimaps = 0;
+		break;
+	}
+
+	if (nimaps) {
+		*niomaps = xfs_imap_to_bmap(io, offset, &imap,
+					    iomapp, nimaps, *niomaps, iomap_flags);
+	} else if (niomaps) {
+		*niomaps = 0;
+	}
+
+out:
+	if (lockmode)
+		XFS_IUNLOCK(mp, io, lockmode);
+	return XFS_ERROR(error);
+}
+
+STATIC int
+xfs_flush_space(
+	xfs_inode_t	*ip,
+	int		*fsynced,
+	int		*ioflags)
+{
+	switch (*fsynced) {
+	case 0:
+		if (ip->i_delayed_blks) {
+			xfs_iunlock(ip, XFS_ILOCK_EXCL);
+			xfs_flush_inode(ip);
+			xfs_ilock(ip, XFS_ILOCK_EXCL);
+			*fsynced = 1;
+		} else {
+			*ioflags |= BMAPI_SYNC;
+			*fsynced = 2;
+		}
+		return 0;
+	case 1:
+		*fsynced = 2;
+		*ioflags |= BMAPI_SYNC;
+		return 0;
+	case 2:
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+		xfs_flush_device(ip);
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		*fsynced = 3;
+		return 0;
+	}
+	return 1;
+}
+
+int
+xfs_iomap_write_direct(
+	xfs_inode_t	*ip,
+	loff_t		offset,
+	size_t		count,
+	int		flags,
+	xfs_bmbt_irec_t *ret_imap,
+	int		*nmaps,
+	int		found)
+{
+	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t	*io = &ip->i_iocore;
+	xfs_fileoff_t	offset_fsb;
+	xfs_fileoff_t	last_fsb;
+	xfs_filblks_t	count_fsb;
+	xfs_fsize_t	isize;
+	xfs_fsblock_t	firstfsb;
+	int		nimaps, maps;
+	int		error;
+	int		bmapi_flag;
+	int		rt;
+	xfs_trans_t	*tp;
+	xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
+	xfs_bmap_free_t free_list;
+	int		aeof;
+	xfs_filblks_t	datablocks;
+	int		committed;
+	int		numrtextents;
+	uint		resblks;
+
+	/*
+	 * Make sure that the dquots are there. This doesn't hold
+	 * the ilock across a disk read.
+	 */
+
+	error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
+	if (error)
+		return XFS_ERROR(error);
+
+	maps = min(XFS_WRITE_IMAPS, *nmaps);
+	nimaps = maps;
+
+	isize = ip->i_d.di_size;
+	aeof = (offset + count) > isize;
+
+	if (io->io_new_size > isize)
+		isize = io->io_new_size;
+
+	offset_fsb = XFS_B_TO_FSBT(mp, offset);
+	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
+	count_fsb = last_fsb - offset_fsb;
+	if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) {
+		xfs_fileoff_t	map_last_fsb;
+
+		map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
+
+		if (map_last_fsb < last_fsb) {
+			last_fsb = map_last_fsb;
+			count_fsb = last_fsb - offset_fsb;
+		}
+		ASSERT(count_fsb > 0);
+	}
+
+	/*
+	 * determine if reserving space on
+	 * the data or realtime partition.
+	 */
+	if ((rt = XFS_IS_REALTIME_INODE(ip))) {
+		int	sbrtextsize, iprtextsize;
+
+		sbrtextsize = mp->m_sb.sb_rextsize;
+		iprtextsize =
+			ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize;
+		numrtextents = (count_fsb + iprtextsize - 1);
+		do_div(numrtextents, sbrtextsize);
+		datablocks = 0;
+	} else {
+		datablocks = count_fsb;
+		numrtextents = 0;
+	}
+
+	/*
+	 * allocate and setup the transaction
+	 */
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
+
+	resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
+
+	error = xfs_trans_reserve(tp, resblks,
+			XFS_WRITE_LOG_RES(mp), numrtextents,
+			XFS_TRANS_PERM_LOG_RES,
+			XFS_WRITE_LOG_COUNT);
+
+	/*
+	 * check for running out of space
+	 */
+	if (error)
+		/*
+		 * Free the transaction structure.
+		 */
+		xfs_trans_cancel(tp, 0);
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+	if (error)
+		goto error_out; /* Don't return in above if .. trans ..,
+					need lock to return */
+
+	if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
+		error = (EDQUOT);
+		goto error1;
+	}
+	nimaps = 1;
+
+	bmapi_flag = XFS_BMAPI_WRITE;
+	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+	xfs_trans_ihold(tp, ip);
+
+	if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt))
+		bmapi_flag |= XFS_BMAPI_PREALLOC;
+
+	/*
+	 * issue the bmapi() call to allocate the blocks
+	 */
+	XFS_BMAP_INIT(&free_list, &firstfsb);
+	imapp = &imap[0];
+	error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
+		bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
+	if (error) {
+		goto error0;
+	}
+
+	/*
+	 * complete the transaction
+	 */
+
+	error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
+	if (error) {
+		goto error0;
+	}
+
+	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+	if (error) {
+		goto error_out;
+	}
+
+	/* copy any maps to caller's array and return any error. */
+	if (nimaps == 0) {
+		error = (ENOSPC);
+		goto error_out;
+	}
+
+	*ret_imap = imap[0];
+	*nmaps = 1;
+	return 0;
+
+ error0:	/* Cancel bmap, unlock inode, and cancel trans */
+	xfs_bmap_cancel(&free_list);
+
+ error1:	/* Just cancel transaction */
+	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
+	*nmaps = 0;	/* nothing set-up here */
+
+error_out:
+	return XFS_ERROR(error);
+}
+
+int
+xfs_iomap_write_delay(
+	xfs_inode_t	*ip,
+	loff_t		offset,
+	size_t		count,
+	int		ioflag,
+	xfs_bmbt_irec_t *ret_imap,
+	int		*nmaps)
+{
+	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t	*io = &ip->i_iocore;
+	xfs_fileoff_t	offset_fsb;
+	xfs_fileoff_t	last_fsb;
+	xfs_fsize_t	isize;
+	xfs_fsblock_t	firstblock;
+	int		nimaps;
+	int		error;
+	xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
+	int		aeof;
+	int		fsynced = 0;
+
+	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
+
+	/*
+	 * Make sure that the dquots are there. This doesn't hold
+	 * the ilock across a disk read.
+	 */
+
+	error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
+	if (error)
+		return XFS_ERROR(error);
+
+retry:
+	isize = ip->i_d.di_size;
+	if (io->io_new_size > isize) {
+		isize = io->io_new_size;
+	}
+
+	aeof = 0;
+	offset_fsb = XFS_B_TO_FSBT(mp, offset);
+	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
+	/*
+	 * If the caller is doing a write at the end of the file,
+	 * then extend the allocation (and the buffer used for the write)
+	 * out to the file system's write iosize.  We clean up any extra
+	 * space left over when the file is closed in xfs_inactive().
+	 *
+	 * We don't bother with this for sync writes, because we need
+	 * to minimize the amount we write for good performance.
+	 */
+	if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) {
+		xfs_off_t	aligned_offset;
+		unsigned int	iosize;
+		xfs_fileoff_t	ioalign;
+
+		iosize = mp->m_writeio_blocks;
+		aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1));
+		ioalign = XFS_B_TO_FSBT(mp, aligned_offset);
+		last_fsb = ioalign + iosize;
+		aeof = 1;
+	}
+
+	nimaps = XFS_WRITE_IMAPS;
+	firstblock = NULLFSBLOCK;
+
+	/*
+	 * roundup the allocation request to m_dalign boundary if file size
+	 * is greater that 512K and we are allocating past the allocation eof
+	 */
+	if (mp->m_dalign && (isize >= mp->m_dalign) && aeof) {
+		int eof;
+		xfs_fileoff_t new_last_fsb;
+		new_last_fsb = roundup_64(last_fsb, mp->m_dalign);
+		error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof);
+		if (error) {
+			return error;
+		}
+		if (eof) {
+			last_fsb = new_last_fsb;
+		}
+	}
+
+	error = xfs_bmapi(NULL, ip, offset_fsb,
+			  (xfs_filblks_t)(last_fsb - offset_fsb),
+			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
+			  XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
+			  &nimaps, NULL);
+	/*
+	 * This can be EDQUOT, if nimaps == 0
+	 */
+	if (error && (error != ENOSPC)) {
+		return XFS_ERROR(error);
+	}
+	/*
+	 * If bmapi returned us nothing, and if we didn't get back EDQUOT,
+	 * then we must have run out of space.
+	 */
+
+	if (nimaps == 0) {
+		if (xfs_flush_space(ip, &fsynced, &ioflag))
+			return XFS_ERROR(ENOSPC);
+
+		error = 0;
+		goto retry;
+	}
+
+	*ret_imap = imap[0];
+	*nmaps = 1;
+	return 0;
+}
+
+/*
+ * Pass in a delayed allocate extent, convert it to real extents;
+ * return to the caller the extent we create which maps on top of
+ * the originating callers request.
+ *
+ * Called without a lock on the inode.
+ */
+int
+xfs_iomap_write_allocate(
+	xfs_inode_t	*ip,
+	xfs_bmbt_irec_t *map,
+	int		*retmap)
+{
+	xfs_mount_t	*mp = ip->i_mount;
+	xfs_fileoff_t	offset_fsb, last_block;
+	xfs_fileoff_t	end_fsb, map_start_fsb;
+	xfs_fsblock_t	first_block;
+	xfs_bmap_free_t	free_list;
+	xfs_filblks_t	count_fsb;
+	xfs_bmbt_irec_t	imap[XFS_STRAT_WRITE_IMAPS];
+	xfs_trans_t	*tp;
+	int		i, nimaps, committed;
+	int		error = 0;
+	int		nres;
+
+	*retmap = 0;
+
+	/*
+	 * Make sure that the dquots are there.
+	 */
+
+	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
+		return XFS_ERROR(error);
+
+	offset_fsb = map->br_startoff;
+	count_fsb = map->br_blockcount;
+	map_start_fsb = offset_fsb;
+
+	XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
+
+	while (count_fsb != 0) {
+		/*
+		 * Set up a transaction with which to allocate the
+		 * backing store for the file.  Do allocations in a
+		 * loop until we get some space in the range we are
+		 * interested in.  The other space that might be allocated
+		 * is in the delayed allocation extent on which we sit
+		 * but before our buffer starts.
+		 */
+
+		nimaps = 0;
+		while (nimaps == 0) {
+			tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
+			nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
+			error = xfs_trans_reserve(tp, nres,
+					XFS_WRITE_LOG_RES(mp),
+					0, XFS_TRANS_PERM_LOG_RES,
+					XFS_WRITE_LOG_COUNT);
+
+			if (error == ENOSPC) {
+				error = xfs_trans_reserve(tp, 0,
+						XFS_WRITE_LOG_RES(mp),
+						0,
+						XFS_TRANS_PERM_LOG_RES,
+						XFS_WRITE_LOG_COUNT);
+			}
+			if (error) {
+				xfs_trans_cancel(tp, 0);
+				return XFS_ERROR(error);
+			}
+			xfs_ilock(ip, XFS_ILOCK_EXCL);
+			xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+			xfs_trans_ihold(tp, ip);
+
+			XFS_BMAP_INIT(&free_list, &first_block);
+
+			nimaps = XFS_STRAT_WRITE_IMAPS;
+			/*
+			 * Ensure we don't go beyond eof - it is possible
+			 * the extents changed since we did the read call,
+			 * we dropped the ilock in the interim.
+			 */
+
+			end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size);
+			xfs_bmap_last_offset(NULL, ip, &last_block,
+				XFS_DATA_FORK);
+			last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
+			if ((map_start_fsb + count_fsb) > last_block) {
+				count_fsb = last_block - map_start_fsb;
+				if (count_fsb == 0) {
+					error = EAGAIN;
+					goto trans_cancel;
+				}
+			}
+
+			/* Go get the actual blocks */
+			error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
+					XFS_BMAPI_WRITE, &first_block, 1,
+					imap, &nimaps, &free_list);
+
+			if (error)
+				goto trans_cancel;
+
+			error = xfs_bmap_finish(&tp, &free_list,
+					first_block, &committed);
+
+			if (error)
+				goto trans_cancel;
+
+			error = xfs_trans_commit(tp,
+					XFS_TRANS_RELEASE_LOG_RES, NULL);
+
+			if (error)
+				goto error0;
+
+			xfs_iunlock(ip, XFS_ILOCK_EXCL);
+		}
+
+		/*
+		 * See if we were able to allocate an extent that
+		 * covers at least part of the callers request
+		 */
+
+		for (i = 0; i < nimaps; i++) {
+			if ((map->br_startoff >= imap[i].br_startoff) &&
+			    (map->br_startoff < (imap[i].br_startoff +
+						 imap[i].br_blockcount))) {
+				*map = imap[i];
+				*retmap = 1;
+				XFS_STATS_INC(xs_xstrat_quick);
+				return 0;
+			}
+			count_fsb -= imap[i].br_blockcount;
+		}
+
+		/* So far we have not mapped the requested part of the
+		 * file, just surrounding data, try again.
+		 */
+		nimaps--;
+		offset_fsb = imap[nimaps].br_startoff +
+			     imap[nimaps].br_blockcount;
+		map_start_fsb = offset_fsb;
+	}
+
+trans_cancel:
+	xfs_bmap_cancel(&free_list);
+	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
+error0:
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	return XFS_ERROR(error);
+}
+
+int
+xfs_iomap_write_unwritten(
+	xfs_inode_t	*ip,
+	loff_t		offset,
+	size_t		count)
+{
+	xfs_mount_t	*mp = ip->i_mount;
+	xfs_trans_t	*tp;
+	xfs_fileoff_t	offset_fsb;
+	xfs_filblks_t	count_fsb;
+	xfs_filblks_t	numblks_fsb;
+	xfs_bmbt_irec_t	imap;
+	int		committed;
+	int		error;
+	int		nres;
+	int		nimaps;
+	xfs_fsblock_t	firstfsb;
+	xfs_bmap_free_t	free_list;
+
+	offset_fsb = XFS_B_TO_FSBT(mp, offset);
+	count_fsb = XFS_B_TO_FSB(mp, count);
+
+	do {
+		nres = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+
+		/*
+		 * set up a transaction to convert the range of extents
+		 * from unwritten to real. Do allocations in a loop until
+		 * we have covered the range passed in.
+		 */
+
+		tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
+		error = xfs_trans_reserve(tp, nres,
+				XFS_WRITE_LOG_RES(mp), 0,
+				XFS_TRANS_PERM_LOG_RES,
+				XFS_WRITE_LOG_COUNT);
+		if (error) {
+			xfs_trans_cancel(tp, 0);
+			goto error0;
+		}
+
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+		xfs_trans_ihold(tp, ip);
+
+		/*
+		 * Modify the unwritten extent state of the buffer.
+		 */
+		XFS_BMAP_INIT(&free_list, &firstfsb);
+		nimaps = 1;
+		error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
+				  XFS_BMAPI_WRITE, &firstfsb,
+				  1, &imap, &nimaps, &free_list);
+		if (error)
+			goto error_on_bmapi_transaction;
+
+		error = xfs_bmap_finish(&(tp), &(free_list),
+				firstfsb, &committed);
+		if (error)
+			goto error_on_bmapi_transaction;
+
+		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+		if (error)
+			goto error0;
+
+		if ((numblks_fsb = imap.br_blockcount) == 0) {
+			/*
+			 * The numblks_fsb value should always get
+			 * smaller, otherwise the loop is stuck.
+			 */
+			ASSERT(imap.br_blockcount);
+			break;
+		}
+		offset_fsb += numblks_fsb;
+		count_fsb -= numblks_fsb;
+	} while (count_fsb > 0);
+
+	return 0;
+
+error_on_bmapi_transaction:
+	xfs_bmap_cancel(&free_list);
+	xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT));
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+error0:
+	return XFS_ERROR(error);
+}
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_log_recover.c linux-2.4.25-rc1/fs/xfs/xfs_log_recover.c
--- linux-2.4.25-pre8/fs/xfs/xfs_log_recover.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_log_recover.c	2004-02-05 04:40:36.000000000 -0800
@@ -1531,7 +1531,7 @@
 	xlog_recover_item_t	*first_item, *itemq, *itemq_next;
 	xfs_buf_log_format_t	*buf_f;
 	xfs_buf_log_format_v1_t	*obuf_f;
-	ushort			flags;
+	ushort			flags = 0;
 
 	first_item = itemq = trans->r_itemq;
 	trans->r_itemq = NULL;
diff -urN linux-2.4.25-pre8/fs/xfs/xfs_vfsops.c linux-2.4.25-rc1/fs/xfs/xfs_vfsops.c
--- linux-2.4.25-pre8/fs/xfs/xfs_vfsops.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfs_vfsops.c	2004-02-05 04:40:36.000000000 -0800
@@ -171,6 +171,25 @@
 	xfs_sysctl_unregister();
 	xfs_refcache_destroy();
 
+#ifdef XFS_DIR2_TRACE
+	ktrace_free(xfs_dir2_trace_buf);
+#endif
+#ifdef XFS_ATTR_TRACE
+	ktrace_free(xfs_attr_trace_buf);
+#endif
+#ifdef XFS_DIR_TRACE
+	ktrace_free(xfs_dir_trace_buf);
+#endif
+#ifdef XFS_BMBT_TRACE
+	ktrace_free(xfs_bmbt_trace_buf);
+#endif
+#ifdef XFS_BMAP_TRACE
+	ktrace_free(xfs_bmap_trace_buf);
+#endif
+#ifdef XFS_ALLOC_TRACE
+	ktrace_free(xfs_alloc_trace_buf);
+#endif
+
 	kmem_cache_destroy(xfs_bmap_free_item_zone);
 	kmem_cache_destroy(xfs_btree_cur_zone);
 	kmem_cache_destroy(xfs_inode_zone);
diff -urN linux-2.4.25-pre8/fs/xfs/xfsidbg.c linux-2.4.25-rc1/fs/xfs/xfsidbg.c
--- linux-2.4.25-pre8/fs/xfs/xfsidbg.c	2004-02-05 04:40:32.000000000 -0800
+++ linux-2.4.25-rc1/fs/xfs/xfsidbg.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,7720 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-#include "xfs.h"
-
-#include <linux/ctype.h>
-#include <linux/kdb.h>
-#include <linux/kdbprivate.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/version.h>
-
-#include "xfs_macros.h"
-#include "xfs_types.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_dmapi.h"
-#include "xfs_mount.h"
-#include "xfs_alloc.h"
-#include "xfs_ag.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_btree.h"
-#include "xfs_buf_item.h"
-#include "xfs_extfree_item.h"
-#include "xfs_inode_item.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dir2_trace.h"
-#include "xfs_dinode.h"
-#include "xfs_rw.h"
-#include "xfs_bmap.h"
-#include "xfs_inode.h"
-#include "xfs_da_btree.h"
-#include "xfs_attr.h"
-#include "xfs_attr_leaf.h"
-#include "xfs_dir_leaf.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
-#include "xfs_dir2_node.h"
-#include "xfs_log_priv.h"
-#include "xfs_log_recover.h"
-#include "xfs_bit.h"
-#include "xfs_quota.h"
-#include "quota/xfs_qm.h"
-#include "xfs_iomap.h"
-
-MODULE_AUTHOR("Silicon Graphics, Inc.");
-MODULE_DESCRIPTION("Additional kdb commands for debugging XFS");
-MODULE_LICENSE("GPL");
-
-#define qprintf	kdb_printf
-
-/*
- * Command table functions. (tracing)
- */
-#ifdef XFS_ALLOC_TRACE
-static void	xfsidbg_xalatrace(int);
-static void	xfsidbg_xalbtrace(xfs_agblock_t);
-static void	xfsidbg_xalgtrace(xfs_agnumber_t);
-static void	xfsidbg_xalmtrace(xfs_mount_t *);
-static void	xfsidbg_xalttrace(int);
-#endif
-#ifdef XFS_ATTR_TRACE
-static void	xfsidbg_xattrtrace(int);
-#endif
-#ifdef XFS_BLI_TRACE
-static void	xfsidbg_xblitrace(xfs_buf_log_item_t *);
-#endif
-#ifdef XFS_BMAP_TRACE
-static void	xfsidbg_xbmatrace(int);
-static void	xfsidbg_xbmitrace(xfs_inode_t *);
-static void	xfsidbg_xbmstrace(xfs_inode_t *);
-static void	xfsidbg_xbxatrace(int);
-static void	xfsidbg_xbxitrace(xfs_inode_t *);
-static void	xfsidbg_xbxstrace(xfs_inode_t *);
-#endif
-#ifdef XFS_ILOCK_TRACE
-static void	xfsidbg_xilock_trace(xfs_inode_t *);
-static void	xfsidbg_xailock_trace(int);
-#endif
-#ifdef XFS_DIR_TRACE
-static void	xfsidbg_xdirtrace(int);
-#endif
-#ifdef XFS_DIR2_TRACE
-static void	xfsidbg_xdir2atrace(int);
-static void	xfsidbg_xdir2itrace(xfs_inode_t *);
-#endif
-#ifdef XFS_LOG_TRACE
-static void	xfsidbg_xiclogtrace(xlog_in_core_t *);
-static void	xfsidbg_xlog_granttrace(xlog_t *);
-#endif
-#ifdef XFS_DQUOT_TRACE
-static void	xfsidbg_xqm_dqtrace(xfs_dquot_t *);
-#endif
-#ifdef XFS_RW_TRACE
-static void	xfsidbg_xrwtrace(xfs_inode_t *);
-#endif
-
-
-/*
- * Command table functions.
- */
-static void	xfsidbg_xagf(xfs_agf_t *);
-static void	xfsidbg_xagi(xfs_agi_t *);
-static void	xfsidbg_xaildump(xfs_mount_t *);
-static void	xfsidbg_xalloc(xfs_alloc_arg_t *);
-static void	xfsidbg_xattrcontext(xfs_attr_list_context_t *);
-static void	xfsidbg_xattrleaf(xfs_attr_leafblock_t *);
-static void	xfsidbg_xattrsf(xfs_attr_shortform_t *);
-static void	xfsidbg_xbirec(xfs_bmbt_irec_t *r);
-static void	xfsidbg_xbmalla(xfs_bmalloca_t *);
-static void	xfsidbg_xbrec(xfs_bmbt_rec_64_t *);
-static void	xfsidbg_xbroot(xfs_inode_t *);
-static void	xfsidbg_xbroota(xfs_inode_t *);
-static void	xfsidbg_xbtcur(xfs_btree_cur_t *);
-static void	xfsidbg_xbuf(xfs_buf_t *);
-static void	xfsidbg_xbuf_real(xfs_buf_t *, int);
-static void	xfsidbg_xarg(int);
-static void	xfsidbg_xchksum(uint *);
-static void	xfsidbg_xchash(xfs_mount_t *mp);
-static void	xfsidbg_xchashlist(xfs_chashlist_t *chl);
-static void	xfsidbg_xdaargs(xfs_da_args_t *);
-static void	xfsidbg_xdabuf(xfs_dabuf_t *);
-static void	xfsidbg_xdanode(xfs_da_intnode_t *);
-static void	xfsidbg_xdastate(xfs_da_state_t *);
-static void	xfsidbg_xdirleaf(xfs_dir_leafblock_t *);
-static void	xfsidbg_xdirsf(xfs_dir_shortform_t *);
-static void	xfsidbg_xdir2free(xfs_dir2_free_t *);
-static void	xfsidbg_xdir2sf(xfs_dir2_sf_t *);
-static void	xfsidbg_xexlist(xfs_inode_t *);
-static void	xfsidbg_xflist(xfs_bmap_free_t *);
-static void	xfsidbg_xhelp(void);
-static void	xfsidbg_xiclog(xlog_in_core_t *);
-static void	xfsidbg_xiclogall(xlog_in_core_t *);
-static void	xfsidbg_xiclogcb(xlog_in_core_t *);
-static void	xfsidbg_xihash(xfs_mount_t *mp);
-static void	xfsidbg_xinodes(xfs_mount_t *);
-static void	xfsidbg_delayed_blocks(xfs_mount_t *);
-static void	xfsidbg_xinodes_quiesce(xfs_mount_t *);
-static void	xfsidbg_xlog(xlog_t *);
-static void	xfsidbg_xlog_ritem(xlog_recover_item_t *);
-static void	xfsidbg_xlog_rtrans(xlog_recover_t *);
-static void	xfsidbg_xlog_rtrans_entire(xlog_recover_t *);
-static void	xfsidbg_xlog_tic(xlog_ticket_t *);
-static void	xfsidbg_xlogitem(xfs_log_item_t *);
-static void	xfsidbg_xmount(xfs_mount_t *);
-static void	xfsidbg_xnode(xfs_inode_t *ip);
-static void	xfsidbg_xcore(xfs_iocore_t *io);
-static void	xfsidbg_xperag(xfs_mount_t *);
-static void	xfsidbg_xqm_diskdq(xfs_disk_dquot_t *);
-static void	xfsidbg_xqm_dqattached_inos(xfs_mount_t *);
-static void	xfsidbg_xqm_dquot(xfs_dquot_t *);
-static void	xfsidbg_xqm_mplist(xfs_mount_t *);
-static void	xfsidbg_xqm_qinfo(xfs_mount_t *mp);
-static void	xfsidbg_xqm_tpdqinfo(xfs_trans_t *tp);
-static void	xfsidbg_xsb(xfs_sb_t *, int convert);
-static void	xfsidbg_xtp(xfs_trans_t *);
-static void	xfsidbg_xtrans_res(xfs_mount_t *);
-#ifdef CONFIG_XFS_QUOTA
-static void	xfsidbg_xqm(void);
-static void	xfsidbg_xqm_htab(void);
-static void	xfsidbg_xqm_freelist_print(xfs_frlist_t *qlist, char *title);
-static void	xfsidbg_xqm_freelist(void);
-#endif
-
-#ifdef XFS_BMAP_TRACE
-static void	xfs_convert_extent(xfs_bmbt_rec_32_t *, xfs_dfiloff_t *,
-				xfs_dfsbno_t *, xfs_dfilblks_t *, int *);
-#endif
-
-/* kdb wrappers */
-
-static int	kdbm_xfs_xagf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xagf((xfs_agf_t *)addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xagi(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xagi((xfs_agi_t *)addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xaildump(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xaildump((xfs_mount_t *) addr);
-	return 0;
-}
-
-#ifdef XFS_ALLOC_TRACE
-static int	kdbm_xfs_xalatrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-	
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xalatrace((int) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xalbtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xalbtrace((xfs_agblock_t) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xalgtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xalgtrace((xfs_agnumber_t) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_ATTR_TRACE
-static int	kdbm_xfs_xattrtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xattrtrace((int) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_BLI_TRACE
-static int	kdbm_xfs_xblitrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xblitrace((xfs_buf_log_item_t *) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_BMAP_TRACE
-static int	kdbm_xfs_xbmatrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbmatrace((int) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbmitrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbmitrace((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbmstrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbmstrace((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbxatrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbxatrace((int) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbxitrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbxitrace((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbxstrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbxstrace((xfs_inode_t *) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_DIR2_TRACE
-static int	kdbm_xfs_xdir2atrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdir2atrace((int) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdir2itrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdir2itrace((xfs_inode_t *) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_DIR_TRACE
-static int	kdbm_xfs_xdirtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdirtrace((int) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_LOG_TRACE
-static int	kdbm_xfs_xiclogtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xiclogtrace((xlog_in_core_t *) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_ILOCK_TRACE
-static int	kdbm_xfs_xilock_trace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xilock_trace((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xailock_trace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xailock_trace((int) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_LOG_TRACE
-static int	kdbm_xfs_xlog_granttrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xlog_granttrace((xlog_t *) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_DQUOT_TRACE
-static int	kdbm_xfs_xqm_dqtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xqm_dqtrace((xfs_dquot_t *) addr);
-	return 0;
-}
-#endif
-
-#ifdef XFS_RW_TRACE
-static int	kdbm_xfs_xrwtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xrwtrace((xfs_inode_t *) addr);
-	return 0;
-}
-#endif
-
-static int	kdbm_xfs_xalloc(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xalloc((xfs_alloc_arg_t *) addr);
-	return 0;
-}
-
-#ifdef XFS_ALLOC_TRACE
-static int	kdbm_xfs_xalmtrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xalmtrace((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xalttrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xalttrace((int) addr);
-	return 0;
-}
-#endif /* XFS_ALLOC_TRACE */
-
-static int	kdbm_xfs_xattrcontext(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xattrcontext((xfs_attr_list_context_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xattrleaf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xattrleaf((xfs_attr_leafblock_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xattrsf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xattrsf((xfs_attr_shortform_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbirec(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbirec((xfs_bmbt_irec_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbmalla(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbmalla((xfs_bmalloca_t *)addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbrec(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbrec((xfs_bmbt_rec_64_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbroot(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbroot((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbroota(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbroota((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbtcur(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbtcur((xfs_btree_cur_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xbuf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xbuf((xfs_buf_t *) addr);
-	return 0;
-}
-
-
-static int	kdbm_xfs_xarg(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xarg((int) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xchksum(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xchksum((uint *) addr);
-	return 0;
-}
-
-
-static int	kdbm_xfs_xchash(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xchash((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xchashlist(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xchashlist((xfs_chashlist_t *) addr);
-	return 0;
-}
-
-
-static int	kdbm_xfs_xdaargs(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdaargs((xfs_da_args_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdabuf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdabuf((xfs_dabuf_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdanode(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdanode((xfs_da_intnode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdastate(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdastate((xfs_da_state_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdirleaf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdirleaf((xfs_dir_leafblock_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdirsf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdirsf((xfs_dir_shortform_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdir2free(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdir2free((xfs_dir2_free_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xdir2sf(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xdir2sf((xfs_dir2_sf_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xexlist(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xexlist((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xflist(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xflist((xfs_bmap_free_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xhelp(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	if (argc != 0)
-		return KDB_ARGCOUNT;
-
-	xfsidbg_xhelp();
-	return 0;
-}
-
-static int	kdbm_xfs_xiclog(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xiclog((xlog_in_core_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xiclogall(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xiclogall((xlog_in_core_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xiclogcb(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xiclogcb((xlog_in_core_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xihash(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xihash((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xinodes(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xinodes((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_delayed_blocks(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_delayed_blocks((xfs_mount_t *) addr);
-	return 0;
-}
-
-
-static int	kdbm_xfs_xinodes_quiesce(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xinodes_quiesce((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xlog(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xlog((xlog_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xlog_ritem(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xlog_ritem((xlog_recover_item_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xlog_rtrans(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xlog_rtrans((xlog_recover_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xlog_rtrans_entire(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xlog_rtrans_entire((xlog_recover_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xlog_tic(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xlog_tic((xlog_ticket_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xlogitem(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xlogitem((xfs_log_item_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xmount(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xmount((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xnode(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xnode((xfs_inode_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xcore(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xcore((xfs_iocore_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xperag(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xperag((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xqm_diskdq(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xqm_diskdq((xfs_disk_dquot_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xqm_dqattached_inos(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xqm_dqattached_inos((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xqm_dquot(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xqm_dquot((xfs_dquot_t *) addr);
-	return 0;
-}
-
-#ifdef	CONFIG_XFS_QUOTA
-static int	kdbm_xfs_xqm(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	if (argc != 0)
-		return KDB_ARGCOUNT;
-
-	xfsidbg_xqm();
-	return 0;
-}
-
-static int	kdbm_xfs_xqm_freelist(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	if (argc != 0)
-		return KDB_ARGCOUNT;
-
-	xfsidbg_xqm_freelist();
-	return 0;
-}
-
-static int	kdbm_xfs_xqm_htab(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	if (argc != 0)
-		return KDB_ARGCOUNT;
-
-	xfsidbg_xqm_htab();
-	return 0;
-}
-#endif
-
-static int	kdbm_xfs_xqm_mplist(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xqm_mplist((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xqm_qinfo(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xqm_qinfo((xfs_mount_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xqm_tpdqinfo(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xqm_tpdqinfo((xfs_trans_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xsb(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	unsigned long convert=0;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1 && argc!=2)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-	if (argc==2) {
-	    /* extra argument - conversion flag */
-	    diag = kdbgetaddrarg(argc, argv, &nextarg, &convert, &offset, NULL, regs);
-	    if (diag)
-		    return diag;
-	}
-
-	xfsidbg_xsb((xfs_sb_t *) addr, (int)convert);
-	return 0;
-}
-
-static int	kdbm_xfs_xtp(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xtp((xfs_trans_t *) addr);
-	return 0;
-}
-
-static int	kdbm_xfs_xtrans_res(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	xfsidbg_xtrans_res((xfs_mount_t *) addr);
-	return 0;
-}
-
-/*
- * Vnode descriptor dump.
- * This table is a string version of all the flags defined in vnode.h.
- */
-char *tab_vflags[] = {
-	/* local only flags */
-	"VINACT",		/*	 0x01 */
-	"VRECLM",		/*	 0x02 */
-	"VWAIT",		/*	 0x04 */
-	"VMODIFIED",		/*	 0x08 */
-	"INVALID0x10",		/*	 0x10 */
-	"INVALID0x20",		/*	 0x20 */
-	"INVALID0x40",		/*	 0x40 */
-	"INVALID0x80",		/*	 0x80 */
-	"INVALID0x100",		/*	0x100 */
-	"INVALID0x200",		/*	0x200 */
-	"INVALID0x400",		/*	0x400 */
-	"INVALID0x800",		/*	0x800 */
-	"INVALID0x1000",	/*     0x1000 */
-	"INVALID0x2000",	/*     0x2000 */
-	"INVALID0x4000",	/*     0x4000 */
-	"INVALID0x8000",	/*     0x8000 */
-	"INVALID0x10000",	/*    0x10000 */
-	"INVALID0x20000",	/*    0x20000 */
-	"INVALID0x40000",	/*    0x40000 */
-	"INVALID0x80000",	/*    0x80000 */
-	"VROOT",		/*   0x100000 */
-	"INVALID0x200000",	/*   0x200000 */
-	"INVALID00x400000",	/*   0x400000 */
-	"INVALID0x800000",	/*   0x800000 */
-	"INVALID0x1000000",	/*  0x1000000 */
-	"INVALID0x2000000",	/*  0x2000000 */
-	"VSHARE",		/*  0x4000000 */
-	"INVALID0x8000000",     /*  0x8000000 */
-	"VENF_LOCKING",		/* 0x10000000 */
-	"VOPLOCK",		/* 0x20000000 */
-	"VPURGE",		/* 0x40000000 */
-	"INVALID0x80000000",	/* 0x80000000 */
-	0
-};
-
-
-static char *vnode_type[] = {
-	"VNON", "VREG", "VDIR", "VBLK", "VLNK", "VFIFO", "VBAD", "VSOCK"
-};
-
-static void
-printflags(register uint64_t flags,
-	register char **strings,
-	register char *name)
-{
-	register uint64_t mask = 1;
-
-	if (name)
-		kdb_printf("%s 0x%llx <", name, (unsigned long long)flags);
-
-	while (flags != 0 && *strings) {
-		if (mask & flags) {
-			kdb_printf("%s ", *strings);
-			flags &= ~mask;
-		}
-		mask <<= 1;
-		strings++;
-	}
-
-	if (name)
-		kdb_printf("> ");
-
-	return;
-}
-
-
-static void printbhv(bhv_desc_t *bdp)
-{
-	kdb_symtab_t	 symtab;
-
-	if (bdp == NULL) {
-		kdb_printf("NULL bhv\n");
-		return;
-	}
-
-	kdb_printf("bhv at 0x%p\n", bdp);
-	while (bdp) {
-		if (kdbnearsym((unsigned long)bdp->bd_ops, &symtab))
-			kdb_printf("  ops %s", symtab.sym_name);
-		else
-			kdb_printf("  ops %s/0x%p", "???", (void *)bdp->bd_ops);
-
-		kdb_printf(" vobj 0x%p pdata 0x%p next 0x%p\n",
-			   bdp->bd_vobj, bdp->bd_pdata, bdp->bd_next);
-
-		bdp = bdp->bd_next;
-	}
-}
-
-
-static void	printvnode(vnode_t *vp, unsigned long addr)
-{
-	kdb_printf("vnode: 0x%lx type ", addr);
-	if ((size_t)vp->v_type >= sizeof(vnode_type)/sizeof(vnode_type[0]))
-		kdb_printf("out of range 0x%x", vp->v_type);
-	else
-		kdb_printf("%s", vnode_type[vp->v_type]);
-	kdb_printf(" v_bh 0x%p\n", &vp->v_bh);
-
-	printbhv(vp->v_fbhv);
-
-	printflags((__psunsigned_t)vp->v_flag, tab_vflags, "flag =");
-	kdb_printf("\n");
-
-#ifdef	XFS_VNODE_TRACE
-	kdb_printf("   v_trace 0x%p\n", vp->v_trace);
-#endif	/* XFS_VNODE_TRACE */
-
-	kdb_printf("   v_vfsp 0x%p v_number 0x%llx\n",
-		vp->v_vfsp, (unsigned long long)vp->v_number);
-}
-
-static int	kdbm_vnode(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-	vnode_t		vp;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-
-	if (diag)
-		return diag;
-
-	if ((diag = kdb_getarea(vp, addr)))
-		return diag;
-
-	printvnode(&vp, addr);
-
-	return 0;
-}
-
-static void
-print_vfs(vfs_t	*vfs, unsigned long addr)
-{
-	kdb_printf("vfsp at 0x%lx", addr);
-	kdb_printf(" vfs_flag 0x%x\n", vfs->vfs_flag);
-	kdb_printf(" vfs_super 0x%p", vfs->vfs_super);
-	kdb_printf(" vfs_bh 0x%p\n", &vfs->vfs_bh);
-
-	printbhv(vfs->vfs_fbhv);
-}
-
-static int	kdbm_bhv(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-	bhv_desc_t	*bh;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-
-	if (diag)
-		return diag;
-
-	bh = (bhv_desc_t *)addr;
-
-	printbhv(bh);
-
-	return 0;
-}
-
-static int	kdbm_vfs(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long addr;
-	int nextarg = 1;
-	long offset = 0;
-	int diag;
-	vfs_t		vfs;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-
-	if (diag)
-		return diag;
-
-	if ((diag = kdb_getarea(vfs, addr)))
-		return diag;
-
-	print_vfs(&vfs, addr);
-
-	return 0;
-}
-
-
-#ifdef	XFS_VNODE_TRACE
-/*
- * Print a vnode trace entry.
- */
-static int
-vn_trace_pr_entry(ktrace_entry_t *ktep)
-{
-	char		funcname[128];
-	kdb_symtab_t	symtab;
-
-
-	if ((__psint_t)ktep->val[0] == 0)
-		return 0;
-
-	if (kdbnearsym((unsigned int)ktep->val[8], &symtab)) {
-		unsigned long offval;
-
-		offval = (unsigned int)ktep->val[8] - symtab.sym_start;
-
-		if (offval)
-			sprintf(funcname, "%s+0x%lx", symtab.sym_name, offval);
-		else
-			sprintf(funcname, "%s", symtab.sym_name);
-	} else
-		funcname[0] = '\0';
-
-
-	switch ((__psint_t)ktep->val[0]) {
-	case VNODE_KTRACE_ENTRY:
-		kdb_printf("entry to %s i_count = %d",
-						(char *)ktep->val[1],
-						(__psint_t)ktep->val[3]);
-		break;
-
-	case VNODE_KTRACE_EXIT:
-		kdb_printf("exit from %s i_count = %d",
-						(char *)ktep->val[1],
-						(__psint_t)ktep->val[3]);
-		break;
-
-	case VNODE_KTRACE_HOLD:
-		if ((__psint_t)ktep->val[3] != 1)
-			kdb_printf("hold @%s:%d(%s) i_count %d => %d ",
-						(char *)ktep->val[1],
-						(__psint_t)ktep->val[2],
-						funcname,
-						(__psint_t)ktep->val[3] - 1,
-						(__psint_t)ktep->val[3]);
-		else
-			kdb_printf("get @%s:%d(%s) i_count = %d",
-						(char *)ktep->val[1],
-						(__psint_t)ktep->val[2],
-						funcname,
-						(__psint_t)ktep->val[3]);
-		break;
-
-	case VNODE_KTRACE_REF:
-		kdb_printf("ref @%s:%d(%s) i_count = %d",
-						(char *)ktep->val[1],
-						(__psint_t)ktep->val[2],
-						funcname,
-						(__psint_t)ktep->val[3]);
-		break;
-
-	case VNODE_KTRACE_RELE:
-		if ((__psint_t)ktep->val[3] != 1)
-			kdb_printf("rele @%s:%d(%s) i_count %d => %d ",
-						(char *)ktep->val[1],
-						(__psint_t)ktep->val[2],
-						funcname,
-						(__psint_t)ktep->val[3],
-						(__psint_t)ktep->val[3] - 1);
-		else
-			kdb_printf("free @%s:%d(%s) i_count = %d",
-						(char *)ktep->val[1],
-						(__psint_t)ktep->val[2],
-						funcname,
-						(__psint_t)ktep->val[3]);
-		break;
-
-	default:
-		kdb_printf("unknown vntrace record\n");
-		return 1;
-	}
-
-	kdb_printf("\n");
-
-	kdb_printf("  cpu = %d pid = %d ",
-			(__psint_t)ktep->val[6], (pid_t)ktep->val[7]);
-
-	printflags((__psunsigned_t)ktep->val[5], tab_vflags, "flag =");
-
-	if (kdbnearsym((unsigned int)ktep->val[4], &symtab)) {
-		unsigned long offval;
-
-		offval = (unsigned int)ktep->val[4] - symtab.sym_start;
-
-		if (offval)
-			kdb_printf("  ra = %s+0x%lx", symtab.sym_name, offval);
-		else
-			kdb_printf("  ra = %s", symtab.sym_name);
-	} else
-		kdb_printf("  ra = ?? 0x%p", (void *)ktep->val[4]);
-
-	return 1;
-}
-
-
-/*
- * Print out the trace buffer attached to the given vnode.
- */
-static int	kdbm_vntrace(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	int		diag;
-	int		nextarg = 1;
-	long		offset = 0;
-	unsigned long	addr;
-	vnode_t		*vp;
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-
-	if (diag)
-		return diag;
-
-	vp = (vnode_t *)addr;
-
-	if (vp->v_trace == NULL) {
-		kdb_printf("The vnode trace buffer is not initialized\n");
-
-		return 0;
-	}
-
-	kdb_printf("vntrace vp 0x%p\n", vp);
-
-	ktep = ktrace_first(vp->v_trace, &kts);
-
-	while (ktep != NULL) {
-		if (vn_trace_pr_entry(ktep))
-			kdb_printf("\n");
-
-		ktep = ktrace_next(vp->v_trace, &kts);
-	}
-
-	return 0;
-}
-/*
- * Print out the trace buffer attached to the given vnode.
- */
-static int	kdbm_vntraceaddr(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	int		diag;
-	int		nextarg = 1;
-	long		offset = 0;
-	unsigned long	addr;
-	struct ktrace	*kt;
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-
-	if (diag)
-		return diag;
-
-	kt = (struct ktrace *)addr;
-
-	kdb_printf("vntraceaddr kt 0x%p\n", kt);
-
-	ktep = ktrace_first(kt, &kts);
-
-	while (ktep != NULL) {
-		if (vn_trace_pr_entry(ktep))
-			kdb_printf("\n");
-
-		ktep = ktrace_next(kt, &kts);
-	}
-
-	return 0;
-}
-#endif	/* XFS_VNODE_TRACE */
-
-
-static void	printinode(struct inode *ip)
-{
-	unsigned long	addr;
-
-
-	if (ip == NULL)
-		return;
-
-	kdb_printf(" i_ino = %lu i_count = %u i_size %Ld\n",
-					ip->i_ino, atomic_read(&ip->i_count),
-					ip->i_size);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-	kdb_printf(
-		" i_mode = 0x%x  i_nlink = %d  i_rdev = 0x%x i_state = 0x%lx\n",
-					ip->i_mode, ip->i_nlink,
-					kdev_t_to_nr(ip->i_rdev), ip->i_state);
-	kdb_printf(" i_hash.nxt = 0x%p i_hash.pprv = 0x%p\n",
-                                        ip->i_hash.next, ip->i_hash.prev);
-#else
-	kdb_printf(
-		" i_mode = 0x%x  i_nlink = %d  i_rdev = 0x%x i_state = 0x%lx\n",
-					ip->i_mode, ip->i_nlink,
-					ip->i_rdev, ip->i_state);
-	kdb_printf(" i_hash.nxt = 0x%p i_hash.pprv = 0x%p\n",
-                                        ip->i_hash.next, ip->i_hash.pprev);
-#endif
-	kdb_printf(" i_list.nxt = 0x%p i_list.prv = 0x%p\n",
-					ip->i_list.next, ip->i_list.prev);
-	kdb_printf(" i_dentry.nxt = 0x%p i_dentry.prv = 0x%p\n",
-					ip->i_dentry.next,
-					ip->i_dentry.prev);
-
-	addr = (unsigned long)ip;
-
-	kdb_printf(" i_sb = 0x%p i_op = 0x%p i_data = 0x%lx nrpages = %lu\n",
-					ip->i_sb, ip->i_op,
-					addr + offsetof(struct inode, i_data),
-					ip->i_data.nrpages);
-
-	kdb_printf("  vnode ptr 0x%p\n", LINVFS_GET_VP(ip));
-}
-
-
-static int	kdbm_vn(
-	int	argc,
-	const char **argv,
-	const char **envp,
-	struct pt_regs *regs)
-{
-	int		diag;
-	int		nextarg = 1;
-	long		offset = 0;
-	unsigned long	addr;
-	struct inode	*ip;
-	vnode_t		vp;
-#ifdef	XFS_VNODE_TRACE
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-#endif
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
-	if (diag)
-		return diag;
-
-	if ((diag = kdb_getarea(vp, addr)))
-		return diag;
-
-	ip = LINVFS_GET_IP((vnode_t *)addr);
-	kdb_printf("--> Inode @ 0x%p\n", ip);
-	printinode(ip);
-
-	kdb_printf("--> Vnode @ 0x%lx\n", addr);
-	printvnode(&vp, addr);
-
-#ifdef	XFS_VNODE_TRACE
-	kdb_printf("--> Vntrace @ 0x%lx/0x%p\n", addr, vp.v_trace);
-	if (vp.v_trace == NULL)
-		return 0;
-	ktep = ktrace_first(vp.v_trace, &kts);
-	while (ktep != NULL) {
-		if (vn_trace_pr_entry(ktep))
-			kdb_printf("\n");
-
-		ktep = ktrace_next(vp.v_trace, &kts);
-	}
-#endif	/* XFS_VNODE_TRACE */
-	return 0;
-}
-
-
-/* pagebuf stuff */
-
-static char	*pb_flag_vals[] = {
-/*  0 */ "READ", "WRITE", "MAPPED", "PARTIAL", "ASYNC",
-/*  5 */ "NONE", "DELWRI", "FREED", "SYNC", "MAPPABLE",
-/* 10 */ "STALE", "FS_MANAGED", "FS_DATAIOD", "LOCK", "TRYLOCK",
-/* 15 */ "DONT_BLOCK", "LOCKABLE", "PRIVATE_BH", "ALL_PAGES_MAPPED", 
-	 "ADDR_ALLOCATED",
-/* 20 */ "MEM_ALLOCATED", "FORCEIO", "FLUSH", "READ_AHEAD",
-	 NULL };
-
-static char	*iomap_flag_vals[] = {
-	"EOF", "HOLE", "DELAY", "INVALID0x08",
-	"INVALID0x10", "UNWRITTEN", "NEW", "INVALID0x80",
-	NULL };
-
-
-static char	*map_flags(unsigned long flags, char *mapping[])
-{
-	static	char	buffer[256];
-	int	index;
-	int	offset = 12;
-
-	buffer[0] = '\0';
-
-	for (index = 0; flags && mapping[index]; flags >>= 1, index++) {
-		if (flags & 1) {
-			if ((offset + strlen(mapping[index]) + 1) >= 80) {
-				strcat(buffer, "\n	    ");
-				offset = 12;
-			} else if (offset > 12) {
-				strcat(buffer, " ");
-				offset++;
-			}
-			strcat(buffer, mapping[index]);
-			offset += strlen(mapping[index]);
-		}
-	}
-
-	return (buffer);
-}
-
-static char	*pb_flags(page_buf_flags_t pb_flag)
-{
-	return(map_flags((unsigned long) pb_flag, pb_flag_vals));
-}
-
-static int
-kdbm_pb_flags(int argc, const char **argv, const char **envp, struct pt_regs *regs)
-{
-	unsigned long flags;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	diag = kdbgetularg(argv[1], &flags);
-	if (diag)
-		return diag;
-
-	kdb_printf("pb flags 0x%lx = %s\n", flags, pb_flags(flags));
-
-	return 0;
-}
-
-static void
-print_pagebuf(
-	page_buf_t	*pb,
-	unsigned long addr)
-{
-	kdb_printf("page_buf_t at 0x%lx\n", addr);
-	kdb_printf("  pb_flags %s\n", pb_flags(pb->pb_flags));
-	kdb_printf("  pb_target 0x%p pb_hold %d pb_next 0x%p pb_prev 0x%p\n",
-		   pb->pb_target, pb->pb_hold.counter,
-		   list_entry(pb->pb_list.next, page_buf_t, pb_list),
-		   list_entry(pb->pb_list.prev, page_buf_t, pb_list));
-	kdb_printf("  pb_hash_index %d pb_hash_next 0x%p pb_hash_prev 0x%p\n",
-		   pb->pb_hash_index,
-		   list_entry(pb->pb_hash_list.next, page_buf_t, pb_hash_list),
-		   list_entry(pb->pb_hash_list.prev, page_buf_t, pb_hash_list));
-	kdb_printf("  pb_file_offset 0x%llx pb_buffer_length 0x%llx pb_addr 0x%p\n",
-		   (unsigned long long) pb->pb_file_offset,
-		   (unsigned long long) pb->pb_buffer_length,
-		   pb->pb_addr);
-	kdb_printf("  pb_bn 0x%Lx pb_count_desired 0x%lx pb_locked %d\n",
-		   pb->pb_bn,
-		   (unsigned long) pb->pb_count_desired, (int)pb->pb_locked);
-	kdb_printf("  pb_flushtime %ld (%ld) pb_io_remaining %d pb_error %u\n",
-		   pb->pb_flushtime, pb->pb_flushtime - jiffies,
-		   pb->pb_io_remaining.counter, pb->pb_error);
-	kdb_printf("  pb_page_count %u pb_offset 0x%x pb_pages 0x%p\n",
-		pb->pb_page_count, pb->pb_offset,
-		pb->pb_pages);
-	kdb_printf("  pb_iodonesema (%d,%d) pb_sema (%d,%d) pincount (%d)\n",
-		   pb->pb_iodonesema.count.counter,
-		   pb->pb_iodonesema.sleepers,
-		   pb->pb_sema.count.counter, pb->pb_sema.sleepers,
-		   pb->pb_pin_count.counter);
-#ifdef PAGEBUF_LOCK_TRACKING
-	kdb_printf("  last holder %d\n", pb->pb_last_holder);
-#endif
-	if (pb->pb_fspriv || pb->pb_fspriv2) {
-		kdb_printf(  "  pb_fspriv 0x%p pb_fspriv2 0x%p\n",
-			   pb->pb_fspriv, pb->pb_fspriv2);
-	}
-}
-
-static int
-kdbm_pb(int argc, const char **argv, const char **envp, struct pt_regs *regs)
-{
-	page_buf_t bp;
-	unsigned long addr;
-	long	offset=0;
-	int nextarg;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	nextarg = 1;
-	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
-	    (diag = kdb_getarea(bp, addr)))
-		return diag;
-
-	print_pagebuf(&bp, addr);
-
-	return 0;
-}
-
-static int
-kdbm_pbdelay(int argc, const char **argv, const char **envp,
-	struct pt_regs *regs)
-{
-#ifdef DEBUG
-	unsigned long	verbose = 0;
-	int	count = 0;
-	struct list_head	*curr, *next;
-	page_buf_t	bp;
-	unsigned long addr;
-	int diag;
-	extern struct list_head pbd_delwrite_queue;
-
-	if (argc > 1)
-		return KDB_ARGCOUNT;
-
-	if (argc == 1) {
-		if ((diag = kdbgetularg(argv[1], &verbose))) {
-			return diag;
-		}
-	}
-
-	if (!verbose) {
-		kdb_printf("index pb       pin   flushtime\n");
-	}
-
-	list_for_each_safe(curr, next, &pbd_delwrite_queue) {
-		addr = (unsigned long)list_entry(curr, page_buf_t, pb_list);
-		if ((diag = kdb_getarea(bp, addr)))
-			return diag;
-
-		if (verbose) {
-			print_pagebuf(&bp, addr);
-		} else {
-			kdb_printf("%4d  0x%lx   %d   %ld\n",
-				count++, addr, 
-				bp.pb_pin_count.counter,
-				bp.pb_flushtime - jiffies);
-		}
-	}
-#else
-	kdb_printf("pbd_delwrite_queue inaccessible (non-debug)\n");
-#endif
-	return 0;
-}
-
-static int
-kdbm_iomap(int argc, const char **argv, const char **envp,
-	struct pt_regs *regs)
-{
-	xfs_iomap_t iomap;
-	unsigned long addr;
-	long offset=0;
-	int nextarg;
-	int diag;
-
-	if (argc != 1)
-		return KDB_ARGCOUNT;
-
-	nextarg = 1;
-	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
-	    (diag = kdb_getarea(iomap, addr)))
-
-	kdb_printf("iomap_t at 0x%lx\n", addr);
-	kdb_printf("  iomap_bn 0x%llx iomap_offset 0x%Lx iomap_delta 0x%lx iomap_bsize 0x%llx\n",
-		(long long) iomap.iomap_bn, iomap.iomap_offset,
-		(unsigned long)iomap.iomap_delta, (long long)iomap.iomap_bsize);
-
-	kdb_printf("  iomap_flags %s\n", map_flags(iomap.iomap_flags, iomap_flag_vals));
-
-	return 0;
-}
-
-#ifdef PAGEBUF_TRACE
-static int pagebuf_trace_entry(ktrace_entry_t *ktep)
-{
-	unsigned long long daddr;
-
-	daddr = ((unsigned long long)(unsigned long)ktep->val[8] << 32)
-		| ((unsigned long long)(unsigned long)ktep->val[9]);
-
-	kdb_printf("pb 0x%p [%s] (hold %lu lock %ld) data 0x%p",
-		ktep->val[0],
-		(char *)ktep->val[1],
-		(unsigned long)ktep->val[3],
-		(long)ktep->val[4],
-		ktep->val[6]);
-	kdb_symbol_print((unsigned long)ktep->val[7], NULL,
-		KDB_SP_SPACEB|KDB_SP_PAREN|KDB_SP_NEWLINE);
-	kdb_printf("    offset 0x%llx size 0x%lx task 0x%p\n",
-		daddr, (long)ktep->val[10], ktep->val[5]);
-	kdb_printf("    flags: %s\n", pb_flags((int)(long)ktep->val[2]));
-	return 1;
-}
-
-static int
-kdbm_pbtrace_offset(int argc, const char **argv, const char **envp,
-	struct pt_regs *regs)
-{
-	long		mask = 0;
-	unsigned long	offset = 0;
-	int		diag;
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-
-	if (argc > 2)
-		return KDB_ARGCOUNT;
-
-	if (argc > 0) {
-		diag = kdbgetularg(argv[1], &offset);
-		if (diag)
-			return diag;
-	}
-
-	if (argc > 1) {
-		diag = kdbgetularg(argv[1], &mask);	/* sign extent mask */
-		if (diag)
-			return diag;
-	}
-
-	ktep = ktrace_first(pagebuf_trace_buf, &kts);
-	while (ktep != NULL) {
-		unsigned long long daddr;
-
-		daddr = ((unsigned long long)(unsigned long)ktep->val[8] << 32)
-			| ((unsigned long long)(unsigned long)ktep->val[9]);
-		if (offset && ((daddr & ~mask) != offset))
-			continue;
-		if (pagebuf_trace_entry(ktep))
-			kdb_printf("\n");
-		ktep = ktrace_next(pagebuf_trace_buf, &kts);
-	}
-	return 0;
-}
-
-static int
-kdbm_pbtrace(int argc, const char **argv, const char **envp,
-	struct pt_regs *regs)
-{
-	unsigned long	addr = 0;
-	int		diag, nextarg;
-	long		offset = 0;
-	char		*event_match = NULL;
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-
-	if (argc > 1)
-		return KDB_ARGCOUNT;
-
-	if (argc == 1) {
-		if (isupper(argv[1][0]) || islower(argv[1][0])) {
-			event_match = (char *)argv[1];
-			kdb_printf("event match on \"%s\"\n", event_match);
-			argc = 0;
-		} else {
-			nextarg = 1;
-			diag = kdbgetaddrarg(argc, argv,
-					&nextarg, &addr, &offset, NULL, regs);
-			if (diag) {
-				kdb_printf("non-numeric arg: %s\n", argv[1]);
-				return diag;
-			}
-		}
-	}
-
-	ktep = ktrace_first(pagebuf_trace_buf, &kts);
-	while (ktep != NULL) {
-		if (addr && (ktep->val[0] != (void *)addr))
-			continue;
-		if (event_match && strcmp((char *)ktep->val[1], event_match))
-			continue;
-		if (pagebuf_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(pagebuf_trace_buf, &kts);
-	}
-	return 0;
-}
-#endif
-
-struct xif {
-	char	*name;
-	int	(*func)(int, const char **, const char **, struct pt_regs *);
-	char	*args;
-	char	*help;
-};
-
-static struct xif xfsidbg_funcs[] = {
-  {  "bhv",	kdbm_bhv,	"<bhv>", "Dump bhv chain"},
-  {  "vn",	kdbm_vn,	"<vnode>", "Dump inode/vnode/trace"},
-  {  "vnode",	kdbm_vnode,	"<vnode>", "Dump vnode"},
-  {  "vfs",	kdbm_vfs,	"<vfs>", "Dump vfs"},
-#ifdef XFS_VNODE_TRACE
-  {  "vntrace",	kdbm_vntrace,	"<vntrace>", "Dump vnode Trace"},
-  {  "vntraceaddr",	kdbm_vntraceaddr, "<vntrace>",
-				"Dump vnode Trace by Address"},
-#endif
-  {  "xagf",	kdbm_xfs_xagf,	"<agf>",
-				"Dump XFS allocation group freespace" },
-  {  "xagi",	kdbm_xfs_xagi,	"<agi>",
-				"Dump XFS allocation group inode" },
-  {  "xail",	kdbm_xfs_xaildump,	"<xfs_mount_t>",
-				"Dump XFS AIL for a mountpoint" },
-#ifdef XFS_ALLOC_TRACE
-  {  "xalatrc",	kdbm_xfs_xalatrace,	"<count>",
-				"Dump XFS alloc count trace" },
-  {  "xalbtrc",	kdbm_xfs_xalbtrace,	"<xfs_agblock_t>",
-				"Dump XFS alloc block trace" },
-  {  "xalgtrc",	kdbm_xfs_xalgtrace,	"<xfs_agnumber_t>",
-				"Dump XFS alloc alloc-group trace" },
-#endif
-
-  {  "xalloc",	kdbm_xfs_xalloc,	"<xfs_alloc_arg_t>",
-				"Dump XFS allocation args structure" },
-#ifdef XFS_ALLOC_TRACE
-  {  "xalmtrc",	kdbm_xfs_xalmtrace,	"<xfs_mount_t>",
-				"Dump XFS alloc mount-point trace" },
-  {  "xalttrc",	kdbm_xfs_xalttrace,	"<tag>",
-				"Dump XFS alloc trace by tag number" },
-#endif
-  {  "xarg",	kdbm_xfs_xarg,		"<value>",
-				"Input XFS argument for next function" },
-  {  "xattrcx",	kdbm_xfs_xattrcontext,	"<xfs_attr_list_context_t>",
-				"Dump XFS attr_list context struct"},
-  {  "xattrlf",	kdbm_xfs_xattrleaf,	"<xfs_attr_leafblock_t>",
-				"Dump XFS attribute leaf block"},
-  {  "xattrsf",	kdbm_xfs_xattrsf,	"<xfs_attr_shortform_t>",
-				"Dump XFS attribute shortform"},
-#ifdef XFS_ATTR_TRACE
-  {  "xattrtr",	kdbm_xfs_xattrtrace,	"<count>",
-				"Dump XFS attribute attr_list() trace" },
-#endif
-  {  "xbirec",	kdbm_xfs_xbirec,	"<xfs_bmbt_irec_t",
-				"Dump XFS bmap incore record"},
-#ifdef XFS_BLI_TRACE
-  {  "xblitrc",	kdbm_xfs_xblitrace,	"<xfs_buf_log_item_t>",
-				"Dump XFS buf log item trace" },
-#endif
-  {  "xbmalla",	kdbm_xfs_xbmalla,	"<xfs_bmalloca_t>",
-				"Dump XFS bmalloc args structure"},
-#ifdef XFS_BMAP_TRACE
-  {  "xbmatrc",	kdbm_xfs_xbmatrace,	"<count>",
-				"Dump XFS bmap btree count trace" },
-  {  "xbmitrc",	kdbm_xfs_xbmitrace,	"<xfs_inode_t>",
-				"Dump XFS bmap btree per-inode trace" },
-  {  "xbmstrc",	kdbm_xfs_xbmstrace,	"<xfs_inode_t>",
-				"Dump XFS bmap btree inode trace" },
-#endif
-  {  "xbrec",	kdbm_xfs_xbrec,		"<xfs_bmbt_rec_64_t>",
-				"Dump XFS bmap record"},
-  {  "xbroot",	kdbm_xfs_xbroot,	"<xfs_inode_t>",
-				"Dump XFS bmap btree root (data)"},
-  {  "xbroota",	kdbm_xfs_xbroota,	"<xfs_inode_t>",
-				"Dump XFS bmap btree root (attr)"},
-  {  "xbtcur",	kdbm_xfs_xbtcur,	"<xfs_btree_cur_t>",
-				"Dump XFS btree cursor"},
-  {  "xbuf",	kdbm_xfs_xbuf,		"<xfs_buf_t>",
-				"Dump XFS data from a buffer"},
-#ifdef XFS_BMAP_TRACE
-  {  "xbxatrc",	kdbm_xfs_xbxatrace,	"<count>",
-				"Dump XFS bmap extent count trace" },
-  {  "xbxitrc",	kdbm_xfs_xbxitrace,	"<xfs_inode_t>",
-				"Dump XFS bmap extent per-inode trace" },
-  {  "xbxstrc",	kdbm_xfs_xbxstrace,	"<xfs_inode_t>",
-				"Dump XFS bmap extent inode trace" },
-#endif
-  {  "xchash",	kdbm_xfs_xchash,	"<xfs_mount_t>",
-				"Dump XFS cluster hash"},
-  {  "xchlist",	kdbm_xfs_xchashlist,	"<xfs_chashlist_t>",
-				"Dump XFS cluster hash list"},
-  {  "xchksum",	kdbm_xfs_xchksum,	"<addr>", "Dump chksum" },
-#ifdef XFS_DIR2_TRACE
-  {  "xd2atrc",	kdbm_xfs_xdir2atrace,	"<count>",
-				"Dump XFS directory v2 count trace" },
-#endif
-  {  "xd2free",	kdbm_xfs_xdir2free,	"<xfs_dir2_free_t>",
-				"Dump XFS directory v2 freemap"},
-#ifdef XFS_DIR2_TRACE
-  {  "xd2itrc",	kdbm_xfs_xdir2itrace,	"<xfs_inode_t>",
-				"Dump XFS directory v2 per-inode trace" },
-#endif
-  {  "xdaargs",	kdbm_xfs_xdaargs,	"<xfs_da_args_t>",
-				"Dump XFS dir/attr args structure"},
-  {  "xdabuf",	kdbm_xfs_xdabuf,	"<xfs_dabuf_t>",
-				"Dump XFS dir/attr buf structure"},
-  {  "xdanode",	kdbm_xfs_xdanode,	"<xfs_da_intnode_t>",
-				"Dump XFS dir/attr node block"},
-  {  "xdastat",	kdbm_xfs_xdastate,	"<xfs_da_state_t>",
-				"Dump XFS dir/attr state_blk struct"},
-  {  "xdelay",	kdbm_xfs_delayed_blocks,	"<xfs_mount_t>",
-				"Dump delayed block totals"},
-  {  "xdirlf",	kdbm_xfs_xdirleaf,	"<xfs_dir_leafblock_t>",
-				"Dump XFS directory leaf block"},
-  {  "xdirsf",	kdbm_xfs_xdirsf,	"<xfs_dir_shortform_t>",
-				"Dump XFS directory shortform"},
-  {  "xdir2sf",	kdbm_xfs_xdir2sf,	"<xfs_dir2_sf_t>",
-				"Dump XFS directory v2 shortform"},
-#ifdef XFS_DIR_TRACE
-  {  "xdirtrc",	kdbm_xfs_xdirtrace,	"<count>",
-				"Dump XFS directory getdents() trace" },
-#endif
-  {  "xdiskdq",	kdbm_xfs_xqm_diskdq,	"<xfs_disk_dquot_t>",
-				"Dump XFS ondisk dquot (quota) struct"},
-  {  "xdqatt",	kdbm_xfs_xqm_dqattached_inos,	"<xfs_mount_t>",
-				 "All incore inodes with dquots"},
-  {  "xdqinfo",	kdbm_xfs_xqm_tpdqinfo,	"<xfs_trans_t>",
-				"Dump dqinfo structure of a trans"},
-#ifdef XFS_DQUOT_TRACE
-  {  "xdqtrace",kdbm_xfs_xqm_dqtrace,	"<xfs_dquot_t>",
-				"Dump trace of a given dquot" },
-#endif
-  {  "xdquot",	kdbm_xfs_xqm_dquot,	"<xfs_dquot_t>",
-				"Dump XFS dquot (quota) structure"},
-  {  "xexlist",	kdbm_xfs_xexlist,	"<xfs_inode_t>",
-				"Dump XFS bmap extents in inode"},
-  {  "xflist",	kdbm_xfs_xflist,	"<xfs_bmap_free_t>",
-				"Dump XFS to-be-freed extent list"},
-  {  "xhelp",	kdbm_xfs_xhelp,		"",
-				"Print idbg-xfs help"},
-  {  "xicall",	kdbm_xfs_xiclogall,	"<xlog_in_core_t>",
-				"Dump All XFS in-core logs"},
-  {  "xiclog",	kdbm_xfs_xiclog,	"<xlog_in_core_t>",
-				"Dump XFS in-core log"},
-#ifdef XFS_LOG_TRACE
-  {  "xictrc",	kdbm_xfs_xiclogtrace,	"<xlog_in_core_t>",
-				"Dump XFS in-core log trace" },
-#endif
-  {  "xihash",	kdbm_xfs_xihash,	"<xfs_mount_t>",
-				"Dump XFS inode hash statistics"},
-#ifdef XFS_ILOCK_TRACE
-  {  "xilocktrc",kdbm_xfs_xilock_trace,	"<xfs_inode_t>",
-				"Dump XFS ilock trace" },
-  {  "xailcktrc",kdbm_xfs_xailock_trace,"<count>",
-				"Dump XFS global ilock trace" },
-#endif
-  {  "xinodes",	kdbm_xfs_xinodes,	"<xfs_mount_t>",
-				"Dump XFS inodes per mount"},
-  {  "xquiesce",kdbm_xfs_xinodes_quiesce, "<xfs_mount_t>",
-				"Dump non-quiesced XFS inodes per mount"},
-#ifdef XFS_LOG_TRACE
-  {  "xl_grtr",	kdbm_xfs_xlog_granttrace,	"<xlog_t>",
-				"Dump XFS log grant trace" },
-#endif
-  {  "xl_rcit",	kdbm_xfs_xlog_ritem,	"<xlog_recover_item_t>",
-				"Dump XFS recovery item"},
-  {  "xl_rctr",	kdbm_xfs_xlog_rtrans,	"<xlog_recover_t>",
-				"Dump XFS recovery transaction"},
-  {  "xl_rctr2",kdbm_xfs_xlog_rtrans_entire,	"<xlog_recover_t>",
-				"Dump entire recovery transaction"},
-  {  "xl_tic",	kdbm_xfs_xlog_tic,	"<xlog_ticket_t>",
-				"Dump XFS log ticket"},
-  {  "xlog",	kdbm_xfs_xlog,	"<xlog_t>",
-				"Dump XFS log"},
-  {  "xlogcb",	kdbm_xfs_xiclogcb,	"<xlog_in_core_t>",
-				"Dump XFS in-core log callbacks"},
-  {  "xlogitm",	kdbm_xfs_xlogitem,	"<xfs_log_item_t>",
-				"Dump XFS log item structure"},
-  {  "xmount",	kdbm_xfs_xmount,	"<xfs_mount_t>",
-				"Dump XFS mount structure"},
-  {  "xnode",	kdbm_xfs_xnode,		"<xfs_inode_t>",
-				"Dump XFS inode"},
-  {  "xiocore",	kdbm_xfs_xcore,		"<xfs_iocore_t>",
-				"Dump XFS iocore"},
-  {  "xperag",	kdbm_xfs_xperag,	"<xfs_mount_t>",
-				"Dump XFS per-allocation group data"},
-  {  "xqinfo",  kdbm_xfs_xqm_qinfo,	"<xfs_mount_t>",
-				"Dump mount->m_quotainfo structure"},
-#ifdef	CONFIG_XFS_QUOTA
-  {  "xqm",	kdbm_xfs_xqm,		"",
-				"Dump XFS quota manager structure"},
-  {  "xqmfree",	kdbm_xfs_xqm_freelist,	"",
-				"Dump XFS global freelist of dquots"},
-  {  "xqmhtab",	kdbm_xfs_xqm_htab,	"",
-				"Dump XFS hashtable of dquots"},
-#endif	/* CONFIG_XFS_QUOTA */
-  {  "xqmplist",kdbm_xfs_xqm_mplist,	"<xfs_mount_t>",
-				"Dump XFS all dquots of a f/s"},
-#ifdef XFS_RW_TRACE
-  {  "xrwtrc",	kdbm_xfs_xrwtrace,	"<xfs_inode_t>",
-				"Dump XFS inode read/write trace" },
-#endif
-  {  "xsb",	kdbm_xfs_xsb,		"<xfs_sb_t> <cnv>",
-				"Dump XFS superblock"},
-  {  "xtp",	kdbm_xfs_xtp,		"<xfs_trans_t>",
-				"Dump XFS transaction structure"},
-  {  "xtrres",	kdbm_xfs_xtrans_res,	"<xfs_mount_t>",
-				"Dump XFS reservation values"},
-  {  0,		0,	0 }
-};
-
-static struct xif pb_funcs[] = {
-  {  "pb",	kdbm_pb,	"<vaddr>",	"Display page_buf_t" },
-  {  "pbflags",	kdbm_pb_flags,	"<flags>",	"Display page_buf flags" },
-  {  "iomapap",	kdbm_iomap,	"<iomap_t *>",	"Display IOmap" },
-  {  "pbdelay",	kdbm_pbdelay,	"0|1",		"Display delwri pagebufs" },
-#ifdef PAGEBUF_TRACE
-  {  "pbtrace",	kdbm_pbtrace,	"<vaddr>|<count>",	"page_buf_t trace" },
-  {  "pboffset",kdbm_pbtrace_offset, "<daddr> [<mask>]","page_buf_t trace" },
-#endif
-  {  0,		0,	0 }
-};
-
-static int
-__init xfsidbg_init(void)
-{
-	struct xif	*p;
-
-	for (p = xfsidbg_funcs; p->name; p++)
-		kdb_register(p->name, p->func, p->args, p->help, 0);
-	for (p = pb_funcs; p->name; p++)
-		kdb_register(p->name, p->func, p->args, p->help, 0);
-	return 0;
-}
-
-static void
-__exit xfsidbg_exit(void)
-{
-	struct xif	*p;
-
-	for (p = xfsidbg_funcs; p->name; p++)
-		kdb_unregister(p->name);
-	for (p = pb_funcs; p->name; p++)
-		kdb_unregister(p->name);
-}
-
-/*
- * Argument to xfs_alloc routines, for allocation type.
- */
-static char *xfs_alloctype[] = {
-	"any_ag", "first_ag", "start_ag", "this_ag",
-	"start_bno", "near_bno", "this_bno"
-};
-
-static int xargument = 0;
-
-/*
- * Prototypes for static functions.
- */
-#ifdef XFS_ALLOC_TRACE
-static int xfs_alloc_trace_entry(ktrace_entry_t *ktep);
-#endif
-#ifdef XFS_ATTR_TRACE
-static int xfs_attr_trace_entry(ktrace_entry_t *ktep);
-#endif
-#ifdef XFS_BMAP_TRACE
-static int xfs_bmap_trace_entry(ktrace_entry_t *ktep);
-#endif
-#ifdef XFS_BMAP_TRACE
-static int xfs_bmbt_trace_entry(ktrace_entry_t *ktep);
-#endif
-static void xfs_broot(xfs_inode_t *ip, xfs_ifork_t *f);
-static void xfs_btalloc(xfs_alloc_block_t *bt, int bsz);
-static void xfs_btbmap(xfs_bmbt_block_t *bt, int bsz);
-static void xfs_btino(xfs_inobt_block_t *bt, int bsz);
-static void xfs_buf_item_print(xfs_buf_log_item_t *blip, int summary);
-static void xfs_dastate_path(xfs_da_state_path_t *p);
-#ifdef XFS_DIR_TRACE
-static int xfs_dir_trace_entry(ktrace_entry_t *ktep);
-#endif
-#ifdef XFS_DIR2_TRACE
-static int xfs_dir2_trace_entry(ktrace_entry_t *ktep);
-#endif
-static void xfs_dir2data(void *addr, int size);
-static void xfs_dir2leaf(xfs_dir2_leaf_t *leaf, int size);
-static void xfs_dquot_item_print(xfs_dq_logitem_t *lip, int summary);
-static void xfs_efd_item_print(xfs_efd_log_item_t *efdp, int summary);
-static void xfs_efi_item_print(xfs_efi_log_item_t *efip, int summary);
-static char *xfs_fmtformat(xfs_dinode_fmt_t f);
-static char *xfs_fmtfsblock(xfs_fsblock_t bno, xfs_mount_t *mp);
-static char *xfs_fmtino(xfs_ino_t ino, xfs_mount_t *mp);
-static char *xfs_fmtlsn(xfs_lsn_t *lsnp);
-static char *xfs_fmtmode(int m);
-static char *xfs_fmtsize(size_t i);
-static char *xfs_fmtuuid(uuid_t *);
-static void xfs_inode_item_print(xfs_inode_log_item_t *ilip, int summary);
-static void xfs_inodebuf(xfs_buf_t *bp);
-static void xfs_prdinode(xfs_dinode_t *di, int coreonly, int convert);
-static void xfs_prdinode_core(xfs_dinode_core_t *dip, int convert);
-static void xfs_qoff_item_print(xfs_qoff_logitem_t *lip, int summary);
-#ifdef XFS_RW_TRACE
-static void xfs_rw_enter_trace_entry(ktrace_entry_t *ktep);
-static int xfs_rw_trace_entry(ktrace_entry_t *ktep);
-#endif
-static void xfs_xexlist_fork(xfs_inode_t *ip, int whichfork);
-static void xfs_xnode_fork(char *name, xfs_ifork_t *f);
-
-/*
- * Static functions.
- */
-
-#ifdef XFS_ALLOC_TRACE
-/*
- * Print xfs alloc trace buffer entry.
- */
-static int
-xfs_alloc_trace_entry(ktrace_entry_t *ktep)
-{
-	static char *modagf_flags[] = {
-		"magicnum",
-		"versionnum",
-		"seqno",
-		"length",
-		"roots",
-		"levels",
-		"flfirst",
-		"fllast",
-		"flcount",
-		"freeblks",
-		"longest",
-		NULL
-	};
-
-	if (((__psint_t)ktep->val[0] & 0xffff) == 0)
-		return 0;
-	switch ((long)ktep->val[0] & 0xffffL) {
-	case XFS_ALLOC_KTRACE_ALLOC:
-		kdb_printf("alloc %s[%s %ld] mp 0x%p\n",
-			(char *)ktep->val[1],
-			ktep->val[2] ? (char *)ktep->val[2] : "",
-			(long)ktep->val[0] >> 16,
-			(xfs_mount_t *)ktep->val[3]);
-		kdb_printf(
-	"agno %ld agbno %ld minlen %ld maxlen %ld mod %ld prod %ld minleft %ld\n",
-			(long)ktep->val[4],
-			(long)ktep->val[5],
-			(long)ktep->val[6],
-			(long)ktep->val[7],
-			(long)ktep->val[8],
-			(long)ktep->val[9],
-			(long)ktep->val[10]);
-		kdb_printf("total %ld alignment %ld len %ld type %s otype %s\n",
-			(long)ktep->val[11],
-			(long)ktep->val[12],
-			(long)ktep->val[13],
-			xfs_alloctype[((__psint_t)ktep->val[14]) >> 16],
-			xfs_alloctype[((__psint_t)ktep->val[14]) & 0xffff]);
-		kdb_printf("wasdel %d wasfromfl %d isfl %d userdata %d\n",
-			((__psint_t)ktep->val[15] & (1 << 3)) != 0,
-			((__psint_t)ktep->val[15] & (1 << 2)) != 0,
-			((__psint_t)ktep->val[15] & (1 << 1)) != 0,
-			((__psint_t)ktep->val[15] & (1 << 0)) != 0);
-		break;
-	case XFS_ALLOC_KTRACE_FREE:
-		kdb_printf("free %s[%s %ld] mp 0x%p\n",
-			(char *)ktep->val[1],
-			ktep->val[2] ? (char *)ktep->val[2] : "",
-			(long)ktep->val[0] >> 16,
-			(xfs_mount_t *)ktep->val[3]);
-		kdb_printf("agno %ld agbno %ld len %ld isfl %d\n",
-			(long)ktep->val[4],
-			(long)ktep->val[5],
-			(long)ktep->val[6],
-			(__psint_t)ktep->val[7] != 0);
-		break;
-	case XFS_ALLOC_KTRACE_MODAGF:
-		kdb_printf("modagf %s[%s %ld] mp 0x%p\n",
-			(char *)ktep->val[1],
-			ktep->val[2] ? (char *)ktep->val[2] : "",
-			(long)ktep->val[0] >> 16,
-			(xfs_mount_t *)ktep->val[3]);
-		printflags((__psint_t)ktep->val[4], modagf_flags, "modified");
-		kdb_printf("seqno %lu length %lu roots b %lu c %lu\n",
-			(unsigned long)ktep->val[5],
-			(unsigned long)ktep->val[6],
-			(unsigned long)ktep->val[7],
-			(unsigned long)ktep->val[8]);
-		kdb_printf("levels b %lu c %lu flfirst %lu fllast %lu flcount %lu\n",
-			(unsigned long)ktep->val[9],
-			(unsigned long)ktep->val[10],
-			(unsigned long)ktep->val[11],
-			(unsigned long)ktep->val[12],
-			(unsigned long)ktep->val[13]);
-		kdb_printf("freeblks %lu longest %lu\n",
-			(unsigned long)ktep->val[14],
-			(unsigned long)ktep->val[15]);
-		break;
-
-	case XFS_ALLOC_KTRACE_UNBUSY:
-		kdb_printf("unbusy %s [%s %ld] mp 0x%p\n",
-			(char *)ktep->val[1],
-			ktep->val[2] ? (char *)ktep->val[2] : "",
-			(long)ktep->val[0] >> 16,
-			(xfs_mount_t *)ktep->val[3]);
-		kdb_printf("      agno %lu slot %lu tp 0x%p\n",
-			(unsigned long)ktep->val[4],
-			(unsigned long)ktep->val[7],
-			(xfs_trans_t *)ktep->val[8]);
-		break;
-	case XFS_ALLOC_KTRACE_BUSY:
-		kdb_printf("busy %s [%s %ld] mp 0x%p\n",
-			(char *)ktep->val[1],
-			ktep->val[2] ? (char *)ktep->val[2] : "",
-			(long)ktep->val[0] >> 16,
-			(xfs_mount_t *)ktep->val[3]);
-		kdb_printf("      agno %lu agbno %lu len %lu slot %lu tp 0x%p\n",
-			(unsigned long)ktep->val[4],
-			(unsigned long)ktep->val[5],
-			(unsigned long)ktep->val[6],
-			(unsigned long)ktep->val[7],
-			(xfs_trans_t *)ktep->val[8]);
-		break;
-	case XFS_ALLOC_KTRACE_BUSYSEARCH:
-		kdb_printf("busy-search %s [%s %ld] mp 0x%p\n",
-			(char *)ktep->val[1],
-			ktep->val[2] ? (char *)ktep->val[2] : "",
-			(long)ktep->val[0] >> 16,
-			(xfs_mount_t *)ktep->val[3]);
-		kdb_printf("      agno %ld agbno %ld len %ld slot %ld tp 0x%p\n",
-			(unsigned long)ktep->val[4],
-			(unsigned long)ktep->val[5],
-			(unsigned long)ktep->val[6],
-			(unsigned long)ktep->val[7],
-			(xfs_trans_t *)ktep->val[8]);
-		break;
-	default:
-		kdb_printf("unknown alloc trace record\n");
-		break;
-	}
-	return 1;
-}
-#endif /* XFS_ALLOC_TRACE */
-
-#ifdef XFS_ATTR_TRACE
-/*
- * Print an attribute trace buffer entry.
- */
-static int
-xfs_attr_trace_entry(ktrace_entry_t *ktep)
-{
-	static char *attr_arg_flags[] = {
-		"DONTFOLLOW",	/* 0x0001 */
-		"ROOT",		/* 0x0002 */
-		"TRUSTED",	/* 0x0004 */
-		"?",		/* 0x0008 */
-		"CREATE",	/* 0x0010 */
-		"REPLACE",	/* 0x0020 */
-		"?",		/* 0x0040 */
-		"?",		/* 0x0080 */
-		"SYSTEM",	/* 0x0100 */
-		"?",		/* 0x0200 */
-		"?",		/* 0x0400 */
-		"?",		/* 0x0800 */
-		"KERNOTIME",	/* 0x1000 */
-		"KERNOVAL",	/* 0x2000 */
-		"KERNAMELS",	/* 0x4000 */
-		"KERNFULLS",	/* 0x8000 */
-		NULL
-	};
-
-	if (!ktep->val[0])
-		return 0;
-
-	qprintf("-- %s: cursor h/b/o 0x%lx/0x%lx/%lu, dupcnt %lu, dp 0x%p\n",
-		 (char *)ktep->val[1],
-		 (unsigned long)ktep->val[3],
-		 (unsigned long)ktep->val[4],
-		 (unsigned long)ktep->val[5],
-		 (unsigned long)ktep->val[11],
-		 (xfs_inode_t *)ktep->val[2]);
-	qprintf("   alist 0x%p, size %lu, count %lu, firstu %lu, Llen %lu",
-		 (attrlist_t *)ktep->val[6],
-		 (unsigned long)ktep->val[7],
-		 (unsigned long)ktep->val[8],
-		 (unsigned long)ktep->val[9],
-		 (unsigned long)ktep->val[10]);
-	printflags((__psunsigned_t)(ktep->val[12]), attr_arg_flags, ", flags");
-	qprintf("\n");
-
-	switch ((__psint_t)ktep->val[0]) {
-	case XFS_ATTR_KTRACE_L_C:
-		break;
-	case XFS_ATTR_KTRACE_L_CN:
-		qprintf("   node: count %lu, 1st hash 0x%lx, last hash 0x%lx\n",
-			 (unsigned long)ktep->val[13],
-			 (unsigned long)ktep->val[14],
-			 (unsigned long)ktep->val[15]);
-		break;
-	case XFS_ATTR_KTRACE_L_CB:
-		qprintf("   btree: hash 0x%lx, blkno 0x%lx\n",
-			 (unsigned long)ktep->val[13],
-			 (unsigned long)ktep->val[14]);
-		break;
-	case XFS_ATTR_KTRACE_L_CL:
-		qprintf("   leaf: count %ld, 1st hash 0x%lx, last hash 0x%lx\n",
-			 (unsigned long)ktep->val[13],
-			 (unsigned long)ktep->val[14],
-			 (unsigned long)ktep->val[15]);
-		break;
-	default:
-		qprintf("   unknown attr trace record format\n");
-		break;
-	}
-	return 1;
-}
-#endif /* XFS_ATTR_TRACE */
-
-#ifdef XFS_BMAP_TRACE
-/*
- * Print xfs bmap extent trace buffer entry.
- */
-static int
-xfs_bmap_trace_entry(ktrace_entry_t *ktep)
-{
-	xfs_dfsbno_t	    b;
-	xfs_dfilblks_t	  c;
-	xfs_inode_t	     *ip;
-	xfs_ino_t	       ino;
-	xfs_dfiloff_t	   o;
-	int		     flag;
-	int		     opcode;
-	static char	     *ops[] = { "del", "ins", "pre", "post" };
-	xfs_bmbt_rec_32_t       r;
-	int		     whichfork;
-
-	opcode = ((__psint_t)ktep->val[0]) & 0xffff;
-	if (opcode == 0)
-		return 0;
-	whichfork = ((__psint_t)ktep->val[0]) >> 16;
-	ip = (xfs_inode_t *)ktep->val[3];
-	ino = ((xfs_ino_t)(unsigned long)ktep->val[6] << 32) |
-		((xfs_ino_t)(unsigned long)ktep->val[7]);
-	qprintf("%s %s:%s ip %p ino %s %cf\n",
-		ops[opcode - 1], (char *)ktep->val[1],
-		(char *)ktep->val[2], ip, xfs_fmtino(ino, ip->i_mount),
-		"da"[whichfork]);
-	r.l0 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[8];
-	r.l1 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[9];
-	r.l2 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[10];
-	r.l3 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[11];
-	xfs_convert_extent(&r, &o, &b, &c, &flag);
-	qprintf(" idx %ld offset %lld block %s",
-		(long)ktep->val[4], o,
-		xfs_fmtfsblock((xfs_fsblock_t)b, ip->i_mount));
-	qprintf(" count %lld flag %d\n", c, flag);
-	if ((__psint_t)ktep->val[5] != 2)
-		return 1;
-	r.l0 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[12];
-	r.l1 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[13];
-	r.l2 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[14];
-	r.l3 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[15];
-	xfs_convert_extent(&r, &o, &b, &c, &flag);
-	qprintf(" offset %lld block %s", o,
-		xfs_fmtfsblock((xfs_fsblock_t)b, ip->i_mount));
-	qprintf(" count %lld flag %d\n", c, flag);
-	return 1;
-}
-
-/*
- * Print xfs bmap btree trace buffer entry.
- */
-static int
-xfs_bmbt_trace_entry(
-	ktrace_entry_t	  *ktep)
-{
-	int			line;
-	xfs_bmbt_rec_32_t	r;
-	xfs_bmbt_irec_t		s;
-	int			type;
-	int			whichfork;
-
-	type = (__psint_t)ktep->val[0] & 0xff;
-	if (type == 0)
-		return 0;
-	whichfork = ((__psint_t)ktep->val[0] >> 8) & 0xff;
-	line = ((__psint_t)ktep->val[0] >> 16) & 0xffff;
-	qprintf("%s[%s@%d] ip 0x%p %cf cur 0x%p\n",
-		(char *)ktep->val[1],
-		(char *)ktep->val[2],
-		line,
-		(xfs_inode_t *)ktep->val[3],
-		"da"[whichfork],
-		(xfs_btree_cur_t *)ktep->val[4]);
-	switch (type) {
-	case XFS_BMBT_KTRACE_ARGBI:
-		qprintf(" buf 0x%p i %ld\n",
-			(xfs_buf_t *)ktep->val[5],
-			(long)ktep->val[6]);
-		break;
-	case XFS_BMBT_KTRACE_ARGBII:
-		qprintf(" buf 0x%p i0 %ld i1 %ld\n",
-			(xfs_buf_t *)ktep->val[5],
-			(long)ktep->val[6],
-			(long)ktep->val[7]);
-		break;
-	case XFS_BMBT_KTRACE_ARGFFFI:
-		qprintf(" o 0x%x%08x b 0x%x%08x i 0x%x%08x j %ld\n",
-			(unsigned int)(long)ktep->val[5],
-			(unsigned int)(long)ktep->val[6],
-			(unsigned int)(long)ktep->val[7],
-			(unsigned int)(long)ktep->val[8],
-			(unsigned int)(long)ktep->val[9],
-			(unsigned int)(long)ktep->val[10],
-			(long)ktep->val[11]);
-		break;
-	case XFS_BMBT_KTRACE_ARGI:
-		qprintf(" i 0x%lx\n",
-			(long)ktep->val[5]);
-		break;
-	case XFS_BMBT_KTRACE_ARGIFK:
-		qprintf(" i 0x%lx f 0x%x%08x o 0x%x%08x\n",
-			(long)ktep->val[5],
-			(unsigned int)(long)ktep->val[6],
-			(unsigned int)(long)ktep->val[7],
-			(unsigned int)(long)ktep->val[8],
-			(unsigned int)(long)ktep->val[9]);
-		break;
-	case XFS_BMBT_KTRACE_ARGIFR:
-		qprintf(" i 0x%lx f 0x%x%08x ",
-			(long)ktep->val[5],
-			(unsigned int)(long)ktep->val[6],
-			(unsigned int)(long)ktep->val[7]);
-		s.br_startoff = (xfs_fileoff_t)
-			(((xfs_dfiloff_t)(unsigned long)ktep->val[8] << 32) |
-				(xfs_dfiloff_t)(unsigned long)ktep->val[9]);
-		s.br_startblock = (xfs_fsblock_t)
-			(((xfs_dfsbno_t)(unsigned long)ktep->val[10] << 32) |
-				(xfs_dfsbno_t)(unsigned long)ktep->val[11]);
-		s.br_blockcount = (xfs_filblks_t)
-			(((xfs_dfilblks_t)(unsigned long)ktep->val[12] << 32) |
-				(xfs_dfilblks_t)(unsigned long)ktep->val[13]);
-		xfsidbg_xbirec(&s);
-		break;
-	case XFS_BMBT_KTRACE_ARGIK:
-		qprintf(" i 0x%lx o 0x%x%08x\n",
-			(long)ktep->val[5],
-			(unsigned int)(long)ktep->val[6],
-			(unsigned int)(long)ktep->val[7]);
-		break;
-	case XFS_BMBT_KTRACE_CUR:
-		qprintf(" nlevels %ld flags %ld allocated %ld ",
-			((long)ktep->val[5] >> 24) & 0xff,
-			((long)ktep->val[5] >> 16) & 0xff,
-			(long)ktep->val[5] & 0xffff);
-		r.l0 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[6];
-		r.l1 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[7];
-		r.l2 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[8];
-		r.l3 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[9];
-		xfsidbg_xbrec((xfs_bmbt_rec_64_t *)&r);
-		qprintf(" bufs 0x%p 0x%p 0x%p 0x%p ",
-			(xfs_buf_t *)ktep->val[10],
-			(xfs_buf_t *)ktep->val[11],
-			(xfs_buf_t *)ktep->val[12],
-			(xfs_buf_t *)ktep->val[13]);
-		qprintf("ptrs %ld %ld %ld %ld\n",
-			(long)ktep->val[14] >> 16,
-			(long)ktep->val[14] & 0xffff,
-			(long)ktep->val[15] >> 16,
-			(long)ktep->val[15] & 0xffff);
-		break;
-	default:
-		qprintf("unknown bmbt trace record\n");
-		break;
-	}
-	return 1;
-}
-#endif
-
-/*
- * Print an xfs in-inode bmap btree root.
- */
-static void
-xfs_broot(xfs_inode_t *ip, xfs_ifork_t *f)
-{
-	xfs_bmbt_block_t	*broot;
-	int			format;
-	int			i;
-	xfs_bmbt_key_t		*kp;
-	xfs_bmbt_ptr_t		*pp;
-
-	format = f == &ip->i_df ? ip->i_d.di_format : ip->i_d.di_aformat;
-	if ((f->if_flags & XFS_IFBROOT) == 0 ||
-	    format != XFS_DINODE_FMT_BTREE) {
-		kdb_printf("inode 0x%p not btree format\n", ip);
-		return;
-	}
-	broot = f->if_broot;
-	kdb_printf("block @0x%p magic %x level %d numrecs %d\n",
-		broot, INT_GET(broot->bb_magic, ARCH_CONVERT), INT_GET(broot->bb_level, ARCH_CONVERT), INT_GET(broot->bb_numrecs, ARCH_CONVERT));
-	kp = XFS_BMAP_BROOT_KEY_ADDR(broot, 1, f->if_broot_bytes);
-	pp = XFS_BMAP_BROOT_PTR_ADDR(broot, 1, f->if_broot_bytes);
-	for (i = 1; i <= INT_GET(broot->bb_numrecs, ARCH_CONVERT); i++)
-		kdb_printf("\t%d: startoff %Ld ptr %Lx %s\n",
-			i, INT_GET(kp[i - 1].br_startoff, ARCH_CONVERT), INT_GET(pp[i - 1], ARCH_CONVERT),
-			xfs_fmtfsblock(INT_GET(pp[i - 1], ARCH_CONVERT), ip->i_mount));
-}
-
-/*
- * Print allocation btree block.
- */
-static void
-xfs_btalloc(xfs_alloc_block_t *bt, int bsz)
-{
-	int i;
-
-	kdb_printf("magic 0x%x level %d numrecs %d leftsib 0x%x rightsib 0x%x\n",
-		INT_GET(bt->bb_magic, ARCH_CONVERT), INT_GET(bt->bb_level, ARCH_CONVERT), INT_GET(bt->bb_numrecs, ARCH_CONVERT),
-		INT_GET(bt->bb_leftsib, ARCH_CONVERT), INT_GET(bt->bb_rightsib, ARCH_CONVERT));
-	if (INT_ISZERO(bt->bb_level, ARCH_CONVERT)) {
-
-		for (i = 1; i <= INT_GET(bt->bb_numrecs, ARCH_CONVERT); i++) {
-			xfs_alloc_rec_t *r;
-
-			r = XFS_BTREE_REC_ADDR(bsz, xfs_alloc, bt, i, 0);
-			kdb_printf("rec %d startblock 0x%x blockcount %d\n",
-				i, INT_GET(r->ar_startblock, ARCH_CONVERT), INT_GET(r->ar_blockcount, ARCH_CONVERT));
-		}
-	} else {
-		int mxr;
-
-		mxr = XFS_BTREE_BLOCK_MAXRECS(bsz, xfs_alloc, 0);
-		for (i = 1; i <= INT_GET(bt->bb_numrecs, ARCH_CONVERT); i++) {
-			xfs_alloc_key_t *k;
-			xfs_alloc_ptr_t *p;
-
-			k = XFS_BTREE_KEY_ADDR(bsz, xfs_alloc, bt, i, mxr);
-			p = XFS_BTREE_PTR_ADDR(bsz, xfs_alloc, bt, i, mxr);
-			kdb_printf("key %d startblock 0x%x blockcount %d ptr 0x%x\n",
-				i, INT_GET(k->ar_startblock, ARCH_CONVERT), INT_GET(k->ar_blockcount, ARCH_CONVERT), *p);
-		}
-	}
-}
-
-/*
- * Print a bmap btree block.
- */
-static void
-xfs_btbmap(xfs_bmbt_block_t *bt, int bsz)
-{
-	int i;
-
-	kdb_printf("magic 0x%x level %d numrecs %d leftsib %Lx ",
-		INT_GET(bt->bb_magic, ARCH_CONVERT),
-		INT_GET(bt->bb_level, ARCH_CONVERT),
-		INT_GET(bt->bb_numrecs, ARCH_CONVERT),
-		INT_GET(bt->bb_leftsib, ARCH_CONVERT));
-	kdb_printf("rightsib %Lx\n", INT_GET(bt->bb_rightsib, ARCH_CONVERT));
-	if (INT_ISZERO(bt->bb_level, ARCH_CONVERT)) {
-		for (i = 1; i <= INT_GET(bt->bb_numrecs, ARCH_CONVERT); i++) {
-			xfs_bmbt_rec_t *r;
-			xfs_bmbt_irec_t	irec;
-
-			r = (xfs_bmbt_rec_t *)XFS_BTREE_REC_ADDR(bsz,
-				xfs_bmbt, bt, i, 0);
-
-			xfs_bmbt_disk_get_all((xfs_bmbt_rec_t *)r, &irec);
-			kdb_printf("rec %d startoff %Ld startblock %Lx blockcount %Ld flag %d\n",
-				i, irec.br_startoff,
-				(__uint64_t)irec.br_startblock,
-				irec.br_blockcount, irec.br_state);
-		}
-	} else {
-		int mxr;
-
-		mxr = XFS_BTREE_BLOCK_MAXRECS(bsz, xfs_bmbt, 0);
-		for (i = 1; i <= INT_GET(bt->bb_numrecs, ARCH_CONVERT); i++) {
-			xfs_bmbt_key_t *k;
-			xfs_bmbt_ptr_t *p;
-
-			k = XFS_BTREE_KEY_ADDR(bsz, xfs_bmbt, bt, i, mxr);
-			p = XFS_BTREE_PTR_ADDR(bsz, xfs_bmbt, bt, i, mxr);
-			kdb_printf("key %d startoff %Ld ",
-				i, INT_GET(k->br_startoff, ARCH_CONVERT));
-			kdb_printf("ptr %Lx\n", INT_GET(*p, ARCH_CONVERT));
-		}
-	}
-}
-
-/*
- * Print an inode btree block.
- */
-static void
-xfs_btino(xfs_inobt_block_t *bt, int bsz)
-{
-	int i;
-
-	kdb_printf("magic 0x%x level %d numrecs %d leftsib 0x%x rightsib 0x%x\n",
-		INT_GET(bt->bb_magic, ARCH_CONVERT),
-		INT_GET(bt->bb_level, ARCH_CONVERT),
-		INT_GET(bt->bb_numrecs, ARCH_CONVERT),
-		INT_GET(bt->bb_leftsib, ARCH_CONVERT),
-		INT_GET(bt->bb_rightsib, ARCH_CONVERT));
-	if (INT_ISZERO(bt->bb_level, ARCH_CONVERT)) {
-
-		for (i = 1; i <= INT_GET(bt->bb_numrecs, ARCH_CONVERT); i++) {
-			xfs_inobt_rec_t *r;
-
-			r = XFS_BTREE_REC_ADDR(bsz, xfs_inobt, bt, i, 0);
-			kdb_printf("rec %d startino 0x%x freecount %d, free %Lx\n",
-				i, INT_GET(r->ir_startino, ARCH_CONVERT),
-				INT_GET(r->ir_freecount, ARCH_CONVERT),
-				INT_GET(r->ir_free, ARCH_CONVERT));
-		}
-	} else {
-		int mxr;
-
-		mxr = XFS_BTREE_BLOCK_MAXRECS(bsz, xfs_inobt, 0);
-		for (i = 1; i <= INT_GET(bt->bb_numrecs, ARCH_CONVERT); i++) {
-			xfs_inobt_key_t *k;
-			xfs_inobt_ptr_t *p;
-
-			k = XFS_BTREE_KEY_ADDR(bsz, xfs_inobt, bt, i, mxr);
-			p = XFS_BTREE_PTR_ADDR(bsz, xfs_inobt, bt, i, mxr);
-			kdb_printf("key %d startino 0x%x ptr 0x%x\n",
-				i, INT_GET(k->ir_startino, ARCH_CONVERT),
-				INT_GET(*p, ARCH_CONVERT));
-		}
-	}
-}
-
-/*
- * Print a buf log item.
- */
-static void
-xfs_buf_item_print(xfs_buf_log_item_t *blip, int summary)
-{
-	static char *bli_flags[] = {
-		"hold",		/* 0x1 */
-		"dirty",	/* 0x2 */
-		"stale",	/* 0x4 */
-		"logged",	/* 0x8 */
-		"ialloc",	/* 0x10 */
-		"inode_stale",  /* 0x20 */
-		0
-		};
-	static char *blf_flags[] = {
-		"inode",	/* 0x1 */
-		"cancel",	/* 0x2 */
-		0
-		};
-
-	if (summary) {
-		kdb_printf("buf 0x%p blkno 0x%Lx ", blip->bli_buf,
-			     blip->bli_format.blf_blkno);
-		printflags(blip->bli_flags, bli_flags, "flags:");
-		kdb_printf("\n   ");
-		xfsidbg_xbuf_real(blip->bli_buf, 1);
-		return;
-	}
-	kdb_printf("buf 0x%p recur %d refcount %d flags:",
-		blip->bli_buf, blip->bli_recur,
-		atomic_read(&blip->bli_refcount));
-	printflags(blip->bli_flags, bli_flags, NULL);
-	kdb_printf("\n");
-	kdb_printf("size %d blkno 0x%Lx len 0x%x map size %d map 0x%p\n",
-		blip->bli_format.blf_size, blip->bli_format.blf_blkno,
-		(uint) blip->bli_format.blf_len, blip->bli_format.blf_map_size,
-		&(blip->bli_format.blf_data_map[0]));
-	kdb_printf("blf flags: ");
-	printflags((uint)blip->bli_format.blf_flags, blf_flags, NULL);
-#ifdef XFS_TRANS_DEBUG
-	kdb_printf("orig 0x%x logged 0x%x",
-		blip->bli_orig, blip->bli_logged);
-#endif
-	kdb_printf("\n");
-}
-
-#ifdef XFS_BMAP_TRACE
-/*
- * Convert an external extent descriptor to internal form.
- */
-static void
-xfs_convert_extent(xfs_bmbt_rec_32_t *rp, xfs_dfiloff_t *op, xfs_dfsbno_t *sp,
-		   xfs_dfilblks_t *cp, int *fp)
-{
-	xfs_dfiloff_t o;
-	xfs_dfsbno_t s;
-	xfs_dfilblks_t c;
-	int flag;
-
-	flag = (((xfs_dfiloff_t)rp->l0) >> 31) & 1;
-	o = ((((xfs_dfiloff_t)rp->l0) & 0x7fffffff) << 23) |
-	    (((xfs_dfiloff_t)rp->l1) >> 9);
-	s = (((xfs_dfsbno_t)(rp->l1 & 0x000001ff)) << 43) |
-	    (((xfs_dfsbno_t)rp->l2) << 11) |
-	    (((xfs_dfsbno_t)rp->l3) >> 21);
-	c = (xfs_dfilblks_t)(rp->l3 & 0x001fffff);
-	*op = o;
-	*sp = s;
-	*cp = c;
-	*fp = flag;
-}
-#endif
-
-#ifdef XFS_RW_TRACE
-/*
- * Print itrunc entry trace.
- */
-static void
-xfs_ctrunc_trace_entry(ktrace_entry_t	*ktep)
-{
-	qprintf("ip 0x%p cpu %ld\n",
-		(xfs_inode_t *)(unsigned long)ktep->val[1], (long)ktep->val[2]);
-}
-#endif
-
-/*
- * Print an xfs_da_state_path structure.
- */
-static void
-xfs_dastate_path(xfs_da_state_path_t *p)
-{
-	int i;
-
-	kdb_printf("active %d\n", p->active);
-	for (i = 0; i < XFS_DA_NODE_MAXDEPTH; i++) {
-		kdb_printf(" blk %d bp 0x%p blkno 0x%x",
-			i, p->blk[i].bp, p->blk[i].blkno);
-		kdb_printf(" index %d hashval 0x%x ",
-			p->blk[i].index, (uint_t)p->blk[i].hashval);
-		switch(p->blk[i].magic) {
-		case XFS_DA_NODE_MAGIC:		kdb_printf("NODE\n");	break;
-		case XFS_DIR_LEAF_MAGIC:	kdb_printf("DIR\n");	break;
-		case XFS_ATTR_LEAF_MAGIC:	kdb_printf("ATTR\n");	break;
-		case XFS_DIR2_LEAFN_MAGIC:	kdb_printf("DIR2\n");	break;
-		default:			kdb_printf("type ?\n");	break;
-		}
-	}
-}
-
-#ifdef XFS_DIR_TRACE
-/*
- * Print a xfs directory trace buffer entry.
- */
-static int
-xfs_dir_trace_entry(ktrace_entry_t *ktep)
-{
-	xfs_mount_t *mp;
-	__uint32_t hash;
-	xfs_off_t cookie;
-
-	if (!ktep->val[0] || !ktep->val[1])
-		return 0;
-
-	mp = (xfs_mount_t *)ktep->val[3];
-	cookie = (__psunsigned_t)ktep->val[4];
-	cookie <<= 32;
-	cookie |= (__psunsigned_t)ktep->val[5];
-	qprintf("%s -- dp=0x%p b/e/h=%ld/%ld/0x%08lx resid=0x%lx ",
-		    (char *)ktep->val[1],
-		    (xfs_inode_t *)ktep->val[2],
-		    (long)XFS_DA_COOKIE_BNO(mp, cookie),
-		    (long)XFS_DA_COOKIE_ENTRY(mp, cookie),
-		    (unsigned long)XFS_DA_COOKIE_HASH(mp, cookie),
-		    (long)ktep->val[6]);
-
-	switch ((__psint_t)ktep->val[0]) {
-	case XFS_DIR_KTRACE_G_DU:
-		break;
-	case XFS_DIR_KTRACE_G_DUB:
-		qprintf("bno=%ld", (long)ktep->val[7]);
-		break;
-	case XFS_DIR_KTRACE_G_DUN:
-		qprintf("forw=%ld, cnt=%ld, 0x%08lx - 0x%08lx",
-			      (long)ktep->val[7],
-			      (long)ktep->val[8],
-			      (unsigned long)ktep->val[9],
-			      (unsigned long)ktep->val[10]);
-		break;
-	case XFS_DIR_KTRACE_G_DUL:
-		qprintf("forw=%ld, cnt=%ld, 0x%08lx - 0x%08lx",
-			      (long)ktep->val[7],
-			      (long)ktep->val[8],
-			      (unsigned long)ktep->val[9],
-			      (unsigned long)ktep->val[10]);
-		break;
-	case XFS_DIR_KTRACE_G_DUE:
-		qprintf("entry hashval 0x%08lx", (unsigned long)ktep->val[7]);
-		break;
-	case XFS_DIR_KTRACE_G_DUC:
-		cookie = (__psunsigned_t)ktep->val[7];
-		cookie <<= 32;
-		cookie |= (__psunsigned_t)ktep->val[8];
-		hash = XFS_DA_COOKIE_HASH(mp, cookie);
-		qprintf("b/e/h=%ld/%ld/0x%08x",
-		    (long)XFS_DA_COOKIE_BNO(mp, cookie),
-		    (long)XFS_DA_COOKIE_ENTRY(mp, cookie),
-		    hash);
-		break;
-	default:
-		qprintf("unknown dir trace record format");
-		break;
-	}
-	return 1;
-}
-#endif
-
-#ifdef XFS_DIR2_TRACE
-/*
- * Print a xfs v2 directory trace buffer entry.
- */
-static int
-xfs_dir2_trace_entry(ktrace_entry_t *ktep)
-{
-	char	    *cp;
-	int	     i;
-	int	     len;
-
-	if (!ktep->val[0])
-		return 0;
-	cp = (char *)&ktep->val[10];
-	qprintf("%s: '", (char *)ktep->val[1]);
-	len = min((__psint_t)ktep->val[9], (__psint_t)sizeof(ktep->val[10])*6);
-	for (i = 0; i < len; i++)
-		qprintf("%c", cp[i]);
-	qprintf("'(%ld)", (long)ktep->val[9]);
-	if ((__psunsigned_t)ktep->val[0] != XFS_DIR2_KTRACE_ARGS_BIBII)
-		qprintf(" hashval 0x%llx inumber %lld dp 0x%p tp 0x%p check %d",
-			(__uint64_t)(unsigned long)ktep->val[2],
-			(__int64_t)(unsigned long)ktep->val[3],
-			ktep->val[4], ktep->val[5],
-			(int)(__psint_t)ktep->val[6]);
-	switch ((__psunsigned_t)ktep->val[0]) {
-	case XFS_DIR2_KTRACE_ARGS:
-		break;
-	case XFS_DIR2_KTRACE_ARGS_B:
-		qprintf(" bp 0x%p", ktep->val[7]);
-		break;
-	case XFS_DIR2_KTRACE_ARGS_BB:
-		qprintf(" lbp 0x%p dbp 0x%p", ktep->val[7], ktep->val[8]);
-		break;
-	case XFS_DIR2_KTRACE_ARGS_BIBII:
-		qprintf(" dp 0x%p tp 0x%p srcbp 0x%p srci %d dstbp 0x%p dsti %d count %d",
-			ktep->val[2], ktep->val[3], ktep->val[4],
-			(int)(__psint_t)ktep->val[5], ktep->val[6],
-			(int)(__psint_t)ktep->val[7],
-			(int)(__psint_t)ktep->val[8]);
-		break;
-	case XFS_DIR2_KTRACE_ARGS_DB:
-		qprintf(" db 0x%x bp 0x%p",
-			(xfs_dir2_db_t)(unsigned long)ktep->val[7],
-			ktep->val[8]);
-		break;
-	case XFS_DIR2_KTRACE_ARGS_I:
-		qprintf(" i 0x%lx", (unsigned long)ktep->val[7]);
-		break;
-	case XFS_DIR2_KTRACE_ARGS_S:
-		qprintf(" s 0x%x", (int)(__psint_t)ktep->val[7]);
-		break;
-	case XFS_DIR2_KTRACE_ARGS_SB:
-		qprintf(" s 0x%x bp 0x%p", (int)(__psint_t)ktep->val[7],
-			ktep->val[8]);
-		break;
-	default:
-		qprintf("unknown dirv2 trace record format");
-		break;
-	}
-	return 1;
-}
-#endif
-
-/*
- * Print an efd log item.
- */
-static void
-xfs_efd_item_print(xfs_efd_log_item_t *efdp, int summary)
-{
-	int		i;
-	xfs_extent_t	*ep;
-
-	if (summary) {
-		kdb_printf("Extent Free Done: ID 0x%Lx nextents %d (at 0x%p)\n",
-				efdp->efd_format.efd_efi_id,
-				efdp->efd_format.efd_nextents, efdp);
-		return;
-	}
-	kdb_printf("size %d nextents %d next extent %d efip 0x%p\n",
-		efdp->efd_format.efd_size, efdp->efd_format.efd_nextents,
-		efdp->efd_next_extent, efdp->efd_efip);
-	kdb_printf("efi_id 0x%Lx\n", efdp->efd_format.efd_efi_id);
-	kdb_printf("efd extents:\n");
-	ep = &(efdp->efd_format.efd_extents[0]);
-	for (i = 0; i < efdp->efd_next_extent; i++, ep++) {
-		kdb_printf("    block %Lx len %d\n",
-			ep->ext_start, ep->ext_len);
-	}
-}
-
-/*
- * Print an efi log item.
- */
-static void
-xfs_efi_item_print(xfs_efi_log_item_t *efip, int summary)
-{
-	int		i;
-	xfs_extent_t	*ep;
-	static char *efi_flags[] = {
-		"recovered",	/* 0x1 */
-		"committed",	/* 0x2 */
-		"cancelled",	/* 0x4 */
-		0,
-		};
-
-	if (summary) {
-		kdb_printf("Extent Free Intention: ID 0x%Lx nextents %d (at 0x%p)\n",
-				efip->efi_format.efi_id,
-				efip->efi_format.efi_nextents, efip);
-		return;
-	}
-	kdb_printf("size %d nextents %d next extent %d\n",
-		efip->efi_format.efi_size, efip->efi_format.efi_nextents,
-		efip->efi_next_extent);
-	kdb_printf("id %Lx", efip->efi_format.efi_id);
-	printflags(efip->efi_flags, efi_flags, "flags :");
-	kdb_printf("\n");
-	kdb_printf("efi extents:\n");
-	ep = &(efip->efi_format.efi_extents[0]);
-	for (i = 0; i < efip->efi_next_extent; i++, ep++) {
-		kdb_printf("    block %Lx len %d\n",
-			ep->ext_start, ep->ext_len);
-	}
-}
-
-/*
- * Format inode "format" into a static buffer & return it.
- */
-static char *
-xfs_fmtformat(xfs_dinode_fmt_t f)
-{
-	static char *t[] = {
-		"dev",
-		"local",
-		"extents",
-		"btree",
-		"uuid"
-	};
-
-	return t[f];
-}
-
-/*
- * Format fsblock number into a static buffer & return it.
- */
-static char *
-xfs_fmtfsblock(xfs_fsblock_t bno, xfs_mount_t *mp)
-{
-	static char rval[50];
-
-	if (bno == NULLFSBLOCK)
-		sprintf(rval, "NULLFSBLOCK");
-	else if (ISNULLSTARTBLOCK(bno))
-		sprintf(rval, "NULLSTARTBLOCK(%Ld)", STARTBLOCKVAL(bno));
-	else if (mp)
-		sprintf(rval, "%Ld[%x:%x]", (xfs_dfsbno_t)bno,
-			XFS_FSB_TO_AGNO(mp, bno), XFS_FSB_TO_AGBNO(mp, bno));
-	else
-		sprintf(rval, "%Ld", (xfs_dfsbno_t)bno);
-	return rval;
-}
-
-/*
- * Format inode number into a static buffer & return it.
- */
-static char *
-xfs_fmtino(xfs_ino_t ino, xfs_mount_t *mp)
-{
-	static char rval[50];
-
-	if (mp)
-		sprintf(rval, "%llu[%x:%x:%x]",
-			(unsigned long long) ino,
-			XFS_INO_TO_AGNO(mp, ino),
-			XFS_INO_TO_AGBNO(mp, ino),
-			XFS_INO_TO_OFFSET(mp, ino));
-	else
-		sprintf(rval, "%llu", (unsigned long long) ino);
-	return rval;
-}
-
-/*
- * Format an lsn for printing into a static buffer & return it.
- */
-static char *
-xfs_fmtlsn(xfs_lsn_t *lsnp)
-{
-	uint		*wordp;
-	uint		*word2p;
-	static char	buf[20];
-
-	wordp = (uint *)lsnp;
-	word2p = wordp++;
-	sprintf(buf, "[%u:%u]", *wordp, *word2p);
-
-	return buf;
-}
-
-/*
- * Format file mode into a static buffer & return it.
- */
-static char *
-xfs_fmtmode(int m)
-{
-	static char rval[16];
-
-	sprintf(rval, "%c%c%c%c%c%c%c%c%c%c%c%c%c",
-		"?fc?dxb?r?l?S?m?"[(m & S_IFMT) >> 12],
-		m & S_ISUID ? 'u' : '-',
-		m & S_ISGID ? 'g' : '-',
-		m & S_ISVTX ? 'v' : '-',
-		m & S_IRUSR ? 'r' : '-',
-		m & S_IWUSR ? 'w' : '-',
-		m & S_IXUSR ? 'x' : '-',
-		m & S_IRGRP ? 'r' : '-',
-		m & S_IWGRP ? 'w' : '-',
-		m & S_IXGRP ? 'x' : '-',
-		m & S_IROTH ? 'r' : '-',
-		m & S_IWOTH ? 'w' : '-',
-		m & S_IXOTH ? 'x' : '-');
-	return rval;
-}
-
-/*
- * Format a size into a static buffer & return it.
- */
-static char *
-xfs_fmtsize(size_t i)
-{
-	static char rval[20];
-
-	/* size_t is 32 bits in 32-bit kernel, 64 bits in 64-bit kernel */
-	sprintf(rval, "0x%lx", (unsigned long) i);
-	return rval;
-}
-
-/*
- * Format a uuid into a static buffer & return it.
- */
-static char *
-xfs_fmtuuid(uuid_t *uu)
-{
-	static char rval[40];
-	char	*o	  = rval;
-	char	*i	  = (unsigned char*)uu;
-	int	 b;
-
-	for (b=0;b<16;b++) {
-	    o+=sprintf(o, "%02x", *i++);
-	    if (b==3||b==5||b==7||b==9) *o++='-';
-	}
-	*o='\0';
-
-	return rval;
-}
-
-/*
- * Print an inode log item.
- */
-static void
-xfs_inode_item_print(xfs_inode_log_item_t *ilip, int summary)
-{
-	static char *ili_flags[] = {
-		"hold",		/* 0x1 */
-		"iolock excl",	/* 0x2 */
-		"iolock shrd",	/* 0x4 */
-		0
-		};
-	static char *ilf_fields[] = {
-		"core",		/* 0x001 */
-		"ddata",	/* 0x002 */
-		"dexts",	/* 0x004 */
-		"dbroot",	/* 0x008 */
-		"dev",		/* 0x010 */
-		"uuid",		/* 0x020 */
-		"adata",	/* 0x040 */
-		"aext",		/* 0x080 */
-		"abroot",	/* 0x100 */
-		0
-		};
-
-	if (summary) {
-		kdb_printf("inode 0x%p logged %d ",
-			ilip->ili_inode, ilip->ili_logged);
-		printflags(ilip->ili_flags, ili_flags, "flags:");
-		printflags(ilip->ili_format.ilf_fields, ilf_fields, "format:");
-		printflags(ilip->ili_last_fields, ilf_fields, "lastfield:");
-		kdb_printf("\n");
-		return;
-	}
-	kdb_printf("inode 0x%p ino 0x%llu pushbuf %d logged %d flags: ",
-		ilip->ili_inode, (unsigned long long) ilip->ili_format.ilf_ino,
-		ilip->ili_pushbuf_flag, ilip->ili_logged);
-	printflags(ilip->ili_flags, ili_flags, NULL);
-	kdb_printf("\n");
-	kdb_printf("ilock recur %d iolock recur %d ext buf 0x%p\n",
-		ilip->ili_ilock_recur, ilip->ili_iolock_recur,
-		ilip->ili_extents_buf);
-#ifdef XFS_TRANS_DEBUG
-	kdb_printf("root bytes %d root orig 0x%x\n",
-		ilip->ili_root_size, ilip->ili_orig_root);
-#endif
-	kdb_printf("size %d ", ilip->ili_format.ilf_size);
-	printflags(ilip->ili_format.ilf_fields, ilf_fields, "fields:");
-	printflags(ilip->ili_last_fields, ilf_fields, " last fields: ");
-	kdb_printf("\n");
-	kdb_printf(" flush lsn %s last lsn %s\n",
-		xfs_fmtlsn(&(ilip->ili_flush_lsn)),
-		xfs_fmtlsn(&(ilip->ili_last_lsn)));
-	kdb_printf("dsize %d, asize %d, rdev 0x%x\n",
-		ilip->ili_format.ilf_dsize,
-		ilip->ili_format.ilf_asize,
-		ilip->ili_format.ilf_u.ilfu_rdev);
-	kdb_printf("blkno 0x%Lx len 0x%x boffset 0x%x\n",
-		ilip->ili_format.ilf_blkno,
-		ilip->ili_format.ilf_len,
-		ilip->ili_format.ilf_boffset);
-}
-
-/*
- * Print a dquot log item.
- */
-/* ARGSUSED */
-static void
-xfs_dquot_item_print(xfs_dq_logitem_t *lip, int summary)
-{
-	kdb_printf("dquot 0x%p\n",
-		lip->qli_dquot);
-
-}
-
-/*
- * Print a quotaoff log item.
- */
-/* ARGSUSED */
-static void
-xfs_qoff_item_print(xfs_qoff_logitem_t *lip, int summary)
-{
-	kdb_printf("start qoff item 0x%p flags 0x%x\n",
-		lip->qql_start_lip, lip->qql_format.qf_flags);
-
-}
-
-/*
- * Print buffer full of inodes.
- */
-static void
-xfs_inodebuf(xfs_buf_t *bp)
-{
-	xfs_dinode_t *di;
-	int n, i;
-
-	n = XFS_BUF_COUNT(bp) >> 8;
-	for (i = 0; i < n; i++) {
-		di = (xfs_dinode_t *)xfs_buf_offset(bp,
-					i * 256);
-		xfs_prdinode(di, 0, ARCH_CONVERT);
-	}
-}
-
-#ifdef XFS_RW_TRACE
-/*
- * Print iomap entry trace.
- */
-static void
-xfs_iomap_enter_trace_entry(ktrace_entry_t *ktep)
-{
-	qprintf("ip 0x%p size 0x%x%x offset 0x%x%x count 0x%x\n",
-		ktep->val[1],
-		(unsigned int)(long)ktep->val[2],
-		(unsigned int)(long)ktep->val[3],
-		(unsigned int)(long)ktep->val[4],
-		(unsigned int)(long)ktep->val[5],
-		(unsigned int)(long)ktep->val[6]);
-	qprintf("next offset 0x%x%x io offset 0x%x%x\n",
-		(unsigned int)(long)ktep->val[7],
-		(unsigned int)(long)ktep->val[8],
-		(unsigned int)(long)ktep->val[9],
-		(unsigned int)(long)ktep->val[10]);
-	qprintf("io size 0x%x last req sz 0x%x new size 0x%x%x\n",
-		(unsigned int)(long)ktep->val[11],
-		(unsigned int)(long)ktep->val[12],
-		(unsigned int)(long)ktep->val[13],
-		(unsigned int)(long)ktep->val[14]);
-}
-
-/*
- * Print iomap map trace.
- */
-static void
-xfs_iomap_map_trace_entry(ktrace_entry_t *ktep)
-{
-	qprintf("ip 0x%p size 0x%x%x offset 0x%x%x count 0x%x\n",
-		ktep->val[1],
-		(unsigned int)(long)ktep->val[2],
-		(unsigned int)(long)ktep->val[3],
-		(unsigned int)(long)ktep->val[4],
-		(unsigned int)(long)ktep->val[5],
-		(unsigned int)(long)ktep->val[6]);
-	qprintf("bmap off 0x%x%x len 0x%x pboff 0x%x pbsize 0x%x bno 0x%x\n",
-		(unsigned int)(long)ktep->val[7],
-		(unsigned int)(long)ktep->val[8],
-		(unsigned int)(long)ktep->val[9],
-		(unsigned int)(long)ktep->val[10],
-		(unsigned int)(long)ktep->val[11],
-		(unsigned int)(long)ktep->val[12]);
-	qprintf("imap off 0x%x count 0x%x block 0x%x\n",
-		(unsigned int)(long)ktep->val[13],
-		(unsigned int)(long)ktep->val[14],
-		(unsigned int)(long)ktep->val[15]);
-}
-
-/*
- * Print itrunc entry trace.
- */
-static void
-xfs_itrunc_trace_entry(ktrace_entry_t   *ktep)
-{
-	qprintf("ip 0x%p size 0x%x%x flag %ld new size 0x%x%x\n",
-		ktep->val[1],
-		(unsigned int)(long)ktep->val[2],
-		(unsigned int)(long)ktep->val[3],
-		(long)ktep->val[4],
-		(unsigned int)(long)ktep->val[5],
-		(unsigned int)(long)ktep->val[6]);
-	qprintf("toss start 0x%x%x toss finish 0x%x%x cpu id %ld\n",
-		(unsigned int)(long)ktep->val[7],
-		(unsigned int)(long)ktep->val[8],
-		(unsigned int)(long)ktep->val[9],
-		(unsigned int)(long)ktep->val[10],
-		(long)ktep->val[11]);
-}
-
-/*
- * Print bunmap entry trace.
- */
-static void
-xfs_bunmap_trace_entry(ktrace_entry_t   *ktep)
-{
-	static char *bunmapi_flags[] = {
-		"write",	/* 0x01 */
-		"delay",	/* 0x02 */
-		"entire",       /* 0x04 */
-		"metadata",     /* 0x08 */
-		"exact",	/* 0x10 */
-		"attrfork",     /* 0x20 */
-		"async",	/* 0x40 */
-		"rsvblocks",    /* 0x80 */
-		0
-	};
-
-	qprintf("ip 0x%p size 0x%x%x bno 0x%x%x len 0x%x cpu id %ld\n",
-		ktep->val[1],
-		(unsigned int)(long)ktep->val[2],
-		(unsigned int)(long)ktep->val[3],
-		(unsigned int)(long)ktep->val[4],
-		(unsigned int)(long)ktep->val[5],
-		(unsigned int)(long)ktep->val[6],
-		(long)ktep->val[8]);
-	qprintf("ra 0x%p ", ktep->val[9]);
-	printflags((__psint_t)ktep->val[7], bunmapi_flags, "flags");
-	qprintf("\n");
-}
-
-/*
- * Print inval_cached_pages entry trace.
- */
-static void
-xfs_inval_cached_trace_entry(ktrace_entry_t     *ktep)
-{
-	qprintf("ip 0x%p offset 0x%x%x len 0x%x%x first 0x%x%x last 0x%x%x\n",
-		ktep->val[1],
-		(unsigned int)(long)ktep->val[2],
-		(unsigned int)(long)ktep->val[3],
-		(unsigned int)(long)ktep->val[4],
-		(unsigned int)(long)ktep->val[5],
-		(unsigned int)(long)ktep->val[6],
-		(unsigned int)(long)ktep->val[7],
-		(unsigned int)(long)ktep->val[8],
-		(unsigned int)(long)ktep->val[9]);
-}
-#endif
-
-
-/*
- * Print disk inode.
- */
-static void
-xfs_prdinode(xfs_dinode_t *di, int coreonly, int convert)
-{
-	xfs_prdinode_core(&di->di_core, convert);
-	if (!coreonly)
-		kdb_printf("next_unlinked 0x%x u@0x%p\n",
-			INT_GET(di->di_next_unlinked, convert),
-			&di->di_u);
-}
-
-/*
- * Print disk inode core.
- */
-static void
-xfs_prdinode_core(xfs_dinode_core_t *dip, int convert)
-{
-	static char *diflags[] = {
-		"realtime",		/* XFS_DIFLAG_REALTIME */
-		"prealloc",		/* XFS_DIFLAG_PREALLOC */
-		"newrtbm",		/* XFS_DIFLAG_NEWRTBM */
-		"immutable",		/* XFS_DIFLAG_IMMUTABLE */
-		"append",		/* XFS_DIFLAG_APPEND */
-		"sync",			/* XFS_DIFLAG_SYNC */
-		"noatime",		/* XFS_DIFLAG_NOATIME */
-		"nodump",		/* XFS_DIFLAG_NODUMP */
-		NULL
-	};
-
-	kdb_printf("magic 0x%x mode 0%o (%s) version 0x%x format 0x%x (%s)\n",
-		INT_GET(dip->di_magic, convert),
-		INT_GET(dip->di_mode, convert),
-		xfs_fmtmode(INT_GET(dip->di_mode, convert)),
-		INT_GET(dip->di_version, convert),
-		INT_GET(dip->di_format, convert),
-		xfs_fmtformat(
-		    (xfs_dinode_fmt_t)INT_GET(dip->di_format, convert)));
-	kdb_printf("nlink %d uid %d gid %d projid %d flushiter %u\n",
-		INT_GET(dip->di_nlink, convert),
-		INT_GET(dip->di_uid, convert),
-		INT_GET(dip->di_gid, convert),
-		(uint)INT_GET(dip->di_projid, convert),
-		(uint)INT_GET(dip->di_flushiter, convert));
-	kdb_printf("atime %u:%u mtime %ud:%u ctime %u:%u\n",
-		INT_GET(dip->di_atime.t_sec, convert),
-		INT_GET(dip->di_atime.t_nsec, convert),
-		INT_GET(dip->di_mtime.t_sec, convert),
-		INT_GET(dip->di_mtime.t_nsec, convert),
-		INT_GET(dip->di_ctime.t_sec, convert),
-		INT_GET(dip->di_ctime.t_nsec, convert));
-	kdb_printf("size %Ld ", INT_GET(dip->di_size, convert));
-	kdb_printf("nblocks %Ld extsize 0x%x nextents 0x%x anextents 0x%x\n",
-		INT_GET(dip->di_nblocks, convert),
-		INT_GET(dip->di_extsize, convert),
-		INT_GET(dip->di_nextents, convert),
-		INT_GET(dip->di_anextents, convert));
-	kdb_printf("forkoff %d aformat 0x%x (%s) dmevmask 0x%x dmstate 0x%x ",
-		INT_GET(dip->di_forkoff, convert),
-		INT_GET(dip->di_aformat, convert),
-		xfs_fmtformat(
-		    (xfs_dinode_fmt_t)INT_GET(dip->di_aformat, convert)),
-		INT_GET(dip->di_dmevmask, convert),
-		INT_GET(dip->di_dmstate, convert));
-	printflags(INT_GET(dip->di_flags, convert), diflags, "flags");
-	kdb_printf("gen 0x%x\n", INT_GET(dip->di_gen, convert));
-}
-
-#ifdef XFS_RW_TRACE
-/*
- * Print read/write entry trace.
- */
-static void
-xfs_rw_enter_trace_entry(ktrace_entry_t *ktep)
-{
-	qprintf("ip 0x%p size 0x%x%x uio offset 0x%x%x uio count 0x%x\n",
-		ktep->val[1],
-		(unsigned int)(long)ktep->val[2],
-		(unsigned int)(long)ktep->val[3],
-		(unsigned int)(long)ktep->val[4],
-		(unsigned int)(long)ktep->val[5],
-		(unsigned int)(long)ktep->val[6]);
-	qprintf("ioflags 0x%x next offset 0x%x%x io offset 0x%x%x\n",
-		(unsigned int)(long)ktep->val[7],
-		(unsigned int)(long)ktep->val[8],
-		(unsigned int)(long)ktep->val[9],
-		(unsigned int)(long)ktep->val[10],
-		(unsigned int)(long)ktep->val[11]);
-	qprintf("io size 0x%x last req sz 0x%x new size 0x%x%x\n",
-		(unsigned int)(long)ktep->val[12],
-		(unsigned int)(long)ktep->val[13],
-		(unsigned int)(long)ktep->val[14],
-		(unsigned int)(long)ktep->val[15]);
-}
-
-/*
- * Print read/write trace entry.
- */
-static int
-xfs_rw_trace_entry(ktrace_entry_t *ktep)
-{
-	switch ( (long)ktep->val[0] ) {
-	case XFS_READ_ENTER:
-		qprintf("READ ENTER:\n");
-		xfs_rw_enter_trace_entry(ktep);
-		break;
-	case XFS_WRITE_ENTER:
-		qprintf("WRITE ENTER:\n");
-		xfs_rw_enter_trace_entry(ktep);
-		break;
-	case XFS_IOMAP_READ_ENTER:
-		qprintf("IOMAP READ ENTER:\n");
-		xfs_iomap_enter_trace_entry(ktep);
-		break;
-	case XFS_IOMAP_WRITE_ENTER:
-		qprintf("IOMAP WRITE ENTER:\n");
-		xfs_iomap_enter_trace_entry(ktep);
-		break;
-	case XFS_IOMAP_WRITE_NOSPACE:
-		qprintf("IOMAP WRITE NOSPACE:\n");
-		xfs_iomap_enter_trace_entry(ktep);
-		break;
-	case XFS_IOMAP_READ_MAP:
-		qprintf("IOMAP READ MAP:\n");
-		xfs_iomap_map_trace_entry(ktep);
-		break;
-	case XFS_IOMAP_WRITE_MAP:
-		qprintf("IOMAP WRITE MAP:\n");
-		xfs_iomap_map_trace_entry(ktep);
-		break;
-	case XFS_ITRUNC_START:
-		qprintf("ITRUNC START:\n");
-		xfs_itrunc_trace_entry(ktep);
-		break;
-	case XFS_ITRUNC_FINISH1:
-		qprintf("ITRUNC FINISH1:\n");
-		xfs_itrunc_trace_entry(ktep);
-		break;
-	case XFS_ITRUNC_FINISH2:
-		qprintf("ITRUNC FINISH2:\n");
-		xfs_itrunc_trace_entry(ktep);
-		break;
-	case XFS_CTRUNC1:
-		qprintf("CTRUNC1:\n");
-		xfs_ctrunc_trace_entry(ktep);
-		break;
-	case XFS_CTRUNC2:
-		qprintf("CTRUNC2:\n");
-		xfs_ctrunc_trace_entry(ktep);
-		break;
-	case XFS_CTRUNC3:
-		qprintf("CTRUNC3:\n");
-		xfs_ctrunc_trace_entry(ktep);
-		break;
-	case XFS_CTRUNC4:
-		qprintf("CTRUNC4:\n");
-		xfs_ctrunc_trace_entry(ktep);
-		break;
-	case XFS_CTRUNC5:
-		qprintf("CTRUNC5:\n");
-		xfs_ctrunc_trace_entry(ktep);
-		break;
-	case XFS_CTRUNC6:
-		qprintf("CTRUNC6:\n");
-		xfs_ctrunc_trace_entry(ktep);
-		break;
-	case XFS_BUNMAPI:
-		qprintf("BUNMAPI:\n");
-		xfs_bunmap_trace_entry(ktep);
-		break;
-	case XFS_INVAL_CACHED:
-		qprintf("INVAL CACHED:\n");
-		xfs_inval_cached_trace_entry(ktep);
-		break;
-	case XFS_DIORD_ENTER:
-		qprintf("DIORD ENTER:\n");
-		xfs_rw_enter_trace_entry(ktep);
-		break;
-	case XFS_DIOWR_ENTER:
-		qprintf("DIOWR ENTER:\n");
-		xfs_rw_enter_trace_entry(ktep);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 1;
-}
-#endif
-
-/*
- * Print xfs extent list for a fork.
- */
-static void
-xfs_xexlist_fork(xfs_inode_t *ip, int whichfork)
-{
-	int nextents, i;
-	xfs_ifork_t *ifp;
-	xfs_bmbt_irec_t irec;
-
-	ifp = XFS_IFORK_PTR(ip, whichfork);
-	if (ifp->if_flags & XFS_IFEXTENTS) {
-		nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_64_t);
-		kdb_printf("inode 0x%p %cf extents 0x%p nextents 0x%x\n",
-			ip, "da"[whichfork], ifp->if_u1.if_extents, nextents);
-		for (i = 0; i < nextents; i++) {
-			xfs_bmbt_get_all(&ifp->if_u1.if_extents[i], &irec);
-			kdb_printf(
-		"%d: startoff %Ld startblock %s blockcount %Ld flag %d\n",
-			i, irec.br_startoff,
-			xfs_fmtfsblock(irec.br_startblock, ip->i_mount),
-			irec.br_blockcount, irec.br_state);
-		}
-	}
-}
-
-static void
-xfs_xnode_fork(char *name, xfs_ifork_t *f)
-{
-	static char *tab_flags[] = {
-		"inline",	/* XFS_IFINLINE */
-		"extents",	/* XFS_IFEXTENTS */
-		"broot",	/* XFS_IFBROOT */
-		NULL
-	};
-	int *p;
-
-	kdb_printf("%s fork", name);
-	if (f == NULL) {
-		kdb_printf(" empty\n");
-		return;
-	} else
-		kdb_printf("\n");
-	kdb_printf(" bytes %s ", xfs_fmtsize(f->if_bytes));
-	kdb_printf("real_bytes %s lastex 0x%x u1:%s 0x%p\n",
-		xfs_fmtsize(f->if_real_bytes), f->if_lastex,
-		f->if_flags & XFS_IFINLINE ? "data" : "extents",
-		f->if_flags & XFS_IFINLINE ?
-			f->if_u1.if_data :
-			(char *)f->if_u1.if_extents);
-	kdb_printf(" broot 0x%p broot_bytes %s ext_max %d ",
-		f->if_broot, xfs_fmtsize(f->if_broot_bytes), f->if_ext_max);
-	printflags(f->if_flags, tab_flags, "flags");
-	kdb_printf("\n");
-	kdb_printf(" u2");
-	for (p = (int *)&f->if_u2;
-	     p < (int *)((char *)&f->if_u2 + XFS_INLINE_DATA);
-	     p++)
-		kdb_printf(" 0x%x", *p);
-	kdb_printf("\n");
-}
-
-/*
- * Command-level xfs-idbg functions.
- */
-
-/*
- * Print xfs allocation group freespace header.
- */
-static void
-xfsidbg_xagf(xfs_agf_t *agf)
-{
-	kdb_printf("magicnum 0x%x versionnum 0x%x seqno 0x%x length 0x%x\n",
-		INT_GET(agf->agf_magicnum, ARCH_CONVERT),
-		INT_GET(agf->agf_versionnum, ARCH_CONVERT),
-		INT_GET(agf->agf_seqno, ARCH_CONVERT),
-		INT_GET(agf->agf_length, ARCH_CONVERT));
-	kdb_printf("roots b 0x%x c 0x%x levels b %d c %d\n",
-		INT_GET(agf->agf_roots[XFS_BTNUM_BNO], ARCH_CONVERT),
-		INT_GET(agf->agf_roots[XFS_BTNUM_CNT], ARCH_CONVERT),
-		INT_GET(agf->agf_levels[XFS_BTNUM_BNO], ARCH_CONVERT),
-		INT_GET(agf->agf_levels[XFS_BTNUM_CNT], ARCH_CONVERT));
-	kdb_printf("flfirst %d fllast %d flcount %d freeblks %d longest %d\n",
-		INT_GET(agf->agf_flfirst, ARCH_CONVERT),
-		INT_GET(agf->agf_fllast, ARCH_CONVERT),
-		INT_GET(agf->agf_flcount, ARCH_CONVERT),
-		INT_GET(agf->agf_freeblks, ARCH_CONVERT),
-		INT_GET(agf->agf_longest, ARCH_CONVERT));
-}
-
-/*
- * Print xfs allocation group inode header.
- */
-static void
-xfsidbg_xagi(xfs_agi_t *agi)
-{
-	int	i;
-	int	j;
-
-	kdb_printf("magicnum 0x%x versionnum 0x%x seqno 0x%x length 0x%x\n",
-		INT_GET(agi->agi_magicnum, ARCH_CONVERT),
-		INT_GET(agi->agi_versionnum, ARCH_CONVERT),
-		INT_GET(agi->agi_seqno, ARCH_CONVERT),
-		INT_GET(agi->agi_length, ARCH_CONVERT));
-	kdb_printf("count 0x%x root 0x%x level 0x%x\n",
-		INT_GET(agi->agi_count, ARCH_CONVERT),
-		INT_GET(agi->agi_root, ARCH_CONVERT),
-		INT_GET(agi->agi_level, ARCH_CONVERT));
-	kdb_printf("freecount 0x%x newino 0x%x dirino 0x%x\n",
-		INT_GET(agi->agi_freecount, ARCH_CONVERT),
-		INT_GET(agi->agi_newino, ARCH_CONVERT),
-		INT_GET(agi->agi_dirino, ARCH_CONVERT));
-
-	kdb_printf("unlinked buckets\n");
-	for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
-		for (j = 0; j < 4; j++, i++) {
-			kdb_printf("0x%08x ",
-				INT_GET(agi->agi_unlinked[i], ARCH_CONVERT));
-		}
-		kdb_printf("\n");
-	}
-}
-
-#ifdef XFS_ALLOC_TRACE
-/*
- * Print out the last "count" entries in the allocation trace buffer.
- */
-static void
-xfsidbg_xalatrace(int count)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	int	     nentries;
-	int	     skip_entries;
-
-	if (xfs_alloc_trace_buf == NULL) {
-		qprintf("The xfs alloc trace buffer is not initialized\n");
-		return;
-	}
-	nentries = ktrace_nentries(xfs_alloc_trace_buf);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = nentries - count - 1;
-		ktep = ktrace_skip(xfs_alloc_trace_buf, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		if (xfs_alloc_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
-	}
-}
-
-/*
- * Print out all the entries in the alloc trace buf corresponding
- * to the given block number.
- */
-static void
-xfsidbg_xalbtrace(xfs_agblock_t bno)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-
-	if (xfs_alloc_trace_buf == NULL) {
-		qprintf("The xfs alloc trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
-	while (ktep != NULL) {
-		switch ((__psint_t)ktep->val[0]) {
-		case XFS_ALLOC_KTRACE_ALLOC:
-		case XFS_ALLOC_KTRACE_FREE:
-			if (bno >= (xfs_agblock_t)((__psint_t)ktep->val[5]) &&
-			    bno < (xfs_agblock_t)((__psint_t)ktep->val[5]) +
-				  (xfs_extlen_t)((__psint_t)ktep->val[13])) {
-				(void)xfs_alloc_trace_entry(ktep);
-				qprintf("\n");
-			}
-			break;
-		}
-		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
-	}
-}
-
-/*
- * Print out all the entries in the alloc trace buf corresponding
- * to the given allocation group.
- */
-static void
-xfsidbg_xalgtrace(xfs_agnumber_t agno)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-
-	if (xfs_alloc_trace_buf == NULL) {
-		qprintf("The xfs alloc trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
-	while (ktep != NULL) {
-		if (  (__psint_t)ktep->val[0] &&
-		      ((xfs_agnumber_t)((__psint_t)ktep->val[4])) == agno ) {
-			(void)xfs_alloc_trace_entry(ktep);
-			qprintf("\n");
-		}
-		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
-	}
-}
-#endif
-
-/*
- * Print an allocation argument structure for XFS.
- */
-static void
-xfsidbg_xalloc(xfs_alloc_arg_t *args)
-{
-	kdb_printf("tp 0x%p mp 0x%p agbp 0x%p pag 0x%p fsbno %s\n",
-		args->tp, args->mp, args->agbp, args->pag,
-		xfs_fmtfsblock(args->fsbno, args->mp));
-	kdb_printf("agno 0x%x agbno 0x%x minlen 0x%x maxlen 0x%x mod 0x%x\n",
-		args->agno, args->agbno, args->minlen, args->maxlen, args->mod);
-	kdb_printf("prod 0x%x minleft 0x%x total 0x%x alignment 0x%x\n",
-		args->prod, args->minleft, args->total, args->alignment);
-	kdb_printf("minalignslop 0x%x len 0x%x type %s otype %s wasdel %d\n",
-		args->minalignslop, args->len, xfs_alloctype[args->type],
-		xfs_alloctype[args->otype], args->wasdel);
-	kdb_printf("wasfromfl %d isfl %d userdata %d\n",
-		args->wasfromfl, args->isfl, args->userdata);
-}
-
-#ifdef XFS_ALLOC_TRACE
-/*
- * Print out all the entries in the alloc trace buf corresponding
- * to the given mount point.
- */
-static void
-xfsidbg_xalmtrace(xfs_mount_t *mp)
-{
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-
-	if (xfs_alloc_trace_buf == NULL) {
-		kdb_printf("The xfs alloc trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
-	while (ktep != NULL) {
-		if ((__psint_t)ktep->val[0] &&
-		    (xfs_mount_t *)ktep->val[3] == mp) {
-			(void)xfs_alloc_trace_entry(ktep);
-			kdb_printf("\n");
-		}
-		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
-	}
-}
-
-/*
- * Print out all the entries in the alloc trace buf corresponding
- * to the given entry type.
- */
-static void
-xfsidbg_xalttrace(int tag)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-
-	if (xfs_alloc_trace_buf == NULL) {
-		qprintf("The xfs alloc trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
-	while (ktep != NULL) {
-		if ((__psint_t)ktep->val[0] &&
-		    ((long)ktep->val[0] & 0xffffL) == (long)tag) {
-			(void)xfs_alloc_trace_entry(ktep);
-			qprintf("\n");
-		}
-		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
-	}
-}
-#endif
-
-/*
- * Set xtra argument, used by xchksum.
- */
-static void
-xfsidbg_xarg(int xarg)
-{
-	if (xarg == -1)
-		qprintf("xargument: %d\n", xargument);
-	else
-		xargument = xarg;
-}       /* xfsidbg_xarg */
-
-/*
- * Print an attr_list() context structure.
- */
-static void
-xfsidbg_xattrcontext(xfs_attr_list_context_t *context)
-{
-	static char *attr_arg_flags[] = {
-		"DONTFOLLOW",	/* 0x0001 */
-		"?",		/* 0x0002 */
-		"?",		/* 0x0004 */
-		"?",		/* 0x0008 */
-		"CREATE",	/* 0x0010 */
-		"?",		/* 0x0020 */
-		"?",		/* 0x0040 */
-		"?",		/* 0x0080 */
-		"?",		/* 0x0100 */
-		"?",		/* 0x0200 */
-		"?",		/* 0x0400 */
-		"?",		/* 0x0800 */
-		"KERNOTIME",	/* 0x1000 */
-		NULL
-	};
-
-	kdb_printf("dp 0x%p, dupcnt %d, resynch %d",
-		    context->dp, context->dupcnt, context->resynch);
-	printflags((__psunsigned_t)context->flags, attr_arg_flags, ", flags");
-	kdb_printf("\ncursor h/b/o 0x%x/0x%x/%d -- p/p/i 0x%x/0x%x/0x%x\n",
-			  context->cursor->hashval, context->cursor->blkno,
-			  context->cursor->offset, context->cursor->pad1,
-			  context->cursor->pad2, context->cursor->initted);
-	kdb_printf("alist 0x%p, bufsize 0x%x, count %d, firstu 0x%x\n",
-		       context->alist, context->bufsize, context->count,
-		       context->firstu);
-}
-
-/*
- * Print attribute leaf block.
- */
-static void
-xfsidbg_xattrleaf(xfs_attr_leafblock_t *leaf)
-{
-	xfs_attr_leaf_hdr_t *h;
-	xfs_da_blkinfo_t *i;
-	xfs_attr_leaf_map_t *m;
-	xfs_attr_leaf_entry_t *e;
-	xfs_attr_leaf_name_local_t *l;
-	xfs_attr_leaf_name_remote_t *r;
-	int j, k;
-
-	h = &leaf->hdr;
-	i = &h->info;
-	kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n",
-		i->forw, i->back, i->magic);
-	kdb_printf("hdr count %d usedbytes %d firstused %d holes %d\n",
-		INT_GET(h->count, ARCH_CONVERT),
-		INT_GET(h->usedbytes, ARCH_CONVERT),
-		INT_GET(h->firstused, ARCH_CONVERT), h->holes);
-	for (j = 0, m = h->freemap; j < XFS_ATTR_LEAF_MAPSIZE; j++, m++) {
-		kdb_printf("hdr freemap %d base %d size %d\n",
-			j, INT_GET(m->base, ARCH_CONVERT),
-			INT_GET(m->size, ARCH_CONVERT));
-	}
-	for (j = 0, e = leaf->entries; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) {
-		kdb_printf("[%2d] hash 0x%x nameidx %d flags 0x%x",
-			j, INT_GET(e->hashval, ARCH_CONVERT),
-			INT_GET(e->nameidx, ARCH_CONVERT), e->flags);
-		if (e->flags & XFS_ATTR_LOCAL)
-			kdb_printf("LOCAL ");
-		if (e->flags & XFS_ATTR_ROOT)
-			kdb_printf("ROOT ");
-		if (e->flags & XFS_ATTR_INCOMPLETE)
-			kdb_printf("INCOMPLETE ");
-		k = ~(XFS_ATTR_LOCAL | XFS_ATTR_ROOT | XFS_ATTR_INCOMPLETE);
-		if ((e->flags & k) != 0)
-			kdb_printf("0x%x", e->flags & k);
-		kdb_printf(">\n     name \"");
-		if (e->flags & XFS_ATTR_LOCAL) {
-			l = XFS_ATTR_LEAF_NAME_LOCAL(leaf, j);
-			for (k = 0; k < l->namelen; k++)
-				kdb_printf("%c", l->nameval[k]);
-			kdb_printf("\"(%d) value \"", l->namelen);
-			for (k = 0; (k < INT_GET(l->valuelen, ARCH_CONVERT)) && (k < 32); k++)
-				kdb_printf("%c", l->nameval[l->namelen + k]);
-			if (k == 32)
-				kdb_printf("...");
-			kdb_printf("\"(%d)\n",
-				INT_GET(l->valuelen, ARCH_CONVERT));
-		} else {
-			r = XFS_ATTR_LEAF_NAME_REMOTE(leaf, j);
-			for (k = 0; k < r->namelen; k++)
-				kdb_printf("%c", r->name[k]);
-			kdb_printf("\"(%d) value blk 0x%x len %d\n",
-				    r->namelen,
-				    INT_GET(r->valueblk, ARCH_CONVERT),
-				    INT_GET(r->valuelen, ARCH_CONVERT));
-		}
-	}
-}
-
-/*
- * Print a shortform attribute list.
- */
-static void
-xfsidbg_xattrsf(xfs_attr_shortform_t *s)
-{
-	xfs_attr_sf_hdr_t *sfh;
-	xfs_attr_sf_entry_t *sfe;
-	int i, j;
-
-	sfh = &s->hdr;
-	kdb_printf("hdr count %d\n", INT_GET(sfh->count, ARCH_CONVERT));
-	for (i = 0, sfe = s->list; i < INT_GET(sfh->count, ARCH_CONVERT); i++) {
-		kdb_printf("entry %d namelen %d name \"", i, sfe->namelen);
-		for (j = 0; j < sfe->namelen; j++)
-			kdb_printf("%c", sfe->nameval[j]);
-		kdb_printf("\" valuelen %d value \"", INT_GET(sfe->valuelen, ARCH_CONVERT));
-		for (j = 0; (j < INT_GET(sfe->valuelen, ARCH_CONVERT)) && (j < 32); j++)
-			kdb_printf("%c", sfe->nameval[sfe->namelen + j]);
-		if (j == 32)
-			kdb_printf("...");
-		kdb_printf("\"\n");
-		sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
-	}
-}
-
-#ifdef XFS_ATTR_TRACE
-/*
- * Print out the last "count" entries in the attribute trace buffer.
- */
-static void
-xfsidbg_xattrtrace(int count)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	int	     nentries;
-	int	     skip_entries;
-
-	if (xfs_attr_trace_buf == NULL) {
-		qprintf("The xfs attribute trace buffer is not initialized\n");
-		return;
-	}
-	nentries = ktrace_nentries(xfs_attr_trace_buf);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(xfs_attr_trace_buf, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = nentries - count - 1;
-		ktep = ktrace_skip(xfs_attr_trace_buf, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		xfs_attr_trace_entry(ktep);
-		ktep = ktrace_next(xfs_attr_trace_buf, &kts);
-	}
-}
-#endif
-
-/*
- * Print xfs bmap internal record
- */
-static void
-xfsidbg_xbirec(xfs_bmbt_irec_t *r)
-{
-	kdb_printf(
-	"startoff %Ld startblock %Lx blockcount %Ld state %Ld\n",
-		(__uint64_t)r->br_startoff,
-		(__uint64_t)r->br_startblock,
-		(__uint64_t)r->br_blockcount,
-		(__uint64_t)r->br_state);
-}
-
-#ifdef XFS_BLI_TRACE
-/*
- * Print out the buf log item trace for the given buf log item.
- */
-static void
-xfsidbg_xblitrace(xfs_buf_log_item_t *bip)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	uint64_t	flags;
-	static char *xbli_flags[] = {
-		"hold",		/* 0x01 */
-		"dirty",	/* 0x02 */
-		"stale",	/* 0x04 */
-		"logged",	/* 0x08 */
-		0
-		};
-	static char *xli_flags[] = {
-		"in ail",       /* 0x1 */
-		0
-		};
-
-	if (bip->bli_trace == NULL) {
-		qprintf("The bli trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(bip->bli_trace, &kts);
-	while (ktep != NULL) {
-		qprintf("%s bp 0x%p flags ",
-			(char *)ktep->val[0], ktep->val[1]);
-		printflags((__psint_t)(ktep->val[2]), xbli_flags, "xbli");
-		qprintf("\n");
-		qprintf("recur %ld refcount %ld blkno 0x%lx bcount 0x%lx\n",
-			(long)ktep->val[3], (long)ktep->val[4],
-			(unsigned long)ktep->val[5],
-			(unsigned long)ktep->val[6]);
-		flags = (((uint64_t)(unsigned long)ktep->val[7] << 32) &
-					0xFFFFFFFF00000000ULL) |
-			(((uint64_t)(unsigned long)ktep->val[8]) &
-					0x00000000FFFFFFFFULL);
-		qprintf("bp flags ");
-		printflags(flags, pb_flag_vals, 0);
-		qprintf("\n");
-		qprintf("fspriv 0x%p fspriv2 0x%p pincount %ld iodone 0x%p\n",
-			ktep->val[9], ktep->val[10],
-			(long)ktep->val[11], ktep->val[12]);
-		qprintf("lockval %ld lid 0x%lx log item flags ",
-			(long)ktep->val[13], (unsigned long)ktep->val[14]);
-		printflags((__psint_t)(ktep->val[15]), xli_flags, "xli");
-		qprintf("\n");
-
-		ktep = ktrace_next(bip->bli_trace, &kts);
-	}
-}
-#endif
-
-/*
- * Print a bmap alloc argument structure for XFS.
- */
-static void
-xfsidbg_xbmalla(xfs_bmalloca_t *a)
-{
-	kdb_printf("tp 0x%p ip 0x%p eof %d prevp 0x%p\n",
-		a->tp, a->ip, a->eof, a->prevp);
-	kdb_printf("gotp 0x%p firstblock %s alen %d total %d\n",
-		a->gotp, xfs_fmtfsblock(a->firstblock, a->ip->i_mount),
-		a->alen, a->total);
-	kdb_printf("off %s wasdel %d userdata %d minlen %d\n",
-		xfs_fmtfsblock(a->off, a->ip->i_mount), a->wasdel,
-		a->userdata, a->minlen);
-	kdb_printf("minleft %d low %d rval %s aeof %d\n",
-		a->minleft, a->low, xfs_fmtfsblock(a->rval, a->ip->i_mount),
-		a->aeof);
-}
-
-#ifdef XFS_BMAP_TRACE
-/*
- * Print out the last "count" entries in the bmap btree trace buffer.
- * The "a" is for "all" inodes.
- */
-static void
-xfsidbg_xbmatrace(int count)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	int	     nentries;
-	int	     skip_entries;
-
-	if (xfs_bmbt_trace_buf == NULL) {
-		qprintf("The xfs bmap btree trace buffer is not initialized\n");		return;
-	}
-	nentries = ktrace_nentries(xfs_bmbt_trace_buf);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(xfs_bmbt_trace_buf, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = nentries - count - 1;
-		ktep = ktrace_skip(xfs_bmbt_trace_buf, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		if (xfs_bmbt_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(xfs_bmbt_trace_buf, &kts);
-	}
-}
-
-/*
- * Print out the bmap btree trace buffer attached to the given inode.
- */
-static void
-xfsidbg_xbmitrace(xfs_inode_t *ip)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-
-	if (ip->i_btrace == NULL) {
-		qprintf("The inode trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(ip->i_btrace, &kts);
-	while (ktep != NULL) {
-		if (xfs_bmbt_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(ip->i_btrace, &kts);
-	}
-}
-
-/*
- * Print out all the entries in the bmap btree trace buf corresponding
- * to the given inode.  The "s" is for "single" inode.
- */
-static void
-xfsidbg_xbmstrace(xfs_inode_t *ip)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-
-	if (xfs_bmbt_trace_buf == NULL) {
-		qprintf("The xfs bmap btree trace buffer is not initialized\n");		return;
-	}
-
-	ktep = ktrace_first(xfs_bmbt_trace_buf, &kts);
-	while (ktep != NULL) {
-		if ((xfs_inode_t *)(ktep->val[2]) == ip) {
-			if (xfs_bmbt_trace_entry(ktep))
-				qprintf("\n");
-		}
-		ktep = ktrace_next(xfs_bmbt_trace_buf, &kts);
-	}
-}
-#endif
-
-/*
- * Print xfs bmap record
- */
-static void
-xfsidbg_xbrec(xfs_bmbt_rec_64_t *r)
-{
-	xfs_bmbt_irec_t	irec;
-
-	xfs_bmbt_get_all((xfs_bmbt_rec_t *)r, &irec);
-	kdb_printf("startoff %Ld startblock %Lx blockcount %Ld flag %d\n",
-		irec.br_startoff, (__uint64_t)irec.br_startblock,
-		irec.br_blockcount, irec.br_state);
-}
-
-/*
- * Print an xfs in-inode bmap btree root (data fork).
- */
-static void
-xfsidbg_xbroot(xfs_inode_t *ip)
-{
-	xfs_broot(ip, &ip->i_df);
-}
-
-/*
- * Print an xfs in-inode bmap btree root (attribute fork).
- */
-static void
-xfsidbg_xbroota(xfs_inode_t *ip)
-{
-	if (ip->i_afp)
-		xfs_broot(ip, ip->i_afp);
-}
-
-/*
- * Print xfs btree cursor.
- */
-static void
-xfsidbg_xbtcur(xfs_btree_cur_t *c)
-{
-	int l;
-
-	kdb_printf("tp 0x%p mp 0x%p\n",
-		c->bc_tp,
-		c->bc_mp);
-	if (c->bc_btnum == XFS_BTNUM_BMAP) {
-		kdb_printf("rec.b ");
-		xfsidbg_xbirec(&c->bc_rec.b);
-	} else if (c->bc_btnum == XFS_BTNUM_INO) {
-		kdb_printf("rec.i startino 0x%x freecount 0x%x free %Lx\n",
-			c->bc_rec.i.ir_startino, c->bc_rec.i.ir_freecount,
-			c->bc_rec.i.ir_free);
-	} else {
-		kdb_printf("rec.a startblock 0x%x blockcount 0x%x\n",
-			c->bc_rec.a.ar_startblock,
-			c->bc_rec.a.ar_blockcount);
-	}
-	kdb_printf("bufs");
-	for (l = 0; l < c->bc_nlevels; l++)
-		kdb_printf(" 0x%p", c->bc_bufs[l]);
-	kdb_printf("\n");
-	kdb_printf("ptrs");
-	for (l = 0; l < c->bc_nlevels; l++)
-		kdb_printf(" 0x%x", c->bc_ptrs[l]);
-	kdb_printf("  ra");
-	for (l = 0; l < c->bc_nlevels; l++)
-		kdb_printf(" %d", c->bc_ra[l]);
-	kdb_printf("\n");
-	kdb_printf("nlevels %d btnum %s blocklog %d\n",
-		c->bc_nlevels,
-		c->bc_btnum == XFS_BTNUM_BNO ? "bno" :
-		(c->bc_btnum == XFS_BTNUM_CNT ? "cnt" :
-		 (c->bc_btnum == XFS_BTNUM_BMAP ? "bmap" : "ino")),
-		c->bc_blocklog);
-	if (c->bc_btnum == XFS_BTNUM_BMAP) {
-		kdb_printf("private forksize 0x%x whichfork %d ip 0x%p flags %d\n",
-			c->bc_private.b.forksize,
-			c->bc_private.b.whichfork,
-			c->bc_private.b.ip,
-			c->bc_private.b.flags);
-		kdb_printf("private firstblock %s flist 0x%p allocated 0x%x\n",
-			xfs_fmtfsblock(c->bc_private.b.firstblock, c->bc_mp),
-			c->bc_private.b.flist,
-			c->bc_private.b.allocated);
-	} else if (c->bc_btnum == XFS_BTNUM_INO) {
-		kdb_printf("private agbp 0x%p agno 0x%x\n",
-			c->bc_private.i.agbp,
-			c->bc_private.i.agno);
-	} else {
-		kdb_printf("private agbp 0x%p agno 0x%x\n",
-			c->bc_private.a.agbp,
-			c->bc_private.a.agno);
-	}
-}
-
-/*
- * Figure out what kind of xfs block the buffer contains,
- * and invoke a print routine.
- */
-static void
-xfsidbg_xbuf(xfs_buf_t *bp)
-{
-	xfsidbg_xbuf_real(bp, 0);
-}
-
-/*
- * Figure out what kind of xfs block the buffer contains,
- * and invoke a print routine (if asked to).
- */
-static void
-xfsidbg_xbuf_real(xfs_buf_t *bp, int summary)
-{
-	void *d;
-	xfs_agf_t *agf;
-	xfs_agi_t *agi;
-	xfs_sb_t *sb;
-	xfs_alloc_block_t *bta;
-	xfs_bmbt_block_t *btb;
-	xfs_inobt_block_t *bti;
-	xfs_attr_leafblock_t *aleaf;
-	xfs_dir_leafblock_t *dleaf;
-	xfs_da_intnode_t *node;
-	xfs_dinode_t *di;
-	xfs_disk_dquot_t *dqb;
-	xfs_dir2_block_t *d2block;
-	xfs_dir2_data_t *d2data;
-	xfs_dir2_leaf_t *d2leaf;
-	xfs_dir2_free_t *d2free;
-
-	d = XFS_BUF_PTR(bp);
-	if (INT_GET((agf = d)->agf_magicnum, ARCH_CONVERT) == XFS_AGF_MAGIC) {
-		if (summary) {
-			kdb_printf("freespace hdr for AG %d (at 0x%p)\n",
-				INT_GET(agf->agf_seqno, ARCH_CONVERT), agf);
-		} else {
-			kdb_printf("buf 0x%p agf 0x%p\n", bp, agf);
-			xfsidbg_xagf(agf);
-		}
-	} else if (INT_GET((agi = d)->agi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC) {
-		if (summary) {
-			kdb_printf("Inode hdr for AG %d (at 0x%p)\n",
-			       INT_GET(agi->agi_seqno, ARCH_CONVERT), agi);
-		} else {
-			kdb_printf("buf 0x%p agi 0x%p\n", bp, agi);
-			xfsidbg_xagi(agi);
-		}
-	} else if (INT_GET((bta = d)->bb_magic, ARCH_CONVERT) == XFS_ABTB_MAGIC) {
-		if (summary) {
-			kdb_printf("Alloc BNO Btree blk, level %d (at 0x%p)\n",
-				       INT_GET(bta->bb_level, ARCH_CONVERT), bta);
-		} else {
-			kdb_printf("buf 0x%p abtbno 0x%p\n", bp, bta);
-			xfs_btalloc(bta, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET((bta = d)->bb_magic, ARCH_CONVERT) == XFS_ABTC_MAGIC) {
-		if (summary) {
-			kdb_printf("Alloc COUNT Btree blk, level %d (at 0x%p)\n",
-				       INT_GET(bta->bb_level, ARCH_CONVERT), bta);
-		} else {
-			kdb_printf("buf 0x%p abtcnt 0x%p\n", bp, bta);
-			xfs_btalloc(bta, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET((btb = d)->bb_magic, ARCH_CONVERT) == XFS_BMAP_MAGIC) {
-		if (summary) {
-			kdb_printf("Bmap Btree blk, level %d (at 0x%p)\n",
-				      INT_GET(btb->bb_level, ARCH_CONVERT), btb);
-		} else {
-			kdb_printf("buf 0x%p bmapbt 0x%p\n", bp, btb);
-			xfs_btbmap(btb, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET((bti = d)->bb_magic, ARCH_CONVERT) == XFS_IBT_MAGIC) {
-		if (summary) {
-			kdb_printf("Inode Btree blk, level %d (at 0x%p)\n",
-				       INT_GET(bti->bb_level, ARCH_CONVERT), bti);
-		} else {
-			kdb_printf("buf 0x%p inobt 0x%p\n", bp, bti);
-			xfs_btino(bti, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET((aleaf = d)->hdr.info.magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC) {
-		if (summary) {
-			kdb_printf("Attr Leaf, 1st hash 0x%x (at 0x%p)\n",
-				      INT_GET(aleaf->entries[0].hashval, ARCH_CONVERT), aleaf);
-		} else {
-			kdb_printf("buf 0x%p attr leaf 0x%p\n", bp, aleaf);
-			xfsidbg_xattrleaf(aleaf);
-		}
-	} else if (INT_GET((dleaf = d)->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) {
-		if (summary) {
-			kdb_printf("Dir Leaf, 1st hash 0x%x (at 0x%p)\n",
-				     dleaf->entries[0].hashval, dleaf);
-		} else {
-			kdb_printf("buf 0x%p dir leaf 0x%p\n", bp, dleaf);
-			xfsidbg_xdirleaf(dleaf);
-		}
-	} else if (INT_GET((node = d)->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) {
-		if (summary) {
-			kdb_printf("Dir/Attr Node, level %d, 1st hash 0x%x (at 0x%p)\n",
-			      node->hdr.level, node->btree[0].hashval, node);
-		} else {
-			kdb_printf("buf 0x%p dir/attr node 0x%p\n", bp, node);
-			xfsidbg_xdanode(node);
-		}
-	} else if (INT_GET((di = d)->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC) {
-		if (summary) {
-			kdb_printf("Disk Inode (at 0x%p)\n", di);
-		} else {
-			kdb_printf("buf 0x%p dinode 0x%p\n", bp, di);
-			xfs_inodebuf(bp);
-		}
-	} else if (INT_GET((sb = d)->sb_magicnum, ARCH_CONVERT) == XFS_SB_MAGIC) {
-		if (summary) {
-			kdb_printf("Superblock (at 0x%p)\n", sb);
-		} else {
-			kdb_printf("buf 0x%p sb 0x%p\n", bp, sb);
-			/* SB in a buffer - we need to convert */
-			xfsidbg_xsb(sb, 1);
-		}
-	} else if ((dqb = d)->d_magic == XFS_DQUOT_MAGIC) {
-#define XFSIDBG_DQTYPESTR(d)     \
-	((INT_GET((d)->d_flags, ARCH_CONVERT) & XFS_DQ_USER) ? "USR" : \
-	((INT_GET((d)->d_flags, ARCH_CONVERT) & XFS_DQ_GROUP) ? "GRP" : "???"))
-		kdb_printf("Quota blk starting ID [%d], type %s at 0x%p\n",
-			INT_GET(dqb->d_id, ARCH_CONVERT), XFSIDBG_DQTYPESTR(dqb), dqb);
-
-	} else if (INT_GET((d2block = d)->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) {
-		if (summary) {
-			kdb_printf("Dir2 block (at 0x%p)\n", d2block);
-		} else {
-			kdb_printf("buf 0x%p dir2 block 0x%p\n", bp, d2block);
-			xfs_dir2data((void *)d2block, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET((d2data = d)->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC) {
-		if (summary) {
-			kdb_printf("Dir2 data (at 0x%p)\n", d2data);
-		} else {
-			kdb_printf("buf 0x%p dir2 data 0x%p\n", bp, d2data);
-			xfs_dir2data((void *)d2data, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET((d2leaf = d)->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC) {
-		if (summary) {
-			kdb_printf("Dir2 leaf(1) (at 0x%p)\n", d2leaf);
-		} else {
-			kdb_printf("buf 0x%p dir2 leaf 0x%p\n", bp, d2leaf);
-			xfs_dir2leaf(d2leaf, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET(d2leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) {
-		if (summary) {
-			kdb_printf("Dir2 leaf(n) (at 0x%p)\n", d2leaf);
-		} else {
-			kdb_printf("buf 0x%p dir2 leaf 0x%p\n", bp, d2leaf);
-			xfs_dir2leaf(d2leaf, XFS_BUF_COUNT(bp));
-		}
-	} else if (INT_GET((d2free = d)->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC) {
-		if (summary) {
-			kdb_printf("Dir2 free (at 0x%p)\n", d2free);
-		} else {
-			kdb_printf("buf 0x%p dir2 free 0x%p\n", bp, d2free);
-			xfsidbg_xdir2free(d2free);
-		}
-	} else {
-		kdb_printf("buf 0x%p unknown 0x%p\n", bp, d);
-	}
-}
-
-#ifdef XFS_BMAP_TRACE
-/*
- * Print out the last "count" entries in the bmap extent trace buffer.
- * The "a" is for "all" inodes.
- */
-static void
-xfsidbg_xbxatrace(int count)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	int	     nentries;
-	int	     skip_entries;
-
-	if (xfs_bmap_trace_buf == NULL) {
-		qprintf("The xfs bmap extent trace buffer is not initialized\n");
-		return;
-	}
-	nentries = ktrace_nentries(xfs_bmap_trace_buf);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(xfs_bmap_trace_buf, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = nentries - count - 1;
-		ktep = ktrace_skip(xfs_bmap_trace_buf, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		if (xfs_bmap_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(xfs_bmap_trace_buf, &kts);
-	}
-}
-
-/*
- * Print out the bmap extent trace buffer attached to the given inode.
- */
-static void
-xfsidbg_xbxitrace(xfs_inode_t *ip)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	if (ip->i_xtrace == NULL) {
-		qprintf("The inode trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(ip->i_xtrace, &kts);
-	while (ktep != NULL) {
-		if (xfs_bmap_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(ip->i_xtrace, &kts);
-	}
-}
-
-/*
- * Print out all the entries in the bmap extent trace buf corresponding
- * to the given inode.  The "s" is for "single" inode.
- */
-static void
-xfsidbg_xbxstrace(xfs_inode_t *ip)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-
-	if (xfs_bmap_trace_buf == NULL) {
-		qprintf("The xfs bmap extent trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(xfs_bmap_trace_buf, &kts);
-	while (ktep != NULL) {
-		if ((xfs_inode_t *)(ktep->val[3]) == ip) {
-			if (xfs_bmap_trace_entry(ktep))
-				qprintf("\n");
-		}
-		ktep = ktrace_next(xfs_bmap_trace_buf, &kts);
-	}
-}
-#endif
-
-#ifdef XFS_ILOCK_TRACE
-/*
- * Print out the ilock trace buffer attached to the given inode.
- */
-static void
-xfsidbg_xilock_trace_entry(ktrace_entry_t *ktep)
-{
-	static char	*xiflags[] = {
-		"IOLOCK_EXCL",
-		"IOLOCK_SHAR",
-		"ILOCK_EXCL",
-		"ILOCK_SHAR",
-		"IUNLK_NONOT",
-		0
-	};
-
-	if ((__psint_t)ktep->val[0] &&
-	     (__psint_t)ktep->val[7] == 0) {
-		 printflags((__psint_t)ktep->val[2], xiflags,"Flags ");
-		if ((__psint_t)ktep->val[1] == 1)
-			 qprintf("LOCK\n");
-		else if ((__psint_t)ktep->val[1] == 2)
-			 qprintf("LOCK SHARED\n");
-		else if ((__psint_t)ktep->val[1] == 3)
-			 qprintf("UNLOCK\n");
-		qprintf("ip 0x%p %llx %ld\n",
-			ktep->val[0],
-			(unsigned long long)((xfs_inode_t*)ktep->val[0])->i_ino,
-			(long)ktep->val[6]);
-		qprintf("raddr 0x%p\n", ktep->val[3]);
-		qprintf("  Pid %ld, cpu %ld\n",
-			 (long)ktep->val[5],
-			 (long)ktep->val[4]);
-		qprintf("-----------------------\n");
-
-	} else if ((__psint_t)ktep->val[7] == 1) {
-		if ((__psint_t)ktep->val[1] == 1)
-			qprintf("FlushLOCK ");
-		else if ((__psint_t)ktep->val[1] == 2)
-			qprintf("FlushTRYLOCK %ld ",
-				(long)ktep->val[2]);
-		else if ((__psint_t)ktep->val[1] == 3)
-			qprintf("FlushUNLOCK ");
-		else if ((__psint_t)ktep->val[1] == 4)
-			qprintf("FlushInode 0x%p",
-				ktep->val[2]);
-		else if ((__psint_t)ktep->val[1] == 5)
-			qprintf("FlushInodeInt ");
-		else     qprintf("FlushUNKNOWN ");
-		qprintf("ip 0x%p ino %llx @ %ld\n",
-			ktep->val[0],
-			(unsigned long long)((xfs_inode_t*)ktep->val[0])->i_ino,
-			(long)ktep->val[6]);
-		qprintf("raddr 0x%p\n", ktep->val[3]);
-		qprintf("  Pid %ld, cpu %ld\n",
-			(long)ktep->val[5],
-			(long)ktep->val[4]);
-		qprintf("-----------------------\n");
-	}
-}
-
-static void
-xfsidbg_xilock_trace(xfs_inode_t *ip)
-{
-	static char *xiflags[] = {
-		"IOLOCK_EXCL",
-		"IOLOCK_SHAR",
-		"ILOCK_EXCL",
-		"ILOCK_SHAR",
-		"IUNLK_NONOT",
-		0
-	};
-
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	if (ip->i_lock_trace == NULL) {
-		qprintf("The inode ilock trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(ip->i_lock_trace, &kts);
-	while (ktep != NULL) {
-		 if ((__psint_t)ktep->val[0] &&
-		     (__psint_t)ktep->val[7] == 0) {
-			 printflags((__psint_t)ktep->val[2], xiflags,"Flags ");
-			 if ((__psint_t)ktep->val[1] == 1)
-				 qprintf("LOCK\n");
-			 else if ((__psint_t)ktep->val[1] == 2)
-				 qprintf("LOCK SHARED\n");
-			 else if ((__psint_t)ktep->val[1] == 3)
-				 qprintf("UNLOCK\n");
-			qprintf("ip 0x%p %lld %ld\n",
-				ktep->val[0], (unsigned long long)
-				((xfs_inode_t*)ktep->val[0])->i_ino,
-				(long)ktep->val[6]);
-			 qprintf("raddr 0x%p\n", ktep->val[3]);
-			 qprintf("  Pid %ld, cpu %ld\n",
-				 (long)ktep->val[5],
-				 (long)ktep->val[4]);
-			 qprintf("-----------------------\n");
-		 } else if ((__psint_t)ktep->val[7] == 1) {
-			if ((__psint_t)ktep->val[1] == 1)
-				qprintf("LOCK ");
-			else if ((__psint_t)ktep->val[1] == 2)
-				qprintf("TRYLOCK %ld ",
-					(long)ktep->val[2]);
-			else if ((__psint_t)ktep->val[1] == 3)
-				qprintf("UNLOCK ");
-			else     qprintf("UNKNOWN ");
-			qprintf("ip 0x%p %lld %ld\n",
-				ktep->val[0], (unsigned long long)
-				((xfs_inode_t*)ktep->val[0])->i_ino,
-				(long)ktep->val[6]);
-			qprintf("raddr 0x%p\n", ktep->val[3]);
-			qprintf("  Pid %ld, cpu %ld\n",
-				(long)ktep->val[5],
-				(long)ktep->val[4]);
-			qprintf("-----------------------\n");
-		 }
-
-		 ktep = ktrace_next(ip->i_lock_trace, &kts);
-	}
-}
-
-/*
- * Print out the last "count" entries in the inode lock trace buffer.
- * The "a" is for "all" entries.
- */
-static void
-xfsidbg_xailock_trace(int count)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	int	     nentries;
-	int	     skip_entries;
-
-	if (xfs_ilock_trace_buf == NULL) {
-		qprintf("The xfs inode lock trace buffer is not initialized\n");		return;
-	}
-	nentries = ktrace_nentries(xfs_ilock_trace_buf);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(xfs_ilock_trace_buf, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = nentries - count - 1;
-		ktep = ktrace_skip(xfs_ilock_trace_buf, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		xfsidbg_xilock_trace_entry(ktep);
-		ktep = ktrace_next(xfs_ilock_trace_buf, &kts);
-	}
-}
-#endif
-
-/*
- * Compute & print buffer's checksum.
- */
-static void
-xfsidbg_xchksum(uint *addr)
-{
-	uint i, chksum = 0;
-
-	if (((__psint_t)addr) == ((__psint_t)-1)) {
-		qprintf("USAGE xchksum <address>\n");
-		qprintf("       length is set with xarg\n");
-	} else {
-		for (i=0; i<xargument; i++) {
-			chksum ^= *addr;
-			addr++;
-		}
-		qprintf("chksum (0x%x)  length (%d)\n", chksum, xargument);
-	}
-}       /* xfsidbg_xchksum */
-
-/*
- * Print an xfs_da_args structure.
- */
-static void
-xfsidbg_xdaargs(xfs_da_args_t *n)
-{
-	char *ch;
-	int i;
-
-	kdb_printf(" name \"");
-	for (i = 0; i < n->namelen; i++) {
-		kdb_printf("%c", n->name[i]);
-	}
-	kdb_printf("\"(%d) value ", n->namelen);
-	if (n->value) {
-		kdb_printf("\"");
-		ch = n->value;
-		for (i = 0; (i < n->valuelen) && (i < 32); ch++, i++) {
-			switch(*ch) {
-			case '\n':	kdb_printf("\n");		break;
-			case '\b':	kdb_printf("\b");		break;
-			case '\t':	kdb_printf("\t");		break;
-			default:	kdb_printf("%c", *ch);	break;
-			}
-		}
-		if (i == 32)
-			kdb_printf("...");
-		kdb_printf("\"(%d)\n", n->valuelen);
-	} else {
-		kdb_printf("(NULL)(%d)\n", n->valuelen);
-	}
-	kdb_printf(" hashval 0x%x whichfork %d flags <",
-		  (uint_t)n->hashval, n->whichfork);
-	if (n->flags & ATTR_ROOT)
-		kdb_printf("ROOT ");
-	if (n->flags & ATTR_CREATE)
-		kdb_printf("CREATE ");
-	if (n->flags & ATTR_REPLACE)
-		kdb_printf("REPLACE ");
-	if (n->flags & XFS_ATTR_INCOMPLETE)
-		kdb_printf("INCOMPLETE ");
-	i = ~(ATTR_ROOT | ATTR_CREATE | ATTR_REPLACE | XFS_ATTR_INCOMPLETE);
-	if ((n->flags & i) != 0)
-		kdb_printf("0x%x", n->flags & i);
-	kdb_printf(">\n");
-	kdb_printf(" rename %d justcheck %d addname %d oknoent %d\n",
-		  n->rename, n->justcheck, n->addname, n->oknoent);
-	kdb_printf(" leaf: blkno %d index %d rmtblkno %d rmtblkcnt %d\n",
-		  n->blkno, n->index, n->rmtblkno, n->rmtblkcnt);
-	kdb_printf(" leaf2: blkno %d index %d rmtblkno %d rmtblkcnt %d\n",
-		  n->blkno2, n->index2, n->rmtblkno2, n->rmtblkcnt2);
-	kdb_printf(" inumber %llu dp 0x%p firstblock 0x%p flist 0x%p\n",
-		  (unsigned long long) n->inumber,
-		  n->dp, n->firstblock, n->flist);
-	kdb_printf(" trans 0x%p total %d\n",
-		  n->trans, n->total);
-}
-
-/*
- * Print a da buffer structure.
- */
-static void
-xfsidbg_xdabuf(xfs_dabuf_t *dabuf)
-{
-	int	i;
-
-	kdb_printf("nbuf %d dirty %d bbcount %d data 0x%p bps",
-		dabuf->nbuf, dabuf->dirty, dabuf->bbcount, dabuf->data);
-	for (i = 0; i < dabuf->nbuf; i++)
-		kdb_printf(" %d:0x%p", i, dabuf->bps[i]);
-	kdb_printf("\n");
-#ifdef XFS_DABUF_DEBUG
-	kdb_printf(" ra 0x%x prev 0x%x next 0x%x dev 0x%x blkno 0x%x\n",
-		dabuf->ra, dabuf->prev, dabuf->next, dabuf->dev, dabuf->blkno);
-#endif
-}
-
-/*
- * Print a directory/attribute internal node block.
- */
-static void
-xfsidbg_xdanode(xfs_da_intnode_t *node)
-{
-	xfs_da_node_hdr_t *h;
-	xfs_da_blkinfo_t *i;
-	xfs_da_node_entry_t *e;
-	int j;
-
-	h = &node->hdr;
-	i = &h->info;
-	kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n",
-		INT_GET(i->forw, ARCH_CONVERT), INT_GET(i->back, ARCH_CONVERT), INT_GET(i->magic, ARCH_CONVERT));
-	kdb_printf("hdr count %d level %d\n",
-		INT_GET(h->count, ARCH_CONVERT), INT_GET(h->level, ARCH_CONVERT));
-	for (j = 0, e = node->btree; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) {
-		kdb_printf("btree %d hashval 0x%x before 0x%x\n",
-			j, (uint_t)INT_GET(e->hashval, ARCH_CONVERT), INT_GET(e->before, ARCH_CONVERT));
-	}
-}
-
-/*
- * Print an xfs_da_state_blk structure.
- */
-static void
-xfsidbg_xdastate(xfs_da_state_t *s)
-{
-	xfs_da_state_blk_t *eblk;
-
-	kdb_printf("args 0x%p mp 0x%p blocksize %u node_ents %u inleaf %u\n",
-		s->args, s->mp, s->blocksize, s->node_ents, s->inleaf);
-	if (s->args)
-		xfsidbg_xdaargs(s->args);
-
-	kdb_printf("path:  ");
-	xfs_dastate_path(&s->path);
-
-	kdb_printf("altpath:  ");
-	xfs_dastate_path(&s->altpath);
-
-	eblk = &s->extrablk;
-	kdb_printf("extra: valid %d, after %d\n", s->extravalid, s->extraafter);
-	kdb_printf(" bp 0x%p blkno 0x%x ", eblk->bp, eblk->blkno);
-	kdb_printf("index %d hashval 0x%x\n", eblk->index, (uint_t)eblk->hashval);
-}
-
-/*
- * Print a directory leaf block.
- */
-static void
-xfsidbg_xdirleaf(xfs_dir_leafblock_t *leaf)
-{
-	xfs_dir_leaf_hdr_t *h;
-	xfs_da_blkinfo_t *i;
-	xfs_dir_leaf_map_t *m;
-	xfs_dir_leaf_entry_t *e;
-	xfs_dir_leaf_name_t *n;
-	int j, k;
-	xfs_ino_t ino;
-
-	h = &leaf->hdr;
-	i = &h->info;
-	kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n",
-		INT_GET(i->forw, ARCH_CONVERT), INT_GET(i->back, ARCH_CONVERT), INT_GET(i->magic, ARCH_CONVERT));
-	kdb_printf("hdr count %d namebytes %d firstused %d holes %d\n",
-		INT_GET(h->count, ARCH_CONVERT), INT_GET(h->namebytes, ARCH_CONVERT), INT_GET(h->firstused, ARCH_CONVERT), h->holes);
-	for (j = 0, m = h->freemap; j < XFS_DIR_LEAF_MAPSIZE; j++, m++) {
-		kdb_printf("hdr freemap %d base %d size %d\n",
-			j, INT_GET(m->base, ARCH_CONVERT), INT_GET(m->size, ARCH_CONVERT));
-	}
-	for (j = 0, e = leaf->entries; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) {
-		n = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(e->nameidx, ARCH_CONVERT));
-		XFS_DIR_SF_GET_DIRINO_ARCH(&n->inumber, &ino, ARCH_CONVERT);
-		kdb_printf("leaf %d hashval 0x%x nameidx %d inumber %llu ",
-			j, (uint_t)INT_GET(e->hashval, ARCH_CONVERT),
-			INT_GET(e->nameidx, ARCH_CONVERT),
-			(unsigned long long)ino);
-		kdb_printf("namelen %d name \"", e->namelen);
-		for (k = 0; k < e->namelen; k++)
-			kdb_printf("%c", n->name[k]);
-		kdb_printf("\"\n");
-	}
-}
-
-/*
- * Print a directory v2 data block, single or multiple.
- */
-static void
-xfs_dir2data(void *addr, int size)
-{
-	xfs_dir2_data_t *db;
-	xfs_dir2_block_t *bb;
-	xfs_dir2_data_hdr_t *h;
-	xfs_dir2_data_free_t *m;
-	xfs_dir2_data_entry_t *e;
-	xfs_dir2_data_unused_t *u;
-	xfs_dir2_leaf_entry_t *l=NULL;
-	int j, k;
-	char *p;
-	char *t;
-	xfs_dir2_block_tail_t *tail=NULL;
-
-	db = (xfs_dir2_data_t *)addr;
-	bb = (xfs_dir2_block_t *)addr;
-	h = &db->hdr;
-	kdb_printf("hdr magic 0x%x (%s)\nhdr bestfree", INT_GET(h->magic, ARCH_CONVERT),
-		INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC ? "DATA" :
-			(INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC ? "BLOCK" : ""));
-	for (j = 0, m = h->bestfree; j < XFS_DIR2_DATA_FD_COUNT; j++, m++) {
-		kdb_printf(" %d: 0x%x@0x%x", j, INT_GET(m->length, ARCH_CONVERT), INT_GET(m->offset, ARCH_CONVERT));
-	}
-	kdb_printf("\n");
-	if (INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC)
-		t = (char *)db + size;
-	else {
-		/* XFS_DIR2_BLOCK_TAIL_P */
-		tail = (xfs_dir2_block_tail_t *)
-		       ((char *)bb + size - sizeof(xfs_dir2_block_tail_t));
-		l = XFS_DIR2_BLOCK_LEAF_P_ARCH(tail, ARCH_CONVERT);
-		t = (char *)l;
-	}
-	for (p = (char *)(h + 1); p < t; ) {
-		u = (xfs_dir2_data_unused_t *)p;
-		if (u->freetag == XFS_DIR2_DATA_FREE_TAG) {
-			kdb_printf("0x%lx unused freetag 0x%x length 0x%x tag 0x%x\n",
-				(unsigned long) (p - (char *)addr),
-				INT_GET(u->freetag, ARCH_CONVERT),
-				INT_GET(u->length, ARCH_CONVERT),
-				INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(u, ARCH_CONVERT), ARCH_CONVERT));
-			p += INT_GET(u->length, ARCH_CONVERT);
-			continue;
-		}
-		e = (xfs_dir2_data_entry_t *)p;
-		kdb_printf("0x%lx entry inumber %llu namelen %d name \"",
-			(unsigned long) (p - (char *)addr),
-			(unsigned long long) INT_GET(e->inumber, ARCH_CONVERT),
-			e->namelen);
-		for (k = 0; k < e->namelen; k++)
-			kdb_printf("%c", e->name[k]);
-		kdb_printf("\" tag 0x%x\n", INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(e), ARCH_CONVERT));
-		p += XFS_DIR2_DATA_ENTSIZE(e->namelen);
-	}
-	if (INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC)
-		return;
-	for (j = 0; j < INT_GET(tail->count, ARCH_CONVERT); j++, l++) {
-		kdb_printf("0x%lx leaf %d hashval 0x%x address 0x%x (byte 0x%x)\n",
-			(unsigned long) ((char *)l - (char *)addr), j,
-			(uint_t)INT_GET(l->hashval, ARCH_CONVERT),
-			INT_GET(l->address, ARCH_CONVERT),
-			/* XFS_DIR2_DATAPTR_TO_BYTE */
-			INT_GET(l->address, ARCH_CONVERT) << XFS_DIR2_DATA_ALIGN_LOG);
-	}
-	kdb_printf("0x%lx tail count %d\n",
-		(unsigned long) ((char *)tail - (char *)addr),
-		INT_GET(tail->count, ARCH_CONVERT));
-}
-
-static void
-xfs_dir2leaf(xfs_dir2_leaf_t *leaf, int size)
-{
-	xfs_dir2_leaf_hdr_t *h;
-	xfs_da_blkinfo_t *i;
-	xfs_dir2_leaf_entry_t *e;
-	xfs_dir2_data_off_t *b;
-	xfs_dir2_leaf_tail_t *t;
-	int j;
-
-	h = &leaf->hdr;
-	i = &h->info;
-	e = leaf->ents;
-	kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n",
-		INT_GET(i->forw, ARCH_CONVERT), INT_GET(i->back, ARCH_CONVERT), INT_GET(i->magic, ARCH_CONVERT));
-	kdb_printf("hdr count %d stale %d\n", INT_GET(h->count, ARCH_CONVERT), INT_GET(h->stale, ARCH_CONVERT));
-	for (j = 0; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) {
-		kdb_printf("0x%lx ent %d hashval 0x%x address 0x%x (byte 0x%x)\n",
-			(unsigned long) ((char *)e - (char *)leaf), j,
-			(uint_t)INT_GET(e->hashval, ARCH_CONVERT),
-			INT_GET(e->address, ARCH_CONVERT),
-			/* XFS_DIR2_DATAPTR_TO_BYTE */
-			INT_GET(e->address, ARCH_CONVERT) << XFS_DIR2_DATA_ALIGN_LOG);
-	}
-	if (INT_GET(i->magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC)
-		return;
-	/* XFS_DIR2_LEAF_TAIL_P */
-	t = (xfs_dir2_leaf_tail_t *)((char *)leaf + size - sizeof(*t));
-	b = XFS_DIR2_LEAF_BESTS_P_ARCH(t, ARCH_CONVERT);
-	for (j = 0; j < INT_GET(t->bestcount, ARCH_CONVERT); j++, b++) {
-		kdb_printf("0x%lx best %d 0x%x\n",
-			(unsigned long) ((char *)b - (char *)leaf), j,
-			INT_GET(*b, ARCH_CONVERT));
-	}
-	kdb_printf("tail bestcount %d\n", INT_GET(t->bestcount, ARCH_CONVERT));
-}
-
-/*
- * Print a shortform directory.
- */
-static void
-xfsidbg_xdirsf(xfs_dir_shortform_t *s)
-{
-	xfs_dir_sf_hdr_t *sfh;
-	xfs_dir_sf_entry_t *sfe;
-	xfs_ino_t ino;
-	int i, j;
-
-	sfh = &s->hdr;
-	XFS_DIR_SF_GET_DIRINO_ARCH(&sfh->parent, &ino, ARCH_CONVERT);
-	kdb_printf("hdr parent %llu", (unsigned long long)ino);
-	kdb_printf(" count %d\n", sfh->count);
-	for (i = 0, sfe = s->list; i < sfh->count; i++) {
-		XFS_DIR_SF_GET_DIRINO_ARCH(&sfe->inumber, &ino, ARCH_CONVERT);
-		kdb_printf("entry %d inumber %llu", i, (unsigned long long)ino);
-		kdb_printf(" namelen %d name \"", sfe->namelen);
-		for (j = 0; j < sfe->namelen; j++)
-			kdb_printf("%c", sfe->name[j]);
-		kdb_printf("\"\n");
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-	}
-}
-
-/*
- * Print a shortform v2 directory.
- */
-static void
-xfsidbg_xdir2sf(xfs_dir2_sf_t *s)
-{
-	xfs_dir2_sf_hdr_t *sfh;
-	xfs_dir2_sf_entry_t *sfe;
-	xfs_ino_t ino;
-	int i, j;
-
-	sfh = &s->hdr;
-	ino = XFS_DIR2_SF_GET_INUMBER_ARCH(s, &sfh->parent, ARCH_CONVERT);
-	kdb_printf("hdr count %d i8count %d parent %llu\n",
-		sfh->count, sfh->i8count, (unsigned long long) ino);
-	for (i = 0, sfe = XFS_DIR2_SF_FIRSTENTRY(s); i < sfh->count; i++) {
-		ino = XFS_DIR2_SF_GET_INUMBER_ARCH(s, XFS_DIR2_SF_INUMBERP(sfe), ARCH_CONVERT);
-		kdb_printf("entry %d inumber %llu offset 0x%x namelen %d name \"",
-			i, (unsigned long long) ino,
-			XFS_DIR2_SF_GET_OFFSET_ARCH(sfe, ARCH_CONVERT),
-			sfe->namelen);
-		for (j = 0; j < sfe->namelen; j++)
-			kdb_printf("%c", sfe->name[j]);
-		kdb_printf("\"\n");
-		sfe = XFS_DIR2_SF_NEXTENTRY(s, sfe);
-	}
-}
-
-/*
- * Print a node-form v2 directory freemap block.
- */
-static void
-xfsidbg_xdir2free(xfs_dir2_free_t *f)
-{
-	int	i;
-
-	kdb_printf("hdr magic 0x%x firstdb %d nvalid %d nused %d\n",
-		INT_GET(f->hdr.magic, ARCH_CONVERT), INT_GET(f->hdr.firstdb, ARCH_CONVERT), INT_GET(f->hdr.nvalid, ARCH_CONVERT), INT_GET(f->hdr.nused, ARCH_CONVERT));
-	for (i = 0; i < INT_GET(f->hdr.nvalid, ARCH_CONVERT); i++) {
-		kdb_printf("entry %d db %d count %d\n",
-			i, i + INT_GET(f->hdr.firstdb, ARCH_CONVERT), INT_GET(f->bests[i], ARCH_CONVERT));
-	}
-}
-
-#ifdef XFS_DIR_TRACE
-/*
- * Print out the last "count" entries in the directory trace buffer.
- */
-static void
-xfsidbg_xdirtrace(int count)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	int	     nentries;
-	int	     skip_entries;
-
-	if (xfs_dir_trace_buf == NULL) {
-		qprintf("The xfs directory trace buffer is not initialized\n");
-		return;
-	}
-	nentries = ktrace_nentries(xfs_dir_trace_buf);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(xfs_dir_trace_buf, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = nentries - count - 1;
-		ktep = ktrace_skip(xfs_dir_trace_buf, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		if (xfs_dir_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(xfs_dir_trace_buf, &kts);
-	}
-}
-#endif
-
-#ifdef XFS_DIR2_TRACE
-/*
- * Print out the last "count" entries in the directory v2 trace buffer.
- */
-static void
-xfsidbg_xdir2atrace(int count)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	int	     nentries;
-	int	     skip_entries;
-
-	if (xfs_dir2_trace_buf == NULL) {
-		qprintf("The xfs dirv2 trace buffer is not initialized\n");
-		return;
-	}
-	nentries = ktrace_nentries(xfs_dir2_trace_buf);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(xfs_dir2_trace_buf, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = nentries - count - 1;
-		ktep = ktrace_skip(xfs_dir2_trace_buf, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		if (xfs_dir2_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(xfs_dir2_trace_buf, &kts);
-	}
-}
-
-/*
- * Print out the directory v2 trace buffer attached to the given inode.
- */
-static void
-xfsidbg_xdir2itrace(xfs_inode_t *ip)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-
-	if (ip->i_dir_trace == NULL) {
-		qprintf("The inode trace buffer is not initialized\n");
-		return;
-	}
-
-	ktep = ktrace_first(ip->i_dir_trace, &kts);
-	while (ktep != NULL) {
-		if (xfs_dir2_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(ip->i_dir_trace, &kts);
-	}
-}
-#endif
-
-/*
- * Print xfs extent list.
- */
-static void
-xfsidbg_xexlist(xfs_inode_t *ip)
-{
-	xfs_xexlist_fork(ip, XFS_DATA_FORK);
-	if (XFS_IFORK_Q(ip))
-		xfs_xexlist_fork(ip, XFS_ATTR_FORK);
-}
-
-/*
- * Print an xfs free-extent list.
- */
-static void
-xfsidbg_xflist(xfs_bmap_free_t *flist)
-{
-	xfs_bmap_free_item_t	*item;
-
-	kdb_printf("flist@0x%p: first 0x%p count %d low %d\n", flist,
-		flist->xbf_first, flist->xbf_count, flist->xbf_low);
-	for (item = flist->xbf_first; item; item = item->xbfi_next) {
-		kdb_printf("item@0x%p: startblock %Lx blockcount %d", item,
-			(xfs_dfsbno_t)item->xbfi_startblock,
-			item->xbfi_blockcount);
-	}
-}
-
-/*
- * Print out the help messages for these functions.
- */
-static void
-xfsidbg_xhelp(void)
-{
-	struct xif	*p;
-
-	for (p = xfsidbg_funcs; p->name; p++)
-		kdb_printf("%-16s %s %s\n", p->name, p->args, p->help);
-}
-
-/*
- * Print out an XFS in-core log structure.
- */
-static void
-xfsidbg_xiclog(xlog_in_core_t *iclog)
-{
-	int i;
-	static char *ic_flags[] = {
-		"ACTIVE",	/* 0x0001 */
-		"WANT_SYNC",	/* 0x0002 */
-		"SYNCING",	/* 0X0004 */
-		"DONE_SYNC",	/* 0X0008 */
-		"DO_CALLBACK",	/* 0X0010 */
-		"CALLBACK",	/* 0X0020 */
-		"DIRTY",	/* 0X0040 */
-		"IOERROR",	/* 0X0080 */
-		"NOTUSED",	/* 0X8000 */
-		0
-	};
-
-	kdb_printf("xlog_in_core/header at 0x%p/0x%p\n",
-		iclog, iclog->hic_data);
-	kdb_printf("magicno: %x  cycle: %d  version: %d  lsn: 0x%Lx\n",
-		INT_GET(iclog->ic_header.h_magicno, ARCH_CONVERT), INT_GET(iclog->ic_header.h_cycle, ARCH_CONVERT),
-		INT_GET(iclog->ic_header.h_version, ARCH_CONVERT), INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT));
-	kdb_printf("tail_lsn: 0x%Lx  len: %d  prev_block: %d  num_ops: %d\n",
-		INT_GET(iclog->ic_header.h_tail_lsn, ARCH_CONVERT), INT_GET(iclog->ic_header.h_len, ARCH_CONVERT),
-		INT_GET(iclog->ic_header.h_prev_block, ARCH_CONVERT), INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT));
-	kdb_printf("cycle_data: ");
-	for (i=0; i<(iclog->ic_size>>BBSHIFT); i++) {
-		kdb_printf("%x  ", INT_GET(iclog->ic_header.h_cycle_data[i], ARCH_CONVERT));
-	}
-	kdb_printf("\n");
-	kdb_printf("size: %d\n", INT_GET(iclog->ic_header.h_size, ARCH_CONVERT));
-	kdb_printf("\n");
-	kdb_printf("--------------------------------------------------\n");
-	kdb_printf("data: 0x%p  &forcesema: 0x%p  next: 0x%p bp: 0x%p\n",
-		iclog->ic_datap, &iclog->ic_forcesema, iclog->ic_next,
-		iclog->ic_bp);
-	kdb_printf("log: 0x%p  callb: 0x%p  callb_tail: 0x%p  roundoff: %d\n",
-		iclog->ic_log, iclog->ic_callback, iclog->ic_callback_tail,
-		iclog->ic_roundoff);
-	kdb_printf("size: %d (OFFSET: %d) trace: 0x%p refcnt: %d bwritecnt: %d",
-		iclog->ic_size, iclog->ic_offset,
-#ifdef XFS_LOG_TRACE
-		iclog->ic_trace,
-#else
-		NULL,
-#endif
-		iclog->ic_refcnt, iclog->ic_bwritecnt);
-	if (iclog->ic_state & XLOG_STATE_ALL)
-		printflags(iclog->ic_state, ic_flags, " state:");
-	else
-		kdb_printf(" state: INVALID 0x%x", iclog->ic_state);
-	kdb_printf("\n");
-}	/* xfsidbg_xiclog */
-
-
-/*
- * Print all incore logs.
- */
-static void
-xfsidbg_xiclogall(xlog_in_core_t *iclog)
-{
-    xlog_in_core_t *first_iclog = iclog;
-
-    do {
-	xfsidbg_xiclog(iclog);
-	kdb_printf("=================================================\n");
-	iclog = iclog->ic_next;
-    } while (iclog != first_iclog);
-}	/* xfsidbg_xiclogall */
-
-/*
- * Print out the callback structures attached to an iclog.
- */
-static void
-xfsidbg_xiclogcb(xlog_in_core_t *iclog)
-{
-	xfs_log_callback_t	*cb;
-	kdb_symtab_t		 symtab;
-
-	for (cb = iclog->ic_callback; cb != NULL; cb = cb->cb_next) {
-
-		if (kdbnearsym((unsigned long)cb->cb_func, &symtab)) {
-			unsigned long offval;
-
-			offval = (unsigned long)cb->cb_func - symtab.sym_start;
-
-			if (offval)
-				kdb_printf("func = %s+0x%lx",
-							symtab.sym_name,
-							offval);
-			else
-				kdb_printf("func = %s", symtab.sym_name);
-		} else
-			kdb_printf("func = ?? 0x%p", (void *)cb->cb_func);
-
-		kdb_printf(" arg 0x%p next 0x%p\n", cb->cb_arg, cb->cb_next);
-	}
-}
-
-#ifdef XFS_LOG_TRACE
-/*
- * Print trace from incore log.
- */
-static void
-xfsidbg_xiclogtrace(xlog_in_core_t *iclog)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	ktrace_t	*kt = iclog->ic_trace;
-
-	qprintf("iclog->ic_trace 0x%p\n", kt);
-	ktep = ktrace_first(kt, &kts);
-	while (ktep != NULL) {
-		switch ((__psint_t)ktep->val[0]) {
-		    case XLOG_TRACE_GRAB_FLUSH: {
-			    qprintf("grabbing semaphore\n");
-			    break;
-		    }
-		    case XLOG_TRACE_REL_FLUSH: {
-			    qprintf("releasing semaphore\n");
-			    break;
-		    }
-		    case XLOG_TRACE_SLEEP_FLUSH: {
-			    qprintf("sleeping on semaphore\n");
-			    break;
-		    }
-		    case XLOG_TRACE_WAKE_FLUSH: {
-			    qprintf("waking up on semaphore\n");
-			    break;
-		    }
-		    default: {
-		    }
-		}
-		ktep = ktrace_next(kt, &kts);
-	}
-}       /* xfsidbg_xiclogtrace */
-#endif
-
-/*
- * Print all of the inodes attached to the given mount structure.
- */
-static void
-xfsidbg_xinodes(xfs_mount_t *mp)
-{
-	xfs_inode_t	*ip;
-
-	kdb_printf("xfs_mount at 0x%p\n", mp);
-	ip = mp->m_inodes;
-	if (ip != NULL) {
-		do {
-			if (ip->i_mount == NULL) {
-				ip = ip->i_mnext;
-				continue;
-			}
-			kdb_printf("\n");
-			xfsidbg_xnode(ip);
-			ip = ip->i_mnext;
-		} while (ip != mp->m_inodes);
-	}
-	kdb_printf("\nEnd of Inodes\n");
-}
-
-static void
-xfsidbg_delayed_blocks(xfs_mount_t *mp)
-{
-	xfs_inode_t	*ip;
-	unsigned int	total = 0;
-	unsigned int	icount = 0;
-
-	ip = mp->m_inodes;
-	if (ip != NULL) {
-		do {
-			if (ip->i_mount == NULL) {
-				ip = ip->i_mnext;
-				continue;
-			}
-			if (ip->i_delayed_blks) {
-				total += ip->i_delayed_blks;
-				icount++;
-			}
-			ip = ip->i_mnext;
-		} while (ip != mp->m_inodes);
-	}
-	kdb_printf("delayed blocks total: %d in %d inodes\n", total, icount);
-}
-
-static void
-xfsidbg_xinodes_quiesce(xfs_mount_t *mp)
-{
-	xfs_inode_t	*ip;
-
-	kdb_printf("xfs_mount at 0x%p\n", mp);
-	ip = mp->m_inodes;
-	if (ip != NULL) {
-		do {
-			if (ip->i_mount == NULL) {
-				ip = ip->i_mnext;
-				continue;
-			}
-			if (!(ip->i_flags & XFS_IQUIESCE)) {
-				kdb_printf("ip 0x%p not quiesced\n", ip);
-			}
-			ip = ip->i_mnext;
-		} while (ip != mp->m_inodes);
-	}
-	kdb_printf("\nEnd of Inodes\n");
-}
-
-static char *
-xfsidbg_get_cstate(int state)
-{
-	switch(state) {
-	case  XLOG_STATE_COVER_IDLE:
-		return("idle");
-	case  XLOG_STATE_COVER_NEED:
-		return("need");
-	case  XLOG_STATE_COVER_DONE:
-		return("done");
-	case  XLOG_STATE_COVER_NEED2:
-		return("need2");
-	case  XLOG_STATE_COVER_DONE2:
-		return("done2");
-	default:
-		return("unknown");
-	}
-}
-
-/*
- * Print out an XFS log structure.
- */
-static void
-xfsidbg_xlog(xlog_t *log)
-{
-	int rbytes;
-	int wbytes;
-	static char *t_flags[] = {
-		"CHKSUM_MISMATCH",	/* 0x01 */
-		"ACTIVE_RECOVERY",	/* 0x02 */
-		"RECOVERY_NEEDED",	/* 0x04 */
-		"IO_ERROR",		/* 0x08 */
-		0
-	};
-
-	kdb_printf("xlog at 0x%p\n", log);
-	kdb_printf("&flushsm: 0x%p  flushcnt: %d tic_cnt: %d	 tic_tcnt: %d  \n",
-		&log->l_flushsema, log->l_flushcnt,
-		log->l_ticket_cnt, log->l_ticket_tcnt);
-	kdb_printf("freelist: 0x%p  tail: 0x%p	ICLOG: 0x%p  \n",
-		log->l_freelist, log->l_tail, log->l_iclog);
-	kdb_printf("&icloglock: 0x%p  tail_lsn: %s  last_sync_lsn: %s \n",
-		&log->l_icloglock, xfs_fmtlsn(&log->l_tail_lsn),
-		xfs_fmtlsn(&log->l_last_sync_lsn));
-	kdb_printf("mp: 0x%p  xbuf: 0x%p  roundoff: %d  l_covered_state: %s \n",
-		log->l_mp, log->l_xbuf, log->l_roundoff,
-			xfsidbg_get_cstate(log->l_covered_state));
-	kdb_printf("flags: ");
-	printflags(log->l_flags, t_flags,"log");
-	kdb_printf("  logBBstart: %lld logsize: %d logBBsize: %d\n",
-		(long long) log->l_logBBstart,
-		log->l_logsize,log->l_logBBsize);
-	kdb_printf("curr_cycle: %d  prev_cycle: %d  curr_block: %d  prev_block: %d\n",
-	     log->l_curr_cycle, log->l_prev_cycle, log->l_curr_block,
-	     log->l_prev_block);
-	kdb_printf("iclog_bak: 0x%p  iclog_size: 0x%x (%d)  num iclogs: %d\n",
-		log->l_iclog_bak, log->l_iclog_size, log->l_iclog_size,
-		log->l_iclog_bufs);
-	kdb_printf("l_stripemask %d l_iclog_hsize %d l_iclog_heads %d\n",
-		log->l_stripemask, log->l_iclog_hsize, log->l_iclog_heads);
-	kdb_printf("l_sectbb_log %u l_sectbb_mask %u\n",
-		log->l_sectbb_log, log->l_sectbb_mask);
-	kdb_printf("&grant_lock: 0x%p  resHeadQ: 0x%p  wrHeadQ: 0x%p\n",
-		&log->l_grant_lock, log->l_reserve_headq, log->l_write_headq);
-	kdb_printf("GResCycle: %d  GResBytes: %d  GWrCycle: %d  GWrBytes: %d\n",
-		log->l_grant_reserve_cycle, log->l_grant_reserve_bytes,
-		log->l_grant_write_cycle, log->l_grant_write_bytes);
-	rbytes = log->l_grant_reserve_bytes + log->l_roundoff;
-	wbytes = log->l_grant_write_bytes + log->l_roundoff;
-	qprintf("GResBlocks: %d GResRemain: %d  GWrBlocks: %d GWrRemain: %d\n",
-	       rbytes / BBSIZE, rbytes % BBSIZE,
-	       wbytes / BBSIZE, wbytes % BBSIZE);
-#ifdef XFS_LOG_TRACE
-	qprintf("trace: 0x%p  grant_trace: use xlog value\n", log->l_trace);
-#endif
-}	/* xfsidbg_xlog */
-
-#ifdef XFS_LOG_TRACE
-/*
- * Print grant trace for a log.
- */
-static void
-xfsidbg_xlog_granttrace(xlog_t *log)
-{
-	ktrace_entry_t  *ktep;
-	ktrace_snap_t   kts;
-	ktrace_t	*kt;
-
-	if (((__psint_t)log) == ((__psint_t)-1)) {
-		qprintf("Usage: xl_grtr <log>\n");
-		return;
-	}
-	if ((kt = log->l_grant_trace))
-		qprintf("log->l_grant_trace 0x%p\n", kt);
-	else {
-		qprintf("log->l_grant_trace is empty!\n");
-		return;
-	}
-	ktep = ktrace_first(kt, &kts);
-	while (ktep != NULL) {
-		qprintf("%s\n", (char *)ktep->val[11]);
-		qprintf("  tic:0x%p resQ:0x%p wrQ:0x%p ",
-			ktep->val[0], ktep->val[1], ktep->val[2]);
-		qprintf("  GrResC:%ld GrResB:%ld GrWrC:%ld GrWrB:%ld \n",
-			(long)ktep->val[3], (long)ktep->val[4],
-			(long)ktep->val[5], (long)ktep->val[6]);
-		qprintf("  HeadC:%ld HeadB:%ld TailC:%ld TailB:%ld\n",
-			(long)ktep->val[7], (long)ktep->val[8],
-			(long)ktep->val[9], (long)ktep->val[10]);
-		ktep = ktrace_next(kt, &kts);
-	}
-}       /* xfsidbg_xlog_granttrace */
-#endif
-
-/*
- * Print out an XFS recovery transaction
- */
-static void
-xfsidbg_xlog_ritem(xlog_recover_item_t *item)
-{
-	int i = XLOG_MAX_REGIONS_IN_ITEM;
-
-	kdb_printf("(xlog_recover_item 0x%p) ", item);
-	kdb_printf("next: 0x%p prev: 0x%p type: %d cnt: %d ttl: %d\n",
-		item->ri_next, item->ri_prev, ITEM_TYPE(item), item->ri_cnt,
-		item->ri_total);
-	for ( ; i > 0; i--) {
-		if (!item->ri_buf[XLOG_MAX_REGIONS_IN_ITEM-i].i_addr)
-			break;
-		kdb_printf("a: 0x%p l: %d ",
-			item->ri_buf[XLOG_MAX_REGIONS_IN_ITEM-i].i_addr,
-			item->ri_buf[XLOG_MAX_REGIONS_IN_ITEM-i].i_len);
-	}
-	kdb_printf("\n");
-}	/* xfsidbg_xlog_ritem */
-
-/*
- * Print out an XFS recovery transaction
- */
-static void
-xfsidbg_xlog_rtrans(xlog_recover_t *trans)
-{
-	xlog_recover_item_t *rip, *first_rip;
-
-	kdb_printf("(xlog_recover 0x%p) ", trans);
-	kdb_printf("tid: %x type: %d items: %d ttid: 0x%x  ",
-		trans->r_log_tid, trans->r_theader.th_type,
-		trans->r_theader.th_num_items, trans->r_theader.th_tid);
-	kdb_printf("itemq: 0x%p\n", trans->r_itemq);
-	if (trans->r_itemq) {
-		rip = first_rip = trans->r_itemq;
-		do {
-			kdb_printf("(recovery item: 0x%p) ", rip);
-			kdb_printf("type: %d cnt: %d total: %d\n",
-				ITEM_TYPE(rip), rip->ri_cnt, rip->ri_total);
-			rip = rip->ri_next;
-		} while (rip != first_rip);
-	}
-}	/* xfsidbg_xlog_rtrans */
-
-static void
-xfsidbg_xlog_buf_logitem(xlog_recover_item_t *item)
-{
-	xfs_buf_log_format_t	*buf_f;
-	int			i, j;
-	int			bit;
-	int			nbits;
-	unsigned int		*data_map;
-	unsigned int		map_size;
-	int			size;
-
-	buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr;
-	if (buf_f->blf_flags & XFS_BLI_INODE_BUF) {
-		kdb_printf("\tINODE BUF <blkno=0x%Lx, len=0x%x>\n",
-			buf_f->blf_blkno, buf_f->blf_len);
-	} else if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF | XFS_BLI_GDQUOT_BUF)) {
-		kdb_printf("\tDQUOT BUF <blkno=0x%Lx, len=0x%x>\n",
-			buf_f->blf_blkno, buf_f->blf_len);
-	} else {
-		data_map = buf_f->blf_data_map;
-		map_size = buf_f->blf_map_size;
-		kdb_printf("\tREG BUF <blkno=0x%Lx, len=0x%x map 0x%p size %d>\n",
-			buf_f->blf_blkno, buf_f->blf_len, data_map, map_size);
-		bit = 0;
-		i = 0;  /* 0 is the buf format structure */
-		while (1) {
-			bit = xfs_next_bit(data_map, map_size, bit);
-			if (bit == -1)
-				break;
-			nbits = xfs_contig_bits(data_map, map_size, bit);
-			size = ((uint)bit << XFS_BLI_SHIFT)+(nbits<<XFS_BLI_SHIFT);
-			kdb_printf("\t\tlogbuf.i_addr 0x%p, size 0x%x\n",
-				item->ri_buf[i].i_addr, size);
-			kdb_printf("\t\t\t\"");
-			for (j=0; j<8 && j<size; j++) {
-				kdb_printf("%02x", ((char *)item->ri_buf[i].i_addr)[j]);
-			}
-			kdb_printf("...\"\n");
-			i++;
-			bit += nbits;
-		}
-
-	}
-}
-
-/*
- * Print out an ENTIRE XFS recovery transaction
- */
-static void
-xfsidbg_xlog_rtrans_entire(xlog_recover_t *trans)
-{
-	xlog_recover_item_t *item, *first_rip;
-
-	kdb_printf("(Recovering Xact 0x%p) ", trans);
-	kdb_printf("tid: %x type: %d nitems: %d ttid: 0x%x  ",
-		trans->r_log_tid, trans->r_theader.th_type,
-		trans->r_theader.th_num_items, trans->r_theader.th_tid);
-	kdb_printf("itemq: 0x%p\n", trans->r_itemq);
-	if (trans->r_itemq) {
-		item = first_rip = trans->r_itemq;
-		do {
-			/*
-			   kdb_printf("(recovery item: 0x%x) ", item);
-			   kdb_printf("type: %d cnt: %d total: %d\n",
-				   item->ri_type, item->ri_cnt, item->ri_total);
-				   */
-			if ((ITEM_TYPE(item) == XFS_LI_BUF) ||
-			    (ITEM_TYPE(item) == XFS_LI_6_1_BUF) ||
-			    (ITEM_TYPE(item) == XFS_LI_5_3_BUF)) {
-				kdb_printf("BUF:");
-				xfsidbg_xlog_buf_logitem(item);
-			} else if ((ITEM_TYPE(item) == XFS_LI_INODE) ||
-				   (ITEM_TYPE(item) == XFS_LI_6_1_INODE) ||
-				   (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) {
-				kdb_printf("INODE:\n");
-			} else if (ITEM_TYPE(item) == XFS_LI_EFI) {
-				kdb_printf("EFI:\n");
-			} else if (ITEM_TYPE(item) == XFS_LI_EFD) {
-				kdb_printf("EFD:\n");
-			} else if (ITEM_TYPE(item) == XFS_LI_DQUOT) {
-				kdb_printf("DQUOT:\n");
-			} else if ((ITEM_TYPE(item) == XFS_LI_QUOTAOFF)) {
-				kdb_printf("QUOTAOFF:\n");
-			} else {
-				kdb_printf("UNKNOWN LOGITEM 0x%x\n", ITEM_TYPE(item));
-			}
-			item = item->ri_next;
-		} while (item != first_rip);
-	}
-}	/* xfsidbg_xlog_rtrans */
-
-/*
- * Print out an XFS ticket structure.
- */
-static void
-xfsidbg_xlog_tic(xlog_ticket_t *tic)
-{
-	static char *t_flags[] = {
-		"INIT",		/* 0x1 */
-		"PERM_RES",	/* 0x2 */
-		"IN_Q",		/* 0x4 */
-		0
-	};
-
-	kdb_printf("xlog_ticket at 0x%p\n", tic);
-	kdb_printf("next: 0x%p  prev: 0x%p  tid: 0x%x  \n",
-		tic->t_next, tic->t_prev, tic->t_tid);
-	kdb_printf("curr_res: %d  unit_res: %d  ocnt: %d  cnt: %d\n",
-		tic->t_curr_res, tic->t_unit_res, (int)tic->t_ocnt,
-		(int)tic->t_cnt);
-	kdb_printf("clientid: %c  \n", tic->t_clientid);
-	printflags(tic->t_flags, t_flags,"ticket");
-	kdb_printf("\n");
-}	/* xfsidbg_xlog_tic */
-
-/*
- * Print out a single log item.
- */
-static void
-xfsidbg_xlogitem(xfs_log_item_t *lip)
-{
-	xfs_log_item_t	*bio_lip;
-	static char *lid_type[] = {
-		"???",		/* 0 */
-		"5-3-buf",	/* 1 */
-		"5-3-inode",	/* 2 */
-		"efi",		/* 3 */
-		"efd",		/* 4 */
-		"iunlink",	/* 5 */
-		"6-1-inode",	/* 6 */
-		"6-1-buf",	/* 7 */
-		"inode",	/* 8 */
-		"buf",		/* 9 */
-		"dquot",	/* 10 */
-		0
-		};
-	static char *li_flags[] = {
-		"in ail",	/* 0x1 */
-		0
-		};
-
-	kdb_printf("type %s mountp 0x%p flags ",
-		lid_type[lip->li_type - XFS_LI_5_3_BUF + 1],
-		lip->li_mountp);
-	printflags((uint)(lip->li_flags), li_flags,"log");
-	kdb_printf("\n");
-	kdb_printf("ail forw 0x%p ail back 0x%p lsn %s\ndesc %p ops 0x%p",
-		lip->li_ail.ail_forw, lip->li_ail.ail_back,
-		xfs_fmtlsn(&(lip->li_lsn)), lip->li_desc, lip->li_ops);
-	kdb_printf(" iodonefunc &0x%p\n", lip->li_cb);
-	if (lip->li_type == XFS_LI_BUF) {
-		bio_lip = lip->li_bio_list;
-		if (bio_lip != NULL) {
-			kdb_printf("iodone list:\n");
-		}
-		while (bio_lip != NULL) {
-			kdb_printf("item 0x%p func 0x%p\n",
-				bio_lip, bio_lip->li_cb);
-			bio_lip = bio_lip->li_bio_list;
-		}
-	}
-	switch (lip->li_type) {
-	case XFS_LI_BUF:
-		xfs_buf_item_print((xfs_buf_log_item_t *)lip, 0);
-		break;
-	case XFS_LI_INODE:
-		xfs_inode_item_print((xfs_inode_log_item_t *)lip, 0);
-		break;
-	case XFS_LI_EFI:
-		xfs_efi_item_print((xfs_efi_log_item_t *)lip, 0);
-		break;
-	case XFS_LI_EFD:
-		xfs_efd_item_print((xfs_efd_log_item_t *)lip, 0);
-		break;
-	case XFS_LI_DQUOT:
-		xfs_dquot_item_print((xfs_dq_logitem_t *)lip, 0);
-		break;
-	case XFS_LI_QUOTAOFF:
-		xfs_qoff_item_print((xfs_qoff_logitem_t *)lip, 0);
-		break;
-
-	default:
-		kdb_printf("Unknown item type %d\n", lip->li_type);
-		break;
-	}
-}
-
-/*
- * Print out a summary of the AIL hanging off of a mount struct.
- */
-static void
-xfsidbg_xaildump(xfs_mount_t *mp)
-{
-	xfs_log_item_t *lip;
-	static char *lid_type[] = {
-		"???",		/* 0 */
-		"5-3-buf",	/* 1 */
-		"5-3-inode",	/* 2 */
-		"efi",		/* 3 */
-		"efd",		/* 4 */
-		"iunlink",	/* 5 */
-		"6-1-inode",	/* 6 */
-		"6-1-buf",	/* 7 */
-		"inode",	/* 8 */
-		"buf",		/* 9 */
-		"dquot",	/* 10 */
-		0
-		};
-	static char *li_flags[] = {
-		"in ail",	/* 0x1 */
-		0
-		};
-	int count;
-
-	if ((mp->m_ail.ail_forw == NULL) ||
-	    (mp->m_ail.ail_forw == (xfs_log_item_t *)&mp->m_ail)) {
-		kdb_printf("AIL is empty\n");
-		return;
-	}
-	kdb_printf("AIL for mp 0x%p, oldest first\n", mp);
-	lip = (xfs_log_item_t*)mp->m_ail.ail_forw;
-	for (count = 0; lip; count++) {
-		kdb_printf("[%d] type %s ", count,
-			      lid_type[lip->li_type - XFS_LI_5_3_BUF + 1]);
-		printflags((uint)(lip->li_flags), li_flags, "flags:");
-		kdb_printf("  lsn %s\n   ", xfs_fmtlsn(&(lip->li_lsn)));
-		switch (lip->li_type) {
-		case XFS_LI_BUF:
-			xfs_buf_item_print((xfs_buf_log_item_t *)lip, 1);
-			break;
-		case XFS_LI_INODE:
-			xfs_inode_item_print((xfs_inode_log_item_t *)lip, 1);
-			break;
-		case XFS_LI_EFI:
-			xfs_efi_item_print((xfs_efi_log_item_t *)lip, 1);
-			break;
-		case XFS_LI_EFD:
-			xfs_efd_item_print((xfs_efd_log_item_t *)lip, 1);
-			break;
-		case XFS_LI_DQUOT:
-			xfs_dquot_item_print((xfs_dq_logitem_t *)lip, 1);
-			break;
-		case XFS_LI_QUOTAOFF:
-			xfs_qoff_item_print((xfs_qoff_logitem_t *)lip, 1);
-			break;
-		default:
-			kdb_printf("Unknown item type %d\n", lip->li_type);
-			break;
-		}
-
-		if (lip->li_ail.ail_forw == (xfs_log_item_t*)&mp->m_ail) {
-			lip = NULL;
-		} else {
-			lip = lip->li_ail.ail_forw;
-		}
-	}
-}
-
-/*
- * Print xfs mount structure.
- */
-static void
-xfsidbg_xmount(xfs_mount_t *mp)
-{
-	static char *xmount_flags[] = {
-		"WSYNC",	/* 0x0001 */
-		"INO64",	/* 0x0002 */
-		"RQCHK",	/* 0x0004 */
-		"FSCLEAN",	/* 0x0008 */
-		"FSSHUTDN",	/* 0x0010 */
-		"NOATIME",	/* 0x0020 */
-		"RETERR",	/* 0x0040 */
-		"NOALIGN",	/* 0x0080 */
-		"UNSHRD",	/* 0x0100 */
-		"RGSTRD",	/* 0x0200 */
-		"NORECVR",	/* 0x0400 */
-		"SHRD",		/* 0x0800 */
-		"IOSZ",		/* 0x1000 */
-		"OSYNC",	/* 0x2000 */
-		"NOUUID",	/* 0x4000 */
-		"32BIT",	/* 0x8000 */
-		"NOLOGFLUSH",	/* 0x10000 */
-		0
-	};
-
-	static char *quota_flags[] = {
-		"UQ",		/* 0x0001 */
-		"UQE",		/* 0x0002 */
-		"UQCHKD",	/* 0x0004 */
-		"PQ",		/* 0x0008 (IRIX ondisk) */
-		"GQE",		/* 0x0010 */
-		"GQCHKD",	/* 0x0020 */
-		"GQ",		/* 0x0040 */
-		"UQACTV",	/* 0x0080 */
-		"GQACTV",	/* 0x0100 */
-		"QMAYBE",	/* 0x0200 */
-		0
-	};
-
-	kdb_printf("xfs_mount at 0x%p\n", mp);
-	kdb_printf("vfsp 0x%p tid 0x%x ail_lock 0x%p &ail 0x%p\n",
-		XFS_MTOVFS(mp), mp->m_tid, &mp->m_ail_lock, &mp->m_ail);
-	kdb_printf("ail_gen 0x%x &sb 0x%p\n",
-		mp->m_ail_gen, &mp->m_sb);
-	kdb_printf("sb_lock 0x%p sb_bp 0x%p dev 0x%x logdev 0x%x rtdev 0x%x\n",
-		&mp->m_sb_lock, mp->m_sb_bp,
-		mp->m_ddev_targp ? mp->m_ddev_targp->pbr_dev : 0,
-		mp->m_logdev_targp ? mp->m_logdev_targp->pbr_dev : 0,
-		mp->m_rtdev_targp ? mp->m_rtdev_targp->pbr_dev : 0);
-	kdb_printf("bsize %d agfrotor %d agirotor %d ihash 0x%p ihsize %d\n",
-		mp->m_bsize, mp->m_agfrotor, mp->m_agirotor,
-		mp->m_ihash, mp->m_ihsize);
-	kdb_printf("inodes 0x%p ilock 0x%p ireclaims 0x%x\n",
-		mp->m_inodes, &mp->m_ilock, mp->m_ireclaims);
-	kdb_printf("readio_log 0x%x readio_blocks 0x%x ",
-		mp->m_readio_log, mp->m_readio_blocks);
-	kdb_printf("writeio_log 0x%x writeio_blocks 0x%x\n",
-		mp->m_writeio_log, mp->m_writeio_blocks);
-	kdb_printf("logbufs %d logbsize %d LOG 0x%p\n", mp->m_logbufs,
-		mp->m_logbsize, mp->m_log);
-	kdb_printf("rsumlevels 0x%x rsumsize 0x%x rbmip 0x%p rsumip 0x%p\n",
-		mp->m_rsumlevels, mp->m_rsumsize, mp->m_rbmip, mp->m_rsumip);
-	kdb_printf("rootip 0x%p\n", mp->m_rootip);
-	kdb_printf("dircook_elog %d blkbit_log %d blkbb_log %d agno_log %d\n",
-		mp->m_dircook_elog, mp->m_blkbit_log, mp->m_blkbb_log,
-		mp->m_agno_log);
-	kdb_printf("agino_log %d nreadaheads %d inode cluster size %d\n",
-		mp->m_agino_log, mp->m_nreadaheads,
-		mp->m_inode_cluster_size);
-	kdb_printf("blockmask 0x%x blockwsize 0x%x blockwmask 0x%x\n",
-		mp->m_blockmask, mp->m_blockwsize, mp->m_blockwmask);
-	kdb_printf("alloc_mxr[lf,nd] %d %d alloc_mnr[lf,nd] %d %d\n",
-		mp->m_alloc_mxr[0], mp->m_alloc_mxr[1],
-		mp->m_alloc_mnr[0], mp->m_alloc_mnr[1]);
-	kdb_printf("bmap_dmxr[lfnr,ndnr] %d %d bmap_dmnr[lfnr,ndnr] %d %d\n",
-		mp->m_bmap_dmxr[0], mp->m_bmap_dmxr[1],
-		mp->m_bmap_dmnr[0], mp->m_bmap_dmnr[1]);
-	kdb_printf("inobt_mxr[lf,nd] %d %d inobt_mnr[lf,nd] %d %d\n",
-		mp->m_inobt_mxr[0], mp->m_inobt_mxr[1],
-		mp->m_inobt_mnr[0], mp->m_inobt_mnr[1]);
-	kdb_printf("ag_maxlevels %d bm_maxlevels[d,a] %d %d in_maxlevels %d\n",
-		mp->m_ag_maxlevels, mp->m_bm_maxlevels[0],
-		mp->m_bm_maxlevels[1], mp->m_in_maxlevels);
-	kdb_printf("perag 0x%p &peraglock 0x%p &growlock 0x%p\n",
-		mp->m_perag, &mp->m_peraglock, &mp->m_growlock);
-	printflags(mp->m_flags, xmount_flags,"flags");
-	kdb_printf("ialloc_inos %d ialloc_blks %d litino %d\n",
-		mp->m_ialloc_inos, mp->m_ialloc_blks, mp->m_litino);
-	kdb_printf("dir_node_ents %u attr_node_ents %u\n",
-		mp->m_dir_node_ents, mp->m_attr_node_ents);
-	kdb_printf("attroffset %d maxicount %Ld inoalign_mask %d\n",
-		mp->m_attroffset, mp->m_maxicount, mp->m_inoalign_mask);
-	kdb_printf("resblks %Ld resblks_avail %Ld\n", mp->m_resblks,
-		mp->m_resblks_avail);
-#if XFS_BIG_INUMS
-	kdb_printf(" inoadd %llx\n", (unsigned long long) mp->m_inoadd);
-#else
-	kdb_printf("\n");
-#endif
-	if (mp->m_quotainfo)
-		kdb_printf("quotainfo 0x%p (uqip = 0x%p, gqip = 0x%p)\n",
-			mp->m_quotainfo,
-			mp->m_quotainfo->qi_uquotaip,
-			mp->m_quotainfo->qi_gquotaip);
-	else
-		kdb_printf("quotainfo NULL\n");
-	printflags(mp->m_qflags, quota_flags,"quotaflags");
-	kdb_printf("\n");
-	kdb_printf("dalign %d swidth %d sinoalign %d attr_magicpct %d dir_magicpct %d\n",
-		mp->m_dalign, mp->m_swidth, mp->m_sinoalign,
-		mp->m_attr_magicpct, mp->m_dir_magicpct);
-	kdb_printf("mk_sharedro %d inode_quiesce %d sectbb_log %d\n",
-		mp->m_mk_sharedro, mp->m_inode_quiesce, mp->m_sectbb_log);
-	kdb_printf("dirversion %d dirblkfsbs %d &dirops 0x%p\n",
-		mp->m_dirversion, mp->m_dirblkfsbs, &mp->m_dirops);
-	kdb_printf("dirblksize %d dirdatablk 0x%Lx dirleafblk 0x%Lx dirfreeblk 0x%Lx\n",
-		mp->m_dirblksize,
-		(xfs_dfiloff_t)mp->m_dirdatablk,
-		(xfs_dfiloff_t)mp->m_dirleafblk,
-		(xfs_dfiloff_t)mp->m_dirfreeblk);
-	kdb_printf("chsize %d chash 0x%p\n",
-		mp->m_chsize, mp->m_chash);
-	kdb_printf("m_frozen %d m_active_trans %d\n",
-		mp->m_frozen, mp->m_active_trans.counter);
-	if (mp->m_fsname != NULL)
-		kdb_printf("mountpoint \"%s\"\n", mp->m_fsname);
-	else
-		kdb_printf("No name!!!\n");
-
-}
-
-static void
-xfsidbg_xihash(xfs_mount_t *mp)
-{
-	xfs_ihash_t	*ih;
-	int		i;
-	int		j;
-	int		total;
-	int		numzeros;
-	xfs_inode_t	*ip;
-	int		*hist;
-	int		hist_bytes = mp->m_ihsize * sizeof(int);
-	int		hist2[21];
-
-	hist = (int *) kmalloc(hist_bytes, GFP_KERNEL);
-
-	if (hist == NULL) {
-		kdb_printf("xfsidbg_xihash: kmalloc(%d) failed!\n",
-							hist_bytes);
-		return;
-	}
-
-	for (i = 0; i < mp->m_ihsize; i++) {
-		ih = mp->m_ihash + i;
-		j = 0;
-		for (ip = ih->ih_next; ip != NULL; ip = ip->i_next)
-			j++;
-		hist[i] = j;
-	}
-
-	numzeros = total = 0;
-
-	for (i = 0; i < 21; i++)
-		hist2[i] = 0;
-
-	for (i = 0; i < mp->m_ihsize; i++)  {
-		kdb_printf("%d ", hist[i]);
-		total += hist[i];
-		numzeros += hist[i] == 0 ? 1 : 0;
-		if (hist[i] > 20)
-			j = 20;
-		else
-			j = hist[i];
-
-		if (! (j <= 20)) {
-			kdb_printf("xfsidbg_xihash: (j > 20)/%d @ line # %d\n",
-							j, __LINE__);
-			return;
-		}
-
-		hist2[j]++;
-	}
-
-	kdb_printf("\n");
-
-	kdb_printf("total inodes = %d, average length = %d, adjusted average = %d \n",
-		total, total / mp->m_ihsize,
-		total / (mp->m_ihsize - numzeros));
-
-	for (i = 0; i < 21; i++)  {
-		kdb_printf("%d - %d , ", i, hist2[i]);
-	}
-	kdb_printf("\n");
-	kfree(hist);
-}
-
-/*
- * Command to print xfs inodes: kp xnode <addr>
- */
-static void
-xfsidbg_xnode(xfs_inode_t *ip)
-{
-	static char *tab_flags[] = {
-		"grio",		/* XFS_IGRIO */
-		"uiosize",	/* XFS_IUIOSZ */
-		"quiesce",	/* XFS_IQUIESCE */
-		"reclaim",	/* XFS_IRECLAIM */
-		"stale",	/* XFS_ISTALE */
-		NULL
-	};
-
-	kdb_printf("hash 0x%p next 0x%p prevp 0x%p mount 0x%p\n",
-		ip->i_hash,
-		ip->i_next,
-		ip->i_prevp,
-		ip->i_mount);
-	kdb_printf("mnext 0x%p mprev 0x%p vnode 0x%p \n",
-		ip->i_mnext,
-		ip->i_mprev,
-		XFS_ITOV_NULL(ip));
-	kdb_printf("dev %x ino %s\n",
-		ip->i_mount->m_dev,
-		xfs_fmtino(ip->i_ino, ip->i_mount));
-	kdb_printf("blkno 0x%llx len 0x%x boffset 0x%x\n",
-		(long long) ip->i_blkno,
-		ip->i_len,
-		ip->i_boffset);
-	kdb_printf("transp 0x%p &itemp 0x%p\n",
-		ip->i_transp,
-		ip->i_itemp);
-	kdb_printf("&lock 0x%p &iolock 0x%p ",
-		&ip->i_lock,
-		&ip->i_iolock);
-	kdb_printf("&flock 0x%p (%d) pincount 0x%x\n",
-		&ip->i_flock, valusema(&ip->i_flock),
-		xfs_ipincount(ip));
-	kdb_printf("udquotp 0x%p gdquotp 0x%p\n",
-		ip->i_udquot, ip->i_gdquot);
-	kdb_printf("new_size %Ld\n", ip->i_iocore.io_new_size);
-	printflags((int)ip->i_flags, tab_flags, "flags");
-	kdb_printf("\n");
-	kdb_printf("update_core %d update size %d\n",
-		(int)(ip->i_update_core), (int) ip->i_update_size);
-	kdb_printf("gen 0x%x delayed blks %d",
-		ip->i_gen,
-		ip->i_delayed_blks);
-#ifdef XFS_BMAP_TRACE
-	qprintf(" bmap_trace 0x%p\n", ip->i_xtrace);
-#endif
-#ifdef XFS_BMBT_TRACE
-	qprintf(" bmbt trace 0x%p\n", ip->i_btrace);
-#endif  
-#ifdef XFS_RW_TRACE
-	qprintf(" rw trace 0x%p\n", ip->i_rwtrace);
-#endif  
-#ifdef XFS_ILOCK_TRACE
-	qprintf(" ilock trace 0x%p\n", ip->i_lock_trace);
-#endif
-#ifdef XFS_DIR2_TRACE
-	qprintf(" dir trace 0x%p\n", ip->i_dir_trace);
-#endif  
-	kdb_printf("\n");
-	kdb_printf("chash 0x%p cnext 0x%p cprev 0x%p\n",
-		ip->i_chash,
-		ip->i_cnext,
-		ip->i_cprev);
-	xfs_xnode_fork("data", &ip->i_df);
-	xfs_xnode_fork("attr", ip->i_afp);
-	kdb_printf("\n");
-	xfs_prdinode_core(&ip->i_d, ARCH_NOCONVERT);
-}
-
-static void
-xfsidbg_xcore(xfs_iocore_t *io)
-{
-	kdb_printf("io_obj 0x%p io_flags 0x%x io_mount 0x%p\n",
-			io->io_obj, io->io_flags, io->io_mount);
-	kdb_printf("new_size %Lx\n", io->io_new_size);
-}
-
-/*
- * Command to print xfs inode cluster hash table: kp xchash <addr>
- */
-static void
-xfsidbg_xchash(xfs_mount_t *mp)
-{
-	int		i;
-	xfs_chash_t	*ch;
-
-	kdb_printf("m_chash 0x%p size %d\n",
-		mp->m_chash, mp->m_chsize);
-	for (i = 0; i < mp->m_chsize; i++) {
-		ch = mp->m_chash + i;
-		kdb_printf("[%3d] ch 0x%p chashlist 0x%p\n", i, ch, ch->ch_list);
-		xfsidbg_xchashlist(ch->ch_list);
-	}
-}
-
-/*
- * Command to print xfs inode cluster hash list: kp xchashlist <addr>
- */
-static void
-xfsidbg_xchashlist(xfs_chashlist_t *chl)
-{
-	xfs_inode_t	*ip;
-
-	while (chl != NULL) {
-		kdb_printf("hashlist inode 0x%p blkno %lld buf 0x%p",
-		       chl->chl_ip, (long long) chl->chl_blkno, chl->chl_buf);
-
-		kdb_printf("\n");
-
-		/* print inodes on chashlist */
-		ip = chl->chl_ip;
-		do {
-			kdb_printf("0x%p ", ip);
-			ip = ip->i_cnext;
-		} while (ip != chl->chl_ip);
-		kdb_printf("\n");
-
-		chl=chl->chl_next;
-	}
-}
-
-/*
- * Print xfs per-ag data structures for filesystem.
- */
-static void
-xfsidbg_xperag(xfs_mount_t *mp)
-{
-	xfs_agnumber_t	agno;
-	xfs_perag_t	*pag;
-	int		busy;
-
-	pag = mp->m_perag;
-	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++, pag++) {
-		kdb_printf("ag %d f_init %d i_init %d\n",
-			agno, pag->pagf_init, pag->pagi_init);
-		if (pag->pagf_init)
-			kdb_printf(
-	"    f_levels[b,c] %d,%d f_flcount %d f_freeblks %d f_longest %d\n"
-	"    f__metadata %d\n",
-				pag->pagf_levels[XFS_BTNUM_BNOi],
-				pag->pagf_levels[XFS_BTNUM_CNTi],
-				pag->pagf_flcount, pag->pagf_freeblks,
-				pag->pagf_longest, pag->pagf_metadata);
-		if (pag->pagi_init)
-			kdb_printf("    i_freecount %d i_inodeok %d\n",
-				pag->pagi_freecount, pag->pagi_inodeok);
-		if (pag->pagf_init) {
-			for (busy = 0; busy < XFS_PAGB_NUM_SLOTS; busy++) {
-				if (pag->pagb_list[busy].busy_length != 0) {
-					kdb_printf(
-		"	 %04d: start %d length %d tp 0x%p\n",
-					    busy,
-					    pag->pagb_list[busy].busy_start,
-					    pag->pagb_list[busy].busy_length,
-					    pag->pagb_list[busy].busy_tp);
-				}
-			}
-		}
-	}
-}
-
-#ifdef CONFIG_XFS_QUOTA
-static void
-xfsidbg_xqm()
-{
-	if (xfs_Gqm == NULL) {
-		kdb_printf("NULL XQM!!\n");
-		return;
-	}
-
-	kdb_printf("usrhtab 0x%p\tgrphtab 0x%p\tndqfree 0x%x\thashmask 0x%x\n",
-		xfs_Gqm->qm_usr_dqhtable,
-		xfs_Gqm->qm_grp_dqhtable,
-		xfs_Gqm->qm_dqfreelist.qh_nelems,
-		xfs_Gqm->qm_dqhashmask);
-	kdb_printf("&freelist 0x%p, totaldquots 0x%x nrefs 0x%x\n",
-		&xfs_Gqm->qm_dqfreelist,
-		atomic_read(&xfs_Gqm->qm_totaldquots),
-		xfs_Gqm->qm_nrefs);
-}
-#endif
-
-static void
-xfsidbg_xqm_diskdq(xfs_disk_dquot_t *d)
-{
-	kdb_printf("magic 0x%x\tversion 0x%x\tID 0x%x (%d)\t\n",
-		INT_GET(d->d_magic, ARCH_CONVERT),
-		INT_GET(d->d_version, ARCH_CONVERT),
-		INT_GET(d->d_id, ARCH_CONVERT),
-		INT_GET(d->d_id, ARCH_CONVERT));
-	kdb_printf("bhard 0x%llx\tbsoft 0x%llx\tihard 0x%llx\tisoft 0x%llx\n",
-		(unsigned long long)INT_GET(d->d_blk_hardlimit, ARCH_CONVERT),
-		(unsigned long long)INT_GET(d->d_blk_softlimit, ARCH_CONVERT),
-		(unsigned long long)INT_GET(d->d_ino_hardlimit, ARCH_CONVERT),
-		(unsigned long long)INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
-	kdb_printf("bcount 0x%llx icount 0x%llx\n",
-		(unsigned long long)INT_GET(d->d_bcount, ARCH_CONVERT),
-		(unsigned long long)INT_GET(d->d_icount, ARCH_CONVERT));
-	kdb_printf("btimer 0x%x itimer 0x%x \n",
-		(int)INT_GET(d->d_btimer, ARCH_CONVERT),
-		(int)INT_GET(d->d_itimer, ARCH_CONVERT));
-}
-
-static void
-xfsidbg_xqm_dquot(xfs_dquot_t *dqp)
-{
-	static char *qflags[] = {
-		"USR",
-		"GRP",
-		"LCKD",
-		"FLKD",
-		"DIRTY",
-		"WANT",
-		"INACT",
-		"MARKER",
-		0
-	};
-	kdb_printf("mount 0x%p hash 0x%p gdquotp 0x%p HL_next 0x%p HL_prevp 0x%p\n",
-		dqp->q_mount,
-		dqp->q_hash,
-		dqp->q_gdquot,
-		dqp->HL_NEXT,
-		dqp->HL_PREVP);
-	kdb_printf("MPL_next 0x%p MPL_prevp 0x%p FL_next 0x%p FL_prev 0x%p\n",
-		dqp->MPL_NEXT,
-		dqp->MPL_PREVP,
-		dqp->dq_flnext,
-		dqp->dq_flprev);
-
-	kdb_printf("nrefs 0x%x, res_bcount %d, ",
-		dqp->q_nrefs, (int) dqp->q_res_bcount);
-	printflags(dqp->dq_flags, qflags, "flags:");
-	kdb_printf("\nblkno 0x%llx\tboffset 0x%x\n",
-		(unsigned long long) dqp->q_blkno, (int) dqp->q_bufoffset);
-	kdb_printf("qlock 0x%p  flock 0x%p (%s) pincount 0x%x\n",
-		&dqp->q_qlock,
-		&dqp->q_flock,
-		(valusema(&dqp->q_flock) <= 0) ? "LCK" : "UNLKD",
-		dqp->q_pincount);
-#ifdef XFS_DQUOT_TRACE
-	qprintf("dqtrace 0x%p\n", dqp->q_trace);
-#endif
-	kdb_printf("disk-dquot 0x%p\n", &dqp->q_core);
-	xfsidbg_xqm_diskdq(&dqp->q_core);
-
-}
-
-
-#define XQMIDBG_LIST_PRINT(l, NXT) \
-{ \
-	  xfs_dquot_t	*dqp;\
-	  int i = 0; \
-	  kdb_printf("[#%d dquots]\n", (int) (l)->qh_nelems); \
-	  for (dqp = (l)->qh_next; dqp != NULL; dqp = dqp->NXT) {\
-	   kdb_printf( \
-	      "\t%d. [0x%p] \"%d (%s)\"\t blks = %d, inos = %d refs = %d\n", \
-			 ++i, dqp, (int) INT_GET(dqp->q_core.d_id, ARCH_CONVERT), \
-			 DQFLAGTO_TYPESTR(dqp),      \
-			 (int) INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), \
-			 (int) INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), \
-			 (int) dqp->q_nrefs); }\
-	  kdb_printf("\n"); \
-}
-
-static void
-xfsidbg_xqm_dqattached_inos(xfs_mount_t	*mp)
-{
-	xfs_inode_t	*ip;
-	int		n = 0;
-
-	ip = mp->m_inodes;
-	do {
-		if (ip->i_mount == NULL) {
-			ip = ip->i_mnext;
-			continue;
-		}
-		if (ip->i_udquot || ip->i_gdquot) {
-			n++;
-			kdb_printf("inode = 0x%p, ino %d: udq 0x%p, gdq 0x%p\n",
-				ip, (int)ip->i_ino, ip->i_udquot, ip->i_gdquot);
-		}
-		ip = ip->i_mnext;
-	} while (ip != mp->m_inodes);
-	kdb_printf("\nNumber of inodes with dquots attached: %d\n", n);
-}
-
-#ifdef CONFIG_XFS_QUOTA
-static void
-xfsidbg_xqm_freelist_print(xfs_frlist_t *qlist, char *title)
-{
-	xfs_dquot_t *dq;
-	int i = 0;
-	kdb_printf("%s (#%d)\n", title, (int) qlist->qh_nelems);
-	FOREACH_DQUOT_IN_FREELIST(dq, qlist) {
-		kdb_printf("\t%d.\t\"%d (%s:0x%p)\"\t bcnt = %d, icnt = %d "
-		       "refs = %d\n",
-		       ++i, (int) INT_GET(dq->q_core.d_id, ARCH_CONVERT),
-		       DQFLAGTO_TYPESTR(dq), dq,
-		       (int) INT_GET(dq->q_core.d_bcount, ARCH_CONVERT),
-		       (int) INT_GET(dq->q_core.d_icount, ARCH_CONVERT),
-		       (int) dq->q_nrefs);
-	}
-}
-
-static void
-xfsidbg_xqm_freelist(void)
-{
-	if (xfs_Gqm) {
-		xfsidbg_xqm_freelist_print(&(xfs_Gqm->qm_dqfreelist), "Freelist");
-	} else
-		kdb_printf("NULL XQM!!\n");
-}
-
-static void
-xfsidbg_xqm_htab(void)
-{
-	int		i;
-	xfs_dqhash_t	*h;
-
-	if (xfs_Gqm == NULL) {
-		kdb_printf("NULL XQM!!\n");
-		return;
-	}
-	for (i = 0; i <= xfs_Gqm->qm_dqhashmask; i++) {
-		h = &xfs_Gqm->qm_usr_dqhtable[i];
-		if (h->qh_next) {
-			kdb_printf("USR %d: ", i);
-			XQMIDBG_LIST_PRINT(h, HL_NEXT);
-		}
-	}
-	for (i = 0; i <= xfs_Gqm->qm_dqhashmask; i++) {
-		h = &xfs_Gqm->qm_grp_dqhtable[i];
-		if (h->qh_next) {
-			kdb_printf("GRP %d: ", i);
-			XQMIDBG_LIST_PRINT(h, HL_NEXT);
-		}
-	}
-}
-#endif
-
-#ifdef XFS_DQUOT_TRACE
-static int
-xfsidbg_xqm_pr_dqentry(ktrace_entry_t *ktep)
-{
-	static char *xdq_flags[] = {
-		"USR",	  /* 0x1 */
-		"PRJ",	  /* 0x2 */
-		"LCKD",	 /* 0x4 */
-		"GRP",	  /* 0x8 */
-		"FLOCKD",       /* 0x08 */
-		"DIRTY",	/* 0x10 */
-		"WANT",	 /* 0x20 */
-		"INACT",	/* 0x40 */
-		"MARKER",       /* 0x80 */
-		0
-	};
-
-	if ((__psint_t)ktep->val[0] == 0)
-		return 0;
-	switch ((__psint_t)ktep->val[0]) {
-	      case DQUOT_KTRACE_ENTRY:
-		qprintf("[%ld] %s\t",
-			(long)ktep->val[12], /* pid */
-			(char *)ktep->val[1]);
-		printflags((__psint_t)ktep->val[3], xdq_flags,"flgs ");
-		qprintf("\nnrefs = %u, "
-			"flags = 0x%x, "
-			"id = %d, "
-			"res_bc = 0x%x\n"
-			"bcnt = 0x%x [0x%x | 0x%x], "
-			"icnt = 0x%x [0x%x | 0x%x]\n"
-			"@ %ld\n",
-			(unsigned int)(long)ktep->val[2], /* nrefs */
-			(unsigned int)(long)ktep->val[3], /* flags */
-			(unsigned int)(long)ktep->val[11], /* ID */
-			(unsigned int)(long)ktep->val[4], /* res_bc */
-			(unsigned int)(long)ktep->val[5], /* bcnt */
-			(unsigned int)(long)ktep->val[8], /* bsoft */
-			(unsigned int)(long)ktep->val[7], /* bhard */
-			(unsigned int)(long)ktep->val[6], /* icnt */
-			(unsigned int)(long)ktep->val[10], /* isoft */
-			(unsigned int)(long)ktep->val[9], /* ihard */
-			(long) ktep->val[13] /* time */
-			);
-		break;
-
-	      default:
-		qprintf("unknown dqtrace record\n");
-		break;
-	}
-	return (1);
-}
-
-void
-xfsidbg_xqm_dqtrace(xfs_dquot_t *dqp)
-{
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-
-	if (dqp->q_trace == NULL) {
-		qprintf("The xfs dquot trace buffer is not initialized\n");
-		return;
-	}
-	qprintf("xdqtrace dquot 0x%p\n", dqp);
-
-	ktep = ktrace_first(dqp->q_trace, &kts);
-	while (ktep != NULL) {
-		if (xfsidbg_xqm_pr_dqentry(ktep))
-			qprintf("---------------------------------\n");
-		ktep = ktrace_next(dqp->q_trace, &kts);
-	}
-}
-#endif
-
-static void
-xfsidbg_xqm_mplist(xfs_mount_t *mp)
-{
-	if (mp->m_quotainfo == NULL) {
-		kdb_printf("NULL quotainfo\n");
-		return;
-	}
-
-	XQMIDBG_LIST_PRINT(&(mp->m_quotainfo->qi_dqlist), MPL_NEXT);
-
-}
-
-
-static void
-xfsidbg_xqm_qinfo(xfs_mount_t *mp)
-{
-	if (mp == NULL || mp->m_quotainfo == NULL) {
-		kdb_printf("NULL quotainfo\n");
-		return;
-	}
-
-	kdb_printf("uqip 0x%p, gqip 0x%p, &pinlock 0x%p &dqlist 0x%p\n",
-		mp->m_quotainfo->qi_uquotaip,
-		mp->m_quotainfo->qi_gquotaip,
-		&mp->m_quotainfo->qi_pinlock,
-		&mp->m_quotainfo->qi_dqlist);
-
-	kdb_printf("nreclaims %d, btmlimit 0x%x, itmlimit 0x%x, RTbtmlim 0x%x\n",
-		(int)mp->m_quotainfo->qi_dqreclaims,
-		(int)mp->m_quotainfo->qi_btimelimit,
-		(int)mp->m_quotainfo->qi_itimelimit,
-		(int)mp->m_quotainfo->qi_rtbtimelimit);
-
-	kdb_printf("bwarnlim 0x%x, iwarnlim 0x%x, &qofflock 0x%p, "
-		"chunklen 0x%x, dqperchunk 0x%x\n",
-		(int)mp->m_quotainfo->qi_bwarnlimit,
-		(int)mp->m_quotainfo->qi_iwarnlimit,
-		&mp->m_quotainfo->qi_quotaofflock,
-		(int)mp->m_quotainfo->qi_dqchunklen,
-		(int)mp->m_quotainfo->qi_dqperchunk);
-}
-
-static void
-xfsidbg_xqm_tpdqinfo(xfs_trans_t *tp)
-{
-	xfs_dqtrx_t	*qa, *q;
-	int		i,j;
-
-	kdb_printf("dqinfo 0x%p\n", tp->t_dqinfo);
-	if (! tp->t_dqinfo)
-		return;
-	kdb_printf("USR: \n");
-	qa = tp->t_dqinfo->dqa_usrdquots;
-	for (j = 0; j < 2; j++) {
-		for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
-			if (qa[i].qt_dquot == NULL)
-				break;
-			q = &qa[i];
-			kdb_printf(
-  "\"%d\"[0x%p]: bres %d, bres-used %d, bdelta %d, del-delta %d, icnt-delta %d\n",
-				(int) q->qt_dquot->q_core.d_id,
-				q->qt_dquot,
-				(int) q->qt_blk_res,
-				(int) q->qt_blk_res_used,
-				(int) q->qt_bcount_delta,
-				(int) q->qt_delbcnt_delta,
-				(int) q->qt_icount_delta);
-		}
-		if (j == 0) {
-			qa = tp->t_dqinfo->dqa_grpdquots;
-			kdb_printf("GRP: \n");
-		}
-	}
-
-}
-
-#ifdef XFS_RW_TRACE
-/*
- * Print out the read/write trace buffer attached to the given inode.
- */
-static void
-xfsidbg_xrwtrace(xfs_inode_t *ip)
-{
-	ktrace_entry_t	*ktep;
-	ktrace_snap_t	kts;
-	int		nentries;
-	int		skip_entries;
-	int		count = xargument;
-
-	if (ip->i_rwtrace == NULL) {
-		qprintf("The inode trace buffer is not initialized\n");
-		return;
-	}
-	qprintf("i_rwtrace = 0x%p\n", ip->i_rwtrace);
-
-	nentries = ktrace_nentries(ip->i_rwtrace);
-	if (count == -1) {
-		count = nentries;
-	}
-	if ((count <= 0) || (count > nentries)) {
-		qprintf("Invalid count.  There are %d entries.\n", nentries);
-		return;
-	}
-
-	ktep = ktrace_first(ip->i_rwtrace, &kts);
-	if (count != nentries) {
-		/*
-		 * Skip the total minus the number to look at minus one
-		 * for the entry returned by ktrace_first().
-		 */
-		skip_entries = count - nentries - 1;
-		ktep = ktrace_skip(ip->i_rwtrace, skip_entries, &kts);
-		if (ktep == NULL) {
-			qprintf("Skipped them all\n");
-			return;
-		}
-	}
-	while (ktep != NULL) {
-		if (xfs_rw_trace_entry(ktep))
-			qprintf("\n");
-		ktep = ktrace_next(ip->i_rwtrace, &kts);
-	}
-}
-#endif
-
-/*
- * Print xfs superblock.
- */
-static void
-xfsidbg_xsb(xfs_sb_t *sbp, int convert)
-{
-	xfs_arch_t arch=convert?ARCH_CONVERT:ARCH_NOCONVERT;
-
-	kdb_printf(convert?"<converted>\n":"<unconverted>\n");
-
-	kdb_printf("magicnum 0x%x blocksize 0x%x dblocks %Ld rblocks %Ld\n",
-		INT_GET(sbp->sb_magicnum, arch), INT_GET(sbp->sb_blocksize, arch),
-		INT_GET(sbp->sb_dblocks, arch), INT_GET(sbp->sb_rblocks, arch));
-	kdb_printf("rextents %Ld uuid %s logstart %s\n",
-		INT_GET(sbp->sb_rextents, arch),
-		xfs_fmtuuid(&sbp->sb_uuid),
-		xfs_fmtfsblock(INT_GET(sbp->sb_logstart, arch), NULL));
-	kdb_printf("rootino %s ",
-		xfs_fmtino(INT_GET(sbp->sb_rootino, arch), NULL));
-	kdb_printf("rbmino %s ",
-		xfs_fmtino(INT_GET(sbp->sb_rbmino, arch), NULL));
-	kdb_printf("rsumino %s\n",
-		xfs_fmtino(INT_GET(sbp->sb_rsumino, arch), NULL));
-	kdb_printf("rextsize 0x%x agblocks 0x%x agcount 0x%x rbmblocks 0x%x\n",
-		INT_GET(sbp->sb_rextsize, arch),
-		INT_GET(sbp->sb_agblocks, arch),
-		INT_GET(sbp->sb_agcount, arch),
-		INT_GET(sbp->sb_rbmblocks, arch));
-	kdb_printf("logblocks 0x%x versionnum 0x%x sectsize 0x%x inodesize 0x%x\n",
-		INT_GET(sbp->sb_logblocks, arch),
-		INT_GET(sbp->sb_versionnum, arch),
-		INT_GET(sbp->sb_sectsize, arch),
-		INT_GET(sbp->sb_inodesize, arch));
-	kdb_printf("inopblock 0x%x blocklog 0x%x sectlog 0x%x inodelog 0x%x\n",
-		INT_GET(sbp->sb_inopblock, arch),
-		INT_GET(sbp->sb_blocklog, arch),
-		INT_GET(sbp->sb_sectlog, arch),
-		INT_GET(sbp->sb_inodelog, arch));
-	kdb_printf("inopblog %d agblklog %d rextslog %d inprogress %d imax_pct %d\n",
-		INT_GET(sbp->sb_inopblog, arch),
-		INT_GET(sbp->sb_agblklog, arch),
-		INT_GET(sbp->sb_rextslog, arch),
-		INT_GET(sbp->sb_inprogress, arch),
-		INT_GET(sbp->sb_imax_pct, arch));
-	kdb_printf("icount %Lx ifree %Lx fdblocks %Lx frextents %Lx\n",
-		INT_GET(sbp->sb_icount, arch),
-		INT_GET(sbp->sb_ifree, arch),
-		INT_GET(sbp->sb_fdblocks, arch),
-		INT_GET(sbp->sb_frextents, arch));
-	kdb_printf("uquotino %s ", xfs_fmtino(INT_GET(sbp->sb_uquotino, arch), NULL));
-	kdb_printf("gquotino %s ", xfs_fmtino(INT_GET(sbp->sb_gquotino, arch), NULL));
-	kdb_printf("qflags 0x%x flags 0x%x shared_vn %d inoaligmt %d\n",
-		INT_GET(sbp->sb_qflags, arch), INT_GET(sbp->sb_flags, arch), INT_GET(sbp->sb_shared_vn, arch),
-		INT_GET(sbp->sb_inoalignmt, arch));
-	kdb_printf("unit %d width %d dirblklog %d\n",
-		INT_GET(sbp->sb_unit, arch), INT_GET(sbp->sb_width, arch), INT_GET(sbp->sb_dirblklog, arch));
-	kdb_printf("log sunit %d\n", INT_GET(sbp->sb_logsunit, arch));
-}
-
-
-/*
- * Print out an XFS transaction structure.  Print summaries for
- * each of the items.
- */
-static void
-xfsidbg_xtp(xfs_trans_t *tp)
-{
-	xfs_log_item_chunk_t	*licp;
-	xfs_log_item_desc_t	*lidp;
-	xfs_log_busy_chunk_t	*lbcp;
-	int			i;
-	int			chunk;
-	static char *xtp_flags[] = {
-		"dirty",	/* 0x1 */
-		"sb_dirty",	/* 0x2 */
-		"perm_log_res",	/* 0x4 */
-		"sync",		 /* 0x08 */
-		"dq_dirty",     /* 0x10 */
-		0
-		};
-	static char *lid_flags[] = {
-		"dirty",	/* 0x1 */
-		"pinned",	/* 0x2 */
-		"sync unlock",	/* 0x4 */
-		"buf stale",	/* 0x8 */
-		0
-		};
-
-	kdb_printf("tp 0x%p type ", tp);
-	switch (tp->t_type) {
-	case XFS_TRANS_SETATTR_NOT_SIZE: kdb_printf("SETATTR_NOT_SIZE");break;
-	case XFS_TRANS_SETATTR_SIZE:	kdb_printf("SETATTR_SIZE");	break;
-	case XFS_TRANS_INACTIVE:	kdb_printf("INACTIVE");		break;
-	case XFS_TRANS_CREATE:		kdb_printf("CREATE");		break;
-	case XFS_TRANS_CREATE_TRUNC:	kdb_printf("CREATE_TRUNC");	break;
-	case XFS_TRANS_TRUNCATE_FILE:	kdb_printf("TRUNCATE_FILE");	break;
-	case XFS_TRANS_REMOVE:		kdb_printf("REMOVE");		break;
-	case XFS_TRANS_LINK:		kdb_printf("LINK");		break;
-	case XFS_TRANS_RENAME:		kdb_printf("RENAME");		break;
-	case XFS_TRANS_MKDIR:		kdb_printf("MKDIR");		break;
-	case XFS_TRANS_RMDIR:		kdb_printf("RMDIR");		break;
-	case XFS_TRANS_SYMLINK:		kdb_printf("SYMLINK");		break;
-	case XFS_TRANS_SET_DMATTRS:	kdb_printf("SET_DMATTRS");	break;
-	case XFS_TRANS_GROWFS:		kdb_printf("GROWFS");		break;
-	case XFS_TRANS_STRAT_WRITE:	kdb_printf("STRAT_WRITE");	break;
-	case XFS_TRANS_DIOSTRAT:	kdb_printf("DIOSTRAT");		break;
-	case XFS_TRANS_WRITE_SYNC:	kdb_printf("WRITE_SYNC");	break;
-	case XFS_TRANS_WRITEID:		kdb_printf("WRITEID");		break;
-	case XFS_TRANS_ADDAFORK:	kdb_printf("ADDAFORK");		break;
-	case XFS_TRANS_ATTRINVAL:	kdb_printf("ATTRINVAL");	break;
-	case XFS_TRANS_ATRUNCATE:	kdb_printf("ATRUNCATE");	break;
-	case XFS_TRANS_ATTR_SET:	kdb_printf("ATTR_SET");		break;
-	case XFS_TRANS_ATTR_RM:		kdb_printf("ATTR_RM");		break;
-	case XFS_TRANS_ATTR_FLAG:	kdb_printf("ATTR_FLAG");	break;
-	case XFS_TRANS_CLEAR_AGI_BUCKET:kdb_printf("CLEAR_AGI_BUCKET");	break;
-	case XFS_TRANS_QM_SBCHANGE:	kdb_printf("QM_SBCHANGE");	break;
-	case XFS_TRANS_QM_QUOTAOFF:	kdb_printf("QM_QUOTAOFF");	break;
-	case XFS_TRANS_QM_DQALLOC:	kdb_printf("QM_DQALLOC");	break;
-	case XFS_TRANS_QM_SETQLIM:	kdb_printf("QM_SETQLIM");	break;
-	case XFS_TRANS_QM_DQCLUSTER:	kdb_printf("QM_DQCLUSTER");	break;
-	case XFS_TRANS_QM_QINOCREATE:	kdb_printf("QM_QINOCREATE");	break;
-	case XFS_TRANS_QM_QUOTAOFF_END:	kdb_printf("QM_QOFF_END");	break;
-	case XFS_TRANS_SB_UNIT:		kdb_printf("SB_UNIT");		break;
-	case XFS_TRANS_FSYNC_TS:	kdb_printf("FSYNC_TS");		break;
-	case XFS_TRANS_GROWFSRT_ALLOC:	kdb_printf("GROWFSRT_ALLOC");	break;
-	case XFS_TRANS_GROWFSRT_ZERO:	kdb_printf("GROWFSRT_ZERO");	break;
-	case XFS_TRANS_GROWFSRT_FREE:	kdb_printf("GROWFSRT_FREE");	break;
-	default:			kdb_printf("0x%x", tp->t_type);	break;
-	}
-	kdb_printf(" mount 0x%p\n", tp->t_mountp);
-	kdb_printf("flags ");
-	printflags(tp->t_flags, xtp_flags,"xtp");
-	kdb_printf("\n");
-	kdb_printf("callback 0x%p forw 0x%p back 0x%p\n",
-		&tp->t_logcb, tp->t_forw, tp->t_back);
-	kdb_printf("log res %d block res %d block res used %d\n",
-		tp->t_log_res, tp->t_blk_res, tp->t_blk_res_used);
-	kdb_printf("rt res %d rt res used %d\n", tp->t_rtx_res,
-		tp->t_rtx_res_used);
-	kdb_printf("ticket 0x%lx lsn %s commit_lsn %s\n",
-		(unsigned long) tp->t_ticket,
-		xfs_fmtlsn(&tp->t_lsn),
-		xfs_fmtlsn(&tp->t_commit_lsn));
-	kdb_printf("callback 0x%p callarg 0x%p\n",
-		tp->t_callback, tp->t_callarg);
-	kdb_printf("icount delta %ld ifree delta %ld\n",
-		tp->t_icount_delta, tp->t_ifree_delta);
-	kdb_printf("blocks delta %ld res blocks delta %ld\n",
-		tp->t_fdblocks_delta, tp->t_res_fdblocks_delta);
-	kdb_printf("rt delta %ld res rt delta %ld\n",
-		tp->t_frextents_delta, tp->t_res_frextents_delta);
-	kdb_printf("ag freeblks delta %ld ag flist delta %ld ag btree delta %ld\n",
-		tp->t_ag_freeblks_delta, tp->t_ag_flist_delta,
-		tp->t_ag_btree_delta);
-	kdb_printf("dblocks delta %ld agcount delta %ld imaxpct delta %ld\n",
-		tp->t_dblocks_delta, tp->t_agcount_delta, tp->t_imaxpct_delta);
-	kdb_printf("rextsize delta %ld rbmblocks delta %ld\n",
-		tp->t_rextsize_delta, tp->t_rbmblocks_delta);
-	kdb_printf("rblocks delta %ld rextents delta %ld rextslog delta %ld\n",
-		tp->t_rblocks_delta, tp->t_rextents_delta,
-		tp->t_rextslog_delta);
-	kdb_printf("dqinfo 0x%p\n", tp->t_dqinfo);
-	kdb_printf("log items:\n");
-	licp = &tp->t_items;
-	chunk = 0;
-	while (licp != NULL) {
-		if (XFS_LIC_ARE_ALL_FREE(licp)) {
-			licp = licp->lic_next;
-			chunk++;
-			continue;
-		}
-		for (i = 0; i < licp->lic_unused; i++) {
-			if (XFS_LIC_ISFREE(licp, i)) {
-				continue;
-			}
-
-			lidp = XFS_LIC_SLOT(licp, i);
-			kdb_printf("\n");
-			kdb_printf("chunk %d index %d item 0x%p size %d\n",
-				chunk, i, lidp->lid_item, lidp->lid_size);
-			kdb_printf("flags ");
-			printflags(lidp->lid_flags, lid_flags,"lic");
-			kdb_printf("\n");
-			xfsidbg_xlogitem(lidp->lid_item);
-		}
-		chunk++;
-		licp = licp->lic_next;
-	}
-
-	kdb_printf("log busy free %d, list:\n", tp->t_busy_free);
-	lbcp = &tp->t_busy;
-	chunk = 0;
-	while (lbcp != NULL) {
-		kdb_printf("Chunk %d at 0x%p next 0x%p free 0x%08x unused %d\n",
-			chunk, lbcp, lbcp->lbc_next, lbcp->lbc_free,
-			lbcp->lbc_unused);
-		for (i = 0; i < XFS_LBC_NUM_SLOTS; i++) {
-			kdb_printf("  %02d: ag %d idx %d\n",
-				i,
-				lbcp->lbc_busy[i].lbc_ag,
-				lbcp->lbc_busy[i].lbc_idx);
-		}
-		lbcp = lbcp->lbc_next;
-	}
-}
-
-static void
-xfsidbg_xtrans_res(
-	xfs_mount_t	*mp)
-{
-	xfs_trans_reservations_t	*xtrp;
-
-	xtrp = &mp->m_reservations;
-	kdb_printf("write: %d\ttruncate: %d\trename: %d\n",
-		xtrp->tr_write, xtrp->tr_itruncate, xtrp->tr_rename);
-	kdb_printf("link: %d\tremove: %d\tsymlink: %d\n",
-		xtrp->tr_link, xtrp->tr_remove, xtrp->tr_symlink);
-	kdb_printf("create: %d\tmkdir: %d\tifree: %d\n",
-		xtrp->tr_create, xtrp->tr_mkdir, xtrp->tr_ifree);
-	kdb_printf("ichange: %d\tgrowdata: %d\tswrite: %d\n",
-		xtrp->tr_ichange, xtrp->tr_growdata, xtrp->tr_swrite);
-	kdb_printf("addafork: %d\twriteid: %d\tattrinval: %d\n",
-		xtrp->tr_addafork, xtrp->tr_writeid, xtrp->tr_attrinval);
-	kdb_printf("attrset: %d\tattrrm: %d\tclearagi: %d\n",
-		xtrp->tr_attrset, xtrp->tr_attrrm, xtrp->tr_clearagi);
-	kdb_printf("growrtalloc: %d\tgrowrtzero: %d\tgrowrtfree: %d\n",
-		xtrp->tr_growrtalloc, xtrp->tr_growrtzero, xtrp->tr_growrtfree);
-}
-
-module_init(xfsidbg_init)
-module_exit(xfsidbg_exit)
diff -urN linux-2.4.25-pre8/include/asm-sparc64/sections.h linux-2.4.25-rc1/include/asm-sparc64/sections.h
--- linux-2.4.25-pre8/include/asm-sparc64/sections.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/include/asm-sparc64/sections.h	2004-02-05 04:40:38.000000000 -0800
@@ -0,0 +1,12 @@
+/* References to section boundaries */
+
+#ifndef __SPARC64_SECTIONS_H
+#define __SPARC64_SECTIONS_H
+
+extern char __init_begin[], __init_end[];
+
+extern char _start[], _end[];
+
+extern char etext[], edata[];
+
+#endif /* !(__SPARC64_SECTIONS_H) */
diff -urN linux-2.4.25-pre8/include/linux/inetdevice.h linux-2.4.25-rc1/include/linux/inetdevice.h
--- linux-2.4.25-pre8/include/linux/inetdevice.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.25-rc1/include/linux/inetdevice.h	2004-02-05 04:40:38.000000000 -0800
@@ -19,6 +19,7 @@
 	int	tag;
 	int     arp_filter;
 	int	medium_id;
+	int	force_igmp_version;
 	void	*sysctl;
 };
 
diff -urN linux-2.4.25-pre8/include/linux/list.h linux-2.4.25-rc1/include/linux/list.h
--- linux-2.4.25-pre8/include/linux/list.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/include/linux/list.h	2004-02-05 04:40:38.000000000 -0800
@@ -240,6 +240,20 @@
 	     &pos->member != (head); 					\
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
+/**
+ * list_for_each_entry_continue -       iterate over list of given type
+ *                      continuing after existing point
+ * @pos:        the type * to use as a loop counter.
+ * @head:       the head for your list.
+ * @member:     the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_continue(pos, head, member)			\
+	for (pos = list_entry(pos->member.next, typeof(*pos), member),	\
+		     prefetch(pos->member.next);			\
+	     &pos->member != (head);					\
+	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
+		     prefetch(pos->member.next))
+
 #endif /* __KERNEL__ || _LVM_H_INCLUDE */
 
 #endif
diff -urN linux-2.4.25-pre8/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.25-rc1/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.4.25-pre8/include/linux/netfilter_ipv4/ip_conntrack.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.25-rc1/include/linux/netfilter_ipv4/ip_conntrack.h	2004-02-05 04:40:38.000000000 -0800
@@ -237,8 +237,6 @@
 /* decrement reference count on an expectation */
 void ip_conntrack_expect_put(struct ip_conntrack_expect *exp);
 
-extern struct module *ip_conntrack_module;
-
 extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
 			  const struct ip_conntrack_tuple *orig);
 
diff -urN linux-2.4.25-pre8/include/linux/pkt_sched.h linux-2.4.25-rc1/include/linux/pkt_sched.h
--- linux-2.4.25-pre8/include/linux/pkt_sched.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/include/linux/pkt_sched.h	2004-02-05 04:40:38.000000000 -0800
@@ -290,6 +290,37 @@
 	__u32 ctokens;
 };
 
+/* HFSC section */
+
+struct tc_hfsc_qopt
+{
+	__u16	defcls;		/* default class */
+};
+
+struct tc_service_curve
+{
+	__u32	m1;		/* slope of the first segment in bps */
+	__u32	d;		/* x-projection of the first segment in us */
+	__u32	m2;		/* slope of the second segment in bps */
+};
+
+struct tc_hfsc_stats
+{
+	__u64	work;		/* total work done */
+	__u64	rtwork;		/* work done by real-time criteria */
+	__u32	period;		/* current period */
+	__u32	level;		/* class level in hierarchy */
+};
+
+enum
+{
+	TCA_HFSC_UNSPEC,
+	TCA_HFSC_RSC,
+	TCA_HFSC_FSC,
+	TCA_HFSC_USC,
+	TCA_HFSC_MAX = TCA_HFSC_USC
+};
+
 /* CBQ section */
 
 #define TC_CBQ_MAXPRIO		8
diff -urN linux-2.4.25-pre8/include/linux/sysctl.h linux-2.4.25-rc1/include/linux/sysctl.h
--- linux-2.4.25-pre8/include/linux/sysctl.h	2004-02-05 04:40:33.000000000 -0800
+++ linux-2.4.25-rc1/include/linux/sysctl.h	2004-02-05 04:40:38.000000000 -0800
@@ -359,6 +359,7 @@
 	NET_IPV4_CONF_TAG=12,
 	NET_IPV4_CONF_ARPFILTER=13,
 	NET_IPV4_CONF_MEDIUM_ID=14,
+	NET_IPV4_CONF_FORCE_IGMP_VERSION=15,
 };
 
 /* /proc/sys/net/ipv4/netfilter */
diff -urN linux-2.4.25-pre8/include/net/pkt_sched.h linux-2.4.25-rc1/include/net/pkt_sched.h
--- linux-2.4.25-pre8/include/net/pkt_sched.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/include/net/pkt_sched.h	2004-02-05 04:40:38.000000000 -0800
@@ -198,6 +198,7 @@
 
 #define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
 #define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
+#define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ))
 
 #define PSCHED_EXPORTLIST EXPORT_SYMBOL(psched_tod_diff);
 
@@ -246,6 +247,7 @@
 #endif
 
 #define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE)
+#define PSCHED_JIFFIE2US(delay) ((delay)<<PSCHED_JSCALE)
 
 #elif PSCHED_CLOCK_SOURCE == PSCHED_CPU
 
@@ -256,6 +258,7 @@
                             EXPORT_SYMBOL(psched_clock_scale);
 
 #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
+#define PSCHED_JIFFIE2US(delay) ((delay)*psched_clock_per_hz)
 
 #ifdef CONFIG_X86_TSC
 
diff -urN linux-2.4.25-pre8/mm/filemap.c linux-2.4.25-rc1/mm/filemap.c
--- linux-2.4.25-pre8/mm/filemap.c	2004-02-05 04:40:33.000000000 -0800
+++ linux-2.4.25-rc1/mm/filemap.c	2004-02-05 04:40:38.000000000 -0800
@@ -1965,7 +1965,7 @@
 		nr = max;
 
 	/* And limit it to a sane percentage of the inactive list.. */
-	max = nr_inactive_pages / 2;
+	max = (nr_free_pages() + nr_inactive_pages) / 2;
 	if (nr > max)
 		nr = max;
 
diff -urN linux-2.4.25-pre8/net/atm/clip.c linux-2.4.25-rc1/net/atm/clip.c
--- linux-2.4.25-pre8/net/atm/clip.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/net/atm/clip.c	2004-02-05 04:40:38.000000000 -0800
@@ -773,6 +773,9 @@
 	clip_tbl.kmem_cachep = kmem_cache_create(clip_tbl.id,
 	    clip_tbl.entry_size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 
+	if (!clip_tbl.kmem_cachep)
+		return -ENOMEM;
+
 	/* so neigh_ifdown() doesn't complain */
 	clip_tbl.proxy_timer.data = 0;
 	clip_tbl.proxy_timer.function = 0;
diff -urN linux-2.4.25-pre8/net/decnet/dn_neigh.c linux-2.4.25-rc1/net/decnet/dn_neigh.c
--- linux-2.4.25-pre8/net/decnet/dn_neigh.c	2001-01-22 13:32:10.000000000 -0800
+++ linux-2.4.25-rc1/net/decnet/dn_neigh.c	2004-02-05 04:40:38.000000000 -0800
@@ -308,7 +308,7 @@
 	}
 
 	data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
-	((unsigned short *)data) = dn_htons(skb->len - 2);
+	*((unsigned short *)data) = dn_htons(skb->len - 2);
 	sp = (struct dn_short_packet *)(data + 2);
 
 	sp->msgflg   = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
diff -urN linux-2.4.25-pre8/net/ipv4/devinet.c linux-2.4.25-rc1/net/ipv4/devinet.c
--- linux-2.4.25-pre8/net/ipv4/devinet.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/net/ipv4/devinet.c	2004-02-05 04:40:39.000000000 -0800
@@ -1057,7 +1057,7 @@
 static struct devinet_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table devinet_vars[15];
+	ctl_table devinet_vars[16];
 	ctl_table devinet_dev[2];
 	ctl_table devinet_conf_dir[2];
 	ctl_table devinet_proto_dir[2];
@@ -1106,6 +1106,9 @@
 	{NET_IPV4_CONF_ARPFILTER, "arp_filter",
 	 &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
+	{NET_IPV4_CONF_FORCE_IGMP_VERSION, "force_igmp_version",
+	 &ipv4_devconf.force_igmp_version, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
 	 {0}},
 
 	{{NET_PROTO_CONF_ALL, "all", NULL, 0, 0555, devinet_sysctl.devinet_vars},{0}},
diff -urN linux-2.4.25-pre8/net/ipv4/igmp.c linux-2.4.25-rc1/net/ipv4/igmp.c
--- linux-2.4.25-pre8/net/ipv4/igmp.c	2004-02-05 04:40:33.000000000 -0800
+++ linux-2.4.25-rc1/net/ipv4/igmp.c	2004-02-05 04:40:39.000000000 -0800
@@ -122,10 +122,14 @@
  * contradict to specs provided this delay is small enough.
  */
 
-#define IGMP_V1_SEEN(in_dev) ((in_dev)->mr_v1_seen && \
-		time_before(jiffies, (in_dev)->mr_v1_seen))
-#define IGMP_V2_SEEN(in_dev) ((in_dev)->mr_v2_seen && \
-		time_before(jiffies, (in_dev)->mr_v2_seen))
+#define IGMP_V1_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 1 || \
+		(in_dev)->cnf.force_igmp_version == 1 || \
+		((in_dev)->mr_v1_seen && \
+		time_before(jiffies, (in_dev)->mr_v1_seen)))
+#define IGMP_V2_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 2 || \
+		(in_dev)->cnf.force_igmp_version == 2 || \
+		((in_dev)->mr_v2_seen && \
+		time_before(jiffies, (in_dev)->mr_v2_seen)))
 
 static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
 static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr);
@@ -1051,7 +1055,7 @@
 	reporter = im->reporter;
 	igmp_stop_timer(im);
 
-	if (in_dev->dev->flags & IFF_UP) {
+	if (!in_dev->dead) {
 		if (IGMP_V1_SEEN(in_dev))
 			goto done;
 		if (IGMP_V2_SEEN(in_dev)) {
@@ -1082,6 +1086,8 @@
 	if (im->multiaddr == IGMP_ALL_HOSTS)
 		return;
 
+	if (in_dev->dead)
+		return;
 	if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
 		spin_lock_bh(&im->lock);
 		igmp_start_timer(im, IGMP_Initial_Report_Delay);
@@ -1155,7 +1161,7 @@
 	igmpv3_del_delrec(in_dev, im->multiaddr);
 #endif
 	igmp_group_added(im);
-	if (in_dev->dev->flags & IFF_UP)
+	if (!in_dev->dead)
 		ip_rt_multicast_event(in_dev);
 out:
 	return;
@@ -1179,7 +1185,7 @@
 				write_unlock_bh(&in_dev->lock);
 				igmp_group_dropped(i);
 
-				if (in_dev->dev->flags & IFF_UP)
+				if (!in_dev->dead)
 					ip_rt_multicast_event(in_dev);
 
 				ip_ma_put(i);
@@ -1255,6 +1261,9 @@
 
 	ASSERT_RTNL();
 
+	/* Deactivate timers */
+	ip_mc_down(in_dev);
+
 	write_lock_bh(&in_dev->lock);
 	while ((i = in_dev->mc_list) != NULL) {
 		in_dev->mc_list = i->next;
diff -urN linux-2.4.25-pre8/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.25-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.4.25-pre8/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-02-05 04:40:33.000000000 -0800
+++ linux-2.4.25-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-02-05 04:40:39.000000000 -0800
@@ -37,7 +37,6 @@
 #define DEBUGP(format, args...)
 #endif
 
-struct module *ip_conntrack_module = THIS_MODULE;
 MODULE_LICENSE("GPL");
 
 static int kill_proto(const struct ip_conntrack *i, void *data)
@@ -465,7 +464,6 @@
 EXPORT_SYMBOL(ip_conntrack_alter_reply);
 EXPORT_SYMBOL(ip_conntrack_destroyed);
 EXPORT_SYMBOL(ip_conntrack_get);
-EXPORT_SYMBOL(ip_conntrack_module);
 EXPORT_SYMBOL(ip_conntrack_helper_register);
 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
 EXPORT_SYMBOL(ip_ct_selective_cleanup);
diff -urN linux-2.4.25-pre8/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.25-rc1/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.4.25-pre8/net/ipv4/netfilter/ip_nat_standalone.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.25-rc1/net/ipv4/netfilter/ip_nat_standalone.c	2004-02-05 04:40:39.000000000 -0800
@@ -309,13 +309,9 @@
 		goto cleanup_localoutops;
 	}
 #endif
-	if (ip_conntrack_module)
-		__MOD_INC_USE_COUNT(ip_conntrack_module);
 	return ret;
 
  cleanup:
-	if (ip_conntrack_module)
-		__MOD_DEC_USE_COUNT(ip_conntrack_module);
 #ifdef CONFIG_IP_NF_NAT_LOCAL
 	nf_unregister_hook(&ip_nat_local_in_ops);
  cleanup_localoutops:
diff -urN linux-2.4.25-pre8/net/ipv4/netfilter/ipt_conntrack.c linux-2.4.25-rc1/net/ipv4/netfilter/ipt_conntrack.c
--- linux-2.4.25-pre8/net/ipv4/netfilter/ipt_conntrack.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.25-rc1/net/ipv4/netfilter/ipt_conntrack.c	2004-02-05 04:40:39.000000000 -0800
@@ -109,17 +109,12 @@
 
 static int __init init(void)
 {
-	/* NULL if ip_conntrack not a module */
-	if (ip_conntrack_module)
-		__MOD_INC_USE_COUNT(ip_conntrack_module);
 	return ipt_register_match(&conntrack_match);
 }
 
 static void __exit fini(void)
 {
 	ipt_unregister_match(&conntrack_match);
-	if (ip_conntrack_module)
-		__MOD_DEC_USE_COUNT(ip_conntrack_module);
 }
 
 module_init(init);
diff -urN linux-2.4.25-pre8/net/ipv4/netfilter/ipt_helper.c linux-2.4.25-rc1/net/ipv4/netfilter/ipt_helper.c
--- linux-2.4.25-pre8/net/ipv4/netfilter/ipt_helper.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.25-rc1/net/ipv4/netfilter/ipt_helper.c	2004-02-05 04:40:39.000000000 -0800
@@ -100,17 +100,12 @@
 
 static int __init init(void)
 {
-	/* NULL if ip_conntrack not a module */
-	if (ip_conntrack_module)
-		__MOD_INC_USE_COUNT(ip_conntrack_module);
 	return ipt_register_match(&helper_match);
 }
 
 static void __exit fini(void)
 {
 	ipt_unregister_match(&helper_match);
-	if (ip_conntrack_module)
-		__MOD_DEC_USE_COUNT(ip_conntrack_module);
 }
 
 module_init(init);
diff -urN linux-2.4.25-pre8/net/ipv4/netfilter/ipt_limit.c linux-2.4.25-rc1/net/ipv4/netfilter/ipt_limit.c
--- linux-2.4.25-pre8/net/ipv4/netfilter/ipt_limit.c	2001-09-30 12:26:08.000000000 -0700
+++ linux-2.4.25-rc1/net/ipv4/netfilter/ipt_limit.c	2004-02-05 04:40:39.000000000 -0800
@@ -34,12 +34,23 @@
 
    See Alexey's formal explanation in net/sched/sch_tbf.c.
 
-   To avoid underflow, we multiply by 128 (ie. you get 128 credits per
-   jiffy).  Hence a cost of 2^32-1, means one pass per 32768 seconds
-   at 1024HZ (or one every 9 hours).  A cost of 1 means 12800 passes
-   per second at 100HZ.  */
+   To get the maxmum range, we multiply by this factor (ie. you get N
+   credits per jiffy).  We want to allow a rate as low as 1 per day
+   (slowest userspace tool allows), which means
+   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32. ie. */
+#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
+
+/* Repeated shift and or gives us all 1s, final shift and add 1 gives
+ * us the power of 2 below the theoretical max, so GCC simply does a
+ * shift. */
+#define _POW2_BELOW2(x) ((x)|((x)>>1))
+#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
+#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
+#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
+#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
+#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
 
-#define CREDITS_PER_JIFFY 128
+#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
 
 static int
 ipt_limit_match(const struct sk_buff *skb,
@@ -97,7 +108,7 @@
 	/* Check for overflow. */
 	if (r->burst == 0
 	    || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
-		printk("Call rusty: overflow in ipt_limit: %u/%u\n",
+		printk("Overflow in ipt_limit, try lower: %u/%u\n",
 		       r->avg, r->burst);
 		return 0;
 	}
diff -urN linux-2.4.25-pre8/net/ipv4/netfilter/ipt_state.c linux-2.4.25-rc1/net/ipv4/netfilter/ipt_state.c
--- linux-2.4.25-pre8/net/ipv4/netfilter/ipt_state.c	2001-09-30 12:26:08.000000000 -0700
+++ linux-2.4.25-rc1/net/ipv4/netfilter/ipt_state.c	2004-02-05 04:40:39.000000000 -0800
@@ -46,17 +46,12 @@
 
 static int __init init(void)
 {
-	/* NULL if ip_conntrack not a module */
-	if (ip_conntrack_module)
-		__MOD_INC_USE_COUNT(ip_conntrack_module);
 	return ipt_register_match(&state_match);
 }
 
 static void __exit fini(void)
 {
 	ipt_unregister_match(&state_match);
-	if (ip_conntrack_module)
-		__MOD_DEC_USE_COUNT(ip_conntrack_module);
 }
 
 module_init(init);
diff -urN linux-2.4.25-pre8/net/sched/Config.in linux-2.4.25-rc1/net/sched/Config.in
--- linux-2.4.25-pre8/net/sched/Config.in	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.25-rc1/net/sched/Config.in	2004-02-05 04:40:39.000000000 -0800
@@ -5,7 +5,7 @@
 tristate '  HTB packet scheduler' CONFIG_NET_SCH_HTB
 tristate '  CSZ packet scheduler' CONFIG_NET_SCH_CSZ
 #tristate '  H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
-#tristate '  H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
+tristate '  H-FSC packet scheduler' CONFIG_NET_SCH_HFSC
 if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then
    dep_tristate '  ATM pseudo-scheduler' CONFIG_NET_SCH_ATM $CONFIG_ATM
 fi
diff -urN linux-2.4.25-pre8/net/sched/sch_hfsc.c linux-2.4.25-rc1/net/sched/sch_hfsc.c
--- linux-2.4.25-pre8/net/sched/sch_hfsc.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.25-rc1/net/sched/sch_hfsc.c	2004-02-05 04:40:39.000000000 -0800
@@ -0,0 +1,1864 @@
+/*
+ * Copyright (c) 2003 Patrick McHardy, <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 2003-10-17 - Ported from altq
+ */
+/*
+ * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation is hereby granted (including for commercial or
+ * for-profit use), provided that both the copyright notice and this
+ * permission notice appear in all copies of the software, derivative
+ * works, or modified versions, and any portions thereof.
+ *
+ * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF
+ * WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON PROVIDES THIS
+ * SOFTWARE IN ITS ``AS IS'' CONDITION, AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Carnegie Mellon encourages (but does not require) users of this
+ * software to return any improvements or extensions that they make,
+ * and to grant Carnegie Mellon the rights to redistribute these
+ * changes without encumbrance.
+ */
+/*
+ * H-FSC is described in Proceedings of SIGCOMM'97,
+ * "A Hierarchical Fair Service Curve Algorithm for Link-Sharing,
+ * Real-Time and Priority Service"
+ * by Ion Stoica, Hui Zhang, and T. S. Eugene Ng.
+ *
+ * Oleg Cherevko <olwi@aq.ml.com.ua> added the upperlimit for link-sharing.
+ * when a class has an upperlimit, the fit-time is computed from the
+ * upperlimit service curve.  the link-sharing scheduler does not schedule
+ * a class whose fit-time exceeds the current time.
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/pkt_sched.h>
+#include <net/pkt_sched.h>
+#include <net/pkt_cls.h>
+#include <asm/system.h>
+#include <asm/div64.h>
+
+#define HFSC_DEBUG 1
+
+/*
+ * kernel internal service curve representation:
+ *   coordinates are given by 64 bit unsigned integers.
+ *   x-axis: unit is clock count.
+ *   y-axis: unit is byte.
+ *
+ *   The service curve parameters are converted to the internal
+ *   representation. The slope values are scaled to avoid overflow.
+ *   the inverse slope values as well as the y-projection of the 1st
+ *   segment are kept in order to to avoid 64-bit divide operations
+ *   that are expensive on 32-bit architectures.
+ */
+
+struct internal_sc
+{
+	u64	sm1;	/* scaled slope of the 1st segment */
+	u64	ism1;	/* scaled inverse-slope of the 1st segment */
+	u64	dx;	/* the x-projection of the 1st segment */
+	u64	dy;	/* the y-projection of the 1st segment */
+	u64	sm2;	/* scaled slope of the 2nd segment */
+	u64	ism2;	/* scaled inverse-slope of the 2nd segment */
+};
+
+/* runtime service curve */
+struct runtime_sc
+{
+	u64	x;	/* current starting position on x-axis */
+	u64	y;	/* current starting position on y-axis */
+	u64	sm1;	/* scaled slope of the 1st segment */
+	u64	ism1;	/* scaled inverse-slope of the 1st segment */
+	u64	dx;	/* the x-projection of the 1st segment */
+	u64	dy;	/* the y-projection of the 1st segment */
+	u64	sm2;	/* scaled slope of the 2nd segment */
+	u64	ism2;	/* scaled inverse-slope of the 2nd segment */
+};
+
+enum hfsc_class_flags
+{
+	HFSC_RSC = 0x1,
+	HFSC_FSC = 0x2,
+	HFSC_USC = 0x4
+};
+
+struct hfsc_class
+{
+	u32	classid;	/* class id */
+	unsigned int	refcnt;		/* usage count */
+
+	struct tc_stats	stats;		/* generic statistics */
+	unsigned int	level;		/* class level in hierarchy */
+	struct tcf_proto *filter_list;	/* filter list */
+	unsigned int	filter_cnt;	/* filter count */
+
+	struct hfsc_sched *sched;	/* scheduler data */
+	struct hfsc_class *cl_parent;	/* parent class */
+	struct list_head siblings;	/* sibling classes */
+	struct list_head children;	/* child classes */
+	struct Qdisc	*qdisc;		/* leaf qdisc */
+
+	struct list_head actlist;	/* active children list */
+	struct list_head alist;		/* active children list member */
+	struct list_head ellist;	/* eligible list member */
+	struct list_head hlist;		/* hash list member */
+	struct list_head dlist;		/* drop list member */
+
+	u64	cl_total;	/* total work in bytes */
+	u64	cl_cumul;	/* cumulative work in bytes done by
+					   real-time criteria */
+
+	u64 	cl_d;		/* deadline*/
+	u64 	cl_e;		/* eligible time */
+	u64	cl_vt;		/* virtual time */
+	u64	cl_f;		/* time when this class will fit for
+					   link-sharing, max(myf, cfmin) */
+	u64	cl_myf;		/* my fit-time (calculated from this
+					   class's own upperlimit curve) */
+	u64	cl_myfadj;	/* my fit-time adjustment (to cancel
+					   history dependence) */
+	u64	cl_cfmin;	/* earliest children's fit-time (used
+					   with cl_myf to obtain cl_f) */
+	u64	cl_cvtmin;	/* minimal virtual time among the
+					   children fit for link-sharing
+					   (monotonic within a period) */
+	u64	cl_vtadj;	/* intra-period cumulative vt
+					   adjustment */
+	u64	cl_vtoff;	/* inter-period cumulative vt offset */
+	u64	cl_cvtmax;	/* max child's vt in the last period */
+
+	struct internal_sc cl_rsc;	/* internal real-time service curve */
+	struct internal_sc cl_fsc;	/* internal fair service curve */
+	struct internal_sc cl_usc;	/* internal upperlimit service curve */
+	struct runtime_sc cl_deadline;	/* deadline curve */
+	struct runtime_sc cl_eligible;	/* eligible curve */
+	struct runtime_sc cl_virtual;	/* virtual curve */
+	struct runtime_sc cl_ulimit;	/* upperlimit curve */
+
+	unsigned long	cl_flags;	/* which curves are valid */
+	unsigned long	cl_vtperiod;	/* vt period sequence number */
+	unsigned long	cl_parentperiod;/* parent's vt period sequence number*/
+	unsigned long	cl_nactive;	/* number of active children */
+};
+
+#define HFSC_HSIZE	16
+
+struct hfsc_sched
+{
+	u16	defcls;			/* default class id */
+
+	struct hfsc_class root;			/* root class */
+	struct hfsc_class *last_xmit;		/* class that transmitted last
+						   packet (for requeueing) */
+	struct list_head clhash[HFSC_HSIZE];	/* class hash */
+	struct list_head eligible;		/* eligible list */
+	struct list_head droplist;		/* active leaf class list (for
+						   dropping) */
+	struct timer_list wd_timer;		/* watchdog timer */
+};
+
+/*
+ * macros
+ */
+#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
+#include <linux/time.h>
+#undef PSCHED_GET_TIME
+#define PSCHED_GET_TIME(stamp)						\
+do {									\
+	struct timeval tv;						\
+	do_gettimeofday(&tv);						\
+	(stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec;			\
+} while (0)
+#endif
+
+#if HFSC_DEBUG
+#define ASSERT(cond)							\
+do {									\
+	if (unlikely(!(cond)))						\
+		printk("assertion %s failed at %s:%i (%s)\n",		\
+		       #cond, __FILE__, __LINE__, __FUNCTION__);	\
+} while (0)
+#else
+#define ASSERT(cond)
+#endif /* HFSC_DEBUG */
+
+#define	HT_INFINITY	0xffffffffffffffffULL	/* infinite time value */
+
+
+/*
+ * eligible list holds backlogged classes being sorted by their eligible times.
+ * there is one eligible list per hfsc instance.
+ */
+
+static void
+ellist_insert(struct hfsc_class *cl)
+{
+	struct list_head *head = &cl->sched->eligible;
+	struct hfsc_class *p;
+
+	/* check the last entry first */
+	if (list_empty(head) ||
+	    ((p = list_entry(head->prev, struct hfsc_class, ellist)) &&
+	     p->cl_e <= cl->cl_e)) {
+		list_add_tail(&cl->ellist, head);
+		return;
+	}
+
+	list_for_each_entry(p, head, ellist) {
+		if (cl->cl_e < p->cl_e) {
+			/* insert cl before p */
+			list_add_tail(&cl->ellist, &p->ellist);
+			return;
+		}
+	}
+	ASSERT(0); /* should not reach here */
+}
+
+static inline void
+ellist_remove(struct hfsc_class *cl)
+{
+	list_del(&cl->ellist);
+}
+
+static void
+ellist_update(struct hfsc_class *cl)
+{
+	struct list_head *head = &cl->sched->eligible;
+	struct hfsc_class *p, *last;
+
+	/*
+	 * the eligible time of a class increases monotonically.
+	 * if the next entry has a larger eligible time, nothing to do.
+	 */
+	if (cl->ellist.next == head ||
+	    ((p = list_entry(cl->ellist.next, struct hfsc_class, ellist)) &&
+	     cl->cl_e <= p->cl_e))
+		return;
+
+	/* check the last entry */
+	last = list_entry(head->prev, struct hfsc_class, ellist);
+	if (last->cl_e <= cl->cl_e) {
+		list_move_tail(&cl->ellist, head);
+		return;
+	}
+
+	/*
+	 * the new position must be between the next entry
+	 * and the last entry
+	 */
+	list_for_each_entry_continue(p, head, ellist) {
+		if (cl->cl_e < p->cl_e) {
+			list_move_tail(&cl->ellist, &p->ellist);
+			return;
+		}
+	}
+	ASSERT(0); /* should not reach here */
+}
+
+/* find the class with the minimum deadline among the eligible classes */
+static inline struct hfsc_class *
+ellist_get_mindl(struct list_head *head, u64 cur_time)
+{
+	struct hfsc_class *p, *cl = NULL;
+
+	list_for_each_entry(p, head, ellist) {
+		if (p->cl_e > cur_time)
+			break;
+		if (cl == NULL || p->cl_d < cl->cl_d)
+			cl = p;
+	}
+	return cl;
+}
+
+/* find the class with minimum eligible time among the eligible classes */
+static inline struct hfsc_class *
+ellist_get_minel(struct list_head *head)
+{
+	if (list_empty(head))
+		return NULL;
+	return list_entry(head->next, struct hfsc_class, ellist);
+}
+
+/*
+ * active children list holds backlogged child classes being sorted
+ * by their virtual time. each intermediate class has one active
+ * children list.
+ */
+static void
+actlist_insert(struct hfsc_class *cl)
+{
+	struct list_head *head = &cl->cl_parent->actlist;
+	struct hfsc_class *p;
+
+	/* check the last entry first */
+	if (list_empty(head) ||
+	    ((p = list_entry(head->prev, struct hfsc_class, alist)) &&
+	     p->cl_vt <= cl->cl_vt)) {
+		list_add_tail(&cl->alist, head);
+		return;
+	}
+
+	list_for_each_entry(p, head, alist) {
+		if (cl->cl_vt < p->cl_vt) {
+			/* insert cl before p */
+			list_add_tail(&cl->alist, &p->alist);
+			return;
+		}
+	}
+	ASSERT(0); /* should not reach here */
+}
+
+static inline void
+actlist_remove(struct hfsc_class *cl)
+{
+	list_del(&cl->alist);
+}
+
+static void
+actlist_update(struct hfsc_class *cl)
+{
+	struct list_head *head = &cl->cl_parent->actlist;
+	struct hfsc_class *p, *last;
+
+	/*
+	 * the virtual time of a class increases monotonically.
+	 * if the next entry has a larger virtual time, nothing to do.
+	 */
+	if (cl->alist.next == head ||
+	    ((p = list_entry(cl->alist.next, struct hfsc_class, alist)) &&
+	     cl->cl_vt <= p->cl_vt))
+		return;
+
+	/* check the last entry */
+	last = list_entry(head->prev, struct hfsc_class, alist);
+	if (last->cl_vt <= cl->cl_vt) {
+		list_move_tail(&cl->alist, head);
+		return;
+	}
+
+	/*
+	 * the new position must be between the next entry
+	 * and the last entry
+	 */
+	list_for_each_entry_continue(p, head, alist) {
+		if (cl->cl_vt < p->cl_vt) {
+			list_move_tail(&cl->alist, &p->alist);
+			return;
+		}
+	}
+	ASSERT(0); /* should not reach here */
+}
+
+static inline struct hfsc_class *
+actlist_firstfit(struct hfsc_class *cl, u64 cur_time)
+{
+	struct hfsc_class *p;
+
+	list_for_each_entry(p, &cl->actlist, alist) {
+		if (p->cl_f <= cur_time) {
+			return p;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * get the leaf class with the minimum vt in the hierarchy
+ */
+static struct hfsc_class *
+actlist_get_minvt(struct hfsc_class *cl, u64 cur_time)
+{
+	/* if root-class's cfmin is bigger than cur_time nothing to do */
+	if (cl->cl_cfmin > cur_time)
+		return NULL;
+
+	while (cl->level > 0) {
+		cl = actlist_firstfit(cl, cur_time);
+		if (cl == NULL)
+			return NULL;
+		/*
+		 * update parent's cl_cvtmin.
+		 */
+		if (cl->cl_parent->cl_cvtmin < cl->cl_vt)
+			cl->cl_parent->cl_cvtmin = cl->cl_vt;
+	}
+	return cl;
+}
+
+/*
+ * service curve support functions
+ *
+ *  external service curve parameters
+ *	m: bps
+ *	d: us
+ *  internal service curve parameters
+ *	sm: (bytes/psched_us) << SM_SHIFT
+ *	ism: (psched_us/byte) << ISM_SHIFT
+ *	dx: psched_us
+ *
+ * Time source resolution
+ *  PSCHED_JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us.
+ *  PSCHED_CPU: resolution is between 0.5us and 1us.
+ *  PSCHED_GETTIMEOFDAY: resolution is exactly 1us.
+ *
+ * sm and ism are scaled in order to keep effective digits.
+ * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective
+ * digits in decimal using the following table.
+ *
+ * Note: We can afford the additional accuracy (altq hfsc keeps at most
+ * 3 effective digits) thanks to the fact that linux clock is bounded
+ * much more tightly.
+ *
+ *  bits/sec      100Kbps     1Mbps     10Mbps     100Mbps    1Gbps
+ *  ------------+-------------------------------------------------------
+ *  bytes/0.5us   6.25e-3    62.5e-3    625e-3     6250e-e    62500e-3
+ *  bytes/us      12.5e-3    125e-3     1250e-3    12500e-3   125000e-3
+ *  bytes/1.27us  15.875e-3  158.75e-3  1587.5e-3  15875e-3   158750e-3
+ *
+ *  0.5us/byte    160        16         1.6        0.16       0.016
+ *  us/byte       80         8          0.8        0.08       0.008
+ *  1.27us/byte   63         6.3        0.63       0.063      0.0063
+ */
+#define	SM_SHIFT	20
+#define	ISM_SHIFT	18
+
+#define	SM_MASK		((1ULL << SM_SHIFT) - 1)
+#define	ISM_MASK	((1ULL << ISM_SHIFT) - 1)
+
+static inline u64
+seg_x2y(u64 x, u64 sm)
+{
+	u64 y;
+
+	/*
+	 * compute
+	 *	y = x * sm >> SM_SHIFT
+	 * but divide it for the upper and lower bits to avoid overflow
+	 */
+	y = (x >> SM_SHIFT) * sm + (((x & SM_MASK) * sm) >> SM_SHIFT);
+	return y;
+}
+
+static inline u64
+seg_y2x(u64 y, u64 ism)
+{
+	u64 x;
+
+	if (y == 0)
+		x = 0;
+	else if (ism == HT_INFINITY)
+		x = HT_INFINITY;
+	else {
+		x = (y >> ISM_SHIFT) * ism
+		    + (((y & ISM_MASK) * ism) >> ISM_SHIFT);
+	}
+	return x;
+}
+
+/* Convert m (bps) into sm (bytes/psched us) */
+static u64
+m2sm(u32 m)
+{
+	u64 sm;
+
+	sm = ((u64)m << SM_SHIFT);
+	sm += PSCHED_JIFFIE2US(HZ) - 1;
+	do_div(sm, PSCHED_JIFFIE2US(HZ));
+	return sm;
+}
+
+/* convert m (bps) into ism (psched us/byte) */
+static u64
+m2ism(u32 m)
+{
+	u64 ism;
+
+	if (m == 0)
+		ism = HT_INFINITY;
+	else {
+		ism = ((u64)PSCHED_JIFFIE2US(HZ) << ISM_SHIFT);
+		ism += m - 1;
+		do_div(ism, m);
+	}
+	return ism;
+}
+
+/* convert d (us) into dx (psched us) */
+static u64
+d2dx(u32 d)
+{
+	u64 dx;
+
+	dx = ((u64)d * PSCHED_JIFFIE2US(HZ));
+	dx += 1000000 - 1;
+	do_div(dx, 1000000);
+	return dx;
+}
+
+/* convert sm (bytes/psched us) into m (bps) */
+static u32
+sm2m(u64 sm)
+{
+	u64 m;
+
+	m = (sm * PSCHED_JIFFIE2US(HZ)) >> SM_SHIFT;
+	return (u32)m;
+}
+
+/* convert dx (psched us) into d (us) */
+static u32
+dx2d(u64 dx)
+{
+	u64 d;
+
+	d = dx * 1000000;
+	do_div(d, PSCHED_JIFFIE2US(HZ));
+	return (u32)d;
+}
+
+static void
+sc2isc(struct tc_service_curve *sc, struct internal_sc *isc)
+{
+	isc->sm1  = m2sm(sc->m1);
+	isc->ism1 = m2ism(sc->m1);
+	isc->dx   = d2dx(sc->d);
+	isc->dy   = seg_x2y(isc->dx, isc->sm1);
+	isc->sm2  = m2sm(sc->m2);
+	isc->ism2 = m2ism(sc->m2);
+}
+
+/*
+ * initialize the runtime service curve with the given internal
+ * service curve starting at (x, y).
+ */
+static void
+rtsc_init(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x,
+                                                            u64 y)
+{
+	rtsc->x	   = x;
+	rtsc->y    = y;
+	rtsc->sm1  = isc->sm1;
+	rtsc->ism1 = isc->ism1;
+	rtsc->dx   = isc->dx;
+	rtsc->dy   = isc->dy;
+	rtsc->sm2  = isc->sm2;
+	rtsc->ism2 = isc->ism2;
+}
+
+/*
+ * calculate the y-projection of the runtime service curve by the
+ * given x-projection value
+ */
+static u64
+rtsc_y2x(struct runtime_sc *rtsc, u64 y)
+{
+	u64 x;
+
+	if (y < rtsc->y)
+		x = rtsc->x;
+	else if (y <= rtsc->y + rtsc->dy) {
+		/* x belongs to the 1st segment */
+		if (rtsc->dy == 0)
+			x = rtsc->x + rtsc->dx;
+		else
+			x = rtsc->x + seg_y2x(y - rtsc->y, rtsc->ism1);
+	} else {
+		/* x belongs to the 2nd segment */
+		x = rtsc->x + rtsc->dx
+		    + seg_y2x(y - rtsc->y - rtsc->dy, rtsc->ism2);
+	}
+	return x;
+}
+
+static u64
+rtsc_x2y(struct runtime_sc *rtsc, u64 x)
+{
+	u64 y;
+
+	if (x <= rtsc->x)
+		y = rtsc->y;
+	else if (x <= rtsc->x + rtsc->dx)
+		/* y belongs to the 1st segment */
+		y = rtsc->y + seg_x2y(x - rtsc->x, rtsc->sm1);
+	else
+		/* y belongs to the 2nd segment */
+		y = rtsc->y + rtsc->dy
+		    + seg_x2y(x - rtsc->x - rtsc->dx, rtsc->sm2);
+	return y;
+}
+
+/*
+ * update the runtime service curve by taking the minimum of the current
+ * runtime service curve and the service curve starting at (x, y).
+ */
+static void
+rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x,
+                                                           u64 y)
+{
+	u64 y1, y2, dx, dy;
+	u32 dsm;
+
+	if (isc->sm1 <= isc->sm2) {
+		/* service curve is convex */
+		y1 = rtsc_x2y(rtsc, x);
+		if (y1 < y)
+			/* the current rtsc is smaller */
+			return;
+		rtsc->x = x;
+		rtsc->y = y;
+		return;
+	}
+
+	/*
+	 * service curve is concave
+	 * compute the two y values of the current rtsc
+	 *	y1: at x
+	 *	y2: at (x + dx)
+	 */
+	y1 = rtsc_x2y(rtsc, x);
+	if (y1 <= y) {
+		/* rtsc is below isc, no change to rtsc */
+		return;
+	}
+
+	y2 = rtsc_x2y(rtsc, x + isc->dx);
+	if (y2 >= y + isc->dy) {
+		/* rtsc is above isc, replace rtsc by isc */
+		rtsc->x = x;
+		rtsc->y = y;
+		rtsc->dx = isc->dx;
+		rtsc->dy = isc->dy;
+		return;
+	}
+
+	/*
+	 * the two curves intersect
+	 * compute the offsets (dx, dy) using the reverse
+	 * function of seg_x2y()
+	 *	seg_x2y(dx, sm1) == seg_x2y(dx, sm2) + (y1 - y)
+	 */
+	dx = (y1 - y) << SM_SHIFT;
+	dsm = isc->sm1 - isc->sm2;
+	do_div(dx, dsm);
+	/*
+	 * check if (x, y1) belongs to the 1st segment of rtsc.
+	 * if so, add the offset.
+	 */
+	if (rtsc->x + rtsc->dx > x)
+		dx += rtsc->x + rtsc->dx - x;
+	dy = seg_x2y(dx, isc->sm1);
+
+	rtsc->x = x;
+	rtsc->y = y;
+	rtsc->dx = dx;
+	rtsc->dy = dy;
+	return;
+}
+
+static void
+init_ed(struct hfsc_class *cl, unsigned int next_len)
+{
+	u64 cur_time;
+
+	PSCHED_GET_TIME(cur_time);
+
+	/* update the deadline curve */
+	rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
+
+	/*
+	 * update the eligible curve.
+	 * for concave, it is equal to the deadline curve.
+	 * for convex, it is a linear curve with slope m2.
+	 */
+	cl->cl_eligible = cl->cl_deadline;
+	if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) {
+		cl->cl_eligible.dx = 0;
+		cl->cl_eligible.dy = 0;
+	}
+
+	/* compute e and d */
+	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
+	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+
+	ellist_insert(cl);
+}
+
+static void
+update_ed(struct hfsc_class *cl, unsigned int next_len)
+{
+	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
+	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+
+	ellist_update(cl);
+}
+
+static inline void
+update_d(struct hfsc_class *cl, unsigned int next_len)
+{
+	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+}
+
+static void
+update_cfmin(struct hfsc_class *cl)
+{
+	struct hfsc_class *p;
+	u64 cfmin;
+
+	if (list_empty(&cl->actlist)) {
+		cl->cl_cfmin = 0;
+		return;
+	}
+	cfmin = HT_INFINITY;
+	list_for_each_entry(p, &cl->actlist, alist) {
+		if (p->cl_f == 0) {
+			cl->cl_cfmin = 0;
+			return;
+		}
+		if (p->cl_f < cfmin)
+			cfmin = p->cl_f;
+	}
+	cl->cl_cfmin = cfmin;
+}
+
+static void
+init_vf(struct hfsc_class *cl, unsigned int len)
+{
+	struct hfsc_class *max_cl, *p;
+	u64 vt, f, cur_time;
+	int go_active;
+
+	cur_time = 0;
+	go_active = 1;
+	for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
+		if (go_active && cl->cl_nactive++ == 0)
+			go_active = 1;
+		else
+			go_active = 0;
+
+		if (go_active) {
+			if (!list_empty(&cl->cl_parent->actlist)) {
+				max_cl = list_entry(cl->cl_parent->actlist.prev,
+				                    struct hfsc_class, alist);
+				/*
+				 * set vt to the average of the min and max
+				 * classes.  if the parent's period didn't
+				 * change, don't decrease vt of the class.
+				 */
+				vt = max_cl->cl_vt;
+				if (cl->cl_parent->cl_cvtmin != 0)
+					vt = (cl->cl_parent->cl_cvtmin + vt)/2;
+
+				if (cl->cl_parent->cl_vtperiod !=
+				    cl->cl_parentperiod || vt > cl->cl_vt)
+					cl->cl_vt = vt;
+			} else {
+				/*
+				 * first child for a new parent backlog period.
+				 * add parent's cvtmax to vtoff of children
+				 * to make a new vt (vtoff + vt) larger than
+				 * the vt in the last period for all children.
+				 */
+				vt = cl->cl_parent->cl_cvtmax;
+				list_for_each_entry(p, &cl->cl_parent->children,
+				                                       siblings)
+					p->cl_vtoff += vt;
+				cl->cl_vt = 0;
+				cl->cl_parent->cl_cvtmax = 0;
+				cl->cl_parent->cl_cvtmin = 0;
+			}
+
+			/* update the virtual curve */
+			vt = cl->cl_vt + cl->cl_vtoff;
+			rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
+			                              cl->cl_total);
+			if (cl->cl_virtual.x == vt) {
+				cl->cl_virtual.x -= cl->cl_vtoff;
+				cl->cl_vtoff = 0;
+			}
+			cl->cl_vtadj = 0;
+
+			cl->cl_vtperiod++;  /* increment vt period */
+			cl->cl_parentperiod = cl->cl_parent->cl_vtperiod;
+			if (cl->cl_parent->cl_nactive == 0)
+				cl->cl_parentperiod++;
+			cl->cl_f = 0;
+
+			actlist_insert(cl);
+
+			if (cl->cl_flags & HFSC_USC) {
+				/* class has upper limit curve */
+				if (cur_time == 0)
+					PSCHED_GET_TIME(cur_time);
+
+				/* update the ulimit curve */
+				rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time,
+				         cl->cl_total);
+				/* compute myf */
+				cl->cl_myf = rtsc_y2x(&cl->cl_ulimit,
+				                      cl->cl_total);
+				cl->cl_myfadj = 0;
+			}
+		}
+
+		f = max(cl->cl_myf, cl->cl_cfmin);
+		if (f != cl->cl_f) {
+			cl->cl_f = f;
+			update_cfmin(cl->cl_parent);
+		}
+	}
+}
+
+static void
+update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
+{
+	u64 f; /* , myf_bound, delta; */
+	int go_passive = 0;
+
+	if (cl->qdisc->q.qlen == 0 && cl->cl_flags & HFSC_FSC)
+		go_passive = 1;
+
+	for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
+		cl->cl_total += len;
+
+		if (!(cl->cl_flags & HFSC_FSC) || cl->cl_nactive == 0)
+			continue;
+
+		if (go_passive && --cl->cl_nactive == 0)
+			go_passive = 1;
+		else
+			go_passive = 0;
+
+		if (go_passive) {
+			/* no more active child, going passive */
+
+			/* update cvtmax of the parent class */
+			if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
+				cl->cl_parent->cl_cvtmax = cl->cl_vt;
+
+			/* remove this class from the vt list */
+			actlist_remove(cl);
+
+			update_cfmin(cl->cl_parent);
+
+			continue;
+		}
+
+		/*
+		 * update vt and f
+		 */
+		cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total)
+		            - cl->cl_vtoff + cl->cl_vtadj;
+
+		/*
+		 * if vt of the class is smaller than cvtmin,
+		 * the class was skipped in the past due to non-fit.
+		 * if so, we need to adjust vtadj.
+		 */
+		if (cl->cl_vt < cl->cl_parent->cl_cvtmin) {
+			cl->cl_vtadj += cl->cl_parent->cl_cvtmin - cl->cl_vt;
+			cl->cl_vt = cl->cl_parent->cl_cvtmin;
+		}
+
+		/* update the vt list */
+		actlist_update(cl);
+
+		if (cl->cl_flags & HFSC_USC) {
+			cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
+			                                      cl->cl_total);
+#if 0
+			/*
+			 * This code causes classes to stay way under their
+			 * limit when multiple classes are used at gigabit
+			 * speed. needs investigation. -kaber
+			 */
+			/*
+			 * if myf lags behind by more than one clock tick
+			 * from the current time, adjust myfadj to prevent
+			 * a rate-limited class from going greedy.
+			 * in a steady state under rate-limiting, myf
+			 * fluctuates within one clock tick.
+			 */
+			myf_bound = cur_time - PSCHED_JIFFIE2US(1);
+			if (cl->cl_myf < myf_bound) {
+				delta = cur_time - cl->cl_myf;
+				cl->cl_myfadj += delta;
+				cl->cl_myf += delta;
+			}
+#endif
+		}
+
+		f = max(cl->cl_myf, cl->cl_cfmin);
+		if (f != cl->cl_f) {
+			cl->cl_f = f;
+			update_cfmin(cl->cl_parent);
+		}
+	}
+}
+
+static void
+set_active(struct hfsc_class *cl, unsigned int len)
+{
+	if (cl->cl_flags & HFSC_RSC)
+		init_ed(cl, len);
+	if (cl->cl_flags & HFSC_FSC)
+		init_vf(cl, len);
+
+	list_add_tail(&cl->dlist, &cl->sched->droplist);
+}
+
+static void
+set_passive(struct hfsc_class *cl)
+{
+	if (cl->cl_flags & HFSC_RSC)
+		ellist_remove(cl);
+
+	list_del(&cl->dlist);
+
+	/*
+	 * actlist is now handled in update_vf() so that update_vf(cl, 0, 0)
+	 * needs to be called explicitly to remove a class from actlist
+	 */
+}
+
+/*
+ * hack to get length of first packet in queue.
+ */
+static unsigned int
+qdisc_peek_len(struct Qdisc *sch)
+{
+	struct sk_buff *skb;
+	unsigned int len;
+
+	skb = sch->dequeue(sch);
+	if (skb == NULL) {
+		if (net_ratelimit())
+			printk("qdisc_peek_len: non work-conserving qdisc ?\n");
+		return 0;
+	}
+	len = skb->len;
+	if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
+		if (net_ratelimit())
+			printk("qdisc_peek_len: failed to requeue\n");
+		return 0;
+	}
+	return len;
+}
+
+static void
+hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
+{
+	unsigned int len = cl->qdisc->q.qlen;
+
+	qdisc_reset(cl->qdisc);
+	if (len > 0) {
+		update_vf(cl, 0, 0);
+		set_passive(cl);
+		sch->q.qlen -= len;
+	}
+}
+
+static void
+hfsc_adjust_levels(struct hfsc_class *cl)
+{
+	struct hfsc_class *p;
+	unsigned int level;
+
+	do {
+		level = 0;
+		list_for_each_entry(p, &cl->children, siblings) {
+			if (p->level > level)
+				level = p->level;
+		}
+		cl->level = level + 1;
+	} while ((cl = cl->cl_parent) != NULL);
+}
+
+static inline unsigned int
+hfsc_hash(u32 h)
+{
+	h ^= h >> 8;
+	h ^= h >> 4;
+
+	return h & (HFSC_HSIZE - 1);
+}
+
+static inline struct hfsc_class *
+hfsc_find_class(u32 classid, struct Qdisc *sch)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl;
+
+	list_for_each_entry(cl, &q->clhash[hfsc_hash(classid)], hlist) {
+		if (cl->classid == classid)
+			return cl;
+	}
+	return NULL;
+}
+
+static void
+hfsc_change_rsc(struct hfsc_class *cl, struct tc_service_curve *rsc,
+                u64 cur_time)
+{
+	sc2isc(rsc, &cl->cl_rsc);
+	rtsc_init(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
+	cl->cl_eligible = cl->cl_deadline;
+	if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) {
+		cl->cl_eligible.dx = 0;
+		cl->cl_eligible.dy = 0;
+	}
+	cl->cl_flags |= HFSC_RSC;
+}
+
+static void
+hfsc_change_fsc(struct hfsc_class *cl, struct tc_service_curve *fsc)
+{
+	sc2isc(fsc, &cl->cl_fsc);
+	rtsc_init(&cl->cl_virtual, &cl->cl_fsc, cl->cl_vt, cl->cl_total);
+	cl->cl_flags |= HFSC_FSC;
+}
+
+static void
+hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
+                u64 cur_time)
+{
+	sc2isc(usc, &cl->cl_usc);
+	rtsc_init(&cl->cl_ulimit, &cl->cl_usc, cur_time, cl->cl_total);
+	cl->cl_flags |= HFSC_USC;
+}
+
+static int
+hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
+                  struct rtattr **tca, unsigned long *arg)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl = (struct hfsc_class *)*arg;
+	struct hfsc_class *parent = NULL;
+	struct rtattr *opt = tca[TCA_OPTIONS-1];
+	struct rtattr *tb[TCA_HFSC_MAX];
+	struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
+	u64 cur_time;
+
+	if (opt == NULL ||
+	    rtattr_parse(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
+		return -EINVAL;
+
+	if (tb[TCA_HFSC_RSC-1]) {
+		if (RTA_PAYLOAD(tb[TCA_HFSC_RSC-1]) < sizeof(*rsc))
+			return -EINVAL;
+		rsc = RTA_DATA(tb[TCA_HFSC_RSC-1]);
+		if (rsc->m1 == 0 && rsc->m2 == 0)
+			rsc = NULL;
+	}
+
+	if (tb[TCA_HFSC_FSC-1]) {
+		if (RTA_PAYLOAD(tb[TCA_HFSC_FSC-1]) < sizeof(*fsc))
+			return -EINVAL;
+		fsc = RTA_DATA(tb[TCA_HFSC_FSC-1]);
+		if (fsc->m1 == 0 && fsc->m2 == 0)
+			fsc = NULL;
+	}
+
+	if (tb[TCA_HFSC_USC-1]) {
+		if (RTA_PAYLOAD(tb[TCA_HFSC_USC-1]) < sizeof(*usc))
+			return -EINVAL;
+		usc = RTA_DATA(tb[TCA_HFSC_USC-1]);
+		if (usc->m1 == 0 && usc->m2 == 0)
+			usc = NULL;
+	}
+
+	if (cl != NULL) {
+		if (parentid) {
+			if (cl->cl_parent && cl->cl_parent->classid != parentid)
+				return -EINVAL;
+			if (cl->cl_parent == NULL && parentid != TC_H_ROOT)
+				return -EINVAL;
+		}
+		PSCHED_GET_TIME(cur_time);
+
+		sch_tree_lock(sch);
+		if (rsc != NULL)
+			hfsc_change_rsc(cl, rsc, cur_time);
+		if (fsc != NULL)
+			hfsc_change_fsc(cl, fsc);
+		if (usc != NULL)
+			hfsc_change_usc(cl, usc, cur_time);
+
+		if (cl->qdisc->q.qlen != 0) {
+			if (cl->cl_flags & HFSC_RSC)
+				update_ed(cl, qdisc_peek_len(cl->qdisc));
+			if (cl->cl_flags & HFSC_FSC)
+				update_vf(cl, 0, cur_time);
+		}
+		sch_tree_unlock(sch);
+
+#ifdef CONFIG_NET_ESTIMATOR
+		if (tca[TCA_RATE-1]) {
+			qdisc_kill_estimator(&cl->stats);
+			qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
+		}
+#endif
+		return 0;
+	}
+
+	if (parentid == TC_H_ROOT)
+		return -EEXIST;
+
+	parent = &q->root;
+	if (parentid) {
+		parent = hfsc_find_class(parentid, sch);
+		if (parent == NULL)
+			return -ENOENT;
+	}
+
+	if (classid == 0 || TC_H_MAJ(classid ^ sch->handle) != 0)
+		return -EINVAL;
+	if (hfsc_find_class(classid, sch))
+		return -EEXIST;
+
+	if (rsc == NULL && fsc == NULL)
+		return -EINVAL;
+
+	cl = kmalloc(sizeof(struct hfsc_class), GFP_KERNEL);
+	if (cl == NULL)
+		return -ENOBUFS;
+	memset(cl, 0, sizeof(struct hfsc_class));
+
+	if (rsc != NULL)
+		hfsc_change_rsc(cl, rsc, 0);
+	if (fsc != NULL)
+		hfsc_change_fsc(cl, fsc);
+	if (usc != NULL)
+		hfsc_change_usc(cl, usc, 0);
+
+	cl->refcnt    = 1;
+	cl->classid   = classid;
+	cl->sched     = q;
+	cl->cl_parent = parent;
+	cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+	if (cl->qdisc == NULL)
+		cl->qdisc = &noop_qdisc;
+	cl->stats.lock = &sch->dev->queue_lock;
+	INIT_LIST_HEAD(&cl->children);
+	INIT_LIST_HEAD(&cl->actlist);
+
+	sch_tree_lock(sch);
+	list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]);
+	list_add_tail(&cl->siblings, &parent->children);
+	if (parent->level == 0)
+		hfsc_purge_queue(sch, parent);
+	hfsc_adjust_levels(parent);
+	sch_tree_unlock(sch);
+
+#ifdef CONFIG_NET_ESTIMATOR
+	if (tca[TCA_RATE-1])
+		qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
+#endif
+	*arg = (unsigned long)cl;
+	return 0;
+}
+
+static void
+hfsc_destroy_filters(struct tcf_proto **fl)
+{
+	struct tcf_proto *tp;
+
+	while ((tp = *fl) != NULL) {
+		*fl = tp->next;
+		tcf_destroy(tp);
+	}
+}
+
+static void
+hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+
+	hfsc_destroy_filters(&cl->filter_list);
+	qdisc_destroy(cl->qdisc);
+#ifdef CONFIG_NET_ESTIMATOR
+	qdisc_kill_estimator(&cl->stats);
+#endif
+	if (cl != &q->root)
+		kfree(cl);
+}
+
+static int
+hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+	if (cl->level > 0 || cl->filter_cnt > 0 || cl == &q->root)
+		return -EBUSY;
+
+	sch_tree_lock(sch);
+
+	list_del(&cl->hlist);
+	list_del(&cl->siblings);
+	hfsc_adjust_levels(cl->cl_parent);
+	hfsc_purge_queue(sch, cl);
+	if (q->last_xmit == cl)
+		q->last_xmit = NULL;
+
+	if (--cl->refcnt == 0)
+		hfsc_destroy_class(sch, cl);
+
+	sch_tree_unlock(sch);
+	return 0;
+}
+
+static struct hfsc_class *
+hfsc_classify(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl;
+	struct tcf_result res;
+	struct tcf_proto *tcf;
+	int result;
+
+	if (TC_H_MAJ(skb->priority ^ sch->handle) == 0 &&
+	    (cl = hfsc_find_class(skb->priority, sch)) != NULL)
+		if (cl->level == 0)
+			return cl;
+
+	tcf = q->root.filter_list;
+	while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
+#ifdef CONFIG_NET_CLS_POLICE
+		if (result == TC_POLICE_SHOT)
+			return NULL;
+#endif
+		if ((cl = (struct hfsc_class *)res.class) == NULL) {
+			if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
+				break; /* filter selected invalid classid */
+		}
+
+		if (cl->level == 0)
+			return cl; /* hit leaf class */
+
+		/* apply inner filter chain */
+		tcf = cl->filter_list;
+	}
+
+	/* classification failed, try default class */
+	cl = hfsc_find_class(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
+	if (cl == NULL || cl->level > 0)
+		return NULL;
+
+	return cl;
+}
+
+static int
+hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+                 struct Qdisc **old)
+{
+	struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+	if (cl == NULL)
+		return -ENOENT;
+	if (cl->level > 0)
+		return -EINVAL;
+	if (new == NULL) {
+		new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+		if (new == NULL)
+			new = &noop_qdisc;
+	}
+
+	sch_tree_lock(sch);
+	hfsc_purge_queue(sch, cl);
+	*old = xchg(&cl->qdisc, new);
+	sch_tree_unlock(sch);
+	return 0;
+}
+
+static struct Qdisc *
+hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+	if (cl != NULL && cl->level == 0)
+		return cl->qdisc;
+
+	return NULL;
+}
+
+static unsigned long
+hfsc_get_class(struct Qdisc *sch, u32 classid)
+{
+	struct hfsc_class *cl = hfsc_find_class(classid, sch);
+
+	if (cl != NULL)
+		cl->refcnt++;
+
+	return (unsigned long)cl;
+}
+
+static void
+hfsc_put_class(struct Qdisc *sch, unsigned long arg)
+{
+	struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+	if (--cl->refcnt == 0)
+		hfsc_destroy_class(sch, cl);
+}
+
+static unsigned long
+hfsc_bind_tcf(struct Qdisc *sch, unsigned long parent, u32 classid)
+{
+	struct hfsc_class *p = (struct hfsc_class *)parent;
+	struct hfsc_class *cl = hfsc_find_class(classid, sch);
+
+	if (cl != NULL) {
+		if (p != NULL && p->level <= cl->level)
+			return 0;
+		cl->filter_cnt++;
+	}
+
+	return (unsigned long)cl;
+}
+
+static void
+hfsc_unbind_tcf(struct Qdisc *sch, unsigned long arg)
+{
+	struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+	cl->filter_cnt--;
+}
+
+static struct tcf_proto **
+hfsc_tcf_chain(struct Qdisc *sch, unsigned long arg)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+	if (cl == NULL)
+		cl = &q->root;
+
+	return &cl->filter_list;
+}
+
+static int
+hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc)
+{
+	struct tc_service_curve tsc;
+
+	tsc.m1 = sm2m(sc->sm1);
+	tsc.d  = dx2d(sc->dx);
+	tsc.m2 = sm2m(sc->sm2);
+	RTA_PUT(skb, attr, sizeof(tsc), &tsc);
+
+	return skb->len;
+
+ rtattr_failure:
+	return -1;
+}
+
+static inline int
+hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl)
+{
+	if ((cl->cl_flags & HFSC_RSC) &&
+	    (hfsc_dump_sc(skb, TCA_HFSC_RSC, &cl->cl_rsc) < 0))
+		goto rtattr_failure;
+
+	if ((cl->cl_flags & HFSC_FSC) &&
+	    (hfsc_dump_sc(skb, TCA_HFSC_FSC, &cl->cl_fsc) < 0))
+		goto rtattr_failure;
+
+	if ((cl->cl_flags & HFSC_USC) &&
+	    (hfsc_dump_sc(skb, TCA_HFSC_USC, &cl->cl_usc) < 0))
+		goto rtattr_failure;
+
+	return skb->len;
+
+ rtattr_failure:
+	return -1;
+}
+
+static inline int
+hfsc_dump_stats(struct sk_buff *skb, struct hfsc_class *cl)
+{
+	cl->stats.qlen = cl->qdisc->q.qlen;
+	if (qdisc_copy_stats(skb, &cl->stats) < 0)
+		goto rtattr_failure;
+
+	return skb->len;
+
+ rtattr_failure:
+	return -1;
+}
+
+static inline int
+hfsc_dump_xstats(struct sk_buff *skb, struct hfsc_class *cl)
+{
+	struct tc_hfsc_stats xstats;
+
+	xstats.level  = cl->level;
+	xstats.period = cl->cl_vtperiod;
+	xstats.work   = cl->cl_total;
+	xstats.rtwork = cl->cl_cumul;
+	RTA_PUT(skb, TCA_XSTATS, sizeof(xstats), &xstats);
+
+	return skb->len;
+
+ rtattr_failure:
+	return -1;
+}
+
+static int
+hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
+                struct tcmsg *tcm)
+{
+	struct hfsc_class *cl = (struct hfsc_class *)arg;
+	unsigned char *b = skb->tail;
+	struct rtattr *rta = (struct rtattr *)b;
+
+	tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT;
+	tcm->tcm_handle = cl->classid;
+	if (cl->level == 0)
+		tcm->tcm_info = cl->qdisc->handle;
+
+	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	if (hfsc_dump_curves(skb, cl) < 0)
+		goto rtattr_failure;
+	rta->rta_len = skb->tail - b;
+
+	if ((hfsc_dump_stats(skb, cl) < 0) ||
+	    (hfsc_dump_xstats(skb, cl) < 0))
+		goto rtattr_failure;
+
+	return skb->len;
+
+ rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static void
+hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl;
+	unsigned int i;
+
+	if (arg->stop)
+		return;
+
+	for (i = 0; i < HFSC_HSIZE; i++) {
+		list_for_each_entry(cl, &q->clhash[i], hlist) {
+			if (arg->count < arg->skip) {
+				arg->count++;
+				continue;
+			}
+			if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
+				arg->stop = 1;
+				return;
+			}
+			arg->count++;
+		}
+	}
+}
+
+static void
+hfsc_watchdog(unsigned long arg)
+{
+	struct Qdisc *sch = (struct Qdisc *)arg;
+
+	sch->flags &= ~TCQ_F_THROTTLED;
+	netif_schedule(sch->dev);
+}
+
+static void
+hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl;
+	u64 next_time = 0;
+	long delay;
+
+	if ((cl = ellist_get_minel(&q->eligible)) != NULL)
+		next_time = cl->cl_e;
+	if (q->root.cl_cfmin != 0) {
+		if (next_time == 0 || next_time > q->root.cl_cfmin)
+			next_time = q->root.cl_cfmin;
+	}
+	ASSERT(next_time != 0);
+	delay = next_time - cur_time;
+	delay = PSCHED_US2JIFFIE(delay);
+
+	sch->flags |= TCQ_F_THROTTLED;
+	mod_timer(&q->wd_timer, jiffies + delay);
+}
+
+static int
+hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct tc_hfsc_qopt *qopt;
+	unsigned int i;
+
+	if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+		return -EINVAL;
+	qopt = RTA_DATA(opt);
+
+	memset(q, 0, sizeof(struct hfsc_sched));
+	sch->stats.lock = &sch->dev->queue_lock;
+
+	q->defcls = qopt->defcls;
+	for (i = 0; i < HFSC_HSIZE; i++)
+		INIT_LIST_HEAD(&q->clhash[i]);
+	INIT_LIST_HEAD(&q->eligible);
+	INIT_LIST_HEAD(&q->droplist);
+
+	q->root.refcnt  = 1;
+	q->root.classid = sch->handle;
+	q->root.sched   = q;
+	q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+	if (q->root.qdisc == NULL)
+		q->root.qdisc = &noop_qdisc;
+	q->root.stats.lock = &sch->dev->queue_lock;
+	INIT_LIST_HEAD(&q->root.children);
+	INIT_LIST_HEAD(&q->root.actlist);
+
+	list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]);
+
+	init_timer(&q->wd_timer);
+	q->wd_timer.function = hfsc_watchdog;
+	q->wd_timer.data = (unsigned long)sch;
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int
+hfsc_change_qdisc(struct Qdisc *sch, struct rtattr *opt)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct tc_hfsc_qopt *qopt;
+
+	if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+		return -EINVAL;;
+	qopt = RTA_DATA(opt);
+
+	sch_tree_lock(sch);
+	q->defcls = qopt->defcls;
+	sch_tree_unlock(sch);
+
+	return 0;
+}
+
+static void
+hfsc_reset_class(struct hfsc_class *cl)
+{
+	cl->cl_total        = 0;
+	cl->cl_cumul        = 0;
+	cl->cl_d            = 0;
+	cl->cl_e            = 0;
+	cl->cl_vt           = 0;
+	cl->cl_vtadj        = 0;
+	cl->cl_vtoff        = 0;
+	cl->cl_cvtmin       = 0;
+	cl->cl_cvtmax       = 0;
+	cl->cl_vtperiod     = 0;
+	cl->cl_parentperiod = 0;
+	cl->cl_f            = 0;
+	cl->cl_myf          = 0;
+	cl->cl_myfadj       = 0;
+	cl->cl_cfmin        = 0;
+	cl->cl_nactive      = 0;
+	INIT_LIST_HEAD(&cl->actlist);
+	qdisc_reset(cl->qdisc);
+
+	if (cl->cl_flags & HFSC_RSC)
+		rtsc_init(&cl->cl_deadline, &cl->cl_rsc, 0, 0);
+	if (cl->cl_flags & HFSC_FSC)
+		rtsc_init(&cl->cl_virtual, &cl->cl_fsc, 0, 0);
+	if (cl->cl_flags & HFSC_USC)
+		rtsc_init(&cl->cl_ulimit, &cl->cl_usc, 0, 0);
+}
+
+static void
+hfsc_reset_qdisc(struct Qdisc *sch)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl;
+	unsigned int i;
+
+	for (i = 0; i < HFSC_HSIZE; i++) {
+		list_for_each_entry(cl, &q->clhash[i], hlist)
+			hfsc_reset_class(cl);
+	}
+
+	INIT_LIST_HEAD(&q->eligible);
+	INIT_LIST_HEAD(&q->droplist);
+	q->last_xmit = NULL;
+	del_timer(&q->wd_timer);
+	sch->flags &= ~TCQ_F_THROTTLED;
+	sch->q.qlen = 0;
+}
+
+static void
+hfsc_destroy_qdisc(struct Qdisc *sch)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl, *next;
+	unsigned int i;
+
+	for (i = 0; i < HFSC_HSIZE; i++) {
+		list_for_each_entry_safe(cl, next, &q->clhash[i], hlist)
+			hfsc_destroy_class(sch, cl);
+	}
+
+	del_timer(&q->wd_timer);
+	MOD_DEC_USE_COUNT;
+}
+
+static int
+hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	unsigned char *b = skb->tail;
+	struct tc_hfsc_qopt qopt;
+
+	qopt.defcls = q->defcls;
+	RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+
+	sch->stats.qlen = sch->q.qlen;
+	if (qdisc_copy_stats(skb, &sch->stats) < 0)
+		goto rtattr_failure;
+
+	return skb->len;
+
+ rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int
+hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct hfsc_class *cl = hfsc_classify(skb, sch);
+	unsigned int len = skb->len;
+	int err;
+
+	if (cl == NULL) {
+		kfree_skb(skb);
+		sch->stats.drops++;
+		return NET_XMIT_DROP;
+	}
+
+	err = cl->qdisc->enqueue(skb, cl->qdisc);
+	if (unlikely(err != NET_XMIT_SUCCESS)) {
+		cl->stats.drops++;
+		sch->stats.drops++;
+		return err;
+	}
+
+	if (cl->qdisc->q.qlen == 1)
+		set_active(cl, len);
+
+	cl->stats.packets++;
+	cl->stats.bytes += len;
+	sch->stats.packets++;
+	sch->stats.bytes += len;
+	sch->q.qlen++;
+
+	return NET_XMIT_SUCCESS;
+}
+
+static struct sk_buff *
+hfsc_dequeue(struct Qdisc *sch)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl;
+	struct sk_buff *skb;
+	u64 cur_time;
+	unsigned int next_len;
+	int realtime = 0;
+
+	if (sch->q.qlen == 0)
+		return NULL;
+
+	PSCHED_GET_TIME(cur_time);
+
+	/*
+	 * if there are eligible classes, use real-time criteria.
+	 * find the class with the minimum deadline among
+	 * the eligible classes.
+	 */
+	if ((cl = ellist_get_mindl(&q->eligible, cur_time)) != NULL) {
+		realtime = 1;
+	} else {
+		/*
+		 * use link-sharing criteria
+		 * get the class with the minimum vt in the hierarchy
+		 */
+		cl = actlist_get_minvt(&q->root, cur_time);
+		if (cl == NULL) {
+			sch->stats.overlimits++;
+			if (!netif_queue_stopped(sch->dev))
+				hfsc_schedule_watchdog(sch, cur_time);
+			return NULL;
+		}
+	}
+
+	skb = cl->qdisc->dequeue(cl->qdisc);
+	if (skb == NULL) {
+		if (net_ratelimit())
+			printk("HFSC: Non-work-conserving qdisc ?\n");
+		return NULL;
+	}
+
+	update_vf(cl, skb->len, cur_time);
+	if (realtime)
+		cl->cl_cumul += skb->len;
+
+	if (cl->qdisc->q.qlen != 0) {
+		if (cl->cl_flags & HFSC_RSC) {
+			/* update ed */
+			next_len = qdisc_peek_len(cl->qdisc);
+			if (realtime)
+				update_ed(cl, next_len);
+			else
+				update_d(cl, next_len);
+		}
+	} else {
+		/* the class becomes passive */
+		set_passive(cl);
+	}
+
+	q->last_xmit = cl;
+	sch->flags &= ~TCQ_F_THROTTLED;
+	sch->q.qlen--;
+
+	return skb;
+}
+
+static int
+hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl = q->last_xmit;
+	unsigned int len = skb->len;
+	int ret;
+
+	if (cl == NULL) {
+		kfree_skb(skb);
+		sch->stats.drops++;
+		return NET_XMIT_DROP;
+	}
+
+	ret = cl->qdisc->ops->requeue(skb, cl->qdisc);
+	if (ret == NET_XMIT_SUCCESS) {
+		if (cl->qdisc->q.qlen == 1)
+			set_active(cl, len);
+		sch->q.qlen++;
+	} else {
+		cl->stats.drops++;
+		sch->stats.drops++;
+	}
+	q->last_xmit = NULL;
+
+	return ret;
+}
+
+static unsigned int
+hfsc_drop(struct Qdisc *sch)
+{
+	struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+	struct hfsc_class *cl;
+	unsigned int len;
+
+	list_for_each_entry(cl, &q->droplist, dlist) {
+		if (cl->qdisc->ops->drop != NULL &&
+		    (len = cl->qdisc->ops->drop(cl->qdisc)) > 0) {
+			if (cl->qdisc->q.qlen == 0) {
+				update_vf(cl, 0, 0);
+				set_passive(cl);
+			} else {
+				list_move_tail(&cl->dlist, &q->droplist);
+			}
+			cl->stats.drops++;
+			sch->stats.drops++;
+			sch->q.qlen--;
+			return len;
+		}
+	}
+	return 0;
+}
+
+static struct Qdisc_class_ops hfsc_class_ops = {
+	.change		= hfsc_change_class,
+	.delete		= hfsc_delete_class,
+	.graft		= hfsc_graft_class,
+	.leaf		= hfsc_class_leaf,
+	.get		= hfsc_get_class,
+	.put		= hfsc_put_class,
+	.bind_tcf	= hfsc_bind_tcf,
+	.unbind_tcf	= hfsc_unbind_tcf,
+	.tcf_chain	= hfsc_tcf_chain,
+	.dump		= hfsc_dump_class,
+	.walk		= hfsc_walk
+};
+
+struct Qdisc_ops hfsc_qdisc_ops = {
+	.id		= "hfsc",
+	.init		= hfsc_init_qdisc,
+	.change		= hfsc_change_qdisc,
+	.reset		= hfsc_reset_qdisc,
+	.destroy	= hfsc_destroy_qdisc,
+	.dump		= hfsc_dump_qdisc,
+	.enqueue	= hfsc_enqueue,
+	.dequeue	= hfsc_dequeue,
+	.requeue	= hfsc_requeue,
+	.drop		= hfsc_drop,
+	.cl_ops		= &hfsc_class_ops,
+	.priv_size	= sizeof(struct hfsc_sched)
+};
+
+static int __init
+hfsc_init(void)
+{
+	return register_qdisc(&hfsc_qdisc_ops);
+}
+
+static void __exit
+hfsc_cleanup(void)
+{
+	unregister_qdisc(&hfsc_qdisc_ops);
+}
+
+MODULE_LICENSE("GPL");
+module_init(hfsc_init);
+module_exit(hfsc_cleanup);
