Commit f96736e1 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-v3.8-rc6' of git://oss.sgi.com/xfs/xfs

Pull xfs bugfixes from Ben Myers:
 "Here are fixes for returning EFSCORRUPTED on probe of a non-xfs
  filesystem, the stack switch in xfs_bmapi_allocate, a crash in
  _xfs_buf_find, speculative preallocation as the filesystem nears
  ENOSPC, an unmount hang, a race with AIO, and a regression with
  xfs_fsr:

   - fix return value when filesystem probe finds no XFS magic, a
     regression introduced in 98021821.

   - fix stack switch in __xfs_bmapi_allocate by moving the check for
     stack switch up into xfs_bmapi_write.

   - fix oops in _xfs_buf_find by validating that the requested block is
     within the filesystem bounds.

   - limit speculative preallocation near ENOSPC.

   - fix an unmount hang in xfs_wait_buftarg by freeing the
     xfs_buf_log_item in xfs_buf_item_unlock.

   - fix a possible use after free with AIO.

   - fix xfs_swap_extents after removal of xfs_flushinval_pages, a
     regression introduced in commit fb595814."

* tag 'for-linus-v3.8-rc6' of git://oss.sgi.com/xfs/xfs:
  xfs: Fix xfs_swap_extents() after removal of xfs_flushinval_pages()
  xfs: Fix possible use-after-free with AIO
  xfs: fix shutdown hang on invalid inode during create
  xfs: limit speculative prealloc near ENOSPC thresholds
  xfs: fix _xfs_buf_find oops on blocks beyond the filesystem end
  xfs: pull up stack_switch check into xfs_bmapi_write
  xfs: Do not return EFSCORRUPTED when filesystem probe finds no XFS magic
