From patchwork Fri Aug 16 23:22:11 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 267935 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 8127E2C019D for ; Sat, 17 Aug 2013 10:22:55 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755193Ab3HQAWx (ORCPT ); Fri, 16 Aug 2013 20:22:53 -0400 Received: from mail-pa0-f54.google.com ([209.85.220.54]:46299 "EHLO mail-pa0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755144Ab3HQAWv (ORCPT ); Fri, 16 Aug 2013 20:22:51 -0400 Received: by mail-pa0-f54.google.com with SMTP id kx10so2464840pab.27 for ; Fri, 16 Aug 2013 17:22:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=UD5suLcH3O09Ep3tPjAkS3fAdNGek0Bf0gEqhfFQUs8=; b=MK5zSnA95JrxPamKcBwNoqidekNs652e2QRB3agCYGNmCv71nZ0d7aZwTPDeoaHpnj 5rbv8FDF2FTcCPsnIxx1Ze6upXB8EMJvmfXv7h0x1QVrTY4zEQO42DW+YCAAiX+pPDyz S/iiEUl9GVaoPiRg8QsmMu3NGCPoeKj1er8pPqMGllgPSS14onTxllKE438pVb+mlRDb m+x/LRu/oCEkK/uVZAhqxFPWG1LzGMohMzUmTa8S3eLDyycAOq7WFshdMeFpMpCySnzH vmYm7Y7ALD08cbEJGbdsX8AI/Is0Nf75iJB71IJfo1/sjeCKsF91VfJmSewb35AU4WTt hBUw== X-Gm-Message-State: ALoCoQkNHJeC9PkIOOia/YW6FSU2y5RoWREdU5vd5KEoY3y9qOuig29KLm4XKqITVTGdgAxYOfzl X-Received: by 10.68.160.193 with SMTP id xm1mr4029294pbb.88.1376695349945; Fri, 16 Aug 2013 16:22:29 -0700 (PDT) Received: from localhost (50-76-60-73-ip-static.hfc.comcastbusiness.net. [50.76.60.73]) by mx.google.com with ESMTPSA id sp4sm51419pbc.45.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 16 Aug 2013 16:22:29 -0700 (PDT) From: Andy Lutomirski To: linux-kernel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, Dave Chinner , Theodore Ts'o , Dave Hansen , xfs@oss.sgi.com, Jan Kara , Tim Chen , Christoph Hellwig , Andy Lutomirski Subject: [PATCH v3 4/5] mm: Scan for dirty ptes and update cmtime on MS_ASYNC Date: Fri, 16 Aug 2013 16:22:11 -0700 Message-Id: <1c0ffd25b5adb4ea65a29e8858ab4674b10aa9df.1376679411.git.luto@amacapital.net> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org This is probably unimportant but improves POSIX compliance. Signed-off-by: Andy Lutomirski --- mm/msync.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 11 deletions(-) diff --git a/mm/msync.c b/mm/msync.c index 632df45..9e41acd 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -13,13 +13,16 @@ #include #include #include +#include +#include /* * MS_SYNC syncs the entire file - including mappings. * * MS_ASYNC does not start I/O (it used to, up to 2.5.67). * Nor does it marks the relevant pages dirty (it used to up to 2.6.17). - * Now it doesn't do anything, since dirty pages are properly tracked. + * Now all it does is ensure that file timestamps get updated, since POSIX + * requires it. We track dirty pages correct without MS_ASYNC. * * The application may now run fsync() to * write out the dirty pages and wait on the writeout and check the result. @@ -28,6 +31,57 @@ * So by _not_ starting I/O in MS_ASYNC we provide complete flexibility to * applications. */ + +static int msync_async_range(struct vm_area_struct *vma, + unsigned long *start, unsigned long end) +{ + struct mm_struct *mm; + struct address_space *mapping; + int iters = 0; + + while (*start < end && *start < vma->vm_end && iters < 128) { + unsigned int page_mask, page_increm; + + /* + * Require that the pte writable (because otherwise it can't + * be dirty, so there's nothing to clean). + * + * In theory we could check the pte dirty bit, but this is + * awkward and barely worth it. + */ + struct page *page = follow_page_mask(vma, *start, + FOLL_GET | FOLL_WRITE, + &page_mask); + + if (page && !IS_ERR(page)) { + if (lock_page_killable(page) == 0) { + page_mkclean(page); + unlock_page(page); + } + put_page(page); + } + + if (IS_ERR(page)) + return PTR_ERR(page); + + page_increm = 1 + (~(*start >> PAGE_SHIFT) & page_mask); + *start += page_increm * PAGE_SIZE; + cond_resched(); + iters++; + } + + /* XXX: try to do this only once? */ + mapping = vma->vm_file->f_mapping; + if (mapping->a_ops->flush_cmtime) + mapping->a_ops->flush_cmtime(mapping); + + /* Give mmap_sem writers a chance. */ + mm = current->mm; + up_read(&mm->mmap_sem); + down_read(&mm->mmap_sem); + return 0; +} + SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) { unsigned long end; @@ -77,18 +131,25 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) goto out_unlock; } file = vma->vm_file; - start = vma->vm_end; - if ((flags & MS_SYNC) && file && - (vma->vm_flags & VM_SHARED)) { - get_file(file); - up_read(&mm->mmap_sem); - error = vfs_fsync(file, 0); - fput(file); - if (error || start >= end) - goto out; - down_read(&mm->mmap_sem); + if (file && vma->vm_flags & VM_SHARED) { + if (flags & MS_SYNC) { + start = vma->vm_end; + get_file(file); + up_read(&mm->mmap_sem); + error = vfs_fsync(file, 0); + fput(file); + if (error || start >= end) + goto out; + down_read(&mm->mmap_sem); + } else if ((vma->vm_flags & VM_WRITE) && + file->f_mapping) { + error = msync_async_range(vma, &start, end); + } else { + start = vma->vm_end; + } vma = find_vma(mm, start); } else { + start = vma->vm_end; if (start >= end) { error = 0; goto out_unlock;