From patchwork Fri Aug 23 00:03:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 269235 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 D75192C0085 for ; Fri, 23 Aug 2013 10:04:53 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754784Ab3HWAEk (ORCPT ); Thu, 22 Aug 2013 20:04:40 -0400 Received: from mail-pb0-f47.google.com ([209.85.160.47]:55587 "EHLO mail-pb0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754701Ab3HWADo (ORCPT ); Thu, 22 Aug 2013 20:03:44 -0400 Received: by mail-pb0-f47.google.com with SMTP id rr4so2456032pbb.20 for ; Thu, 22 Aug 2013 17:03:43 -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=m1LdlJbPMbshVFPIkdkKHXEQwvZGvKouPezxjPE+ZRw=; b=cX/n8XCtgf2GW3xYh4Y548WYi/OQEJHWdapvt3JVfOZWZTTKkdVBY0VoPKoRTuM4Y1 4h1hD6YimEMkwLqKvEjwsnSgvFrc5HJREGWtpQ5wgTjJQZSSB7xxwHrHQjLxbiENfD0w Lt+ZO2lX+MIfA4knmWblFM1yhYhc/7RUUogefzUwCvuW2/hEcPlLGqJW4lt2P1rlLCIu yDGwU9zuo7bR3txLbPYLLD2Iayt0UcL59jUpl8KorxIaOGS5wIXwmfMx709Vq5Qrn2ab rHEvraxnF27tkjpsq574CpdyWIsaI6ABGGmpX3XKlsGdKfeaE2ri3XvAhXTEhjEMFuRy FIQg== X-Gm-Message-State: ALoCoQkkx5GV3apduLYS66xprYv4NKmkx5bDb+SD1jy9KNlUQHfUkODvAlAVohSBC5mbcg5AxII7 X-Received: by 10.68.36.38 with SMTP id n6mr16190105pbj.15.1377216223697; Thu, 22 Aug 2013 17:03:43 -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 bu4sm3370866pbc.11.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 22 Aug 2013 17:03:42 -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 v4 4/7] mm: Scan for dirty ptes and update cmtime on MS_ASYNC Date: Thu, 22 Aug 2013 17:03:20 -0700 Message-Id: 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 | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 11 deletions(-) diff --git a/mm/msync.c b/mm/msync.c index 632df45..a2ee43c 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,54 @@ * 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; + int iters = 0; + + while (*start < end && *start < vma->vm_end && iters < 128) { + unsigned int page_mask, page_increm; + + /* + * Require that the pte is 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_flush_cmtime_nowb(vma->vm_file->f_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 +128,29 @@ 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); + if (error || start >= end) + goto out_unlock; + } else { + start = vma->vm_end; + if (start >= end) + goto out_unlock; + } vma = find_vma(mm, start); } else { + start = vma->vm_end; if (start >= end) { error = 0; goto out_unlock;