From patchwork Mon Apr 19 17:26:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: gregkh@suse.de X-Patchwork-Id: 50478 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id AE869B7D11 for ; Tue, 20 Apr 2010 03:30:05 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752318Ab0DSR37 (ORCPT ); Mon, 19 Apr 2010 13:29:59 -0400 Received: from kroah.org ([198.145.64.141]:48455 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752257Ab0DSR36 (ORCPT ); Mon, 19 Apr 2010 13:29:58 -0400 Received: from localhost (c-24-16-163-131.hsd1.wa.comcast.net [24.16.163.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by coco.kroah.org (Postfix) with ESMTPSA id C6B2B488F7; Mon, 19 Apr 2010 10:29:57 -0700 (PDT) Subject: patch ext4-invalidate-pages-if-delalloc-block-allocation-fails.patch added to 2.6.27-stable tree To: aneesh.kumar@linux.vnet.ibm.com, dev@jaysonking.com, gregkh@suse.de, linux-ext4@vger.kernel.org, tytso@mit.edu Cc: , From: Date: Mon, 19 Apr 2010 10:26:55 -0700 In-Reply-To: <1268699165-17461-2-git-send-email-tytso@mit.edu> Message-ID: <12716980151857@kroah.org> MIME-Version: 1.0 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org This is a note to let you know that we have just queued up the patch titled Subject: ext4: invalidate pages if delalloc block allocation fails. to the 2.6.27-stable tree. Its filename is ext4-invalidate-pages-if-delalloc-block-allocation-fails.patch A git repo of this tree can be found at http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary From tytso@mit.edu Mon Apr 19 10:19:40 2010 From: Aneesh Kumar K.V Date: Mon, 15 Mar 2010 20:25:55 -0400 Subject: ext4: invalidate pages if delalloc block allocation fails. To: stable@kernel.org Cc: Ext4 Developers List , "Theodore Ts'o" , "Jayson R. King" , "Aneesh Kumar K.V" Message-ID: <1268699165-17461-2-git-send-email-tytso@mit.edu> From: Aneesh Kumar K.V commit c4a0c46ec92c194c873232b88debce4e1a448483 upstream. We are a bit agressive in invalidating all the pages. But it is ok because we really don't know why the block allocation failed and it is better to come of the writeback path so that user can look for more info. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Jayson R. King Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 12 deletions(-) Patches currently in stable-queue which might be from aneesh.kumar@linux.vnet.ibm.com are queue-2.6.27/ext4-fix-file-fragmentation-during-large-file-write.patch queue-2.6.27/ext4-retry-block-allocation-if-we-have-free-blocks-left.patch queue-2.6.27/vfs-add-no_nrwrite_index_update-writeback-control-flag.patch queue-2.6.27/ext4-retry-block-reservation.patch queue-2.6.27/ext4-invalidate-pages-if-delalloc-block-allocation-fails.patch queue-2.6.27/ext4-use-tag-dirty-lookup-during-mpage_da_submit_io.patch queue-2.6.27/vfs-remove-the-range_cont-writeback-mode.patch queue-2.6.27/ext4-make-sure-all-the-block-allocation-paths-reserve-blocks.patch queue-2.6.27/ext4-implement-range_cyclic-in-ext4_da_writepages-instead-of-write_cache_pages.patch queue-2.6.27/ext4-add-percpu-dirty-block-accounting.patch -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1821,6 +1821,39 @@ static inline void __unmap_underlying_bl unmap_underlying_metadata(bdev, bh->b_blocknr + i); } +static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, + sector_t logical, long blk_cnt) +{ + int nr_pages, i; + pgoff_t index, end; + struct pagevec pvec; + struct inode *inode = mpd->inode; + struct address_space *mapping = inode->i_mapping; + + index = logical >> (PAGE_CACHE_SHIFT - inode->i_blkbits); + end = (logical + blk_cnt - 1) >> + (PAGE_CACHE_SHIFT - inode->i_blkbits); + while (index <= end) { + nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); + if (nr_pages == 0) + break; + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + index = page->index; + if (index > end) + break; + index++; + + BUG_ON(!PageLocked(page)); + BUG_ON(PageWriteback(page)); + block_invalidatepage(page, 0); + ClearPageUptodate(page); + unlock_page(page); + } + } + return; +} + /* * mpage_da_map_blocks - go through given space * @@ -1830,7 +1863,7 @@ static inline void __unmap_underlying_bl * The function skips space we know is already mapped to disk blocks. * */ -static void mpage_da_map_blocks(struct mpage_da_data *mpd) +static int mpage_da_map_blocks(struct mpage_da_data *mpd) { int err = 0; struct buffer_head *lbh = &mpd->lbh; @@ -1841,7 +1874,7 @@ static void mpage_da_map_blocks(struct m * We consider only non-mapped and non-allocated blocks */ if (buffer_mapped(lbh) && !buffer_delay(lbh)) - return; + return 0; new.b_state = lbh->b_state; new.b_blocknr = 0; @@ -1852,10 +1885,38 @@ static void mpage_da_map_blocks(struct m * to write simply return */ if (!new.b_size) - return; + return 0; err = mpd->get_block(mpd->inode, next, &new, 1); - if (err) - return; + if (err) { + + /* If get block returns with error + * we simply return. Later writepage + * will redirty the page and writepages + * will find the dirty page again + */ + if (err == -EAGAIN) + return 0; + /* + * get block failure will cause us + * to loop in writepages. Because + * a_ops->writepage won't be able to + * make progress. The page will be redirtied + * by writepage and writepages will again + * try to write the same. + */ + printk(KERN_EMERG "%s block allocation failed for inode %lu " + "at logical offset %llu with max blocks " + "%zd with error %d\n", + __func__, mpd->inode->i_ino, + (unsigned long long)next, + lbh->b_size >> mpd->inode->i_blkbits, err); + printk(KERN_EMERG "This should not happen.!! " + "Data will be lost\n"); + /* invlaidate all the pages */ + ext4_da_block_invalidatepages(mpd, next, + lbh->b_size >> mpd->inode->i_blkbits); + return err; + } BUG_ON(new.b_size == 0); if (buffer_new(&new)) @@ -1868,7 +1929,7 @@ static void mpage_da_map_blocks(struct m if (buffer_delay(lbh) || buffer_unwritten(lbh)) mpage_put_bnr_to_bhs(mpd, next, &new); - return; + return 0; } #define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \ @@ -1937,8 +1998,8 @@ flush_it: * We couldn't merge the block to our extent, so we * need to flush current extent and start new one */ - mpage_da_map_blocks(mpd); - mpage_da_submit_io(mpd); + if (mpage_da_map_blocks(mpd) == 0) + mpage_da_submit_io(mpd); mpd->io_done = 1; return; } @@ -1980,8 +2041,8 @@ static int __mpage_da_writepage(struct p * and start IO on them using writepage() */ if (mpd->next_page != mpd->first_page) { - mpage_da_map_blocks(mpd); - mpage_da_submit_io(mpd); + if (mpage_da_map_blocks(mpd) == 0) + mpage_da_submit_io(mpd); /* * skip rest of the page in the page_vec */ @@ -2102,8 +2163,8 @@ static int mpage_da_writepages(struct ad * Handle last extent of pages */ if (!mpd.io_done && mpd.next_page != mpd.first_page) { - mpage_da_map_blocks(&mpd); - mpage_da_submit_io(&mpd); + if (mpage_da_map_blocks(&mpd) == 0) + mpage_da_submit_io(&mpd); } wbc->nr_to_write = to_write - mpd.pages_written;