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 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 #include #include +#include #include #include @@ -69,9 +70,11 @@ #include -#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 +#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 +#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 #include #include +#include +#include #include #include -#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 /* - * 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 -#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 -#include -#include -#include -#include -#include -#include -#include - -#include - -#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 /* * 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 #include -/* 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 -# 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 #include @@ -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, "", "Dump bhv chain"}, { "vn", kdbm_vn, "", "Dump inode/vnode/trace"}, { "vnode", kdbm_vnode, "", "Dump vnode"}, -#ifdef CONFIG_XFS_VNODE_TRACING + { "vfs", kdbm_vfs, "", "Dump vfs"}, +#ifdef XFS_VNODE_TRACE { "vntrace", kdbm_vntrace, "", "Dump vnode Trace"}, - { "vntraceaddr", kdbm_vntraceaddr, "", "Dump vnode Trace by Address"}, -#endif /* CONFIG_XFS_VNODE_TRACING */ + { "vntraceaddr", kdbm_vntraceaddr, "", + "Dump vnode Trace by Address"}, +#endif { "xagf", kdbm_xfs_xagf, "", "Dump XFS allocation group freespace" }, { "xagi", kdbm_xfs_xagi, "", "Dump XFS allocation group inode" }, { "xail", kdbm_xfs_xaildump, "", "Dump XFS AIL for a mountpoint" }, +#ifdef XFS_ALLOC_TRACE + { "xalatrc", kdbm_xfs_xalatrace, "", + "Dump XFS alloc count trace" }, + { "xalbtrc", kdbm_xfs_xalbtrace, "", + "Dump XFS alloc block trace" }, + { "xalgtrc", kdbm_xfs_xalgtrace, "", + "Dump XFS alloc alloc-group trace" }, +#endif + { "xalloc", kdbm_xfs_xalloc, "", "Dump XFS allocation args structure" }, -#ifdef DEBUG +#ifdef XFS_ALLOC_TRACE { "xalmtrc", kdbm_xfs_xalmtrace, "", "Dump XFS alloc mount-point trace" }, + { "xalttrc", kdbm_xfs_xalttrace, "", + "Dump XFS alloc trace by tag number" }, #endif + { "xarg", kdbm_xfs_xarg, "", + "Input XFS argument for next function" }, { "xattrcx", kdbm_xfs_xattrcontext, "", "Dump XFS attr_list context struct"}, { "xattrlf", kdbm_xfs_xattrleaf, "", "Dump XFS attribute leaf block"}, { "xattrsf", kdbm_xfs_xattrsf, "", "Dump XFS attribute shortform"}, +#ifdef XFS_ATTR_TRACE + { "xattrtr", kdbm_xfs_xattrtrace, "", + "Dump XFS attribute attr_list() trace" }, +#endif { "xbirec", kdbm_xfs_xbirec, "", + "Dump XFS buf log item trace" }, +#endif { "xbmalla", kdbm_xfs_xbmalla, "", "Dump XFS bmalloc args structure"}, - { "xbrec", kdbm_xfs_xbrec, "", + "Dump XFS bmap btree count trace" }, + { "xbmitrc", kdbm_xfs_xbmitrace, "", + "Dump XFS bmap btree per-inode trace" }, + { "xbmstrc", kdbm_xfs_xbmstrace, "", + "Dump XFS bmap btree inode trace" }, +#endif + { "xbrec", kdbm_xfs_xbrec, "", "Dump XFS bmap record"}, { "xbroot", kdbm_xfs_xbroot, "", "Dump XFS bmap btree root (data)"}, @@ -2175,12 +2802,29 @@ "Dump XFS btree cursor"}, { "xbuf", kdbm_xfs_xbuf, "", "Dump XFS data from a buffer"}, +#ifdef XFS_BMAP_TRACE + { "xbxatrc", kdbm_xfs_xbxatrace, "", + "Dump XFS bmap extent count trace" }, + { "xbxitrc", kdbm_xfs_xbxitrace, "", + "Dump XFS bmap extent per-inode trace" }, + { "xbxstrc", kdbm_xfs_xbxstrace, "", + "Dump XFS bmap extent inode trace" }, +#endif { "xchash", kdbm_xfs_xchash, "", "Dump XFS cluster hash"}, { "xchlist", kdbm_xfs_xchashlist, "", "Dump XFS cluster hash list"}, + { "xchksum", kdbm_xfs_xchksum, "", "Dump chksum" }, +#ifdef XFS_DIR2_TRACE + { "xd2atrc", kdbm_xfs_xdir2atrace, "", + "Dump XFS directory v2 count trace" }, +#endif { "xd2free", kdbm_xfs_xdir2free, "", "Dump XFS directory v2 freemap"}, +#ifdef XFS_DIR2_TRACE + { "xd2itrc", kdbm_xfs_xdir2itrace, "", + "Dump XFS directory v2 per-inode trace" }, +#endif { "xdaargs", kdbm_xfs_xdaargs, "", "Dump XFS dir/attr args structure"}, { "xdabuf", kdbm_xfs_xdabuf, "", @@ -2197,12 +2841,20 @@ "Dump XFS directory shortform"}, { "xdir2sf", kdbm_xfs_xdir2sf, "", "Dump XFS directory v2 shortform"}, +#ifdef XFS_DIR_TRACE + { "xdirtrc", kdbm_xfs_xdirtrace, "", + "Dump XFS directory getdents() trace" }, +#endif { "xdiskdq", kdbm_xfs_xqm_diskdq, "", "Dump XFS ondisk dquot (quota) struct"}, { "xdqatt", kdbm_xfs_xqm_dqattached_inos, "", "All incore inodes with dquots"}, { "xdqinfo", kdbm_xfs_xqm_tpdqinfo, "", "Dump dqinfo structure of a trans"}, +#ifdef XFS_DQUOT_TRACE + { "xdqtrace",kdbm_xfs_xqm_dqtrace, "", + "Dump trace of a given dquot" }, +#endif { "xdquot", kdbm_xfs_xqm_dquot, "", "Dump XFS dquot (quota) structure"}, { "xexlist", kdbm_xfs_xexlist, "", @@ -2215,12 +2867,26 @@ "Dump All XFS in-core logs"}, { "xiclog", kdbm_xfs_xiclog, "", "Dump XFS in-core log"}, +#ifdef XFS_LOG_TRACE + { "xictrc", kdbm_xfs_xiclogtrace, "", + "Dump XFS in-core log trace" }, +#endif { "xihash", kdbm_xfs_xihash, "", "Dump XFS inode hash statistics"}, +#ifdef XFS_ILOCK_TRACE + { "xilocktrc",kdbm_xfs_xilock_trace, "", + "Dump XFS ilock trace" }, + { "xailcktrc",kdbm_xfs_xailock_trace,"", + "Dump XFS global ilock trace" }, +#endif { "xinodes", kdbm_xfs_xinodes, "", "Dump XFS inodes per mount"}, { "xquiesce",kdbm_xfs_xinodes_quiesce, "", "Dump non-quiesced XFS inodes per mount"}, +#ifdef XFS_LOG_TRACE + { "xl_grtr", kdbm_xfs_xlog_granttrace, "", + "Dump XFS log grant trace" }, +#endif { "xl_rcit", kdbm_xfs_xlog_ritem, "", "Dump XFS recovery item"}, { "xl_rctr", kdbm_xfs_xlog_rtrans, "", @@ -2255,6 +2921,10 @@ #endif /* CONFIG_XFS_QUOTA */ { "xqmplist",kdbm_xfs_xqm_mplist, "", "Dump XFS all dquots of a f/s"}, +#ifdef XFS_RW_TRACE + { "xrwtrc", kdbm_xfs_xrwtrace, "", + "Dump XFS inode read/write trace" }, +#endif { "xsb", kdbm_xfs_xsb, " ", "Dump XFS superblock"}, { "xtp", kdbm_xfs_xtp, "", @@ -2264,6 +2934,18 @@ { 0, 0, 0 } }; +static struct xif pb_funcs[] = { + { "pb", kdbm_pb, "", "Display page_buf_t" }, + { "pbflags", kdbm_pb_flags, "", "Display page_buf flags" }, + { "iomapap", kdbm_iomap, "", "Display IOmap" }, + { "pbdelay", kdbm_pbdelay, "0|1", "Display delwri pagebufs" }, +#ifdef PAGEBUF_TRACE + { "pbtrace", kdbm_pbtrace, "|", "page_buf_t trace" }, + { "pboffset",kdbm_pbtrace_offset, " []","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, "", "Display page_buf_t", 0); - kdb_register("pbflags", kdbm_pb_flags, "", - "Display page buf flags", 0); - kdb_register("pbiodesc", kdbm_pbiodesc, "", - "Display I/O Descriptor", 0); - kdb_register("pbmap", kdbm_pbmap, "", - "Display Bmap", 0); - kdb_register("pbtrace", kdbm_pbtrace, "|", - "page_buf_t trace", 0); -#ifdef PAGEBUF_TRACE - kdb_register("pboffset", kdbm_pbtrace_offset, " []", - "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
\n"); + qprintf(" length is set with xarg\n"); + } else { + for (i=0; ibps[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 \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,