Merge branch 'xfs-bug-fixes-for-3.15-2' into for-next

This commit is contained in:
Dave Chinner 2014-03-13 19:13:05 +11:00
Родитель 49ae4b97d7 fe4c224aa1
Коммит 5f44e4c185
8 изменённых файлов: 126 добавлений и 39 удалений

Просмотреть файл

@ -65,12 +65,31 @@ kmem_alloc(size_t size, xfs_km_flags_t flags)
void * void *
kmem_zalloc_large(size_t size, xfs_km_flags_t flags) kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
{ {
unsigned noio_flag = 0;
void *ptr; void *ptr;
gfp_t lflags;
ptr = kmem_zalloc(size, flags | KM_MAYFAIL); ptr = kmem_zalloc(size, flags | KM_MAYFAIL);
if (ptr) if (ptr)
return ptr; return ptr;
return vzalloc(size);
/*
* __vmalloc() will allocate data pages and auxillary structures (e.g.
* pagetables) with GFP_KERNEL, yet we may be under GFP_NOFS context
* here. Hence we need to tell memory reclaim that we are in such a
* context via PF_MEMALLOC_NOIO to prevent memory reclaim re-entering
* the filesystem here and potentially deadlocking.
*/
if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
noio_flag = memalloc_noio_save();
lflags = kmem_flags_convert(flags);
ptr = __vmalloc(size, lflags | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
memalloc_noio_restore(noio_flag);
return ptr;
} }
void void

Просмотреть файл

@ -632,38 +632,46 @@ xfs_map_at_offset(
} }
/* /*
* Test if a given page is suitable for writing as part of an unwritten * Test if a given page contains at least one buffer of a given @type.
* or delayed allocate extent. * If @check_all_buffers is true, then we walk all the buffers in the page to
* try to find one of the type passed in. If it is not set, then the caller only
* needs to check the first buffer on the page for a match.
*/ */
STATIC int STATIC bool
xfs_check_page_type( xfs_check_page_type(
struct page *page, struct page *page,
unsigned int type) unsigned int type,
bool check_all_buffers)
{ {
struct buffer_head *bh;
struct buffer_head *head;
if (PageWriteback(page)) if (PageWriteback(page))
return 0; return false;
if (!page->mapping)
return false;
if (!page_has_buffers(page))
return false;
if (page->mapping && page_has_buffers(page)) { bh = head = page_buffers(page);
struct buffer_head *bh, *head; do {
int acceptable = 0; if (buffer_unwritten(bh)) {
if (type == XFS_IO_UNWRITTEN)
return true;
} else if (buffer_delay(bh)) {
if (type == XFS_IO_DELALLOC);
return true;
} else if (buffer_dirty(bh) && buffer_mapped(bh)) {
if (type == XFS_IO_OVERWRITE);
return true;
}
bh = head = page_buffers(page); /* If we are only checking the first buffer, we are done now. */
do { if (!check_all_buffers)
if (buffer_unwritten(bh)) break;
acceptable += (type == XFS_IO_UNWRITTEN); } while ((bh = bh->b_this_page) != head);
else if (buffer_delay(bh))
acceptable += (type == XFS_IO_DELALLOC);
else if (buffer_dirty(bh) && buffer_mapped(bh))
acceptable += (type == XFS_IO_OVERWRITE);
else
break;
} while ((bh = bh->b_this_page) != head);
if (acceptable) return false;
return 1;
}
return 0;
} }
/* /*
@ -697,7 +705,7 @@ xfs_convert_page(
goto fail_unlock_page; goto fail_unlock_page;
if (page->mapping != inode->i_mapping) if (page->mapping != inode->i_mapping)
goto fail_unlock_page; goto fail_unlock_page;
if (!xfs_check_page_type(page, (*ioendp)->io_type)) if (!xfs_check_page_type(page, (*ioendp)->io_type, false))
goto fail_unlock_page; goto fail_unlock_page;
/* /*
@ -742,6 +750,15 @@ xfs_convert_page(
p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE;
page_dirty = p_offset / len; page_dirty = p_offset / len;
/*
* The moment we find a buffer that doesn't match our current type
* specification or can't be written, abort the loop and start
* writeback. As per the above xfs_imap_valid() check, only
* xfs_vm_writepage() can handle partial page writeback fully - we are
* limited here to the buffers that are contiguous with the current
* ioend, and hence a buffer we can't write breaks that contiguity and
* we have to defer the rest of the IO to xfs_vm_writepage().
*/
bh = head = page_buffers(page); bh = head = page_buffers(page);
do { do {
if (offset >= end_offset) if (offset >= end_offset)
@ -750,7 +767,7 @@ xfs_convert_page(
uptodate = 0; uptodate = 0;
if (!(PageUptodate(page) || buffer_uptodate(bh))) { if (!(PageUptodate(page) || buffer_uptodate(bh))) {
done = 1; done = 1;
continue; break;
} }
if (buffer_unwritten(bh) || buffer_delay(bh) || if (buffer_unwritten(bh) || buffer_delay(bh) ||
@ -762,10 +779,11 @@ xfs_convert_page(
else else
type = XFS_IO_OVERWRITE; type = XFS_IO_OVERWRITE;
if (!xfs_imap_valid(inode, imap, offset)) { /*
done = 1; * imap should always be valid because of the above
continue; * partial page end_offset check on the imap.
} */
ASSERT(xfs_imap_valid(inode, imap, offset));
lock_buffer(bh); lock_buffer(bh);
if (type != XFS_IO_OVERWRITE) if (type != XFS_IO_OVERWRITE)
@ -777,6 +795,7 @@ xfs_convert_page(
count++; count++;
} else { } else {
done = 1; done = 1;
break;
} }
} while (offset += len, (bh = bh->b_this_page) != head); } while (offset += len, (bh = bh->b_this_page) != head);
@ -868,7 +887,7 @@ xfs_aops_discard_page(
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
loff_t offset = page_offset(page); loff_t offset = page_offset(page);
if (!xfs_check_page_type(page, XFS_IO_DELALLOC)) if (!xfs_check_page_type(page, XFS_IO_DELALLOC, true))
goto out_invalidate; goto out_invalidate;
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) if (XFS_FORCED_SHUTDOWN(ip->i_mount))

Просмотреть файл

@ -396,7 +396,17 @@ _xfs_buf_map_pages(
bp->b_addr = NULL; bp->b_addr = NULL;
} else { } else {
int retried = 0; int retried = 0;
unsigned noio_flag;
/*
* vm_map_ram() will allocate auxillary structures (e.g.
* pagetables) with GFP_KERNEL, yet we are likely to be under
* GFP_NOFS context here. Hence we need to tell memory reclaim
* that we are in such a context via PF_MEMALLOC_NOIO to prevent
* memory reclaim re-entering the filesystem here and
* potentially deadlocking.
*/
noio_flag = memalloc_noio_save();
do { do {
bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count, bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
-1, PAGE_KERNEL); -1, PAGE_KERNEL);
@ -404,6 +414,7 @@ _xfs_buf_map_pages(
break; break;
vm_unmap_aliases(); vm_unmap_aliases();
} while (retried++ <= 1); } while (retried++ <= 1);
memalloc_noio_restore(noio_flag);
if (!bp->b_addr) if (!bp->b_addr)
return -ENOMEM; return -ENOMEM;

Просмотреть файл

@ -363,6 +363,18 @@ xfs_ialloc_ag_alloc(
args.minleft = args.mp->m_in_maxlevels - 1; args.minleft = args.mp->m_in_maxlevels - 1;
if ((error = xfs_alloc_vextent(&args))) if ((error = xfs_alloc_vextent(&args)))
return error; return error;
/*
* This request might have dirtied the transaction if the AG can
* satisfy the request, but the exact block was not available.
* If the allocation did fail, subsequent requests will relax
* the exact agbno requirement and increase the alignment
* instead. It is critical that the total size of the request
* (len + alignment + slop) does not increase from this point
* on, so reset minalignslop to ensure it is not included in
* subsequent requests.
*/
args.minalignslop = 0;
} else } else
args.fsbno = NULLFSBLOCK; args.fsbno = NULLFSBLOCK;

Просмотреть файл

@ -314,6 +314,9 @@ reread:
error = bp->b_error; error = bp->b_error;
if (loud) if (loud)
xfs_warn(mp, "SB validate failed with error %d.", error); xfs_warn(mp, "SB validate failed with error %d.", error);
/* bad CRC means corrupted metadata */
if (error == EFSBADCRC)
error = EFSCORRUPTED;
goto release_buf; goto release_buf;
} }

Просмотреть файл

@ -80,6 +80,10 @@ xfs_readlink_bmap(
if (error) { if (error) {
xfs_buf_ioerror_alert(bp, __func__); xfs_buf_ioerror_alert(bp, __func__);
xfs_buf_relse(bp); xfs_buf_relse(bp);
/* bad CRC means corrupted metadata */
if (error == EFSBADCRC)
error = EFSCORRUPTED;
goto out; goto out;
} }
byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt); byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);

