diff options
| -rw-r--r-- | fs/xfs/linux/xfs_aops.c | 79 | ||||
| -rw-r--r-- | fs/xfs/linux/xfs_iomap.c | 45 | ||||
| -rw-r--r-- | fs/xfs/pagebuf/page_buf.c | 14 | ||||
| -rw-r--r-- | fs/xfs/pagebuf/page_buf.h | 36 | ||||
| -rw-r--r-- | fs/xfs/xfsidbg.c | 8 |
5 files changed, 101 insertions, 81 deletions
diff --git a/fs/xfs/linux/xfs_aops.c b/fs/xfs/linux/xfs_aops.c index 7e9ecd1cbd2e..3d15789b4abd 100644 --- a/fs/xfs/linux/xfs_aops.c +++ b/fs/xfs/linux/xfs_aops.c @@ -50,8 +50,6 @@ linvfs_unwritten_done( pagebuf_ioerror(pb, -EIO); if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { pagebuf_iodone(pb, 1, 1); - pb->pb_flags &= ~_PBF_LOCKABLE; - pagebuf_rele(pb); } end_buffer_async_write(bh, uptodate); } @@ -61,28 +59,21 @@ linvfs_unwritten_done( * to written extents. */ STATIC void -xfs_unwritten_conv( - xfs_buf_t *bp) +linvfs_unwritten_conv( + xfs_buf_t *bp) { - bhv_desc_t *bdp = XFS_BUF_FSPRIVATE(bp, bhv_desc_t *); - xfs_mount_t *mp; - xfs_inode_t *ip; + vnode_t *vp = XFS_BUF_FSPRIVATE(bp, vnode_t *); + int error; - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; - - if (XFS_TEST_ERROR(XFS_BUF_GETERROR(bp), mp, - XFS_ERRTAG_STRATCMPL_IOERR, - XFS_RANDOM_STRATCMPL_IOERR)) { - xfs_ioerror_alert(__FUNCTION__, mp, bp, XFS_BUF_ADDR(bp)); - } + if (atomic_read(&bp->pb_hold) < 1) + BUG(); - XFS_IOMAP_WRITE_UNWRITTEN(mp, &ip->i_iocore, - XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp)); + VOP_BMAP(vp, XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp), + BMAP_UNWRITTEN, NULL, NULL, error); XFS_BUF_SET_FSPRIVATE(bp, NULL); XFS_BUF_CLR_IODONE_FUNC(bp); XFS_BUF_UNDATAIO(bp); - xfs_biodone(bp); + pagebuf_iodone(bp, 0, 0); } STATIC int @@ -96,20 +87,20 @@ map_blocks( vnode_t *vp = LINVFS_GET_VP(inode); int error, nmaps = 1; - if (((flags & (PBF_DIRECT|PBF_SYNC)) == PBF_DIRECT) && + if (((flags & (BMAP_DIRECT|BMAP_SYNC)) == BMAP_DIRECT) && (offset >= inode->i_size)) count = max_t(ssize_t, count, XFS_WRITE_IO_LOG); retry: VOP_BMAP(vp, offset, count, flags, pbmapp, &nmaps, error); - if (error == EAGAIN) + if ((error == EAGAIN) || (error == EIO)) return -error; - if (unlikely((flags & (PBF_WRITE|PBF_DIRECT)) == - (PBF_WRITE|PBF_DIRECT) && nmaps && + if (unlikely((flags & (BMAP_WRITE|BMAP_DIRECT)) == + (BMAP_WRITE|BMAP_DIRECT) && nmaps && (pbmapp->pbm_flags & PBMF_DELAY))) { - flags = PBF_FILE_ALLOCATE; + flags = BMAP_ALLOCATE; goto retry; } - if (flags & (PBF_WRITE|PBF_FILE_ALLOCATE)) { + if (flags & (BMAP_WRITE|BMAP_ALLOCATE)) { VMODIFY(vp); } return -error; @@ -371,7 +362,7 @@ map_unwritten( offset += p_offset; pb = pagebuf_lookup(mp->pbm_target, - mp->pbm_offset, mp->pbm_bsize, _PBF_LOCKABLE); + mp->pbm_offset, mp->pbm_bsize, 0); if (!pb) return -ENOMEM; @@ -390,7 +381,6 @@ map_unwritten( tmp = match_offset_to_mapping(start_page, mp, p_offset); if (!tmp) break; - BUG_ON(!(tmp->pbm_flags & PBMF_UNWRITTEN)); map_buffer_at_offset(start_page, bh, p_offset, block_bits, mp); set_buffer_unwritten_io(bh); bh->b_private = pb; @@ -442,15 +432,14 @@ map_unwritten( size <<= block_bits; /* convert fsb's to byte range */ XFS_BUF_DATAIO(pb); + XFS_BUF_ASYNC(pb); XFS_BUF_SET_SIZE(pb, size); XFS_BUF_SET_OFFSET(pb, offset); - XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode)->v_fbhv); - XFS_BUF_SET_IODONE_FUNC(pb, xfs_unwritten_conv); + XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode)); + XFS_BUF_SET_IODONE_FUNC(pb, linvfs_unwritten_conv); if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { pagebuf_iodone(pb, 1, 1); - pb->pb_flags &= ~_PBF_LOCKABLE; - pagebuf_rele(pb); } return 0; @@ -552,6 +541,7 @@ convert_page( } else { set_buffer_dirty(bh); unlock_buffer(bh); + mark_buffer_dirty(bh); } } while (i++, (bh = bh->b_this_page) != head); @@ -617,7 +607,7 @@ page_state_convert( unsigned long p_offset = 0, end_index; loff_t offset, end_offset; int len, err, i, cnt = 0, uptodate = 1; - int flags = startio ? 0 : PBF_TRYLOCK; + int flags = startio ? 0 : BMAP_TRYLOCK; int page_dirty = 1; @@ -655,7 +645,7 @@ page_state_convert( if (buffer_unwritten(bh)) { if (!mp) { err = map_blocks(inode, offset, len, &map, - PBF_FILE_UNWRITTEN); + BMAP_READ|BMAP_IGNSTATE); if (err) { goto error; } @@ -677,6 +667,7 @@ page_state_convert( } else { set_buffer_dirty(bh); unlock_buffer(bh); + mark_buffer_dirty(bh); } page_dirty = 0; } @@ -687,7 +678,7 @@ page_state_convert( } else if (buffer_delay(bh)) { if (!mp) { err = map_blocks(inode, offset, len, &map, - PBF_FILE_ALLOCATE | flags); + BMAP_ALLOCATE | flags); if (err) { goto error; } @@ -702,6 +693,7 @@ page_state_convert( } else { set_buffer_dirty(bh); unlock_buffer(bh); + mark_buffer_dirty(bh); } page_dirty = 0; } @@ -720,8 +712,8 @@ page_state_convert( size = probe_unmapped_cluster( inode, page, bh, head); err = map_blocks(inode, offset, - size, &map, - PBF_WRITE | PBF_DIRECT); + size, &map, + BMAP_WRITE | BMAP_MMAP); if (err) { goto error; } @@ -737,6 +729,7 @@ page_state_convert( } else { set_buffer_dirty(bh); unlock_buffer(bh); + mark_buffer_dirty(bh); } page_dirty = 0; } @@ -760,13 +753,11 @@ next_bh: if (uptodate) SetPageUptodate(page); - if (startio) { + if (startio) submit_page(page, bh_arr, cnt); - } - if (mp) { + if (mp) cluster_write(inode, page->index + 1, mp, startio, unmapped); - } return page_dirty; @@ -797,7 +788,7 @@ linvfs_get_block_core( struct buffer_head *bh_result, int create, int direct, - page_buf_flags_t flags) + bmapi_flags_t flags) { vnode_t *vp = LINVFS_GET_VP(inode); page_buf_bmap_t pbmap; @@ -817,7 +808,7 @@ linvfs_get_block_core( size = 1 << inode->i_blkbits; VOP_BMAP(vp, offset, size, - create ? flags : PBF_READ, &pbmap, &retpbbm, error); + create ? flags : BMAP_READ, &pbmap, &retpbbm, error); if (error) return -error; @@ -887,7 +878,7 @@ linvfs_get_block( int create) { return linvfs_get_block_core(inode, iblock, 0, bh_result, - create, 0, PBF_WRITE); + create, 0, BMAP_WRITE); } STATIC int @@ -898,7 +889,7 @@ linvfs_get_block_sync( int create) { return linvfs_get_block_core(inode, iblock, 0, bh_result, - create, 0, PBF_SYNC|PBF_WRITE); + create, 0, BMAP_SYNC|BMAP_WRITE); } STATIC int @@ -910,7 +901,7 @@ linvfs_get_blocks_direct( int create) { return linvfs_get_block_core(inode, iblock, max_blocks, bh_result, - create, 1, PBF_WRITE|PBF_DIRECT); + create, 1, BMAP_WRITE|BMAP_DIRECT); } STATIC int diff --git a/fs/xfs/linux/xfs_iomap.c b/fs/xfs/linux/xfs_iomap.c index 359af7513116..0cd5c7269854 100644 --- a/fs/xfs/linux/xfs_iomap.c +++ b/fs/xfs/linux/xfs_iomap.c @@ -97,7 +97,7 @@ xfs_iomap( { xfs_mount_t *mp = io->io_mount; xfs_fileoff_t offset_fsb, end_fsb; - int error; + int error = 0; int lockmode = 0; xfs_bmbt_irec_t imap; int nimaps = 1; @@ -107,32 +107,31 @@ xfs_iomap( return XFS_ERROR(EIO); switch (flags & - (PBF_READ|PBF_WRITE|PBF_FILE_ALLOCATE|PBF_FILE_UNWRITTEN)) { - case PBF_READ: + (BMAP_READ|BMAP_WRITE|BMAP_ALLOCATE|BMAP_UNWRITTEN)) { + case BMAP_READ: lockmode = XFS_LCK_MAP_SHARED(mp, io); bmap_flags = XFS_BMAPI_ENTIRE; + if (flags & BMAP_IGNSTATE) + bmap_flags |= XFS_BMAPI_IGSTATE; break; case PBF_WRITE: lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; bmap_flags = 0; XFS_ILOCK(mp, io, lockmode); break; - case PBF_FILE_ALLOCATE: + case BMAP_ALLOCATE: lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; bmap_flags = XFS_BMAPI_ENTIRE; /* Attempt non-blocking lock */ - if (flags & PBF_TRYLOCK) { + if (flags & BMAP_TRYLOCK) { if (!XFS_ILOCK_NOWAIT(mp, io, lockmode)) return XFS_ERROR(EAGAIN); } else { XFS_ILOCK(mp, io, lockmode); } break; - case PBF_FILE_UNWRITTEN: - lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; - bmap_flags = XFS_BMAPI_ENTIRE|XFS_BMAPI_IGSTATE; - XFS_ILOCK(mp, io, lockmode); - break; + case BMAP_UNWRITTEN: + goto phase2; default: BUG(); } @@ -148,13 +147,14 @@ xfs_iomap( if (error) goto out; - switch (flags & (PBF_WRITE|PBF_FILE_ALLOCATE)) { - case PBF_WRITE: +phase2: + switch (flags & (BMAP_WRITE|BMAP_ALLOCATE|BMAP_UNWRITTEN)) { + case BMAP_WRITE: /* If we found an extent, return it */ if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) break; - if (flags & PBF_DIRECT) { + if (flags & (BMAP_DIRECT|BMAP_MMAP)) { error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, count, flags, &imap, &nimaps, nimaps); } else { @@ -162,7 +162,7 @@ xfs_iomap( flags, &imap, &nimaps); } break; - case PBF_FILE_ALLOCATE: + case BMAP_ALLOCATE: /* If we found an extent, return it */ XFS_IUNLOCK(mp, io, lockmode); lockmode = 0; @@ -172,12 +172,17 @@ xfs_iomap( error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); break; + case BMAP_UNWRITTEN: + lockmode = 0; + error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count); + nimaps = 0; + break; } if (nimaps) { *npbmaps = _xfs_imap_to_bmap(io, offset, &imap, pbmapp, nimaps, *npbmaps); - } else { + } else if (npbmaps) { *npbmaps = 0; } @@ -203,13 +208,13 @@ xfs_flush_space( xfs_ilock(ip, XFS_ILOCK_EXCL); *fsynced = 1; } else { - *ioflags |= PBF_SYNC; + *ioflags |= BMAP_SYNC; *fsynced = 2; } return 0; case 1: *fsynced = 2; - *ioflags |= PBF_SYNC; + *ioflags |= BMAP_SYNC; return 0; case 2: xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -228,7 +233,7 @@ xfs_iomap_write_direct( xfs_inode_t *ip, loff_t offset, size_t count, - int ioflag, + int flags, xfs_bmbt_irec_t *ret_imap, int *nmaps, int found) @@ -342,7 +347,7 @@ xfs_iomap_write_direct( xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ihold(tp, ip); - if (offset < ip->i_d.di_size || rt) + if (!(flags & BMAP_MMAP) && (offset < ip->i_d.di_size || rt)) bmapi_flag |= XFS_BMAPI_PREALLOC; /* @@ -441,7 +446,7 @@ retry: * We don't bother with this for sync writes, because we need * to minimize the amount we write for good performance. */ - if (!(ioflag & PBF_SYNC) && ((offset + count) > ip->i_d.di_size)) { + if (!(ioflag & BMAP_SYNC) && ((offset + count) > ip->i_d.di_size)) { xfs_off_t aligned_offset; unsigned int iosize; xfs_fileoff_t ioalign; diff --git a/fs/xfs/pagebuf/page_buf.c b/fs/xfs/pagebuf/page_buf.c index c1b53bfb6967..6b44090ddefc 100644 --- a/fs/xfs/pagebuf/page_buf.c +++ b/fs/xfs/pagebuf/page_buf.c @@ -1575,6 +1575,13 @@ pagebuf_delwri_dequeue( spin_unlock(&pbd_delwrite_lock); } +STATIC void +pagebuf_runall_queues( + struct workqueue_struct *queue) +{ + flush_workqueue(queue); +} + /* Defines for pagebuf daemon */ DECLARE_WAIT_QUEUE_HEAD(pbd_waitq); STATIC int force_flush; @@ -1680,10 +1687,13 @@ pagebuf_delwri_flush( page_buf_t *pb; struct list_head *curr, *next, tmp; int pincount = 0; + int flush_cnt = 0; spin_lock(&pbd_delwrite_lock); INIT_LIST_HEAD(&tmp); + pagebuf_runall_queues(pagebuf_dataio_workqueue); + list_for_each_safe(curr, next, &pbd_delwrite_queue) { pb = list_entry(curr, page_buf_t, pb_list); @@ -1725,6 +1735,10 @@ pagebuf_delwri_flush( pb->pb_flags |= PBF_WRITE; __pagebuf_iorequest(pb); + if (++flush_cnt > 32) { + pagebuf_run_queues(NULL); + flush_cnt = 0; + } spin_lock(&pbd_delwrite_lock); } diff --git a/fs/xfs/pagebuf/page_buf.h b/fs/xfs/pagebuf/page_buf.h index 4d400d0f6583..2a24ba8c6fb0 100644 --- a/fs/xfs/pagebuf/page_buf.h +++ b/fs/xfs/pagebuf/page_buf.h @@ -83,6 +83,20 @@ typedef enum { /* pbm_flags values */ /* but uninitialized file data */ } 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 */ +} bmapi_flags_t; + typedef enum page_buf_flags_e { /* pb_flags values */ PBF_READ = (1 << 0), /* buffer intended for reading from device */ PBF_WRITE = (1 << 1), /* buffer intended for writing to device */ @@ -101,20 +115,18 @@ typedef enum page_buf_flags_e { /* pb_flags values */ /* flags used only as arguments to access routines */ PBF_LOCK = (1 << 13), /* lock requested */ PBF_TRYLOCK = (1 << 14), /* lock requested, but do not wait */ - PBF_FILE_ALLOCATE = (1 << 15), /* allocate all file space */ - PBF_DONT_BLOCK = (1 << 16), /* do not block in current thread */ - PBF_DIRECT = (1 << 17), /* direct I/O desired */ - PBF_FILE_UNWRITTEN = (1 << 18), /* convert unwritten extent space */ + PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread */ /* flags used only internally */ - _PBF_LOCKABLE = (1 << 19), /* page_buf_t may be locked */ - _PBF_ALL_PAGES_MAPPED = (1 << 21), /* all pages in range mapped */ - _PBF_ADDR_ALLOCATED = (1 << 22), /* pb_addr space was allocated */ - _PBF_MEM_ALLOCATED = (1 << 23), /* pb_mem+underlying pages alloc'd */ - - PBF_FORCEIO = (1 << 24), - PBF_FLUSH = (1 << 25), /* flush disk write cache */ - PBF_READ_AHEAD = (1 << 26), + _PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked */ + _PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads */ + _PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped */ + _PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated */ + _PBF_MEM_ALLOCATED = (1 << 20), /* pb_mem+underlying pages alloc'd */ + + PBF_FORCEIO = (1 << 21), + PBF_FLUSH = (1 << 22), /* flush disk write cache */ + PBF_READ_AHEAD = (1 << 23), } page_buf_flags_t; diff --git a/fs/xfs/xfsidbg.c b/fs/xfs/xfsidbg.c index b77b2308cf00..793ca4cab415 100644 --- a/fs/xfs/xfsidbg.c +++ b/fs/xfs/xfsidbg.c @@ -1732,11 +1732,9 @@ static char *pb_flag_vals[] = { /* 0 */ "READ", "WRITE", "MAPPED", "PARTIAL", "ASYNC", /* 5 */ "NONE", "DELWRI", "FREED", "SYNC", "MAPPABLE", /* 10 */ "STALE", "FS_MANAGED", "INVALID12", "LOCK", "TRYLOCK", -/* 15 */ "FILE_ALLOCATE", "DONT_BLOCK", "DIRECT", "INVALID18", "LOCKABLE", -/* 20 */ "PRIVATE_BH", "ALL_PAGES_MAPPED", "ADDR_ALLOCATED", "MEM_ALLOCATED", - "FORCEIO", -/* 25 */ "FLUSH", "READ_AHEAD", "INVALID27", "INVALID28", "INVALID29", -/* 30 */ "INVALID30", "INVALID31", +/* 15 */ "DONT_BLOCK", "LOCKABLE", "PRIVATE_BH", "ALL_PAGES_MAPPED", + "ADDR_ALLOCATED", +/* 20 */ "MEM_ALLOCATED", "FORCEIO", "FLUSH", "READ_AHEAD", NULL }; static char *pbm_flag_vals[] = { |