parents 8e5d573a 65e3aa77
...@@ -86,11 +86,11 @@ xfs_destroy_ioend( ...@@ -86,11 +86,11 @@ xfs_destroy_ioend(
} }
if (ioend->io_iocb) { if (ioend->io_iocb) {
inode_dio_done(ioend->io_inode);
if (ioend->io_isasync) { if (ioend->io_isasync) {
aio_complete(ioend->io_iocb, ioend->io_error ? aio_complete(ioend->io_iocb, ioend->io_error ?
ioend->io_error : ioend->io_result, 0); ioend->io_error : ioend->io_result, 0);
} }
inode_dio_done(ioend->io_inode);
} }
mempool_free(ioend, xfs_ioend_pool); mempool_free(ioend, xfs_ioend_pool);
......
...@@ -4680,9 +4680,6 @@ __xfs_bmapi_allocate( ...@@ -4680,9 +4680,6 @@ __xfs_bmapi_allocate(
return error; return error;
} }
if (bma->flags & XFS_BMAPI_STACK_SWITCH)
bma->stack_switch = 1;
error = xfs_bmap_alloc(bma); error = xfs_bmap_alloc(bma);
if (error) if (error)
return error; return error;
...@@ -4956,6 +4953,9 @@ xfs_bmapi_write( ...@@ -4956,6 +4953,9 @@ xfs_bmapi_write(
bma.flist = flist; bma.flist = flist;
bma.firstblock = firstblock; bma.firstblock = firstblock;
if (flags & XFS_BMAPI_STACK_SWITCH)
bma.stack_switch = 1;
while (bno < end && n < *nmap) { while (bno < end && n < *nmap) {
inhole = eof || bma.got.br_startoff > bno; inhole = eof || bma.got.br_startoff > bno;
wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
......
...@@ -487,6 +487,7 @@ _xfs_buf_find( ...@@ -487,6 +487,7 @@ _xfs_buf_find(
struct rb_node *parent; struct rb_node *parent;
xfs_buf_t *bp; xfs_buf_t *bp;
xfs_daddr_t blkno = map[0].bm_bn; xfs_daddr_t blkno = map[0].bm_bn;
xfs_daddr_t eofs;
int numblks = 0; int numblks = 0;
int i; int i;
...@@ -498,6 +499,23 @@ _xfs_buf_find( ...@@ -498,6 +499,23 @@ _xfs_buf_find(
ASSERT(!(numbytes < (1 << btp->bt_sshift))); ASSERT(!(numbytes < (1 << btp->bt_sshift)));
ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_smask)); ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_smask));
/*
* Corrupted block numbers can get through to here, unfortunately, so we
* have to check that the buffer falls within the filesystem bounds.
*/
eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks);
if (blkno >= eofs) {
/*
* XXX (dgc): we should really be returning EFSCORRUPTED here,
* but none of the higher level infrastructure supports
* returning a specific error on buffer lookup failures.
*/
xfs_alert(btp->bt_mount,
"%s: Block out of range: block 0x%llx, EOFS 0x%llx ",
__func__, blkno, eofs);
return NULL;
}
/* get tree root */ /* get tree root */
pag = xfs_perag_get(btp->bt_mount, pag = xfs_perag_get(btp->bt_mount,
xfs_daddr_to_agno(btp->bt_mount, blkno)); xfs_daddr_to_agno(btp->bt_mount, blkno));
...@@ -1487,6 +1505,8 @@ xfs_wait_buftarg( ...@@ -1487,6 +1505,8 @@ xfs_wait_buftarg(
while (!list_empty(&btp->bt_lru)) { while (!list_empty(&btp->bt_lru)) {
bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru); bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru);
if (atomic_read(&bp->b_hold) > 1) { if (atomic_read(&bp->b_hold) > 1) {
trace_xfs_buf_wait_buftarg(bp, _RET_IP_);
list_move_tail(&bp->b_lru, &btp->bt_lru);
spin_unlock(&btp->bt_lru_lock); spin_unlock(&btp->bt_lru_lock);
delay(100); delay(100);
goto restart; goto restart;
......
...@@ -652,7 +652,10 @@ xfs_buf_item_unlock( ...@@ -652,7 +652,10 @@ xfs_buf_item_unlock(
/* /*
* If the buf item isn't tracking any data, free it, otherwise drop the * If the buf item isn't tracking any data, free it, otherwise drop the
* reference we hold to it. * reference we hold to it. If we are aborting the transaction, this may
* be the only reference to the buf item, so we free it anyway
* regardless of whether it is dirty or not. A dirty abort implies a
* shutdown, anyway.
*/ */
clean = 1; clean = 1;
for (i = 0; i < bip->bli_format_count; i++) { for (i = 0; i < bip->bli_format_count; i++) {
...@@ -664,7 +667,12 @@ xfs_buf_item_unlock( ...@@ -664,7 +667,12 @@ xfs_buf_item_unlock(
} }
if (clean) if (clean)
xfs_buf_item_relse(bp); xfs_buf_item_relse(bp);
else else if (aborted) {
if (atomic_dec_and_test(&bip->bli_refcount)) {
ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
xfs_buf_item_relse(bp);
}
} else
atomic_dec(&bip->bli_refcount); atomic_dec(&bip->bli_refcount);
if (!hold) if (!hold)
......
...@@ -246,10 +246,10 @@ xfs_swap_extents( ...@@ -246,10 +246,10 @@ xfs_swap_extents(
goto out_unlock; goto out_unlock;
} }
error = -filemap_write_and_wait(VFS_I(ip)->i_mapping); error = -filemap_write_and_wait(VFS_I(tip)->i_mapping);
if (error) if (error)
goto out_unlock; goto out_unlock;
truncate_pagecache_range(VFS_I(ip), 0, -1); truncate_pagecache_range(VFS_I(tip), 0, -1);
/* Verify O_DIRECT for ftmp */ /* Verify O_DIRECT for ftmp */
if (VN_CACHED(VFS_I(tip)) != 0) { if (VN_CACHED(VFS_I(tip)) != 0) {
......
...@@ -351,6 +351,15 @@ xfs_iomap_prealloc_size( ...@@ -351,6 +351,15 @@ xfs_iomap_prealloc_size(
} }
if (shift) if (shift)
alloc_blocks >>= shift; alloc_blocks >>= shift;
/*
* If we are still trying to allocate more space than is
* available, squash the prealloc hard. This can happen if we
* have a large file on a small filesystem and the above
* lowspace thresholds are smaller than MAXEXTLEN.
*/
while (alloc_blocks >= freesp)
alloc_blocks >>= 4;
} }
if (alloc_blocks < mp->m_writeio_blocks) if (alloc_blocks < mp->m_writeio_blocks)
......
...@@ -658,7 +658,7 @@ xfs_sb_quiet_read_verify( ...@@ -658,7 +658,7 @@ xfs_sb_quiet_read_verify(
return; return;
} }
/* quietly fail */ /* quietly fail */
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EWRONGFS);
} }
static void static void
......
...@@ -341,6 +341,7 @@ DEFINE_BUF_EVENT(xfs_buf_item_relse); ...@@ -341,6 +341,7 @@ DEFINE_BUF_EVENT(xfs_buf_item_relse);
DEFINE_BUF_EVENT(xfs_buf_item_iodone); DEFINE_BUF_EVENT(xfs_buf_item_iodone);
DEFINE_BUF_EVENT(xfs_buf_item_iodone_async); DEFINE_BUF_EVENT(xfs_buf_item_iodone_async);
DEFINE_BUF_EVENT(xfs_buf_error_relse); DEFINE_BUF_EVENT(xfs_buf_error_relse);
DEFINE_BUF_EVENT(xfs_buf_wait_buftarg);
DEFINE_BUF_EVENT(xfs_trans_read_buf_io); DEFINE_BUF_EVENT(xfs_trans_read_buf_io);
DEFINE_BUF_EVENT(xfs_trans_read_buf_shut); DEFINE_BUF_EVENT(xfs_trans_read_buf_shut);
......
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