From patchwork Fri Nov 22 23:53:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Gruenbacher X-Patchwork-Id: 11258681 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9FC2013A4 for ; Fri, 22 Nov 2019 23:53:53 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 6232A20637 for ; Fri, 22 Nov 2019 23:53:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="FWeJYkyw" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6232A20637 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 8F1F06B0532; Fri, 22 Nov 2019 18:53:52 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 8C7A86B0533; Fri, 22 Nov 2019 18:53:52 -0500 (EST) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7DF0C6B0534; Fri, 22 Nov 2019 18:53:52 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0080.hostedemail.com [216.40.44.80]) by kanga.kvack.org (Postfix) with ESMTP id 69A1A6B0532 for ; Fri, 22 Nov 2019 18:53:52 -0500 (EST) Received: from smtpin06.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with SMTP id 009764DB3 for ; Fri, 22 Nov 2019 23:53:52 +0000 (UTC) X-FDA: 76185568662.06.neck68_78fd5e211ea40 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,agruenba@redhat.com,:torvalds@linux-foundation.org:swhiteho@redhat.com:khlebnikov@yandex-team.ru:kirill@shutemov.name::akpm@linux-foundation.org:linux-kernel@vger.kernel.org:linux-fsdevel@vger.kernel.org:viro@zeniv.linux.org.uk:hannes@cmpxchg.org:cluster-devel@redhat.com:lsahlber@redhat.com:sfrench@samba.org:rpeterso@redhat.com:agruenba@redhat.com,RULES_HIT:30003:30012:30054,0,RBL:205.139.110.120:@redhat.com:.lbl8.mailshell.net-62.18.0.100 66.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:23,LUA_SUMMARY:none X-HE-Tag: neck68_78fd5e211ea40 X-Filterd-Recvd-Size: 7813 Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by imf37.hostedemail.com (Postfix) with ESMTP for ; Fri, 22 Nov 2019 23:53:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1574466830; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NOGkY4foGqbdnpZbcMiOQpwjMwXw9GwTN5p3QDTd77E=; b=FWeJYkywRLw89xbD1pdwqkyHuBW6Yskgb5LGaWgmydLkzced8TWtIg4LHx/AxcUl6Qz0Af 4g1eBfSKhvgvtgGsHAk5xaQGUSdERD1MgIkw0rPECIY4LH/EkxdOyAcUeCmyqFVkJPWF7E jGf+cWKXGYRgZY0cf9pjqYFIPwXmaTs= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-12-ccp0u32WPuykWAMXE7w2NQ-1; Fri, 22 Nov 2019 18:53:47 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3EB3B107ACE3; Fri, 22 Nov 2019 23:53:46 +0000 (UTC) Received: from max.com (ovpn-204-21.brq.redhat.com [10.40.204.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id EA83B5C1BB; Fri, 22 Nov 2019 23:53:42 +0000 (UTC) From: Andreas Gruenbacher To: Linus Torvalds Cc: Steven Whitehouse , Konstantin Khlebnikov , "Kirill A. Shutemov" , linux-mm@kvack.org, Andrew Morton , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alexander Viro , Johannes Weiner , cluster-devel@redhat.com, Ronnie Sahlberg , Steve French , Bob Peterson , Andreas Gruenbacher Subject: [RFC PATCH 3/3] gfs2: Rework read and page fault locking Date: Sat, 23 Nov 2019 00:53:24 +0100 Message-Id: <20191122235324.17245-4-agruenba@redhat.com> In-Reply-To: <20191122235324.17245-1-agruenba@redhat.com> References: <20191122235324.17245-1-agruenba@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-MC-Unique: ccp0u32WPuykWAMXE7w2NQ-1 X-Mimecast-Spam-Score: 0 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Move the glock lock taking code from the ->readpage and ->readpages address space operations to the ->read_iter file and ->fault vm operations. To avoid taking the lock even when an operation can be satisfied out of the page cache, try the operation without taking the lock first. When that fails, take the lock and repeat the opeation. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/aops.c | 36 ++++++--------------------- fs/gfs2/file.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index b9fe975d7625..4aa6c952eb90 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -515,26 +515,10 @@ static int __gfs2_readpage(void *file, struct page *page) static int gfs2_readpage(struct file *file, struct page *page) { - struct address_space *mapping = page->mapping; - struct gfs2_inode *ip = GFS2_I(mapping->host); - struct gfs2_holder gh; int error; - unlock_page(page); - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); - error = gfs2_glock_nq(&gh); - if (unlikely(error)) - goto out; - error = AOP_TRUNCATED_PAGE; - lock_page(page); - if (page->mapping == mapping && !PageUptodate(page)) - error = __gfs2_readpage(file, page); - else - unlock_page(page); - gfs2_glock_dq(&gh); -out: - gfs2_holder_uninit(&gh); - if (error && error != AOP_TRUNCATED_PAGE) + error = __gfs2_readpage(file, page); + if (error) lock_page(page); return error; } @@ -602,18 +586,12 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping, struct inode *inode = mapping->host; struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); - struct gfs2_holder gh; - int ret; + int ret = 0; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); - ret = gfs2_glock_nq(&gh); - if (unlikely(ret)) - goto out_uninit; - if (!gfs2_is_stuffed(ip)) - ret = mpage_readpages(mapping, pages, nr_pages, gfs2_block_map); - gfs2_glock_dq(&gh); -out_uninit: - gfs2_holder_uninit(&gh); + if (gfs2_is_stuffed(ip)) + goto out; + ret = mpage_readpages(mapping, pages, nr_pages, gfs2_block_map); +out: if (unlikely(test_bit(SDF_WITHDRAWN, &sdp->sd_flags))) ret = -EIO; return ret; diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 997b326247e2..207d39996353 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -524,8 +524,34 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) return block_page_mkwrite_return(ret); } +static vm_fault_t gfs2_fault(struct vm_fault *vmf) +{ + struct inode *inode = file_inode(vmf->vma->vm_file); + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_holder gh; + vm_fault_t ret; + int err; + + vmf->flags |= FAULT_FLAG_CACHED; + ret = filemap_fault(vmf); + vmf->flags &= ~FAULT_FLAG_CACHED; + if (!(ret & VM_FAULT_RETRY)) + return ret; + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + err = gfs2_glock_nq(&gh); + if (err) { + ret = block_page_mkwrite_return(err); + goto out_uninit; + } + ret = filemap_fault(vmf); + gfs2_glock_dq(&gh); +out_uninit: + gfs2_holder_uninit(&gh); + return ret; +} + static const struct vm_operations_struct gfs2_vm_ops = { - .fault = filemap_fault, + .fault = gfs2_fault, .map_pages = filemap_map_pages, .page_mkwrite = gfs2_page_mkwrite, }; @@ -778,15 +804,51 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from) static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { + struct gfs2_inode *ip; + struct gfs2_holder gh; + size_t written = 0; ssize_t ret; + gfs2_holder_mark_uninitialized(&gh); if (iocb->ki_flags & IOCB_DIRECT) { ret = gfs2_file_direct_read(iocb, to); if (likely(ret != -ENOTBLK)) return ret; iocb->ki_flags &= ~IOCB_DIRECT; } - return generic_file_read_iter(iocb, to); + iocb->ki_flags |= IOCB_CACHED; + ret = generic_file_read_iter(iocb, to); + iocb->ki_flags &= ~IOCB_CACHED; + if (ret >= 0) { + if (!iov_iter_count(to)) + return ret; + written = ret; + } else { + switch(ret) { + case -EAGAIN: + if (iocb->ki_flags & IOCB_NOWAIT) + return ret; + break; + case -ECANCELED: + break; + default: + return ret; + } + } + ip = GFS2_I(iocb->ki_filp->f_mapping->host); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + ret = gfs2_glock_nq(&gh); + if (ret) + goto out_uninit; + ret = generic_file_read_iter(iocb, to); + if (ret > 0) + written += ret; + if (gfs2_holder_initialized(&gh)) + gfs2_glock_dq(&gh); +out_uninit: + if (gfs2_holder_initialized(&gh)) + gfs2_holder_uninit(&gh); + return written ? written : ret; } /**