--- /dev/null
+diff -urN linux.org/fs/xfs/linux/xfs_aops.c linux/fs/xfs/linux/xfs_aops.c
+--- linux.org/fs/xfs/linux/xfs_aops.c 2003-12-31 05:48:20.000000000 +0100
++++ linux/fs/xfs/linux/xfs_aops.c 2004-01-02 04:21:43.000000000 +0100
+@@ -51,10 +51,11 @@
+ #include "xfs_inode.h"
+ #include "xfs_error.h"
+ #include "xfs_rw.h"
++#include "xfs_iomap.h"
+ #include <linux/mpage.h>
+
+ STATIC void convert_page(struct inode *, struct page *,
+- page_buf_bmap_t *, void *, int, int);
++ xfs_iomap_t *, void *, int, int);
+
+ void
+ linvfs_unwritten_done(
+@@ -85,11 +86,9 @@
+ vnode_t *vp = XFS_BUF_FSPRIVATE(bp, vnode_t *);
+ int error;
+
+- if (atomic_read(&bp->pb_hold) < 1)
+- BUG();
+-
++ BUG_ON(atomic_read(&bp->pb_hold) < 1);
+ VOP_BMAP(vp, XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp),
+- BMAP_UNWRITTEN, NULL, NULL, error);
++ BMAPI_UNWRITTEN, NULL, NULL, error);
+ XFS_BUF_SET_FSPRIVATE(bp, NULL);
+ XFS_BUF_CLR_IODONE_FUNC(bp);
+ XFS_BUF_UNDATAIO(bp);
+@@ -117,7 +116,7 @@
+ vnode_t *vp = LINVFS_GET_VP(inode);
+ int error;
+
+- VOP_BMAP(vp, offset, size, BMAP_UNWRITTEN, NULL, NULL, error);
++ VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error);
+ }
+ }
+
+@@ -126,26 +125,26 @@
+ struct inode *inode,
+ loff_t offset,
+ ssize_t count,
+- page_buf_bmap_t *pbmapp,
++ xfs_iomap_t *iomapp,
+ int flags)
+ {
+ vnode_t *vp = LINVFS_GET_VP(inode);
+- int error, nmaps = 1;
++ int error, niomaps = 1;
+
+- if (((flags & (BMAP_DIRECT|BMAP_SYNC)) == BMAP_DIRECT) &&
++ if (((flags & (BMAPI_DIRECT|BMAPI_SYNC)) == BMAPI_DIRECT) &&
+ (offset >= i_size_read(inode)))
+ count = max_t(ssize_t, count, XFS_WRITE_IO_LOG);
+ retry:
+- VOP_BMAP(vp, offset, count, flags, pbmapp, &nmaps, error);
++ VOP_BMAP(vp, offset, count, flags, iomapp, &niomaps, error);
+ if ((error == EAGAIN) || (error == EIO))
+ return -error;
+- if (unlikely((flags & (BMAP_WRITE|BMAP_DIRECT)) ==
+- (BMAP_WRITE|BMAP_DIRECT) && nmaps &&
+- (pbmapp->pbm_flags & PBMF_DELAY))) {
+- flags = BMAP_ALLOCATE;
++ if (unlikely((flags & (BMAPI_WRITE|BMAPI_DIRECT)) ==
++ (BMAPI_WRITE|BMAPI_DIRECT) && niomaps &&
++ (iomapp->iomap_flags & IOMAP_DELAY))) {
++ flags = BMAPI_ALLOCATE;
+ goto retry;
+ }
+- if (flags & (BMAP_WRITE|BMAP_ALLOCATE)) {
++ if (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)) {
+ VMODIFY(vp);
+ }
+ return -error;
+@@ -156,10 +155,10 @@
+ * Finds the corresponding mapping in block @map array of the
+ * given @offset within a @page.
+ */
+-STATIC page_buf_bmap_t *
++STATIC xfs_iomap_t *
+ match_offset_to_mapping(
+ struct page *page,
+- page_buf_bmap_t *map,
++ xfs_iomap_t *iomapp,
+ unsigned long offset)
+ {
+ loff_t full_offset; /* offset from start of file */
+@@ -170,10 +169,10 @@
+ full_offset <<= PAGE_CACHE_SHIFT; /* offset from file start */
+ full_offset += offset; /* offset from page start */
+
+- if (full_offset < map->pbm_offset)
++ if (full_offset < iomapp->iomap_offset)
+ return NULL;
+- if (map->pbm_offset + map->pbm_bsize > full_offset)
+- return map;
++ if (iomapp->iomap_offset + iomapp->iomap_bsize > full_offset)
++ return iomapp;
+ return NULL;
+ }
+
+@@ -183,30 +182,30 @@
+ struct buffer_head *bh,
+ unsigned long offset,
+ int block_bits,
+- page_buf_bmap_t *mp)
++ xfs_iomap_t *iomapp)
+ {
+- page_buf_daddr_t bn;
++ xfs_daddr_t bn;
+ loff_t delta;
+ int sector_shift;
+
+- ASSERT(!(mp->pbm_flags & PBMF_HOLE));
+- ASSERT(!(mp->pbm_flags & PBMF_DELAY));
+- ASSERT(mp->pbm_bn != PAGE_BUF_DADDR_NULL);
++ ASSERT(!(iomapp->iomap_flags & IOMAP_HOLE));
++ ASSERT(!(iomapp->iomap_flags & IOMAP_DELAY));
++ ASSERT(iomapp->iomap_bn != IOMAP_DADDR_NULL);
+
+ delta = page->index;
+ delta <<= PAGE_CACHE_SHIFT;
+ delta += offset;
+- delta -= mp->pbm_offset;
++ delta -= iomapp->iomap_offset;
+ delta >>= block_bits;
+
+ sector_shift = block_bits - BBSHIFT;
+- bn = mp->pbm_bn >> sector_shift;
++ bn = iomapp->iomap_bn >> sector_shift;
+ bn += delta;
+- ASSERT((bn << sector_shift) >= mp->pbm_bn);
++ ASSERT((bn << sector_shift) >= iomapp->iomap_bn);
+
+ lock_buffer(bh);
+ bh->b_blocknr = bn;
+- bh->b_bdev = mp->pbm_target->pbr_bdev;
++ bh->b_bdev = iomapp->iomap_target->pbr_bdev;
+ set_buffer_mapped(bh);
+ clear_buffer_delay(bh);
+ }
+@@ -222,7 +221,7 @@
+ probe_unwritten_page(
+ struct address_space *mapping,
+ unsigned long index,
+- page_buf_bmap_t *mp,
++ xfs_iomap_t *iomapp,
+ page_buf_t *pb,
+ unsigned long max_offset,
+ unsigned long *fsbs,
+@@ -245,11 +244,11 @@
+ do {
+ if (!buffer_unwritten(bh))
+ break;
+- if (!match_offset_to_mapping(page, mp, p_offset))
++ if (!match_offset_to_mapping(page, iomapp, p_offset))
+ break;
+ if (p_offset >= max_offset)
+ break;
+- map_buffer_at_offset(page, bh, p_offset, bbits, mp);
++ map_buffer_at_offset(page, bh, p_offset, bbits, iomapp);
+ set_buffer_unwritten_io(bh);
+ bh->b_private = pb;
+ p_offset += bh->b_size;
+@@ -394,11 +393,12 @@
+ struct buffer_head *curr,
+ unsigned long p_offset,
+ int block_bits,
+- page_buf_bmap_t *mp,
++ xfs_iomap_t *iomapp,
++ int startio,
+ int all_bh)
+ {
+ struct buffer_head *bh = curr;
+- page_buf_bmap_t *tmp;
++ xfs_iomap_t *tmp;
+ page_buf_t *pb;
+ loff_t offset, size;
+ unsigned long nblocks = 0;
+@@ -407,8 +407,8 @@
+ offset <<= PAGE_CACHE_SHIFT;
+ offset += p_offset;
+
+- pb = pagebuf_lookup(mp->pbm_target,
+- mp->pbm_offset, mp->pbm_bsize, 0);
++ pb = pagebuf_lookup(iomapp->iomap_target,
++ iomapp->iomap_offset, iomapp->iomap_bsize, 0);
+ if (!pb)
+ return -EAGAIN;
+
+@@ -433,10 +433,10 @@
+ do {
+ if (!buffer_unwritten(bh))
+ break;
+- tmp = match_offset_to_mapping(start_page, mp, p_offset);
++ tmp = match_offset_to_mapping(start_page, iomapp, p_offset);
+ if (!tmp)
+ break;
+- map_buffer_at_offset(start_page, bh, p_offset, block_bits, mp);
++ map_buffer_at_offset(start_page, bh, p_offset, block_bits, iomapp);
+ set_buffer_unwritten_io(bh);
+ bh->b_private = pb;
+ p_offset += bh->b_size;
+@@ -444,8 +444,8 @@
+ } while ((bh = bh->b_this_page) != head);
+
+ if (unlikely(nblocks == 0)) {
+- printk("XFS: bad unwritten extent map: bh=0x%p, mp=0x%p\n",
+- curr, mp);
++ printk("XFS: bad unwritten extent map: bh=0x%p, iomapp=0x%p\n",
++ curr, iomapp);
+ BUG();
+ }
+
+@@ -461,26 +461,26 @@
+ struct page *page;
+
+ tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT;
+- tloff = (mp->pbm_offset + mp->pbm_bsize) >> PAGE_CACHE_SHIFT;
++ tloff = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT;
+ tloff = min(tlast, tloff);
+ for (tindex = start_page->index + 1; tindex < tloff; tindex++) {
+- page = probe_unwritten_page(mapping, tindex, mp, pb,
++ page = probe_unwritten_page(mapping, tindex, iomapp, pb,
+ PAGE_CACHE_SIZE, &bs, bbits);
+ if (!page)
+ break;
+ nblocks += bs;
+ atomic_add(bs, &pb->pb_io_remaining);
+- convert_page(inode, page, mp, pb, 1, all_bh);
++ convert_page(inode, page, iomapp, pb, startio, all_bh);
+ }
+
+ if (tindex == tlast &&
+ (tloff = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)))) {
+- page = probe_unwritten_page(mapping, tindex, mp, pb,
++ page = probe_unwritten_page(mapping, tindex, iomapp, pb,
+ tloff, &bs, bbits);
+ if (page) {
+ nblocks += bs;
+ atomic_add(bs, &pb->pb_io_remaining);
+- convert_page(inode, page, mp, pb, 1, all_bh);
++ convert_page(inode, page, iomapp, pb, startio, all_bh);
+ }
+ }
+ }
+@@ -542,13 +542,13 @@
+ convert_page(
+ struct inode *inode,
+ struct page *page,
+- page_buf_bmap_t *maps,
++ xfs_iomap_t *iomapp,
+ void *private,
+ int startio,
+ int all_bh)
+ {
+ struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
+- page_buf_bmap_t *mp = maps, *tmp;
++ xfs_iomap_t *mp = iomapp, *tmp;
+ unsigned long end, offset, end_index;
+ int i = 0, index = 0;
+ int bbits = inode->i_blkbits;
+@@ -575,17 +575,17 @@
+ tmp = match_offset_to_mapping(page, mp, offset);
+ if (!tmp)
+ continue;
+- ASSERT(!(tmp->pbm_flags & PBMF_HOLE));
+- ASSERT(!(tmp->pbm_flags & PBMF_DELAY));
++ ASSERT(!(tmp->iomap_flags & IOMAP_HOLE));
++ ASSERT(!(tmp->iomap_flags & IOMAP_DELAY));
+
+ /* If this is a new unwritten extent buffer (i.e. one
+ * that we haven't passed in private data for, we must
+ * now map this buffer too.
+ */
+ if (buffer_unwritten(bh) && !bh->b_end_io) {
+- ASSERT(tmp->pbm_flags & PBMF_UNWRITTEN);
++ ASSERT(tmp->iomap_flags & IOMAP_UNWRITTEN);
+ map_unwritten(inode, page, head, bh,
+- offset, bbits, tmp, all_bh);
++ offset, bbits, tmp, startio, all_bh);
+ } else if (! (buffer_unwritten(bh) && buffer_locked(bh))) {
+ map_buffer_at_offset(page, bh, offset, bbits, tmp);
+ if (buffer_unwritten(bh)) {
+@@ -618,19 +618,19 @@
+ cluster_write(
+ struct inode *inode,
+ unsigned long tindex,
+- page_buf_bmap_t *mp,
++ xfs_iomap_t *iomapp,
+ int startio,
+ int all_bh)
+ {
+ unsigned long tlast;
+ struct page *page;
+
+- tlast = (mp->pbm_offset + mp->pbm_bsize) >> PAGE_CACHE_SHIFT;
++ tlast = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT;
+ for (; tindex < tlast; tindex++) {
+ page = probe_delalloc_page(inode, tindex);
+ if (!page)
+ break;
+- convert_page(inode, page, mp, NULL, startio, all_bh);
++ convert_page(inode, page, iomapp, NULL, startio, all_bh);
+ }
+ }
+
+@@ -661,20 +661,21 @@
+ int unmapped) /* also implies page uptodate */
+ {
+ struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
+- page_buf_bmap_t *mp, map;
++ xfs_iomap_t *iomp, iomap;
+ unsigned long p_offset = 0, end_index;
+ loff_t offset, end_offset;
+ int len, err, i, cnt = 0, uptodate = 1;
+- int flags = startio ? 0 : BMAP_TRYLOCK;
++ int flags = startio ? 0 : BMAPI_TRYLOCK;
+ int page_dirty = 1;
+
+
+ /* Are we off the end of the file ? */
+ end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
+ if (page->index >= end_index) {
+- unsigned remaining = i_size_read(inode) & (PAGE_CACHE_SIZE-1);
+- if ((page->index >= end_index+1) || !remaining) {
+- return -EIO;
++ if ((page->index >= end_index + 1) ||
++ !(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) {
++ err = -EIO;
++ goto error;
+ }
+ }
+
+@@ -684,16 +685,19 @@
+ end_offset = i_size_read(inode);
+
+ bh = head = page_buffers(page);
+- mp = NULL;
++ iomp = NULL;
+
+ len = bh->b_size;
+ do {
+- if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio) {
+- goto next_bh;
+- }
++ if (offset >= end_offset)
++ break;
++ if (!buffer_uptodate(bh))
++ uptodate = 0;
++ if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio)
++ continue;
+
+- if (mp) {
+- mp = match_offset_to_mapping(page, &map, p_offset);
++ if (iomp) {
++ iomp = match_offset_to_mapping(page, &iomap, p_offset);
+ }
+
+ /*
+@@ -701,21 +705,21 @@
+ * extent state conversion transaction on completion.
+ */
+ if (buffer_unwritten(bh)) {
+- if (!mp) {
+- err = map_blocks(inode, offset, len, &map,
+- BMAP_READ|BMAP_IGNSTATE);
++ if (!iomp) {
++ err = map_blocks(inode, offset, len, &iomap,
++ BMAPI_READ|BMAPI_IGNSTATE);
+ if (err) {
+ goto error;
+ }
+- mp = match_offset_to_mapping(page, &map,
++ iomp = match_offset_to_mapping(page, &iomap,
+ p_offset);
+ }
+- if (mp) {
++ if (iomp) {
+ if (!bh->b_end_io) {
+ err = map_unwritten(inode, page,
+ head, bh, p_offset,
+- inode->i_blkbits,
+- mp, unmapped);
++ inode->i_blkbits, iomp,
++ startio, unmapped);
+ if (err) {
+ goto error;
+ }
+@@ -734,18 +738,18 @@
+ * We can return EAGAIN here in the release page case.
+ */
+ } else if (buffer_delay(bh)) {
+- if (!mp) {
+- err = map_blocks(inode, offset, len, &map,
+- BMAP_ALLOCATE | flags);
++ if (!iomp) {
++ err = map_blocks(inode, offset, len, &iomap,
++ BMAPI_ALLOCATE | flags);
+ if (err) {
+ goto error;
+ }
+- mp = match_offset_to_mapping(page, &map,
++ iomp = match_offset_to_mapping(page, &iomap,
+ p_offset);
+ }
+- if (mp) {
++ if (iomp) {
+ map_buffer_at_offset(page, bh, p_offset,
+- inode->i_blkbits, mp);
++ inode->i_blkbits, iomp);
+ if (startio) {
+ bh_arr[cnt++] = bh;
+ } else {
+@@ -766,22 +770,22 @@
+ * was found, and we are in a path where we
+ * need to write the whole page out.
+ */
+- if (!mp) {
++ if (!iomp) {
+ size = probe_unmapped_cluster(
+ inode, page, bh, head);
+ err = map_blocks(inode, offset,
+- size, &map,
+- BMAP_WRITE | BMAP_MMAP);
++ size, &iomap,
++ BMAPI_WRITE | BMAPI_MMAP);
+ if (err) {
+ goto error;
+ }
+- mp = match_offset_to_mapping(page, &map,
++ iomp = match_offset_to_mapping(page, &iomap,
+ p_offset);
+ }
+- if (mp) {
++ if (iomp) {
+ map_buffer_at_offset(page,
+ bh, p_offset,
+- inode->i_blkbits, mp);
++ inode->i_blkbits, iomp);
+ if (startio) {
+ bh_arr[cnt++] = bh;
+ } else {
+@@ -799,14 +803,8 @@
+ }
+ }
+ }
+-
+-next_bh:
+- if (!buffer_uptodate(bh))
+- uptodate = 0;
+- offset += len;
+- p_offset += len;
+- bh = bh->b_this_page;
+- } while (offset < end_offset);
++ } while (offset += len, p_offset += len,
++ ((bh = bh->b_this_page) != head));
+
+ if (uptodate && bh == head)
+ SetPageUptodate(page);
+@@ -814,8 +812,8 @@
+ if (startio)
+ submit_page(page, bh_arr, cnt);
+
+- if (mp)
+- cluster_write(inode, page->index + 1, mp, startio, unmapped);
++ if (iomp)
++ cluster_write(inode, page->index + 1, iomp, startio, unmapped);
+
+ return page_dirty;
+
+@@ -849,7 +847,7 @@
+ bmapi_flags_t flags)
+ {
+ vnode_t *vp = LINVFS_GET_VP(inode);
+- page_buf_bmap_t pbmap;
++ xfs_iomap_t iomap;
+ int retpbbm = 1;
+ int error;
+ ssize_t size;
+@@ -866,32 +864,32 @@
+ size = 1 << inode->i_blkbits;
+
+ VOP_BMAP(vp, offset, size,
+- create ? flags : BMAP_READ, &pbmap, &retpbbm, error);
++ create ? flags : BMAPI_READ, &iomap, &retpbbm, error);
+ if (error)
+ return -error;
+
+ if (retpbbm == 0)
+ return 0;
+
+- if (pbmap.pbm_bn != PAGE_BUF_DADDR_NULL) {
+- page_buf_daddr_t bn;
++ if (iomap.iomap_bn != IOMAP_DADDR_NULL) {
++ xfs_daddr_t bn;
+ loff_t delta;
+
+ /* For unwritten extents do not report a disk address on
+ * the read case.
+ */
+- if (create || ((pbmap.pbm_flags & PBMF_UNWRITTEN) == 0)) {
+- delta = offset - pbmap.pbm_offset;
++ if (create || ((iomap.iomap_flags & IOMAP_UNWRITTEN) == 0)) {
++ delta = offset - iomap.iomap_offset;
+ delta >>= inode->i_blkbits;
+
+- bn = pbmap.pbm_bn >> (inode->i_blkbits - BBSHIFT);
++ bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT);
+ bn += delta;
+
+ bh_result->b_blocknr = bn;
+- bh_result->b_bdev = pbmap.pbm_target->pbr_bdev;
++ bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
+ set_buffer_mapped(bh_result);
+ }
+- if (pbmap.pbm_flags & PBMF_UNWRITTEN) {
++ if (iomap.iomap_flags & IOMAP_UNWRITTEN) {
+ if (create) {
+ if (direct)
+ bh_result->b_private = inode;
+@@ -902,29 +900,32 @@
+ }
+ }
+
++ /* If this is a realtime file, data might be on a new device */
++ bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
++
+ /* If we previously allocated a block out beyond eof and
+ * we are now coming back to use it then we will need to
+ * flag it as new even if it has a disk address.
+ */
+ if (create &&
+ ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
+- (offset >= i_size_read(inode)) || (pbmap.pbm_flags & PBMF_NEW))) {
++ (offset >= i_size_read(inode)) || (iomap.iomap_flags & IOMAP_NEW))) {
+ set_buffer_new(bh_result);
+ }
+
+- if (pbmap.pbm_flags & PBMF_DELAY) {
++ if (iomap.iomap_flags & IOMAP_DELAY) {
+ if (unlikely(direct))
+ BUG();
+ if (create) {
+ set_buffer_mapped(bh_result);
+ set_buffer_uptodate(bh_result);
+ }
+- bh_result->b_bdev = pbmap.pbm_target->pbr_bdev;
++ bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
+ set_buffer_delay(bh_result);
+ }
+
+ if (blocks) {
+- size = (pbmap.pbm_bsize - pbmap.pbm_delta);
++ size = (iomap.iomap_bsize - iomap.iomap_delta);
+ bh_result->b_size = min_t(ssize_t, size, blocks << inode->i_blkbits);
+ }
+
+@@ -939,7 +940,7 @@
+ int create)
+ {
+ return linvfs_get_block_core(inode, iblock, 0, bh_result,
+- create, 0, BMAP_WRITE);
++ create, 0, BMAPI_WRITE);
+ }
+
+ STATIC int
+@@ -950,7 +951,7 @@
+ int create)
+ {
+ return linvfs_get_block_core(inode, iblock, 0, bh_result,
+- create, 0, BMAP_SYNC|BMAP_WRITE);
++ create, 0, BMAPI_SYNC|BMAPI_WRITE);
+ }
+
+ STATIC int
+@@ -962,7 +963,7 @@
+ int create)
+ {
+ return linvfs_get_block_core(inode, iblock, max_blocks, bh_result,
+- create, 1, BMAP_WRITE|BMAP_DIRECT);
++ create, 1, BMAPI_WRITE|BMAPI_DIRECT);
+ }
+
+ STATIC int
+@@ -976,15 +977,15 @@
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+ vnode_t *vp = LINVFS_GET_VP(inode);
+- page_buf_bmap_t pbmap;
++ xfs_iomap_t iomap;
+ int maps = 1;
+ int error;
+
+- VOP_BMAP(vp, offset, 0, BMAP_DEVICE, &pbmap, &maps, error);
++ VOP_BMAP(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps, error);
+ if (error)
+ return -error;
+
+- return blockdev_direct_IO(rw, iocb, inode, pbmap.pbm_target->pbr_bdev,
++ return blockdev_direct_IO(rw, iocb, inode, iomap.iomap_target->pbr_bdev,
+ iov, offset, nr_segs,
+ linvfs_get_blocks_direct,
+ linvfs_unwritten_convert_direct);
+diff -urN linux.org/fs/xfs/linux/xfs_globals.c linux/fs/xfs/linux/xfs_globals.c
+--- linux.org/fs/xfs/linux/xfs_globals.c 2003-12-31 05:47:44.000000000 +0100
++++ linux/fs/xfs/linux/xfs_globals.c 2004-01-02 04:21:43.000000000 +0100
+@@ -36,9 +36,57 @@
+ */
+
+ #include "xfs.h"
++
++#include "xfs_fs.h"
++#include "xfs_buf.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_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.
+@@ -69,10 +117,34 @@
+ */
+ cred_t sys_cred_val, *sys_cred = &sys_cred_val;
+
+-/* Export XFS symbols used by xfsidbg */
++/*
++ * 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
++
++/*
++ * 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.org/fs/xfs/linux/xfs_ioctl.c linux/fs/xfs/linux/xfs_ioctl.c
+--- linux.org/fs/xfs/linux/xfs_ioctl.c 2003-12-31 05:48:05.000000000 +0100
++++ linux/fs/xfs/linux/xfs_ioctl.c 2004-01-02 04:21:43.000000000 +0100
+@@ -943,7 +943,7 @@
+ bulkreq.ubuffer, &done);
+ } else {
+ error = xfs_bulkstat(mp, NULL, &inlast, &count,
+- (bulkstat_one_pf)xfs_bulkstat_one,
++ (bulkstat_one_pf)xfs_bulkstat_one, NULL,
+ sizeof(xfs_bstat_t), bulkreq.ubuffer,
+ BULKSTAT_FG_QUICK, &done);
+ }
+diff -urN linux.org/fs/xfs/linux/xfs_iomap.c linux/fs/xfs/linux/xfs_iomap.c
+--- linux.org/fs/xfs/linux/xfs_iomap.c 2003-12-31 05:47:27.000000000 +0100
++++ linux/fs/xfs/linux/xfs_iomap.c 2004-01-02 04:21:43.000000000 +0100
+@@ -67,6 +67,7 @@
+ #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)
+@@ -74,14 +75,14 @@
+ #define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP
+
+ STATIC int
+-_xfs_imap_to_bmap(
++xfs_imap_to_bmap(
+ xfs_iocore_t *io,
+ xfs_off_t offset,
+- int new,
+ xfs_bmbt_irec_t *imap,
+- page_buf_bmap_t *pbmapp,
++ xfs_iomap_t *iomapp,
+ int imaps, /* Number of imap entries */
+- int pbmaps) /* Number of pbmap entries */
++ int iomaps, /* Number of iomap entries */
++ int flags)
+ {
+ xfs_mount_t *mp;
+ xfs_fsize_t nisize;
+@@ -93,35 +94,32 @@
+ if (io->io_new_size > nisize)
+ nisize = io->io_new_size;
+
+- for (pbm = 0; imaps && pbm < pbmaps; imaps--, pbmapp++, imap++, pbm++) {
+- pbmapp->pbm_target = io->io_flags & XFS_IOCORE_RT ?
++ 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;
+- pbmapp->pbm_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
+- pbmapp->pbm_delta = offset - pbmapp->pbm_offset;
+- pbmapp->pbm_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
+- pbmapp->pbm_flags = 0;
++ 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) {
+- pbmapp->pbm_bn = PAGE_BUF_DADDR_NULL;
+- pbmapp->pbm_flags = PBMF_HOLE;
++ iomapp->iomap_bn = IOMAP_DADDR_NULL;
++ iomapp->iomap_flags = IOMAP_HOLE;
+ } else if (start_block == DELAYSTARTBLOCK) {
+- pbmapp->pbm_bn = PAGE_BUF_DADDR_NULL;
+- pbmapp->pbm_flags = PBMF_DELAY;
++ iomapp->iomap_bn = IOMAP_DADDR_NULL;
++ iomapp->iomap_flags = IOMAP_DELAY;
+ } else {
+- pbmapp->pbm_bn = XFS_FSB_TO_DB_IO(io, start_block);
++ iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
+ if (ISUNWRITTEN(imap))
+- pbmapp->pbm_flags |= PBMF_UNWRITTEN;
++ iomapp->iomap_flags |= IOMAP_UNWRITTEN;
+ }
+
+- if ((pbmapp->pbm_offset + pbmapp->pbm_bsize) >= nisize) {
+- pbmapp->pbm_flags |= PBMF_EOF;
++ if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) {
++ iomapp->iomap_flags |= IOMAP_EOF;
+ }
+
+- if (new)
+- pbmapp->pbm_flags |= PBMF_NEW;
+-
+- offset += pbmapp->pbm_bsize - pbmapp->pbm_delta;
++ offset += iomapp->iomap_bsize - iomapp->iomap_delta;
+ }
+ return pbm; /* Return the number filled */
+ }
+@@ -132,54 +130,54 @@
+ xfs_off_t offset,
+ ssize_t count,
+ int flags,
+- page_buf_bmap_t *pbmapp,
+- int *npbmaps)
++ xfs_iomap_t *iomapp,
++ int *niomaps)
+ {
+ xfs_mount_t *mp = io->io_mount;
+ xfs_fileoff_t offset_fsb, end_fsb;
+ int error = 0;
+- int new = 0;
+ int lockmode = 0;
+ xfs_bmbt_irec_t imap;
+ int nimaps = 1;
+- int bmap_flags = 0;
++ int bmapi_flags = 0;
++ int iomap_flags = 0;
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+- return -XFS_ERROR(EIO);
++ return XFS_ERROR(EIO);
+
+ switch (flags &
+- (BMAP_READ | BMAP_WRITE | BMAP_ALLOCATE |
+- BMAP_UNWRITTEN | BMAP_DEVICE)) {
+- case BMAP_READ:
++ (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
++ BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
++ case BMAPI_READ:
+ lockmode = XFS_LCK_MAP_SHARED(mp, io);
+- bmap_flags = XFS_BMAPI_ENTIRE;
+- if (flags & BMAP_IGNSTATE)
+- bmap_flags |= XFS_BMAPI_IGSTATE;
++ bmapi_flags = XFS_BMAPI_ENTIRE;
++ if (flags & BMAPI_IGNSTATE)
++ bmapi_flags |= XFS_BMAPI_IGSTATE;
+ break;
+- case BMAP_WRITE:
++ case BMAPI_WRITE:
+ lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
+- bmap_flags = 0;
++ bmapi_flags = 0;
+ XFS_ILOCK(mp, io, lockmode);
+ break;
+- case BMAP_ALLOCATE:
++ case BMAPI_ALLOCATE:
+ lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
+- bmap_flags = XFS_BMAPI_ENTIRE;
++ bmapi_flags = XFS_BMAPI_ENTIRE;
+ /* Attempt non-blocking lock */
+- if (flags & BMAP_TRYLOCK) {
++ if (flags & BMAPI_TRYLOCK) {
+ if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))
+ return XFS_ERROR(EAGAIN);
+ } else {
+ XFS_ILOCK(mp, io, lockmode);
+ }
+ break;
+- case BMAP_UNWRITTEN:
++ case BMAPI_UNWRITTEN:
+ goto phase2;
+- case BMAP_DEVICE:
++ case BMAPI_DEVICE:
+ lockmode = XFS_LCK_MAP_SHARED(mp, io);
+- pbmapp->pbm_target = io->io_flags & XFS_IOCORE_RT ?
++ iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
+ mp->m_rtdev_targp : mp->m_ddev_targp;
+ error = 0;
+- *npbmaps = 1;
++ *niomaps = 1;
+ goto out;
+ default:
+ BUG();
+@@ -192,30 +190,30 @@
+ offset_fsb = XFS_B_TO_FSBT(mp, offset);
+
+ error = XFS_BMAPI(mp, NULL, io, offset_fsb,
+- (xfs_filblks_t)(end_fsb - offset_fsb) ,
+- bmap_flags, NULL, 0, &imap,
++ (xfs_filblks_t)(end_fsb - offset_fsb),
++ bmapi_flags, NULL, 0, &imap,
+ &nimaps, NULL);
+
+ if (error)
+ goto out;
+
+ phase2:
+- switch (flags & (BMAP_WRITE|BMAP_ALLOCATE|BMAP_UNWRITTEN)) {
+- case BMAP_WRITE:
++ 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 & (BMAP_DIRECT|BMAP_MMAP)) {
++ 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);
+ }
+- new = 1;
++ iomap_flags = IOMAP_NEW;
+ break;
+- case BMAP_ALLOCATE:
++ case BMAPI_ALLOCATE:
+ /* If we found an extent, return it */
+ XFS_IUNLOCK(mp, io, lockmode);
+ lockmode = 0;
+@@ -225,7 +223,7 @@
+
+ error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
+ break;
+- case BMAP_UNWRITTEN:
++ case BMAPI_UNWRITTEN:
+ lockmode = 0;
+ error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count);
+ nimaps = 0;
+@@ -233,10 +231,10 @@
+ }
+
+ if (nimaps) {
+- *npbmaps = _xfs_imap_to_bmap(io, offset, new, &imap,
+- pbmapp, nimaps, *npbmaps);
+- } else if (npbmaps) {
+- *npbmaps = 0;
++ *niomaps = xfs_imap_to_bmap(io, offset, &imap,
++ iomapp, nimaps, *niomaps, iomap_flags);
++ } else if (niomaps) {
++ *niomaps = 0;
+ }
+
+ out:
+@@ -251,29 +249,25 @@
+ int *fsynced,
+ int *ioflags)
+ {
+- vnode_t *vp = XFS_ITOV(ip);
+-
+ switch (*fsynced) {
+ case 0:
+ if (ip->i_delayed_blks) {
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+- filemap_fdatawrite(LINVFS_GET_IP(vp)->i_mapping);
++ xfs_flush_inode(ip);
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ *fsynced = 1;
+ } else {
+- *ioflags |= BMAP_SYNC;
++ *ioflags |= BMAPI_SYNC;
+ *fsynced = 2;
+ }
+ return 0;
+ case 1:
+ *fsynced = 2;
+- *ioflags |= BMAP_SYNC;
++ *ioflags |= BMAPI_SYNC;
+ return 0;
+ case 2:
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+- sync_blockdev(vp->v_vfsp->vfs_super->s_bdev);
+- xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
+- XFS_LOG_FORCE|XFS_LOG_SYNC);
++ xfs_flush_device(ip);
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ *fsynced = 3;
+ return 0;
+@@ -400,7 +394,7 @@
+ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+ xfs_trans_ihold(tp, ip);
+
+- if (!(flags & BMAP_MMAP) && (offset < ip->i_d.di_size || rt))
++ if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt))
+ bmapi_flag |= XFS_BMAPI_PREALLOC;
+
+ /*
+@@ -499,7 +493,7 @@
+ * We don't bother with this for sync writes, because we need
+ * to minimize the amount we write for good performance.
+ */
+- if (!(ioflag & BMAP_SYNC) && ((offset + count) > ip->i_d.di_size)) {
++ if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) {
+ xfs_off_t aligned_offset;
+ unsigned int iosize;
+ xfs_fileoff_t ioalign;
+diff -urN linux.org/fs/xfs/linux/xfs_iops.c linux/fs/xfs/linux/xfs_iops.c
+--- linux.org/fs/xfs/linux/xfs_iops.c 2003-12-31 05:46:55.000000000 +0100
++++ linux/fs/xfs/linux/xfs_iops.c 2004-01-02 04:21:43.000000000 +0100
+@@ -110,7 +110,7 @@
+ vattr_t va;
+ vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir);
+ xfs_acl_t *default_acl = NULL;
+- xattr_exists_t test_default_acl = _ACL_DEFAULT_EXISTS;
++ attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
+ int error;
+
+ /*
+@@ -552,61 +552,6 @@
+ block_truncate_page(inode->i_mapping, inode->i_size, linvfs_get_block);
+ }
+
+-
+-
+-/*
+- * Extended attributes interfaces
+- */
+-
+-#define SYSTEM_NAME "system." /* VFS shared names/values */
+-#define ROOT_NAME "trusted." /* root's own names/values */
+-#define USER_NAME "user." /* user's own names/values */
+-STATIC xattr_namespace_t xfs_namespace_array[] = {
+- { .name= SYSTEM_NAME, .namelen= sizeof(SYSTEM_NAME)-1,.exists= NULL },
+- { .name= ROOT_NAME, .namelen= sizeof(ROOT_NAME)-1, .exists= NULL },
+- { .name= USER_NAME, .namelen= sizeof(USER_NAME)-1, .exists= NULL },
+- { .name= NULL }
+-};
+-xattr_namespace_t *xfs_namespaces = &xfs_namespace_array[0];
+-
+-#define POSIXACL_ACCESS "posix_acl_access"
+-#define POSIXACL_ACCESS_SIZE (sizeof(POSIXACL_ACCESS)-1)
+-#define POSIXACL_DEFAULT "posix_acl_default"
+-#define POSIXACL_DEFAULT_SIZE (sizeof(POSIXACL_DEFAULT)-1)
+-#define POSIXCAP "posix_capabilities"
+-#define POSIXCAP_SIZE (sizeof(POSIXCAP)-1)
+-#define POSIXMAC "posix_mac"
+-#define POSIXMAC_SIZE (sizeof(POSIXMAC)-1)
+-STATIC xattr_namespace_t sys_namespace_array[] = {
+- { .name= POSIXACL_ACCESS,
+- .namelen= POSIXACL_ACCESS_SIZE, .exists= _ACL_ACCESS_EXISTS },
+- { .name= POSIXACL_DEFAULT,
+- .namelen= POSIXACL_DEFAULT_SIZE, .exists= _ACL_DEFAULT_EXISTS },
+- { .name= POSIXCAP,
+- .namelen= POSIXCAP_SIZE, .exists= _CAP_EXISTS },
+- { .name= POSIXMAC,
+- .namelen= POSIXMAC_SIZE, .exists= _MAC_EXISTS },
+- { .name= NULL }
+-};
+-
+-/*
+- * Some checks to prevent people abusing EAs to get over quota:
+- * - Don't allow modifying user EAs on devices/symlinks;
+- * - Don't allow modifying user EAs if sticky bit set;
+- */
+-STATIC int
+-capable_user_xattr(
+- struct inode *inode)
+-{
+- if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
+- !capable(CAP_SYS_ADMIN))
+- return 0;
+- if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
+- (current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+- return 0;
+- return 1;
+-}
+-
+ STATIC int
+ linvfs_setxattr(
+ struct dentry *dentry,
+@@ -615,59 +560,27 @@
+ size_t size,
+ int flags)
+ {
+- struct inode *inode = dentry->d_inode;
+- vnode_t *vp = LINVFS_GET_VP(inode);
+- char *p = (char *)name;
++ vnode_t *vp = LINVFS_GET_VP(dentry->d_inode);
++ char *attr = (char *)name;
++ attrnames_t *namesp;
+ int xflags = 0;
+ int error;
+
+- if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
+- xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
+- error = -EINVAL;
+- if (flags & XATTR_CREATE)
+- return error;
+- error = -EOPNOTSUPP;
+- p += xfs_namespaces[SYSTEM_NAMES].namelen;
+- if (strcmp(p, POSIXACL_ACCESS) == 0)
+- error = xfs_acl_vset(vp, (void *) data, size,
+- _ACL_TYPE_ACCESS);
+- else if (strcmp(p, POSIXACL_DEFAULT) == 0)
+- error = xfs_acl_vset(vp, (void *) data, size,
+- _ACL_TYPE_DEFAULT);
+- else if (strcmp(p, POSIXCAP) == 0)
+- error = xfs_cap_vset(vp, (void *) data, size);
+- if (!error)
+- error = vn_revalidate(vp);
++ namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
++ if (!namesp)
++ return -EOPNOTSUPP;
++ attr += namesp->attr_namelen;
++ error = namesp->attr_capable(vp, NULL);
++ if (error)
+ return error;
+- }
+-
+- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+- return -EPERM;
+
+ /* Convert Linux syscall to XFS internal ATTR flags */
+ if (flags & XATTR_CREATE)
+ xflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE)
+ xflags |= ATTR_REPLACE;
+-
+- if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
+- xfs_namespaces[ROOT_NAMES].namelen) == 0) {
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+- xflags |= ATTR_ROOT;
+- p += xfs_namespaces[ROOT_NAMES].namelen;
+- VOP_ATTR_SET(vp, p, (void *) data, size, xflags, NULL, error);
+- return -error;
+- }
+- if (strncmp(name, xfs_namespaces[USER_NAMES].name,
+- xfs_namespaces[USER_NAMES].namelen) == 0) {
+- if (!capable_user_xattr(inode))
+- return -EPERM;
+- p += xfs_namespaces[USER_NAMES].namelen;
+- VOP_ATTR_SET(vp, p, (void *) data, size, xflags, NULL, error);
+- return -error;
+- }
+- return -EOPNOTSUPP;
++ xflags |= namesp->attr_flag;
++ return namesp->attr_set(vp, attr, (void *)data, size, xflags);
+ }
+
+ STATIC ssize_t
+@@ -677,53 +590,27 @@
+ void *data,
+ size_t size)
+ {
+- struct inode *inode = dentry->d_inode;
+- vnode_t *vp = LINVFS_GET_VP(inode);
+- char *p = (char *)name;
++ vnode_t *vp = LINVFS_GET_VP(dentry->d_inode);
++ char *attr = (char *)name;
++ attrnames_t *namesp;
+ int xflags = 0;
+ ssize_t error;
+
+- if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
+- xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
+- error = -EOPNOTSUPP;
+- p += xfs_namespaces[SYSTEM_NAMES].namelen;
+- if (strcmp(p, POSIXACL_ACCESS) == 0)
+- error = xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
+- else if (strcmp(p, POSIXACL_DEFAULT) == 0)
+- error = xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
+- else if (strcmp(p, POSIXCAP) == 0)
+- error = xfs_cap_vget(vp, data, size);
++ namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
++ if (!namesp)
++ return -EOPNOTSUPP;
++ attr += namesp->attr_namelen;
++ error = namesp->attr_capable(vp, NULL);
++ if (error)
+ return error;
+- }
+
+ /* Convert Linux syscall to XFS internal ATTR flags */
+ if (!size) {
+ xflags |= ATTR_KERNOVAL;
+ data = NULL;
+ }
+-
+- if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
+- xfs_namespaces[ROOT_NAMES].namelen) == 0) {
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+- xflags |= ATTR_ROOT;
+- p += xfs_namespaces[ROOT_NAMES].namelen;
+- VOP_ATTR_GET(vp, p, data, (int *)&size, xflags, NULL, error);
+- if (!error)
+- error = -size;
+- return -error;
+- }
+- if (strncmp(name, xfs_namespaces[USER_NAMES].name,
+- xfs_namespaces[USER_NAMES].namelen) == 0) {
+- p += xfs_namespaces[USER_NAMES].namelen;
+- if (!capable_user_xattr(inode))
+- return -EPERM;
+- VOP_ATTR_GET(vp, p, data, (int *)&size, xflags, NULL, error);
+- if (!error)
+- error = -size;
+- return -error;
+- }
+- return -EOPNOTSUPP;
++ xflags |= namesp->attr_flag;
++ return namesp->attr_get(vp, attr, (void *)data, size, xflags);
+ }
+
+ STATIC ssize_t
+@@ -732,40 +619,18 @@
+ char *data,
+ size_t size)
+ {
+- attrlist_cursor_kern_t cursor;
+- xattr_namespace_t *sys;
+ vnode_t *vp = LINVFS_GET_VP(dentry->d_inode);
+- char *k = data;
+- int xflags = ATTR_KERNAMELS;
+- int result = 0;
+- ssize_t error;
++ int error, xflags = ATTR_KERNAMELS;
++ ssize_t result;
+
+ if (!size)
+ xflags |= ATTR_KERNOVAL;
+ if (capable(CAP_SYS_ADMIN))
+ xflags |= ATTR_KERNFULLS;
+
+- memset(&cursor, 0, sizeof(cursor));
+- VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error);
+- if (error > 0)
+- return -error;
+- result += -error;
+-
+- k += result; /* advance start of our buffer */
+- for (sys = &sys_namespace_array[0]; sys->name != NULL; sys++) {
+- if (sys->exists == NULL || !sys->exists(vp))
+- continue;
+- result += xfs_namespaces[SYSTEM_NAMES].namelen;
+- result += sys->namelen + 1;
+- if (size) {
+- if (result > size)
+- return -ERANGE;
+- strcpy(k, xfs_namespaces[SYSTEM_NAMES].name);
+- k += xfs_namespaces[SYSTEM_NAMES].namelen;
+- strcpy(k, sys->name);
+- k += sys->namelen + 1;
+- }
+- }
++ error = attr_generic_list(vp, data, size, xflags, &result);
++ if (error < 0)
++ return error;
+ return result;
+ }
+
+@@ -774,51 +639,25 @@
+ struct dentry *dentry,
+ const char *name)
+ {
+- struct inode *inode = dentry->d_inode;
+- vnode_t *vp = LINVFS_GET_VP(inode);
+- char *p = (char *)name;
++ vnode_t *vp = LINVFS_GET_VP(dentry->d_inode);
++ char *attr = (char *)name;
++ attrnames_t *namesp;
+ int xflags = 0;
+ int error;
+
+- if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
+- xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
+- error = -EOPNOTSUPP;
+- p += xfs_namespaces[SYSTEM_NAMES].namelen;
+- if (strcmp(p, POSIXACL_ACCESS) == 0)
+- error = xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
+- else if (strcmp(p, POSIXACL_DEFAULT) == 0)
+- error = xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
+- else if (strcmp(p, POSIXCAP) == 0)
+- error = xfs_cap_vremove(vp);
++ namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
++ if (!namesp)
++ return -EOPNOTSUPP;
++ attr += namesp->attr_namelen;
++ error = namesp->attr_capable(vp, NULL);
++ if (error)
+ return error;
+- }
+-
+- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+- return -EPERM;
+-
+- if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
+- xfs_namespaces[ROOT_NAMES].namelen) == 0) {
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+- xflags |= ATTR_ROOT;
+- p += xfs_namespaces[ROOT_NAMES].namelen;
+- VOP_ATTR_REMOVE(vp, p, xflags, NULL, error);
+- return -error;
+- }
+- if (strncmp(name, xfs_namespaces[USER_NAMES].name,
+- xfs_namespaces[USER_NAMES].namelen) == 0) {
+- p += xfs_namespaces[USER_NAMES].namelen;
+- if (!capable_user_xattr(inode))
+- return -EPERM;
+- VOP_ATTR_REMOVE(vp, p, xflags, NULL, error);
+- return -error;
+- }
+- return -EOPNOTSUPP;
++ xflags |= namesp->attr_flag;
++ return namesp->attr_remove(vp, attr, xflags);
+ }
+
+
+-struct inode_operations linvfs_file_inode_operations =
+-{
++struct inode_operations linvfs_file_inode_operations = {
+ .permission = linvfs_permission,
+ .truncate = linvfs_truncate,
+ .getattr = linvfs_getattr,
+@@ -829,8 +668,7 @@
+ .removexattr = linvfs_removexattr,
+ };
+
+-struct inode_operations linvfs_dir_inode_operations =
+-{
++struct inode_operations linvfs_dir_inode_operations = {
+ .create = linvfs_create,
+ .lookup = linvfs_lookup,
+ .link = linvfs_link,
+@@ -849,8 +687,7 @@
+ .removexattr = linvfs_removexattr,
+ };
+
+-struct inode_operations linvfs_symlink_inode_operations =
+-{
++struct inode_operations linvfs_symlink_inode_operations = {
+ .readlink = linvfs_readlink,
+ .follow_link = linvfs_follow_link,
+ .permission = linvfs_permission,
+diff -urN linux.org/fs/xfs/linux/xfs_iops.h linux/fs/xfs/linux/xfs_iops.h
+--- linux.org/fs/xfs/linux/xfs_iops.h 2003-12-31 05:47:32.000000000 +0100
++++ linux/fs/xfs/linux/xfs_iops.h 2004-01-02 04:21:43.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -32,30 +32,6 @@
+ #ifndef __XFS_IOPS_H__
+ #define __XFS_IOPS_H__
+
+-/*
+- * Extended system attributes.
+- * So far only POSIX ACLs are supported, but this will need to
+- * grow in time (capabilities, mandatory access control, etc).
+- */
+-#define XFS_SYSTEM_NAMESPACE SYSTEM_POSIXACL
+-
+-/*
+- * Define a table of the namespaces XFS supports
+- */
+-typedef int (*xattr_exists_t)(vnode_t *);
+-
+-typedef struct xattr_namespace {
+- char *name;
+- unsigned int namelen;
+- xattr_exists_t exists;
+-} xattr_namespace_t;
+-
+-#define SYSTEM_NAMES 0
+-#define ROOT_NAMES 1
+-#define USER_NAMES 2
+-extern struct xattr_namespace *xfs_namespaces;
+-
+-
+ extern struct inode_operations linvfs_file_inode_operations;
+ extern struct inode_operations linvfs_dir_inode_operations;
+ extern struct inode_operations linvfs_symlink_inode_operations;
+@@ -69,4 +45,7 @@
+ extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+ extern void linvfs_unwritten_done(struct buffer_head *, int);
+
++extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
++ int, unsigned int, unsigned long);
++
+ #endif /* __XFS_IOPS_H__ */
+diff -urN linux.org/fs/xfs/linux/xfs_linux.h linux/fs/xfs/linux/xfs_linux.h
+--- linux.org/fs/xfs/linux/xfs_linux.h 2003-12-31 05:46:20.000000000 +0100
++++ linux/fs/xfs/linux/xfs_linux.h 2004-01-02 04:21:43.000000000 +0100
+@@ -47,6 +47,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/init.h>
+ #include <linux/proc_fs.h>
++#include <linux/version.h>
+
+ #include <asm/page.h>
+ #include <asm/div64.h>
+@@ -69,9 +70,11 @@
+
+ #include <pagebuf/page_buf.h>
+
+-#ifndef STATIC
+-#define STATIC static
+-#endif
++/*
++ * Feature macros (disable/enable)
++ */
++#undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */
++#define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */
+
+ /*
+ * State flag for unwritten extent buffers.
+@@ -100,6 +103,11 @@
+ #define xfs_inherit_nodump xfs_params.inherit_nodump.val
+ #define xfs_inherit_noatime xfs_params.inherit_noatim.val
+
++#define current_cpu() smp_processor_id()
++#define current_pid() (current->pid)
++#define current_fsuid(cred) (current->fsuid)
++#define current_fsgid(cred) (current->fsgid)
++
+ #define NBPP PAGE_SIZE
+ #define DPPSHFT (PAGE_SHIFT - 9)
+ #define NDPP (1 << (PAGE_SHIFT - 9))
+@@ -200,6 +208,11 @@
+ #define howmany(x, y) (((x)+((y)-1))/(y))
+ #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+
++static inline void xfs_stack_trace(void)
++{
++ dump_stack();
++}
++
+ /* Move the kernel do_div definition off to one side */
+
+ #if defined __i386__
+diff -urN linux.org/fs/xfs/linux/xfs_lrw.c linux/fs/xfs/linux/xfs_lrw.c
+--- linux.org/fs/xfs/linux/xfs_lrw.c 2003-12-31 05:46:18.000000000 +0100
++++ linux/fs/xfs/linux/xfs_lrw.c 2004-01-02 04:21:43.000000000 +0100
+@@ -71,10 +71,76 @@
+ #include "xfs_inode_item.h"
+ #include "xfs_buf_item.h"
+ #include "xfs_utils.h"
++#include "xfs_iomap.h"
+
+ #include <linux/capability.h>
+
+
++#if defined(XFS_RW_TRACE)
++void
++xfs_rw_enter_trace(
++ int tag,
++ xfs_iocore_t *io,
++ const struct iovec *iovp,
++ size_t segs,
++ loff_t offset,
++ int ioflags)
++{
++ xfs_inode_t *ip = XFS_IO_INODE(io);
++
++ if (ip->i_rwtrace == NULL)
++ return;
++ ktrace_enter(ip->i_rwtrace,
++ (void *)(unsigned long)tag,
++ (void *)ip,
++ (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
++ (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
++ (void *)(__psint_t)iovp,
++ (void *)((unsigned long)segs),
++ (void *)((unsigned long)((offset >> 32) & 0xffffffff)),
++ (void *)((unsigned long)(offset & 0xffffffff)),
++ (void *)((unsigned long)ioflags),
++ (void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
++ (void *)((unsigned long)(io->io_new_size & 0xffffffff)),
++ (void *)NULL,
++ (void *)NULL,
++ (void *)NULL,
++ (void *)NULL,
++ (void *)NULL);
++}
++
++void
++xfs_inval_cached_trace(
++ xfs_iocore_t *io,
++ xfs_off_t offset,
++ xfs_off_t len,
++ xfs_off_t first,
++ xfs_off_t last)
++{
++ xfs_inode_t *ip = XFS_IO_INODE(io);
++
++ if (ip->i_rwtrace == NULL)
++ return;
++ ktrace_enter(ip->i_rwtrace,
++ (void *)(__psint_t)XFS_INVAL_CACHED,
++ (void *)ip,
++ (void *)((unsigned long)((offset >> 32) & 0xffffffff)),
++ (void *)((unsigned long)(offset & 0xffffffff)),
++ (void *)((unsigned long)((len >> 32) & 0xffffffff)),
++ (void *)((unsigned long)(len & 0xffffffff)),
++ (void *)((unsigned long)((first >> 32) & 0xffffffff)),
++ (void *)((unsigned long)(first & 0xffffffff)),
++ (void *)((unsigned long)((last >> 32) & 0xffffffff)),
++ (void *)((unsigned long)(last & 0xffffffff)),
++ (void *)NULL,
++ (void *)NULL,
++ (void *)NULL,
++ (void *)NULL,
++ (void *)NULL,
++ (void *)NULL);
++}
++#endif
++
+ /*
+ * xfs_iozero
+ *
+@@ -142,6 +208,59 @@
+ return (-status);
+ }
+
++/*
++ * xfs_inval_cached_pages
++ *
++ * This routine is responsible for keeping direct I/O and buffered I/O
++ * somewhat coherent. From here we make sure that we're at least
++ * temporarily holding the inode I/O lock exclusively and then call
++ * the page cache to flush and invalidate any cached pages. If there
++ * are no cached pages this routine will be very quick.
++ */
++void
++xfs_inval_cached_pages(
++ vnode_t *vp,
++ xfs_iocore_t *io,
++ xfs_off_t offset,
++ int write,
++ int relock)
++{
++ xfs_mount_t *mp;
++
++ if (!VN_CACHED(vp)) {
++ return;
++ }
++
++ mp = io->io_mount;
++
++ /*
++ * We need to get the I/O lock exclusively in order
++ * to safely invalidate pages and mappings.
++ */
++ if (relock) {
++ XFS_IUNLOCK(mp, io, XFS_IOLOCK_SHARED);
++ XFS_ILOCK(mp, io, XFS_IOLOCK_EXCL);
++ }
++
++ /* Writing beyond EOF creates a hole that must be zeroed */
++ if (write && (offset > XFS_SIZE(mp, io))) {
++ xfs_fsize_t isize;
++
++ XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
++ isize = XFS_SIZE(mp, io);
++ if (offset > isize) {
++ xfs_zero_eof(vp, io, offset, isize, offset);
++ }
++ XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
++ }
++
++ xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
++ VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
++ if (relock) {
++ XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
++ }
++}
++
+ ssize_t /* bytes read, or (-) error */
+ xfs_read(
+ bhv_desc_t *bdp,
+@@ -211,7 +330,8 @@
+ * does not really happen here, but is scheduled
+ * later?
+ */
+- xfs_ilock(ip, XFS_IOLOCK_SHARED);
++ if (!(ioflags & IO_ISLOCKED))
++ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+ if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
+ !(ioflags & IO_INVIS)) {
+@@ -221,13 +341,15 @@
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, size,
+ FILP_DELAY_FLAG(file), &locktype);
+ if (error) {
+- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
++ if (!(ioflags & IO_ISLOCKED))
++ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return -error;
+ }
+ }
+
+ ret = __generic_file_aio_read(iocb, iovp, segs, offset);
+- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
++ if (!(ioflags & IO_ISLOCKED))
++ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+
+ if (ret > 0)
+ XFS_STATS_ADD(xs_read_bytes, ret);
+@@ -272,7 +394,8 @@
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return -EIO;
+
+- xfs_ilock(ip, XFS_IOLOCK_SHARED);
++ if (!(ioflags & IO_ISLOCKED))
++ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+ if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
+ (!(ioflags & IO_INVIS))) {
+@@ -282,12 +405,14 @@
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count,
+ FILP_DELAY_FLAG(filp), &locktype);
+ if (error) {
+- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
++ if (!(ioflags & IO_ISLOCKED))
++ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return -error;
+ }
+ }
+ ret = generic_file_sendfile(filp, offset, count, actor, target);
+- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
++ if (!(ioflags & IO_ISLOCKED))
++ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+
+ XFS_STATS_ADD(xs_read_bytes, ret);
+ xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
+@@ -584,6 +709,9 @@
+ locktype = VRWLOCK_WRITE;
+ }
+
++ if (ioflags & IO_ISLOCKED)
++ iolock = 0;
++
+ xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
+
+ isize = xip->i_d.di_size;
+@@ -616,7 +744,7 @@
+ *offset, size,
+ FILP_DELAY_FLAG(file), &locktype);
+ if (error) {
+- xfs_iunlock(xip, iolock);
++ if (iolock) xfs_iunlock(xip, iolock);
+ return -error;
+ }
+ xfs_ilock(xip, XFS_ILOCK_EXCL);
+@@ -684,9 +812,13 @@
+
+ retry:
+ if (ioflags & IO_ISDIRECT) {
+- xfs_inval_cached_pages(vp, &xip->i_iocore, *offset, 1, 1);
++ xfs_inval_cached_pages(vp, io, *offset, 1, 1);
++ xfs_rw_enter_trace(XFS_DIOWR_ENTER,
++ io, iovp, segs, *offset, ioflags);
++ } else {
++ xfs_rw_enter_trace(XFS_WRITE_ENTER,
++ io, iovp, segs, *offset, ioflags);
+ }
+-
+ ret = generic_file_aio_write_nolock(iocb, iovp, segs, offset);
+
+ if ((ret == -ENOSPC) &&
+@@ -702,7 +834,6 @@
+ xfs_rwlock(bdp, locktype);
+ *offset = xip->i_d.di_size;
+ goto retry;
+-
+ }
+
+ if (*offset > xip->i_d.di_size) {
+@@ -806,7 +937,9 @@
+ }
+ } /* (ioflags & O_SYNC) */
+
+- xfs_rwunlock(bdp, locktype);
++ if (iolock)
++ xfs_rwunlock(bdp, locktype);
++
+ return(ret);
+ }
+
+@@ -846,8 +979,8 @@
+ xfs_off_t offset,
+ ssize_t count,
+ int flags,
+- page_buf_bmap_t *pbmapp,
+- int *npbmaps)
++ xfs_iomap_t *iomapp,
++ int *niomaps)
+ {
+ xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ xfs_iocore_t *io = &ip->i_iocore;
+@@ -856,7 +989,7 @@
+ ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
+ ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
+
+- return xfs_iomap(io, offset, count, flags, pbmapp, npbmaps);
++ return xfs_iomap(io, offset, count, flags, iomapp, niomaps);
+ }
+
+ /*
+diff -urN linux.org/fs/xfs/linux/xfs_lrw.h linux/fs/xfs/linux/xfs_lrw.h
+--- linux.org/fs/xfs/linux/xfs_lrw.h 2003-12-31 05:46:25.000000000 +0100
++++ linux/fs/xfs/linux/xfs_lrw.h 2004-01-02 04:21:43.000000000 +0100
+@@ -39,21 +39,59 @@
+ struct xfs_inode;
+ struct xfs_bmbt_irec;
+ struct page_buf_s;
+-struct page_buf_bmap_s;
++struct xfs_iomap;
+
++#if defined(XFS_RW_TRACE)
++/*
++ * Defines for the trace mechanisms in xfs_lrw.c.
++ */
++#define XFS_RW_KTRACE_SIZE 64
++#define XFS_STRAT_KTRACE_SIZE 64
++#define XFS_STRAT_GTRACE_SIZE 512
++
++#define XFS_READ_ENTER 1
++#define XFS_WRITE_ENTER 2
+ #define XFS_IOMAP_READ_ENTER 3
++#define XFS_IOMAP_WRITE_ENTER 4
++#define XFS_IOMAP_READ_MAP 5
++#define XFS_IOMAP_WRITE_MAP 6
++#define XFS_IOMAP_WRITE_NOSPACE 7
++#define XFS_ITRUNC_START 8
++#define XFS_ITRUNC_FINISH1 9
++#define XFS_ITRUNC_FINISH2 10
++#define XFS_CTRUNC1 11
++#define XFS_CTRUNC2 12
++#define XFS_CTRUNC3 13
++#define XFS_CTRUNC4 14
++#define XFS_CTRUNC5 15
++#define XFS_CTRUNC6 16
++#define XFS_BUNMAPI 17
++#define XFS_INVAL_CACHED 18
++#define XFS_DIORD_ENTER 19
++#define XFS_DIOWR_ENTER 20
++extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
++ const struct iovec *, size_t, loff_t, int);
++extern void xfs_inval_cached_trace(struct xfs_iocore *,
++ xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
++#else
++#define xfs_rw_enter_trace(tag, io, iovec, segs, offset, ioflags)
++#define xfs_inval_cached_trace(io, offset, len, first, last)
++#endif
++
+ /*
+ * Maximum count of bmaps used by read and write paths.
+ */
+ #define XFS_MAX_RW_NBMAPS 4
+
+ extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
+- struct page_buf_bmap_s *, int *);
++ struct xfs_iomap *, int *);
+ extern int xfsbdstrat(struct xfs_mount *, struct page_buf_s *);
+ extern int xfs_bdstrat_cb(struct page_buf_s *);
+
+ extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
+ xfs_fsize_t, xfs_fsize_t);
++extern void xfs_inval_cached_pages(struct vnode *, struct xfs_iocore *,
++ xfs_off_t, int, int);
+ extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
+ const struct iovec *, unsigned int,
+ loff_t *, int, struct cred *);
+@@ -64,16 +102,6 @@
+ loff_t *, int, size_t, read_actor_t,
+ void *, struct cred *);
+
+-extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
+- struct page_buf_bmap_s *, int *);
+-extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t,
+- int, struct xfs_bmbt_irec *, int *, int);
+-extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t,
+- int, struct xfs_bmbt_irec *, int *);
+-extern int xfs_iomap_write_allocate(struct xfs_inode *,
+- struct xfs_bmbt_irec *, int *);
+-extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t);
+-
+ extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+
+ #define XFS_FSB_TO_DB_IO(io,fsb) \
+diff -urN linux.org/fs/xfs/linux/xfs_super.c linux/fs/xfs/linux/xfs_super.c
+--- linux.org/fs/xfs/linux/xfs_super.c 2003-12-31 05:48:23.000000000 +0100
++++ linux/fs/xfs/linux/xfs_super.c 2004-01-02 04:21:43.000000000 +0100
+@@ -120,7 +120,7 @@
+ */
+
+ #if BITS_PER_LONG == 32
+-# if defined(HAVE_SECTOR_T)
++# if defined(CONFIG_LBD)
+ ASSERT(sizeof(sector_t) == 8);
+ pagefactor = PAGE_CACHE_SIZE;
+ bitshift = BITS_PER_LONG;
+@@ -241,6 +241,36 @@
+ }
+ }
+
++struct inode *
++xfs_get_inode(
++ bhv_desc_t *bdp,
++ xfs_ino_t ino,
++ int flags)
++{
++ struct vfs *vfsp = bhvtovfs(bdp);
++
++ if (flags & IGET_NOALLOC)
++ return ilookup(vfsp->vfs_super, ino);
++ return iget_locked(vfsp->vfs_super, ino);
++}
++
++void
++xfs_flush_inode(
++ xfs_inode_t *ip)
++{
++ struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip));
++
++ filemap_fdatawrite(inode->i_mapping);
++}
++
++void
++xfs_flush_device(
++ xfs_inode_t *ip)
++{
++ sync_blockdev(XFS_ITOV(ip)->v_vfsp->vfs_super->s_bdev);
++ xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
++}
++
+ int
+ xfs_blkdev_get(
+ xfs_mount_t *mp,
+@@ -860,15 +890,16 @@
+ {
+ int error;
+ struct sysinfo si;
+- static char message[] __initdata =
+- KERN_INFO "SGI XFS " XFS_VERSION_STRING " with "
+- XFS_BUILD_OPTIONS " enabled\n";
++ static char message[] __initdata = KERN_INFO \
++ XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n";
+
+ printk(message);
+
+ si_meminfo(&si);
+ xfs_physmem = si.totalram;
+
++ ktrace_init(64);
++
+ error = init_inodecache();
+ if (error < 0)
+ goto undo_inodecache;
+@@ -907,12 +938,12 @@
+ vfs_exitdmapi();
+ pagebuf_terminate();
+ destroy_inodecache();
++ ktrace_uninit();
+ }
+
+ module_init(init_xfs_fs);
+ module_exit(exit_xfs_fs);
+
+ MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION(
+- "SGI XFS " XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled");
++MODULE_DESCRIPTION(XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled");
+ MODULE_LICENSE("GPL");
+diff -urN linux.org/fs/xfs/linux/xfs_super.h linux/fs/xfs/linux/xfs_super.h
+--- linux.org/fs/xfs/linux/xfs_super.h 2003-12-31 05:46:52.000000000 +0100
++++ linux/fs/xfs/linux/xfs_super.h 2004-01-02 04:21:43.000000000 +0100
+@@ -76,10 +76,10 @@
+ # define XFS_BIGFS_STRING
+ #endif
+
+-#ifdef CONFIG_XFS_VNODE_TRACING
+-# define XFS_VNTRACE_STRING "VN-trace, "
++#ifdef CONFIG_XFS_TRACE
++# define XFS_TRACE_STRING "tracing, "
+ #else
+-# define XFS_VNTRACE_STRING
++# define XFS_TRACE_STRING
+ #endif
+
+ #ifdef XFSDEBUG
+@@ -91,7 +91,7 @@
+ #define XFS_BUILD_OPTIONS XFS_ACL_STRING \
+ XFS_REALTIME_STRING \
+ XFS_BIGFS_STRING \
+- XFS_VNTRACE_STRING \
++ XFS_TRACE_STRING \
+ XFS_DBG_STRING /* DBG must be last */
+
+ #define LINVFS_GET_VFS(s) \
+@@ -99,14 +99,19 @@
+ #define LINVFS_SET_VFS(s, vfsp) \
+ ((s)->s_fs_info = vfsp)
+
++struct xfs_inode;
+ struct xfs_mount;
+ struct pb_target;
+ struct block_device;
+
+ extern __uint64_t xfs_max_file_offset(unsigned int);
+
++extern struct inode *xfs_get_inode(bhv_desc_t *, xfs_ino_t, int);
+ extern void xfs_initialize_vnode(bhv_desc_t *, vnode_t *, bhv_desc_t *, int);
+
++extern void xfs_flush_inode(struct xfs_inode *);
++extern void xfs_flush_device(struct xfs_inode *);
++
+ extern int xfs_blkdev_get(struct xfs_mount *, const char *,
+ struct block_device **);
+ extern void xfs_blkdev_put(struct block_device *);
+diff -urN linux.org/fs/xfs/linux/xfs_sysctl.c linux/fs/xfs/linux/xfs_sysctl.c
+--- linux.org/fs/xfs/linux/xfs_sysctl.c 2003-12-31 05:48:56.000000000 +0100
++++ linux/fs/xfs/linux/xfs_sysctl.c 2004-01-02 04:21:44.000000000 +0100
+@@ -51,7 +51,7 @@
+ int c, ret, *valp = ctl->data;
+ __uint32_t vn_active;
+
+- ret = proc_doulongvec_minmax(ctl, write, filp, buffer, lenp);
++ ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp);
+
+ if (!ret && write && *valp) {
+ printk("XFS Clearing xfsstats\n");
+diff -urN linux.org/fs/xfs/linux/xfs_version.h linux/fs/xfs/linux/xfs_version.h
+--- linux.org/fs/xfs/linux/xfs_version.h 2003-12-31 05:48:35.000000000 +0100
++++ linux/fs/xfs/linux/xfs_version.h 2004-01-02 04:21:44.000000000 +0100
+@@ -39,6 +39,6 @@
+ #ifndef __XFS_VERSION_H__
+ #define __XFS_VERSION_H__
+
+-#define XFS_VERSION_STRING "for Linux"
++#define XFS_VERSION_STRING "SGI-XFS CVS-2004-01-01_06:00_UTC"
+
+ #endif /* __XFS_VERSION_H__ */
+diff -urN linux.org/fs/xfs/linux/xfs_vfs.c linux/fs/xfs/linux/xfs_vfs.c
+--- linux.org/fs/xfs/linux/xfs_vfs.c 2003-12-31 05:46:21.000000000 +0100
++++ linux/fs/xfs/linux/xfs_vfs.c 2004-01-02 04:21:44.000000000 +0100
+@@ -134,7 +134,7 @@
+ int
+ vfs_statvfs(
+ struct bhv_desc *bdp,
+- struct kstatfs *sp,
++ xfs_statfs_t *sp,
+ struct vnode *vp)
+ {
+ struct bhv_desc *next = bdp;
+@@ -201,6 +201,19 @@
+ return ((*bhvtovfsops(next)->vfs_quotactl)(next, cmd, id, addr));
+ }
+
++struct inode *
++vfs_get_inode(
++ struct bhv_desc *bdp,
++ xfs_ino_t ino,
++ int fl)
++{
++ struct bhv_desc *next = bdp;
++
++ while (! (bhvtovfsops(next))->vfs_get_inode)
++ next = BHV_NEXTNULL(next);
++ return ((*bhvtovfsops(next)->vfs_get_inode)(next, ino, fl));
++}
++
+ void
+ vfs_init_vnode(
+ struct bhv_desc *bdp,
+diff -urN linux.org/fs/xfs/linux/xfs_vfs.h linux/fs/xfs/linux/xfs_vfs.h
+--- linux.org/fs/xfs/linux/xfs_vfs.h 2003-12-31 05:46:23.000000000 +0100
++++ linux/fs/xfs/linux/xfs_vfs.h 2004-01-02 04:21:44.000000000 +0100
+@@ -33,6 +33,7 @@
+ #define __XFS_VFS_H__
+
+ #include <linux/vfs.h>
++#include "xfs_fs.h"
+
+ struct fid;
+ struct cred;
+@@ -42,10 +43,12 @@
+ struct super_block;
+ struct xfs_mount_args;
+
++typedef struct kstatfs xfs_statfs_t;
++
+ typedef struct vfs {
+ u_int vfs_flag; /* flags */
+- fsid_t vfs_fsid; /* file system ID */
+- fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
++ xfs_fsid_t vfs_fsid; /* file system ID */
++ xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
+ bhv_head_t vfs_bh; /* head of vfs behavior chain */
+ struct super_block *vfs_super; /* Linux superblock structure */
+ struct task_struct *vfs_sync_task;
+@@ -92,6 +95,8 @@
+ #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
+ #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
+
++#define IGET_NOALLOC 0x0001 /* vfs_get_inode may return NULL */
++
+ typedef int (*vfs_mount_t)(bhv_desc_t *,
+ struct xfs_mount_args *, struct cred *);
+ typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *,
+@@ -101,7 +106,7 @@
+ typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *,
+ struct xfs_mount_args *);
+ typedef int (*vfs_root_t)(bhv_desc_t *, struct vnode **);
+-typedef int (*vfs_statvfs_t)(bhv_desc_t *, struct kstatfs *, struct vnode *);
++typedef int (*vfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, struct vnode *);
+ typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
+ typedef int (*vfs_vget_t)(bhv_desc_t *, struct vnode **, struct fid *);
+ typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t);
+@@ -109,6 +114,7 @@
+ typedef void (*vfs_init_vnode_t)(bhv_desc_t *,
+ struct vnode *, bhv_desc_t *, int);
+ typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
++typedef struct inode * (*vfs_get_inode_t)(bhv_desc_t *, xfs_ino_t, int);
+
+ typedef struct vfsops {
+ bhv_position_t vf_position; /* behavior chain position */
+@@ -123,6 +129,7 @@
+ vfs_vget_t vfs_vget; /* get vnode from fid */
+ vfs_dmapiops_t vfs_dmapiops; /* data migration */
+ vfs_quotactl_t vfs_quotactl; /* disk quota */
++ vfs_get_inode_t vfs_get_inode; /* bhv specific iget */
+ vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */
+ vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */
+ } vfsops_t;
+@@ -142,6 +149,7 @@
+ #define VFS_VGET(v, vpp,fidp, rv) ((rv) = vfs_vget(VHEAD(v), vpp,fidp))
+ #define VFS_DMAPIOPS(v, p, rv) ((rv) = vfs_dmapiops(VHEAD(v), p))
+ #define VFS_QUOTACTL(v, c,id,p, rv) ((rv) = vfs_quotactl(VHEAD(v), c,id,p))
++#define VFS_GET_INODE(v, ino, fl) ( vfs_get_inode(VHEAD(v), ino,fl) )
+ #define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) )
+ #define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) )
+
+@@ -159,6 +167,7 @@
+ #define PVFS_VGET(b, vpp,fidp, rv) ((rv) = vfs_vget(b, vpp,fidp))
+ #define PVFS_DMAPIOPS(b, p, rv) ((rv) = vfs_dmapiops(b, p))
+ #define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = vfs_quotactl(b, c,id,p))
++#define PVFS_GET_INODE(b, ino,fl) ( vfs_get_inode(b, ino,fl) )
+ #define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) )
+ #define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) )
+
+@@ -168,11 +177,12 @@
+ extern int vfs_unmount(bhv_desc_t *, int, struct cred *);
+ extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
+ extern int vfs_root(bhv_desc_t *, struct vnode **);
+-extern int vfs_statvfs(bhv_desc_t *, struct kstatfs *, struct vnode *);
++extern int vfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct vnode *);
+ extern int vfs_sync(bhv_desc_t *, int, struct cred *);
+ extern int vfs_vget(bhv_desc_t *, struct vnode **, struct fid *);
+ extern int vfs_dmapiops(bhv_desc_t *, caddr_t);
+ extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
++extern struct inode *vfs_get_inode(bhv_desc_t *, xfs_ino_t, int);
+ extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int);
+ extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
+
+diff -urN linux.org/fs/xfs/linux/xfs_vnode.c linux/fs/xfs/linux/xfs_vnode.c
+--- linux.org/fs/xfs/linux/xfs_vnode.c 2003-12-31 05:46:55.000000000 +0100
++++ linux/fs/xfs/linux/xfs_vnode.c 2004-01-02 04:21:44.000000000 +0100
+@@ -98,7 +98,7 @@
+ vp->v_type = VNON;
+ vp->v_fbhv = NULL;
+
+-#ifdef CONFIG_XFS_VNODE_TRACING
++#ifdef XFS_VNODE_TRACE
+ ktrace_free(vp->v_trace);
+ vp->v_trace = NULL;
+ #endif
+@@ -154,9 +154,10 @@
+ /* Initialize the first behavior and the behavior chain head. */
+ vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode");
+
+-#ifdef CONFIG_XFS_VNODE_TRACING
++#ifdef XFS_VNODE_TRACE
+ vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
+-#endif /* CONFIG_XFS_VNODE_TRACING */
++ printk("Allocated VNODE_TRACE at 0x%p\n", vp->v_trace);
++#endif /* XFS_VNODE_TRACE */
+
+ vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
+ return vp;
+@@ -177,7 +178,7 @@
+ if (inode->i_state & I_FREEING)
+ return NULL;
+
+- inode = ilookup(vmap->v_vfsp->vfs_super, vmap->v_ino);
++ inode = VFS_GET_INODE(vmap->v_vfsp, vmap->v_ino, IGET_NOALLOC);
+ if (!inode) /* Inode not present */
+ return NULL;
+
+@@ -392,7 +393,7 @@
+ }
+
+
+-#ifdef CONFIG_XFS_VNODE_TRACING
++#ifdef XFS_VNODE_TRACE
+
+ #define KTRACE_ENTER(vp, vk, s, line, ra) \
+ ktrace_enter( (vp)->v_trace, \
+@@ -439,4 +440,4 @@
+ {
+ KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
+ }
+-#endif /* CONFIG_XFS_VNODE_TRACING */
++#endif /* XFS_VNODE_TRACE */
+diff -urN linux.org/fs/xfs/linux/xfs_vnode.h linux/fs/xfs/linux/xfs_vnode.h
+--- linux.org/fs/xfs/linux/xfs_vnode.h 2003-12-31 05:48:46.000000000 +0100
++++ linux/fs/xfs/linux/xfs_vnode.h 2004-01-02 04:21:44.000000000 +0100
+@@ -62,7 +62,7 @@
+ struct uio;
+ struct file;
+ struct vattr;
+-struct page_buf_bmap_s;
++struct xfs_iomap;
+ struct attrlist_cursor_kern;
+
+ /*
+@@ -87,7 +87,7 @@
+ vn_bhv_head_t v_bh; /* behavior head */
+ spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
+ struct inode v_inode; /* Linux inode */
+-#ifdef CONFIG_XFS_VNODE_TRACING
++#ifdef XFS_VNODE_TRACE
+ struct ktrace *v_trace; /* trace header structure */
+ #endif
+ } vnode_t;
+@@ -225,8 +225,10 @@
+ typedef int (*vop_release_t)(bhv_desc_t *);
+ typedef int (*vop_rwlock_t)(bhv_desc_t *, vrwlock_t);
+ typedef void (*vop_rwunlock_t)(bhv_desc_t *, vrwlock_t);
++typedef int (*vop_frlock_t)(bhv_desc_t *, int, struct file_lock *,int,
++ xfs_off_t, struct cred *);
+ typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
+- struct page_buf_bmap_s *, int *);
++ struct xfs_iomap *, int *);
+ typedef int (*vop_reclaim_t)(bhv_desc_t *);
+ typedef int (*vop_attr_get_t)(bhv_desc_t *, char *, char *, int *, int,
+ struct cred *);
+@@ -269,6 +271,7 @@
+ vop_fid2_t vop_fid2;
+ vop_rwlock_t vop_rwlock;
+ vop_rwunlock_t vop_rwunlock;
++ vop_frlock_t vop_frlock;
+ vop_bmap_t vop_bmap;
+ vop_reclaim_t vop_reclaim;
+ vop_attr_get_t vop_attr_get;
+@@ -381,6 +384,7 @@
+ */
+ #define IO_ISDIRECT 0x00004 /* bypass page cache */
+ #define IO_INVIS 0x00020 /* don't update inode timestamps */
++#define IO_ISLOCKED 0x00800 /* don't do inode locking */
+
+ /*
+ * Flags for VOP_IFLUSH call
+@@ -545,21 +549,17 @@
+ extern vnode_t *vn_hold(struct vnode *);
+ extern void vn_rele(struct vnode *);
+
+-#if defined(CONFIG_XFS_VNODE_TRACING)
+-
++#if defined(XFS_VNODE_TRACE)
+ #define VN_HOLD(vp) \
+- ((void)vn_hold(vp), \
++ ((void)vn_hold(vp), \
+ vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address))
+ #define VN_RELE(vp) \
+ (vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \
+ iput(LINVFS_GET_IP(vp)))
+-
+-#else /* ! (defined(CONFIG_XFS_VNODE_TRACING)) */
+-
++#else
+ #define VN_HOLD(vp) ((void)vn_hold(vp))
+ #define VN_RELE(vp) (iput(LINVFS_GET_IP(vp)))
+-
+-#endif /* ! (defined(CONFIG_XFS_VNODE_TRACING)) */
++#endif
+
+ /*
+ * Vname handling macros.
+@@ -591,6 +591,13 @@
+ }
+
+ /*
++ * Update modify/access/change times on the vnode
++ */
++#define VN_MTIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_mtime = *(tvp))
++#define VN_ATIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_atime = *(tvp))
++#define VN_CTIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_ctime = *(tvp))
++
++/*
+ * Some useful predicates.
+ */
+ #define VN_MAPPED(vp) \
+@@ -617,13 +624,12 @@
+ #define FSYNC_INVAL 0x2 /* flush and invalidate cached data */
+ #define FSYNC_DATA 0x4 /* synchronous fsync of data only */
+
+-#if (defined(CONFIG_XFS_VNODE_TRACING))
+-
+-#define VNODE_TRACE_SIZE 16 /* number of trace entries */
+-
+ /*
+- * Tracing entries.
++ * Tracking vnode activity.
+ */
++#if defined(XFS_VNODE_TRACE)
++
++#define VNODE_TRACE_SIZE 16 /* number of trace entries */
+ #define VNODE_KTRACE_ENTRY 1
+ #define VNODE_KTRACE_EXIT 2
+ #define VNODE_KTRACE_HOLD 3
+@@ -635,18 +641,16 @@
+ extern void vn_trace_hold(struct vnode *, char *, int, inst_t *);
+ extern void vn_trace_ref(struct vnode *, char *, int, inst_t *);
+ extern void vn_trace_rele(struct vnode *, char *, int, inst_t *);
++
+ #define VN_TRACE(vp) \
+ vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address)
+-
+-#else /* ! (defined(CONFIG_XFS_VNODE_TRACING)) */
+-
++#else
+ #define vn_trace_entry(a,b,c)
+ #define vn_trace_exit(a,b,c)
+ #define vn_trace_hold(a,b,c,d)
+ #define vn_trace_ref(a,b,c,d)
+ #define vn_trace_rele(a,b,c,d)
+ #define VN_TRACE(vp)
+-
+-#endif /* ! (defined(CONFIG_XFS_VNODE_TRACING)) */
++#endif
+
+ #endif /* __XFS_VNODE_H__ */
+diff -urN linux.org/fs/xfs/Makefile linux/fs/xfs/Makefile
+--- linux.org/fs/xfs/Makefile 2003-12-31 05:47:58.000000000 +0100
++++ linux/fs/xfs/Makefile 2004-01-02 04:21:42.000000000 +0100
+@@ -34,13 +34,45 @@
+
+ ifeq ($(CONFIG_XFS_DEBUG),y)
+ EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG -DXFSDEBUG
++ EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING
+ endif
+-ifeq ($(CONFIG_PAGEBUF_DEBUG),y)
++ifeq ($(CONFIG_XFS_TRACE),y)
++ EXTRA_CFLAGS += -DXFS_ALLOC_TRACE
++ EXTRA_CFLAGS += -DXFS_ATTR_TRACE
++ EXTRA_CFLAGS += -DXFS_BLI_TRACE
++ EXTRA_CFLAGS += -DXFS_BMAP_TRACE
++ EXTRA_CFLAGS += -DXFS_BMBT_TRACE
++ EXTRA_CFLAGS += -DXFS_DIR_TRACE
++ EXTRA_CFLAGS += -DXFS_DIR2_TRACE
++ EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
++ EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
++ EXTRA_CFLAGS += -DXFS_LOG_TRACE
++ EXTRA_CFLAGS += -DXFS_RW_TRACE
+ EXTRA_CFLAGS += -DPAGEBUF_TRACE
++ # EXTRA_CFLAGS += -DXFS_VNODE_TRACE
+ endif
+
+ obj-$(CONFIG_XFS_FS) += xfs.o
+
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ifneq ($(CONFIG_XFS_DMAPI),y)
++xfs-y += xfs_dmops.o
++endif
+
+ xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \
+ xfs_dquot.o \
+@@ -49,9 +81,10 @@
+ xfs_qm_syscalls.o \
+ xfs_qm_bhv.o \
+ xfs_qm.o)
+-
+ ifeq ($(CONFIG_XFS_QUOTA),y)
+ xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o
++else
++xfs-y += xfs_qmops.o
+ endif
+
+ xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
+@@ -79,7 +112,6 @@
+ xfs_dir2_leaf.o \
+ xfs_dir2_node.o \
+ xfs_dir2_sf.o \
+- xfs_dir2_trace.o \
+ xfs_dir_leaf.o \
+ xfs_error.o \
+ xfs_extfree_item.o \
+@@ -108,10 +140,10 @@
+ xfs_vnodeops.o \
+ xfs_rw.o
+
++xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o
++
+ # Objects in pagebuf/
+-xfs-y += $(addprefix pagebuf/, \
+- page_buf.o \
+- page_buf_locking.o)
++xfs-y += pagebuf/page_buf.o
+
+ # Objects in linux/
+ xfs-y += $(addprefix linux/, \
+@@ -131,15 +163,12 @@
+ # Objects in support/
+ xfs-y += $(addprefix support/, \
+ debug.o \
+- ktrace.o \
+ move.o \
+ mrlock.o \
+ qsort.o \
+ uuid.o)
+
+-# Quota and DMAPI stubs
+-xfs-y += xfs_dmops.o \
+- xfs_qmops.o
++xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o
+
+ # 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
+diff -urN linux.org/fs/xfs/pagebuf/page_buf.c linux/fs/xfs/pagebuf/page_buf.c
+--- linux.org/fs/xfs/pagebuf/page_buf.c 2003-12-31 05:46:24.000000000 +0100
++++ linux/fs/xfs/pagebuf/page_buf.c 2004-01-02 04:21:44.000000000 +0100
+@@ -58,11 +58,13 @@
+ #include <linux/proc_fs.h>
+ #include <linux/workqueue.h>
+ #include <linux/suspend.h>
++#include <linux/percpu.h>
+
++#include <support/ktrace.h>
+ #include <support/debug.h>
+ #include <support/kmem.h>
+
+-#include "page_buf_internal.h"
++#include "page_buf.h"
+
+ #define BBSHIFT 9
+ #define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)
+@@ -72,50 +74,7 @@
+ #endif
+
+ /*
+- * Debug code
+- */
+-
+-#ifdef PAGEBUF_TRACE
+-static spinlock_t pb_trace_lock = SPIN_LOCK_UNLOCKED;
+-struct pagebuf_trace_buf pb_trace;
+-EXPORT_SYMBOL(pb_trace);
+-EXPORT_SYMBOL(pb_trace_func);
+-#define CIRC_INC(i) (((i) + 1) & (PB_TRACE_BUFSIZE - 1))
+-
+-void
+-pb_trace_func(
+- page_buf_t *pb,
+- int event,
+- void *misc,
+- void *ra)
+-{
+- int j;
+- unsigned long flags;
+-
+- if (!pb_params.debug.val) return;
+-
+- if (ra == NULL) ra = (void *)__builtin_return_address(0);
+-
+- spin_lock_irqsave(&pb_trace_lock, flags);
+- j = pb_trace.start;
+- pb_trace.start = CIRC_INC(j);
+- spin_unlock_irqrestore(&pb_trace_lock, flags);
+-
+- pb_trace.buf[j].pb = (unsigned long) pb;
+- pb_trace.buf[j].event = event;
+- pb_trace.buf[j].flags = pb->pb_flags;
+- pb_trace.buf[j].hold = pb->pb_hold.counter;
+- pb_trace.buf[j].lock_value = pb->pb_sema.count.counter;
+- pb_trace.buf[j].task = (void *)current;
+- pb_trace.buf[j].misc = misc;
+- pb_trace.buf[j].ra = ra;
+- pb_trace.buf[j].offset = pb->pb_file_offset;
+- pb_trace.buf[j].size = pb->pb_buffer_length;
+-}
+-#endif /* PAGEBUF_TRACE */
+-
+-/*
+- * File wide globals
++ * File wide globals
+ */
+
+ STATIC kmem_cache_t *pagebuf_cache;
+@@ -129,7 +88,20 @@
+ * /proc/sys/vm/pagebuf
+ */
+
+-pagebuf_param_t pb_params = {
++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 },
+@@ -137,12 +109,79 @@
+ .debug = { 0, 0, 1 },
+ };
+
++enum {
++ PB_FLUSH_INT = 1,
++ PB_FLUSH_AGE = 2,
++ PB_STATS_CLEAR = 3,
++ PB_DEBUG = 4,
++};
++
+ /*
+ * Pagebuf statistics variables
+ */
+
++struct pbstats {
++ 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_PER_CPU(struct pbstats, pbstats);
+
++/* We don't disable preempt, not too worried about poking the
++ * wrong cpu's stat for now */
++#define PB_STATS_INC(count) (__get_cpu_var(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.
+ */
+@@ -198,11 +237,11 @@
+ 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.
+ */
+@@ -247,16 +286,6 @@
+ }
+
+ /*
+- * 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
+- * spinlock in the buffer, for use by the caller when concurrent
+- * access is possible.
+- */
+-
+-/*
+ * Internal pagebuf object manipulation
+ */
+
+@@ -294,7 +323,7 @@
+ init_waitqueue_head(&pb->pb_waiters);
+
+ PB_STATS_INC(pb_create);
+- PB_TRACE(pb, PB_TRACE_REC(get), target);
++ PB_TRACE(pb, "initialize", target);
+ }
+
+ /*
+@@ -343,9 +372,6 @@
+ page_cache_release(page);
+ }
+ }
+-
+- if (pb->pb_pages != pb->pb_page_array)
+- kfree(pb->pb_pages);
+ }
+
+ /*
+@@ -361,7 +387,7 @@
+ {
+ page_buf_flags_t pb_flags = pb->pb_flags;
+
+- PB_TRACE(pb, PB_TRACE_REC(free_obj), 0);
++ PB_TRACE(pb, "free_object", 0);
+ pb->pb_flags |= PBF_FREED;
+
+ if (hash) {
+@@ -384,20 +410,17 @@
+ if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
+ if (pb->pb_pages) {
+ /* release the pages in the address list */
+- if (pb->pb_pages[0] &&
+- PageSlab(pb->pb_pages[0])) {
+- /*
+- * This came from the slab
+- * allocator free it as such
+- */
++ 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;
++ pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
+ }
+ }
+
+@@ -572,7 +595,7 @@
+ }
+ }
+
+- PB_TRACE(pb, PB_TRACE_REC(look_pg), good_pages);
++ PB_TRACE(pb, "lookup_pages", (long)good_pages);
+
+ return rval;
+ }
+@@ -663,7 +686,7 @@
+ if (not_locked) {
+ if (!(flags & PBF_TRYLOCK)) {
+ /* wait for buffer ownership */
+- PB_TRACE(pb, PB_TRACE_REC(get_lk), 0);
++ PB_TRACE(pb, "get_lock", 0);
+ pagebuf_lock(pb);
+ PB_STATS_INC(pb_get_locked_waited);
+ } else {
+@@ -689,8 +712,9 @@
+ _PBF_LOCKABLE | \
+ _PBF_ALL_PAGES_MAPPED | \
+ _PBF_ADDR_ALLOCATED | \
+- _PBF_MEM_ALLOCATED;
+- PB_TRACE(pb, PB_TRACE_REC(got_lk), 0);
++ _PBF_MEM_ALLOCATED | \
++ _PBF_MEM_SLAB;
++ PB_TRACE(pb, "got_lock", 0);
+ PB_STATS_INC(pb_get_locked);
+ return (pb);
+ }
+@@ -765,10 +789,11 @@
+
+ if (flags & PBF_READ) {
+ if (PBF_NOT_DONE(pb)) {
+- PB_TRACE(pb, PB_TRACE_REC(get_read), flags);
++ 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
+@@ -778,12 +803,13 @@
+ 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);
+ }
+-
+- PB_TRACE(pb, PB_TRACE_REC(get_obj), flags);
+ return (pb);
+ }
+
+@@ -916,8 +942,8 @@
+ page_buf_t *pb;
+ size_t tlen = 0;
+
+- if (len > 0x20000)
+- return(NULL);
++ if (unlikely(len > 0x20000))
++ return NULL;
+
+ pb = pagebuf_allocate(flags);
+ if (!pb)
+@@ -944,11 +970,11 @@
+ return NULL;
+ }
+ /* otherwise pagebuf_free just ignores it */
+- pb->pb_flags |= _PBF_MEM_ALLOCATED;
++ pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB);
+ PB_CLEAR_OWNER(pb);
+ up(&pb->pb_sema); /* Return unlocked pagebuf */
+
+- PB_TRACE(pb, PB_TRACE_REC(no_daddr), rmem);
++ PB_TRACE(pb, "no_daddr", rmem);
+
+ return pb;
+ }
+@@ -967,7 +993,7 @@
+ page_buf_t *pb)
+ {
+ atomic_inc(&pb->pb_hold);
+- PB_TRACE(pb, PB_TRACE_REC(hold), 0);
++ PB_TRACE(pb, "hold", 0);
+ }
+
+ /*
+@@ -1002,7 +1028,7 @@
+ {
+ pb_hash_t *h;
+
+- PB_TRACE(pb, PB_TRACE_REC(rele), pb->pb_relse);
++ PB_TRACE(pb, "rele", pb->pb_relse);
+ if (pb->pb_flags & _PBF_LOCKABLE) {
+ h = pb_hash(pb);
+ spin_lock(&h->pb_hash_lock);
+@@ -1043,6 +1069,95 @@
+
+
+ /*
++ * 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
+ */
+
+@@ -1065,7 +1180,7 @@
+ page_buf_t *pb)
+ {
+ atomic_inc(&pb->pb_pin_count);
+- PB_TRACE(pb, PB_TRACE_REC(pin), pb->pb_pin_count.counter);
++ PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter);
+ }
+
+ /*
+@@ -1082,7 +1197,7 @@
+ if (atomic_dec_and_test(&pb->pb_pin_count)) {
+ wake_up_all(&pb->pb_waiters);
+ }
+- PB_TRACE(pb, PB_TRACE_REC(unpin), pb->pb_pin_count.counter);
++ PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter);
+ }
+
+ int
+@@ -1161,7 +1276,7 @@
+ pb->pb_flags &= ~(PBF_PARTIAL | PBF_NONE);
+ }
+
+- PB_TRACE(pb, PB_TRACE_REC(done), pb->pb_iodone);
++ PB_TRACE(pb, "iodone", pb->pb_iodone);
+
+ if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
+ if (schedule) {
+@@ -1187,7 +1302,7 @@
+ unsigned int error) /* error to store (0 if none) */
+ {
+ pb->pb_error = error;
+- PB_TRACE(pb, PB_TRACE_REC(ioerror), error);
++ PB_TRACE(pb, "ioerror", (unsigned long)error);
+ }
+
+ /*
+@@ -1211,7 +1326,7 @@
+ {
+ int status = 0;
+
+- PB_TRACE(pb, PB_TRACE_REC(iostart), flags);
++ PB_TRACE(pb, "iostart", (unsigned long)flags);
+
+ if (flags & PBF_DELWRI) {
+ pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC);
+@@ -1395,7 +1510,6 @@
+ break;
+
+ offset = 0;
+-
+ sector += nbytes >> BBSHIFT;
+ size -= nbytes;
+ total_nr_pages--;
+@@ -1403,15 +1517,11 @@
+
+ submit_io:
+ if (likely(bio->bi_size)) {
+- if (pb->pb_flags & PBF_READ) {
+- submit_bio(READ, bio);
+- } else {
+- submit_bio(WRITE, bio);
+- }
+-
++ submit_bio((pb->pb_flags & PBF_READ) ? READ : WRITE, bio);
+ if (size)
+ goto next_chunk;
+ } else {
++ bio_put(bio);
+ pagebuf_ioerror(pb, EIO);
+ }
+
+@@ -1444,7 +1554,7 @@
+ pagebuf_iorequest( /* start real I/O */
+ page_buf_t *pb) /* buffer to convey to device */
+ {
+- PB_TRACE(pb, PB_TRACE_REC(ioreq), 0);
++ PB_TRACE(pb, "iorequest", 0);
+
+ if (pb->pb_flags & PBF_DELWRI) {
+ pagebuf_delwri_queue(pb, 1);
+@@ -1480,11 +1590,11 @@
+ pagebuf_iowait(
+ page_buf_t *pb)
+ {
+- PB_TRACE(pb, PB_TRACE_REC(iowait), 0);
++ PB_TRACE(pb, "iowait", 0);
+ if (atomic_read(&pb->pb_io_remaining))
+ blk_run_queues();
+ down(&pb->pb_iodonesema);
+- PB_TRACE(pb, PB_TRACE_REC(iowaited), (int)pb->pb_error);
++ PB_TRACE(pb, "iowaited", (long)pb->pb_error);
+ return pb->pb_error;
+ }
+
+@@ -1575,7 +1685,7 @@
+ page_buf_t *pb,
+ int unlock)
+ {
+- PB_TRACE(pb, PB_TRACE_REC(delwri_q), 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)) {
+@@ -1598,7 +1708,7 @@
+ pagebuf_delwri_dequeue(
+ page_buf_t *pb)
+ {
+- PB_TRACE(pb, PB_TRACE_REC(delwri_uq), 0);
++ PB_TRACE(pb, "delwri_uq", 0);
+ spin_lock(&pbd_delwrite_lock);
+ list_del_init(&pb->pb_list);
+ pb->pb_flags &= ~PBF_DELWRI;
+@@ -1665,7 +1775,7 @@
+ list_for_each_safe(curr, next, &pbd_delwrite_queue) {
+ pb = list_entry(curr, page_buf_t, pb_list);
+
+- PB_TRACE(pb, PB_TRACE_REC(walkq1), pagebuf_ispin(pb));
++ PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
+
+ if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) &&
+ (((pb->pb_flags & _PBF_LOCKABLE) == 0) ||
+@@ -1738,7 +1848,7 @@
+ continue;
+ }
+
+- PB_TRACE(pb, PB_TRACE_REC(walkq2), pagebuf_ispin(pb));
++ PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb));
+ if (pagebuf_ispin(pb)) {
+ pincount++;
+ continue;
+@@ -1839,7 +1949,7 @@
+ int c, ret;
+ int *valp = ctl->data;
+
+- ret = proc_doulongvec_minmax(ctl, write, filp, buffer, lenp);
++ ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp);
+
+ if (!ret && write && *valp) {
+ printk("XFS Clearing pbstats\n");
+@@ -1960,11 +2070,7 @@
+ }
+
+ #ifdef PAGEBUF_TRACE
+- pb_trace.buf = (pagebuf_trace_t *)kmalloc(
+- PB_TRACE_BUFSIZE * sizeof(pagebuf_trace_t), GFP_KERNEL);
+- memset(pb_trace.buf, 0, PB_TRACE_BUFSIZE * sizeof(pagebuf_trace_t));
+- pb_trace.start = 0;
+- pb_trace.end = PB_TRACE_BUFSIZE - 1;
++ pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
+ #endif
+
+ pagebuf_daemon_start();
+@@ -1996,3 +2102,6 @@
+ * Module management (for kernel debugger module)
+ */
+ EXPORT_SYMBOL(pagebuf_offset);
++#ifdef DEBUG
++EXPORT_SYMBOL(pbd_delwrite_queue);
++#endif
+diff -urN linux.org/fs/xfs/pagebuf/page_buf.h linux/fs/xfs/pagebuf/page_buf.h
+--- linux.org/fs/xfs/pagebuf/page_buf.h 2003-12-31 05:47:38.000000000 +0100
++++ linux/fs/xfs/pagebuf/page_buf.h 2004-01-02 04:21:44.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -48,11 +48,6 @@
+ #include <linux/uio.h>
+
+ /*
+- * Turn this on to get pagebuf lock ownership
+-#define PAGEBUF_LOCK_TRACKING
+-*/
+-
+-/*
+ * Base types
+ */
+
+@@ -61,8 +56,6 @@
+
+ #define PAGE_BUF_DADDR_NULL ((page_buf_daddr_t) (-1LL))
+
+-typedef size_t page_buf_dsize_t; /* size of buffer in blocks */
+-
+ #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)
+@@ -74,29 +67,6 @@
+ PBRW_ZERO = 3 /* Zero target memory */
+ } page_buf_rw_t;
+
+-typedef enum { /* pbm_flags values */
+- PBMF_EOF = 0x01, /* mapping contains EOF */
+- PBMF_HOLE = 0x02, /* mapping covers a hole */
+- PBMF_DELAY = 0x04, /* mapping covers delalloc region */
+- PBMF_UNWRITTEN = 0x20, /* mapping covers allocated */
+- /* but uninitialized file data */
+- PBMF_NEW = 0x40 /* just allocated */
+-} bmap_flags_t;
+-
+-typedef enum {
+- /* base extent manipulation calls */
+- BMAP_READ = (1 << 0), /* read extents */
+- BMAP_WRITE = (1 << 1), /* create extents */
+- BMAP_ALLOCATE = (1 << 2), /* delayed allocate to real extents */
+- BMAP_UNWRITTEN = (1 << 3), /* unwritten extents to real extents */
+- /* modifiers */
+- BMAP_IGNSTATE = (1 << 4), /* ignore unwritten state on read */
+- BMAP_DIRECT = (1 << 5), /* direct instead of buffered write */
+- BMAP_MMAP = (1 << 6), /* allocate for mmap write */
+- BMAP_SYNC = (1 << 7), /* sync write */
+- BMAP_TRYLOCK = (1 << 8), /* non-blocking request */
+- BMAP_DEVICE = (1 << 9), /* we only want to know the device */
+-} bmapi_flags_t;
+
+ typedef enum page_buf_flags_e { /* pb_flags values */
+ PBF_READ = (1 << 0), /* buffer intended for reading from device */
+@@ -123,12 +93,13 @@
+ _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), /* pb_mem+underlying pages alloc'd */
++ _PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated */
++ _PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated */
+
+- PBF_FORCEIO = (1 << 21),
+- PBF_FLUSH = (1 << 22), /* flush disk write cache */
+- PBF_READ_AHEAD = (1 << 23),
+- PBF_RUN_QUEUES = (1 << 24), /* run block device task queue */
++ 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 */
+
+ } page_buf_flags_t;
+
+@@ -146,36 +117,6 @@
+ } pb_target_t;
+
+ /*
+- * page_buf_bmap_t: File system I/O map
+- *
+- * The pbm_bn, pbm_offset and pbm_length fields are expressed in disk blocks.
+- * The pbm_length field specifies the size of the underlying backing store
+- * for the particular mapping.
+- *
+- * The pbm_bsize, pbm_size and pbm_delta fields are in bytes and indicate
+- * the size of the mapping, the number of bytes that are valid to access
+- * (read or write), and the offset into the mapping, given the offset
+- * supplied to the file I/O map routine. pbm_delta is the offset of the
+- * desired data from the beginning of the mapping.
+- *
+- * When a request is made to read beyond the logical end of the object,
+- * pbm_size may be set to 0, but pbm_offset and pbm_length should be set to
+- * the actual amount of underlying storage that has been allocated, if any.
+- */
+-
+-typedef struct page_buf_bmap_s {
+- page_buf_daddr_t pbm_bn; /* block number in file system */
+- pb_target_t *pbm_target; /* device to do I/O to */
+- loff_t pbm_offset; /* byte offset of mapping in file */
+- size_t pbm_delta; /* offset of request into bmap */
+- size_t pbm_bsize; /* size of this mapping in bytes */
+- bmap_flags_t pbm_flags; /* options flags for mapping */
+-} page_buf_bmap_t;
+-
+-typedef page_buf_bmap_t pb_bmap_t;
+-
+-
+-/*
+ * page_buf_t: Buffer structure for page cache-based buffers
+ *
+ * This buffer structure is used by the page cache buffer management routines
+@@ -381,4 +322,19 @@
+ 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) \
++ ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; })
++
+ #endif /* __PAGE_BUF_H__ */
+diff -urN linux.org/fs/xfs/pagebuf/page_buf_internal.h linux/fs/xfs/pagebuf/page_buf_internal.h
+--- linux.org/fs/xfs/pagebuf/page_buf_internal.h 2003-12-31 05:47:14.000000000 +0100
++++ linux/fs/xfs/pagebuf/page_buf_internal.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,134 +0,0 @@
+-/*
+- * Copyright (c) 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/
+- */
+-
+-/*
+- * Written by Steve Lord at SGI
+- */
+-
+-#ifndef __PAGE_BUF_PRIVATE_H__
+-#define __PAGE_BUF_PRIVATE_H__
+-
+-#include <linux/percpu.h>
+-#include "page_buf.h"
+-
+-#define _PAGE_BUF_INTERNAL_
+-#define PB_DEFINE_TRACES
+-#include "page_buf_trace.h"
+-
+-#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)
+-#define PB_CLEAR_OWNER(pb)
+-#define PB_GET_OWNER(pb)
+-#endif /* PAGEBUF_LOCK_TRACKING */
+-
+-/* Tracing utilities for pagebuf */
+-typedef struct {
+- int event;
+- unsigned long pb;
+- page_buf_flags_t flags;
+- unsigned short hold;
+- unsigned short lock_value;
+- void *task;
+- void *misc;
+- void *ra;
+- loff_t offset;
+- size_t size;
+-} pagebuf_trace_t;
+-
+-struct pagebuf_trace_buf {
+- pagebuf_trace_t *buf;
+- volatile int start;
+- volatile int end;
+-};
+-
+-#define PB_TRACE_BUFSIZE 1024
+-#define CIRC_INC(i) (((i) + 1) & (PB_TRACE_BUFSIZE - 1))
+-
+-/*
+- * Tunable pagebuf parameters
+- */
+-
+-typedef struct pb_sysctl_val {
+- int min;
+- int val;
+- int max;
+-} pb_sysctl_val_t;
+-
+-typedef struct pagebuf_param {
+- 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 */
+-} pagebuf_param_t;
+-
+-enum {
+- PB_FLUSH_INT = 1,
+- PB_FLUSH_AGE = 2,
+- PB_STATS_CLEAR = 3,
+- PB_DEBUG = 4
+-};
+-
+-extern pagebuf_param_t pb_params;
+-
+-/*
+- * Pagebuf statistics
+- */
+-
+-struct pbstats {
+- 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;
+-};
+-
+-DECLARE_PER_CPU(struct pbstats, pbstats);
+-
+-/* We don't disable preempt, not too worried about poking the
+- * wrong cpu's stat for now */
+-#define PB_STATS_INC(count) (__get_cpu_var(pbstats).count++)
+-
+-#ifndef STATIC
+-# define STATIC static
+-#endif
+-
+-#endif /* __PAGE_BUF_PRIVATE_H__ */
+diff -urN linux.org/fs/xfs/pagebuf/page_buf_locking.c linux/fs/xfs/pagebuf/page_buf_locking.c
+--- linux.org/fs/xfs/pagebuf/page_buf_locking.c 2003-12-31 05:47:32.000000000 +0100
++++ linux/fs/xfs/pagebuf/page_buf_locking.c 1970-01-01 01:00:00.000000000 +0100
+@@ -1,139 +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/
+- */
+-
+-/*
+- * page_buf_locking.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. The page_buf_locking module adds support for
+- * locking such page buffers.
+- *
+- * Written by Steve Lord at SGI
+- *
+- */
+-
+-#include <linux/stddef.h>
+-#include <linux/errno.h>
+-#include <linux/slab.h>
+-#include <linux/bitops.h>
+-#include <linux/string.h>
+-#include <linux/pagemap.h>
+-#include <linux/init.h>
+-#include <linux/major.h>
+-
+-#include <support/debug.h>
+-
+-#include "page_buf_internal.h"
+-
+-/*
+- * 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, PB_TRACE_REC(condlck), 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, PB_TRACE_REC(lock), 0);
+- if (atomic_read(&pb->pb_io_remaining))
+- blk_run_queues();
+- down(&pb->pb_sema);
+- PB_SET_OWNER(pb);
+- PB_TRACE(pb, PB_TRACE_REC(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, PB_TRACE_REC(unlock), 0);
+-}
+diff -urN linux.org/fs/xfs/pagebuf/page_buf_trace.h linux/fs/xfs/pagebuf/page_buf_trace.h
+--- linux.org/fs/xfs/pagebuf/page_buf_trace.h 2003-12-31 05:47:37.000000000 +0100
++++ linux/fs/xfs/pagebuf/page_buf_trace.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,95 +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 __PAGEBUF_TRACE__
+-#define __PAGEBUF_TRACE__
+-
+-#ifdef PB_DEFINE_TRACES
+-#define PB_TRACE_START typedef enum {
+-#define PB_TRACE_REC(x) pb_trace_point_##x
+-#define PB_TRACE_END } pb_trace_var_t;
+-#else
+-#define PB_TRACE_START static char *event_names[] = {
+-#define PB_TRACE_REC(x) #x
+-#define PB_TRACE_END };
+-#endif
+-
+-PB_TRACE_START
+-PB_TRACE_REC(get),
+-PB_TRACE_REC(get_obj),
+-PB_TRACE_REC(free_obj),
+-PB_TRACE_REC(look_pg),
+-PB_TRACE_REC(get_read),
+-PB_TRACE_REC(no_daddr),
+-PB_TRACE_REC(hold),
+-PB_TRACE_REC(rele),
+-PB_TRACE_REC(done),
+-PB_TRACE_REC(ioerror),
+-PB_TRACE_REC(iostart),
+-PB_TRACE_REC(end_io),
+-PB_TRACE_REC(do_io),
+-PB_TRACE_REC(ioreq),
+-PB_TRACE_REC(iowait),
+-PB_TRACE_REC(iowaited),
+-PB_TRACE_REC(free_lk),
+-PB_TRACE_REC(freed_l),
+-PB_TRACE_REC(cmp),
+-PB_TRACE_REC(get_lk),
+-PB_TRACE_REC(got_lk),
+-PB_TRACE_REC(skip),
+-PB_TRACE_REC(lock),
+-PB_TRACE_REC(locked),
+-PB_TRACE_REC(unlock),
+-PB_TRACE_REC(avl_ret),
+-PB_TRACE_REC(condlck),
+-PB_TRACE_REC(avl_ins),
+-PB_TRACE_REC(walkq1),
+-PB_TRACE_REC(walkq2),
+-PB_TRACE_REC(walkq3),
+-PB_TRACE_REC(delwri_q),
+-PB_TRACE_REC(delwri_uq),
+-PB_TRACE_REC(pin),
+-PB_TRACE_REC(unpin),
+-PB_TRACE_REC(file_write),
+-PB_TRACE_REC(external),
+-PB_TRACE_END
+-
+-extern void pb_trace_func(page_buf_t *, int, void *, void *);
+-#ifdef PAGEBUF_TRACE
+-# define PB_TRACE(pb, event, misc) \
+- pb_trace_func(pb, event, (void *) misc, \
+- (void *)__builtin_return_address(0))
+-#else
+-# define PB_TRACE(pb, event, misc) do { } while (0)
+-#endif
+-
+-#endif /* __PAGEBUF_TRACE__ */
+diff -urN linux.org/fs/xfs/quota/xfs_dquot.c linux/fs/xfs/quota/xfs_dquot.c
+--- linux.org/fs/xfs/quota/xfs_dquot.c 2003-12-31 05:47:13.000000000 +0100
++++ linux/fs/xfs/quota/xfs_dquot.c 2004-01-02 04:21:44.000000000 +0100
+@@ -124,7 +124,7 @@
+ initnsema(&dqp->q_flock, 1, "fdq");
+ sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq");
+
+-#ifdef DQUOT_TRACING
++#ifdef XFS_DQUOT_TRACE
+ dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP);
+ xfs_dqtrace_entry(dqp, "DQINIT");
+ #endif
+@@ -148,7 +148,7 @@
+ dqp->q_hash = 0;
+ ASSERT(dqp->dq_flnext == dqp->dq_flprev);
+
+-#ifdef DQUOT_TRACING
++#ifdef XFS_DQUOT_TRACE
+ ASSERT(dqp->q_trace);
+ xfs_dqtrace_entry(dqp, "DQRECLAIMED_INIT");
+ #endif
+@@ -173,7 +173,7 @@
+ freesema(&dqp->q_flock);
+ sv_destroy(&dqp->q_pinwait);
+
+-#ifdef DQUOT_TRACING
++#ifdef XFS_DQUOT_TRACE
+ if (dqp->q_trace)
+ ktrace_free(dqp->q_trace);
+ dqp->q_trace = NULL;
+@@ -201,20 +201,20 @@
+ }
+
+
+-#ifdef DQUOT_TRACING
++#ifdef XFS_DQUOT_TRACE
+ /*
+ * Dquot tracing for debugging.
+ */
+ /* ARGSUSED */
+ void
+-xfs_dqtrace_entry__(
+- xfs_dquot_t *dqp,
+- char *func,
+- void *retaddr,
+- xfs_inode_t *ip)
++__xfs_dqtrace_entry(
++ xfs_dquot_t *dqp,
++ char *func,
++ void *retaddr,
++ xfs_inode_t *ip)
+ {
+- xfs_dquot_t *udqp = NULL;
+- int ino;
++ xfs_dquot_t *udqp = NULL;
++ xfs_ino_t ino = 0;
+
+ ASSERT(dqp->q_trace);
+ if (ip) {
+@@ -227,13 +227,19 @@
+ (void *)(__psint_t)dqp->q_nrefs,
+ (void *)(__psint_t)dqp->dq_flags,
+ (void *)(__psint_t)dqp->q_res_bcount,
+- (void *)(__psint_t)INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT),
+- (void *)(__psint_t)INT_GET(dqp->q_core.d_icount, ARCH_CONVERT),
+- (void *)(__psint_t)INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT),
+- (void *)(__psint_t)INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT),
+- (void *)(__psint_t)INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT),
+- (void *)(__psint_t)INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT),
+- (void *)(__psint_t)INT_GET(dqp->q_core.d_id, ARCH_CONVERT), /* 11 */
++ (void *)(__psint_t)INT_GET(dqp->q_core.d_bcount,
++ ARCH_CONVERT),
++ (void *)(__psint_t)INT_GET(dqp->q_core.d_icount,
++ ARCH_CONVERT),
++ (void *)(__psint_t)INT_GET(dqp->q_core.d_blk_hardlimit,
++ ARCH_CONVERT),
++ (void *)(__psint_t)INT_GET(dqp->q_core.d_blk_softlimit,
++ ARCH_CONVERT),
++ (void *)(__psint_t)INT_GET(dqp->q_core.d_ino_hardlimit,
++ ARCH_CONVERT),
++ (void *)(__psint_t)INT_GET(dqp->q_core.d_ino_softlimit,
++ ARCH_CONVERT),
++ (void *)(__psint_t)INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
+ (void *)(__psint_t)current_pid(),
+ (void *)(__psint_t)ino,
+ (void *)(__psint_t)retaddr,
+@@ -751,7 +757,6 @@
+ }
+
+ *O_dqpp = dqp;
+- ASSERT(! XFS_DQ_IS_LOCKED(dqp));
+ return (0);
+
+ error0:
+@@ -1000,7 +1005,6 @@
+ /*
+ * Dquot lock comes after hashlock in the lock ordering
+ */
+- ASSERT(! XFS_DQ_IS_LOCKED(dqp));
+ if (ip) {
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ if (! XFS_IS_DQTYPE_ON(mp, type)) {
+@@ -1504,7 +1508,7 @@
+ */
+ ASSERT(XFS_DQ_IS_ON_FREELIST(dqp));
+
+- dqp->q_mount = NULL;;
++ dqp->q_mount = NULL;
+ dqp->q_hash = NULL;
+ dqp->dq_flags = XFS_DQ_INACTIVE;
+ memset(&dqp->q_core, 0, sizeof(dqp->q_core));
+diff -urN linux.org/fs/xfs/quota/xfs_dquot.h linux/fs/xfs/quota/xfs_dquot.h
+--- linux.org/fs/xfs/quota/xfs_dquot.h 2003-12-31 05:48:42.000000000 +0100
++++ linux/fs/xfs/quota/xfs_dquot.h 2004-01-02 04:21:44.000000000 +0100
+@@ -99,7 +99,7 @@
+ sema_t q_flock; /* flush lock */
+ uint q_pincount; /* pin count for this dquot */
+ sv_t q_pinwait; /* sync var for pinning */
+-#ifdef DQUOT_TRACING
++#ifdef XFS_DQUOT_TRACE
+ struct ktrace *q_trace; /* trace header structure */
+ #endif
+ } xfs_dquot_t;
+@@ -175,23 +175,25 @@
+ #define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
+ (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
+ (XFS_IS_GQUOTA_ON((d)->q_mount))))
+-#ifdef DQUOT_TRACING
++
++#ifdef XFS_DQUOT_TRACE
+ /*
+ * Dquot Tracing stuff.
+ */
+ #define DQUOT_TRACE_SIZE 64
+ #define DQUOT_KTRACE_ENTRY 1
+
++extern void __xfs_dqtrace_entry(xfs_dquot_t *dqp, char *func,
++ void *, xfs_inode_t *);
+ #define xfs_dqtrace_entry_ino(a,b,ip) \
+-xfs_dqtrace_entry__((a), (b), (void*)__return_address, (ip))
++ __xfs_dqtrace_entry((a), (b), (void*)__return_address, (ip))
+ #define xfs_dqtrace_entry(a,b) \
+-xfs_dqtrace_entry__((a), (b), (void*)__return_address, NULL)
+-extern void xfs_dqtrace_entry__(xfs_dquot_t *dqp, char *func,
+- void *, xfs_inode_t *);
++ __xfs_dqtrace_entry((a), (b), (void*)__return_address, NULL)
+ #else
+ #define xfs_dqtrace_entry(a,b)
+ #define xfs_dqtrace_entry_ino(a,b,ip)
+ #endif
++
+ #ifdef QUOTADEBUG
+ extern void xfs_qm_dqprint(xfs_dquot_t *);
+ #else
+diff -urN linux.org/fs/xfs/quota/xfs_qm.c linux/fs/xfs/quota/xfs_qm.c
+--- linux.org/fs/xfs/quota/xfs_qm.c 2003-12-31 05:46:24.000000000 +0100
++++ linux/fs/xfs/quota/xfs_qm.c 2004-01-02 04:21:44.000000000 +0100
+@@ -82,6 +82,7 @@
+
+ kmem_zone_t *qm_dqzone;
+ kmem_zone_t *qm_dqtrxzone;
++kmem_shaker_t xfs_qm_shaker;
+
+ STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
+ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
+@@ -112,8 +113,6 @@
+ #define XQM_LIST_PRINT(l, NXT, title) do { } while (0)
+ #endif
+
+-struct shrinker *xfs_qm_shrinker;
+-
+ /*
+ * Initialize the XQM structure.
+ * Note that there is not one quota manager per file system.
+@@ -163,7 +162,7 @@
+ } else
+ xqm->qm_dqzone = qm_dqzone;
+
+- xfs_qm_shrinker = set_shrinker(DEFAULT_SEEKS, xfs_qm_shake);
++ xfs_qm_shaker = kmem_shake_register(xfs_qm_shake);
+
+ /*
+ * The t_dqinfo portion of transactions.
+@@ -195,8 +194,7 @@
+
+ ASSERT(xqm != NULL);
+ ASSERT(xqm->qm_nrefs == 0);
+-
+- remove_shrinker(xfs_qm_shrinker);
++ kmem_shake_deregister(xfs_qm_shaker);
+ hsize = xqm->qm_dqhashmask + 1;
+ for (i = 0; i < hsize; i++) {
+ xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
+@@ -806,7 +804,6 @@
+ ASSERT(XFS_DQ_IS_LOCKED(dqp));
+ if (! dolock) {
+ xfs_dqunlock(dqp);
+- ASSERT(!udqhint || !XFS_DQ_IS_LOCKED(udqhint));
+ goto done;
+ }
+ if (! udqhint)
+@@ -814,7 +811,6 @@
+
+ ASSERT(udqhint);
+ ASSERT(dolock);
+- ASSERT(! XFS_DQ_IS_LOCKED(udqhint));
+ ASSERT(XFS_DQ_IS_LOCKED(dqp));
+ if (! xfs_qm_dqlock_nowait(udqhint)) {
+ xfs_dqunlock(dqp);
+@@ -826,14 +822,10 @@
+ if (udqhint) {
+ if (dolock)
+ ASSERT(XFS_DQ_IS_LOCKED(udqhint));
+- else
+- ASSERT(! XFS_DQ_IS_LOCKED(udqhint));
+ }
+ if (! error) {
+ if (dolock)
+ ASSERT(XFS_DQ_IS_LOCKED(dqp));
+- else
+- ASSERT(! XFS_DQ_IS_LOCKED(dqp));
+ }
+ #endif
+ return (error);
+@@ -860,9 +852,6 @@
+ if (locked) {
+ ASSERT(XFS_DQ_IS_LOCKED(udq));
+ ASSERT(XFS_DQ_IS_LOCKED(gdq));
+- } else {
+- ASSERT(! XFS_DQ_IS_LOCKED(udq));
+- ASSERT(! XFS_DQ_IS_LOCKED(gdq));
+ }
+ #endif
+ if (! locked)
+@@ -890,15 +879,12 @@
+ */
+ xfs_qm_dqrele(tmp);
+
+- ASSERT(! XFS_DQ_IS_LOCKED(udq));
+- ASSERT(! XFS_DQ_IS_LOCKED(gdq));
+ xfs_dqlock(udq);
+ xfs_dqlock(gdq);
+
+ } else {
+ ASSERT(XFS_DQ_IS_LOCKED(udq));
+ if (! locked) {
+- ASSERT(! XFS_DQ_IS_LOCKED(gdq));
+ xfs_dqlock(gdq);
+ }
+ }
+@@ -1006,14 +992,10 @@
+ if (ip->i_udquot) {
+ if (flags & XFS_QMOPT_DQLOCK)
+ ASSERT(XFS_DQ_IS_LOCKED(ip->i_udquot));
+- else
+- ASSERT(! XFS_DQ_IS_LOCKED(ip->i_udquot));
+ }
+ if (ip->i_gdquot) {
+ if (flags & XFS_QMOPT_DQLOCK)
+ ASSERT(XFS_DQ_IS_LOCKED(ip->i_gdquot));
+- else
+- ASSERT(! XFS_DQ_IS_LOCKED(ip->i_gdquot));
+ }
+ if (XFS_IS_UQUOTA_ON(mp))
+ ASSERT(ip->i_udquot);
+@@ -1756,7 +1738,10 @@
+ xfs_trans_t *tp, /* transaction pointer - NULL */
+ xfs_ino_t ino, /* inode number to get data for */
+ void *buffer, /* not used */
++ int ubsize, /* not used */
++ void *private_data, /* not used */
+ xfs_daddr_t bno, /* starting block of inode cluster */
++ int *ubused, /* not used */
+ void *dip, /* on-disk inode pointer (not used) */
+ int *res) /* result code value */
+ {
+@@ -1920,7 +1905,7 @@
+ * adjusting the corresponding dquot counters in core.
+ */
+ if ((error = xfs_bulkstat(mp, NULL, &lastino, &count,
+- xfs_qm_dqusage_adjust,
++ xfs_qm_dqusage_adjust, NULL,
+ structsz, NULL,
+ BULKSTAT_FG_IGET|BULKSTAT_FG_VFSLOCKED,
+ &done)))
+@@ -2091,7 +2076,7 @@
+ xfs_dqunlock(dqp);
+ xfs_qm_freelist_unlock(xfs_Gqm);
+ if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
+- goto out;
++ return (nreclaimed);
+ XQM_STATS_INC(xqmstats.xs_qm_dqwants);
+ goto tryagain;
+ }
+@@ -2166,7 +2151,7 @@
+ XFS_DQ_HASH_UNLOCK(hash);
+ xfs_qm_freelist_unlock(xfs_Gqm);
+ if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
+- goto out;
++ return (nreclaimed);
+ goto tryagain;
+ }
+ xfs_dqtrace_entry(dqp, "DQSHAKE: UNLINKING");
+@@ -2191,14 +2176,12 @@
+ dqp = nextdqp;
+ }
+ xfs_qm_freelist_unlock(xfs_Gqm);
+- out:
+- return nreclaimed;
++ return (nreclaimed);
+ }
+
+
+ /*
+- * The shake manager routine called by shaked() when memory is
+- * running low.
++ * The kmem_shake interface is invoked when memory is running low.
+ */
+ /* ARGSUSED */
+ STATIC int
+@@ -2206,10 +2189,10 @@
+ {
+ int ndqused, nfree, n;
+
+- if (!(gfp_mask & __GFP_WAIT))
+- return 0;
++ if (!kmem_shake_allow(gfp_mask))
++ return (0);
+ if (!xfs_Gqm)
+- return 0;
++ return (0);
+
+ nfree = xfs_Gqm->qm_dqfreelist.qh_nelems; /* free dquots */
+ /* incore dquots in all f/s's */
+@@ -2218,7 +2201,7 @@
+ ASSERT(ndqused >= 0);
+
+ if (nfree <= ndqused && nfree < ndquot)
+- return 0;
++ return (0);
+
+ ndqused *= xfs_Gqm->qm_dqfree_ratio; /* target # of free dquots */
+ n = nfree - ndqused - ndquot; /* # over target */
+diff -urN linux.org/fs/xfs/quota/xfs_qm_syscalls.c linux/fs/xfs/quota/xfs_qm_syscalls.c
+--- linux.org/fs/xfs/quota/xfs_qm_syscalls.c 2003-12-31 05:47:47.000000000 +0100
++++ linux/fs/xfs/quota/xfs_qm_syscalls.c 2004-01-02 04:21:44.000000000 +0100
+@@ -1301,7 +1301,10 @@
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_ino_t ino, /* inode number to get data for */
+ void *buffer, /* not used */
++ int ubsize, /* not used */
++ void *private_data, /* not used */
+ xfs_daddr_t bno, /* starting block of inode cluster */
++ int *ubused, /* not used */
+ void *dip, /* not used */
+ int *res) /* bulkstat result code */
+ {
+@@ -1403,7 +1406,7 @@
+ * adjusting the corresponding dquot counters
+ */
+ if ((error = xfs_bulkstat(mp, NULL, &lastino, &count,
+- xfs_qm_internalqcheck_adjust,
++ xfs_qm_internalqcheck_adjust, NULL,
+ 0, NULL, BULKSTAT_FG_IGET, &done))) {
+ break;
+ }
+diff -urN linux.org/fs/xfs/quota/xfs_trans_dquot.c linux/fs/xfs/quota/xfs_trans_dquot.c
+--- linux.org/fs/xfs/quota/xfs_trans_dquot.c 2003-12-31 05:46:41.000000000 +0100
++++ linux/fs/xfs/quota/xfs_trans_dquot.c 2004-01-02 04:21:44.000000000 +0100
+@@ -835,13 +835,6 @@
+ ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
+ ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
+
+-#ifdef QUOTADEBUG
+- if (ip->i_udquot)
+- ASSERT(! XFS_DQ_IS_LOCKED(ip->i_udquot));
+- if (ip->i_gdquot)
+- ASSERT(! XFS_DQ_IS_LOCKED(ip->i_gdquot));
+-#endif
+-
+ ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+ ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
+ ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||
+diff -urN linux.org/fs/xfs/support/debug.h linux/fs/xfs/support/debug.h
+--- linux.org/fs/xfs/support/debug.h 2003-12-31 05:48:49.000000000 +0100
++++ linux/fs/xfs/support/debug.h 2004-01-02 04:21:44.000000000 +0100
+@@ -44,6 +44,10 @@
+ extern void icmn_err(int, char *, va_list);
+ extern void cmn_err(int, char *, ...);
+
++#ifndef STATIC
++# define STATIC static
++#endif
++
+ #ifdef DEBUG
+ # ifdef lint
+ # define ASSERT(EX) ((void)0) /* avoid "constant in conditional" babble */
+diff -urN linux.org/fs/xfs/support/kmem.h linux/fs/xfs/support/kmem.h
+--- linux.org/fs/xfs/support/kmem.h 2003-12-31 05:48:56.000000000 +0100
++++ linux/fs/xfs/support/kmem.h 2004-01-02 04:21:44.000000000 +0100
+@@ -165,4 +165,25 @@
+ kmem_cache_free(zone, ptr);
+ }
+
++typedef struct shrinker *kmem_shaker_t;
++typedef int (*kmem_shake_func_t)(int, unsigned int);
++
++static __inline kmem_shaker_t
++kmem_shake_register(kmem_shake_func_t sfunc)
++{
++ return set_shrinker(DEFAULT_SEEKS, sfunc);
++}
++
++static __inline void
++kmem_shake_deregister(kmem_shaker_t shrinker)
++{
++ remove_shrinker(shrinker);
++}
++
++static __inline int
++kmem_shake_allow(unsigned int gfp_mask)
++{
++ return (gfp_mask & __GFP_WAIT);
++}
++
+ #endif /* __XFS_SUPPORT_KMEM_H__ */
+diff -urN linux.org/fs/xfs/support/ktrace.c linux/fs/xfs/support/ktrace.c
+--- linux.org/fs/xfs/support/ktrace.c 2003-12-31 05:47:09.000000000 +0100
++++ linux/fs/xfs/support/ktrace.c 2004-01-02 04:21:44.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -40,8 +40,6 @@
+ #include "debug.h"
+ #include "ktrace.h"
+
+-#if (defined(DEBUG) || defined(CONFIG_XFS_VNODE_TRACING))
+-
+ static kmem_zone_t *ktrace_hdr_zone;
+ static kmem_zone_t *ktrace_ent_zone;
+ static int ktrace_zentries;
+@@ -121,7 +119,6 @@
+ ktp->kt_nentries = nentries;
+ ktp->kt_index = 0;
+ ktp->kt_rollover = 0;
+-
+ return ktp;
+ }
+
+@@ -182,6 +179,7 @@
+ void *val15)
+ {
+ static lock_t wrap_lock = SPIN_LOCK_UNLOCKED;
++ unsigned long flags;
+ int index;
+ ktrace_entry_t *ktep;
+
+@@ -190,11 +188,11 @@
+ /*
+ * Grab an entry by pushing the index up to the next one.
+ */
+- spin_lock(&wrap_lock);
++ spin_lock_irqsave(&wrap_lock, flags);
+ index = ktp->kt_index;
+ if (++ktp->kt_index == ktp->kt_nentries)
+ ktp->kt_index = 0;
+- spin_unlock(&wrap_lock);
++ spin_unlock_irqrestore(&wrap_lock, flags);
+
+ if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
+ ktp->kt_rollover = 1;
+@@ -235,7 +233,6 @@
+ return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
+ }
+
+-
+ /*
+ * ktrace_first()
+ *
+@@ -276,7 +273,7 @@
+ }
+ return ktep;
+ }
+-
++EXPORT_SYMBOL(ktrace_first);
+
+ /*
+ * ktrace_next()
+@@ -311,11 +308,7 @@
+
+ return ktep;
+ }
+-
+-#if (defined(DEBUG) || defined(CONFIG_XFS_VNODE_TRACING))
+-EXPORT_SYMBOL(ktrace_first);
+ EXPORT_SYMBOL(ktrace_next);
+-#endif
+
+ /*
+ * ktrace_skip()
+@@ -323,7 +316,6 @@
+ * Skip the next "count" entries and return the entry after that.
+ * Return NULL if this causes us to iterate past the beginning again.
+ */
+-
+ ktrace_entry_t *
+ ktrace_skip(
+ ktrace_t *ktp,
+@@ -362,18 +354,3 @@
+ }
+ return ktep;
+ }
+-
+-#else
+-
+-ktrace_t *
+-ktrace_alloc(int nentries, int sleep)
+-{
+- /*
+- * KM_SLEEP callers don't expect failure.
+- */
+- if (sleep & KM_SLEEP)
+- panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
+-
+- return NULL;
+-}
+-#endif
+diff -urN linux.org/fs/xfs/support/ktrace.h linux/fs/xfs/support/ktrace.h
+--- linux.org/fs/xfs/support/ktrace.h 2003-12-31 05:47:26.000000000 +0100
++++ linux/fs/xfs/support/ktrace.h 2004-01-02 04:21:44.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -32,6 +32,7 @@
+ #ifndef __XFS_SUPPORT_KTRACE_H__
+ #define __XFS_SUPPORT_KTRACE_H__
+
++#include <support/spin.h>
+
+ /*
+ * Trace buffer entry structure.
+@@ -59,16 +60,13 @@
+ int ks_index; /* current index */
+ } ktrace_snap_t;
+
+-/*
+- * Exported interfaces.
+- */
+-extern ktrace_t *ktrace_alloc(int, int);
+
+-#if (defined(DEBUG) || defined(CONFIG_XFS_VNODE_TRACING))
++#ifdef CONFIG_XFS_TRACE
+
+ extern void ktrace_init(int zentries);
+ extern void ktrace_uninit(void);
+
++extern ktrace_t *ktrace_alloc(int, int);
+ extern void ktrace_free(ktrace_t *);
+
+ extern void ktrace_enter(
+@@ -96,10 +94,8 @@
+ extern ktrace_entry_t *ktrace_skip(ktrace_t *, int, ktrace_snap_t *);
+
+ #else
++#define ktrace_init(x) do { } while (0)
++#define ktrace_uninit() do { } while (0)
++#endif /* CONFIG_XFS_TRACE */
+
+-#define ktrace_free(ktp)
+-#define ktrace_enter(ktp,v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15)
+-
+-#endif
+-
+-#endif /* __XFS_SUPPORT_KTRACE_H__ */
++#endif /* __XFS_SUPPORT_KTRACE_H__ */
+diff -urN linux.org/fs/xfs/support/qsort.c linux/fs/xfs/support/qsort.c
+--- linux.org/fs/xfs/support/qsort.c 2003-12-31 05:48:26.000000000 +0100
++++ linux/fs/xfs/support/qsort.c 2004-01-02 04:21:44.000000000 +0100
+@@ -1,243 +1,155 @@
+-/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+- Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, write to the Free
+- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+- 02111-1307 USA. */
+-
+-/* If you consider tuning this algorithm, you should consult first:
+- Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
+- Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
++/*
++ * Copyright (c) 1992, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
+
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+
+-/* Byte-wise swap two items of size SIZE. */
+-#define SWAP(a, b, size) \
+- do \
+- { \
+- register size_t __size = (size); \
+- register char *__a = (a), *__b = (b); \
+- do \
+- { \
+- char __tmp = *__a; \
+- *__a++ = *__b; \
+- *__b++ = __tmp; \
+- } while (--__size > 0); \
+- } while (0)
+-
+-/* Discontinue quicksort algorithm when partition gets below this size.
+- This particular magic number was chosen to work best on a Sun 4/260. */
+-#define MAX_THRESH 4
+-
+-/* Stack node declarations used to store unfulfilled partition obligations. */
+-typedef struct
+- {
+- char *lo;
+- char *hi;
+- } stack_node;
+-
+-/* The next 4 #defines implement a very fast in-line stack abstraction. */
+-/* The stack needs log (total_elements) entries (we could even subtract
+- log(MAX_THRESH)). Since total_elements has type size_t, we get as
+- upper bound for log (total_elements):
+- bits per byte (CHAR_BIT) * sizeof(size_t). */
+-#define STACK_SIZE (8 * sizeof(unsigned long int))
+-#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
+-#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
+-#define STACK_NOT_EMPTY (stack < top)
+-
+-
+-/* Order size using quicksort. This implementation incorporates
+- four optimizations discussed in Sedgewick:
+-
+- 1. Non-recursive, using an explicit stack of pointer that store the
+- next array partition to sort. To save time, this maximum amount
+- of space required to store an array of SIZE_MAX is allocated on the
+- stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
+- only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
+- Pretty cheap, actually.
+-
+- 2. Chose the pivot element using a median-of-three decision tree.
+- This reduces the probability of selecting a bad pivot value and
+- eliminates certain extraneous comparisons.
+-
+- 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
+- insertion sort to order the MAX_THRESH items within each partition.
+- This is a big win, since insertion sort is faster for small, mostly
+- sorted array segments.
+-
+- 4. The larger of the two sub-partitions is always pushed onto the
+- stack first, with the algorithm then concentrating on the
+- smaller partition. This *guarantees* no more than log (total_elems)
+- stack size is needed (actually O(1) in this case)! */
++/*
++ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
++ */
++#define swapcode(TYPE, parmi, parmj, n) { \
++ long i = (n) / sizeof (TYPE); \
++ register TYPE *pi = (TYPE *) (parmi); \
++ register TYPE *pj = (TYPE *) (parmj); \
++ do { \
++ register TYPE t = *pi; \
++ *pi++ = *pj; \
++ *pj++ = t; \
++ } while (--i > 0); \
++}
+
+-void
+-qsort (void *const pbase, size_t total_elems, size_t size,
+- int (*cmp)(const void *, const void *))
++#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
++ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
++
++static __inline void
++swapfunc(char *a, char *b, int n, int swaptype)
+ {
+- register char *base_ptr = (char *) pbase;
++ if (swaptype <= 1)
++ swapcode(long, a, b, n)
++ else
++ swapcode(char, a, b, n)
++}
+
+- const size_t max_thresh = MAX_THRESH * size;
++#define swap(a, b) \
++ if (swaptype == 0) { \
++ long t = *(long *)(a); \
++ *(long *)(a) = *(long *)(b); \
++ *(long *)(b) = t; \
++ } else \
++ swapfunc(a, b, es, swaptype)
+
+- if (total_elems == 0)
+- /* Avoid lossage with unsigned arithmetic below. */
+- return;
+-
+- if (total_elems > MAX_THRESH)
+- {
+- char *lo = base_ptr;
+- char *hi = &lo[size * (total_elems - 1)];
+- stack_node stack[STACK_SIZE];
+- stack_node *top = stack + 1;
+-
+- while (STACK_NOT_EMPTY)
+- {
+- char *left_ptr;
+- char *right_ptr;
+-
+- /* Select median value from among LO, MID, and HI. Rearrange
+- LO and HI so the three values are sorted. This lowers the
+- probability of picking a pathological pivot value and
+- skips a comparison for both the LEFT_PTR and RIGHT_PTR in
+- the while loops. */
+-
+- char *mid = lo + size * ((hi - lo) / size >> 1);
+-
+- if ((*cmp) ((void *) mid, (void *) lo) < 0)
+- SWAP (mid, lo, size);
+- if ((*cmp) ((void *) hi, (void *) mid) < 0)
+- SWAP (mid, hi, size);
+- else
+- goto jump_over;
+- if ((*cmp) ((void *) mid, (void *) lo) < 0)
+- SWAP (mid, lo, size);
+- jump_over:;
+-
+- left_ptr = lo + size;
+- right_ptr = hi - size;
+-
+- /* Here's the famous ``collapse the walls'' section of quicksort.
+- Gotta like those tight inner loops! They are the main reason
+- that this algorithm runs much faster than others. */
+- do
+- {
+- while ((*cmp) ((void *) left_ptr, (void *) mid) < 0)
+- left_ptr += size;
+-
+- while ((*cmp) ((void *) mid, (void *) right_ptr) < 0)
+- right_ptr -= size;
+-
+- if (left_ptr < right_ptr)
+- {
+- SWAP (left_ptr, right_ptr, size);
+- if (mid == left_ptr)
+- mid = right_ptr;
+- else if (mid == right_ptr)
+- mid = left_ptr;
+- left_ptr += size;
+- right_ptr -= size;
+- }
+- else if (left_ptr == right_ptr)
+- {
+- left_ptr += size;
+- right_ptr -= size;
+- break;
++#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
++
++static __inline char *
++med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
++{
++ return cmp(a, b) < 0 ?
++ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
++ :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
++}
++
++void
++qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
++{
++ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
++ int d, r, swaptype, swap_cnt;
++ register char *a = aa;
++
++loop: SWAPINIT(a, es);
++ swap_cnt = 0;
++ if (n < 7) {
++ for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
++ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
++ pl -= es)
++ swap(pl, pl - es);
++ return;
++ }
++ pm = (char *)a + (n / 2) * es;
++ if (n > 7) {
++ pl = (char *)a;
++ pn = (char *)a + (n - 1) * es;
++ if (n > 40) {
++ d = (n / 8) * es;
++ pl = med3(pl, pl + d, pl + 2 * d, cmp);
++ pm = med3(pm - d, pm, pm + d, cmp);
++ pn = med3(pn - 2 * d, pn - d, pn, cmp);
+ }
+- }
+- while (left_ptr <= right_ptr);
++ pm = med3(pl, pm, pn, cmp);
++ }
++ swap(a, pm);
++ pa = pb = (char *)a + es;
+
+- /* Set up pointers for next iteration. First determine whether
+- left and right partitions are below the threshold size. If so,
+- ignore one or both. Otherwise, push the larger partition's
+- bounds on the stack and continue sorting the smaller one. */
+-
+- if ((size_t) (right_ptr - lo) <= max_thresh)
+- {
+- if ((size_t) (hi - left_ptr) <= max_thresh)
+- /* Ignore both small partitions. */
+- POP (lo, hi);
+- else
+- /* Ignore small left partition. */
+- lo = left_ptr;
+- }
+- else if ((size_t) (hi - left_ptr) <= max_thresh)
+- /* Ignore small right partition. */
+- hi = right_ptr;
+- else if ((right_ptr - lo) > (hi - left_ptr))
+- {
+- /* Push larger left partition indices. */
+- PUSH (lo, right_ptr);
+- lo = left_ptr;
+- }
+- else
+- {
+- /* Push larger right partition indices. */
+- PUSH (left_ptr, hi);
+- hi = right_ptr;
+- }
++ pc = pd = (char *)a + (n - 1) * es;
++ for (;;) {
++ while (pb <= pc && (r = cmp(pb, a)) <= 0) {
++ if (r == 0) {
++ swap_cnt = 1;
++ swap(pa, pb);
++ pa += es;
++ }
++ pb += es;
++ }
++ while (pb <= pc && (r = cmp(pc, a)) >= 0) {
++ if (r == 0) {
++ swap_cnt = 1;
++ swap(pc, pd);
++ pd -= es;
++ }
++ pc -= es;
++ }
++ if (pb > pc)
++ break;
++ swap(pb, pc);
++ swap_cnt = 1;
++ pb += es;
++ pc -= es;
++ }
++ if (swap_cnt == 0) { /* Switch to insertion sort */
++ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
++ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
++ pl -= es)
++ swap(pl, pl - es);
++ return;
+ }
+- }
+
+- /* Once the BASE_PTR array is partially sorted by quicksort the rest
+- is completely sorted using insertion sort, since this is efficient
+- for partitions below MAX_THRESH size. BASE_PTR points to the beginning
+- of the array to sort, and END_PTR points at the very last element in
+- the array (*not* one beyond it!). */
+- {
+- char *const end_ptr = &base_ptr[size * (total_elems - 1)];
+- char *tmp_ptr = base_ptr;
+- char *const thresh = min_t(char *const, end_ptr, base_ptr + max_thresh);
+- register char *run_ptr;
+-
+- /* Find smallest element in first threshold and place it at the
+- array's beginning. This is the smallest array element,
+- and the operation speeds up insertion sort's inner loop. */
+-
+- for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
+- if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+- tmp_ptr = run_ptr;
+-
+- if (tmp_ptr != base_ptr)
+- SWAP (tmp_ptr, base_ptr, size);
+-
+- /* Insertion sort, running from left-hand-side up to right-hand-side. */
+-
+- run_ptr = base_ptr + size;
+- while ((run_ptr += size) <= end_ptr)
+- {
+- tmp_ptr = run_ptr - size;
+- while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+- tmp_ptr -= size;
+-
+- tmp_ptr += size;
+- if (tmp_ptr != run_ptr)
+- {
+- char *trav;
+-
+- trav = run_ptr + size;
+- while (--trav >= run_ptr)
+- {
+- char c = *trav;
+- char *hi, *lo;
+-
+- for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
+- *hi = *lo;
+- *hi = c;
+- }
+- }
+- }
+- }
++ pn = (char *)a + n * es;
++ r = min(pa - (char *)a, pb - pa);
++ vecswap(a, pb - r, r);
++ r = min((long)(pd - pc), (long)(pn - pd - es));
++ vecswap(pb, pn - r, r);
++ if ((r = pb - pa) > es)
++ qsort(a, r / es, es, cmp);
++ if ((r = pd - pc) > es) {
++ /* Iterate rather than recurse to save stack space */
++ a = pn - r;
++ n = r / es;
++ goto loop;
++ }
++/* qsort(pn - r, r / es, es, cmp);*/
+ }
+diff -urN linux.org/fs/xfs/xfs_acl.h linux/fs/xfs/xfs_acl.h
+--- linux.org/fs/xfs/xfs_acl.h 2003-12-31 05:47:08.000000000 +0100
++++ linux/fs/xfs/xfs_acl.h 2004-01-02 04:21:42.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2001-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * Copyright (c) 2001-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
+@@ -102,6 +102,8 @@
+ #define xfs_acl_vset(v,p,sz,t) (-EOPNOTSUPP)
+ #define xfs_acl_vget(v,p,sz,t) (-EOPNOTSUPP)
+ #define xfs_acl_vremove(v,t) (-EOPNOTSUPP)
++#define xfs_acl_vhasacl_access(v) (0)
++#define xfs_acl_vhasacl_default(v) (0)
+ #define _ACL_DECL(a) ((void)0)
+ #define _ACL_ALLOC(a) (1) /* successfully allocate nothing */
+ #define _ACL_FREE(a) ((void)0)
+diff -urN linux.org/fs/xfs/xfs_alloc.c linux/fs/xfs/xfs_alloc.c
+--- linux.org/fs/xfs/xfs_alloc.c 2003-12-31 05:46:44.000000000 +0100
++++ linux/fs/xfs/xfs_alloc.c 2004-01-02 04:21:42.000000000 +0100
+@@ -54,13 +54,6 @@
+ #include "xfs_error.h"
+
+
+-#if defined(DEBUG)
+-/*
+- * Allocation tracing.
+- */
+-ktrace_t *xfs_alloc_trace_buf;
+-#endif
+-
+ #define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
+
+ #define XFSA_FIXUP_BNO_OK 1
+@@ -73,6 +66,8 @@
+ xfs_extlen_t len);
+
+ #if defined(XFS_ALLOC_TRACE)
++ktrace_t *xfs_alloc_trace_buf;
++
+ #define TRACE_ALLOC(s,a) \
+ xfs_alloc_trace_alloc(fname, s, a, __LINE__)
+ #define TRACE_FREE(s,a,b,x,f) \
+@@ -85,8 +80,6 @@
+ xfs_alloc_trace_busy(fname, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
+ #define TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp) \
+ xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
+-
+-
+ #else
+ #define TRACE_ALLOC(s,a)
+ #define TRACE_FREE(s,a,b,x,f)
+diff -urN linux.org/fs/xfs/xfs_alloc.h linux/fs/xfs/xfs_alloc.h
+--- linux.org/fs/xfs/xfs_alloc.h 2003-12-31 05:46:56.000000000 +0100
++++ linux/fs/xfs/xfs_alloc.h 2004-01-02 04:21:42.000000000 +0100
+@@ -95,6 +95,13 @@
+
+ #ifdef __KERNEL__
+
++#if defined(XFS_ALLOC_TRACE)
++/*
++ * Allocation tracing buffer size.
++ */
++#define XFS_ALLOC_TRACE_SIZE 4096
++extern ktrace_t *xfs_alloc_trace_buf;
++
+ /*
+ * Types for alloc tracing.
+ */
+@@ -104,26 +111,9 @@
+ #define XFS_ALLOC_KTRACE_BUSY 4
+ #define XFS_ALLOC_KTRACE_UNBUSY 5
+ #define XFS_ALLOC_KTRACE_BUSYSEARCH 6
+-
+-
+-/*
+- * Allocation tracing buffer size.
+- */
+-#define XFS_ALLOC_TRACE_SIZE 4096
+-
+-#ifdef XFS_ALL_TRACE
+-#define XFS_ALLOC_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_ALLOC_TRACE
+ #endif
+
+ /*
+- * Prototypes for visible xfs_alloc.c routines
+- */
+-
+-/*
+ * Compute and fill in value of m_ag_maxlevels.
+ */
+ void
+diff -urN linux.org/fs/xfs/xfs_arch.h linux/fs/xfs/xfs_arch.h
+--- linux.org/fs/xfs/xfs_arch.h 2003-12-31 05:48:14.000000000 +0100
++++ linux/fs/xfs/xfs_arch.h 2004-01-02 04:21:42.000000000 +0100
+@@ -53,16 +53,18 @@
+
+ #define ARCH_NOCONVERT 1
+ #if __BYTE_ORDER == __LITTLE_ENDIAN
+-#define ARCH_CONVERT 0
++# define ARCH_CONVERT 0
+ #else
+-#define ARCH_CONVERT ARCH_NOCONVERT
++# define ARCH_CONVERT ARCH_NOCONVERT
+ #endif
+
+ /* generic swapping macros */
+
++#ifndef HAVE_SWABMACROS
+ #define INT_SWAP16(type,var) ((typeof(type))(__swab16((__u16)(var))))
+ #define INT_SWAP32(type,var) ((typeof(type))(__swab32((__u32)(var))))
+ #define INT_SWAP64(type,var) ((typeof(type))(__swab64((__u64)(var))))
++#endif
+
+ #define INT_SWAP(type, var) \
+ ((sizeof(type) == 8) ? INT_SWAP64(type,var) : \
+diff -urN linux.org/fs/xfs/xfs_attr.c linux/fs/xfs/xfs_attr.c
+--- linux.org/fs/xfs/xfs_attr.c 2003-12-31 05:47:38.000000000 +0100
++++ linux/fs/xfs/xfs_attr.c 2004-01-02 04:21:42.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -63,6 +63,7 @@
+ #include "xfs_quota.h"
+ #include "xfs_rw.h"
+ #include "xfs_trans_space.h"
++#include "xfs_acl.h"
+
+ /*
+ * xfs_attr.c
+@@ -2234,7 +2235,8 @@
+ (__psunsigned_t)context->count,
+ (__psunsigned_t)context->firstu,
+ (__psunsigned_t)
+- (context->count > 0)
++ ((context->count > 0) &&
++ !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
+ ? (ATTR_ENTRY(context->alist,
+ context->count-1)->a_valuelen)
+ : 0,
+@@ -2262,7 +2264,8 @@
+ (__psunsigned_t)context->count,
+ (__psunsigned_t)context->firstu,
+ (__psunsigned_t)
+- (context->count > 0)
++ ((context->count > 0) &&
++ !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
+ ? (ATTR_ENTRY(context->alist,
+ context->count-1)->a_valuelen)
+ : 0,
+@@ -2290,7 +2293,8 @@
+ (__psunsigned_t)context->count,
+ (__psunsigned_t)context->firstu,
+ (__psunsigned_t)
+- (context->count > 0)
++ ((context->count > 0) &&
++ !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
+ ? (ATTR_ENTRY(context->alist,
+ context->count-1)->a_valuelen)
+ : 0,
+@@ -2318,7 +2322,8 @@
+ (__psunsigned_t)context->count,
+ (__psunsigned_t)context->firstu,
+ (__psunsigned_t)
+- (context->count > 0)
++ ((context->count > 0) &&
++ !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
+ ? (ATTR_ENTRY(context->alist,
+ context->count-1)->a_valuelen)
+ : 0,
+@@ -2353,3 +2358,307 @@
+ (void *)a14, (void *)a15);
+ }
+ #endif /* XFS_ATTR_TRACE */
++
++
++/*========================================================================
++ * System (pseudo) namespace attribute interface routines.
++ *========================================================================*/
++
++STATIC int
++posix_acl_access_set(
++ vnode_t *vp, char *name, void *data, size_t size, int xflags)
++{
++ return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
++}
++
++STATIC int
++posix_acl_access_remove(
++ struct vnode *vp, char *name, int xflags)
++{
++ return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
++}
++
++STATIC int
++posix_acl_access_get(
++ vnode_t *vp, char *name, void *data, size_t size, int xflags)
++{
++ return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
++}
++
++STATIC int
++posix_acl_access_exists(
++ vnode_t *vp)
++{
++ return xfs_acl_vhasacl_access(vp);
++}
++
++STATIC int
++posix_acl_default_set(
++ vnode_t *vp, char *name, void *data, size_t size, int xflags)
++{
++ return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
++}
++
++STATIC int
++posix_acl_default_get(
++ vnode_t *vp, char *name, void *data, size_t size, int xflags)
++{
++ return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
++}
++
++STATIC int
++posix_acl_default_remove(
++ struct vnode *vp, char *name, int xflags)
++{
++ return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
++}
++
++STATIC int
++posix_acl_default_exists(
++ vnode_t *vp)
++{
++ return xfs_acl_vhasacl_default(vp);
++}
++
++struct attrnames posix_acl_access = {
++ .attr_name = "posix_acl_access",
++ .attr_namelen = sizeof("posix_acl_access") - 1,
++ .attr_get = posix_acl_access_get,
++ .attr_set = posix_acl_access_set,
++ .attr_remove = posix_acl_access_remove,
++ .attr_exists = posix_acl_access_exists,
++};
++
++struct attrnames posix_acl_default = {
++ .attr_name = "posix_acl_default",
++ .attr_namelen = sizeof("posix_acl_default") - 1,
++ .attr_get = posix_acl_default_get,
++ .attr_set = posix_acl_default_set,
++ .attr_remove = posix_acl_default_remove,
++ .attr_exists = posix_acl_default_exists,
++};
++
++struct attrnames *attr_system_names[] =
++ { &posix_acl_access, &posix_acl_default };
++
++
++/*========================================================================
++ * Namespace-prefix-style attribute name interface routines.
++ *========================================================================*/
++
++STATIC int
++attr_generic_set(
++ struct vnode *vp, char *name, void *data, size_t size, int xflags)
++{
++ int error;
++
++ VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error);
++ return -error;
++}
++
++STATIC int
++attr_generic_get(
++ struct vnode *vp, char *name, void *data, size_t size, int xflags)
++{
++ int error, asize = size;
++
++ VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error);
++ if (!error)
++ return asize;
++ return -error;
++}
++
++STATIC int
++attr_generic_remove(
++ struct vnode *vp, char *name, int xflags)
++{
++ int error;
++
++ VOP_ATTR_REMOVE(vp, name, xflags, NULL, error);
++ return -error;
++}
++
++STATIC int
++attr_generic_listadd(
++ attrnames_t *prefix,
++ attrnames_t *namesp,
++ void *data,
++ size_t size,
++ ssize_t *result)
++{
++ char *p = data + *result;
++
++ *result += prefix->attr_namelen;
++ *result += namesp->attr_namelen + 1;
++ if (!size)
++ return 0;
++ if (*result > size)
++ return -ERANGE;
++ strcpy(p, prefix->attr_name);
++ p += prefix->attr_namelen;
++ strcpy(p, namesp->attr_name);
++ p += namesp->attr_namelen + 1;
++ return 0;
++}
++
++STATIC int
++attr_system_list(
++ struct vnode *vp,
++ void *data,
++ size_t size,
++ ssize_t *result)
++{
++ attrnames_t *namesp;
++ int i, error = 0;
++
++ for (i = 0; i < ATTR_SYSCOUNT; i++) {
++ namesp = attr_system_names[i];
++ if (!namesp->attr_exists || !namesp->attr_exists(vp))
++ continue;
++ error = attr_generic_listadd(&attr_system, namesp,
++ data, size, result);
++ if (error)
++ break;
++ }
++ return error;
++}
++
++int
++attr_generic_list(
++ struct vnode *vp, void *data, size_t size, int xflags, ssize_t *result)
++{
++ attrlist_cursor_kern_t cursor = { 0 };
++ int error;
++
++ VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error);
++ if (error > 0)
++ return -error;
++ *result = -error;
++ return attr_system_list(vp, data, size, result);
++}
++
++attrnames_t *
++attr_lookup_namespace(
++ char *name,
++ struct attrnames **names,
++ int nnames)
++{
++ int i;
++
++ for (i = 0; i < nnames; i++)
++ if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen))
++ return names[i];
++ return NULL;
++}
++
++/*
++ * Some checks to prevent people abusing EAs to get over quota:
++ * - Don't allow modifying user EAs on devices/symlinks;
++ * - Don't allow modifying user EAs if sticky bit set;
++ */
++STATIC int
++attr_user_capable(
++ struct vnode *vp,
++ cred_t *cred)
++{
++ struct inode *inode = LINVFS_GET_IP(vp);
++
++ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
++ return -EPERM;
++ if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
++ !capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
++ (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
++ return -EPERM;
++ return 0;
++}
++
++STATIC int
++attr_trusted_capable(
++ struct vnode *vp,
++ cred_t *cred)
++{
++ struct inode *inode = LINVFS_GET_IP(vp);
++
++ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
++ return -EPERM;
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ return 0;
++}
++
++STATIC int
++attr_system_set(
++ struct vnode *vp, char *name, void *data, size_t size, int xflags)
++{
++ attrnames_t *namesp;
++ int error;
++
++ if (xflags & ATTR_CREATE)
++ return -EINVAL;
++
++ namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
++ if (!namesp)
++ return -EOPNOTSUPP;
++ error = namesp->attr_set(vp, name, data, size, xflags);
++ if (!error)
++ error = vn_revalidate(vp);
++ return error;
++}
++
++STATIC int
++attr_system_get(
++ struct vnode *vp, char *name, void *data, size_t size, int xflags)
++{
++ attrnames_t *namesp;
++
++ namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
++ if (!namesp)
++ return -EOPNOTSUPP;
++ return namesp->attr_get(vp, name, data, size, xflags);
++}
++
++STATIC int
++attr_system_remove(
++ struct vnode *vp, char *name, int xflags)
++{
++ attrnames_t *namesp;
++
++ namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
++ if (!namesp)
++ return -EOPNOTSUPP;
++ return namesp->attr_remove(vp, name, xflags);
++}
++
++struct attrnames attr_system = {
++ .attr_name = "system.",
++ .attr_namelen = sizeof("system.") - 1,
++ .attr_flag = ATTR_SYSTEM,
++ .attr_get = attr_system_get,
++ .attr_set = attr_system_set,
++ .attr_remove = attr_system_remove,
++ .attr_capable = (attrcapable_t)fs_noerr,
++};
++
++struct attrnames attr_trusted = {
++ .attr_name = "trusted.",
++ .attr_namelen = sizeof("trusted.") - 1,
++ .attr_flag = ATTR_ROOT,
++ .attr_get = attr_generic_get,
++ .attr_set = attr_generic_set,
++ .attr_remove = attr_generic_remove,
++ .attr_capable = attr_trusted_capable,
++};
++
++struct attrnames attr_user = {
++ .attr_name = "user.",
++ .attr_namelen = sizeof("user.") - 1,
++ .attr_get = attr_generic_get,
++ .attr_set = attr_generic_set,
++ .attr_remove = attr_generic_remove,
++ .attr_capable = attr_user_capable,
++};
++
++struct attrnames *attr_namespaces[] =
++ { &attr_system, &attr_trusted, &attr_user };
+diff -urN linux.org/fs/xfs/xfs_attr.h linux/fs/xfs/xfs_attr.h
+--- linux.org/fs/xfs/xfs_attr.h 2003-12-31 05:46:42.000000000 +0100
++++ linux/fs/xfs/xfs_attr.h 2004-01-02 04:21:42.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
++ * Copyright (c) 2000, 2002-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
+@@ -45,22 +45,50 @@
+ * as possible so as to fit into the literal area of the inode.
+ */
+
+-#ifdef XFS_ALL_TRACE
+-#define XFS_ATTR_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_ATTR_TRACE
+-#endif
+-
+-
+ /*========================================================================
+ * External interfaces
+ *========================================================================*/
+
+-#define ATTR_ROOT 0x0002 /* use attrs in root namespace, not user */
++struct cred;
++struct vnode;
++
++typedef int (*attrset_t)(struct vnode *, char *, void *, size_t, int);
++typedef int (*attrget_t)(struct vnode *, char *, void *, size_t, int);
++typedef int (*attrremove_t)(struct vnode *, char *, int);
++typedef int (*attrexists_t)(struct vnode *);
++typedef int (*attrcapable_t)(struct vnode *, struct cred *);
++
++typedef struct attrnames {
++ char * attr_name;
++ unsigned int attr_namelen;
++ unsigned int attr_flag;
++ attrget_t attr_get;
++ attrset_t attr_set;
++ attrremove_t attr_remove;
++ attrexists_t attr_exists;
++ attrcapable_t attr_capable;
++} attrnames_t;
++
++#define ATTR_NAMECOUNT 3
++extern struct attrnames attr_user;
++extern struct attrnames attr_system;
++extern struct attrnames attr_trusted;
++extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
++
++#define ATTR_SYSCOUNT 2
++extern struct attrnames posix_acl_access;
++extern struct attrnames posix_acl_default;
++extern struct attrnames *attr_system_names[ATTR_SYSCOUNT];
++
++extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
++extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
++
++#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_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 */
+ #define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
+ #define ATTR_KERNOVAL 0x2000 /* [kernel] get attr size only, not value */
+ #define ATTR_KERNAMELS 0x4000 /* [kernel] list attr names (simple list) */
+@@ -135,11 +163,8 @@
+ * Function prototypes for the kernel.
+ *========================================================================*/
+
+-struct cred;
+-struct vnode;
+ struct xfs_inode;
+ struct attrlist_cursor_kern;
+-struct xfs_ext_attr;
+ struct xfs_da_args;
+
+ /*
+diff -urN linux.org/fs/xfs/xfs_attr_leaf.c linux/fs/xfs/xfs_attr_leaf.c
+--- linux.org/fs/xfs/xfs_attr_leaf.c 2003-12-31 05:47:15.000000000 +0100
++++ linux/fs/xfs/xfs_attr_leaf.c 2004-01-02 04:21:42.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -444,8 +444,10 @@
+ < context->bufsize) {
+ for (i = 0, sfe = &sf->list[0];
+ i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
+- int ns = (sfe->flags & XFS_ATTR_ROOT)?
+- ROOT_NAMES : USER_NAMES;
++ 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)) {
+@@ -454,11 +456,11 @@
+ }
+ if (context->flags & ATTR_KERNOVAL) {
+ ASSERT(context->flags & ATTR_KERNAMELS);
+- context->count += xfs_namespaces[ns].namelen +
++ context->count += namesp->attr_namelen +
+ INT_GET(sfe->namelen, ARCH_CONVERT) + 1;
+ }
+ else {
+- if (xfs_attr_put_listent(context, ns,
++ if (xfs_attr_put_listent(context, namesp,
+ (char *)sfe->nameval,
+ (int)sfe->namelen,
+ (int)INT_GET(sfe->valuelen,
+@@ -544,18 +546,22 @@
+ * Loop putting entries into the user buffer.
+ */
+ for ( ; i < nsbuf; i++, sbp++) {
+- int ns = (sbp->flags & XFS_ATTR_ROOT)? ROOT_NAMES:USER_NAMES;
++ attrnames_t *namesp;
++
++ namesp = (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);
+ cursor->offset = 0;
+ }
+ if (context->flags & ATTR_KERNOVAL) {
+ ASSERT(context->flags & ATTR_KERNAMELS);
+- context->count += xfs_namespaces[ns].namelen
+- + sbp->namelen + 1;
++ context->count += namesp->attr_namelen +
++ sbp->namelen + 1;
+ }
+ else {
+- if (xfs_attr_put_listent(context, ns,
++ if (xfs_attr_put_listent(context, namesp,
+ sbp->name, sbp->namelen,
+ INT_GET(sbp->valuelen, ARCH_CONVERT)))
+ break;
+@@ -2270,7 +2276,7 @@
+ retval = 0;
+ for ( ; (i < INT_GET(leaf->hdr.count, ARCH_CONVERT))
+ && (retval == 0); entry++, i++) {
+- int ns = (entry->flags & XFS_ATTR_ROOT)? ROOT_NAMES:USER_NAMES;
++ attrnames_t *namesp;
+
+ if (INT_GET(entry->hashval, ARCH_CONVERT) != cursor->hashval) {
+ cursor->hashval = INT_GET(entry->hashval, ARCH_CONVERT);
+@@ -2284,14 +2290,17 @@
+ !(context->flags & ATTR_KERNFULLS))
+ continue; /* skip non-matching entries */
+
++ namesp = (entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
++ &attr_user;
++
+ if (entry->flags & XFS_ATTR_LOCAL) {
+ name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
+ if (context->flags & ATTR_KERNOVAL) {
+ ASSERT(context->flags & ATTR_KERNAMELS);
+- context->count += xfs_namespaces[ns].namelen
+- + (int)name_loc->namelen + 1;
++ context->count += namesp->attr_namelen +
++ (int)name_loc->namelen + 1;
+ } else {
+- retval = xfs_attr_put_listent(context, ns,
++ retval = xfs_attr_put_listent(context, namesp,
+ (char *)name_loc->nameval,
+ (int)name_loc->namelen,
+ (int)INT_GET(name_loc->valuelen,
+@@ -2301,10 +2310,10 @@
+ name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
+ if (context->flags & ATTR_KERNOVAL) {
+ ASSERT(context->flags & ATTR_KERNAMELS);
+- context->count += xfs_namespaces[ns].namelen
+- + (int)name_rmt->namelen + 1;
++ context->count += namesp->attr_namelen +
++ (int)name_rmt->namelen + 1;
+ } else {
+- retval = xfs_attr_put_listent(context, ns,
++ retval = xfs_attr_put_listent(context, namesp,
+ (char *)name_rmt->name,
+ (int)name_rmt->namelen,
+ (int)INT_GET(name_rmt->valuelen,
+@@ -2333,7 +2342,7 @@
+ /*ARGSUSED*/
+ int
+ xfs_attr_put_listent(xfs_attr_list_context_t *context,
+- int ns, char *name, int namelen, int valuelen)
++ attrnames_t *namesp, char *name, int namelen, int valuelen)
+ {
+ attrlist_ent_t *aep;
+ int arraytop;
+@@ -2341,23 +2350,21 @@
+ ASSERT(!(context->flags & ATTR_KERNOVAL));
+ if (context->flags & ATTR_KERNAMELS) {
+ char *offset;
+- xattr_namespace_t *nsp;
+
+ ASSERT(context->count >= 0);
+
+- nsp = &xfs_namespaces[ns];
+- arraytop = context->count + nsp->namelen + namelen+1;
++ arraytop = context->count + namesp->attr_namelen + namelen + 1;
+ if (arraytop > context->firstu) {
+ context->count = -1; /* insufficient space */
+ return(1);
+ }
+ offset = (char *)context->alist + context->count;
+- strncpy(offset, nsp->name, nsp->namelen); /* namespace */
+- offset += nsp->namelen;
++ strncpy(offset, namesp->attr_name, namesp->attr_namelen);
++ offset += namesp->attr_namelen;
+ strncpy(offset, name, namelen); /* real name */
+ offset += namelen;
+ *offset = '\0';
+- context->count += nsp->namelen + namelen + 1;
++ context->count += namesp->attr_namelen + namelen + 1;
+ return(0);
+ }
+
+diff -urN linux.org/fs/xfs/xfs_attr_leaf.h linux/fs/xfs/xfs_attr_leaf.h
+--- linux.org/fs/xfs/xfs_attr_leaf.h 2003-12-31 05:46:18.000000000 +0100
++++ linux/fs/xfs/xfs_attr_leaf.h 2004-01-02 04:21:42.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
++ * Copyright (c) 2000, 2002-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
+@@ -44,6 +44,7 @@
+
+ struct attrlist;
+ struct attrlist_cursor_kern;
++struct attrnames;
+ struct xfs_dabuf;
+ struct xfs_da_args;
+ struct xfs_da_state;
+@@ -128,7 +129,7 @@
+ * on the system call, they are "or"ed together for various operations.
+ */
+ #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
+-#define XFS_ATTR_ROOT_BIT 1 /* limit access to attr to userid 0 */
++#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted 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)
+@@ -299,7 +300,8 @@
+ int *local);
+ int xfs_attr_leaf_entsize(struct xfs_attr_leafblock *leaf, int index);
+ int xfs_attr_put_listent(struct xfs_attr_list_context *context,
+- int ns, char *name, int namelen, int valuelen);
++ struct attrnames *, char *name, int namelen,
++ int valuelen);
+ int xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
+
+ #endif /* __XFS_ATTR_LEAF_H__ */
+diff -urN linux.org/fs/xfs/xfs_attr_sf.h linux/fs/xfs/xfs_attr_sf.h
+--- linux.org/fs/xfs/xfs_attr_sf.h 2003-12-31 05:46:54.000000000 +0100
++++ linux/fs/xfs/xfs_attr_sf.h 2004-01-02 04:21:42.000000000 +0100
+@@ -104,14 +104,7 @@
+ (INT_GET(((xfs_attr_shortform_t *)((dp)->i_afp->if_u1.if_data))->hdr.totsize, ARCH_CONVERT))
+ #endif
+
+-#ifdef XFS_ALL_TRACE
+-#define XFS_ATTR_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_ATTR_TRACE
+-#endif
+-
++#if defined(XFS_ATTR_TRACE)
+ /*
+ * Kernel tracing support for attribute lists
+ */
+@@ -121,6 +114,7 @@
+ struct xfs_attr_leafblock;
+
+ #define XFS_ATTR_TRACE_SIZE 4096 /* size of global trace buffer */
++extern ktrace_t *xfs_attr_trace_buf;
+
+ /*
+ * Trace record types.
+@@ -130,8 +124,6 @@
+ #define XFS_ATTR_KTRACE_L_CB 3 /* context, btree */
+ #define XFS_ATTR_KTRACE_L_CL 4 /* context, leaf */
+
+-#if defined(XFS_ATTR_TRACE)
+-
+ void xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context);
+ void xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,
+ struct xfs_da_intnode *node);
+diff -urN linux.org/fs/xfs/xfs_bmap_btree.c linux/fs/xfs/xfs_bmap_btree.c
+--- linux.org/fs/xfs/xfs_bmap_btree.c 2003-12-31 05:47:31.000000000 +0100
++++ linux/fs/xfs/xfs_bmap_btree.c 2004-01-02 04:21:42.000000000 +0100
+@@ -81,6 +81,13 @@
+
+
+ #if defined(XFS_BMBT_TRACE)
++
++static char ARGS[] = "args";
++static char ENTRY[] = "entry";
++static char ERROR[] = "error";
++#undef EXIT
++static char EXIT[] = "exit";
++
+ /*
+ * Add a trace buffer entry for the arguments given to the routine,
+ * generic form.
+@@ -305,11 +312,6 @@
+ xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
+ #define XFS_BMBT_TRACE_CURSOR(c,s) \
+ xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
+-static char ARGS[] = "args";
+-static char ENTRY[] = "entry";
+-static char ERROR[] = "error";
+-#undef EXIT
+-static char EXIT[] = "exit";
+ #else
+ #define XFS_BMBT_TRACE_ARGBI(c,b,i)
+ #define XFS_BMBT_TRACE_ARGBII(c,b,i,j)
+diff -urN linux.org/fs/xfs/xfs_bmap_btree.h linux/fs/xfs/xfs_bmap_btree.h
+--- linux.org/fs/xfs/xfs_bmap_btree.h 2003-12-31 05:47:25.000000000 +0100
++++ linux/fs/xfs/xfs_bmap_btree.h 2004-01-02 04:21:43.000000000 +0100
+@@ -435,6 +435,10 @@
+ INT_GET((bb)->bb_numrecs, ARCH_CONVERT) <= (mp)->m_bmap_dmxr[(level) != 0])
+ #endif
+
++
++#ifdef __KERNEL__
++
++#if defined(XFS_BMBT_TRACE)
+ /*
+ * Trace buffer entry types.
+ */
+@@ -449,18 +453,9 @@
+
+ #define XFS_BMBT_TRACE_SIZE 4096 /* size of global trace buffer */
+ #define XFS_BMBT_KTRACE_SIZE 32 /* size of per-inode trace buffer */
+-
+-#if defined(XFS_ALL_TRACE)
+-#define XFS_BMBT_TRACE
++extern ktrace_t *xfs_bmbt_trace_buf;
+ #endif
+
+-#if !defined(DEBUG)
+-#undef XFS_BMBT_TRACE
+-#endif
+-
+-
+-#ifdef __KERNEL__
+-
+ /*
+ * Prototypes for xfs_bmap.c to call.
+ */
+diff -urN linux.org/fs/xfs/xfs_bmap.c linux/fs/xfs/xfs_bmap.c
+--- linux.org/fs/xfs/xfs_bmap.c 2003-12-31 05:48:24.000000000 +0100
++++ linux/fs/xfs/xfs_bmap.c 2004-01-02 04:21:42.000000000 +0100
+@@ -68,9 +68,6 @@
+ #include "xfs_trans_space.h"
+ #include "xfs_buf_item.h"
+
+-#ifdef DEBUG
+-ktrace_t *xfs_bmap_trace_buf;
+-#endif
+
+ #ifdef XFSDEBUG
+ STATIC void
+@@ -404,7 +401,7 @@
+ #define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
+ #endif /* DEBUG */
+
+-#if defined(DEBUG) && defined(XFS_RW_TRACE)
++#if defined(XFS_RW_TRACE)
+ STATIC void
+ xfs_bunmap_trace(
+ xfs_inode_t *ip,
+@@ -414,7 +411,7 @@
+ inst_t *ra);
+ #else
+ #define xfs_bunmap_trace(ip, bno, len, flags, ra)
+-#endif /* DEBUG && XFS_RW_TRACE */
++#endif /* XFS_RW_TRACE */
+
+ STATIC int
+ xfs_bmap_count_tree(
+@@ -3543,6 +3540,8 @@
+
+
+ #ifdef XFS_BMAP_TRACE
++ktrace_t *xfs_bmap_trace_buf;
++
+ /*
+ * Add a bmap trace buffer entry. Base routine for the others.
+ */
+@@ -3575,14 +3574,14 @@
+ (void *)(__psint_t)cnt,
+ (void *)(__psunsigned_t)(ip->i_ino >> 32),
+ (void *)(__psunsigned_t)(unsigned)ip->i_ino,
+- (void *)(__psunsigned_t)(INT_GET(r1->l0, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r1->l0, ARCH_CONVERT)),
+- (void *)(__psunsigned_t)(INT_GET(r1->l1, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r1->l1, ARCH_CONVERT)),
+- (void *)(__psunsigned_t)(INT_GET(r2->l0, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r2->l0, ARCH_CONVERT)),
+- (void *)(__psunsigned_t)(INT_GET(r2->l1, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r2->l1, ARCH_CONVERT))
++ (void *)(__psunsigned_t)(r1->l0 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r1->l0),
++ (void *)(__psunsigned_t)(r1->l1 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r1->l1),
++ (void *)(__psunsigned_t)(r2->l0 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r2->l0),
++ (void *)(__psunsigned_t)(r2->l1 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r2->l1)
+ );
+ ASSERT(ip->i_xtrace);
+ ktrace_enter(ip->i_xtrace,
+@@ -3592,14 +3591,14 @@
+ (void *)(__psint_t)cnt,
+ (void *)(__psunsigned_t)(ip->i_ino >> 32),
+ (void *)(__psunsigned_t)(unsigned)ip->i_ino,
+- (void *)(__psunsigned_t)(INT_GET(r1->l0, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r1->l0, ARCH_CONVERT)),
+- (void *)(__psunsigned_t)(INT_GET(r1->l1, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r1->l1, ARCH_CONVERT)),
+- (void *)(__psunsigned_t)(INT_GET(r2->l0, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r2->l0, ARCH_CONVERT)),
+- (void *)(__psunsigned_t)(INT_GET(r2->l1, ARCH_CONVERT) >> 32),
+- (void *)(__psunsigned_t)(unsigned)(INT_GET(r2->l1, ARCH_CONVERT))
++ (void *)(__psunsigned_t)(r1->l0 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r1->l0),
++ (void *)(__psunsigned_t)(r1->l1 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r1->l1),
++ (void *)(__psunsigned_t)(r2->l0 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r2->l0),
++ (void *)(__psunsigned_t)(r2->l1 >> 32),
++ (void *)(__psunsigned_t)(unsigned)(r2->l1)
+ );
+ }
+
+@@ -3722,7 +3721,7 @@
+ return rval;
+ }
+
+-#if defined(DEBUG) && defined(XFS_RW_TRACE)
++#if defined(XFS_RW_TRACE)
+ STATIC void
+ xfs_bunmap_trace(
+ xfs_inode_t *ip,
+@@ -3742,7 +3741,7 @@
+ (void *)(__psint_t)((xfs_dfiloff_t)bno & 0xffffffff),
+ (void *)(__psint_t)len,
+ (void *)(__psint_t)flags,
+- (void *)(__psint_t)private.p_cpuid,
++ (void *)(unsigned long)current_cpu(),
+ (void *)ra,
+ (void *)0,
+ (void *)0,
+diff -urN linux.org/fs/xfs/xfs_bmap.h linux/fs/xfs/xfs_bmap.h
+--- linux.org/fs/xfs/xfs_bmap.h 2003-12-31 05:46:44.000000000 +0100
++++ linux/fs/xfs/xfs_bmap.h 2004-01-02 04:21:42.000000000 +0100
+@@ -90,26 +90,6 @@
+ #define DELAYSTARTBLOCK ((xfs_fsblock_t)-1LL)
+ #define HOLESTARTBLOCK ((xfs_fsblock_t)-2LL)
+
+-/*
+- * Trace operations for bmap extent tracing
+- */
+-#define XFS_BMAP_KTRACE_DELETE 1
+-#define XFS_BMAP_KTRACE_INSERT 2
+-#define XFS_BMAP_KTRACE_PRE_UP 3
+-#define XFS_BMAP_KTRACE_POST_UP 4
+-
+-#define XFS_BMAP_TRACE_SIZE 4096 /* size of global trace buffer */
+-#define XFS_BMAP_KTRACE_SIZE 32 /* size of per-inode trace buffer */
+-
+-#if defined(XFS_ALL_TRACE)
+-#define XFS_BMAP_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_BMAP_TRACE
+-#endif
+-
+-
+ #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_BMAP_INIT)
+ void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp);
+ #define XFS_BMAP_INIT(flp,fbp) xfs_bmap_init(flp,fbp)
+@@ -142,6 +122,33 @@
+ } xfs_bmalloca_t;
+
+ #ifdef __KERNEL__
++
++#if defined(XFS_BMAP_TRACE)
++/*
++ * Trace operations for bmap extent tracing
++ */
++#define XFS_BMAP_KTRACE_DELETE 1
++#define XFS_BMAP_KTRACE_INSERT 2
++#define XFS_BMAP_KTRACE_PRE_UP 3
++#define XFS_BMAP_KTRACE_POST_UP 4
++
++#define XFS_BMAP_TRACE_SIZE 4096 /* size of global trace buffer */
++#define XFS_BMAP_KTRACE_SIZE 32 /* size of per-inode trace buffer */
++extern ktrace_t *xfs_bmap_trace_buf;
++
++/*
++ * Add bmap trace insert entries for all the contents of the extent list.
++ */
++void
++xfs_bmap_trace_exlist(
++ char *fname, /* function name */
++ struct xfs_inode *ip, /* incore inode pointer */
++ xfs_extnum_t cnt, /* count of entries in list */
++ int whichfork); /* data or attr fork */
++#else
++#define xfs_bmap_trace_exlist(f,ip,c,w)
++#endif
++
+ /*
+ * Convert inode from non-attributed to attributed.
+ * Must not be in a transaction, ip must not be locked.
+@@ -260,20 +267,6 @@
+ struct xfs_inode *ip, /* incore inode */
+ int whichfork); /* data or attr fork */
+
+-#if defined(XFS_BMAP_TRACE)
+-/*
+- * Add bmap trace insert entries for all the contents of the extent list.
+- */
+-void
+-xfs_bmap_trace_exlist(
+- char *fname, /* function name */
+- struct xfs_inode *ip, /* incore inode pointer */
+- xfs_extnum_t cnt, /* count of entries in list */
+- int whichfork); /* data or attr fork */
+-#else
+-#define xfs_bmap_trace_exlist(f,ip,c,w)
+-#endif
+-
+ /*
+ * Map file blocks to filesystem blocks.
+ * File range is given by the bno/len pair.
+@@ -375,7 +368,7 @@
+ int
+ xfs_bmap_count_blocks(
+ xfs_trans_t *tp,
+- xfs_inode_t *ip,
++ struct xfs_inode *ip,
+ int whichfork,
+ int *count);
+
+diff -urN linux.org/fs/xfs/xfs_buf.h linux/fs/xfs/xfs_buf.h
+--- linux.org/fs/xfs/xfs_buf.h 2003-12-31 05:48:37.000000000 +0100
++++ linux/fs/xfs/xfs_buf.h 2004-01-02 04:21:43.000000000 +0100
+@@ -181,7 +181,7 @@
+ #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_ISPINNED(bp) pagebuf_ispin(bp)
+
+ #define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp)
+ #define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0)
+@@ -191,13 +191,11 @@
+
+ /* setup the buffer target from a buftarg structure */
+ #define XFS_BUF_SET_TARGET(bp, target) \
+- (bp)->pb_target = (target)
+-
++ (bp)->pb_target = (target)
+ #define XFS_BUF_TARGET(bp) ((bp)->pb_target)
++#define XFS_BUFTARG_NAME(target) \
++ pagebuf_target_name(target)
+
+-#define XFS_BUFTARG_NAME(target) \
+- ({ char __b[BDEVNAME_SIZE]; bdevname((target->pbr_bdev), __b); __b; })
+-
+ #define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
+ #define XFS_BUF_SET_VTYPE(bp, type)
+ #define XFS_BUF_SET_REF(bp, ref)
+@@ -231,18 +229,11 @@
+ pagebuf_rele(bp);
+ }
+
+-
+ #define xfs_bpin(bp) pagebuf_pin(bp)
+ #define xfs_bunpin(bp) pagebuf_unpin(bp)
+
+-#ifdef PAGEBUF_TRACE
+-# define PB_DEFINE_TRACES
+-# include <pagebuf/page_buf_trace.h>
+-# define xfs_buftrace(id, bp) PB_TRACE(bp, PB_TRACE_REC(external), (void *)id)
+-#else
+-# define xfs_buftrace(id, bp) do { } while (0)
+-#endif
+-
++#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)
+diff -urN linux.org/fs/xfs/xfs_buf_item.c linux/fs/xfs/xfs_buf_item.c
+--- linux.org/fs/xfs/xfs_buf_item.c 2003-12-31 05:46:23.000000000 +0100
++++ linux/fs/xfs/xfs_buf_item.c 2004-01-02 04:21:43.000000000 +0100
+@@ -1207,13 +1207,14 @@
+ (void *)((unsigned long)bip->bli_flags),
+ (void *)((unsigned long)bip->bli_recur),
+ (void *)((unsigned long)atomic_read(&bip->bli_refcount)),
+- (void *)XFS_BUF_ADDR(bp),
++ (void *)((unsigned long)
++ (0xFFFFFFFF & XFS_BUF_ADDR(bp) >> 32)),
++ (void *)((unsigned long)(0xFFFFFFFF & XFS_BUF_ADDR(bp))),
+ (void *)((unsigned long)XFS_BUF_COUNT(bp)),
+- (void *)((unsigned long)(0xFFFFFFFF & (XFS_BFLAGS(bp) >> 32))),
+- (void *)((unsigned long)(0xFFFFFFFF & XFS_BFLAGS(bp))),
++ (void *)((unsigned long)XFS_BUF_BFLAGS(bp)),
+ XFS_BUF_FSPRIVATE(bp, void *),
+ XFS_BUF_FSPRIVATE2(bp, void *),
+- (void *)((unsigned long)bp->b_pincount),
++ (void *)(unsigned long)XFS_BUF_ISPINNED(bp),
+ (void *)XFS_BUF_IODONE_FUNC(bp),
+ (void *)((unsigned long)(XFS_BUF_VALUSEMA(bp))),
+ (void *)bip->bli_item.li_desc,
+diff -urN linux.org/fs/xfs/xfs_buf_item.h linux/fs/xfs/xfs_buf_item.h
+--- linux.org/fs/xfs/xfs_buf_item.h 2003-12-31 05:48:00.000000000 +0100
++++ linux/fs/xfs/xfs_buf_item.h 2004-01-02 04:21:43.000000000 +0100
+@@ -104,6 +104,15 @@
+ struct xfs_buf;
+ struct ktrace;
+ struct xfs_mount;
++struct xfs_buf_log_item;
++
++#if defined(XFS_BLI_TRACE)
++#define XFS_BLI_TRACE_SIZE 32
++
++void xfs_buf_item_trace(char *, struct xfs_buf_log_item *);
++#else
++#define xfs_buf_item_trace(id, bip)
++#endif
+
+ /*
+ * This is the in core log item structure used to track information
+@@ -116,7 +125,7 @@
+ unsigned int bli_flags; /* misc flags */
+ unsigned int bli_recur; /* lock recursion count */
+ atomic_t bli_refcount; /* cnt of tp refs */
+-#ifdef DEBUG
++#ifdef XFS_BLI_TRACE
+ struct ktrace *bli_trace; /* event trace buf */
+ #endif
+ #ifdef XFS_TRANS_DEBUG
+@@ -137,23 +146,6 @@
+ struct xfs_buf_cancel *bc_next;
+ } xfs_buf_cancel_t;
+
+-#define XFS_BLI_TRACE_SIZE 32
+-
+-
+-#if defined(XFS_ALL_TRACE)
+-#define XFS_BLI_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_BLI_TRACE
+-#endif
+-
+-#if defined(XFS_BLI_TRACE)
+-void xfs_buf_item_trace(char *, xfs_buf_log_item_t *);
+-#else
+-#define xfs_buf_item_trace(id, bip)
+-#endif
+-
+ void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
+ void xfs_buf_item_relse(struct xfs_buf *);
+ void xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint);
+diff -urN linux.org/fs/xfs/xfs_da_btree.c linux/fs/xfs/xfs_da_btree.c
+--- linux.org/fs/xfs/xfs_da_btree.c 2003-12-31 05:48:06.000000000 +0100
++++ linux/fs/xfs/xfs_da_btree.c 2004-01-02 04:21:43.000000000 +0100
+@@ -66,13 +66,6 @@
+ #include "xfs_error.h"
+ #include "xfs_bit.h"
+
+-#if defined(XFSDEBUG) && defined(CONFIG_KDB)
+-#undef xfs_buftrace
+-#define xfs_buftrace(A,B) \
+- printk(" xfs_buftrace : %s (0x%p)\n", A, B); \
+- BUG();
+-#endif
+-
+ /*
+ * xfs_da_btree.c
+ *
+diff -urN linux.org/fs/xfs/xfs_dfrag.c linux/fs/xfs/xfs_dfrag.c
+--- linux.org/fs/xfs/xfs_dfrag.c 2003-12-31 05:46:28.000000000 +0100
++++ linux/fs/xfs/xfs_dfrag.c 2004-01-02 04:21:43.000000000 +0100
+@@ -153,12 +153,12 @@
+ if ((error = _MAC_XFS_IACCESS(tip, MACWRITE, NULL))) {
+ goto error0;
+ }
+- if ((current->fsuid != ip->i_d.di_uid) &&
++ if ((current_fsuid(cred) != ip->i_d.di_uid) &&
+ (error = xfs_iaccess(ip, S_IWUSR, NULL)) &&
+ !capable_cred(NULL, CAP_FOWNER)) {
+ goto error0;
+ }
+- if ((current->fsuid != tip->i_d.di_uid) &&
++ if ((current_fsuid(cred) != tip->i_d.di_uid) &&
+ (error = xfs_iaccess(tip, S_IWUSR, NULL)) &&
+ !capable_cred(NULL, CAP_FOWNER)) {
+ goto error0;
+diff -urN linux.org/fs/xfs/xfs_dir2_trace.c linux/fs/xfs/xfs_dir2_trace.c
+--- linux.org/fs/xfs/xfs_dir2_trace.c 2003-12-31 05:48:09.000000000 +0100
++++ linux/fs/xfs/xfs_dir2_trace.c 2004-01-02 04:21:44.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -64,36 +64,37 @@
+ char *where,
+ char *name,
+ int namelen,
+- __psunsigned_t a0,
+- __psunsigned_t a1,
+- __psunsigned_t a2,
+- __psunsigned_t a3,
+- __psunsigned_t a4,
+- __psunsigned_t a5,
+- __psunsigned_t a6)
++ void *a0,
++ void *a1,
++ void *a2,
++ void *a3,
++ void *a4,
++ void *a5,
++ void *a6,
++ void *a7)
+ {
+- __psunsigned_t n[6];
++ void *n[5];
+
+ ASSERT(xfs_dir2_trace_buf);
+ ASSERT(dp->i_dir_trace);
+ if (name)
+- memcpy(n, name, min(sizeof(n), namelen));
++ memcpy(n, name, min((int)sizeof(n), namelen));
+ else
+ memset((char *)n, 0, sizeof(n));
+ ktrace_enter(xfs_dir2_trace_buf,
+- (void *)(__psunsigned_t)type, (void *)where,
++ (void *)(long)type, (void *)where,
+ (void *)a0, (void *)a1, (void *)a2, (void *)a3,
+- (void *)a4, (void *)a5, (void *)a6,
+- (void *)(__psunsigned_t)namelen,
++ (void *)a4, (void *)a5, (void *)a6, (void *)a7,
++ (void *)(long)namelen,
+ (void *)n[0], (void *)n[1], (void *)n[2],
+- (void *)n[3], (void *)n[4], (void *)n[5]);
++ (void *)n[3], (void *)n[4]);
+ ktrace_enter(dp->i_dir_trace,
+- (void *)(__psunsigned_t)type, (void *)where,
++ (void *)(long)type, (void *)where,
+ (void *)a0, (void *)a1, (void *)a2, (void *)a3,
+- (void *)a4, (void *)a5, (void *)a6,
+- (void *)(__psunsigned_t)namelen,
++ (void *)a4, (void *)a5, (void *)a6, (void *)a7,
++ (void *)(long)namelen,
+ (void *)n[0], (void *)n[1], (void *)n[2],
+- (void *)n[3], (void *)n[4], (void *)n[5]);
++ (void *)n[3], (void *)n[4]);
+ }
+
+ void
+@@ -103,9 +104,11 @@
+ {
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->hashval, (__psunsigned_t)args->inumber,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)args->justcheck, 0, 0);
++ (void *)(unsigned long)args->hashval,
++ (void *)((unsigned long)(args->inumber >> 32)),
++ (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
++ (void *)args->dp, (void *)args->trans,
++ (void *)(unsigned long)args->justcheck, NULL, NULL);
+ }
+
+ void
+@@ -116,10 +119,12 @@
+ {
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_B, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->hashval, (__psunsigned_t)args->inumber,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)args->justcheck,
+- (__psunsigned_t)(bp ? bp->bps[0] : NULL), 0);
++ (void *)(unsigned long)args->hashval,
++ (void *)((unsigned long)(args->inumber >> 32)),
++ (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
++ (void *)args->dp, (void *)args->trans,
++ (void *)(unsigned long)args->justcheck,
++ (void *)(bp ? bp->bps[0] : NULL), NULL);
+ }
+
+ void
+@@ -131,11 +136,13 @@
+ {
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_BB, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->hashval, (__psunsigned_t)args->inumber,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)args->justcheck,
+- (__psunsigned_t)(lbp ? lbp->bps[0] : NULL),
+- (__psunsigned_t)(dbp ? dbp->bps[0] : NULL));
++ (void *)(unsigned long)args->hashval,
++ (void *)((unsigned long)(args->inumber >> 32)),
++ (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
++ (void *)args->dp, (void *)args->trans,
++ (void *)(unsigned long)args->justcheck,
++ (void *)(lbp ? lbp->bps[0] : NULL),
++ (void *)(dbp ? dbp->bps[0] : NULL));
+ }
+
+ void
+@@ -148,12 +155,14 @@
+ int sd,
+ int c)
+ {
++ xfs_buf_t *bpbs = bs ? bs->bps[0] : NULL;
++ xfs_buf_t *bpbd = bd ? bd->bps[0] : NULL;
++
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_BIBII, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)(bs ? bs->bps[0] : NULL), (__psunsigned_t)ss,
+- (__psunsigned_t)(bd ? bd->bps[0] : NULL), (__psunsigned_t)sd,
+- (__psunsigned_t)c);
++ (void *)args->dp, (void *)args->trans,
++ (void *)bpbs, (void *)(long)ss, (void *)bpbd, (void *)(long)sd,
++ (void *)(long)c, NULL);
+ }
+
+ void
+@@ -163,12 +172,16 @@
+ xfs_dir2_db_t db,
+ xfs_dabuf_t *bp)
+ {
++ xfs_buf_t *dbp = bp ? bp->bps[0] : NULL;
++
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_DB, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->hashval, (__psunsigned_t)args->inumber,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)args->justcheck, (__psunsigned_t)db,
+- (__psunsigned_t)(bp ? bp->bps[0] : NULL));
++ (void *)(unsigned long)args->hashval,
++ (void *)((unsigned long)(args->inumber >> 32)),
++ (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
++ (void *)args->dp, (void *)args->trans,
++ (void *)(unsigned long)args->justcheck, (void *)(long)db,
++ (void *)dbp);
+ }
+
+ void
+@@ -179,9 +192,13 @@
+ {
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_I, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->hashval, (__psunsigned_t)args->inumber,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)args->justcheck, (__psunsigned_t)i, 0);
++ (void *)(unsigned long)args->hashval,
++ (void *)((unsigned long)(args->inumber >> 32)),
++ (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
++ (void *)args->dp, (void *)args->trans,
++ (void *)(unsigned long)args->justcheck,
++ (void *)((unsigned long)(i >> 32)),
++ (void *)((unsigned long)(i & 0xFFFFFFFF)));
+ }
+
+ void
+@@ -192,9 +209,11 @@
+ {
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_S, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->hashval, (__psunsigned_t)args->inumber,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)args->justcheck, (__psunsigned_t)s, 0);
++ (void *)(unsigned long)args->hashval,
++ (void *)((unsigned long)(args->inumber >> 32)),
++ (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
++ (void *)args->dp, (void *)args->trans,
++ (void *)(unsigned long)args->justcheck, (void *)(long)s, 0);
+ }
+
+ void
+@@ -204,11 +223,15 @@
+ int s,
+ xfs_dabuf_t *bp)
+ {
++ xfs_buf_t *dbp = bp ? bp->bps[0] : NULL;
++
+ xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_SB, where,
+ (char *)args->name, (int)args->namelen,
+- (__psunsigned_t)args->hashval, (__psunsigned_t)args->inumber,
+- (__psunsigned_t)args->dp, (__psunsigned_t)args->trans,
+- (__psunsigned_t)args->justcheck, (__psunsigned_t)s,
+- (__psunsigned_t)(bp ? bp->bps[0] : NULL));
++ (void *)(unsigned long)args->hashval,
++ (void *)((unsigned long)(args->inumber >> 32)),
++ (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
++ (void *)args->dp, (void *)args->trans,
++ (void *)(unsigned long)args->justcheck, (void *)(long)s,
++ (void *)dbp);
+ }
+ #endif /* XFS_DIR2_TRACE */
+diff -urN linux.org/fs/xfs/xfs_dir2_trace.h linux/fs/xfs/xfs_dir2_trace.h
+--- linux.org/fs/xfs/xfs_dir2_trace.h 2003-12-31 05:46:56.000000000 +0100
++++ linux/fs/xfs/xfs_dir2_trace.h 2004-01-02 04:21:44.000000000 +0100
+@@ -36,20 +36,15 @@
+ * Tracing for xfs v2 directories.
+ */
+
++#if defined(XFS_DIR2_TRACE)
++
+ struct ktrace;
+ struct xfs_dabuf;
+ struct xfs_da_args;
+
+-#ifdef XFS_ALL_TRACE
+-#define XFS_DIR2_TRACE
+-#endif /* XFS_ALL_TRACE */
+-
+-#if !defined(DEBUG)
+-#undef XFS_DIR2_TRACE
+-#endif /* !DEBUG */
+-
+ #define XFS_DIR2_GTRACE_SIZE 4096 /* global buffer */
+ #define XFS_DIR2_KTRACE_SIZE 32 /* per-inode buffer */
++extern struct ktrace *xfs_dir2_trace_buf;
+
+ #define XFS_DIR2_KTRACE_ARGS 1 /* args only */
+ #define XFS_DIR2_KTRACE_ARGS_B 2 /* args + buffer */
+@@ -60,8 +55,6 @@
+ #define XFS_DIR2_KTRACE_ARGS_SB 7 /* args, int, buffer */
+ #define XFS_DIR2_KTRACE_ARGS_BIBII 8 /* args, buf/int/buf/int/int */
+
+-#ifdef XFS_DIR2_TRACE
+-
+ void xfs_dir2_trace_args(char *where, struct xfs_da_args *args);
+ void xfs_dir2_trace_args_b(char *where, struct xfs_da_args *args,
+ struct xfs_dabuf *bp);
+@@ -90,6 +83,4 @@
+
+ #endif /* XFS_DIR2_TRACE */
+
+-extern struct ktrace *xfs_dir2_trace_buf;
+-
+ #endif /* __XFS_DIR2_TRACE_H__ */
+diff -urN linux.org/fs/xfs/xfs_dir.c linux/fs/xfs/xfs_dir.c
+--- linux.org/fs/xfs/xfs_dir.c 2003-12-31 05:46:43.000000000 +0100
++++ linux/fs/xfs/xfs_dir.c 2004-01-02 04:21:43.000000000 +0100
+@@ -1093,10 +1093,10 @@
+ xfs_dir_trace_g_du(char *where, xfs_inode_t *dp, uio_t *uio)
+ {
+ xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DU, where,
+- (__psunsigned_t)dp, (__psunsigned_t)dp->i_mount,
+- (__psunsigned_t)(uio->uio_offset >> 32),
+- (__psunsigned_t)(uio->uio_offset & 0xFFFFFFFF),
+- (__psunsigned_t)uio->uio_resid,
++ (void *)dp, (void *)dp->i_mount,
++ (void *)((unsigned long)(uio->uio_offset >> 32)),
++ (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
++ (void *)(unsigned long)uio->uio_resid,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+
+@@ -1107,11 +1107,11 @@
+ xfs_dir_trace_g_dub(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dablk_t bno)
+ {
+ xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUB, where,
+- (__psunsigned_t)dp, (__psunsigned_t)dp->i_mount,
+- (__psunsigned_t)(uio->uio_offset >> 32),
+- (__psunsigned_t)(uio->uio_offset & 0xFFFFFFFF),
+- (__psunsigned_t)uio->uio_resid,
+- (__psunsigned_t)bno,
++ (void *)dp, (void *)dp->i_mount,
++ (void *)((unsigned long)(uio->uio_offset >> 32)),
++ (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
++ (void *)(unsigned long)uio->uio_resid,
++ (void *)(unsigned long)bno,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+
+@@ -1122,15 +1122,21 @@
+ xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio,
+ xfs_da_intnode_t *node)
+ {
++ int last = INT_GET(node->hdr.count, ARCH_CONVERT) - 1;
++
+ xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where,
+- (__psunsigned_t)dp, (__psunsigned_t)dp->i_mount,
+- (__psunsigned_t)(uio->uio_offset >> 32),
+- (__psunsigned_t)(uio->uio_offset & 0xFFFFFFFF),
+- (__psunsigned_t)uio->uio_resid,
+- (__psunsigned_t)INT_GET(node->hdr.info.forw, ARCH_CONVERT),
+- (__psunsigned_t)INT_GET(node->hdr.count, ARCH_CONVERT),
+- (__psunsigned_t)INT_GET(node->btree[0].hashval, ARCH_CONVERT),
+- (__psunsigned_t)INT_GET(node->btree[INT_GET(node->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT),
++ (void *)dp, (void *)dp->i_mount,
++ (void *)((unsigned long)(uio->uio_offset >> 32)),
++ (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
++ (void *)(unsigned long)uio->uio_resid,
++ (void *)(unsigned long)
++ INT_GET(node->hdr.info.forw, ARCH_CONVERT),
++ (void *)(unsigned long)
++ INT_GET(node->hdr.count, ARCH_CONVERT),
++ (void *)(unsigned long)
++ INT_GET(node->btree[0].hashval, ARCH_CONVERT),
++ (void *)(unsigned long)
++ INT_GET(node->btree[last].hashval, ARCH_CONVERT),
+ NULL, NULL, NULL);
+ }
+
+@@ -1141,15 +1147,21 @@
+ xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio,
+ xfs_dir_leafblock_t *leaf)
+ {
++ int last = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1;
++
+ xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where,
+- (__psunsigned_t)dp, (__psunsigned_t)dp->i_mount,
+- (__psunsigned_t)(uio->uio_offset >> 32),
+- (__psunsigned_t)(uio->uio_offset & 0xFFFFFFFF),
+- (__psunsigned_t)uio->uio_resid,
+- (__psunsigned_t)INT_GET(leaf->hdr.info.forw, ARCH_CONVERT),
+- (__psunsigned_t)INT_GET(leaf->hdr.count, ARCH_CONVERT),
+- (__psunsigned_t)INT_GET(leaf->entries[0].hashval, ARCH_CONVERT),
+- (__psunsigned_t)INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT),
++ (void *)dp, (void *)dp->i_mount,
++ (void *)((unsigned long)(uio->uio_offset >> 32)),
++ (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
++ (void *)(unsigned long)uio->uio_resid,
++ (void *)(unsigned long)
++ INT_GET(leaf->hdr.info.forw, ARCH_CONVERT),
++ (void *)(unsigned long)
++ INT_GET(leaf->hdr.count, ARCH_CONVERT),
++ (void *)(unsigned long)
++ INT_GET(leaf->entries[0].hashval, ARCH_CONVERT),
++ (void *)(unsigned long)
++ INT_GET(leaf->entries[last].hashval, ARCH_CONVERT),
+ NULL, NULL, NULL);
+ }
+
+@@ -1161,11 +1173,12 @@
+ xfs_dir_leaf_entry_t *entry)
+ {
+ xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUE, where,
+- (__psunsigned_t)dp, (__psunsigned_t)dp->i_mount,
+- (__psunsigned_t)(uio->uio_offset >> 32),
+- (__psunsigned_t)(uio->uio_offset & 0xFFFFFFFF),
+- (__psunsigned_t)uio->uio_resid,
+- (__psunsigned_t)INT_GET(entry->hashval, ARCH_CONVERT),
++ (void *)dp, (void *)dp->i_mount,
++ (void *)((unsigned long)(uio->uio_offset >> 32)),
++ (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
++ (void *)(unsigned long)uio->uio_resid,
++ (void *)(unsigned long)
++ INT_GET(entry->hashval, ARCH_CONVERT),
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+
+@@ -1176,12 +1189,12 @@
+ xfs_dir_trace_g_duc(char *where, xfs_inode_t *dp, uio_t *uio, xfs_off_t cookie)
+ {
+ xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUC, where,
+- (__psunsigned_t)dp, (__psunsigned_t)dp->i_mount,
+- (__psunsigned_t)(uio->uio_offset >> 32),
+- (__psunsigned_t)(uio->uio_offset & 0xFFFFFFFF),
+- (__psunsigned_t)uio->uio_resid,
+- (__psunsigned_t)(cookie >> 32),
+- (__psunsigned_t)(cookie & 0xFFFFFFFF),
++ (void *)dp, (void *)dp->i_mount,
++ (void *)((unsigned long)(uio->uio_offset >> 32)),
++ (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
++ (void *)(unsigned long)uio->uio_resid,
++ (void *)((unsigned long)(cookie >> 32)),
++ (void *)((unsigned long)(cookie & 0xFFFFFFFF)),
+ NULL, NULL, NULL, NULL, NULL);
+ }
+
+@@ -1191,15 +1204,15 @@
+ */
+ void
+ xfs_dir_trace_enter(int type, char *where,
+- __psunsigned_t a0, __psunsigned_t a1,
+- __psunsigned_t a2, __psunsigned_t a3,
+- __psunsigned_t a4, __psunsigned_t a5,
+- __psunsigned_t a6, __psunsigned_t a7,
+- __psunsigned_t a8, __psunsigned_t a9,
+- __psunsigned_t a10, __psunsigned_t a11)
++ void * a0, void * a1,
++ void * a2, void * a3,
++ void * a4, void * a5,
++ void * a6, void * a7,
++ void * a8, void * a9,
++ void * a10, void * a11)
+ {
+ ASSERT(xfs_dir_trace_buf);
+- ktrace_enter(xfs_dir_trace_buf, (void *)((__psunsigned_t)type),
++ ktrace_enter(xfs_dir_trace_buf, (void *)(unsigned long)type,
+ (void *)where,
+ (void *)a0, (void *)a1, (void *)a2,
+ (void *)a3, (void *)a4, (void *)a5,
+diff -urN linux.org/fs/xfs/xfs_dir.h linux/fs/xfs/xfs_dir.h
+--- linux.org/fs/xfs/xfs_dir.h 2003-12-31 05:46:52.000000000 +0100
++++ linux/fs/xfs/xfs_dir.h 2004-01-02 04:21:43.000000000 +0100
+@@ -43,14 +43,6 @@
+ * as possible so as to fit into the literal area of the inode.
+ */
+
+-#ifdef XFS_ALL_TRACE
+-#define XFS_DIR_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_DIR_TRACE
+-#endif
+-
+ /*========================================================================
+ * Function prototypes for the kernel.
+ *========================================================================*/
+diff -urN linux.org/fs/xfs/xfs_dir_sf.h linux/fs/xfs/xfs_dir_sf.h
+--- linux.org/fs/xfs/xfs_dir_sf.h 2003-12-31 05:47:55.000000000 +0100
++++ linux/fs/xfs/xfs_dir_sf.h 2004-01-02 04:21:44.000000000 +0100
+@@ -126,13 +126,7 @@
+ ((uint)sizeof(xfs_dir_sf_entry_t)-1)*(count) + (totallen))
+ #endif
+
+-#ifdef XFS_ALL_TRACE
+-#define XFS_DIR_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_DIR_TRACE
+-#endif
++#if defined(XFS_DIR_TRACE)
+
+ /*
+ * Kernel tracing support for directories.
+@@ -145,6 +139,7 @@
+ struct xfs_dir_leaf_entry;
+
+ #define XFS_DIR_TRACE_SIZE 4096 /* size of global trace buffer */
++extern ktrace_t *xfs_dir_trace_buf;
+
+ /*
+ * Trace record types.
+@@ -156,8 +151,6 @@
+ #define XFS_DIR_KTRACE_G_DUE 5 /* dp, uio, leaf entry */
+ #define XFS_DIR_KTRACE_G_DUC 6 /* dp, uio, cookie */
+
+-#if defined(XFS_DIR_TRACE)
+-
+ void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio);
+ void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio,
+ xfs_dablk_t bno);
+@@ -170,12 +163,9 @@
+ void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio,
+ xfs_off_t cookie);
+ void xfs_dir_trace_enter(int type, char *where,
+- __psunsigned_t a0, __psunsigned_t a1,
+- __psunsigned_t a2, __psunsigned_t a3,
+- __psunsigned_t a4, __psunsigned_t a5,
+- __psunsigned_t a6, __psunsigned_t a7,
+- __psunsigned_t a8, __psunsigned_t a9,
+- __psunsigned_t a10, __psunsigned_t a11);
++ void *a0, void *a1, void *a2, void *a3,
++ void *a4, void *a5, void *a6, void *a7,
++ void *a8, void *a9, void *a10, void *a11);
+ #else
+ #define xfs_dir_trace_g_du(w,d,u)
+ #define xfs_dir_trace_g_dub(w,d,u,b)
+diff -urN linux.org/fs/xfs/xfs_dmapi.h linux/fs/xfs/xfs_dmapi.h
+--- linux.org/fs/xfs/xfs_dmapi.h 2003-12-31 05:48:36.000000000 +0100
++++ linux/fs/xfs/xfs_dmapi.h 2004-01-02 04:21:44.000000000 +0100
+@@ -175,14 +175,6 @@
+ DM_FLAGS_NDELAY : 0)
+ #define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0)
+
+-/*
+- * Macros to turn caller specified delay/block flags into
+- * dm_send_xxxx_event flag DM_FLAGS_NDELAY.
+- */
+-
+-#define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \
+- DM_FLAGS_NDELAY : 0)
+-
+
+ extern struct bhv_vfsops xfs_dmops;
+
+diff -urN linux.org/fs/xfs/xfs_dmops.c linux/fs/xfs/xfs_dmops.c
+--- linux.org/fs/xfs/xfs_dmops.c 2003-12-31 05:48:36.000000000 +0100
++++ linux/fs/xfs/xfs_dmops.c 2004-01-02 04:21:44.000000000 +0100
+@@ -43,8 +43,6 @@
+ #include "xfs_dmapi.h"
+ #include "xfs_mount.h"
+
+-
+-#ifndef CONFIG_XFS_DMAPI
+ xfs_dmops_t xfs_dmcore_xfs = {
+ .xfs_send_data = (xfs_send_data_t)fs_nosys,
+ .xfs_send_mmap = (xfs_send_mmap_t)fs_noerr,
+@@ -52,4 +50,3 @@
+ .xfs_send_namesp = (xfs_send_namesp_t)fs_nosys,
+ .xfs_send_unmount = (xfs_send_unmount_t)fs_noval,
+ };
+-#endif /* CONFIG_XFS_DMAPI */
+diff -urN linux.org/fs/xfs/xfs_error.c linux/fs/xfs/xfs_error.c
+--- linux.org/fs/xfs/xfs_error.c 2003-12-31 05:48:26.000000000 +0100
++++ linux/fs/xfs/xfs_error.c 2004-01-02 04:21:44.000000000 +0100
+@@ -102,7 +102,7 @@
+ if (random() % randfactor)
+ return 0;
+
+- memcpy(&fsid, fsidp, sizeof(fsid_t));
++ memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
+
+ for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
+ if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
+@@ -123,7 +123,7 @@
+ int len;
+ int64_t fsid;
+
+- memcpy(&fsid, mp->m_fixedfsid, sizeof(fsid_t));
++ memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
+
+ for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
+ if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
+@@ -156,7 +156,7 @@
+ int i;
+ int64_t fsid;
+
+- memcpy(&fsid, mp->m_fixedfsid, sizeof(fsid_t));
++ memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
+
+ for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
+ if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
+@@ -209,7 +209,7 @@
+ {
+ int64_t fsid;
+
+- memcpy(&fsid, mp->m_fixedfsid, sizeof(fsid_t));
++ memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
+
+ return xfs_errortag_clearall_umount(fsid, mp->m_fsname, 1);
+ }
+@@ -258,12 +258,6 @@
+ }
+
+ void
+-xfs_stack_trace(void)
+-{
+- dump_stack();
+-}
+-
+-void
+ xfs_error_report(
+ char *tag,
+ int level,
+diff -urN linux.org/fs/xfs/xfs_fsops.c linux/fs/xfs/xfs_fsops.c
+--- linux.org/fs/xfs/xfs_fsops.c 2003-12-31 05:48:18.000000000 +0100
++++ linux/fs/xfs/xfs_fsops.c 2004-01-02 04:21:42.000000000 +0100
+@@ -51,6 +51,7 @@
+ #include "xfs_fsops.h"
+ #include "xfs_itable.h"
+ #include "xfs_rw.h"
++#include "xfs_refcache.h"
+ #include "xfs_trans_space.h"
+ #include "xfs_rtalloc.h"
+ #include "xfs_dir2.h"
+@@ -593,6 +594,9 @@
+ /* Stop new writers */
+ xfs_start_freeze(mp, XFS_FREEZE_WRITE);
+
++ /* Flush the refcache */
++ xfs_refcache_purge_mp(mp);
++
+ /* Flush delalloc and delwri data */
+ VFS_SYNC(vfsp, SYNC_DELWRI|SYNC_WAIT, NULL, error);
+
+diff -urN linux.org/fs/xfs/xfsidbg.c linux/fs/xfs/xfsidbg.c
+--- linux.org/fs/xfs/xfsidbg.c 2003-12-31 05:48:07.000000000 +0100
++++ linux/fs/xfs/xfsidbg.c 2004-01-02 04:21:43.000000000 +0100
+@@ -31,7 +31,6 @@
+ */
+
+ #include "xfs.h"
+-#include "pagebuf/page_buf_internal.h"
+
+ #include <linux/ctype.h>
+ #include <linux/kdb.h>
+@@ -61,9 +60,11 @@
+ #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_inode.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"
+@@ -72,18 +73,66 @@
+ #include "xfs_dir2_leaf.h"
+ #include "xfs_dir2_block.h"
+ #include "xfs_dir2_node.h"
+-#include "xfs_dir2_trace.h"
+ #include "xfs_log_priv.h"
+ #include "xfs_log_recover.h"
+-#include "xfs_rw.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.
+ */
+@@ -91,9 +140,6 @@
+ static void xfsidbg_xagi(xfs_agi_t *);
+ static void xfsidbg_xaildump(xfs_mount_t *);
+ static void xfsidbg_xalloc(xfs_alloc_arg_t *);
+-#ifdef DEBUG
+-static void xfsidbg_xalmtrace(xfs_mount_t *);
+-#endif
+ 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 *);
+@@ -105,6 +151,8 @@
+ 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 *);
+@@ -144,13 +192,18 @@
+ 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
++#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(
+@@ -216,7 +269,8 @@
+ return 0;
+ }
+
+-static int kdbm_xfs_xalloc(
++#ifdef XFS_ALLOC_TRACE
++static int kdbm_xfs_xalatrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -226,19 +280,19 @@
+ 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);
++ xfsidbg_xalatrace((int) addr);
+ return 0;
+ }
+
+-#ifdef DEBUG
+-static int kdbm_xfs_xalmtrace(
++static int kdbm_xfs_xalbtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -251,16 +305,16 @@
+
+ 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);
++ xfsidbg_xalbtrace((xfs_agblock_t) addr);
+ return 0;
+ }
+-#endif /* DEBUG */
+
+-static int kdbm_xfs_xattrcontext(
++static int kdbm_xfs_xalgtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -273,15 +327,18 @@
+
+ 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);
++ xfsidbg_xalgtrace((xfs_agnumber_t) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xattrleaf(
++#ifdef XFS_ATTR_TRACE
++static int kdbm_xfs_xattrtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -294,15 +351,18 @@
+
+ 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);
++ xfsidbg_xattrtrace((int) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xattrsf(
++#ifdef XFS_BLI_TRACE
++static int kdbm_xfs_xblitrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -315,15 +375,18 @@
+
+ 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);
++ xfsidbg_xblitrace((xfs_buf_log_item_t *) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xbirec(
++#ifdef XFS_BMAP_TRACE
++static int kdbm_xfs_xbmatrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -336,15 +399,16 @@
+
+ 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);
++ xfsidbg_xbmatrace((int) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xbmalla(
++static int kdbm_xfs_xbmitrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -357,15 +421,16 @@
+
+ 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);
++ xfsidbg_xbmitrace((xfs_inode_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xbrec(
++static int kdbm_xfs_xbmstrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -378,15 +443,16 @@
+
+ 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);
++ xfsidbg_xbmstrace((xfs_inode_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xbroot(
++static int kdbm_xfs_xbxatrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -399,15 +465,16 @@
+
+ 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);
++ xfsidbg_xbxatrace((int) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xbroota(
++static int kdbm_xfs_xbxitrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -420,15 +487,16 @@
+
+ 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);
++ xfsidbg_xbxitrace((xfs_inode_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xbtcur(
++static int kdbm_xfs_xbxstrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -441,15 +509,18 @@
+
+ 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);
++ xfsidbg_xbxstrace((xfs_inode_t *) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xbuf(
++#ifdef XFS_DIR2_TRACE
++static int kdbm_xfs_xdir2atrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -462,16 +533,16 @@
+
+ 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);
++ xfsidbg_xdir2atrace((int) addr);
+ return 0;
+ }
+
+-
+-static int kdbm_xfs_xchash(
++static int kdbm_xfs_xdir2itrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -484,15 +555,18 @@
+
+ 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);
++ xfsidbg_xdir2itrace((xfs_inode_t *) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xchashlist(
++#ifdef XFS_DIR_TRACE
++static int kdbm_xfs_xdirtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -505,16 +579,18 @@
+
+ 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);
++ xfsidbg_xdirtrace((int) addr);
+ return 0;
+ }
++#endif
+
+-
+-static int kdbm_xfs_xdaargs(
++#ifdef XFS_LOG_TRACE
++static int kdbm_xfs_xiclogtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -527,15 +603,18 @@
+
+ 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);
++ xfsidbg_xiclogtrace((xlog_in_core_t *) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xdabuf(
++#ifdef XFS_ILOCK_TRACE
++static int kdbm_xfs_xilock_trace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -548,15 +627,16 @@
+
+ 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);
++ xfsidbg_xilock_trace((xfs_inode_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xdanode(
++static int kdbm_xfs_xailock_trace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -569,15 +649,18 @@
+
+ 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);
++ xfsidbg_xailock_trace((int) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xdastate(
++#ifdef XFS_LOG_TRACE
++static int kdbm_xfs_xlog_granttrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -590,15 +673,18 @@
+
+ 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);
++ xfsidbg_xlog_granttrace((xlog_t *) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xdirleaf(
++#ifdef XFS_DQUOT_TRACE
++static int kdbm_xfs_xqm_dqtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -611,15 +697,18 @@
+
+ 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);
++ xfsidbg_xqm_dqtrace((xfs_dquot_t *) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xdirsf(
++#ifdef XFS_RW_TRACE
++static int kdbm_xfs_xrwtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -632,15 +721,17 @@
+
+ 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);
++ xfsidbg_xrwtrace((xfs_inode_t *) addr);
+ return 0;
+ }
++#endif
+
+-static int kdbm_xfs_xdir2free(
++static int kdbm_xfs_xalloc(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -657,11 +748,12 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xdir2free((xfs_dir2_free_t *) addr);
++ xfsidbg_xalloc((xfs_alloc_arg_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xdir2sf(
++#ifdef XFS_ALLOC_TRACE
++static int kdbm_xfs_xalmtrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -678,11 +770,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xdir2sf((xfs_dir2_sf_t *) addr);
++ xfsidbg_xalmtrace((xfs_mount_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xexlist(
++static int kdbm_xfs_xalttrace(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -699,11 +791,12 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xexlist((xfs_inode_t *) addr);
++ xfsidbg_xalttrace((int) addr);
+ return 0;
+ }
++#endif /* XFS_ALLOC_TRACE */
+
+-static int kdbm_xfs_xflist(
++static int kdbm_xfs_xattrcontext(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -720,24 +813,32 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xflist((xfs_bmap_free_t *) addr);
++ xfsidbg_xattrcontext((xfs_attr_list_context_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xhelp(
++static int kdbm_xfs_xattrleaf(
+ int argc,
+ const char **argv,
+ const char **envp,
+ struct pt_regs *regs)
+ {
+- if (argc != 0)
++ 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_xhelp();
++ xfsidbg_xattrleaf((xfs_attr_leafblock_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xiclog(
++static int kdbm_xfs_xattrsf(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -754,11 +855,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xiclog((xlog_in_core_t *) addr);
++ xfsidbg_xattrsf((xfs_attr_shortform_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xiclogall(
++static int kdbm_xfs_xbirec(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -775,11 +876,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xiclogall((xlog_in_core_t *) addr);
++ xfsidbg_xbirec((xfs_bmbt_irec_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xiclogcb(
++static int kdbm_xfs_xbmalla(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -796,11 +897,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xiclogcb((xlog_in_core_t *) addr);
++ xfsidbg_xbmalla((xfs_bmalloca_t *)addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xihash(
++static int kdbm_xfs_xbrec(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -817,11 +918,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xihash((xfs_mount_t *) addr);
++ xfsidbg_xbrec((xfs_bmbt_rec_64_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xinodes(
++static int kdbm_xfs_xbroot(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -838,11 +939,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xinodes((xfs_mount_t *) addr);
++ xfsidbg_xbroot((xfs_inode_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_delayed_blocks(
++static int kdbm_xfs_xbroota(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -859,12 +960,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_delayed_blocks((xfs_mount_t *) addr);
++ xfsidbg_xbroota((xfs_inode_t *) addr);
+ return 0;
+ }
+
+-
+-static int kdbm_xfs_xinodes_quiesce(
++static int kdbm_xfs_xbtcur(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -881,11 +981,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xinodes_quiesce((xfs_mount_t *) addr);
++ xfsidbg_xbtcur((xfs_btree_cur_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xlog(
++static int kdbm_xfs_xbuf(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -902,11 +1002,12 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xlog((xlog_t *) addr);
++ xfsidbg_xbuf((xfs_buf_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xlog_ritem(
++
++static int kdbm_xfs_xarg(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -923,11 +1024,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xlog_ritem((xlog_recover_item_t *) addr);
++ xfsidbg_xarg((int) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xlog_rtrans(
++static int kdbm_xfs_xchksum(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -944,11 +1045,12 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xlog_rtrans((xlog_recover_t *) addr);
++ xfsidbg_xchksum((uint *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xlog_rtrans_entire(
++
++static int kdbm_xfs_xchash(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -965,11 +1067,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xlog_rtrans_entire((xlog_recover_t *) addr);
++ xfsidbg_xchash((xfs_mount_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xlog_tic(
++static int kdbm_xfs_xchashlist(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -986,11 +1088,12 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xlog_tic((xlog_ticket_t *) addr);
++ xfsidbg_xchashlist((xfs_chashlist_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xlogitem(
++
++static int kdbm_xfs_xdaargs(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1007,11 +1110,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xlogitem((xfs_log_item_t *) addr);
++ xfsidbg_xdaargs((xfs_da_args_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xmount(
++static int kdbm_xfs_xdabuf(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1028,11 +1131,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xmount((xfs_mount_t *) addr);
++ xfsidbg_xdabuf((xfs_dabuf_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xnode(
++static int kdbm_xfs_xdanode(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1049,11 +1152,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xnode((xfs_inode_t *) addr);
++ xfsidbg_xdanode((xfs_da_intnode_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xcore(
++static int kdbm_xfs_xdastate(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1070,11 +1173,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xcore((xfs_iocore_t *) addr);
++ xfsidbg_xdastate((xfs_da_state_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xperag(
++static int kdbm_xfs_xdirleaf(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1091,11 +1194,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xperag((xfs_mount_t *) addr);
++ xfsidbg_xdirleaf((xfs_dir_leafblock_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xqm_diskdq(
++static int kdbm_xfs_xdirsf(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1112,11 +1215,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xqm_diskdq((xfs_disk_dquot_t *) addr);
++ xfsidbg_xdirsf((xfs_dir_shortform_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xqm_dqattached_inos(
++static int kdbm_xfs_xdir2free(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1133,11 +1236,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xqm_dqattached_inos((xfs_mount_t *) addr);
++ xfsidbg_xdir2free((xfs_dir2_free_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xqm_dquot(
++static int kdbm_xfs_xdir2sf(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1154,38 +1257,53 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xqm_dquot((xfs_dquot_t *) addr);
++ xfsidbg_xdir2sf((xfs_dir2_sf_t *) addr);
+ return 0;
+ }
+
+-#ifdef CONFIG_XFS_QUOTA
+-static int kdbm_xfs_xqm(
++static int kdbm_xfs_xexlist(
+ int argc,
+ const char **argv,
+ const char **envp,
+ struct pt_regs *regs)
+ {
+- if (argc != 0)
++ 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();
++ xfsidbg_xexlist((xfs_inode_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xqm_freelist(
++static int kdbm_xfs_xflist(
+ int argc,
+ const char **argv,
+ const char **envp,
+ struct pt_regs *regs)
+ {
+- if (argc != 0)
++ 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_freelist();
++ xfsidbg_xflist((xfs_bmap_free_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xqm_htab(
++static int kdbm_xfs_xhelp(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1194,12 +1312,11 @@
+ if (argc != 0)
+ return KDB_ARGCOUNT;
+
+- xfsidbg_xqm_htab();
++ xfsidbg_xhelp();
+ return 0;
+ }
+-#endif
+
+-static int kdbm_xfs_xqm_mplist(
++static int kdbm_xfs_xiclog(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1216,11 +1333,11 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xqm_mplist((xfs_mount_t *) addr);
++ xfsidbg_xiclog((xlog_in_core_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xqm_qinfo(
++static int kdbm_xfs_xiclogall(
+ int argc,
+ const char **argv,
+ const char **envp,
+@@ -1237,11 +1354,473 @@
+ if (diag)
+ return diag;
+
+- xfsidbg_xqm_qinfo((xfs_mount_t *) addr);
++ xfsidbg_xiclogall((xlog_in_core_t *) addr);
+ return 0;
+ }
+
+-static int kdbm_xfs_xqm_tpdqinfo(
++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,
+@@ -1404,45 +1983,52 @@
+ }
+
+
+-static void printvnode(vnode_t *vp)
++static void printbhv(bhv_desc_t *bdp)
+ {
+- bhv_desc_t *bh;
+ 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;
++ }
++}
+
+- kdb_printf("vnode: 0x%p type ", vp);
++
++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 %p\n", &vp->v_bh);
++ kdb_printf(" v_bh 0x%p\n", &vp->v_bh);
+
+- if ((bh = vp->v_bh.bh_first)) {
+- kdb_printf(" v_inode 0x%p v_bh->bh_first 0x%p pobj 0x%p\n",
+- LINVFS_GET_IP(vp), bh, bh->bd_pdata);
+-
+- if (kdbnearsym((unsigned long)bh->bd_ops, &symtab))
+- kdb_printf(" ops %s ", symtab.sym_name);
+- else
+- kdb_printf(" ops %s/0x%p ",
+- "???", (void *)bh->bd_ops);
+- } else {
+- kdb_printf(" v_inode 0x%p v_bh->bh_first = NULLBHV ",
+- LINVFS_GET_IP(vp));
+- }
++ printbhv(vp->v_fbhv);
+
+ printflags((__psunsigned_t)vp->v_flag, tab_vflags, "flag =");
+ kdb_printf("\n");
+
+-#ifdef CONFIG_XFS_VNODE_TRACING
++#ifdef XFS_VNODE_TRACE
+ kdb_printf(" v_trace 0x%p\n", vp->v_trace);
+-#endif /* CONFIG_XFS_VNODE_TRACING */
++#endif /* XFS_VNODE_TRACE */
+
+- kdb_printf(" v_vfsp 0x%p v_number %Lx\n",
+- vp->v_vfsp, vp->v_number);
++ 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,
+@@ -1453,9 +2039,7 @@
+ int nextarg = 1;
+ long offset = 0;
+ int diag;
+- vnode_t *vp;
+-/* bhv_desc_t *bh; */
+-/* kdb_symtab_t symtab;*/
++ vnode_t vp;
+
+ if (argc != 1)
+ return KDB_ARGCOUNT;
+@@ -1465,14 +2049,82 @@
+ if (diag)
+ return diag;
+
+- vp = (vnode_t *)addr;
++ 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;
+
+- printvnode(vp);
++ print_vfs(&vfs, addr);
+
+ return 0;
+ }
+
+-#ifdef CONFIG_XFS_VNODE_TRACING
++
++#ifdef XFS_VNODE_TRACE
+ /*
+ * Print a vnode trace entry.
+ */
+@@ -1668,7 +2320,7 @@
+
+ return 0;
+ }
+-#endif /* CONFIG_XFS_VNODE_TRACING */
++#endif /* XFS_VNODE_TRACE */
+
+
+ static void printinode(struct inode *ip)
+@@ -1682,16 +2334,21 @@
+ 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 = %u:%u i_state = 0x%lx\n",
++ " i_mode = 0x%x i_nlink = %d i_rdev = 0x%x i_state = 0x%lx\n",
+ ip->i_mode, ip->i_nlink,
+- MAJOR(ip->i_rdev),
+- MINOR(ip->i_rdev),
+- ip->i_state);
+-
+- kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n",
+- ip->i_hash.next, ip->i_hash.prev);
++ 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",
+@@ -1717,52 +2374,44 @@
+ {
+ int diag;
+ int nextarg = 1;
+-/* char *symname; */
+ long offset = 0;
+ unsigned long addr;
+ struct inode *ip;
+-/* bhv_desc_t *bh; */
+-#ifdef CONFIG_XFS_VNODE_TRACING
++ vnode_t vp;
++#ifdef XFS_VNODE_TRACE
+ ktrace_entry_t *ktep;
+ ktrace_snap_t kts;
+ #endif
+- vnode_t *vp;
+
+ if (argc != 1)
+ return KDB_ARGCOUNT;
+
+ diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+-
+ if (diag)
+ return diag;
+
+- vp = (vnode_t *)addr;
+-
+- ip = LINVFS_GET_IP(vp);
++ 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%p\n", vp);
+- printvnode(vp);
+-
+-#ifdef CONFIG_XFS_VNODE_TRACING
++ kdb_printf("--> Vnode @ 0x%lx\n", addr);
++ printvnode(&vp, addr);
+
+- kdb_printf("--> Vntrace @ 0x%p/0x%p\n", vp, vp->v_trace);
+-
+- if (vp->v_trace == NULL)
++#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);
+-
++ 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);
++ ktep = ktrace_next(vp.v_trace, &kts);
+ }
+-#endif /* CONFIG_XFS_VNODE_TRACING */
+-
++#endif /* XFS_VNODE_TRACE */
+ return 0;
+ }
+
+@@ -1772,15 +2421,15 @@
+ static char *pb_flag_vals[] = {
+ /* 0 */ "READ", "WRITE", "MAPPED", "PARTIAL", "ASYNC",
+ /* 5 */ "NONE", "DELWRI", "FREED", "SYNC", "MAPPABLE",
+-/* 10 */ "STALE", "FS_MANAGED", "INVALID12", "LOCK", "TRYLOCK",
++/* 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 *pbm_flag_vals[] = {
++static char *iomap_flag_vals[] = {
+ "EOF", "HOLE", "DELAY", "INVALID0x08",
+- "INVALID0x10", "UNWRITTEN", "INVALID0x40", "INVALID0x80",
++ "INVALID0x10", "UNWRITTEN", "NEW", "INVALID0x80",
+ NULL };
+
+
+@@ -1795,7 +2444,7 @@
+ for (index = 0; flags && mapping[index]; flags >>= 1, index++) {
+ if (flags & 1) {
+ if ((offset + strlen(mapping[index]) + 1) >= 80) {
+- strcat(buffer, "\n ");
++ strcat(buffer, "\n ");
+ offset = 12;
+ } else if (offset > 12) {
+ strcat(buffer, " ");
+@@ -1832,6 +2481,48 @@
+ 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)
+ {
+@@ -1849,109 +2540,64 @@
+ (diag = kdb_getarea(bp, addr)))
+ return diag;
+
+- kdb_printf("page_buf_t at 0x%lx\n", addr);
+- kdb_printf(" pb_flags %s\n", pb_flags(bp.pb_flags));
+- kdb_printf(" pb_target 0x%p pb_hold %d pb_next 0x%p pb_prev 0x%p\n",
+- bp.pb_target, bp.pb_hold.counter,
+- bp.pb_list.next, bp.pb_list.prev);
+- kdb_printf(" pb_hash_index %d pb_hash_next 0x%p pb_hash_prev 0x%p\n",
+- bp.pb_hash_index,
+- bp.pb_hash_list.next,
+- bp.pb_hash_list.prev);
+- kdb_printf(" pb_file_offset 0x%llx pb_buffer_length 0x%llx pb_addr 0x%p\n",
+- (unsigned long long) bp.pb_file_offset,
+- (unsigned long long) bp.pb_buffer_length,
+- bp.pb_addr);
+- kdb_printf(" pb_bn 0x%Lx pb_count_desired 0x%lx\n",
+- bp.pb_bn,
+- (unsigned long) bp.pb_count_desired);
+- kdb_printf(" pb_io_remaining %d pb_error %u\n",
+- bp.pb_io_remaining.counter,
+- bp.pb_error);
+- kdb_printf(" pb_page_count %u pb_offset 0x%x pb_pages 0x%p\n",
+- bp.pb_page_count, bp.pb_offset,
+- bp.pb_pages);
+-#ifdef PAGEBUF_LOCK_TRACKING
+- kdb_printf(" pb_iodonesema (%d,%d) pb_sema (%d,%d) pincount (%d) last holder %d\n",
+- bp.pb_iodonesema.count.counter,
+- bp.pb_iodonesema.sleepers,
+- bp.pb_sema.count.counter, bp.pb_sema.sleepers,
+- bp.pb_pin_count.counter, bp.pb_last_holder);
+-#else
+- kdb_printf(" pb_iodonesema (%d,%d) pb_sema (%d,%d) pincount (%d)\n",
+- bp.pb_iodonesema.count.counter,
+- bp.pb_iodonesema.sleepers,
+- bp.pb_sema.count.counter, bp.pb_sema.sleepers,
+- bp.pb_pin_count.counter);
+-#endif
+- if (bp.pb_fspriv || bp.pb_fspriv2) {
+- kdb_printf( "pb_fspriv 0x%p pb_fspriv2 0x%p\n",
+- bp.pb_fspriv, bp.pb_fspriv2);
+- }
++ print_pagebuf(&bp, addr);
+
+ return 0;
+ }
+
+-/* XXXXXXXXXXXXXXXXXXXXXX */
+-/* The start of this deliberately looks like a read_descriptor_t in layout */
+-typedef struct {
+- read_descriptor_t io_rdesc;
+-
+- /* 0x10 */
+- page_buf_rw_t io_dir; /* read or write */
+- loff_t io_offset; /* Starting offset of I/O */
+- int io_iovec_nr; /* Number of entries in iovec */
+-
+- /* 0x20 */
+- struct iovec **io_iovec; /* iovec list indexed by iovec_index */
+- loff_t io_iovec_offset; /* offset into current iovec. */
+- int io_iovec_index; /* current iovec being processed */
+- unsigned int io_sshift; /* sector bit shift */
+- loff_t io_i_size; /* size of the file */
+-} pb_io_desc_t;
+-
+ static int
+-kdbm_pbiodesc(int argc, const char **argv, const char **envp,
++kdbm_pbdelay(int argc, const char **argv, const char **envp,
+ struct pt_regs *regs)
+ {
+- pb_io_desc_t pbio;
++#ifdef DEBUG
++ unsigned long verbose = 0;
++ int count = 0;
++ struct list_head *curr, *next;
++ page_buf_t bp;
+ unsigned long addr;
+- long offset=0;
+- int nextarg;
+ int diag;
++ extern struct list_head pbd_delwrite_queue;
+
+- if (argc != 1)
++ if (argc > 1)
+ return KDB_ARGCOUNT;
+
+- nextarg = 1;
+- if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+- (diag = kdb_getarea(pbio, addr)))
+-
+- kdb_printf("pb_io_desc_t at 0x%lx\n", addr);
+- kdb_printf(" io_rdesc [ written 0x%lx count 0x%lx buf 0x%p error %d ]\n",
+- (unsigned long) pbio.io_rdesc.written,
+- (unsigned long) pbio.io_rdesc.count,
+- pbio.io_rdesc.buf, pbio.io_rdesc.error);
+-
+- kdb_printf(" io_dir %d io_offset 0x%Lx io_iovec_nr 0x%d\n",
+- pbio.io_dir, pbio.io_offset, pbio.io_iovec_nr);
++ if (argc == 1) {
++ if ((diag = kdbgetularg(argv[1], &verbose))) {
++ return diag;
++ }
++ }
+
+- kdb_printf(" io_iovec 0x%p io_iovec_offset 0x%Lx io_iovec_index 0x%d\n",
+- pbio.io_iovec, pbio.io_iovec_offset, pbio.io_iovec_index);
++ if (!verbose) {
++ kdb_printf("index pb pin flushtime\n");
++ }
+
+- kdb_printf(" io_sshift 0x%d io_i_size 0x%Lx\n",
+- pbio.io_sshift, pbio.io_i_size);
++ 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_pbmap(int argc, const char **argv, const char **envp,
++kdbm_iomap(int argc, const char **argv, const char **envp,
+ struct pt_regs *regs)
+ {
+- page_buf_bmap_t pbm;
++ xfs_iomap_t iomap;
+ unsigned long addr;
+- long offset=0;
++ long offset=0;
+ int nextarg;
+ int diag;
+
+@@ -1960,113 +2606,49 @@
+
+ nextarg = 1;
+ if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+- (diag = kdb_getarea(pbm, addr)))
++ (diag = kdb_getarea(iomap, addr)))
+
+- kdb_printf("page_buf_bmap_t at 0x%lx\n", addr);
+- kdb_printf(" pbm_bn 0x%llx pbm_offset 0x%Lx pbm_delta 0x%lx pbm_bsize 0x%lx\n",
+- (long long) pbm.pbm_bn, pbm.pbm_offset,
+- (unsigned long) pbm.pbm_delta, (unsigned long) pbm.pbm_bsize);
++ 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%lx\n",
++ (long long) iomap.iomap_bn, iomap.iomap_offset,
++ (unsigned long) iomap.iomap_delta, (unsigned long) iomap.iomap_bsize);
+
+- kdb_printf(" pbm_flags %s\n", map_flags(pbm.pbm_flags, pbm_flag_vals));
++ kdb_printf(" iomap_flags %s\n", map_flags(iomap.iomap_flags, iomap_flag_vals));
+
+ return 0;
+ }
+
+ #ifdef PAGEBUF_TRACE
+-# ifdef __PAGEBUF_TRACE__
+-# undef __PAGEBUF_TRACE__
+-# undef PB_DEFINE_TRACES
+-# undef PB_TRACE_START
+-# undef PB_TRACE_REC
+-# undef PB_TRACE_END
+-# endif
+-#include "pagebuf/page_buf_trace.h"
+-
+-#define EV_SIZE (sizeof(event_names)/sizeof(char *))
+-
+-void
+-pb_trace_core(
+- unsigned long match,
+- char *event_match,
+- unsigned long long offset,
+- long long mask)
+-{
+- extern struct pagebuf_trace_buf pb_trace;
+- int i, total, end;
+- pagebuf_trace_t *trace;
+- char *event;
+- char value[10];
+-
+- end = pb_trace.start - 1;
+- if (end < 0)
+- end = PB_TRACE_BUFSIZE - 1;
+-
+- if (match && (match < PB_TRACE_BUFSIZE)) {
+- for (i = pb_trace.start, total = 0; i != end; i = CIRC_INC(i)) {
+- trace = &pb_trace.buf[i];
+- if (trace->pb == 0)
+- continue;
+- total++;
+- }
+- total = total - match;
+- for (i = pb_trace.start; i != end && total; i = CIRC_INC(i)) {
+- trace = &pb_trace.buf[i];
+- if (trace->pb == 0)
+- continue;
+- total--;
+- }
+- match = 0;
+- } else
+- i = pb_trace.start;
+- for ( ; i != end; i = CIRC_INC(i)) {
+- trace = &pb_trace.buf[i];
+-
+- if (offset) {
+- if ((trace->offset & ~mask) != offset)
+- continue;
+- }
+-
+- if (trace->pb == 0)
+- continue;
+-
+- if ((match != 0) && (trace->pb != match))
+- continue;
+-
+- if ((trace->event < EV_SIZE-1) && event_names[trace->event]) {
+- event = event_names[trace->event];
+- } else if (trace->event == EV_SIZE-1) {
+- event = (char *)trace->misc;
+- } else {
+- event = value;
+- sprintf(value, "%8d", trace->event);
+- }
+-
+- if (event_match && strcmp(event, event_match)) {
+- continue;
+- }
++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%lx [%s] (hold %u lock %d) misc 0x%p",
+- trace->pb, event,
+- trace->hold, trace->lock_value,
+- trace->misc);
+- kdb_symbol_print((unsigned int)trace->ra, NULL,
+- KDB_SP_SPACEB|KDB_SP_PAREN|KDB_SP_NEWLINE);
+- kdb_printf(" offset 0x%Lx size 0x%x task 0x%p\n",
+- trace->offset, trace->size, trace->task);
+- kdb_printf(" flags: %s\n",
+- pb_flags(trace->flags));
+- }
++ 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;
++ long mask = 0;
++ unsigned long offset = 0;
++ int diag;
++ ktrace_entry_t *ktep;
++ ktrace_snap_t kts;
+
+ if (argc > 2)
+ return KDB_ARGCOUNT;
+@@ -2078,13 +2660,23 @@
+ }
+
+ if (argc > 1) {
+- diag = kdbgetularg(argv[1], &mask);
++ diag = kdbgetularg(argv[1], &mask); /* sign extent mask */
+ if (diag)
+ return diag;
+ }
+
+- pb_trace_core(0, NULL, (unsigned long long)offset,
+- (long long)mask); /* sign extent mask */
++ 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;
+ }
+
+@@ -2092,10 +2684,12 @@
+ 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;
++ 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;
+@@ -2103,69 +2697,102 @@
+ if (argc == 1) {
+ if (isupper(argv[1][0]) || islower(argv[1][0])) {
+ event_match = (char *)argv[1];
+- printk("event match on \"%s\"\n", event_match);
++ kdb_printf("event match on \"%s\"\n", event_match);
+ argc = 0;
+ } else {
+ nextarg = 1;
+- diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
++ diag = kdbgetaddrarg(argc, argv,
++ &nextarg, &addr, &offset, NULL, regs);
+ if (diag) {
+- printk("failed to parse %s as a number\n",
+- argv[1]);
++ kdb_printf("non-numeric arg: %s\n", argv[1]);
+ return diag;
+ }
+ }
+ }
+
+- pb_trace_core(addr, event_match, 0LL, 0LL);
+- return 0;
+-}
+-
+-#else /* PAGEBUF_TRACE */
+-static int
+-kdbm_pbtrace(int argc, const char **argv, const char **envp,
+- struct pt_regs *regs)
+-{
+- kdb_printf("pagebuf tracing not compiled in\n");
+-
++ 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 /* PAGEBUF_TRACE */
++#endif
+
+-static struct xif {
++struct xif {
+ char *name;
+ int (*func)(int, const char **, const char **, struct pt_regs *);
+ char *args;
+ char *help;
+-} xfsidbg_funcs[] = {
++};
++
++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"},
+-#ifdef CONFIG_XFS_VNODE_TRACING
++ { "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 /* CONFIG_XFS_VNODE_TRACING */
++ { "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 DEBUG
++#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"},
+- { "xbrec", kdbm_xfs_xbrec, "<xfs_bmbt_rec_64_t",
++#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)"},
+@@ -2175,12 +2802,29 @@
+ "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>",
+@@ -2197,12 +2841,20 @@
+ "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>",
+@@ -2215,12 +2867,26 @@
+ "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>",
+@@ -2255,6 +2921,10 @@
+ #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>",
+@@ -2264,6 +2934,18 @@
+ { 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)
+ {
+@@ -2271,20 +2953,8 @@
+
+ for (p = xfsidbg_funcs; p->name; p++)
+ kdb_register(p->name, p->func, p->args, p->help, 0);
+-
+- kdb_register("pb", kdbm_pb, "<vaddr>", "Display page_buf_t", 0);
+- kdb_register("pbflags", kdbm_pb_flags, "<flags>",
+- "Display page buf flags", 0);
+- kdb_register("pbiodesc", kdbm_pbiodesc, "<pb_io_desc_t *>",
+- "Display I/O Descriptor", 0);
+- kdb_register("pbmap", kdbm_pbmap, "<page_buf_bmap_t *>",
+- "Display Bmap", 0);
+- kdb_register("pbtrace", kdbm_pbtrace, "<vaddr>|<count>",
+- "page_buf_t trace", 0);
+-#ifdef PAGEBUF_TRACE
+- kdb_register("pboffset", kdbm_pbtrace_offset, "<addr> [<mask>]",
+- "page_buf_t trace", 0);
+-#endif
++ for (p = pb_funcs; p->name; p++)
++ kdb_register(p->name, p->func, p->args, p->help, 0);
+ return 0;
+ }
+
+@@ -2295,16 +2965,8 @@
+
+ for (p = xfsidbg_funcs; p->name; p++)
+ kdb_unregister(p->name);
+-
+- kdb_unregister("pb");
+- kdb_unregister("pbflags");
+- kdb_unregister("pbmap");
+- kdb_unregister("pbiodesc");
+- kdb_unregister("pbtrace");
+-#ifdef PAGEBUF_TRACE
+- kdb_unregister("pboffset");
+-#endif
+-
++ for (p = pb_funcs; p->name; p++)
++ kdb_unregister(p->name);
+ }
+
+ /*
+@@ -2315,19 +2977,35 @@
+ "start_bno", "near_bno", "this_bno"
+ };
+
++static int xargument = 0;
+
+ /*
+ * Prototypes for static functions.
+ */
+-#ifdef DEBUG
++#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);
+@@ -2345,6 +3023,10 @@
+ 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);
+
+@@ -2352,7 +3034,7 @@
+ * Static functions.
+ */
+
+-#ifdef DEBUG
++#ifdef XFS_ALLOC_TRACE
+ /*
+ * Print xfs alloc trace buffer entry.
+ */
+@@ -2378,24 +3060,24 @@
+ return 0;
+ switch ((long)ktep->val[0] & 0xffffL) {
+ case XFS_ALLOC_KTRACE_ALLOC:
+- kdb_printf("alloc %s[%s %d] mp 0x%p\n",
++ kdb_printf("alloc %s[%s %ld] mp 0x%p\n",
+ (char *)ktep->val[1],
+ ktep->val[2] ? (char *)ktep->val[2] : "",
+- (__psint_t)ktep->val[0] >> 16,
++ (long)ktep->val[0] >> 16,
+ (xfs_mount_t *)ktep->val[3]);
+ kdb_printf(
+- "agno %d agbno %d minlen %d maxlen %d mod %d prod %d minleft %d\n",
+- (__psunsigned_t)ktep->val[4],
+- (__psunsigned_t)ktep->val[5],
+- (__psunsigned_t)ktep->val[6],
+- (__psunsigned_t)ktep->val[7],
+- (__psunsigned_t)ktep->val[8],
+- (__psunsigned_t)ktep->val[9],
+- (__psunsigned_t)ktep->val[10]);
+- kdb_printf("total %d alignment %d len %d type %s otype %s\n",
+- (__psunsigned_t)ktep->val[11],
+- (__psunsigned_t)ktep->val[12],
+- (__psunsigned_t)ktep->val[13],
++ "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",
+@@ -2405,76 +3087,76 @@
+ ((__psint_t)ktep->val[15] & (1 << 0)) != 0);
+ break;
+ case XFS_ALLOC_KTRACE_FREE:
+- kdb_printf("free %s[%s %d] mp 0x%p\n",
++ kdb_printf("free %s[%s %ld] mp 0x%p\n",
+ (char *)ktep->val[1],
+ ktep->val[2] ? (char *)ktep->val[2] : "",
+- (__psint_t)ktep->val[0] >> 16,
++ (long)ktep->val[0] >> 16,
+ (xfs_mount_t *)ktep->val[3]);
+- kdb_printf("agno %d agbno %d len %d isfl %d\n",
+- (__psunsigned_t)ktep->val[4],
+- (__psunsigned_t)ktep->val[5],
+- (__psunsigned_t)ktep->val[6],
+- (__psint_t)ktep->val[7]);
++ 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 %d] mp 0x%p\n",
++ kdb_printf("modagf %s[%s %ld] mp 0x%p\n",
+ (char *)ktep->val[1],
+ ktep->val[2] ? (char *)ktep->val[2] : "",
+- (__psint_t)ktep->val[0] >> 16,
++ (long)ktep->val[0] >> 16,
+ (xfs_mount_t *)ktep->val[3]);
+ printflags((__psint_t)ktep->val[4], modagf_flags, "modified");
+- kdb_printf("seqno %d length %d roots b %d c %d\n",
+- (__psunsigned_t)ktep->val[5],
+- (__psunsigned_t)ktep->val[6],
+- (__psunsigned_t)ktep->val[7],
+- (__psunsigned_t)ktep->val[8]);
+- kdb_printf("levels b %d c %d flfirst %d fllast %d flcount %d\n",
+- (__psunsigned_t)ktep->val[9],
+- (__psunsigned_t)ktep->val[10],
+- (__psunsigned_t)ktep->val[11],
+- (__psunsigned_t)ktep->val[12],
+- (__psunsigned_t)ktep->val[13]);
+- kdb_printf("freeblks %d longest %d\n",
+- (__psunsigned_t)ktep->val[14],
+- (__psunsigned_t)ktep->val[15]);
++ 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 %d] mp 0x%p\n",
++ kdb_printf("unbusy %s [%s %ld] mp 0x%p\n",
+ (char *)ktep->val[1],
+ ktep->val[2] ? (char *)ktep->val[2] : "",
+- (__psint_t)ktep->val[0] >> 16,
++ (long)ktep->val[0] >> 16,
+ (xfs_mount_t *)ktep->val[3]);
+- kdb_printf(" agno %d slot %d tp 0x%x\n",
+- (__psunsigned_t)ktep->val[4],
+- (__psunsigned_t)ktep->val[7],
+- (__psunsigned_t)ktep->val[8]);
++ 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 %d] mp 0x%p\n",
++ kdb_printf("busy %s [%s %ld] mp 0x%p\n",
+ (char *)ktep->val[1],
+ ktep->val[2] ? (char *)ktep->val[2] : "",
+- (__psint_t)ktep->val[0] >> 16,
++ (long)ktep->val[0] >> 16,
+ (xfs_mount_t *)ktep->val[3]);
+- kdb_printf(" agno %d agbno %d len %d slot %d tp 0x%x\n",
+- (__psunsigned_t)ktep->val[4],
+- (__psunsigned_t)ktep->val[5],
+- (__psunsigned_t)ktep->val[6],
+- (__psunsigned_t)ktep->val[7],
+- (__psunsigned_t)ktep->val[8]);
++ 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 %d] mp 0x%p\n",
++ kdb_printf("busy-search %s [%s %ld] mp 0x%p\n",
+ (char *)ktep->val[1],
+ ktep->val[2] ? (char *)ktep->val[2] : "",
+- (__psint_t)ktep->val[0] >> 16,
++ (long)ktep->val[0] >> 16,
+ (xfs_mount_t *)ktep->val[3]);
+- kdb_printf(" agno %d agbno %d len %d slot %d tp 0x%x\n",
+- (__psunsigned_t)ktep->val[4],
+- (__psunsigned_t)ktep->val[5],
+- (__psunsigned_t)ktep->val[6],
+- (__psunsigned_t)ktep->val[7],
+- (__psunsigned_t)ktep->val[8]);
++ 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");
+@@ -2482,7 +3164,242 @@
+ }
+ return 1;
+ }
+-#endif /* DEBUG */
++#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.
+@@ -2603,8 +3520,11 @@
+ 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));
++ 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++) {
+@@ -2612,7 +3532,8 @@
+
+ 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),
++ i, INT_GET(r->ir_startino, ARCH_CONVERT),
++ INT_GET(r->ir_freecount, ARCH_CONVERT),
+ INT_GET(r->ir_free, ARCH_CONVERT));
+ }
+ } else {
+@@ -2626,7 +3547,8 @@
+ 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));
++ i, INT_GET(k->ir_startino, ARCH_CONVERT),
++ INT_GET(*p, ARCH_CONVERT));
+ }
+ }
+ }
+@@ -2678,30 +3600,199 @@
+ 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 an xfs_da_state_path structure.
++ * Print a xfs v2 directory trace buffer entry.
+ */
+-static void
+-xfs_dastate_path(xfs_da_state_path_t *p)
++static int
++xfs_dir2_trace_entry(ktrace_entry_t *ktep)
+ {
+- int i;
++ char *cp;
++ int i;
++ int len;
+
+- 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;
+- }
++ 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.
+@@ -2847,19 +3938,19 @@
+ 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 & IFMT) >> 12],
+- m & ISUID ? 'u' : '-',
+- m & ISGID ? 'g' : '-',
+- m & ISVTX ? 'v' : '-',
+- m & IREAD ? 'r' : '-',
+- m & IWRITE ? 'w' : '-',
+- m & IEXEC ? 'x' : '-',
+- m & (IREAD >> 3) ? 'r' : '-',
+- m & (IWRITE >> 3) ? 'w' : '-',
+- m & (IEXEC >> 3) ? 'x' : '-',
+- m & (IREAD >> 6) ? 'r' : '-',
+- m & (IWRITE >> 6) ? 'w' : '-',
+- m & (IEXEC >> 6) ? 'x' : '-');
++ "?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;
+ }
+
+@@ -2883,9 +3974,9 @@
+ xfs_fmtuuid(uuid_t *uu)
+ {
+ static char rval[40];
+- char *o = rval;
+- char *i = (unsigned char*)uu;
+- int b;
++ char *o = rval;
++ char *i = (unsigned char*)uu;
++ int b;
+
+ for (b=0;b<16;b++) {
+ o+=sprintf(o, "%02x", *i++);
+@@ -2930,9 +4021,9 @@
+ kdb_printf("\n");
+ return;
+ }
+- kdb_printf("inode 0x%p ino 0x%llu logged %d flags: ",
++ 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_logged);
++ 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",
+@@ -2942,10 +4033,9 @@
+ kdb_printf("root bytes %d root orig 0x%x\n",
+ ilip->ili_root_size, ilip->ili_orig_root);
+ #endif
+- kdb_printf("size %d fields: ", ilip->ili_format.ilf_size);
+- printflags(ilip->ili_format.ilf_fields, ilf_fields, "formatfield");
+- kdb_printf(" last fields: ");
+- printflags(ilip->ili_last_fields, ilf_fields, "lastfield");
++ 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)),
+@@ -3001,6 +4091,129 @@
+ }
+ }
+
++#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.
+@@ -3047,14 +4260,14 @@
+ INT_GET(dip->di_gid, convert),
+ (uint)INT_GET(dip->di_projid, convert),
+ (uint)INT_GET(dip->di_flushiter, convert));
+- kdb_printf("atime 0x%x:%x mtime 0x%x:%x ctime 0x%x:%x\n",
++ 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 0x%Lx ", INT_GET(dip->di_size, 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),
+@@ -3071,6 +4284,129 @@
+ 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.
+ */
+@@ -3194,6 +4530,109 @@
+ }
+ }
+
++#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.
+@@ -3215,7 +4654,7 @@
+ args->wasfromfl, args->isfl, args->userdata);
+ }
+
+-#ifdef DEBUG
++#ifdef XFS_ALLOC_TRACE
+ /*
+ * Print out all the entries in the alloc trace buf corresponding
+ * to the given mount point.
+@@ -3225,7 +4664,6 @@
+ {
+ ktrace_entry_t *ktep;
+ ktrace_snap_t kts;
+- extern ktrace_t *xfs_alloc_trace_buf;
+
+ if (xfs_alloc_trace_buf == NULL) {
+ kdb_printf("The xfs alloc trace buffer is not initialized\n");
+@@ -3234,14 +4672,53 @@
+
+ ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
+ while (ktep != NULL) {
+- if ((__psint_t)ktep->val[0] && (xfs_mount_t *)ktep->val[3] == mp) {
++ 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);
+ }
+ }
+-#endif /* DEBUG */
++
++/*
++ * 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.
+@@ -3368,41 +4845,232 @@
+ }
+ }
+
+-
++#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 xfs bmap internal record
++ * Print out the bmap btree trace buffer attached to the given inode.
+ */
+ static void
+-xfsidbg_xbirec(xfs_bmbt_irec_t *r)
++xfsidbg_xbmitrace(xfs_inode_t *ip)
+ {
+- 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);
+-}
++ 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 a bmap alloc argument structure for XFS.
++ * 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_xbmalla(xfs_bmalloca_t *a)
++xfsidbg_xbmstrace(xfs_inode_t *ip)
+ {
+- 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);
+-}
++ 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
+@@ -3667,6 +5335,286 @@
+ }
+ }
+
++#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.
+@@ -3740,9 +5688,8 @@
+ 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 %s blkno 0x%x\n",
+- dabuf->ra, dabuf->prev, dabuf->next,
+- XFS_BUFTARG_NAME(dabuf->dev), dabuf->blkno);
++ 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
+ }
+
+@@ -4012,6 +5959,119 @@
+ }
+ }
+
++#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.
+@@ -4095,13 +6155,18 @@
+ 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) refcnt: %d bwritecnt: %d",
++ 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:");
++ printflags(iclog->ic_state, ic_flags, " state:");
+ else
+- kdb_printf("state: INVALID 0x%x", iclog->ic_state);
++ kdb_printf(" state: INVALID 0x%x", iclog->ic_state);
+ kdb_printf("\n");
+ } /* xfsidbg_xiclog */
+
+@@ -4150,6 +6215,44 @@
+ }
+ }
+
++#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.
+@@ -4270,8 +6373,8 @@
+ xfsidbg_get_cstate(log->l_covered_state));
+ kdb_printf("flags: ");
+ printflags(log->l_flags, t_flags,"log");
+- kdb_printf(" dev: %s logBBstart: %lld logsize: %d logBBsize: %d\n",
+- XFS_BUFTARG_NAME(log->l_targ), (long long) log->l_logBBstart,
++ 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,
+@@ -4290,11 +6393,50 @@
+ 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;
+- kdb_printf("GResBlocks: %d GResRemain: %d GWrBlocks: %d GWrRemain: %d\n",
++ 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
+@@ -4488,10 +6630,10 @@
+ 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 desc %p ops 0x%p\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);
++ 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) {
+@@ -4547,7 +6689,7 @@
+ "6-1-buf", /* 7 */
+ "inode", /* 8 */
+ "buf", /* 9 */
+- "dquot", /* 10 */
++ "dquot", /* 10 */
+ 0
+ };
+ static char *li_flags[] = {
+@@ -4609,7 +6751,7 @@
+ static char *xmount_flags[] = {
+ "WSYNC", /* 0x0001 */
+ "INO64", /* 0x0002 */
+- "RQCHK", /* 0x0004 */
++ "RQCHK", /* 0x0004 */
+ "FSCLEAN", /* 0x0008 */
+ "FSSHUTDN", /* 0x0010 */
+ "NOATIME", /* 0x0020 */
+@@ -4646,14 +6788,11 @@
+ 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 %s logdev %s rtdev %s\n",
++ 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 ?
+- XFS_BUFTARG_NAME(mp->m_ddev_targp) : "none",
+- mp->m_logdev_targp ?
+- XFS_BUFTARG_NAME(mp->m_logdev_targp) : "none",
+- mp->m_rtdev_targp ?
+- XFS_BUFTARG_NAME(mp->m_rtdev_targp) : "none");
++ 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);
+@@ -4825,8 +6964,8 @@
+ ip->i_mnext,
+ ip->i_mprev,
+ XFS_ITOV_NULL(ip));
+- kdb_printf("dev %s ino %s\n",
+- XFS_BUFTARG_NAME(ip->i_mount->m_ddev_targp),
++ 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,
+@@ -4835,7 +6974,7 @@
+ kdb_printf("transp 0x%p &itemp 0x%p\n",
+ ip->i_transp,
+ ip->i_itemp);
+- kdb_printf("&lock 0x%p &iolock 0x%p",
++ kdb_printf("&lock 0x%p &iolock 0x%p ",
+ &ip->i_lock,
+ &ip->i_iolock);
+ kdb_printf("&flock 0x%p (%d) pincount 0x%x\n",
+@@ -4843,14 +6982,29 @@
+ xfs_ipincount(ip));
+ kdb_printf("udquotp 0x%p gdquotp 0x%p\n",
+ ip->i_udquot, ip->i_gdquot);
+- kdb_printf("new_size %Lx\n", ip->i_iocore.io_new_size);
++ 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 0x%x update size 0x%x\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,
+@@ -5032,6 +7186,9 @@
+ &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);
+
+@@ -5076,7 +7233,7 @@
+ kdb_printf("\nNumber of inodes with dquots attached: %d\n", n);
+ }
+
+-#ifdef CONFIG_XFS_QUOTA
++#ifdef CONFIG_XFS_QUOTA
+ static void
+ xfsidbg_xqm_freelist_print(xfs_frlist_t *qlist, char *title)
+ {
+@@ -5130,6 +7287,80 @@
+ }
+ #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)
+ {
+@@ -5206,7 +7437,54 @@
+
+ }
+
++#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.
+@@ -5284,7 +7562,7 @@
+ "dirty", /* 0x1 */
+ "sb_dirty", /* 0x2 */
+ "perm_log_res", /* 0x4 */
+- "sync", /* 0x08 */
++ "sync", /* 0x08 */
+ "dq_dirty", /* 0x10 */
+ 0
+ };
+@@ -5298,7 +7576,7 @@
+
+ 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_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;
+@@ -5310,32 +7588,31 @@
+ 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_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_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_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_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_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_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_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);
+diff -urN linux.org/fs/xfs/xfs_iget.c linux/fs/xfs/xfs_iget.c
+--- linux.org/fs/xfs/xfs_iget.c 2003-12-31 05:48:38.000000000 +0100
++++ linux/fs/xfs/xfs_iget.c 2004-01-02 04:21:44.000000000 +0100
+@@ -445,18 +445,17 @@
+ retry:
+ XFS_STATS_INC(xs_ig_attempts);
+
+- if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) {
++ if ((inode = VFS_GET_INODE(XFS_MTOVFS(mp), ino, 0))) {
+ bhv_desc_t *bdp;
+ xfs_inode_t *ip;
+ int newnode;
+
+-
+ vp = LINVFS_GET_VP(inode);
+ if (inode->i_state & I_NEW) {
+ inode_allocate:
+ vn_initialize(inode);
+ error = xfs_iget_core(vp, mp, tp, ino,
+- lock_flags, ipp, bno);
++ lock_flags, ipp, bno);
+ if (error) {
+ make_bad_inode(inode);
+ if (inode->i_state & I_NEW)
+@@ -506,9 +505,6 @@
+ mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
+ "xfsino", (long)vp->v_number);
+ mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", vp->v_number);
+-#ifdef NOTYET
+- mutex_init(&ip->i_range_lock.r_spinlock, MUTEX_SPIN, "xrange");
+-#endif /* NOTYET */
+ init_waitqueue_head(&ip->i_ipin_wait);
+ atomic_set(&ip->i_pincount, 0);
+ init_sema(&ip->i_flock, 1, "xfsfino", vp->v_number);
+@@ -830,9 +826,7 @@
+ } else if (lock_flags & XFS_ILOCK_SHARED) {
+ mraccess(&ip->i_lock);
+ }
+-#ifdef XFS_ILOCK_TRACE
+- xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)return_address);
+-#endif
++ xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address);
+ }
+
+ /*
+@@ -895,9 +889,7 @@
+ return 0;
+ }
+ }
+-#ifdef XFS_ILOCK_TRACE
+ xfs_ilock_trace(ip, 2, lock_flags, (inst_t *)__return_address);
+-#endif
+ return 1;
+ }
+
+@@ -955,9 +947,7 @@
+ (xfs_log_item_t*)(ip->i_itemp));
+ }
+ }
+-#ifdef XFS_ILOCK_TRACE
+ xfs_ilock_trace(ip, 3, lock_flags, (inst_t *)__return_address);
+-#endif
+ }
+
+ /*
+diff -urN linux.org/fs/xfs/xfs_inode.c linux/fs/xfs/xfs_inode.c
+--- linux.org/fs/xfs/xfs_inode.c 2003-12-31 05:48:38.000000000 +0100
++++ linux/fs/xfs/xfs_inode.c 2004-01-02 04:21:44.000000000 +0100
+@@ -908,9 +908,6 @@
+ #ifdef XFS_RW_TRACE
+ ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_SLEEP);
+ #endif
+-#ifdef XFS_STRAT_TRACE
+- ip->i_strat_trace = ktrace_alloc(XFS_STRAT_KTRACE_SIZE, KM_SLEEP);
+-#endif
+ #ifdef XFS_ILOCK_TRACE
+ ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_SLEEP);
+ #endif
+@@ -1144,8 +1141,8 @@
+ ip->i_d.di_onlink = 0;
+ ip->i_d.di_nlink = nlink;
+ ASSERT(ip->i_d.di_nlink == nlink);
+- ip->i_d.di_uid = current->fsuid;
+- ip->i_d.di_gid = current->fsgid;
++ ip->i_d.di_uid = current_fsuid(cr);
++ ip->i_d.di_gid = current_fsgid(cr);
+ ip->i_d.di_projid = prid;
+ memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
+
+@@ -1362,16 +1359,16 @@
+ ktrace_enter(ip->i_rwtrace,
+ (void*)((long)tag),
+ (void*)ip,
+- (void*)((ip->i_d.di_size >> 32) & 0xffffffff),
+- (void*)(ip->i_d.di_size & 0xffffffff),
++ (void*)(unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff),
++ (void*)(unsigned long)(ip->i_d.di_size & 0xffffffff),
+ (void*)((long)flag),
+- (void*)((new_size >> 32) & 0xffffffff),
+- (void*)(new_size & 0xffffffff),
+- (void*)((toss_start >> 32) & 0xffffffff),
+- (void*)(toss_start & 0xffffffff),
+- (void*)((toss_finish >> 32) & 0xffffffff),
+- (void*)(toss_finish & 0xffffffff),
+- (void*)((long)private.p_cpuid),
++ (void*)(unsigned long)((new_size >> 32) & 0xffffffff),
++ (void*)(unsigned long)(new_size & 0xffffffff),
++ (void*)(unsigned long)((toss_start >> 32) & 0xffffffff),
++ (void*)(unsigned long)(toss_start & 0xffffffff),
++ (void*)(unsigned long)((toss_finish >> 32) & 0xffffffff),
++ (void*)(unsigned long)(toss_finish & 0xffffffff),
++ (void*)(unsigned long)current_cpu(),
+ (void*)0,
+ (void*)0,
+ (void*)0,
+@@ -2755,17 +2752,8 @@
+ }
+ if (ip->i_afp)
+ xfs_idestroy_fork(ip, XFS_ATTR_FORK);
+-#ifdef NOTYET
+- if (ip->i_range_lock.r_sleep != NULL) {
+- freesema(ip->i_range_lock.r_sleep);
+- kmem_free(ip->i_range_lock.r_sleep, sizeof(sema_t));
+- }
+-#endif /* NOTYET */
+ mrfree(&ip->i_lock);
+ mrfree(&ip->i_iolock);
+-#ifdef NOTYET
+- mutex_destroy(&ip->i_range_lock.r_spinlock);
+-#endif /* NOTYET */
+ freesema(&ip->i_flock);
+ #ifdef XFS_BMAP_TRACE
+ ktrace_free(ip->i_xtrace);
+@@ -2776,9 +2764,6 @@
+ #ifdef XFS_RW_TRACE
+ ktrace_free(ip->i_rwtrace);
+ #endif
+-#ifdef XFS_STRAT_TRACE
+- ktrace_free(ip->i_strat_trace);
+-#endif
+ #ifdef XFS_ILOCK_TRACE
+ ktrace_free(ip->i_lock_trace);
+ #endif
+@@ -3707,7 +3692,7 @@
+ if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1)
+ return error ? XFS_ERROR(error) : 0;
+
+- if (current->fsuid != ip->i_d.di_uid) {
++ if (current_fsuid(cr) != ip->i_d.di_uid) {
+ mode >>= 3;
+ if (!in_group_p((gid_t)ip->i_d.di_gid))
+ mode >>= 3;
+@@ -3814,7 +3799,7 @@
+ * We're not supposed to change timestamps in readonly-mounted
+ * filesystems. Throw it away if anyone asks us.
+ */
+- if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
++ if (unlikely(vp->v_vfsp->vfs_flag & VFS_RDONLY))
+ return;
+
+ /*
+@@ -3828,17 +3813,17 @@
+
+ nanotime(&tv);
+ if (flags & XFS_ICHGTIME_MOD) {
+- inode->i_mtime = tv;
++ VN_MTIMESET(vp, &tv);
+ ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
+ ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
+ }
+ if (flags & XFS_ICHGTIME_ACC) {
+- inode->i_atime = tv;
++ VN_ATIMESET(vp, &tv);
+ ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
+ ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
+ }
+ if (flags & XFS_ICHGTIME_CHG) {
+- inode->i_ctime = tv;
++ VN_CTIMESET(vp, &tv);
+ ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
+ ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
+ }
+@@ -3859,17 +3844,18 @@
+ }
+
+ #ifdef XFS_ILOCK_TRACE
++ktrace_t *xfs_ilock_trace_buf;
++
+ void
+ xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
+ {
+ ktrace_enter(ip->i_lock_trace,
+ (void *)ip,
+- (void *)(__psint_t)lock, /* 1 = LOCK, 3=UNLOCK, etc */
+- (void *)(__psint_t)lockflags, /* XFS_ILOCK_EXCL etc */
+- (void *)ra, /* caller of ilock */
+- (void *)(__psint_t)cpuid(),
+- (void *)(__psint_t)current_pid(),
++ (void *)(unsigned long)lock, /* 1 = LOCK, 3=UNLOCK, etc */
++ (void *)(unsigned long)lockflags, /* XFS_ILOCK_EXCL etc */
++ (void *)ra, /* caller of ilock */
++ (void *)(unsigned long)current_cpu(),
++ (void *)(unsigned long)current_pid(),
+ 0,0,0,0,0,0,0,0,0,0);
+-
+ }
+-#endif /* ILOCK_TRACE */
++#endif
+diff -urN linux.org/fs/xfs/xfs_inode.h linux/fs/xfs/xfs_inode.h
+--- linux.org/fs/xfs/xfs_inode.h 2003-12-31 05:48:01.000000000 +0100
++++ linux/fs/xfs/xfs_inode.h 2004-01-02 04:21:44.000000000 +0100
+@@ -99,6 +99,13 @@
+ struct xfs_trans;
+ struct xfs_dquot;
+
++#if defined(XFS_ILOCK_TRACE)
++#define XFS_ILOCK_KTRACE_SIZE 32
++extern ktrace_t *xfs_ilock_trace_buf;
++extern void xfs_ilock_trace(struct xfs_inode *, int, unsigned int, inst_t *);
++#else
++#define xfs_ilock_trace(i,n,f,ra)
++#endif
+
+ /*
+ * This structure is used to communicate which extents of a file
+@@ -264,7 +271,10 @@
+ sema_t i_flock; /* inode flush lock */
+ atomic_t i_pincount; /* inode pin count */
+ wait_queue_head_t i_ipin_wait; /* inode pinning wait queue */
+-
++#ifdef HAVE_REFCACHE
++ struct xfs_inode **i_refcache; /* ptr to entry in ref cache */
++ struct xfs_inode *i_release; /* inode to unref */
++#endif
+ /* I/O state */
+ xfs_iocore_t i_iocore; /* I/O core */
+
+@@ -280,15 +290,22 @@
+ struct xfs_inode *i_cnext; /* cluster hash link forward */
+ struct xfs_inode *i_cprev; /* cluster hash link backward */
+
+-#ifdef DEBUG
+ /* Trace buffers per inode. */
++#ifdef XFS_BMAP_TRACE
+ struct ktrace *i_xtrace; /* inode extent list trace */
++#endif
++#ifdef XFS_BMBT_TRACE
+ struct ktrace *i_btrace; /* inode bmap btree trace */
++#endif
++#ifdef XFS_RW_TRACE
+ struct ktrace *i_rwtrace; /* inode read/write trace */
+- struct ktrace *i_strat_trace; /* inode strat_write trace */
++#endif
++#ifdef XFS_ILOCK_TRACE
+ struct ktrace *i_lock_trace; /* inode lock/unlock trace */
++#endif
++#ifdef XFS_DIR2_TRACE
+ struct ktrace *i_dir_trace; /* inode directory trace */
+-#endif /* DEBUG */
++#endif
+ } xfs_inode_t;
+
+ #endif /* __KERNEL__ */
+@@ -536,12 +553,6 @@
+ extern struct kmem_zone *xfs_ili_zone;
+ extern struct vnodeops xfs_vnodeops;
+
+-#ifdef XFS_ILOCK_TRACE
+-#define XFS_ILOCK_KTRACE_SIZE 32
+-void xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags,
+- inst_t *ra);
+-#endif
+-
+ #endif /* __KERNEL__ */
+
+ #endif /* __XFS_INODE_H__ */
+diff -urN linux.org/fs/xfs/xfs_iocore.c linux/fs/xfs/xfs_iocore.c
+--- linux.org/fs/xfs/xfs_iocore.c 2003-12-31 05:48:05.000000000 +0100
++++ linux/fs/xfs/xfs_iocore.c 2004-01-02 04:21:44.000000000 +0100
+@@ -61,6 +61,7 @@
+ #include "xfs_rw.h"
+ #include "xfs_quota.h"
+ #include "xfs_trans_space.h"
++#include "xfs_iomap.h"
+
+
+ STATIC xfs_fsize_t
+diff -urN linux.org/fs/xfs/xfs_iomap.h linux/fs/xfs/xfs_iomap.h
+--- linux.org/fs/xfs/xfs_iomap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/xfs/xfs_iomap.h 2004-01-02 04:21:44.000000000 +0100
+@@ -0,0 +1,107 @@
++/*
++ * Copyright (c) 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_IOMAP_H__
++#define __XFS_IOMAP_H__
++
++#define IOMAP_DADDR_NULL ((xfs_daddr_t) (-1LL))
++
++
++typedef enum { /* iomap_flags values */
++ IOMAP_EOF = 0x01, /* mapping contains EOF */
++ IOMAP_HOLE = 0x02, /* mapping covers a hole */
++ IOMAP_DELAY = 0x04, /* mapping covers delalloc region */
++ IOMAP_UNWRITTEN = 0x20, /* mapping covers allocated */
++ /* but uninitialized file data */
++ IOMAP_NEW = 0x40 /* just allocate */
++} iomap_flags_t;
++
++typedef enum {
++ /* base extent manipulation calls */
++ BMAPI_READ = (1 << 0), /* read extents */
++ BMAPI_WRITE = (1 << 1), /* create extents */
++ BMAPI_ALLOCATE = (1 << 2), /* delayed allocate to real extents */
++ BMAPI_UNWRITTEN = (1 << 3), /* unwritten extents to real extents */
++ /* modifiers */
++ BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */
++ BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */
++ BMAPI_MMAP = (1 << 6), /* allocate for mmap write */
++ BMAPI_SYNC = (1 << 7), /* sync write */
++ BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */
++ BMAPI_DEVICE = (1 << 9), /* we only want to know the device */
++} bmapi_flags_t;
++
++
++/*
++ * xfs_iomap_t: File system I/O map
++ *
++ * The iomap_bn, iomap_offset and iomap_length fields are expressed in disk blocks.
++ * The iomap_length field specifies the size of the underlying backing store
++ * for the particular mapping.
++ *
++ * The iomap_bsize, iomap_size and iomap_delta fields are in bytes and indicate
++ * the size of the mapping, the number of bytes that are valid to access
++ * (read or write), and the offset into the mapping, given the offset
++ * supplied to the file I/O map routine. iomap_delta is the offset of the
++ * desired data from the beginning of the mapping.
++ *
++ * When a request is made to read beyond the logical end of the object,
++ * iomap_size may be set to 0, but iomap_offset and iomap_length should be set to
++ * the actual amount of underlying storage that has been allocated, if any.
++ */
++
++typedef struct xfs_iomap {
++ xfs_daddr_t iomap_bn;
++ xfs_buftarg_t *iomap_target;
++ loff_t iomap_offset;
++ size_t iomap_delta;
++ size_t iomap_bsize;
++ iomap_flags_t iomap_flags;
++} xfs_iomap_t;
++
++struct xfs_iocore;
++struct xfs_inode;
++struct xfs_bmbt_irec;
++
++extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
++ struct xfs_iomap *, int *);
++extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t,
++ int, struct xfs_bmbt_irec *, int *, int);
++extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t, int,
++ struct xfs_bmbt_irec *, int *);
++extern int xfs_iomap_write_allocate(struct xfs_inode *,
++ struct xfs_bmbt_irec *, int *);
++extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t);
++
++#endif /* __XFS_IOMAP_H__*/
+diff -urN linux.org/fs/xfs/xfs_itable.c linux/fs/xfs/xfs_itable.c
+--- linux.org/fs/xfs/xfs_itable.c 2003-12-31 05:46:26.000000000 +0100
++++ linux/fs/xfs/xfs_itable.c 2004-01-02 04:21:44.000000000 +0100
+@@ -65,7 +65,10 @@
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_ino_t ino, /* inode number to get data for */
+ void *buffer, /* buffer to place output in */
++ int ubsize, /* size of buffer */
++ void *private_data, /* my private data */
+ xfs_daddr_t bno, /* starting bno of inode cluster */
++ int *ubused, /* bytes used by me */
+ void *dibuff, /* on-disk inode buffer */
+ int *stat) /* BULKSTAT_RV_... */
+ {
+@@ -86,6 +89,10 @@
+ *stat = BULKSTAT_RV_NOTHING;
+ return XFS_ERROR(EINVAL);
+ }
++ if (ubsize < sizeof(*buf)) {
++ *stat = BULKSTAT_RV_NOTHING;
++ return XFS_ERROR(ENOMEM);
++ }
+
+ if (dip == NULL) {
+ /* We're not being passed a pointer to a dinode. This happens
+@@ -218,6 +225,8 @@
+ }
+
+ *stat = BULKSTAT_RV_DIDONE;
++ if (ubused)
++ *ubused = sizeof(*buf);
+ return 0;
+ }
+
+@@ -231,6 +240,7 @@
+ xfs_ino_t *lastinop, /* last inode returned */
+ int *ubcountp, /* size of buffer/count returned */
+ bulkstat_one_pf formatter, /* func that'd fill a single buf */
++ void *private_data,/* private data for formatter */
+ size_t statstruct_size, /* sizeof struct filling */
+ xfs_caddr_t ubuffer, /* buffer with inode stats */
+ int flags, /* defined in xfs_itable.h */
+@@ -265,8 +275,10 @@
+ int rval; /* return value error code */
+ int tmp; /* result value from btree calls */
+ int ubcount; /* size of user's buffer */
+- int ubleft; /* spaces left in user's buffer */
++ int ubleft; /* bytes left in user's buffer */
+ xfs_caddr_t ubufp; /* current pointer into user's buffer */
++ int ubelem; /* spaces used in user's buffer */
++ int ubused; /* bytes used by formatter */
+ xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */
+ xfs_dinode_t *dip; /* ptr into bp for specific inode */
+ xfs_inode_t *ip; /* ptr to in-core inode struct */
+@@ -284,8 +296,9 @@
+ *ubcountp = 0;
+ return 0;
+ }
+- ubcount = ubleft = *ubcountp;
+- *ubcountp = 0;
++ ubcount = *ubcountp; /* statstruct's */
++ ubleft = ubcount * statstruct_size; /* bytes */
++ *ubcountp = ubelem = 0;
+ *done = 0;
+ fmterror = 0;
+ ubufp = ubuffer;
+@@ -317,7 +330,7 @@
+ * inode returned; 0 means start of the allocation group.
+ */
+ rval = 0;
+- while (ubleft > 0 && agno < mp->m_sb.sb_agcount) {
++ while ((ubleft/statstruct_size) > 0 && agno < mp->m_sb.sb_agcount) {
+ bp = NULL;
+ down_read(&mp->m_peraglock);
+ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
+@@ -402,7 +415,7 @@
+ * Loop through inode btree records in this ag,
+ * until we run out of inodes or space in the buffer.
+ */
+- while (irbp < irbufend && icount < ubcount) {
++ while (irbp < irbufend && icount < (ubleft/statstruct_size)) {
+ /*
+ * Loop as long as we're unable to read the
+ * inode btree.
+@@ -453,7 +466,8 @@
+ * Now format all the good inodes into the user's buffer.
+ */
+ irbufend = irbp;
+- for (irbp = irbuf; irbp < irbufend && ubleft > 0; irbp++) {
++ for (irbp = irbuf;
++ irbp < irbufend && (ubleft/statstruct_size) > 0; irbp++) {
+ /*
+ * Read-ahead the next chunk's worth of inodes.
+ */
+@@ -561,14 +575,19 @@
+ * Get the inode and fill in a single buffer.
+ * BULKSTAT_FG_QUICK uses dip to fill it in.
+ * BULKSTAT_FG_IGET uses igets.
+- * See: xfs_bulkstat_one & dm_bulkstat_one.
++ * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
+ * This is also used to count inodes/blks, etc
+ * in xfs_qm_quotacheck.
+ */
+- error = formatter(mp, tp, ino, ubufp, bno, dip,
+- &fmterror);
+- if (fmterror == BULKSTAT_RV_NOTHING)
++ ubused = statstruct_size;
++ error = formatter(mp, tp, ino, ubufp,
++ ubleft, private_data,
++ bno, &ubused, dip, &fmterror);
++ if (fmterror == BULKSTAT_RV_NOTHING) {
++ if (error == ENOMEM)
++ ubleft = 0;
+ continue;
++ }
+ if (fmterror == BULKSTAT_RV_GIVEUP) {
+ ubleft = 0;
+ ASSERT(error);
+@@ -576,8 +595,9 @@
+ break;
+ }
+ if (ubufp)
+- ubufp += statstruct_size;
+- ubleft--;
++ ubufp += ubused;
++ ubleft -= ubused;
++ ubelem++;
+ lastino = ino;
+ }
+ }
+@@ -605,7 +625,7 @@
+ if (ubuffer)
+ unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS));
+ #endif
+- *ubcountp = ubcount - ubleft;
++ *ubcountp = ubelem;
+ if (agno >= mp->m_sb.sb_agcount) {
+ /*
+ * If we ran out of filesystem, mark lastino as off
+@@ -647,7 +667,8 @@
+ */
+
+ ino = (xfs_ino_t)*lastinop;
+- error = xfs_bulkstat_one(mp, NULL, ino, &bstat, 0, 0, &res);
++ error = xfs_bulkstat_one(mp, NULL, ino, &bstat, sizeof(bstat),
++ NULL, 0, NULL, NULL, &res);
+ if (error) {
+ /*
+ * Special case way failed, do it the "long" way
+@@ -656,6 +677,7 @@
+ (*lastinop)--;
+ count = 1;
+ if (xfs_bulkstat(mp, NULL, lastinop, &count, xfs_bulkstat_one,
++ NULL,
+ sizeof(bstat), buffer, BULKSTAT_FG_IGET, done))
+ return error;
+ if (count == 0 || (xfs_ino_t)*lastinop != ino)
+diff -urN linux.org/fs/xfs/xfs_itable.h linux/fs/xfs/xfs_itable.h
+--- linux.org/fs/xfs/xfs_itable.h 2003-12-31 05:48:36.000000000 +0100
++++ linux/fs/xfs/xfs_itable.h 2004-01-02 04:21:42.000000000 +0100
+@@ -36,15 +36,19 @@
+ * xfs_bulkstat() is used to fill in xfs_bstat structures as well as dm_stat
+ * structures (by the dmi library). This is a pointer to a formatter function
+ * that will iget the inode and fill in the appropriate structure.
+- * see xfs_bulkstat_one() and dm_bulkstat_one() in dmi_xfs.c
++ * see xfs_bulkstat_one() and xfs_dm_bulkstat_one() in dmapi_xfs.c
+ */
+ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp,
+ struct xfs_trans *tp,
+ xfs_ino_t ino,
+ void *buffer,
++ int ubsize,
++ void *private_data,
+ xfs_daddr_t bno,
++ int *ubused,
+ void *dip,
+ int *stat);
++
+ /*
+ * Values for stat return value.
+ */
+@@ -69,6 +73,7 @@
+ xfs_ino_t *lastino, /* last inode returned */
+ int *count, /* size of buffer/count returned */
+ bulkstat_one_pf formatter, /* func that'd fill a single buf */
++ void *private_data, /* private data for formatter */
+ size_t statstruct_size,/* sizeof struct that we're filling */
+ xfs_caddr_t ubuffer, /* buffer with inode stats */
+ int flags, /* flag to control access method */
+@@ -87,7 +92,10 @@
+ xfs_trans_t *tp,
+ xfs_ino_t ino,
+ void *buffer,
++ int ubsize,
++ void *private_data,
+ xfs_daddr_t bno,
++ int *ubused,
+ void *dibuff,
+ int *stat);
+
+diff -urN linux.org/fs/xfs/xfs_log.c linux/fs/xfs/xfs_log.c
+--- linux.org/fs/xfs/xfs_log.c 2003-12-31 05:48:47.000000000 +0100
++++ linux/fs/xfs/xfs_log.c 2004-01-02 04:21:42.000000000 +0100
+@@ -159,11 +159,15 @@
+ #endif
+
+ #if defined(XFS_LOG_TRACE)
++
+ void
+ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
+ {
+- if (! log->l_grant_trace)
+- log->l_grant_trace = ktrace_alloc(1024, KM_SLEEP);
++ if (! log->l_grant_trace) {
++ log->l_grant_trace = ktrace_alloc(1024, KM_NOSLEEP);
++ if (! log->l_grant_trace)
++ return;
++ }
+
+ ktrace_enter(log->l_grant_trace,
+ (void *)tic,
+@@ -185,31 +189,6 @@
+ }
+
+ void
+-xlog_trace_tic(xlog_t *log, xlog_ticket_t *tic)
+-{
+- if (! log->l_trace)
+- log->l_trace = ktrace_alloc(256, KM_SLEEP);
+-
+- ktrace_enter(log->l_trace,
+- (void *)tic,
+- (void *)((unsigned long)tic->t_curr_res),
+- (void *)((unsigned long)tic->t_unit_res),
+- (void *)((unsigned long)tic->t_ocnt),
+- (void *)((unsigned long)tic->t_cnt),
+- (void *)((unsigned long)tic->t_flags),
+- (void *)((unsigned long)7),
+- (void *)((unsigned long)8),
+- (void *)((unsigned long)9),
+- (void *)((unsigned long)10),
+- (void *)((unsigned long)11),
+- (void *)((unsigned long)12),
+- (void *)((unsigned long)13),
+- (void *)((unsigned long)14),
+- (void *)((unsigned long)15),
+- (void *)((unsigned long)16));
+-}
+-
+-void
+ xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
+ {
+ pid_t pid;
+@@ -1044,7 +1023,6 @@
+ *
+ * If the filesystem blocksize is too large, we may need to choose a
+ * larger size since the directory code currently logs entire blocks.
+- * XXXmiken XXXcurtis
+ */
+
+ STATIC void
+@@ -1059,7 +1037,7 @@
+ * When logbufs == 0, someone has disabled the log from the FSTAB
+ * file. This is not a documented feature. We need to set xlog_debug
+ * to zero (this deactivates the log) and set xlog_target to the
+- * appropriate dev_t. Only one filesystem may be affected as such
++ * appropriate device. Only one filesystem may be affected as such
+ * since this is just a performance hack to test what we might be able
+ * to get if the log were not present.
+ */
+@@ -1078,7 +1056,7 @@
+ if (xfs_physmem <= btoc(128*1024*1024)) {
+ log->l_iclog_bufs = XLOG_MIN_ICLOGS;
+ } else if (xfs_physmem <= btoc(400*1024*1024)) {
+- log->l_iclog_bufs = XLOG_MED_ICLOGS;;
++ log->l_iclog_bufs = XLOG_MED_ICLOGS;
+ } else {
+ /* 256K with 32K bufs */
+ log->l_iclog_bufs = XLOG_MAX_ICLOGS;
+@@ -1087,9 +1065,9 @@
+ log->l_iclog_bufs = mp->m_logbufs;
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- /* We are reactivating a filesystem after it was active */
++ /* We are reactivating a filesystem after it was inactive */
+ if (log->l_targ == xlog_target) {
+- xlog_target = 1; /* XXX(hch): WTF? */
++ xlog_target = NULL;
+ xlog_debug = 1;
+ }
+ #endif
+@@ -1578,7 +1556,7 @@
+ sv_destroy(&iclog->ic_forcesema);
+ sv_destroy(&iclog->ic_writesema);
+ xfs_buf_free(iclog->ic_bp);
+-#ifdef DEBUG
++#ifdef XFS_LOG_TRACE
+ if (iclog->ic_trace != NULL) {
+ ktrace_free(iclog->ic_trace);
+ }
+@@ -1609,7 +1587,7 @@
+ }
+ }
+ xfs_buf_free(log->l_xbuf);
+-#ifdef DEBUG
++#ifdef XFS_LOG_TRACE
+ if (log->l_trace != NULL) {
+ ktrace_free(log->l_trace);
+ }
+diff -urN linux.org/fs/xfs/xfs_log.h linux/fs/xfs/xfs_log.h
+--- linux.org/fs/xfs/xfs_log.h 2003-12-31 05:48:56.000000000 +0100
++++ linux/fs/xfs/xfs_log.h 2004-01-02 04:21:42.000000000 +0100
+@@ -53,8 +53,8 @@
+ * endian issues in treating two 32 bit numbers as one 64 bit number
+ */
+ static
+-#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
+-__attribute__((unused)) /* gcc 2.95 miscompiles this when inlined */
++#if defined(__GNUC__) && (__GNUC__ == 2) && ( (__GNUC_MINOR__ == 95) || (__GNUC_MINOR__ == 96))
++__attribute__((unused)) /* gcc 2.95, 2.96 miscompile this when inlined */
+ #else
+ __inline__
+ #endif
+diff -urN linux.org/fs/xfs/xfs_log_priv.h linux/fs/xfs/xfs_log_priv.h
+--- linux.org/fs/xfs/xfs_log_priv.h 2003-12-31 05:46:29.000000000 +0100
++++ linux/fs/xfs/xfs_log_priv.h 2004-01-02 04:21:42.000000000 +0100
+@@ -32,14 +32,6 @@
+ #ifndef __XFS_LOG_PRIV_H__
+ #define __XFS_LOG_PRIV_H__
+
+-#if defined(XFS_ALL_TRACE)
+-#define XFS_LOG_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_LOG_TRACE
+-#endif
+-
+ struct xfs_buf;
+ struct ktrace;
+ struct log;
+@@ -109,6 +101,7 @@
+
+
+ #ifdef __KERNEL__
++
+ /*
+ * get client id from packed copy.
+ *
+@@ -434,7 +427,7 @@
+ struct log *ic_log;
+ xfs_log_callback_t *ic_callback;
+ xfs_log_callback_t **ic_callback_tail;
+-#ifdef DEBUG
++#ifdef XFS_LOG_TRACE
+ struct ktrace *ic_trace;
+ #endif
+ int ic_size;
+@@ -531,7 +524,7 @@
+ int l_grant_write_bytes;
+
+ /* The following fields don't need locking */
+-#ifdef DEBUG
++#ifdef XFS_LOG_TRACE
+ struct ktrace *l_trace;
+ struct ktrace *l_grant_trace;
+ #endif
+diff -urN linux.org/fs/xfs/xfs_mount.c linux/fs/xfs/xfs_mount.c
+--- linux.org/fs/xfs/xfs_mount.c 2003-12-31 05:46:55.000000000 +0100
++++ linux/fs/xfs/xfs_mount.c 2004-01-02 04:21:42.000000000 +0100
+@@ -903,7 +903,7 @@
+ * File systems that don't support user level file handles (i.e.
+ * all of them except for XFS) will leave vfs_altfsid as NULL.
+ */
+- vfsp->vfs_altfsid = (fsid_t *)mp->m_fixedfsid;
++ vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
+ mp->m_dmevmask = 0; /* not persistent; set after each mount */
+
+ /*
+diff -urN linux.org/fs/xfs/xfs_qmops.c linux/fs/xfs/xfs_qmops.c
+--- linux.org/fs/xfs/xfs_qmops.c 2003-12-31 05:46:56.000000000 +0100
++++ linux/fs/xfs/xfs_qmops.c 2004-01-02 04:21:43.000000000 +0100
+@@ -44,7 +44,6 @@
+ #include "xfs_mount.h"
+
+
+-#ifndef CONFIG_XFS_QUOTA
+ STATIC struct xfs_dquot *
+ xfs_dqvopchown_default(
+ struct xfs_trans *tp,
+@@ -70,4 +69,3 @@
+ .xfs_dqvopchown = xfs_dqvopchown_default,
+ .xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr,
+ };
+-#endif /* CONFIG_XFS_QUOTA */
+diff -urN linux.org/fs/xfs/xfs_refcache.c linux/fs/xfs/xfs_refcache.c
+--- linux.org/fs/xfs/xfs_refcache.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/xfs/xfs_refcache.c 2004-01-02 04:21:43.000000000 +0100
+@@ -0,0 +1,439 @@
++/*
++ * 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_macros.h"
++#include "xfs_types.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_dmapi.h"
++#include "xfs_mount.h"
++#include "xfs_alloc_btree.h"
++#include "xfs_bmap_btree.h"
++#include "xfs_ialloc_btree.h"
++#include "xfs_itable.h"
++#include "xfs_btree.h"
++#include "xfs_alloc.h"
++#include "xfs_ialloc.h"
++#include "xfs_attr.h"
++#include "xfs_attr_sf.h"
++#include "xfs_dir_sf.h"
++#include "xfs_dir2_sf.h"
++#include "xfs_dinode.h"
++#include "xfs_inode_item.h"
++#include "xfs_inode.h"
++#include "xfs_bmap.h"
++#include "xfs_error.h"
++#include "xfs_buf_item.h"
++#include "xfs_refcache.h"
++
++STATIC spinlock_t xfs_refcache_lock = SPIN_LOCK_UNLOCKED;
++STATIC xfs_inode_t **xfs_refcache;
++STATIC int xfs_refcache_index;
++STATIC int xfs_refcache_busy;
++STATIC int xfs_refcache_count;
++
++/*
++ * Insert the given inode into the reference cache.
++ */
++void
++xfs_refcache_insert(
++ xfs_inode_t *ip)
++{
++ vnode_t *vp;
++ xfs_inode_t *release_ip;
++ xfs_inode_t **refcache;
++
++ ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE));
++
++ /*
++ * If an unmount is busy blowing entries out of the cache,
++ * then don't bother.
++ */
++ if (xfs_refcache_busy) {
++ return;
++ }
++
++ /*
++ * If we tuned the refcache down to zero, don't do anything.
++ */
++ if (!xfs_refcache_size) {
++ return;
++ }
++
++ /*
++ * The inode is already in the refcache, so don't bother
++ * with it.
++ */
++ if (ip->i_refcache != NULL) {
++ return;
++ }
++
++ vp = XFS_ITOV(ip);
++ /* ASSERT(vp->v_count > 0); */
++ VN_HOLD(vp);
++
++ /*
++ * We allocate the reference cache on use so that we don't
++ * waste the memory on systems not being used as NFS servers.
++ */
++ if (xfs_refcache == NULL) {
++ refcache = (xfs_inode_t **)kmem_zalloc(XFS_REFCACHE_SIZE_MAX *
++ sizeof(xfs_inode_t *),
++ KM_SLEEP);
++ } else {
++ refcache = NULL;
++ }
++
++ spin_lock(&xfs_refcache_lock);
++
++ /*
++ * If we allocated memory for the refcache above and it still
++ * needs it, then use the memory we allocated. Otherwise we'll
++ * free the memory below.
++ */
++ if (refcache != NULL) {
++ if (xfs_refcache == NULL) {
++ xfs_refcache = refcache;
++ refcache = NULL;
++ }
++ }
++
++ /*
++ * If an unmount is busy clearing out the cache, don't add new
++ * entries to it.
++ */
++ if (xfs_refcache_busy) {
++ spin_unlock(&xfs_refcache_lock);
++ VN_RELE(vp);
++ /*
++ * If we allocated memory for the refcache above but someone
++ * else beat us to using it, then free the memory now.
++ */
++ if (refcache != NULL) {
++ kmem_free(refcache,
++ XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
++ }
++ return;
++ }
++ release_ip = xfs_refcache[xfs_refcache_index];
++ if (release_ip != NULL) {
++ release_ip->i_refcache = NULL;
++ xfs_refcache_count--;
++ ASSERT(xfs_refcache_count >= 0);
++ }
++ xfs_refcache[xfs_refcache_index] = ip;
++ ASSERT(ip->i_refcache == NULL);
++ ip->i_refcache = &(xfs_refcache[xfs_refcache_index]);
++ xfs_refcache_count++;
++ ASSERT(xfs_refcache_count <= xfs_refcache_size);
++ xfs_refcache_index++;
++ if (xfs_refcache_index == xfs_refcache_size) {
++ xfs_refcache_index = 0;
++ }
++ spin_unlock(&xfs_refcache_lock);
++
++ /*
++ * Save the pointer to the inode to be released so that we can
++ * VN_RELE it once we've dropped our inode locks in xfs_rwunlock().
++ * The pointer may be NULL, but that's OK.
++ */
++ ip->i_release = release_ip;
++
++ /*
++ * If we allocated memory for the refcache above but someone
++ * else beat us to using it, then free the memory now.
++ */
++ if (refcache != NULL) {
++ kmem_free(refcache,
++ XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
++ }
++}
++
++
++/*
++ * If the given inode is in the reference cache, purge its entry and
++ * release the reference on the vnode.
++ */
++void
++xfs_refcache_purge_ip(
++ xfs_inode_t *ip)
++{
++ vnode_t *vp;
++ int error;
++
++ /*
++ * If we're not pointing to our entry in the cache, then
++ * we must not be in the cache.
++ */
++ if (ip->i_refcache == NULL) {
++ return;
++ }
++
++ spin_lock(&xfs_refcache_lock);
++ if (ip->i_refcache == NULL) {
++ spin_unlock(&xfs_refcache_lock);
++ return;
++ }
++
++ /*
++ * Clear both our pointer to the cache entry and its pointer
++ * back to us.
++ */
++ ASSERT(*(ip->i_refcache) == ip);
++ *(ip->i_refcache) = NULL;
++ ip->i_refcache = NULL;
++ xfs_refcache_count--;
++ ASSERT(xfs_refcache_count >= 0);
++ spin_unlock(&xfs_refcache_lock);
++
++ vp = XFS_ITOV(ip);
++ /* ASSERT(vp->v_count > 1); */
++ VOP_RELEASE(vp, error);
++ VN_RELE(vp);
++}
++
++
++/*
++ * This is called from the XFS unmount code to purge all entries for the
++ * given mount from the cache. It uses the refcache busy counter to
++ * make sure that new entries are not added to the cache as we purge them.
++ */
++void
++xfs_refcache_purge_mp(
++ xfs_mount_t *mp)
++{
++ vnode_t *vp;
++ int error, i;
++ xfs_inode_t *ip;
++
++ if (xfs_refcache == NULL) {
++ return;
++ }
++
++ spin_lock(&xfs_refcache_lock);
++ /*
++ * Bumping the busy counter keeps new entries from being added
++ * to the cache. We use a counter since multiple unmounts could
++ * be in here simultaneously.
++ */
++ xfs_refcache_busy++;
++
++ for (i = 0; i < xfs_refcache_size; i++) {
++ ip = xfs_refcache[i];
++ if ((ip != NULL) && (ip->i_mount == mp)) {
++ xfs_refcache[i] = NULL;
++ ip->i_refcache = NULL;
++ xfs_refcache_count--;
++ ASSERT(xfs_refcache_count >= 0);
++ spin_unlock(&xfs_refcache_lock);
++ vp = XFS_ITOV(ip);
++ VOP_RELEASE(vp, error);
++ VN_RELE(vp);
++ spin_lock(&xfs_refcache_lock);
++ }
++ }
++
++ xfs_refcache_busy--;
++ ASSERT(xfs_refcache_busy >= 0);
++ spin_unlock(&xfs_refcache_lock);
++}
++
++
++/*
++ * This is called from the XFS sync code to ensure that the refcache
++ * is emptied out over time. We purge a small number of entries with
++ * each call.
++ */
++void
++xfs_refcache_purge_some(xfs_mount_t *mp)
++{
++ int error, i;
++ xfs_inode_t *ip;
++ int iplist_index;
++ xfs_inode_t **iplist;
++
++ if ((xfs_refcache == NULL) || (xfs_refcache_count == 0)) {
++ return;
++ }
++
++ iplist_index = 0;
++ iplist = (xfs_inode_t **)kmem_zalloc(xfs_refcache_purge_count *
++ sizeof(xfs_inode_t *), KM_SLEEP);
++
++ spin_lock(&xfs_refcache_lock);
++
++ /*
++ * Store any inodes we find in the next several entries
++ * into the iplist array to be released after dropping
++ * the spinlock. We always start looking from the currently
++ * oldest place in the cache. We move the refcache index
++ * forward as we go so that we are sure to eventually clear
++ * out the entire cache when the system goes idle.
++ */
++ for (i = 0; i < xfs_refcache_purge_count; i++) {
++ ip = xfs_refcache[xfs_refcache_index];
++ if (ip != NULL) {
++ xfs_refcache[xfs_refcache_index] = NULL;
++ ip->i_refcache = NULL;
++ xfs_refcache_count--;
++ ASSERT(xfs_refcache_count >= 0);
++ iplist[iplist_index] = ip;
++ iplist_index++;
++ }
++ xfs_refcache_index++;
++ if (xfs_refcache_index == xfs_refcache_size) {
++ xfs_refcache_index = 0;
++ }
++ }
++
++ spin_unlock(&xfs_refcache_lock);
++
++ /*
++ * Now drop the inodes we collected.
++ */
++ for (i = 0; i < iplist_index; i++) {
++ VOP_RELEASE(XFS_ITOV(iplist[i]), error);
++ VN_RELE(XFS_ITOV(iplist[i]));
++ }
++
++ kmem_free(iplist, xfs_refcache_purge_count *
++ sizeof(xfs_inode_t *));
++}
++
++/*
++ * This is called when the refcache is dynamically resized
++ * via a sysctl.
++ *
++ * If the new size is smaller than the old size, purge all
++ * entries in slots greater than the new size, and move
++ * the index if necessary.
++ *
++ * If the refcache hasn't even been allocated yet, or the
++ * new size is larger than the old size, just set the value
++ * of xfs_refcache_size.
++ */
++
++void
++xfs_refcache_resize(int xfs_refcache_new_size)
++{
++ int i;
++ xfs_inode_t *ip;
++ int iplist_index = 0;
++ xfs_inode_t **iplist;
++ int error;
++
++ /*
++ * If the new size is smaller than the current size,
++ * purge entries to create smaller cache, and
++ * reposition index if necessary.
++ * Don't bother if no refcache yet.
++ */
++ if (xfs_refcache && (xfs_refcache_new_size < xfs_refcache_size)) {
++
++ iplist = (xfs_inode_t **)kmem_zalloc(XFS_REFCACHE_SIZE_MAX *
++ sizeof(xfs_inode_t *), KM_SLEEP);
++
++ spin_lock(&xfs_refcache_lock);
++
++ for (i = xfs_refcache_new_size; i < xfs_refcache_size; i++) {
++ ip = xfs_refcache[i];
++ if (ip != NULL) {
++ xfs_refcache[i] = NULL;
++ ip->i_refcache = NULL;
++ xfs_refcache_count--;
++ ASSERT(xfs_refcache_count >= 0);
++ iplist[iplist_index] = ip;
++ iplist_index++;
++ }
++ }
++
++ xfs_refcache_size = xfs_refcache_new_size;
++
++ /*
++ * Move index to beginning of cache if it's now past the end
++ */
++ if (xfs_refcache_index >= xfs_refcache_new_size)
++ xfs_refcache_index = 0;
++
++ spin_unlock(&xfs_refcache_lock);
++
++ /*
++ * Now drop the inodes we collected.
++ */
++ for (i = 0; i < iplist_index; i++) {
++ VOP_RELEASE(XFS_ITOV(iplist[i]), error);
++ VN_RELE(XFS_ITOV(iplist[i]));
++ }
++
++ kmem_free(iplist, XFS_REFCACHE_SIZE_MAX *
++ sizeof(xfs_inode_t *));
++ } else {
++ spin_lock(&xfs_refcache_lock);
++ xfs_refcache_size = xfs_refcache_new_size;
++ spin_unlock(&xfs_refcache_lock);
++ }
++}
++
++void
++xfs_refcache_iunlock(
++ xfs_inode_t *ip,
++ uint lock_flags)
++{
++ xfs_inode_t *release_ip;
++ int error;
++
++ release_ip = ip->i_release;
++ ip->i_release = NULL;
++
++ xfs_iunlock(ip, lock_flags);
++
++ if (release_ip != NULL) {
++ VOP_RELEASE(XFS_ITOV(release_ip), error);
++ VN_RELE(XFS_ITOV(release_ip));
++ }
++}
++
++void
++xfs_refcache_destroy(void)
++{
++ if (xfs_refcache) {
++ kmem_free(xfs_refcache,
++ XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
++ xfs_refcache = NULL;
++ }
++}
+diff -urN linux.org/fs/xfs/xfs_refcache.h linux/fs/xfs/xfs_refcache.h
+--- linux.org/fs/xfs/xfs_refcache.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/xfs/xfs_refcache.h 2004-01-02 04:21:43.000000000 +0100
+@@ -0,0 +1,66 @@
++/*
++ * 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_REFCACHE_H__
++#define __XFS_REFCACHE_H__
++
++#ifdef HAVE_REFCACHE
++/*
++ * Maximum size (in inodes) for the NFS reference cache
++ */
++#define XFS_REFCACHE_SIZE_MAX 512
++
++struct xfs_inode;
++struct xfs_mount;
++
++extern void xfs_refcache_insert(struct xfs_inode *);
++extern void xfs_refcache_purge_ip(struct xfs_inode *);
++extern void xfs_refcache_purge_mp(struct xfs_mount *);
++extern void xfs_refcache_purge_some(struct xfs_mount *);
++extern void xfs_refcache_resize(int);
++extern void xfs_refcache_destroy(void);
++
++extern void xfs_refcache_iunlock(struct xfs_inode *, uint);
++
++#else
++
++#define xfs_refcache_insert(ip) do { } while (0)
++#define xfs_refcache_purge_ip(ip) do { } while (0)
++#define xfs_refcache_purge_mp(mp) do { } while (0)
++#define xfs_refcache_purge_some(mp) do { } while (0)
++#define xfs_refcache_resize(size) do { } while (0)
++#define xfs_refcache_destroy() do { } while (0)
++
++#define xfs_refcache_iunlock(ip, flags) xfs_iunlock(ip, flags)
++
++#endif
++
++#endif /* __XFS_REFCACHE_H__ */
+diff -urN linux.org/fs/xfs/xfs_rename.c linux/fs/xfs/xfs_rename.c
+--- linux.org/fs/xfs/xfs_rename.c 2003-12-31 05:47:23.000000000 +0100
++++ linux/fs/xfs/xfs_rename.c 2004-01-02 04:21:43.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -51,7 +51,7 @@
+ #include "xfs_bmap.h"
+ #include "xfs_error.h"
+ #include "xfs_quota.h"
+-#include "xfs_rw.h"
++#include "xfs_refcache.h"
+ #include "xfs_utils.h"
+ #include "xfs_trans_space.h"
+ #include "xfs_da_btree.h"
+@@ -343,8 +343,7 @@
+ src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
+
+ /*
+- * Drop the locks on our inodes so that we can do the ancestor
+- * check if necessary and start the transaction.
++ * Drop the locks on our inodes so that we can start the transaction.
+ */
+ xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+
+@@ -486,7 +485,7 @@
+ error = xfs_droplink(tp, target_ip);
+ if (error) {
+ rename_which_error_return = __LINE__;
+- goto abort_return;;
++ goto abort_return;
+ }
+ target_ip_dropped = 1;
+
+@@ -627,6 +626,7 @@
+ */
+ error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
+ if (target_ip != NULL) {
++ xfs_refcache_purge_ip(target_ip);
+ IRELE(target_ip);
+ }
+ /*
+diff -urN linux.org/fs/xfs/xfs_rw.c linux/fs/xfs/xfs_rw.c
+--- linux.org/fs/xfs/xfs_rw.c 2003-12-31 05:48:40.000000000 +0100
++++ linux/fs/xfs/xfs_rw.c 2004-01-02 04:21:43.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -149,6 +149,9 @@
+ xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
+ "Corruption of in-memory data detected. Shutting down filesystem: %s",
+ mp->m_fsname);
++ if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
++ xfs_stack_trace();
++ }
+ } else if (!(flags & XFS_FORCE_UMOUNT)) {
+ if (logerror) {
+ xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
+@@ -351,54 +354,3 @@
+ }
+ return (error);
+ }
+-
+-/*
+- * xfs_inval_cached_pages()
+- * This routine is responsible for keeping direct I/O and buffered I/O
+- * somewhat coherent. From here we make sure that we're at least
+- * temporarily holding the inode I/O lock exclusively and then call
+- * the page cache to flush and invalidate any cached pages. If there
+- * are no cached pages this routine will be very quick.
+- */
+-void
+-xfs_inval_cached_pages(
+- vnode_t *vp,
+- xfs_iocore_t *io,
+- xfs_off_t offset,
+- int write,
+- int relock)
+-{
+- xfs_mount_t *mp;
+-
+- if (!VN_CACHED(vp)) {
+- return;
+- }
+-
+- mp = io->io_mount;
+-
+- /*
+- * We need to get the I/O lock exclusively in order
+- * to safely invalidate pages and mappings.
+- */
+- if (relock) {
+- XFS_IUNLOCK(mp, io, XFS_IOLOCK_SHARED);
+- XFS_ILOCK(mp, io, XFS_IOLOCK_EXCL);
+- }
+-
+- /* Writing beyond EOF creates a hole that must be zeroed */
+- if (write && (offset > XFS_SIZE(mp, io))) {
+- xfs_fsize_t isize;
+-
+- XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+- isize = XFS_SIZE(mp, io);
+- if (offset > isize) {
+- xfs_zero_eof(vp, io, offset, isize, offset);
+- }
+- XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+- }
+-
+- VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
+- if (relock) {
+- XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
+- }
+-}
+diff -urN linux.org/fs/xfs/xfs_rw.h linux/fs/xfs/xfs_rw.h
+--- linux.org/fs/xfs/xfs_rw.h 2003-12-31 05:46:29.000000000 +0100
++++ linux/fs/xfs/xfs_rw.h 2004-01-02 04:21:43.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
++ * 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
+@@ -32,16 +32,9 @@
+ #ifndef __XFS_RW_H__
+ #define __XFS_RW_H__
+
+-struct bhv_desc;
+-struct bmapval;
+ struct xfs_buf;
+-struct cred;
+-struct uio;
+-struct vnode;
+ struct xfs_inode;
+-struct xfs_iocore;
+ struct xfs_mount;
+-struct xfs_trans;
+
+ /*
+ * Maximum count of bmaps used by read and write paths.
+@@ -91,44 +84,6 @@
+ XFS_FSB_TO_DADDR((io)->io_mount, (fsb)))
+
+ /*
+- * Defines for the trace mechanisms in xfs_rw.c.
+- */
+-#define XFS_RW_KTRACE_SIZE 64
+-#define XFS_STRAT_KTRACE_SIZE 64
+-#define XFS_STRAT_GTRACE_SIZE 512
+-
+-#define XFS_READ_ENTER 1
+-#define XFS_WRITE_ENTER 2
+-#define XFS_IOMAP_READ_ENTER 3
+-#define XFS_IOMAP_WRITE_ENTER 4
+-#define XFS_IOMAP_READ_MAP 5
+-#define XFS_IOMAP_WRITE_MAP 6
+-#define XFS_IOMAP_WRITE_NOSPACE 7
+-#define XFS_ITRUNC_START 8
+-#define XFS_ITRUNC_FINISH1 9
+-#define XFS_ITRUNC_FINISH2 10
+-#define XFS_CTRUNC1 11
+-#define XFS_CTRUNC2 12
+-#define XFS_CTRUNC3 13
+-#define XFS_CTRUNC4 14
+-#define XFS_CTRUNC5 15
+-#define XFS_CTRUNC6 16
+-#define XFS_BUNMAPI 17
+-#define XFS_INVAL_CACHED 18
+-#define XFS_DIORD_ENTER 19
+-#define XFS_DIOWR_ENTER 20
+-
+-#if defined(XFS_ALL_TRACE)
+-#define XFS_RW_TRACE
+-#define XFS_STRAT_TRACE
+-#endif
+-
+-#if !defined(DEBUG)
+-#undef XFS_RW_TRACE
+-#undef XFS_STRAT_TRACE
+-#endif
+-
+-/*
+ * Prototypes for functions in xfs_rw.c.
+ */
+
+@@ -141,14 +96,6 @@
+ struct xfs_mount *mp,
+ struct xfs_buf *bp);
+
+-void
+-xfs_inval_cached_pages(
+- struct vnode *vp,
+- struct xfs_iocore *io,
+- xfs_off_t offset,
+- int write,
+- int relock);
+-
+ int
+ xfs_bioerror(
+ struct xfs_buf *b);
+diff -urN linux.org/fs/xfs/xfs_trans.c linux/fs/xfs/xfs_trans.c
+--- linux.org/fs/xfs/xfs_trans.c 2003-12-31 05:47:13.000000000 +0100
++++ linux/fs/xfs/xfs_trans.c 2004-01-02 04:21:43.000000000 +0100
+@@ -142,9 +142,9 @@
+ uint type)
+ {
+ xfs_trans_t *tp;
++
+ ASSERT(xfs_trans_zone != NULL);
+ tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
+- tp->t_dqinfo = NULL;
+
+ /*
+ * Initialize the transaction structure.
+diff -urN linux.org/fs/xfs/xfs_vfsops.c linux/fs/xfs/xfs_vfsops.c
+--- linux.org/fs/xfs/xfs_vfsops.c 2003-12-31 05:46:41.000000000 +0100
++++ linux/fs/xfs/xfs_vfsops.c 2004-01-02 04:21:43.000000000 +0100
+@@ -60,6 +60,7 @@
+ #include "xfs_bmap.h"
+ #include "xfs_da_btree.h"
+ #include "xfs_rw.h"
++#include "xfs_refcache.h"
+ #include "xfs_buf_item.h"
+ #include "xfs_extfree_item.h"
+ #include "xfs_quota.h"
+@@ -74,24 +75,11 @@
+ int
+ xfs_init(void)
+ {
+- extern kmem_zone_t *xfs_da_state_zone;
+ extern kmem_zone_t *xfs_bmap_free_item_zone;
+ extern kmem_zone_t *xfs_btree_cur_zone;
+- extern kmem_zone_t *xfs_inode_zone;
+- extern kmem_zone_t *xfs_chashlist_zone;
+ extern kmem_zone_t *xfs_trans_zone;
+ extern kmem_zone_t *xfs_buf_item_zone;
+- extern kmem_zone_t *xfs_efd_zone;
+- extern kmem_zone_t *xfs_efi_zone;
+ extern kmem_zone_t *xfs_dabuf_zone;
+-#ifdef DEBUG_NOT
+- extern ktrace_t *xfs_alloc_trace_buf;
+- extern ktrace_t *xfs_bmap_trace_buf;
+- extern ktrace_t *xfs_bmbt_trace_buf;
+- extern ktrace_t *xfs_dir_trace_buf;
+- extern ktrace_t *xfs_attr_trace_buf;
+- extern ktrace_t *xfs_dir2_trace_buf;
+-#endif /* DEBUG */
+ #ifdef XFS_DABUF_DEBUG
+ extern lock_t xfs_dabuf_global_lock;
+ spinlock_init(&xfs_dabuf_global_lock, "xfsda");
+@@ -132,14 +120,6 @@
+ "xfs_chashlist");
+ _ACL_ZONE_INIT(xfs_acl_zone, "xfs_acl");
+
+-#ifdef CONFIG_XFS_VNODE_TRACING
+- ktrace_init(VNODE_TRACE_SIZE);
+-#else
+-#ifdef DEBUG
+- ktrace_init(64);
+-#endif
+-#endif
+-
+ /*
+ * Allocate global trace buffers.
+ */
+@@ -189,6 +169,7 @@
+
+ xfs_cleanup_procfs();
+ xfs_sysctl_unregister();
++ xfs_refcache_destroy();
+
+ kmem_cache_destroy(xfs_bmap_free_item_zone);
+ kmem_cache_destroy(xfs_btree_cur_zone);
+@@ -203,9 +184,6 @@
+ kmem_cache_destroy(xfs_ili_zone);
+ kmem_cache_destroy(xfs_chashlist_zone);
+ _ACL_ZONE_DESTROY(xfs_acl_zone);
+-#if (defined(DEBUG) || defined(CONFIG_XFS_VNODE_TRACING))
+- ktrace_uninit();
+-#endif
+ }
+
+ /*
+@@ -547,6 +525,12 @@
+ 0 : DM_FLAGS_UNWANTED;
+ }
+
++ /*
++ * First blow any referenced inode from this file system
++ * out of the reference cache, and delete the timer.
++ */
++ xfs_refcache_purge_mp(mp);
++
+ XFS_bflush(mp->m_ddev_targp);
+ error = xfs_unmount_flush(mp, 0);
+ if (error)
+@@ -617,6 +601,7 @@
+ }
+
+ if (*flags & MS_RDONLY) {
++ xfs_refcache_purge_mp(mp);
+ pagebuf_delwri_flush(mp->m_ddev_targp, 0, NULL);
+ xfs_finish_reclaim_all(mp, 0);
+
+@@ -758,7 +743,7 @@
+ STATIC int
+ xfs_statvfs(
+ bhv_desc_t *bdp,
+- struct kstatfs *statp,
++ xfs_statfs_t *statp,
+ vnode_t *vp)
+ {
+ __uint64_t fakeinos;
+@@ -766,7 +751,6 @@
+ xfs_mount_t *mp;
+ xfs_sb_t *sbp;
+ unsigned long s;
+- u64 id;
+
+ mp = XFS_BHVTOM(bdp);
+ sbp = &(mp->m_sb);
+@@ -793,9 +777,8 @@
+ statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
+ XFS_SB_UNLOCK(mp, s);
+
+- id = huge_encode_dev(mp->m_dev);
+- statp->f_fsid.val[0] = (u32)id;
+- statp->f_fsid.val[1] = (u32)(id >> 32);
++ statp->f_fsid.val[0] = mp->m_dev;
++ statp->f_fsid.val[1] = 0;
+ statp->f_namelen = MAXNAMELEN - 1;
+
+ return 0;
+@@ -1489,8 +1472,18 @@
+ }
+
+ /*
++ * If this is the periodic sync, then kick some entries out of
++ * the reference cache. This ensures that idle entries are
++ * eventually kicked out of the cache.
++ */
++ if (flags & SYNC_REFCACHE) {
++ xfs_refcache_purge_some(mp);
++ }
++
++ /*
+ * Now check to see if the log needs a "dummy" transaction.
+ */
++
+ if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
+ xfs_trans_t *tp;
+ xfs_inode_t *ip;
+@@ -1598,8 +1591,9 @@
+ #define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
+ #define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */
+ #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
+-#define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */
+-#define MNTOPT_IKEEP "ikeep" /* free empty inode clusters */
++#define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */
++#define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */
++#define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */
+
+
+ int
+@@ -1614,7 +1608,9 @@
+ int dsunit, dswidth, vol_dsunit, vol_dswidth;
+ int iosize;
+
++#if 0 /* XXX: off by default, until some remaining issues ironed out */
+ args->flags |= XFSMNT_IDELETE; /* default to on */
++#endif
+
+ if (!options)
+ return 0;
+@@ -1722,6 +1718,8 @@
+ args->flags |= XFSMNT_NOLOGFLUSH;
+ } else if (!strcmp(this_char, MNTOPT_IKEEP)) {
+ args->flags &= ~XFSMNT_IDELETE;
++ } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
++ args->flags |= XFSMNT_IDELETE;
+ } else if (!strcmp(this_char, "osyncisdsync")) {
+ /* no-op, this is now the default */
+ printk("XFS: osyncisdsync is now the default, option is deprecated.\n");
+@@ -1784,10 +1782,14 @@
+ char *str;
+ } xfs_info[] = {
+ /* the few simple ones we can get from the mount struct */
++ { XFS_MOUNT_WSYNC, "," MNTOPT_WSYNC },
++ { XFS_MOUNT_INO64, "," MNTOPT_INO64 },
+ { XFS_MOUNT_NOALIGN, "," MNTOPT_NOALIGN },
++ { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID },
+ { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY },
+ { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC },
+- { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID },
++ { XFS_MOUNT_NOLOGFLUSH, "," MNTOPT_NOLOGFLUSH },
++ { XFS_MOUNT_IDELETE, "," MNTOPT_NOIKEEP },
+ { 0, NULL }
+ };
+ struct proc_xfs_info *xfs_infop;
+@@ -1823,6 +1825,9 @@
+ seq_printf(m, "," MNTOPT_SWIDTH "=%d",
+ (int)XFS_FSB_TO_BB(mp, mp->m_swidth));
+
++ if (!(mp->m_flags & XFS_MOUNT_32BITINOOPT))
++ seq_printf(m, "," MNTOPT_64BITINODE);
++
+ return 0;
+ }
+
+@@ -1840,6 +1845,7 @@
+ .vfs_vget = xfs_vget,
+ .vfs_dmapiops = (vfs_dmapiops_t)fs_nosys,
+ .vfs_quotactl = (vfs_quotactl_t)fs_nosys,
++ .vfs_get_inode = xfs_get_inode,
+ .vfs_init_vnode = xfs_initialize_vnode,
+ .vfs_force_shutdown = xfs_do_force_shutdown,
+ };
+diff -urN linux.org/fs/xfs/xfs_vnodeops.c linux/fs/xfs/xfs_vnodeops.c
+--- linux.org/fs/xfs/xfs_vnodeops.c 2003-12-31 05:48:49.000000000 +0100
++++ linux/fs/xfs/xfs_vnodeops.c 2004-01-02 04:21:43.000000000 +0100
+@@ -59,6 +59,7 @@
+ #include "xfs_da_btree.h"
+ #include "xfs_attr.h"
+ #include "xfs_rw.h"
++#include "xfs_refcache.h"
+ #include "xfs_error.h"
+ #include "xfs_bit.h"
+ #include "xfs_rtalloc.h"
+@@ -77,10 +78,6 @@
+ */
+ #define SYMLINK_MAPS 2
+
+-extern int xfs_ioctl(bhv_desc_t *, struct inode *, struct file *,
+- int, unsigned int, unsigned long);
+-
+-
+ /*
+ * For xfs, we check that the file isn't too big to be opened by this kernel.
+ * No other open action is required for regular files. Devices are handled
+@@ -434,7 +431,7 @@
+ }
+
+ /* boolean: are we the file owner? */
+- file_owner = (current->fsuid == ip->i_d.di_uid);
++ file_owner = (current_fsuid(credp) == ip->i_d.di_uid);
+
+ /*
+ * Change various properties of a file.
+@@ -1660,6 +1657,12 @@
+ if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
+ return 0;
+
++#ifdef HAVE_REFCACHE
++ /* If we are in the NFS reference cache then don't do this now */
++ if (ip->i_refcache)
++ return 0;
++#endif
++
+ mp = ip->i_mount;
+
+ if (ip->i_d.di_nlink != 0) {
+@@ -2004,7 +2007,8 @@
+ /*
+ * Make sure that we have allocated dquot(s) on disk.
+ */
+- error = XFS_QM_DQVOPALLOC(mp, dp, current->fsuid, current->fsgid,
++ error = XFS_QM_DQVOPALLOC(mp, dp,
++ current_fsuid(credp), current_fsgid(credp),
+ XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
+ if (error)
+ goto std_return;
+@@ -2613,6 +2617,14 @@
+ goto std_return;
+ }
+
++ /*
++ * Before we drop our extra reference to the inode, purge it
++ * from the refcache if it is there. By waiting until afterwards
++ * to do the IRELE, we ensure that we won't go inactive in the
++ * xfs_refcache_purge_ip routine (although that would be OK).
++ */
++ xfs_refcache_purge_ip(ip);
++
+ vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
+
+ /*
+@@ -2652,6 +2664,14 @@
+ cancel_flags |= XFS_TRANS_ABORT;
+ xfs_trans_cancel(tp, cancel_flags);
+
++ /*
++ * Before we drop our extra reference to the inode, purge it
++ * from the refcache if it is there. By waiting until afterwards
++ * to do the IRELE, we ensure that we won't go inactive in the
++ * xfs_refcache_purge_ip routine (although that would be OK).
++ */
++ xfs_refcache_purge_ip(ip);
++
+ IRELE(ip);
+
+ goto std_return;
+@@ -2899,7 +2919,8 @@
+ /*
+ * Make sure that we have allocated dquot(s) on disk.
+ */
+- error = XFS_QM_DQVOPALLOC(mp, dp, current->fsuid, current->fsgid,
++ error = XFS_QM_DQVOPALLOC(mp, dp,
++ current_fsuid(credp), current_fsgid(credp),
+ XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
+ if (error)
+ goto std_return;
+@@ -3456,7 +3477,8 @@
+ /*
+ * Make sure that we have allocated dquot(s) on disk.
+ */
+- error = XFS_QM_DQVOPALLOC(mp, dp, current->fsuid, current->fsgid,
++ error = XFS_QM_DQVOPALLOC(mp, dp,
++ current_fsuid(credp), current_fsgid(credp),
+ XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
+ if (error)
+ goto std_return;
+@@ -3743,7 +3765,14 @@
+ return;
+ ip = XFS_BHVTOI(bdp);
+ if (locktype == VRWLOCK_WRITE) {
+- xfs_iunlock (ip, XFS_IOLOCK_EXCL);
++ /*
++ * In the write case, we may have added a new entry to
++ * the reference cache. This might store a pointer to
++ * an inode to be released in this inode. If it is there,
++ * clear the pointer and release the inode after unlocking
++ * this one.
++ */
++ xfs_refcache_iunlock(ip, XFS_IOLOCK_EXCL);
+ } else {
+ ASSERT((locktype == VRWLOCK_READ) ||
+ (locktype == VRWLOCK_WRITE_DIRECT));
+@@ -4738,7 +4767,9 @@
+ BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
+ .vop_open = xfs_open,
+ .vop_read = xfs_read,
++#ifdef HAVE_SENDFILE
+ .vop_sendfile = xfs_sendfile,
++#endif
+ .vop_write = xfs_write,
+ .vop_ioctl = xfs_ioctl,
+ .vop_getattr = xfs_getattr,