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 @@ ...@@ -54,9 +54,54 @@
#include "xfs_iomap.h" #include "xfs_iomap.h"
#include <linux/mpage.h> #include <linux/mpage.h>
STATIC void count_page_state(struct page *, int *, int *, int *);
STATIC void convert_page(struct inode *, struct page *, STATIC void convert_page(struct inode *, struct page *,
xfs_iomap_t *, void *, int, int); 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 void
linvfs_unwritten_done( linvfs_unwritten_done(
struct buffer_head *bh, struct buffer_head *bh,
...@@ -1085,13 +1130,16 @@ linvfs_writepage( ...@@ -1085,13 +1130,16 @@ linvfs_writepage(
int delalloc, unmapped, unwritten; int delalloc, unmapped, unwritten;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
xfs_page_trace(XFS_WRITEPAGE_ENTER, inode, page, 0);
/* /*
* We need a transaction if: * We need a transaction if:
* 1. There are delalloc buffers on the page * 1. There are delalloc buffers on the page
* 2. The page is upto date and we have unmapped buffers * 2. The page is uptodate and we have unmapped buffers
* 3. The page is upto date and we have no buffers * 3. The page is uptodate and we have no buffers
* 4. There are unwritten buffers on the page * 4. There are unwritten buffers on the page
*/ */
if (!page_has_buffers(page)) { if (!page_has_buffers(page)) {
unmapped = 1; unmapped = 1;
need_trans = 1; need_trans = 1;
...@@ -1166,6 +1214,8 @@ linvfs_release_page( ...@@ -1166,6 +1214,8 @@ linvfs_release_page(
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
int dirty, delalloc, unmapped, unwritten; int dirty, delalloc, unmapped, unwritten;
xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask);
count_page_state(page, &delalloc, &unmapped, &unwritten); count_page_state(page, &delalloc, &unmapped, &unwritten);
if (!delalloc && !unwritten) if (!delalloc && !unwritten)
goto free_buffers; goto free_buffers;
......
...@@ -283,7 +283,6 @@ xfs_read( ...@@ -283,7 +283,6 @@ xfs_read(
ip = XFS_BHVTOI(bdp); ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp); vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount; mp = ip->i_mount;
vn_trace_entry(vp, "xfs_read", (inst_t *)__return_address);
XFS_STATS_INC(xs_read_calls); XFS_STATS_INC(xs_read_calls);
...@@ -345,6 +344,8 @@ xfs_read( ...@@ -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); ret = __generic_file_aio_read(iocb, iovp, segs, offset);
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
...@@ -377,7 +378,6 @@ xfs_sendfile( ...@@ -377,7 +378,6 @@ xfs_sendfile(
ip = XFS_BHVTOI(bdp); ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp); vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount; mp = ip->i_mount;
vn_trace_entry(vp, "xfs_sendfile", (inst_t *)__return_address);
XFS_STATS_INC(xs_read_calls); XFS_STATS_INC(xs_read_calls);
...@@ -405,6 +405,8 @@ xfs_sendfile( ...@@ -405,6 +405,8 @@ xfs_sendfile(
return -error; 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); ret = generic_file_sendfile(filp, offset, count, actor, target);
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
...@@ -658,7 +660,6 @@ xfs_write( ...@@ -658,7 +660,6 @@ xfs_write(
XFS_STATS_INC(xs_write_calls); XFS_STATS_INC(xs_write_calls);
vp = BHV_TO_VNODE(bdp); vp = BHV_TO_VNODE(bdp);
vn_trace_entry(vp, "xfs_write", (inst_t *)__return_address);
xip = XFS_BHVTOI(bdp); xip = XFS_BHVTOI(bdp);
/* START copy & waste from filemap.c */ /* START copy & waste from filemap.c */
...@@ -678,7 +679,7 @@ xfs_write( ...@@ -678,7 +679,7 @@ xfs_write(
if (size == 0) if (size == 0)
return 0; return 0;
io = &(xip->i_iocore); io = &xip->i_iocore;
mp = io->io_mount; mp = io->io_mount;
xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE); xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE);
......
...@@ -45,9 +45,7 @@ struct xfs_iomap; ...@@ -45,9 +45,7 @@ struct xfs_iomap;
/* /*
* Defines for the trace mechanisms in xfs_lrw.c. * Defines for the trace mechanisms in xfs_lrw.c.
*/ */
#define XFS_RW_KTRACE_SIZE 64 #define XFS_RW_KTRACE_SIZE 128
#define XFS_STRAT_KTRACE_SIZE 64
#define XFS_STRAT_GTRACE_SIZE 512
#define XFS_READ_ENTER 1 #define XFS_READ_ENTER 1
#define XFS_WRITE_ENTER 2 #define XFS_WRITE_ENTER 2
...@@ -69,6 +67,12 @@ struct xfs_iomap; ...@@ -69,6 +67,12 @@ struct xfs_iomap;
#define XFS_INVAL_CACHED 18 #define XFS_INVAL_CACHED 18
#define XFS_DIORD_ENTER 19 #define XFS_DIORD_ENTER 19
#define XFS_DIOWR_ENTER 20 #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 *, extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
const struct iovec *, size_t, loff_t, int); const struct iovec *, size_t, loff_t, int);
extern void xfs_inval_cached_trace(struct xfs_iocore *, 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 * 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 * under the terms of version 2 of the GNU General Public License as
...@@ -69,6 +69,76 @@ ...@@ -69,6 +69,76 @@
#include "xfs_utils.h" #include "xfs_utils.h"
#include "xfs_iomap.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) \ #define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \
<< mp->m_writeio_log) << mp->m_writeio_log)
#define XFS_STRAT_WRITE_IMAPS 2 #define XFS_STRAT_WRITE_IMAPS 2
...@@ -149,17 +219,20 @@ xfs_iomap( ...@@ -149,17 +219,20 @@ xfs_iomap(
(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
BMAPI_UNWRITTEN | BMAPI_DEVICE)) { BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
case BMAPI_READ: case BMAPI_READ:
xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
lockmode = XFS_LCK_MAP_SHARED(mp, io); lockmode = XFS_LCK_MAP_SHARED(mp, io);
bmapi_flags = XFS_BMAPI_ENTIRE; bmapi_flags = XFS_BMAPI_ENTIRE;
if (flags & BMAPI_IGNSTATE) if (flags & BMAPI_IGNSTATE)
bmapi_flags |= XFS_BMAPI_IGSTATE; bmapi_flags |= XFS_BMAPI_IGSTATE;
break; break;
case BMAPI_WRITE: case BMAPI_WRITE:
xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
bmapi_flags = 0; bmapi_flags = 0;
XFS_ILOCK(mp, io, lockmode); XFS_ILOCK(mp, io, lockmode);
break; break;
case BMAPI_ALLOCATE: case BMAPI_ALLOCATE:
xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count);
lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
bmapi_flags = XFS_BMAPI_ENTIRE; bmapi_flags = XFS_BMAPI_ENTIRE;
/* Attempt non-blocking lock */ /* Attempt non-blocking lock */
...@@ -201,8 +274,11 @@ xfs_iomap( ...@@ -201,8 +274,11 @@ xfs_iomap(
switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
case BMAPI_WRITE: case BMAPI_WRITE:
/* If we found an extent, return it */ /* 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; break;
}
if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
...@@ -211,6 +287,10 @@ xfs_iomap( ...@@ -211,6 +287,10 @@ xfs_iomap(
error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
flags, &imap, &nimaps); flags, &imap, &nimaps);
} }
if (!error) {
xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io,
offset, count, iomapp, &imap, flags);
}
iomap_flags = IOMAP_NEW; iomap_flags = IOMAP_NEW;
break; break;
case BMAPI_ALLOCATE: case BMAPI_ALLOCATE:
...@@ -218,8 +298,11 @@ xfs_iomap( ...@@ -218,8 +298,11 @@ xfs_iomap(
XFS_IUNLOCK(mp, io, lockmode); XFS_IUNLOCK(mp, io, lockmode);
lockmode = 0; 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; break;
}
error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
break; break;
...@@ -309,7 +392,6 @@ xfs_iomap_write_direct( ...@@ -309,7 +392,6 @@ xfs_iomap_write_direct(
* Make sure that the dquots are there. This doesn't hold * Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read. * the ilock across a disk read.
*/ */
error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
if (error) if (error)
return XFS_ERROR(error); return XFS_ERROR(error);
...@@ -540,8 +622,9 @@ xfs_iomap_write_delay( ...@@ -540,8 +622,9 @@ xfs_iomap_write_delay(
* If bmapi returned us nothing, and if we didn't get back EDQUOT, * If bmapi returned us nothing, and if we didn't get back EDQUOT,
* then we must have run out of space. * then we must have run out of space.
*/ */
if (nimaps == 0) { if (nimaps == 0) {
xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
io, offset, count);
if (xfs_flush_space(ip, &fsynced, &ioflag)) if (xfs_flush_space(ip, &fsynced, &ioflag))
return XFS_ERROR(ENOSPC); return XFS_ERROR(ENOSPC);
...@@ -584,7 +667,6 @@ xfs_iomap_write_allocate( ...@@ -584,7 +667,6 @@ xfs_iomap_write_allocate(
/* /*
* Make sure that the dquots are there. * Make sure that the dquots are there.
*/ */
if ((error = XFS_QM_DQATTACH(mp, ip, 0))) if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return XFS_ERROR(error); return XFS_ERROR(error);
...@@ -612,7 +694,6 @@ xfs_iomap_write_allocate( ...@@ -612,7 +694,6 @@ xfs_iomap_write_allocate(
XFS_WRITE_LOG_RES(mp), XFS_WRITE_LOG_RES(mp),
0, XFS_TRANS_PERM_LOG_RES, 0, XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT); XFS_WRITE_LOG_COUNT);
if (error == ENOSPC) { if (error == ENOSPC) {
error = xfs_trans_reserve(tp, 0, error = xfs_trans_reserve(tp, 0,
XFS_WRITE_LOG_RES(mp), XFS_WRITE_LOG_RES(mp),
...@@ -653,19 +734,16 @@ xfs_iomap_write_allocate( ...@@ -653,19 +734,16 @@ xfs_iomap_write_allocate(
error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
XFS_BMAPI_WRITE, &first_block, 1, XFS_BMAPI_WRITE, &first_block, 1,
imap, &nimaps, &free_list); imap, &nimaps, &free_list);
if (error) if (error)
goto trans_cancel; goto trans_cancel;
error = xfs_bmap_finish(&tp, &free_list, error = xfs_bmap_finish(&tp, &free_list,
first_block, &committed); first_block, &committed);
if (error) if (error)
goto trans_cancel; goto trans_cancel;
error = xfs_trans_commit(tp, error = xfs_trans_commit(tp,
XFS_TRANS_RELEASE_LOG_RES, NULL); XFS_TRANS_RELEASE_LOG_RES, NULL);
if (error) if (error)
goto error0; goto error0;
...@@ -725,6 +803,9 @@ xfs_iomap_write_unwritten( ...@@ -725,6 +803,9 @@ xfs_iomap_write_unwritten(
xfs_fsblock_t firstfsb; xfs_fsblock_t firstfsb;
xfs_bmap_free_t free_list; 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); offset_fsb = XFS_B_TO_FSBT(mp, offset);
count_fsb = XFS_B_TO_FSB(mp, count); 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