xfs: bugfixes for 3.8-rc6
- fix return value when filesystem probe finds no XFS magic, a regression introduced in9802182
. - 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 infb59581404
. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJRBvmgAAoJENaLyazVq6ZOOacP/RilCPsi41NkJqRx1Rs5aRGE UvinrHfAL/tBupS2JVo1niIilBNJG/cI+lLcpV/P5omLBJfpEu0trzZUSxU7S1Vc a2M8J0qhmKfBcl70fuCALAxPY52895y+44gufxaH0O5HQDN6tB8n4MMqYGPmS8hz Ul/q3MO601hVyBHaoYa7BNGS3YG0TCdFGtWcC5tQaR3v7upTLR2ouZrGQ8CV0BBa Ek1xdxLh4D0fRybSL7lUw64W957iyldoLsEg+zQrE9NSfTE8DSqUG+NPWB0wjPce ICtmO6TbE5c6q1ScOL3YCC2cmYvjR9mlAHnPy73SqWSIsTqUsVzdibNo+tUJJZ5r RZf3u6Uri6uKC6Hl4XEtg4LVnnquKosTXfoiHmn+eh0dhYL7sZG0Ya5we5pH5Tmi P6B2DlfUA1fj4Ne4Asx2d7mwOJaZcLHDZoeCs/Haz2Z6kGVEm7ImyAb1h76uNOZo l0NFhXJGcOQLyjPtQjl81SGjQmntiIN0Poia3528zjxxGXlBNwAwalkOtdJnk5iN IaYRKtvIcrdjFvunasiKZIsV/O9w3/mguXlrSqBDgUsKPUc/cq5vLfsa70jYGc2j M6ldJRRqTvSjkVXc/7SXv4GLt/qbUWa92ESzhZQXEABIjZJUnOZpZuLmSVdRUyZk +SaGvbMphE0U/4ps3pO/ =wViN -----END PGP SIGNATURE----- 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 in9802182
. - 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 fb59581404a." * 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
This commit is contained in:
Коммит
f96736e1ba
|
@ -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(
|
||||||
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(
|
||||||
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(
|
||||||
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(
|
||||||
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 @@ restart:
|
||||||
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(
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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(
|
||||||
}
|
}
|
||||||
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(
|
||||||
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(
|
||||||
}
|
}
|
||||||
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(
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче