From patchwork Fri Nov 18 10:43:04 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robin Dong X-Patchwork-Id: 126386 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 25CD4B7256 for ; Fri, 18 Nov 2011 21:43:36 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752447Ab1KRKnf (ORCPT ); Fri, 18 Nov 2011 05:43:35 -0500 Received: from mail-iy0-f174.google.com ([209.85.210.174]:62580 "EHLO mail-iy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752298Ab1KRKne (ORCPT ); Fri, 18 Nov 2011 05:43:34 -0500 Received: by mail-iy0-f174.google.com with SMTP id e36so3428378iag.19 for ; Fri, 18 Nov 2011 02:43:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=u9avrxJKrRWELDOkqqyjawkIOfN7ZvsVLmDH743+wME=; b=K/ZTNfGAk0u6BYSunmAXD6c/h1cqBLbNMVo6Ys78w9kWnrxv+ODOphR1D67Xbk/wiU 2AwymaziZb+GrAc+4wGQ27xXbvtRr4exTUneErfJvry883G5BNHPrO8KK+j144g44hxj ss6OpNdUbSypx4RTzLz64VPeJwIoK1eU2U9Cw= Received: by 10.42.96.132 with SMTP id j4mr2098598icn.50.1321613014379; Fri, 18 Nov 2011 02:43:34 -0800 (PST) Received: from localhost.localdomain ([110.75.120.250]) by mx.google.com with ESMTPS id g16sm1461207ibs.8.2011.11.18.02.43.32 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 18 Nov 2011 02:43:33 -0800 (PST) From: Robin Dong To: linux-ext4@vger.kernel.org Cc: Robin Dong Subject: [PATCH 9/9 v2 bigalloc] ext4: make cluster works for mmap Date: Fri, 18 Nov 2011 18:43:04 +0800 Message-Id: <1321612984-10228-10-git-send-email-hao.bigrat@gmail.com> X-Mailer: git-send-email 1.7.3.2 In-Reply-To: <1321612984-10228-1-git-send-email-hao.bigrat@gmail.com> References: <1321612984-10228-1-git-send-email-hao.bigrat@gmail.com> Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org From: Robin Dong When users write a page in mmap regioin, it need to zero out other pages around it. Signed-off-by: Robin Dong --- fs/ext4/inode.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 68 insertions(+), 1 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 4331d07..f965ed1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4651,13 +4651,17 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct page *page = vmf->page; loff_t size; unsigned long len; - int ret; + int ret, i, uninit = 0; struct file *file = vma->vm_file; struct inode *inode = file->f_path.dentry->d_inode; + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct address_space *mapping = inode->i_mapping; + struct ext4_write_cluster_ctxt *ewcc = NULL; handle_t *handle; get_block_t *get_block; int retries = 0; + unsigned int flags = AOP_FLAG_NOFS; + unsigned long from, to; /* * This check is racy but catches the common case. We rely on @@ -4714,7 +4718,47 @@ retry_alloc: ret = VM_FAULT_SIGBUS; goto out; } + + ewcc = ext4_alloc_write_cluster_ctxt(); + if (!ewcc) { + ret = -ENOMEM; + goto out; + } + + if (sbi->s_cluster_ratio > 1) { + /* We need to know whether the block is allocated already + */ + struct ext4_map_blocks map; + map.m_lblk = page->index; + map.m_len = 1; + ret = ext4_map_blocks(handle, inode, &map, 0); + uninit = map.m_flags & EXT4_MAP_UNWRITTEN; + if (ret <= 0 || uninit) { + ret = ext4_prepare_cluster_left_pages(inode, + page->index, ewcc, flags); + if (ret) + goto err_out; + } + } + ret = __block_page_mkwrite(vma, vmf, get_block); + if (ret) + goto err_out; + + if (sbi->s_cluster_ratio > 1 && uninit) { + ret = ext4_prepare_cluster_right_pages(inode, page->index, + ewcc, flags); + if (ret) + goto err_out; + for (i = 0; i < ewcc->w_num_pages; i++) { + if (!ewcc->w_pages[i] || + !page_buffers(ewcc->w_pages[i])) + break; + block_commit_write(ewcc->w_pages[i], + 0, PAGE_CACHE_SIZE); + } + } + if (!ret && ext4_should_journal_data(inode)) { if (walk_page_buffers(handle, page_buffers(page), 0, PAGE_CACHE_SIZE, NULL, do_journal_get_write_access)) { @@ -4722,13 +4766,36 @@ retry_alloc: ret = VM_FAULT_SIGBUS; goto out; } + + for (i = 0; i < ewcc->w_num_pages; i++) { + page = ewcc->w_pages[i]; + if (!page || !page_buffers(page)) + continue; + from = page->index << PAGE_CACHE_SHIFT; + to = from + PAGE_CACHE_SIZE; + ret = walk_page_buffers(handle, page_buffers(page), + from, to, NULL, do_journal_get_write_access); + if (ret) { + ret = VM_FAULT_SIGBUS; + goto out; + } + } ext4_set_inode_state(inode, EXT4_STATE_JDATA); } + +err_out: + if (ewcc) { + ext4_free_write_cluster_ctxt(ewcc); + ewcc = NULL; + } ext4_journal_stop(handle); if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) goto retry_alloc; out_ret: ret = block_page_mkwrite_return(ret); + out: + if (ewcc) + ext4_free_write_cluster_ctxt(ewcc); return ret; }