Просмотреть файл

@ -275,6 +275,10 @@ xfs_trans_read_buf_map(
XFS_BUF_UNDONE(bp); XFS_BUF_UNDONE(bp);
xfs_buf_stale(bp); xfs_buf_stale(bp);
xfs_buf_relse(bp); xfs_buf_relse(bp);
/* bad CRC means corrupted metadata */
if (error == EFSBADCRC)
error = EFSCORRUPTED;
return error; return error;
} }
#ifdef DEBUG #ifdef DEBUG
@ -338,6 +342,9 @@ xfs_trans_read_buf_map(
if (tp->t_flags & XFS_TRANS_DIRTY) if (tp->t_flags & XFS_TRANS_DIRTY)
xfs_force_shutdown(tp->t_mountp, xfs_force_shutdown(tp->t_mountp,
SHUTDOWN_META_IO_ERROR); SHUTDOWN_META_IO_ERROR);
/* bad CRC means corrupted metadata */
if (error == EFSBADCRC)
error = EFSCORRUPTED;
return error; return error;
} }
} }
@ -375,6 +382,10 @@ xfs_trans_read_buf_map(
if (tp->t_flags & XFS_TRANS_DIRTY) if (tp->t_flags & XFS_TRANS_DIRTY)
xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
xfs_buf_relse(bp); xfs_buf_relse(bp);
/* bad CRC means corrupted metadata */
if (error == EFSBADCRC)
error = EFSCORRUPTED;
return error; return error;
} }
#ifdef DEBUG #ifdef DEBUG

