Commit bf47e0c2 authored by Nathan Scott's avatar Nathan Scott

[XFS] Add I/O path tracing code, useful in diagnosing that last unwritten extent problem.

SGI Modid: xfs-linux:xfs-kern:166497a
parent 8f45cdd9
......@@ -54,9 +54,54 @@
#include "xfs_iomap.h"
#include <linux/mpage.h>
STATIC void count_page_state(struct page *, int *, int *, int *);
STATIC void convert_page(struct inode *, struct page *,
xfs_iomap_t *, void *, int, int);
#if defined(XFS_RW_TRACE)
void
xfs_page_trace(
int tag,
struct inode *inode,
struct page *page,
int mask)
{
xfs_inode_t *ip;
bhv_desc_t *bdp;
vnode_t *vp = LINVFS_GET_VP(inode);
loff_t isize = i_size_read(inode);
loff_t offset = page->index << PAGE_CACHE_SHIFT;
int delalloc, unmapped, unwritten;
count_page_state(page, &delalloc, &unmapped, &unwritten);
bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
ip = XFS_BHVTOI(bdp);
if (!ip->i_rwtrace)
return;
ktrace_enter(ip->i_rwtrace,
(void *)((unsigned long)tag),
(void *)ip,
(void *)inode,
(void *)page,
(void *)((unsigned long)mask),
(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
(void *)((unsigned long)((isize >> 32) & 0xffffffff)),
(void *)((unsigned long)(isize & 0xffffffff)),
(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
(void *)((unsigned long)(offset & 0xffffffff)),
(void *)((unsigned long)delalloc),
(void *)((unsigned long)unmapped),
(void *)((unsigned long)unwritten),
(void *)NULL,
(void *)NULL);
}
#else
#define xfs_page_trace(tag, inode, page, mask)
#endif
void
linvfs_unwritten_done(
struct buffer_head *bh,
......@@ -1085,13 +1130,16 @@ linvfs_writepage(
int delalloc, unmapped, unwritten;
struct inode *inode = page->mapping->host;
xfs_page_trace(XFS_WRITEPAGE_ENTER, inode, page, 0);
/*
* We need a transaction if:
* 1. There are delalloc buffers on the page
* 2. The page is upto date and we have unmapped buffers
* 3. The page is upto date and we have no buffers
* 2. The page is uptodate and we have unmapped buffers
* 3. The page is uptodate and we have no buffers
* 4. There are unwritten buffers on the page
*/
if (!page_has_buffers(page)) {
unmapped = 1;
need_trans = 1;
......@@ -1166,6 +1214,8 @@ linvfs_release_page(
struct inode *inode = page->mapping->host;
int dirty, delalloc, unmapped, unwritten;
xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask);
count_page_state(page, &delalloc, &unmapped, &unwritten);
if (!delalloc && !unwritten)
goto free_buffers;
......
......@@ -283,7 +283,6 @@ xfs_read(
ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount;
vn_trace_entry(vp, "xfs_read", (inst_t *)__return_address);
XFS_STATS_INC(xs_read_calls);
......@@ -345,6 +344,8 @@ xfs_read(
}
}
xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
iovp, segs, *offset, ioflags);
ret = __generic_file_aio_read(iocb, iovp, segs, offset);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
......@@ -377,7 +378,6 @@ xfs_sendfile(
ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount;
vn_trace_entry(vp, "xfs_sendfile", (inst_t *)__return_address);
XFS_STATS_INC(xs_read_calls);
......@@ -405,6 +405,8 @@ xfs_sendfile(
return -error;
}
}
xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
target, count, *offset, ioflags);
ret = generic_file_sendfile(filp, offset, count, actor, target);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
......@@ -658,7 +660,6 @@ xfs_write(
XFS_STATS_INC(xs_write_calls);
vp = BHV_TO_VNODE(bdp);
vn_trace_entry(vp, "xfs_write", (inst_t *)__return_address);
xip = XFS_BHVTOI(bdp);
/* START copy & waste from filemap.c */
......@@ -678,7 +679,7 @@ xfs_write(
if (size == 0)
return 0;
io = &(xip->i_iocore);
io = &xip->i_iocore;
mp = io->io_mount;
xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE);
......
......@@ -45,9 +45,7 @@ struct xfs_iomap;
/*
* 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_RW_KTRACE_SIZE 128
#define XFS_READ_ENTER 1
#define XFS_WRITE_ENTER 2
......@@ -69,6 +67,12 @@ struct xfs_iomap;
#define XFS_INVAL_CACHED 18
#define XFS_DIORD_ENTER 19
#define XFS_DIOWR_ENTER 20
#define XFS_SENDFILE_ENTER 21
#define XFS_WRITEPAGE_ENTER 22
#define XFS_RELEASEPAGE_ENTER 23
#define XFS_IOMAP_ALLOC_ENTER 24
#define XFS_IOMAP_ALLOC_MAP 25
#define XFS_IOMAP_UNWRITTEN 26
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 *,
......
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
......@@ -69,6 +69,76 @@
#include "xfs_utils.h"
#include "xfs_iomap.h"
#if defined(XFS_RW_TRACE)
void
xfs_iomap_enter_trace(
int tag,
xfs_iocore_t *io,
xfs_off_t offset,
ssize_t count)
{
xfs_inode_t *ip = XFS_IO_INODE(io);
if (!ip->i_rwtrace)
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 *)((unsigned long)((offset >> 32) & 0xffffffff)),
(void *)((unsigned long)(offset & 0xffffffff)),
(void *)((unsigned long)count),
(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 *)NULL,
(void *)NULL);
}
void
xfs_iomap_map_trace(
int tag,
xfs_iocore_t *io,
xfs_off_t offset,
ssize_t count,
xfs_iomap_t *iomapp,
xfs_bmbt_irec_t *imapp,
int flags)
{
xfs_inode_t *ip = XFS_IO_INODE(io);
if (!ip->i_rwtrace)
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 *)((unsigned long)((offset >> 32) & 0xffffffff)),
(void *)((unsigned long)(offset & 0xffffffff)),
(void *)((unsigned long)count),
(void *)((unsigned long)flags),
(void *)((unsigned long)((iomapp->iomap_offset >> 32) & 0xffffffff)),
(void *)((unsigned long)(iomapp->iomap_offset & 0xffffffff)),
(void *)((unsigned long)(iomapp->iomap_delta)),
(void *)((unsigned long)(iomapp->iomap_bsize)),
(void *)((unsigned long)(iomapp->iomap_bn)),
(void *)(__psint_t)(imapp->br_startoff),
(void *)((unsigned long)(imapp->br_blockcount)),
(void *)(__psint_t)(imapp->br_startblock));
}
#else
#define xfs_iomap_enter_trace(tag, io, offset, count)
#define xfs_iomap_map_trace(tag, io, offset, count, iomapp, imapp, flags)
#endif
#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \
<< mp->m_writeio_log)
#define XFS_STRAT_WRITE_IMAPS 2
......@@ -149,17 +219,20 @@ xfs_iomap(
(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
case BMAPI_READ:
xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
lockmode = XFS_LCK_MAP_SHARED(mp, io);
bmapi_flags = XFS_BMAPI_ENTIRE;
if (flags & BMAPI_IGNSTATE)
bmapi_flags |= XFS_BMAPI_IGSTATE;
break;
case BMAPI_WRITE:
xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
bmapi_flags = 0;
XFS_ILOCK(mp, io, lockmode);
break;
case BMAPI_ALLOCATE:
xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count);
lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
bmapi_flags = XFS_BMAPI_ENTIRE;
/* Attempt non-blocking lock */
......@@ -201,8 +274,11 @@ xfs_iomap(
switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
case BMAPI_WRITE:
/* If we found an extent, return it */
if (nimaps && (imap.br_startblock != HOLESTARTBLOCK))
if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) {
xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
offset, count, iomapp, &imap, flags);
break;
}
if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
......@@ -211,6 +287,10 @@ xfs_iomap(
error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
flags, &imap, &nimaps);
}
if (!error) {
xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io,
offset, count, iomapp, &imap, flags);
}
iomap_flags = IOMAP_NEW;
break;
case BMAPI_ALLOCATE:
......@@ -218,8 +298,11 @@ xfs_iomap(
XFS_IUNLOCK(mp, io, lockmode);
lockmode = 0;
if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock))
if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) {
xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
offset, count, iomapp, &imap, flags);
break;
}
error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
break;
......@@ -309,7 +392,6 @@ xfs_iomap_write_direct(
* Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read.
*/
error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
if (error)
return XFS_ERROR(error);
......@@ -540,8 +622,9 @@ xfs_iomap_write_delay(
* If bmapi returned us nothing, and if we didn't get back EDQUOT,
* then we must have run out of space.
*/
if (nimaps == 0) {
xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
io, offset, count);
if (xfs_flush_space(ip, &fsynced, &ioflag))
return XFS_ERROR(ENOSPC);
......@@ -584,7 +667,6 @@ xfs_iomap_write_allocate(
/*
* Make sure that the dquots are there.
*/
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return XFS_ERROR(error);
......@@ -612,7 +694,6 @@ xfs_iomap_write_allocate(
XFS_WRITE_LOG_RES(mp),
0, XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT);
if (error == ENOSPC) {
error = xfs_trans_reserve(tp, 0,
XFS_WRITE_LOG_RES(mp),
......@@ -653,19 +734,16 @@ xfs_iomap_write_allocate(
error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
XFS_BMAPI_WRITE, &first_block, 1,
imap, &nimaps, &free_list);
if (error)
goto trans_cancel;
error = xfs_bmap_finish(&tp, &free_list,
first_block, &committed);
if (error)
goto trans_cancel;
error = xfs_trans_commit(tp,
XFS_TRANS_RELEASE_LOG_RES, NULL);
if (error)
goto error0;
......@@ -725,6 +803,9 @@ xfs_iomap_write_unwritten(
xfs_fsblock_t firstfsb;
xfs_bmap_free_t free_list;
xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN,
&ip->i_iocore, offset, count);
offset_fsb = XFS_B_TO_FSBT(mp, offset);
count_fsb = XFS_B_TO_FSB(mp, count);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment