diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_aops.c')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 1499 | 
1 files changed, 0 insertions, 1499 deletions
| diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c deleted file mode 100644 index 63e971e2b837..000000000000 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ /dev/null @@ -1,1499 +0,0 @@ -/* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA - */ -#include "xfs.h" -#include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_inum.h" -#include "xfs_sb.h" -#include "xfs_ag.h" -#include "xfs_trans.h" -#include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_alloc.h" -#include "xfs_error.h" -#include "xfs_rw.h" -#include "xfs_iomap.h" -#include "xfs_vnodeops.h" -#include "xfs_trace.h" -#include "xfs_bmap.h" -#include <linux/gfp.h> -#include <linux/mpage.h> -#include <linux/pagevec.h> -#include <linux/writeback.h> - - -/* - * Prime number of hash buckets since address is used as the key. - */ -#define NVSYNC		37 -#define to_ioend_wq(v)	(&xfs_ioend_wq[((unsigned long)v) % NVSYNC]) -static wait_queue_head_t xfs_ioend_wq[NVSYNC]; - -void __init -xfs_ioend_init(void) -{ -	int i; - -	for (i = 0; i < NVSYNC; i++) -		init_waitqueue_head(&xfs_ioend_wq[i]); -} - -void -xfs_ioend_wait( -	xfs_inode_t	*ip) -{ -	wait_queue_head_t *wq = to_ioend_wq(ip); - -	wait_event(*wq, (atomic_read(&ip->i_iocount) == 0)); -} - -STATIC void -xfs_ioend_wake( -	xfs_inode_t	*ip) -{ -	if (atomic_dec_and_test(&ip->i_iocount)) -		wake_up(to_ioend_wq(ip)); -} - -void -xfs_count_page_state( -	struct page		*page, -	int			*delalloc, -	int			*unwritten) -{ -	struct buffer_head	*bh, *head; - -	*delalloc = *unwritten = 0; - -	bh = head = page_buffers(page); -	do { -		if (buffer_unwritten(bh)) -			(*unwritten) = 1; -		else if (buffer_delay(bh)) -			(*delalloc) = 1; -	} while ((bh = bh->b_this_page) != head); -} - -STATIC struct block_device * -xfs_find_bdev_for_inode( -	struct inode		*inode) -{ -	struct xfs_inode	*ip = XFS_I(inode); -	struct xfs_mount	*mp = ip->i_mount; - -	if (XFS_IS_REALTIME_INODE(ip)) -		return mp->m_rtdev_targp->bt_bdev; -	else -		return mp->m_ddev_targp->bt_bdev; -} - -/* - * We're now finished for good with this ioend structure. - * Update the page state via the associated buffer_heads, - * release holds on the inode and bio, and finally free - * up memory.  Do not use the ioend after this. - */ -STATIC void -xfs_destroy_ioend( -	xfs_ioend_t		*ioend) -{ -	struct buffer_head	*bh, *next; -	struct xfs_inode	*ip = XFS_I(ioend->io_inode); - -	for (bh = ioend->io_buffer_head; bh; bh = next) { -		next = bh->b_private; -		bh->b_end_io(bh, !ioend->io_error); -	} - -	/* -	 * Volume managers supporting multiple paths can send back ENODEV -	 * when the final path disappears.  In this case continuing to fill -	 * the page cache with dirty data which cannot be written out is -	 * evil, so prevent that. -	 */ -	if (unlikely(ioend->io_error == -ENODEV)) { -		xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, -				      __FILE__, __LINE__); -	} - -	xfs_ioend_wake(ip); -	mempool_free(ioend, xfs_ioend_pool); -} - -/* - * If the end of the current ioend is beyond the current EOF, - * return the new EOF value, otherwise zero. - */ -STATIC xfs_fsize_t -xfs_ioend_new_eof( -	xfs_ioend_t		*ioend) -{ -	xfs_inode_t		*ip = XFS_I(ioend->io_inode); -	xfs_fsize_t		isize; -	xfs_fsize_t		bsize; - -	bsize = ioend->io_offset + ioend->io_size; -	isize = MAX(ip->i_size, ip->i_new_size); -	isize = MIN(isize, bsize); -	return isize > ip->i_d.di_size ? isize : 0; -} - -/* - * Update on-disk file size now that data has been written to disk.  The - * current in-memory file size is i_size.  If a write is beyond eof i_new_size - * will be the intended file size until i_size is updated.  If this write does - * not extend all the way to the valid file size then restrict this update to - * the end of the write. - * - * This function does not block as blocking on the inode lock in IO completion - * can lead to IO completion order dependency deadlocks.. If it can't get the - * inode ilock it will return EAGAIN. Callers must handle this. - */ -STATIC int -xfs_setfilesize( -	xfs_ioend_t		*ioend) -{ -	xfs_inode_t		*ip = XFS_I(ioend->io_inode); -	xfs_fsize_t		isize; - -	if (unlikely(ioend->io_error)) -		return 0; - -	if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) -		return EAGAIN; - -	isize = xfs_ioend_new_eof(ioend); -	if (isize) { -		trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size); -		ip->i_d.di_size = isize; -		xfs_mark_inode_dirty(ip); -	} - -	xfs_iunlock(ip, XFS_ILOCK_EXCL); -	return 0; -} - -/* - * Schedule IO completion handling on the final put of an ioend. - */ -STATIC void -xfs_finish_ioend( -	struct xfs_ioend	*ioend) -{ -	if (atomic_dec_and_test(&ioend->io_remaining)) { -		if (ioend->io_type == IO_UNWRITTEN) -			queue_work(xfsconvertd_workqueue, &ioend->io_work); -		else -			queue_work(xfsdatad_workqueue, &ioend->io_work); -	} -} - -/* - * IO write completion. - */ -STATIC void -xfs_end_io( -	struct work_struct *work) -{ -	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work); -	struct xfs_inode *ip = XFS_I(ioend->io_inode); -	int		error = 0; - -	/* -	 * For unwritten extents we need to issue transactions to convert a -	 * range to normal written extens after the data I/O has finished. -	 */ -	if (ioend->io_type == IO_UNWRITTEN && -	    likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) { - -		error = xfs_iomap_write_unwritten(ip, ioend->io_offset, -						 ioend->io_size); -		if (error) -			ioend->io_error = error; -	} - -	/* -	 * We might have to update the on-disk file size after extending -	 * writes. -	 */ -	error = xfs_setfilesize(ioend); -	ASSERT(!error || error == EAGAIN); - -	/* -	 * If we didn't complete processing of the ioend, requeue it to the -	 * tail of the workqueue for another attempt later. Otherwise destroy -	 * it. -	 */ -	if (error == EAGAIN) { -		atomic_inc(&ioend->io_remaining); -		xfs_finish_ioend(ioend); -		/* ensure we don't spin on blocked ioends */ -		delay(1); -	} else { -		if (ioend->io_iocb) -			aio_complete(ioend->io_iocb, ioend->io_result, 0); -		xfs_destroy_ioend(ioend); -	} -} - -/* - * Call IO completion handling in caller context on the final put of an ioend. - */ -STATIC void -xfs_finish_ioend_sync( -	struct xfs_ioend	*ioend) -{ -	if (atomic_dec_and_test(&ioend->io_remaining)) -		xfs_end_io(&ioend->io_work); -} - -/* - * Allocate and initialise an IO completion structure. - * We need to track unwritten extent write completion here initially. - * We'll need to extend this for updating the ondisk inode size later - * (vs. incore size). - */ -STATIC xfs_ioend_t * -xfs_alloc_ioend( -	struct inode		*inode, -	unsigned int		type) -{ -	xfs_ioend_t		*ioend; - -	ioend = mempool_alloc(xfs_ioend_pool, GFP_NOFS); - -	/* -	 * Set the count to 1 initially, which will prevent an I/O -	 * completion callback from happening before we have started -	 * all the I/O from calling the completion routine too early. -	 */ -	atomic_set(&ioend->io_remaining, 1); -	ioend->io_error = 0; -	ioend->io_list = NULL; -	ioend->io_type = type; -	ioend->io_inode = inode; -	ioend->io_buffer_head = NULL; -	ioend->io_buffer_tail = NULL; -	atomic_inc(&XFS_I(ioend->io_inode)->i_iocount); -	ioend->io_offset = 0; -	ioend->io_size = 0; -	ioend->io_iocb = NULL; -	ioend->io_result = 0; - -	INIT_WORK(&ioend->io_work, xfs_end_io); -	return ioend; -} - -STATIC int -xfs_map_blocks( -	struct inode		*inode, -	loff_t			offset, -	struct xfs_bmbt_irec	*imap, -	int			type, -	int			nonblocking) -{ -	struct xfs_inode	*ip = XFS_I(inode); -	struct xfs_mount	*mp = ip->i_mount; -	ssize_t			count = 1 << inode->i_blkbits; -	xfs_fileoff_t		offset_fsb, end_fsb; -	int			error = 0; -	int			bmapi_flags = XFS_BMAPI_ENTIRE; -	int			nimaps = 1; - -	if (XFS_FORCED_SHUTDOWN(mp)) -		return -XFS_ERROR(EIO); - -	if (type == IO_UNWRITTEN) -		bmapi_flags |= XFS_BMAPI_IGSTATE; - -	if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { -		if (nonblocking) -			return -XFS_ERROR(EAGAIN); -		xfs_ilock(ip, XFS_ILOCK_SHARED); -	} - -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || -	       (ip->i_df.if_flags & XFS_IFEXTENTS)); -	ASSERT(offset <= mp->m_maxioffset); - -	if (offset + count > mp->m_maxioffset) -		count = mp->m_maxioffset - offset; -	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); -	offset_fsb = XFS_B_TO_FSBT(mp, offset); -	error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, -			  bmapi_flags,  NULL, 0, imap, &nimaps, NULL); -	xfs_iunlock(ip, XFS_ILOCK_SHARED); - -	if (error) -		return -XFS_ERROR(error); - -	if (type == IO_DELALLOC && -	    (!nimaps || isnullstartblock(imap->br_startblock))) { -		error = xfs_iomap_write_allocate(ip, offset, count, imap); -		if (!error) -			trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); -		return -XFS_ERROR(error); -	} - -#ifdef DEBUG -	if (type == IO_UNWRITTEN) { -		ASSERT(nimaps); -		ASSERT(imap->br_startblock != HOLESTARTBLOCK); -		ASSERT(imap->br_startblock != DELAYSTARTBLOCK); -	} -#endif -	if (nimaps) -		trace_xfs_map_blocks_found(ip, offset, count, type, imap); -	return 0; -} - -STATIC int -xfs_imap_valid( -	struct inode		*inode, -	struct xfs_bmbt_irec	*imap, -	xfs_off_t		offset) -{ -	offset >>= inode->i_blkbits; - -	return offset >= imap->br_startoff && -		offset < imap->br_startoff + imap->br_blockcount; -} - -/* - * BIO completion handler for buffered IO. - */ -STATIC void -xfs_end_bio( -	struct bio		*bio, -	int			error) -{ -	xfs_ioend_t		*ioend = bio->bi_private; - -	ASSERT(atomic_read(&bio->bi_cnt) >= 1); -	ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error; - -	/* Toss bio and pass work off to an xfsdatad thread */ -	bio->bi_private = NULL; -	bio->bi_end_io = NULL; -	bio_put(bio); - -	xfs_finish_ioend(ioend); -} - -STATIC void -xfs_submit_ioend_bio( -	struct writeback_control *wbc, -	xfs_ioend_t		*ioend, -	struct bio		*bio) -{ -	atomic_inc(&ioend->io_remaining); -	bio->bi_private = ioend; -	bio->bi_end_io = xfs_end_bio; - -	/* -	 * If the I/O is beyond EOF we mark the inode dirty immediately -	 * but don't update the inode size until I/O completion. -	 */ -	if (xfs_ioend_new_eof(ioend)) -		xfs_mark_inode_dirty(XFS_I(ioend->io_inode)); - -	submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio); -} - -STATIC struct bio * -xfs_alloc_ioend_bio( -	struct buffer_head	*bh) -{ -	int			nvecs = bio_get_nr_vecs(bh->b_bdev); -	struct bio		*bio = bio_alloc(GFP_NOIO, nvecs); - -	ASSERT(bio->bi_private == NULL); -	bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); -	bio->bi_bdev = bh->b_bdev; -	return bio; -} - -STATIC void -xfs_start_buffer_writeback( -	struct buffer_head	*bh) -{ -	ASSERT(buffer_mapped(bh)); -	ASSERT(buffer_locked(bh)); -	ASSERT(!buffer_delay(bh)); -	ASSERT(!buffer_unwritten(bh)); - -	mark_buffer_async_write(bh); -	set_buffer_uptodate(bh); -	clear_buffer_dirty(bh); -} - -STATIC void -xfs_start_page_writeback( -	struct page		*page, -	int			clear_dirty, -	int			buffers) -{ -	ASSERT(PageLocked(page)); -	ASSERT(!PageWriteback(page)); -	if (clear_dirty) -		clear_page_dirty_for_io(page); -	set_page_writeback(page); -	unlock_page(page); -	/* If no buffers on the page are to be written, finish it here */ -	if (!buffers) -		end_page_writeback(page); -} - -static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) -{ -	return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); -} - -/* - * Submit all of the bios for all of the ioends we have saved up, covering the - * initial writepage page and also any probed pages. - * - * Because we may have multiple ioends spanning a page, we need to start - * writeback on all the buffers before we submit them for I/O. If we mark the - * buffers as we got, then we can end up with a page that only has buffers - * marked async write and I/O complete on can occur before we mark the other - * buffers async write. - * - * The end result of this is that we trip a bug in end_page_writeback() because - * we call it twice for the one page as the code in end_buffer_async_write() - * assumes that all buffers on the page are started at the same time. - * - * The fix is two passes across the ioend list - one to start writeback on the - * buffer_heads, and then submit them for I/O on the second pass. - */ -STATIC void -xfs_submit_ioend( -	struct writeback_control *wbc, -	xfs_ioend_t		*ioend) -{ -	xfs_ioend_t		*head = ioend; -	xfs_ioend_t		*next; -	struct buffer_head	*bh; -	struct bio		*bio; -	sector_t		lastblock = 0; - -	/* Pass 1 - start writeback */ -	do { -		next = ioend->io_list; -		for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) -			xfs_start_buffer_writeback(bh); -	} while ((ioend = next) != NULL); - -	/* Pass 2 - submit I/O */ -	ioend = head; -	do { -		next = ioend->io_list; -		bio = NULL; - -		for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { - -			if (!bio) { - retry: -				bio = xfs_alloc_ioend_bio(bh); -			} else if (bh->b_blocknr != lastblock + 1) { -				xfs_submit_ioend_bio(wbc, ioend, bio); -				goto retry; -			} - -			if (bio_add_buffer(bio, bh) != bh->b_size) { -				xfs_submit_ioend_bio(wbc, ioend, bio); -				goto retry; -			} - -			lastblock = bh->b_blocknr; -		} -		if (bio) -			xfs_submit_ioend_bio(wbc, ioend, bio); -		xfs_finish_ioend(ioend); -	} while ((ioend = next) != NULL); -} - -/* - * Cancel submission of all buffer_heads so far in this endio. - * Toss the endio too.  Only ever called for the initial page - * in a writepage request, so only ever one page. - */ -STATIC void -xfs_cancel_ioend( -	xfs_ioend_t		*ioend) -{ -	xfs_ioend_t		*next; -	struct buffer_head	*bh, *next_bh; - -	do { -		next = ioend->io_list; -		bh = ioend->io_buffer_head; -		do { -			next_bh = bh->b_private; -			clear_buffer_async_write(bh); -			unlock_buffer(bh); -		} while ((bh = next_bh) != NULL); - -		xfs_ioend_wake(XFS_I(ioend->io_inode)); -		mempool_free(ioend, xfs_ioend_pool); -	} while ((ioend = next) != NULL); -} - -/* - * Test to see if we've been building up a completion structure for - * earlier buffers -- if so, we try to append to this ioend if we - * can, otherwise we finish off any current ioend and start another. - * Return true if we've finished the given ioend. - */ -STATIC void -xfs_add_to_ioend( -	struct inode		*inode, -	struct buffer_head	*bh, -	xfs_off_t		offset, -	unsigned int		type, -	xfs_ioend_t		**result, -	int			need_ioend) -{ -	xfs_ioend_t		*ioend = *result; - -	if (!ioend || need_ioend || type != ioend->io_type) { -		xfs_ioend_t	*previous = *result; - -		ioend = xfs_alloc_ioend(inode, type); -		ioend->io_offset = offset; -		ioend->io_buffer_head = bh; -		ioend->io_buffer_tail = bh; -		if (previous) -			previous->io_list = ioend; -		*result = ioend; -	} else { -		ioend->io_buffer_tail->b_private = bh; -		ioend->io_buffer_tail = bh; -	} - -	bh->b_private = NULL; -	ioend->io_size += bh->b_size; -} - -STATIC void -xfs_map_buffer( -	struct inode		*inode, -	struct buffer_head	*bh, -	struct xfs_bmbt_irec	*imap, -	xfs_off_t		offset) -{ -	sector_t		bn; -	struct xfs_mount	*m = XFS_I(inode)->i_mount; -	xfs_off_t		iomap_offset = XFS_FSB_TO_B(m, imap->br_startoff); -	xfs_daddr_t		iomap_bn = xfs_fsb_to_db(XFS_I(inode), imap->br_startblock); - -	ASSERT(imap->br_startblock != HOLESTARTBLOCK); -	ASSERT(imap->br_startblock != DELAYSTARTBLOCK); - -	bn = (iomap_bn >> (inode->i_blkbits - BBSHIFT)) + -	      ((offset - iomap_offset) >> inode->i_blkbits); - -	ASSERT(bn || XFS_IS_REALTIME_INODE(XFS_I(inode))); - -	bh->b_blocknr = bn; -	set_buffer_mapped(bh); -} - -STATIC void -xfs_map_at_offset( -	struct inode		*inode, -	struct buffer_head	*bh, -	struct xfs_bmbt_irec	*imap, -	xfs_off_t		offset) -{ -	ASSERT(imap->br_startblock != HOLESTARTBLOCK); -	ASSERT(imap->br_startblock != DELAYSTARTBLOCK); - -	xfs_map_buffer(inode, bh, imap, offset); -	set_buffer_mapped(bh); -	clear_buffer_delay(bh); -	clear_buffer_unwritten(bh); -} - -/* - * Test if a given page is suitable for writing as part of an unwritten - * or delayed allocate extent. - */ -STATIC int -xfs_is_delayed_page( -	struct page		*page, -	unsigned int		type) -{ -	if (PageWriteback(page)) -		return 0; - -	if (page->mapping && page_has_buffers(page)) { -		struct buffer_head	*bh, *head; -		int			acceptable = 0; - -		bh = head = page_buffers(page); -		do { -			if (buffer_unwritten(bh)) -				acceptable = (type == IO_UNWRITTEN); -			else if (buffer_delay(bh)) -				acceptable = (type == IO_DELALLOC); -			else if (buffer_dirty(bh) && buffer_mapped(bh)) -				acceptable = (type == IO_OVERWRITE); -			else -				break; -		} while ((bh = bh->b_this_page) != head); - -		if (acceptable) -			return 1; -	} - -	return 0; -} - -/* - * Allocate & map buffers for page given the extent map. Write it out. - * except for the original page of a writepage, this is called on - * delalloc/unwritten pages only, for the original page it is possible - * that the page has no mapping at all. - */ -STATIC int -xfs_convert_page( -	struct inode		*inode, -	struct page		*page, -	loff_t			tindex, -	struct xfs_bmbt_irec	*imap, -	xfs_ioend_t		**ioendp, -	struct writeback_control *wbc) -{ -	struct buffer_head	*bh, *head; -	xfs_off_t		end_offset; -	unsigned long		p_offset; -	unsigned int		type; -	int			len, page_dirty; -	int			count = 0, done = 0, uptodate = 1; - 	xfs_off_t		offset = page_offset(page); - -	if (page->index != tindex) -		goto fail; -	if (!trylock_page(page)) -		goto fail; -	if (PageWriteback(page)) -		goto fail_unlock_page; -	if (page->mapping != inode->i_mapping) -		goto fail_unlock_page; -	if (!xfs_is_delayed_page(page, (*ioendp)->io_type)) -		goto fail_unlock_page; - -	/* -	 * page_dirty is initially a count of buffers on the page before -	 * EOF and is decremented as we move each into a cleanable state. -	 * -	 * Derivation: -	 * -	 * End offset is the highest offset that this page should represent. -	 * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1)) -	 * will evaluate non-zero and be less than PAGE_CACHE_SIZE and -	 * hence give us the correct page_dirty count. On any other page, -	 * it will be zero and in that case we need page_dirty to be the -	 * count of buffers on the page. -	 */ -	end_offset = min_t(unsigned long long, -			(xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, -			i_size_read(inode)); - -	len = 1 << inode->i_blkbits; -	p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1), -					PAGE_CACHE_SIZE); -	p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; -	page_dirty = p_offset / len; - -	bh = head = page_buffers(page); -	do { -		if (offset >= end_offset) -			break; -		if (!buffer_uptodate(bh)) -			uptodate = 0; -		if (!(PageUptodate(page) || buffer_uptodate(bh))) { -			done = 1; -			continue; -		} - -		if (buffer_unwritten(bh) || buffer_delay(bh) || -		    buffer_mapped(bh)) { -			if (buffer_unwritten(bh)) -				type = IO_UNWRITTEN; -			else if (buffer_delay(bh)) -				type = IO_DELALLOC; -			else -				type = IO_OVERWRITE; - -			if (!xfs_imap_valid(inode, imap, offset)) { -				done = 1; -				continue; -			} - -			lock_buffer(bh); -			if (type != IO_OVERWRITE) -				xfs_map_at_offset(inode, bh, imap, offset); -			xfs_add_to_ioend(inode, bh, offset, type, -					 ioendp, done); - -			page_dirty--; -			count++; -		} else { -			done = 1; -		} -	} while (offset += len, (bh = bh->b_this_page) != head); - -	if (uptodate && bh == head) -		SetPageUptodate(page); - -	if (count) { -		if (--wbc->nr_to_write <= 0 && -		    wbc->sync_mode == WB_SYNC_NONE) -			done = 1; -	} -	xfs_start_page_writeback(page, !page_dirty, count); - -	return done; - fail_unlock_page: -	unlock_page(page); - fail: -	return 1; -} - -/* - * Convert & write out a cluster of pages in the same extent as defined - * by mp and following the start page. - */ -STATIC void -xfs_cluster_write( -	struct inode		*inode, -	pgoff_t			tindex, -	struct xfs_bmbt_irec	*imap, -	xfs_ioend_t		**ioendp, -	struct writeback_control *wbc, -	pgoff_t			tlast) -{ -	struct pagevec		pvec; -	int			done = 0, i; - -	pagevec_init(&pvec, 0); -	while (!done && tindex <= tlast) { -		unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1); - -		if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len)) -			break; - -		for (i = 0; i < pagevec_count(&pvec); i++) { -			done = xfs_convert_page(inode, pvec.pages[i], tindex++, -					imap, ioendp, wbc); -			if (done) -				break; -		} - -		pagevec_release(&pvec); -		cond_resched(); -	} -} - -STATIC void -xfs_vm_invalidatepage( -	struct page		*page, -	unsigned long		offset) -{ -	trace_xfs_invalidatepage(page->mapping->host, page, offset); -	block_invalidatepage(page, offset); -} - -/* - * If the page has delalloc buffers on it, we need to punch them out before we - * invalidate the page. If we don't, we leave a stale delalloc mapping on the - * inode that can trip a BUG() in xfs_get_blocks() later on if a direct IO read - * is done on that same region - the delalloc extent is returned when none is - * supposed to be there. - * - * We prevent this by truncating away the delalloc regions on the page before - * invalidating it. Because they are delalloc, we can do this without needing a - * transaction. Indeed - if we get ENOSPC errors, we have to be able to do this - * truncation without a transaction as there is no space left for block - * reservation (typically why we see a ENOSPC in writeback). - * - * This is not a performance critical path, so for now just do the punching a - * buffer head at a time. - */ -STATIC void -xfs_aops_discard_page( -	struct page		*page) -{ -	struct inode		*inode = page->mapping->host; -	struct xfs_inode	*ip = XFS_I(inode); -	struct buffer_head	*bh, *head; -	loff_t			offset = page_offset(page); - -	if (!xfs_is_delayed_page(page, IO_DELALLOC)) -		goto out_invalidate; - -	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) -		goto out_invalidate; - -	xfs_alert(ip->i_mount, -		"page discard on page %p, inode 0x%llx, offset %llu.", -			page, ip->i_ino, offset); - -	xfs_ilock(ip, XFS_ILOCK_EXCL); -	bh = head = page_buffers(page); -	do { -		int		error; -		xfs_fileoff_t	start_fsb; - -		if (!buffer_delay(bh)) -			goto next_buffer; - -		start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); -		error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1); -		if (error) { -			/* something screwed, just bail */ -			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { -				xfs_alert(ip->i_mount, -			"page discard unable to remove delalloc mapping."); -			} -			break; -		} -next_buffer: -		offset += 1 << inode->i_blkbits; - -	} while ((bh = bh->b_this_page) != head); - -	xfs_iunlock(ip, XFS_ILOCK_EXCL); -out_invalidate: -	xfs_vm_invalidatepage(page, 0); -	return; -} - -/* - * Write out a dirty page. - * - * For delalloc space on the page we need to allocate space and flush it. - * For unwritten space on the page we need to start the conversion to - * regular allocated space. - * For any other dirty buffer heads on the page we should flush them. - */ -STATIC int -xfs_vm_writepage( -	struct page		*page, -	struct writeback_control *wbc) -{ -	struct inode		*inode = page->mapping->host; -	struct buffer_head	*bh, *head; -	struct xfs_bmbt_irec	imap; -	xfs_ioend_t		*ioend = NULL, *iohead = NULL; -	loff_t			offset; -	unsigned int		type; -	__uint64_t              end_offset; -	pgoff_t                 end_index, last_index; -	ssize_t			len; -	int			err, imap_valid = 0, uptodate = 1; -	int			count = 0; -	int			nonblocking = 0; - -	trace_xfs_writepage(inode, page, 0); - -	ASSERT(page_has_buffers(page)); - -	/* -	 * Refuse to write the page out if we are called from reclaim context. -	 * -	 * This avoids stack overflows when called from deeply used stacks in -	 * random callers for direct reclaim or memcg reclaim.  We explicitly -	 * allow reclaim from kswapd as the stack usage there is relatively low. -	 * -	 * This should really be done by the core VM, but until that happens -	 * filesystems like XFS, btrfs and ext4 have to take care of this -	 * by themselves. -	 */ -	if ((current->flags & (PF_MEMALLOC|PF_KSWAPD)) == PF_MEMALLOC) -		goto redirty; - -	/* -	 * Given that we do not allow direct reclaim to call us, we should -	 * never be called while in a filesystem transaction. -	 */ -	if (WARN_ON(current->flags & PF_FSTRANS)) -		goto redirty; - -	/* Is this page beyond the end of the file? */ -	offset = i_size_read(inode); -	end_index = offset >> PAGE_CACHE_SHIFT; -	last_index = (offset - 1) >> PAGE_CACHE_SHIFT; -	if (page->index >= end_index) { -		if ((page->index >= end_index + 1) || -		    !(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) { -			unlock_page(page); -			return 0; -		} -	} - -	end_offset = min_t(unsigned long long, -			(xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, -			offset); -	len = 1 << inode->i_blkbits; - -	bh = head = page_buffers(page); -	offset = page_offset(page); -	type = IO_OVERWRITE; - -	if (wbc->sync_mode == WB_SYNC_NONE) -		nonblocking = 1; - -	do { -		int new_ioend = 0; - -		if (offset >= end_offset) -			break; -		if (!buffer_uptodate(bh)) -			uptodate = 0; - -		/* -		 * set_page_dirty dirties all buffers in a page, independent -		 * of their state.  The dirty state however is entirely -		 * meaningless for holes (!mapped && uptodate), so skip -		 * buffers covering holes here. -		 */ -		if (!buffer_mapped(bh) && buffer_uptodate(bh)) { -			imap_valid = 0; -			continue; -		} - -		if (buffer_unwritten(bh)) { -			if (type != IO_UNWRITTEN) { -				type = IO_UNWRITTEN; -				imap_valid = 0; -			} -		} else if (buffer_delay(bh)) { -			if (type != IO_DELALLOC) { -				type = IO_DELALLOC; -				imap_valid = 0; -			} -		} else if (buffer_uptodate(bh)) { -			if (type != IO_OVERWRITE) { -				type = IO_OVERWRITE; -				imap_valid = 0; -			} -		} else { -			if (PageUptodate(page)) { -				ASSERT(buffer_mapped(bh)); -				imap_valid = 0; -			} -			continue; -		} - -		if (imap_valid) -			imap_valid = xfs_imap_valid(inode, &imap, offset); -		if (!imap_valid) { -			/* -			 * If we didn't have a valid mapping then we need to -			 * put the new mapping into a separate ioend structure. -			 * This ensures non-contiguous extents always have -			 * separate ioends, which is particularly important -			 * for unwritten extent conversion at I/O completion -			 * time. -			 */ -			new_ioend = 1; -			err = xfs_map_blocks(inode, offset, &imap, type, -					     nonblocking); -			if (err) -				goto error; -			imap_valid = xfs_imap_valid(inode, &imap, offset); -		} -		if (imap_valid) { -			lock_buffer(bh); -			if (type != IO_OVERWRITE) -				xfs_map_at_offset(inode, bh, &imap, offset); -			xfs_add_to_ioend(inode, bh, offset, type, &ioend, -					 new_ioend); -			count++; -		} - -		if (!iohead) -			iohead = ioend; - -	} while (offset += len, ((bh = bh->b_this_page) != head)); - -	if (uptodate && bh == head) -		SetPageUptodate(page); - -	xfs_start_page_writeback(page, 1, count); - -	if (ioend && imap_valid) { -		xfs_off_t		end_index; - -		end_index = imap.br_startoff + imap.br_blockcount; - -		/* to bytes */ -		end_index <<= inode->i_blkbits; - -		/* to pages */ -		end_index = (end_index - 1) >> PAGE_CACHE_SHIFT; - -		/* check against file size */ -		if (end_index > last_index) -			end_index = last_index; - -		xfs_cluster_write(inode, page->index + 1, &imap, &ioend, -				  wbc, end_index); -	} - -	if (iohead) -		xfs_submit_ioend(wbc, iohead); - -	return 0; - -error: -	if (iohead) -		xfs_cancel_ioend(iohead); - -	if (err == -EAGAIN) -		goto redirty; - -	xfs_aops_discard_page(page); -	ClearPageUptodate(page); -	unlock_page(page); -	return err; - -redirty: -	redirty_page_for_writepage(wbc, page); -	unlock_page(page); -	return 0; -} - -STATIC int -xfs_vm_writepages( -	struct address_space	*mapping, -	struct writeback_control *wbc) -{ -	xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED); -	return generic_writepages(mapping, wbc); -} - -/* - * Called to move a page into cleanable state - and from there - * to be released. The page should already be clean. We always - * have buffer heads in this call. - * - * Returns 1 if the page is ok to release, 0 otherwise. - */ -STATIC int -xfs_vm_releasepage( -	struct page		*page, -	gfp_t			gfp_mask) -{ -	int			delalloc, unwritten; - -	trace_xfs_releasepage(page->mapping->host, page, 0); - -	xfs_count_page_state(page, &delalloc, &unwritten); - -	if (WARN_ON(delalloc)) -		return 0; -	if (WARN_ON(unwritten)) -		return 0; - -	return try_to_free_buffers(page); -} - -STATIC int -__xfs_get_blocks( -	struct inode		*inode, -	sector_t		iblock, -	struct buffer_head	*bh_result, -	int			create, -	int			direct) -{ -	struct xfs_inode	*ip = XFS_I(inode); -	struct xfs_mount	*mp = ip->i_mount; -	xfs_fileoff_t		offset_fsb, end_fsb; -	int			error = 0; -	int			lockmode = 0; -	struct xfs_bmbt_irec	imap; -	int			nimaps = 1; -	xfs_off_t		offset; -	ssize_t			size; -	int			new = 0; - -	if (XFS_FORCED_SHUTDOWN(mp)) -		return -XFS_ERROR(EIO); - -	offset = (xfs_off_t)iblock << inode->i_blkbits; -	ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); -	size = bh_result->b_size; - -	if (!create && direct && offset >= i_size_read(inode)) -		return 0; - -	if (create) { -		lockmode = XFS_ILOCK_EXCL; -		xfs_ilock(ip, lockmode); -	} else { -		lockmode = xfs_ilock_map_shared(ip); -	} - -	ASSERT(offset <= mp->m_maxioffset); -	if (offset + size > mp->m_maxioffset) -		size = mp->m_maxioffset - offset; -	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); -	offset_fsb = XFS_B_TO_FSBT(mp, offset); - -	error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, -			  XFS_BMAPI_ENTIRE,  NULL, 0, &imap, &nimaps, NULL); -	if (error) -		goto out_unlock; - -	if (create && -	    (!nimaps || -	     (imap.br_startblock == HOLESTARTBLOCK || -	      imap.br_startblock == DELAYSTARTBLOCK))) { -		if (direct) { -			error = xfs_iomap_write_direct(ip, offset, size, -						       &imap, nimaps); -		} else { -			error = xfs_iomap_write_delay(ip, offset, size, &imap); -		} -		if (error) -			goto out_unlock; - -		trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap); -	} else if (nimaps) { -		trace_xfs_get_blocks_found(ip, offset, size, 0, &imap); -	} else { -		trace_xfs_get_blocks_notfound(ip, offset, size); -		goto out_unlock; -	} -	xfs_iunlock(ip, lockmode); - -	if (imap.br_startblock != HOLESTARTBLOCK && -	    imap.br_startblock != DELAYSTARTBLOCK) { -		/* -		 * For unwritten extents do not report a disk address on -		 * the read case (treat as if we're reading into a hole). -		 */ -		if (create || !ISUNWRITTEN(&imap)) -			xfs_map_buffer(inode, bh_result, &imap, offset); -		if (create && ISUNWRITTEN(&imap)) { -			if (direct) -				bh_result->b_private = inode; -			set_buffer_unwritten(bh_result); -		} -	} - -	/* -	 * If this is a realtime file, data may be on a different device. -	 * to that pointed to from the buffer_head b_bdev currently. -	 */ -	bh_result->b_bdev = xfs_find_bdev_for_inode(inode); - -	/* -	 * If we previously allocated a block out beyond eof and we are now -	 * coming back to use it then we will need to flag it as new even if it -	 * has a disk address. -	 * -	 * With sub-block writes into unwritten extents we also need to mark -	 * the buffer as new so that the unwritten parts of the buffer gets -	 * correctly zeroed. -	 */ -	if (create && -	    ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) || -	     (offset >= i_size_read(inode)) || -	     (new || ISUNWRITTEN(&imap)))) -		set_buffer_new(bh_result); - -	if (imap.br_startblock == DELAYSTARTBLOCK) { -		BUG_ON(direct); -		if (create) { -			set_buffer_uptodate(bh_result); -			set_buffer_mapped(bh_result); -			set_buffer_delay(bh_result); -		} -	} - -	/* -	 * If this is O_DIRECT or the mpage code calling tell them how large -	 * the mapping is, so that we can avoid repeated get_blocks calls. -	 */ -	if (direct || size > (1 << inode->i_blkbits)) { -		xfs_off_t		mapping_size; - -		mapping_size = imap.br_startoff + imap.br_blockcount - iblock; -		mapping_size <<= inode->i_blkbits; - -		ASSERT(mapping_size > 0); -		if (mapping_size > size) -			mapping_size = size; -		if (mapping_size > LONG_MAX) -			mapping_size = LONG_MAX; - -		bh_result->b_size = mapping_size; -	} - -	return 0; - -out_unlock: -	xfs_iunlock(ip, lockmode); -	return -error; -} - -int -xfs_get_blocks( -	struct inode		*inode, -	sector_t		iblock, -	struct buffer_head	*bh_result, -	int			create) -{ -	return __xfs_get_blocks(inode, iblock, bh_result, create, 0); -} - -STATIC int -xfs_get_blocks_direct( -	struct inode		*inode, -	sector_t		iblock, -	struct buffer_head	*bh_result, -	int			create) -{ -	return __xfs_get_blocks(inode, iblock, bh_result, create, 1); -} - -/* - * Complete a direct I/O write request. - * - * If the private argument is non-NULL __xfs_get_blocks signals us that we - * need to issue a transaction to convert the range from unwritten to written - * extents.  In case this is regular synchronous I/O we just call xfs_end_io - * to do this and we are done.  But in case this was a successful AIO - * request this handler is called from interrupt context, from which we - * can't start transactions.  In that case offload the I/O completion to - * the workqueues we also use for buffered I/O completion. - */ -STATIC void -xfs_end_io_direct_write( -	struct kiocb		*iocb, -	loff_t			offset, -	ssize_t			size, -	void			*private, -	int			ret, -	bool			is_async) -{ -	struct xfs_ioend	*ioend = iocb->private; - -	/* -	 * blockdev_direct_IO can return an error even after the I/O -	 * completion handler was called.  Thus we need to protect -	 * against double-freeing. -	 */ -	iocb->private = NULL; - -	ioend->io_offset = offset; -	ioend->io_size = size; -	if (private && size > 0) -		ioend->io_type = IO_UNWRITTEN; - -	if (is_async) { -		/* -		 * If we are converting an unwritten extent we need to delay -		 * the AIO completion until after the unwrittent extent -		 * conversion has completed, otherwise do it ASAP. -		 */ -		if (ioend->io_type == IO_UNWRITTEN) { -			ioend->io_iocb = iocb; -			ioend->io_result = ret; -		} else { -			aio_complete(iocb, ret, 0); -		} -		xfs_finish_ioend(ioend); -	} else { -		xfs_finish_ioend_sync(ioend); -	} - -	/* XXX: probably should move into the real I/O completion handler */ -	inode_dio_done(ioend->io_inode); -} - -STATIC ssize_t -xfs_vm_direct_IO( -	int			rw, -	struct kiocb		*iocb, -	const struct iovec	*iov, -	loff_t			offset, -	unsigned long		nr_segs) -{ -	struct inode		*inode = iocb->ki_filp->f_mapping->host; -	struct block_device	*bdev = xfs_find_bdev_for_inode(inode); -	ssize_t			ret; - -	if (rw & WRITE) { -		iocb->private = xfs_alloc_ioend(inode, IO_DIRECT); - -		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, -					    offset, nr_segs, -					    xfs_get_blocks_direct, -					    xfs_end_io_direct_write, NULL, 0); -		if (ret != -EIOCBQUEUED && iocb->private) -			xfs_destroy_ioend(iocb->private); -	} else { -		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, -					    offset, nr_segs, -					    xfs_get_blocks_direct, -					    NULL, NULL, 0); -	} - -	return ret; -} - -STATIC void -xfs_vm_write_failed( -	struct address_space	*mapping, -	loff_t			to) -{ -	struct inode		*inode = mapping->host; - -	if (to > inode->i_size) { -		/* -		 * punch out the delalloc blocks we have already allocated. We -		 * don't call xfs_setattr() to do this as we may be in the -		 * middle of a multi-iovec write and so the vfs inode->i_size -		 * will not match the xfs ip->i_size and so it will zero too -		 * much. Hence we jus truncate the page cache to zero what is -		 * necessary and punch the delalloc blocks directly. -		 */ -		struct xfs_inode	*ip = XFS_I(inode); -		xfs_fileoff_t		start_fsb; -		xfs_fileoff_t		end_fsb; -		int			error; - -		truncate_pagecache(inode, to, inode->i_size); - -		/* -		 * Check if there are any blocks that are outside of i_size -		 * that need to be trimmed back. -		 */ -		start_fsb = XFS_B_TO_FSB(ip->i_mount, inode->i_size) + 1; -		end_fsb = XFS_B_TO_FSB(ip->i_mount, to); -		if (end_fsb <= start_fsb) -			return; - -		xfs_ilock(ip, XFS_ILOCK_EXCL); -		error = xfs_bmap_punch_delalloc_range(ip, start_fsb, -							end_fsb - start_fsb); -		if (error) { -			/* something screwed, just bail */ -			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { -				xfs_alert(ip->i_mount, -			"xfs_vm_write_failed: unable to clean up ino %lld", -						ip->i_ino); -			} -		} -		xfs_iunlock(ip, XFS_ILOCK_EXCL); -	} -} - -STATIC int -xfs_vm_write_begin( -	struct file		*file, -	struct address_space	*mapping, -	loff_t			pos, -	unsigned		len, -	unsigned		flags, -	struct page		**pagep, -	void			**fsdata) -{ -	int			ret; - -	ret = block_write_begin(mapping, pos, len, flags | AOP_FLAG_NOFS, -				pagep, xfs_get_blocks); -	if (unlikely(ret)) -		xfs_vm_write_failed(mapping, pos + len); -	return ret; -} - -STATIC int -xfs_vm_write_end( -	struct file		*file, -	struct address_space	*mapping, -	loff_t			pos, -	unsigned		len, -	unsigned		copied, -	struct page		*page, -	void			*fsdata) -{ -	int			ret; - -	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); -	if (unlikely(ret < len)) -		xfs_vm_write_failed(mapping, pos + len); -	return ret; -} - -STATIC sector_t -xfs_vm_bmap( -	struct address_space	*mapping, -	sector_t		block) -{ -	struct inode		*inode = (struct inode *)mapping->host; -	struct xfs_inode	*ip = XFS_I(inode); - -	trace_xfs_vm_bmap(XFS_I(inode)); -	xfs_ilock(ip, XFS_IOLOCK_SHARED); -	xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF); -	xfs_iunlock(ip, XFS_IOLOCK_SHARED); -	return generic_block_bmap(mapping, block, xfs_get_blocks); -} - -STATIC int -xfs_vm_readpage( -	struct file		*unused, -	struct page		*page) -{ -	return mpage_readpage(page, xfs_get_blocks); -} - -STATIC int -xfs_vm_readpages( -	struct file		*unused, -	struct address_space	*mapping, -	struct list_head	*pages, -	unsigned		nr_pages) -{ -	return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks); -} - -const struct address_space_operations xfs_address_space_operations = { -	.readpage		= xfs_vm_readpage, -	.readpages		= xfs_vm_readpages, -	.writepage		= xfs_vm_writepage, -	.writepages		= xfs_vm_writepages, -	.releasepage		= xfs_vm_releasepage, -	.invalidatepage		= xfs_vm_invalidatepage, -	.write_begin		= xfs_vm_write_begin, -	.write_end		= xfs_vm_write_end, -	.bmap			= xfs_vm_bmap, -	.direct_IO		= xfs_vm_direct_IO, -	.migratepage		= buffer_migrate_page, -	.is_partially_uptodate  = block_is_partially_uptodate, -	.error_remove_page	= generic_error_remove_page, -}; |