Просмотреть файл

@ -81,20 +81,28 @@ xfs_calc_buf_res(
* on disk. Hence we need an inode reservation function that calculates all this * on disk. Hence we need an inode reservation function that calculates all this
* correctly. So, we log: * correctly. So, we log:
* *
* - log op headers for object * - 4 log op headers for object
* - for the ilf, the inode core and 2 forks
* - inode log format object * - inode log format object
* - the entire inode contents (core + 2 forks) * - the inode core
* - two bmap btree block headers * - two inode forks containing bmap btree root blocks.
* - the btree data contained by both forks will fit into the inode size,
* hence when combined with the inode core above, we have a total of the
* actual inode size.
* - the BMBT headers need to be accounted separately, as they are
* additional to the records and pointers that fit inside the inode
* forks.
*/ */
STATIC uint STATIC uint
xfs_calc_inode_res( xfs_calc_inode_res(
struct xfs_mount *mp, struct xfs_mount *mp,
uint ninodes) uint ninodes)
{ {
return ninodes * (sizeof(struct xlog_op_header) + return ninodes *
sizeof(struct xfs_inode_log_format) + (4 * sizeof(struct xlog_op_header) +
mp->m_sb.sb_inodesize + sizeof(struct xfs_inode_log_format) +
2 * XFS_BMBT_BLOCK_LEN(mp)); mp->m_sb.sb_inodesize +
2 * XFS_BMBT_BLOCK_LEN(mp));
} }
/* /*