From patchwork Fri Nov 20 15:02:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329231 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D34A6C64E8A for ; Fri, 20 Nov 2020 15:03:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7FBB222226 for ; Fri, 20 Nov 2020 15:03:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="bXMBEl5c" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728327AbgKTPDN (ORCPT ); Fri, 20 Nov 2020 10:03:13 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:58437 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728230AbgKTPDM (ORCPT ); Fri, 20 Nov 2020 10:03:12 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884590; 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=zNBhm9QpHO+0SZC1AS77TFXnL/TtyW0E3XLeila/1wE=; b=bXMBEl5cm8EmO28VPvPRbXbQzKpBZxpJVQaK9k2mR7csldtzqELpcJnBjG/pl9Raulva4q v+PBv79jLy6AbeLsxivKRYXuzsz1NZV0Mw+jESurlLAiemh+O7xI2/UvUbYC1IGqFaMpax IMGYfYpZ5RYu3ZeilidxbXa6VJAUPMU= 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-146-1HPAw0GDMG-ytnsyQZ_TGg-1; Fri, 20 Nov 2020 10:03:08 -0500 X-MC-Unique: 1HPAw0GDMG-ytnsyQZ_TGg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BF19D63CCB; Fri, 20 Nov 2020 15:03:05 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0D05C19C46; Fri, 20 Nov 2020 15:02:59 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 02/76] afs: Disable use of the fscache I/O routines From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: linux-afs@lists.infradead.org, dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:02:59 +0000 Message-ID: <160588457929.3465195.1730097418904945578.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Disable use of the fscache I/O routined by the AFS filesystem. It's about to transition to passing iov_iters down and fscache is about to have its I/O path to use iov_iter, so all that needs to change. Signed-off-by: David Howells cc: linux-afs@lists.infradead.org --- fs/afs/file.c | 199 ++++++++++---------------------------------------------- fs/afs/inode.c | 2 - fs/afs/write.c | 10 --- 3 files changed, 36 insertions(+), 175 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index 85f5adf21aa0..6d43713fde01 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -203,24 +203,6 @@ void afs_put_read(struct afs_read *req) } } -#ifdef CONFIG_AFS_FSCACHE -/* - * deal with notification that a page was read from the cache - */ -static void afs_file_readpage_read_complete(struct page *page, - void *data, - int error) -{ - _enter("%p,%p,%d", page, data, error); - - /* if the read completes with an error, we just unlock the page and let - * the VM reissue the readpage */ - if (!error) - SetPageUptodate(page); - unlock_page(page); -} -#endif - static void afs_fetch_data_success(struct afs_operation *op) { struct afs_vnode *vnode = op->file[0].vnode; @@ -288,89 +270,46 @@ int afs_page_filler(void *data, struct page *page) if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) goto error; - /* is it cached? */ -#ifdef CONFIG_AFS_FSCACHE - ret = fscache_read_or_alloc_page(vnode->cache, - page, - afs_file_readpage_read_complete, - NULL, - GFP_KERNEL); -#else - ret = -ENOBUFS; -#endif - switch (ret) { - /* read BIO submitted (page in cache) */ - case 0: - break; - - /* page not yet cached */ - case -ENODATA: - _debug("cache said ENODATA"); - goto go_on; - - /* page will not be cached */ - case -ENOBUFS: - _debug("cache said ENOBUFS"); - - fallthrough; - default: - go_on: - req = kzalloc(struct_size(req, array, 1), GFP_KERNEL); - if (!req) - goto enomem; - - /* We request a full page. If the page is a partial one at the - * end of the file, the server will return a short read and the - * unmarshalling code will clear the unfilled space. - */ - refcount_set(&req->usage, 1); - req->pos = (loff_t)page->index << PAGE_SHIFT; - req->len = PAGE_SIZE; - req->nr_pages = 1; - req->pages = req->array; - req->pages[0] = page; - get_page(page); - - /* read the contents of the file from the server into the - * page */ - ret = afs_fetch_data(vnode, key, req); - afs_put_read(req); - - if (ret < 0) { - if (ret == -ENOENT) { - _debug("got NOENT from server" - " - marking file deleted and stale"); - set_bit(AFS_VNODE_DELETED, &vnode->flags); - ret = -ESTALE; - } - -#ifdef CONFIG_AFS_FSCACHE - fscache_uncache_page(vnode->cache, page); -#endif - BUG_ON(PageFsCache(page)); - - if (ret == -EINTR || - ret == -ENOMEM || - ret == -ERESTARTSYS || - ret == -EAGAIN) - goto error; - goto io_error; - } + req = kzalloc(struct_size(req, array, 1), GFP_KERNEL); + if (!req) + goto enomem; - SetPageUptodate(page); + /* We request a full page. If the page is a partial one at the + * end of the file, the server will return a short read and the + * unmarshalling code will clear the unfilled space. + */ + refcount_set(&req->usage, 1); + req->pos = (loff_t)page->index << PAGE_SHIFT; + req->len = PAGE_SIZE; + req->nr_pages = 1; + req->pages = req->array; + req->pages[0] = page; + get_page(page); + + /* read the contents of the file from the server into the + * page */ + ret = afs_fetch_data(vnode, key, req); + afs_put_read(req); - /* send the page to the cache */ -#ifdef CONFIG_AFS_FSCACHE - if (PageFsCache(page) && - fscache_write_page(vnode->cache, page, vnode->status.size, - GFP_KERNEL) != 0) { - fscache_uncache_page(vnode->cache, page); - BUG_ON(PageFsCache(page)); + if (ret < 0) { + if (ret == -ENOENT) { + _debug("got NOENT from server" + " - marking file deleted and stale"); + set_bit(AFS_VNODE_DELETED, &vnode->flags); + ret = -ESTALE; } -#endif - unlock_page(page); + + if (ret == -EINTR || + ret == -ENOMEM || + ret == -ERESTARTSYS || + ret == -EAGAIN) + goto error; + goto io_error; } + SetPageUptodate(page); + unlock_page(page); + _leave(" = 0"); return 0; @@ -416,23 +355,10 @@ static int afs_readpage(struct file *file, struct page *page) */ static void afs_readpages_page_done(struct afs_read *req) { -#ifdef CONFIG_AFS_FSCACHE - struct afs_vnode *vnode = req->vnode; -#endif struct page *page = req->pages[req->index]; req->pages[req->index] = NULL; SetPageUptodate(page); - - /* send the page to the cache */ -#ifdef CONFIG_AFS_FSCACHE - if (PageFsCache(page) && - fscache_write_page(vnode->cache, page, vnode->status.size, - GFP_KERNEL) != 0) { - fscache_uncache_page(vnode->cache, page); - BUG_ON(PageFsCache(page)); - } -#endif unlock_page(page); put_page(page); } @@ -491,9 +417,6 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, index = page->index; if (add_to_page_cache_lru(page, mapping, index, readahead_gfp_mask(mapping))) { -#ifdef CONFIG_AFS_FSCACHE - fscache_uncache_page(vnode->cache, page); -#endif put_page(page); break; } @@ -526,9 +449,6 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, for (i = 0; i < req->nr_pages; i++) { page = req->pages[i]; if (page) { -#ifdef CONFIG_AFS_FSCACHE - fscache_uncache_page(vnode->cache, page); -#endif SetPageError(page); unlock_page(page); } @@ -560,37 +480,6 @@ static int afs_readpages(struct file *file, struct address_space *mapping, } /* attempt to read as many of the pages as possible */ -#ifdef CONFIG_AFS_FSCACHE - ret = fscache_read_or_alloc_pages(vnode->cache, - mapping, - pages, - &nr_pages, - afs_file_readpage_read_complete, - NULL, - mapping_gfp_mask(mapping)); -#else - ret = -ENOBUFS; -#endif - - switch (ret) { - /* all pages are being read from the cache */ - case 0: - BUG_ON(!list_empty(pages)); - BUG_ON(nr_pages != 0); - _leave(" = 0 [reading all]"); - return 0; - - /* there were pages that couldn't be read from the cache */ - case -ENODATA: - case -ENOBUFS: - break; - - /* other error */ - default: - _leave(" = %d", ret); - return ret; - } - while (!list_empty(pages)) { ret = afs_readpages_one(file, mapping, pages); if (ret < 0) @@ -670,17 +559,6 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, BUG_ON(!PageLocked(page)); -#ifdef CONFIG_AFS_FSCACHE - /* we clean up only if the entire page is being invalidated */ - if (offset == 0 && length == PAGE_SIZE) { - if (PageFsCache(page)) { - struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); - fscache_wait_on_page_write(vnode->cache, page); - fscache_uncache_page(vnode->cache, page); - } - } -#endif - if (PagePrivate(page)) afs_invalidate_dirty(page, offset, length); @@ -702,13 +580,6 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) /* deny if page is being written to the cache and the caller hasn't * elected to wait */ -#ifdef CONFIG_AFS_FSCACHE - if (!fscache_maybe_release_page(vnode->cache, page, gfp_flags)) { - _leave(" = F [cache busy]"); - return 0; - } -#endif - if (PagePrivate(page)) { priv = (unsigned long)detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("rel"), diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 0fe8844b4bee..79c8dc06c0b8 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -420,7 +420,7 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) } __packed key; struct afs_vnode_cache_aux aux; - if (vnode->status.type == AFS_FTYPE_DIR) { + if (vnode->status.type != AFS_FTYPE_FILE) { vnode->cache = NULL; return; } diff --git a/fs/afs/write.c b/fs/afs/write.c index c9195fc67fd8..92eaa88000d7 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -847,9 +847,6 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) /* Wait for the page to be written to the cache before we allow it to * be modified. We then assume the entire page will need writing back. */ -#ifdef CONFIG_AFS_FSCACHE - fscache_wait_on_page_write(vnode->cache, vmf->page); -#endif if (PageWriteback(vmf->page) && wait_on_page_bit_killable(vmf->page, PG_writeback) < 0) @@ -936,12 +933,5 @@ int afs_launder_page(struct page *page) priv = (unsigned long)detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("laundered"), page->index, priv); - -#ifdef CONFIG_AFS_FSCACHE - if (PageFsCache(page)) { - fscache_wait_on_page_write(vnode->cache, page); - fscache_uncache_page(vnode->cache, page); - } -#endif return ret; } From patchwork Fri Nov 20 15:03:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329230 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2568C64E7C for ; Fri, 20 Nov 2020 15:04:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 63B79221F8 for ; Fri, 20 Nov 2020 15:04:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="bulMtzr2" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728397AbgKTPDq (ORCPT ); Fri, 20 Nov 2020 10:03:46 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:30824 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728373AbgKTPDp (ORCPT ); Fri, 20 Nov 2020 10:03:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884623; 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=HdZoDEt2N+ulORfz2BQDDybClITJAs4nahS2dDIyBOk=; b=bulMtzr2YVgU4JRPhgTYKuSsEjXSAGzY/Fr6p96ByL/VrxfOokWTpwaBwo6RYCvbHMF6Fi GhdDHcBm7ScusFevG192XgtbSYY65qZklXhHysELQA/Bma7qQO56I6q4Vm3w9ZJzkXzLGf 9IIkQQe0NutpHf8P3dnRxgQwARkvpjI= 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-389-olT40s9PMRSXCJ4cHkFUcw-1; Fri, 20 Nov 2020 10:03:39 -0500 X-MC-Unique: olT40s9PMRSXCJ4cHkFUcw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1FD891006C81; Fri, 20 Nov 2020 15:03:37 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id C59F16085D; Fri, 20 Nov 2020 15:03:30 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 04/76] fscache: Procfile to display cookies From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:03:29 +0000 Message-ID: <160588460994.3465195.16963417803501149328.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add /proc/fs/fscache/cookies to display active cookies. Signed-off-by: David Howells --- fs/fscache/cookie.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++ fs/fscache/internal.h | 1 fs/fscache/proc.c | 7 +++ include/linux/fscache.h | 1 4 files changed, 112 insertions(+) diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index f2be98d2c64d..c7047544972b 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -19,6 +19,8 @@ static atomic_t fscache_object_debug_id = ATOMIC_INIT(0); #define fscache_cookie_hash_shift 15 static struct hlist_bl_head fscache_cookie_hash[1 << fscache_cookie_hash_shift]; +static LIST_HEAD(fscache_cookies); +static DEFINE_RWLOCK(fscache_cookies_lock); static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie, loff_t object_size); @@ -65,6 +67,9 @@ void fscache_free_cookie(struct fscache_cookie *cookie) { if (cookie) { BUG_ON(!hlist_empty(&cookie->backing_objects)); + write_lock(&fscache_cookies_lock); + list_del(&cookie->proc_link); + write_unlock(&fscache_cookies_lock); if (cookie->aux_len > sizeof(cookie->inline_aux)) kfree(cookie->aux); if (cookie->key_len > sizeof(cookie->inline_key)) @@ -192,6 +197,10 @@ struct fscache_cookie *fscache_alloc_cookie( /* radix tree insertion won't use the preallocation pool unless it's * told it may not wait */ INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM); + + write_lock(&fscache_cookies_lock); + list_add_tail(&cookie->proc_link, &fscache_cookies); + write_unlock(&fscache_cookies_lock); return cookie; nomem: @@ -969,3 +978,97 @@ int __fscache_check_consistency(struct fscache_cookie *cookie, return -ESTALE; } EXPORT_SYMBOL(__fscache_check_consistency); + +/* + * Generate a list of extant cookies in /proc/fs/fscache/cookies + */ +static int fscache_cookies_seq_show(struct seq_file *m, void *v) +{ + struct fscache_cookie *cookie; + unsigned int keylen = 0, auxlen = 0; + char _type[3], *type; + u8 *p; + + if (v == &fscache_cookies) { + seq_puts(m, + "COOKIE PARENT USAGE CHILD ACT TY FL DEF NETFS_DATA\n" + "======== ======== ===== ===== === == === ================ ==========\n" + ); + return 0; + } + + cookie = list_entry(v, struct fscache_cookie, proc_link); + + switch (cookie->type) { + case 0: + type = "IX"; + break; + case 1: + type = "DT"; + break; + default: + snprintf(_type, sizeof(_type), "%02u", + cookie->type); + type = _type; + break; + } + + seq_printf(m, + "%08x %08x %5u %5u %3u %s %03lx %-16s %px", + cookie->debug_id, + cookie->parent ? cookie->parent->debug_id : 0, + atomic_read(&cookie->usage), + atomic_read(&cookie->n_children), + atomic_read(&cookie->n_active), + type, + cookie->flags, + cookie->def->name, + cookie->netfs_data); + + keylen = cookie->key_len; + auxlen = cookie->aux_len; + + if (keylen > 0 || auxlen > 0) { + seq_puts(m, " "); + p = keylen <= sizeof(cookie->inline_key) ? + cookie->inline_key : cookie->key; + for (; keylen > 0; keylen--) + seq_printf(m, "%02x", *p++); + if (auxlen > 0) { + seq_puts(m, ", "); + p = auxlen <= sizeof(cookie->inline_aux) ? + cookie->inline_aux : cookie->aux; + for (; auxlen > 0; auxlen--) + seq_printf(m, "%02x", *p++); + } + } + + seq_puts(m, "\n"); + return 0; +} + +static void *fscache_cookies_seq_start(struct seq_file *m, loff_t *_pos) + __acquires(fscache_cookies_lock) +{ + read_lock(&fscache_cookies_lock); + return seq_list_start_head(&fscache_cookies, *_pos); +} + +static void *fscache_cookies_seq_next(struct seq_file *m, void *v, loff_t *_pos) +{ + return seq_list_next(v, &fscache_cookies, _pos); +} + +static void fscache_cookies_seq_stop(struct seq_file *m, void *v) + __releases(rcu) +{ + read_unlock(&fscache_cookies_lock); +} + + +const struct seq_operations fscache_cookies_seq_ops = { + .start = fscache_cookies_seq_start, + .next = fscache_cookies_seq_next, + .stop = fscache_cookies_seq_stop, + .show = fscache_cookies_seq_show, +}; diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 08e91efbce53..4b535c2dae4a 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -45,6 +45,7 @@ extern struct fscache_cache *fscache_select_cache_for_object( * cookie.c */ extern struct kmem_cache *fscache_cookie_jar; +extern const struct seq_operations fscache_cookies_seq_ops; extern void fscache_free_cookie(struct fscache_cookie *); extern struct fscache_cookie *fscache_alloc_cookie(struct fscache_cookie *, diff --git a/fs/fscache/proc.c b/fs/fscache/proc.c index 90a7bc22f7e1..da51fdfc8641 100644 --- a/fs/fscache/proc.c +++ b/fs/fscache/proc.c @@ -21,6 +21,10 @@ int __init fscache_proc_init(void) if (!proc_mkdir("fs/fscache", NULL)) goto error_dir; + if (!proc_create_seq("fs/fscache/cookies", S_IFREG | 0444, NULL, + &fscache_cookies_seq_ops)) + goto error_cookies; + #ifdef CONFIG_FSCACHE_STATS if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL, fscache_stats_show)) @@ -53,6 +57,8 @@ int __init fscache_proc_init(void) remove_proc_entry("fs/fscache/stats", NULL); error_stats: #endif + remove_proc_entry("fs/fscache/cookies", NULL); +error_cookies: remove_proc_entry("fs/fscache", NULL); error_dir: _leave(" = -ENOMEM"); @@ -73,5 +79,6 @@ void fscache_proc_cleanup(void) #ifdef CONFIG_FSCACHE_STATS remove_proc_entry("fs/fscache/stats", NULL); #endif + remove_proc_entry("fs/fscache/cookies", NULL); remove_proc_entry("fs/fscache", NULL); } diff --git a/include/linux/fscache.h b/include/linux/fscache.h index f31df9a075f6..2606fe7edd29 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -141,6 +141,7 @@ struct fscache_cookie { const struct fscache_cookie_def *def; /* definition */ struct fscache_cookie *parent; /* parent of this entry */ struct hlist_bl_node hash_link; /* Link in hash table */ + struct list_head proc_link; /* Link in proc list */ void *netfs_data; /* back pointer to netfs */ struct radix_tree_root stores; /* pages to be stored on this cookie */ #define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */ From patchwork Fri Nov 20 15:03:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329229 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, UNWANTED_LANGUAGE_BODY autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20A36C63777 for ; Fri, 20 Nov 2020 15:05:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B7165221F8 for ; Fri, 20 Nov 2020 15:05:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="bs90FKWC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728474AbgKTPEN (ORCPT ); Fri, 20 Nov 2020 10:04:13 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:49429 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728408AbgKTPEM (ORCPT ); Fri, 20 Nov 2020 10:04:12 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884646; 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=pc91uKcoaNabkc5j9yzLyhrGzya1Wd5jdjqeBJLyAJs=; b=bs90FKWC+sLPst4LYkt14jp365StuPlkYIat9mVkhzsHJ4kCx9Cg6waTw8HBvjAHwtfACa 8OzLImUd728tzaHGg3r60mU7FED4WHsC+2E7uca2BAmG7IuMGJgc8KXYYXlZ851NEgepWH iEmh6nVunvJG9sM0GvcSsUoy8iDDG4M= 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-201-IQPxjQIrOwu6AKwM6JRdLg-1; Fri, 20 Nov 2020 10:04:04 -0500 X-MC-Unique: IQPxjQIrOwu6AKwM6JRdLg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2B76D801B2C; Fri, 20 Nov 2020 15:04:02 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id C93E95D6AD; Fri, 20 Nov 2020 15:03:55 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 06/76] fscache: Remove the netfs data from the cookie From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:03:54 +0000 Message-ID: <160588463494.3465195.6612093184241882813.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Remove the netfs data pointer from the cookie so that we don't refer back to the netfs state and don't need accessors to manage this. Keep the information we do need (of which there's not actually a lot) in the cookie which we can keep hold of if the netfs state goes away. Signed-off-by: David Howells --- fs/afs/cache.c | 39 -------- fs/afs/cell.c | 3 - fs/afs/inode.c | 3 - fs/afs/volume.c | 4 - fs/cachefiles/interface.c | 104 +++------------------ fs/cachefiles/internal.h | 20 +--- fs/cachefiles/namei.c | 10 +- fs/cachefiles/xattr.c | 204 +++++++---------------------------------- fs/fscache/cache.c | 20 +--- fs/fscache/cookie.c | 37 ++++--- fs/fscache/fsdef.c | 37 ------- fs/fscache/internal.h | 29 ++++-- fs/fscache/netfs.c | 3 - fs/fscache/object-list.c | 9 +- fs/fscache/object.c | 48 ---------- fs/nfs/fscache-index.c | 4 - include/linux/fscache-cache.h | 32 +++++- include/linux/fscache.h | 39 +------- 18 files changed, 144 insertions(+), 501 deletions(-) diff --git a/fs/afs/cache.c b/fs/afs/cache.c index 037af93e3aba..9b2de3014dbf 100644 --- a/fs/afs/cache.c +++ b/fs/afs/cache.c @@ -8,11 +8,6 @@ #include #include "internal.h" -static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, - const void *buffer, - uint16_t buflen, - loff_t object_size); - struct fscache_netfs afs_cache_netfs = { .name = "afs", .version = 2, @@ -31,38 +26,4 @@ struct fscache_cookie_def afs_volume_cache_index_def = { struct fscache_cookie_def afs_vnode_cache_index_def = { .name = "AFS.vnode", .type = FSCACHE_COOKIE_TYPE_DATAFILE, - .check_aux = afs_vnode_cache_check_aux, }; - -/* - * check that the auxiliary data indicates that the entry is still valid - */ -static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, - const void *buffer, - uint16_t buflen, - loff_t object_size) -{ - struct afs_vnode *vnode = cookie_netfs_data; - struct afs_vnode_cache_aux aux; - - _enter("{%llx,%x,%llx},%p,%u", - vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, - buffer, buflen); - - memcpy(&aux, buffer, sizeof(aux)); - - /* check the size of the data is what we're expecting */ - if (buflen != sizeof(aux)) { - _leave(" = OBSOLETE [len %hx != %zx]", buflen, sizeof(aux)); - return FSCACHE_CHECKAUX_OBSOLETE; - } - - if (vnode->status.data_version != aux.data_version) { - _leave(" = OBSOLETE [vers %llx != %llx]", - aux.data_version, vnode->status.data_version); - return FSCACHE_CHECKAUX_OBSOLETE; - } - - _leave(" = SUCCESS"); - return FSCACHE_CHECKAUX_OKAY; -} diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 887b673f6223..d4cc13ce847b 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c @@ -681,9 +681,10 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) #ifdef CONFIG_AFS_FSCACHE cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index, &afs_cell_cache_index_def, + NULL, cell->name, strlen(cell->name), NULL, 0, - cell, 0, true); + 0, true); #endif ret = afs_proc_cell_setup(cell); if (ret < 0) diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 79c8dc06c0b8..883fa9f67520 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -433,9 +433,10 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) vnode->cache = fscache_acquire_cookie(vnode->volume->cache, &afs_vnode_cache_index_def, + NULL, &key, sizeof(key), &aux, sizeof(aux), - vnode, vnode->status.size, true); + vnode->status.size, true); #endif } diff --git a/fs/afs/volume.c b/fs/afs/volume.c index f84194b791d3..9ca246ab1a86 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c @@ -273,9 +273,9 @@ void afs_activate_volume(struct afs_volume *volume) #ifdef CONFIG_AFS_FSCACHE volume->cache = fscache_acquire_cookie(volume->cell->cache, &afs_volume_cache_index_def, + NULL, &volume->vid, sizeof(volume->vid), - NULL, 0, - volume, 0, true); + NULL, 0, 0, true); #endif } diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 04d92ad402a4..530ed11bb213 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -7,13 +7,9 @@ #include #include +#include #include "internal.h" -struct cachefiles_lookup_data { - struct cachefiles_xattr *auxdata; /* auxiliary data */ - char *key; /* key path */ -}; - static int cachefiles_attr_changed(struct fscache_object *_object); /* @@ -23,11 +19,9 @@ static struct fscache_object *cachefiles_alloc_object( struct fscache_cache *_cache, struct fscache_cookie *cookie) { - struct cachefiles_lookup_data *lookup_data; struct cachefiles_object *object; struct cachefiles_cache *cache; - struct cachefiles_xattr *auxdata; - unsigned keylen, auxlen; + unsigned keylen; void *buffer, *p; char *key; @@ -35,10 +29,6 @@ static struct fscache_object *cachefiles_alloc_object( _enter("{%s},%p,", cache->cache.identifier, cookie); - lookup_data = kmalloc(sizeof(*lookup_data), cachefiles_gfp); - if (!lookup_data) - goto nomem_lookup_data; - /* create a new object record and a temporary leaf image */ object = kmem_cache_alloc(cachefiles_object_jar, cachefiles_gfp); if (!object) @@ -62,10 +52,7 @@ static struct fscache_object *cachefiles_alloc_object( goto nomem_buffer; keylen = cookie->key_len; - if (keylen <= sizeof(cookie->inline_key)) - p = cookie->inline_key; - else - p = cookie->key; + p = fscache_get_key(cookie); memcpy(buffer + 2, p, keylen); *(uint16_t *)buffer = keylen; @@ -75,28 +62,13 @@ static struct fscache_object *cachefiles_alloc_object( /* turn the raw key into something that can work with as a filename */ key = cachefiles_cook_key(buffer, keylen + 2, object->type); + kfree(buffer); if (!key) goto nomem_key; - /* get hold of the auxiliary data and prepend the object type */ - auxdata = buffer; - auxlen = cookie->aux_len; - if (auxlen) { - if (auxlen <= sizeof(cookie->inline_aux)) - p = cookie->inline_aux; - else - p = cookie->aux; - memcpy(auxdata->data, p, auxlen); - } - - auxdata->len = auxlen + 1; - auxdata->type = cookie->type; - - lookup_data->auxdata = auxdata; - lookup_data->key = key; - object->lookup_data = lookup_data; + object->lookup_key = key; - _leave(" = %p [%p]", &object->fscache, lookup_data); + _leave(" = %p [%s]", &object->fscache, key); return &object->fscache; nomem_key: @@ -106,8 +78,6 @@ static struct fscache_object *cachefiles_alloc_object( kmem_cache_free(cachefiles_object_jar, object); fscache_object_destroyed(&cache->cache); nomem_object: - kfree(lookup_data); -nomem_lookup_data: _leave(" = -ENOMEM"); return ERR_PTR(-ENOMEM); } @@ -118,7 +88,6 @@ static struct fscache_object *cachefiles_alloc_object( */ static int cachefiles_lookup_object(struct fscache_object *_object) { - struct cachefiles_lookup_data *lookup_data; struct cachefiles_object *parent, *object; struct cachefiles_cache *cache; const struct cred *saved_cred; @@ -130,15 +99,12 @@ static int cachefiles_lookup_object(struct fscache_object *_object) parent = container_of(_object->parent, struct cachefiles_object, fscache); object = container_of(_object, struct cachefiles_object, fscache); - lookup_data = object->lookup_data; - ASSERTCMP(lookup_data, !=, NULL); + ASSERTCMP(object->lookup_key, !=, NULL); /* look up the key, creating any missing bits */ cachefiles_begin_secure(cache, &saved_cred); - ret = cachefiles_walk_to_object(parent, object, - lookup_data->key, - lookup_data->auxdata); + ret = cachefiles_walk_to_object(parent, object, object->lookup_key); cachefiles_end_secure(cache, saved_cred); /* polish off by setting the attributes of non-index files */ @@ -165,14 +131,10 @@ static void cachefiles_lookup_complete(struct fscache_object *_object) object = container_of(_object, struct cachefiles_object, fscache); - _enter("{OBJ%x,%p}", object->fscache.debug_id, object->lookup_data); + _enter("{OBJ%x}", object->fscache.debug_id); - if (object->lookup_data) { - kfree(object->lookup_data->key); - kfree(object->lookup_data->auxdata); - kfree(object->lookup_data); - object->lookup_data = NULL; - } + kfree(object->lookup_key); + object->lookup_key = NULL; } /* @@ -204,12 +166,8 @@ struct fscache_object *cachefiles_grab_object(struct fscache_object *_object, static void cachefiles_update_object(struct fscache_object *_object) { struct cachefiles_object *object; - struct cachefiles_xattr *auxdata; struct cachefiles_cache *cache; - struct fscache_cookie *cookie; const struct cred *saved_cred; - const void *aux; - unsigned auxlen; _enter("{OBJ%x}", _object->debug_id); @@ -217,40 +175,9 @@ static void cachefiles_update_object(struct fscache_object *_object) cache = container_of(object->fscache.cache, struct cachefiles_cache, cache); - if (!fscache_use_cookie(_object)) { - _leave(" [relinq]"); - return; - } - - cookie = object->fscache.cookie; - auxlen = cookie->aux_len; - - if (!auxlen) { - fscache_unuse_cookie(_object); - _leave(" [no aux]"); - return; - } - - auxdata = kmalloc(2 + auxlen + 3, cachefiles_gfp); - if (!auxdata) { - fscache_unuse_cookie(_object); - _leave(" [nomem]"); - return; - } - - aux = (auxlen <= sizeof(cookie->inline_aux)) ? - cookie->inline_aux : cookie->aux; - - memcpy(auxdata->data, aux, auxlen); - fscache_unuse_cookie(_object); - - auxdata->len = auxlen + 1; - auxdata->type = cookie->type; - cachefiles_begin_secure(cache, &saved_cred); - cachefiles_update_object_xattr(object, auxdata); + cachefiles_set_object_xattr(object, XATTR_REPLACE); cachefiles_end_secure(cache, saved_cred); - kfree(auxdata); _leave(""); } @@ -354,12 +281,7 @@ static void cachefiles_put_object(struct fscache_object *_object, ASSERTCMP(object->fscache.n_ops, ==, 0); ASSERTCMP(object->fscache.n_children, ==, 0); - if (object->lookup_data) { - kfree(object->lookup_data->key); - kfree(object->lookup_data->auxdata); - kfree(object->lookup_data); - object->lookup_data = NULL; - } + kfree(object->lookup_key); cache = object->fscache.cache; fscache_object_destroy(&object->fscache); diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index aca73c8403ab..a5d48f271ce1 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -34,7 +34,7 @@ extern unsigned cachefiles_debug; */ struct cachefiles_object { struct fscache_object fscache; /* fscache handle */ - struct cachefiles_lookup_data *lookup_data; /* cached lookup data */ + char *lookup_key; /* key to look up */ struct dentry *dentry; /* the file/dir representing this object */ struct dentry *backer; /* backing file */ loff_t i_size; /* object size */ @@ -88,15 +88,6 @@ struct cachefiles_cache { char *tag; /* cache binding tag */ }; -/* - * auxiliary data xattr buffer - */ -struct cachefiles_xattr { - uint16_t len; - uint8_t type; - uint8_t data[]; -}; - #include /* @@ -142,8 +133,7 @@ extern int cachefiles_delete_object(struct cachefiles_cache *cache, struct cachefiles_object *object); extern int cachefiles_walk_to_object(struct cachefiles_object *parent, struct cachefiles_object *object, - const char *key, - struct cachefiles_xattr *auxdata); + const char *key); extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, struct dentry *dir, const char *name); @@ -204,12 +194,8 @@ static inline void cachefiles_end_secure(struct cachefiles_cache *cache, */ extern int cachefiles_check_object_type(struct cachefiles_object *object); extern int cachefiles_set_object_xattr(struct cachefiles_object *object, - struct cachefiles_xattr *auxdata); -extern int cachefiles_update_object_xattr(struct cachefiles_object *object, - struct cachefiles_xattr *auxdata); + unsigned int xattr_flags); extern int cachefiles_check_auxdata(struct cachefiles_object *object); -extern int cachefiles_check_object_xattr(struct cachefiles_object *object, - struct cachefiles_xattr *auxdata); extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, struct dentry *dentry); diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index ecc8ecbbfa5a..432002080b83 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -45,11 +45,10 @@ void __cachefiles_printk_object(struct cachefiles_object *object, spin_lock(&object->fscache.lock); cookie = object->fscache.cookie; if (cookie) { - pr_err("%scookie=%p [pr=%p nd=%p fl=%lx]\n", + pr_err("%scookie=%p [pr=%p fl=%lx]\n", prefix, object->fscache.cookie, object->fscache.cookie->parent, - object->fscache.cookie->netfs_data, object->fscache.cookie->flags); pr_err("%skey=[%u] '", prefix, cookie->key_len); k = (cookie->key_len <= sizeof(cookie->inline_key)) ? @@ -481,8 +480,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache, */ int cachefiles_walk_to_object(struct cachefiles_object *parent, struct cachefiles_object *object, - const char *key, - struct cachefiles_xattr *auxdata) + const char *key) { struct cachefiles_cache *cache; struct dentry *dir, *next = NULL; @@ -636,7 +634,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, if (!object->new) { _debug("validate '%pd'", next); - ret = cachefiles_check_object_xattr(object, auxdata); + ret = cachefiles_check_auxdata(object); if (ret == -ESTALE) { /* delete the object (the deleter drops the directory * mutex) */ @@ -671,7 +669,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, if (object->new) { /* attach data to a newly constructed terminal object */ - ret = cachefiles_set_object_xattr(object, auxdata); + ret = cachefiles_set_object_xattr(object, XATTR_CREATE); if (ret < 0) goto check_error; } else { diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index 72e42438f3d7..5ab8643ca97a 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -15,6 +15,11 @@ #include #include "internal.h" +struct cachefiles_xattr { + uint8_t type; + uint8_t data[]; +} __packed; + static const char cachefiles_xattr_cache[] = XATTR_USER_PREFIX "CacheFiles.cache"; @@ -97,56 +102,35 @@ int cachefiles_check_object_type(struct cachefiles_object *object) * set the state xattr on a cache file */ int cachefiles_set_object_xattr(struct cachefiles_object *object, - struct cachefiles_xattr *auxdata) -{ - struct dentry *dentry = object->dentry; - int ret; - - ASSERT(dentry); - - _enter("%p,#%d", object, auxdata->len); - - /* attempt to install the cache metadata directly */ - _debug("SET #%u", auxdata->len); - - clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags); - ret = vfs_setxattr(dentry, cachefiles_xattr_cache, - &auxdata->type, auxdata->len, - XATTR_CREATE); - if (ret < 0 && ret != -ENOMEM) - cachefiles_io_error_obj( - object, - "Failed to set xattr with error %d", ret); - - _leave(" = %d", ret); - return ret; -} - -/* - * update the state xattr on a cache file - */ -int cachefiles_update_object_xattr(struct cachefiles_object *object, - struct cachefiles_xattr *auxdata) + unsigned int xattr_flags) { + struct cachefiles_xattr *buf; struct dentry *dentry = object->dentry; + unsigned int len = object->fscache.cookie->aux_len; int ret; if (!dentry) return -ESTALE; - _enter("%p,#%d", object, auxdata->len); + _enter("%p,#%d", object, len); - /* attempt to install the cache metadata directly */ - _debug("SET #%u", auxdata->len); + buf = kmalloc(sizeof(struct cachefiles_xattr) + len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf->type = object->fscache.cookie->def->type; + if (len > 0) + memcpy(buf->data, fscache_get_aux(object->fscache.cookie), len); clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags); ret = vfs_setxattr(dentry, cachefiles_xattr_cache, - &auxdata->type, auxdata->len, - XATTR_REPLACE); + buf, sizeof(struct cachefiles_xattr) + len, + xattr_flags); + kfree(buf); if (ret < 0 && ret != -ENOMEM) cachefiles_io_error_obj( object, - "Failed to update xattr with error %d", ret); + "Failed to set xattr with error %d", ret); _leave(" = %d", ret); return ret; @@ -157,148 +141,30 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object, */ int cachefiles_check_auxdata(struct cachefiles_object *object) { - struct cachefiles_xattr *auxbuf; - enum fscache_checkaux validity; + struct cachefiles_xattr *buf; struct dentry *dentry = object->dentry; - ssize_t xlen; - int ret; + unsigned int len = object->fscache.cookie->aux_len, tlen; + const void *p = fscache_get_aux(object->fscache.cookie); + ssize_t ret; ASSERT(dentry); ASSERT(d_backing_inode(dentry)); - ASSERT(object->fscache.cookie->def->check_aux); - auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL); - if (!auxbuf) + tlen = sizeof(struct cachefiles_xattr) + len; + buf = kmalloc(tlen, GFP_KERNEL); + if (!buf) return -ENOMEM; - xlen = vfs_getxattr(dentry, cachefiles_xattr_cache, - &auxbuf->type, 512 + 1); - ret = -ESTALE; - if (xlen < 1 || - auxbuf->type != object->fscache.cookie->def->type) - goto error; - - xlen--; - validity = fscache_check_aux(&object->fscache, &auxbuf->data, xlen, - i_size_read(d_backing_inode(dentry))); - if (validity != FSCACHE_CHECKAUX_OKAY) - goto error; - - ret = 0; -error: - kfree(auxbuf); - return ret; -} - -/* - * check the state xattr on a cache file - * - return -ESTALE if the object should be deleted - */ -int cachefiles_check_object_xattr(struct cachefiles_object *object, - struct cachefiles_xattr *auxdata) -{ - struct cachefiles_xattr *auxbuf; - struct dentry *dentry = object->dentry; - int ret; - - _enter("%p,#%d", object, auxdata->len); - - ASSERT(dentry); - ASSERT(d_backing_inode(dentry)); - - auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, cachefiles_gfp); - if (!auxbuf) { - _leave(" = -ENOMEM"); - return -ENOMEM; - } - - /* read the current type label */ - ret = vfs_getxattr(dentry, cachefiles_xattr_cache, - &auxbuf->type, 512 + 1); - if (ret < 0) { - if (ret == -ENODATA) - goto stale; /* no attribute - power went off - * mid-cull? */ - - if (ret == -ERANGE) - goto bad_type_length; - - cachefiles_io_error_obj(object, - "Can't read xattr on %lu (err %d)", - d_backing_inode(dentry)->i_ino, -ret); - goto error; - } - - /* check the on-disk object */ - if (ret < 1) - goto bad_type_length; - - if (auxbuf->type != auxdata->type) - goto stale; - - auxbuf->len = ret; - - /* consult the netfs */ - if (object->fscache.cookie->def->check_aux) { - enum fscache_checkaux result; - unsigned int dlen; - - dlen = auxbuf->len - 1; - - _debug("checkaux %s #%u", - object->fscache.cookie->def->name, dlen); - - result = fscache_check_aux(&object->fscache, - &auxbuf->data, dlen, - i_size_read(d_backing_inode(dentry))); - - switch (result) { - /* entry okay as is */ - case FSCACHE_CHECKAUX_OKAY: - goto okay; - - /* entry requires update */ - case FSCACHE_CHECKAUX_NEEDS_UPDATE: - break; - - /* entry requires deletion */ - case FSCACHE_CHECKAUX_OBSOLETE: - goto stale; - - default: - BUG(); - } - - /* update the current label */ - ret = vfs_setxattr(dentry, cachefiles_xattr_cache, - &auxdata->type, auxdata->len, - XATTR_REPLACE); - if (ret < 0) { - cachefiles_io_error_obj(object, - "Can't update xattr on %lu" - " (error %d)", - d_backing_inode(dentry)->i_ino, -ret); - goto error; - } - } - -okay: - ret = 0; + ret = vfs_getxattr(dentry, cachefiles_xattr_cache, buf, tlen); + if (ret == tlen && + buf->type == object->fscache.cookie->def->type && + memcmp(buf->data, p, len) == 0) + ret = 0; + else + ret = -ESTALE; -error: - kfree(auxbuf); - _leave(" = %d", ret); + kfree(buf); return ret; - -bad_type_length: - pr_err("Cache object %lu xattr length incorrect\n", - d_backing_inode(dentry)->i_ino); - ret = -EIO; - goto error; - -stale: - ret = -ESTALE; - goto error; } /* diff --git a/fs/fscache/cache.c b/fs/fscache/cache.c index 7de6d4cd29ee..2231691845b8 100644 --- a/fs/fscache/cache.c +++ b/fs/fscache/cache.c @@ -30,6 +30,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name) list_for_each_entry(tag, &fscache_cache_tag_list, link) { if (strcmp(tag->name, name) == 0) { atomic_inc(&tag->usage); + refcount_inc(&tag->ref); up_read(&fscache_addremove_sem); return tag; } @@ -44,6 +45,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name) return ERR_PTR(-ENOMEM); atomic_set(&xtag->usage, 1); + refcount_set(&xtag->ref, 1); strcpy(xtag->name, name); /* write lock, search again and add if still not present */ @@ -52,6 +54,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name) list_for_each_entry(tag, &fscache_cache_tag_list, link) { if (strcmp(tag->name, name) == 0) { atomic_inc(&tag->usage); + refcount_inc(&tag->ref); up_write(&fscache_addremove_sem); kfree(xtag); return tag; @@ -64,7 +67,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name) } /* - * release a reference to a cache tag + * Unuse a cache tag */ void __fscache_release_cache_tag(struct fscache_cache_tag *tag) { @@ -77,8 +80,7 @@ void __fscache_release_cache_tag(struct fscache_cache_tag *tag) tag = NULL; up_write(&fscache_addremove_sem); - - kfree(tag); + fscache_put_cache_tag(tag); } } @@ -130,20 +132,10 @@ struct fscache_cache *fscache_select_cache_for_object( spin_unlock(&cookie->lock); - if (!cookie->def->select_cache) - goto no_preference; - - /* ask the netfs for its preference */ - tag = cookie->def->select_cache(cookie->parent->netfs_data, - cookie->netfs_data); + tag = cookie->preferred_cache; if (!tag) goto no_preference; - if (tag == ERR_PTR(-ENOMEM)) { - _leave(" = NULL [nomem tag]"); - return NULL; - } - if (!tag->cache) { _leave(" = NULL [unbacked tag]"); return NULL; diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index b35f727cc0d4..e38f02589077 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -43,11 +43,10 @@ static void fscache_print_cookie(struct fscache_cookie *cookie, char prefix) cookie->flags, atomic_read(&cookie->n_children), atomic_read(&cookie->n_active)); - pr_err("%c-cookie d=%p{%s} n=%p\n", + pr_err("%c-cookie d=%p{%s}\n", prefix, cookie->def, - cookie->def ? cookie->def->name : "?", - cookie->netfs_data); + cookie->def ? cookie->def->name : "?"); o = READ_ONCE(cookie->backing_objects.first); if (o) { @@ -74,6 +73,7 @@ void fscache_free_cookie(struct fscache_cookie *cookie) kfree(cookie->aux); if (cookie->key_len > sizeof(cookie->inline_key)) kfree(cookie->key); + fscache_put_cache_tag(cookie->preferred_cache); kmem_cache_free(fscache_cookie_jar, cookie); } } @@ -150,9 +150,9 @@ static atomic_t fscache_cookie_debug_id = ATOMIC_INIT(1); struct fscache_cookie *fscache_alloc_cookie( struct fscache_cookie *parent, const struct fscache_cookie_def *def, + struct fscache_cache_tag *preferred_cache, const void *index_key, size_t index_key_len, const void *aux_data, size_t aux_data_len, - void *netfs_data, loff_t object_size) { struct fscache_cookie *cookie; @@ -187,7 +187,9 @@ struct fscache_cookie *fscache_alloc_cookie( cookie->def = def; cookie->parent = parent; - cookie->netfs_data = netfs_data; + + cookie->preferred_cache = fscache_get_cache_tag(preferred_cache); + cookie->flags = (1 << FSCACHE_COOKIE_NO_DATA_YET); cookie->type = def->type; spin_lock_init(&cookie->lock); @@ -252,7 +254,6 @@ struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *candidate) * - the top level index cookie for each netfs is stored in the fscache_netfs * struct upon registration * - def points to the definition - * - the netfs_data will be passed to the functions pointed to in *def * - all attached caches will be searched to see if they contain this object * - index objects aren't stored on disk until there's a dependent file that * needs storing @@ -264,9 +265,9 @@ struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *candidate) struct fscache_cookie *__fscache_acquire_cookie( struct fscache_cookie *parent, const struct fscache_cookie_def *def, + struct fscache_cache_tag *preferred_cache, const void *index_key, size_t index_key_len, const void *aux_data, size_t aux_data_len, - void *netfs_data, loff_t object_size, bool enable) { @@ -274,9 +275,9 @@ struct fscache_cookie *__fscache_acquire_cookie( BUG_ON(!def); - _enter("{%s},{%s},%p,%u", + _enter("{%s},{%s},%u", parent ? (char *) parent->def->name : "", - def->name, netfs_data, enable); + def->name, enable); if (!index_key || !index_key_len || index_key_len > 255 || aux_data_len > 255) return NULL; @@ -300,10 +301,10 @@ struct fscache_cookie *__fscache_acquire_cookie( BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX && parent->type != FSCACHE_COOKIE_TYPE_INDEX); - candidate = fscache_alloc_cookie(parent, def, + candidate = fscache_alloc_cookie(parent, def, preferred_cache, index_key, index_key_len, aux_data, aux_data_len, - netfs_data, object_size); + object_size); if (!candidate) { fscache_stat(&fscache_n_acquires_oom); _leave(" [ENOMEM]"); @@ -814,8 +815,8 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, return; } - _enter("%p{%s,%p,%d},%d", - cookie, cookie->def->name, cookie->netfs_data, + _enter("%p{%s,%d},%d", + cookie, cookie->def->name, atomic_read(&cookie->n_active), retire); trace_fscache_relinquish(cookie, retire); @@ -827,7 +828,6 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, __fscache_disable_cookie(cookie, aux_data, retire); /* Clear pointers back to the netfs */ - cookie->netfs_data = NULL; cookie->def = NULL; if (cookie->parent) { @@ -981,8 +981,8 @@ static int fscache_cookies_seq_show(struct seq_file *m, void *v) if (v == &fscache_cookies) { seq_puts(m, - "COOKIE PARENT USAGE CHILD ACT TY FL DEF NETFS_DATA\n" - "======== ======== ===== ===== === == === ================ ==========\n" + "COOKIE PARENT USAGE CHILD ACT TY FL DEF \n" + "======== ======== ===== ===== === == === ================\n" ); return 0; } @@ -1004,7 +1004,7 @@ static int fscache_cookies_seq_show(struct seq_file *m, void *v) } seq_printf(m, - "%08x %08x %5u %5u %3u %s %03lx %-16s %px", + "%08x %08x %5u %5u %3u %s %03lx %-16s", cookie->debug_id, cookie->parent ? cookie->parent->debug_id : 0, atomic_read(&cookie->usage), @@ -1012,8 +1012,7 @@ static int fscache_cookies_seq_show(struct seq_file *m, void *v) atomic_read(&cookie->n_active), type, cookie->flags, - cookie->def->name, - cookie->netfs_data); + cookie->def->name); keylen = cookie->key_len; auxlen = cookie->aux_len; diff --git a/fs/fscache/fsdef.c b/fs/fscache/fsdef.c index 5f8f6fe243fe..0e2e242121fe 100644 --- a/fs/fscache/fsdef.c +++ b/fs/fscache/fsdef.c @@ -9,12 +9,6 @@ #include #include "internal.h" -static -enum fscache_checkaux fscache_fsdef_netfs_check_aux(void *cookie_netfs_data, - const void *data, - uint16_t datalen, - loff_t object_size); - /* * The root index is owned by FS-Cache itself. * @@ -64,35 +58,4 @@ EXPORT_SYMBOL(fscache_fsdef_index); struct fscache_cookie_def fscache_fsdef_netfs_def = { .name = "FSDEF.netfs", .type = FSCACHE_COOKIE_TYPE_INDEX, - .check_aux = fscache_fsdef_netfs_check_aux, }; - -/* - * check that the index structure version number stored in the auxiliary data - * matches the one the netfs gave us - */ -static enum fscache_checkaux fscache_fsdef_netfs_check_aux( - void *cookie_netfs_data, - const void *data, - uint16_t datalen, - loff_t object_size) -{ - struct fscache_netfs *netfs = cookie_netfs_data; - uint32_t version; - - _enter("{%s},,%hu", netfs->name, datalen); - - if (datalen != sizeof(version)) { - _leave(" = OBSOLETE [dl=%d v=%zu]", datalen, sizeof(version)); - return FSCACHE_CHECKAUX_OBSOLETE; - } - - memcpy(&version, data, sizeof(version)); - if (version != netfs->version) { - _leave(" = OBSOLETE [ver=%x net=%x]", version, netfs->version); - return FSCACHE_CHECKAUX_OBSOLETE; - } - - _leave(" = OKAY"); - return FSCACHE_CHECKAUX_OKAY; -} diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 83dfbe0e3964..7dc447f7f3b0 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -24,6 +24,7 @@ #define pr_fmt(fmt) "FS-Cache: " fmt +#include #include #include #include @@ -41,6 +42,20 @@ extern struct rw_semaphore fscache_addremove_sem; extern struct fscache_cache *fscache_select_cache_for_object( struct fscache_cookie *); +static inline +struct fscache_cache_tag *fscache_get_cache_tag(struct fscache_cache_tag *tag) +{ + if (tag) + refcount_inc(&tag->ref); + return tag; +} + +static inline void fscache_put_cache_tag(struct fscache_cache_tag *tag) +{ + if (tag && refcount_dec_and_test(&tag->ref)) + kfree(tag); +} + /* * cookie.c */ @@ -50,9 +65,10 @@ extern const struct seq_operations fscache_cookies_seq_ops; extern void fscache_free_cookie(struct fscache_cookie *); extern struct fscache_cookie *fscache_alloc_cookie(struct fscache_cookie *, const struct fscache_cookie_def *, + struct fscache_cache_tag *, const void *, size_t, const void *, size_t, - void *, loff_t); + loff_t); extern struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *); extern void fscache_cookie_put(struct fscache_cookie *, enum fscache_cookie_trace); @@ -329,16 +345,9 @@ static inline void fscache_cookie_get(struct fscache_cookie *cookie, static inline void fscache_update_aux(struct fscache_cookie *cookie, const void *aux_data) { - void *p; - - if (!aux_data) - return; - if (cookie->aux_len <= sizeof(cookie->inline_aux)) - p = cookie->inline_aux; - else - p = cookie->aux; + void *p = fscache_get_aux(cookie); - if (memcmp(p, aux_data, cookie->aux_len) != 0) { + if (p && memcmp(p, aux_data, cookie->aux_len) != 0) { memcpy(p, aux_data, cookie->aux_len); set_bit(FSCACHE_COOKIE_AUX_UPDATED, &cookie->flags); } diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c index cce92216fa28..8ce4c7fa11a0 100644 --- a/fs/fscache/netfs.c +++ b/fs/fscache/netfs.c @@ -22,9 +22,10 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) /* allocate a cookie for the primary index */ candidate = fscache_alloc_cookie(&fscache_fsdef_index, &fscache_fsdef_netfs_def, + NULL, netfs->name, strlen(netfs->name), &netfs->version, sizeof(netfs->version), - netfs, 0); + 0); if (!candidate) { _leave(" = -ENOMEM"); return -ENOMEM; diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index 1a0dc32c0a33..240e71d3faf2 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c @@ -170,7 +170,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v) if ((unsigned long) v == 1) { seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS" " EM EV FL S" - " | COOKIE NETFS_COOKIE_DEF TY FL NETFS_DATA"); + " | COOKIE NETFS_COOKIE_DEF TY FL"); if (config & (FSCACHE_OBJLIST_CONFIG_KEY | FSCACHE_OBJLIST_CONFIG_AUX)) seq_puts(m, " "); @@ -189,7 +189,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v) if ((unsigned long) v == 2) { seq_puts(m, "======== ======== ==== ===== === === === == =====" " == == == =" - " | ======== ================ == === ================"); + " | ======== ================ == ==="); if (config & (FSCACHE_OBJLIST_CONFIG_KEY | FSCACHE_OBJLIST_CONFIG_AUX)) seq_puts(m, " ================"); @@ -263,12 +263,11 @@ static int fscache_objlist_show(struct seq_file *m, void *v) break; } - seq_printf(m, "%08x %-16s %s %3lx %16p", + seq_printf(m, "%08x %-16s %s %3lx", cookie->debug_id, cookie->def->name, type, - cookie->flags, - cookie->netfs_data); + cookie->flags); if (config & FSCACHE_OBJLIST_CONFIG_KEY) keylen = cookie->key_len; diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 3d7f956a01c6..4ee9b5473c43 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -910,54 +910,6 @@ static void fscache_dequeue_object(struct fscache_object *object) _leave(""); } -/** - * fscache_check_aux - Ask the netfs whether an object on disk is still valid - * @object: The object to ask about - * @data: The auxiliary data for the object - * @datalen: The size of the auxiliary data - * - * This function consults the netfs about the coherency state of an object. - * The caller must be holding a ref on cookie->n_active (held by - * fscache_look_up_object() on behalf of the cache backend during object lookup - * and creation). - */ -enum fscache_checkaux fscache_check_aux(struct fscache_object *object, - const void *data, uint16_t datalen, - loff_t object_size) -{ - enum fscache_checkaux result; - - if (!object->cookie->def->check_aux) { - fscache_stat(&fscache_n_checkaux_none); - return FSCACHE_CHECKAUX_OKAY; - } - - result = object->cookie->def->check_aux(object->cookie->netfs_data, - data, datalen, object_size); - switch (result) { - /* entry okay as is */ - case FSCACHE_CHECKAUX_OKAY: - fscache_stat(&fscache_n_checkaux_okay); - break; - - /* entry requires update */ - case FSCACHE_CHECKAUX_NEEDS_UPDATE: - fscache_stat(&fscache_n_checkaux_update); - break; - - /* entry requires deletion */ - case FSCACHE_CHECKAUX_OBSOLETE: - fscache_stat(&fscache_n_checkaux_obsolete); - break; - - default: - BUG(); - } - - return result; -} -EXPORT_SYMBOL(fscache_check_aux); - /* * Asynchronously invalidate an object. */ diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c index 573b1da9342c..b1049815729e 100644 --- a/fs/nfs/fscache-index.c +++ b/fs/nfs/fscache-index.c @@ -106,7 +106,7 @@ enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data, * cache fails with EIO - in which case the server must be contacted to * retrieve the data, which requires the read context for security. */ -static void nfs_fh_get_context(void *cookie_netfs_data, void *context) +static void nfs_fh_get_context(void *context) { get_nfs_open_context(context); } @@ -116,7 +116,7 @@ static void nfs_fh_get_context(void *cookie_netfs_data, void *context) * - This function can be absent if the completion function doesn't require a * context. */ -static void nfs_fh_put_context(void *cookie_netfs_data, void *context) +static void nfs_fh_put_context(void *context) { if (context) put_nfs_open_context(context); diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index f01fe979b323..0b395bcb4b16 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -45,8 +45,9 @@ struct fscache_cache_tag { struct fscache_cache *cache; /* cache referred to by this tag */ unsigned long flags; #define FSCACHE_TAG_RESERVED 0 /* T if tag is reserved for a cache */ - atomic_t usage; - char name[]; /* tag name */ + atomic_t usage; /* Number of using netfs's */ + refcount_t ref; /* Reference count on structure */ + char name[]; /* tag name */ }; /* @@ -414,11 +415,6 @@ extern void fscache_io_error(struct fscache_cache *cache); extern bool fscache_object_sleep_till_congested(signed long *timeoutp); -extern enum fscache_checkaux fscache_check_aux(struct fscache_object *object, - const void *data, - uint16_t datalen, - loff_t object_size); - extern void fscache_object_retrying_stale(struct fscache_object *object); enum fscache_why_object_killed { @@ -430,4 +426,26 @@ enum fscache_why_object_killed { extern void fscache_object_mark_killed(struct fscache_object *object, enum fscache_why_object_killed why); +/* + * Find the key on a cookie. + */ +static inline void *fscache_get_key(struct fscache_cookie *cookie) +{ + if (cookie->key_len <= sizeof(cookie->inline_key)) + return cookie->inline_key; + else + return cookie->key; +} + +/* + * Find the auxiliary data on a cookie. + */ +static inline void *fscache_get_aux(struct fscache_cookie *cookie) +{ + if (cookie->aux_len <= sizeof(cookie->inline_aux)) + return cookie->inline_aux; + else + return cookie->aux; +} + #endif /* _LINUX_FSCACHE_CACHE_H */ diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 143d48281117..a9a11dff6eae 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -47,13 +47,6 @@ struct fscache_cache_tag; struct fscache_cookie; struct fscache_netfs; -/* result of index entry consultation */ -enum fscache_checkaux { - FSCACHE_CHECKAUX_OKAY, /* entry okay as is */ - FSCACHE_CHECKAUX_NEEDS_UPDATE, /* entry requires update */ - FSCACHE_CHECKAUX_OBSOLETE, /* entry requires deletion */ -}; - /* * fscache cookie definition */ @@ -65,26 +58,6 @@ struct fscache_cookie_def { uint8_t type; #define FSCACHE_COOKIE_TYPE_INDEX 0 #define FSCACHE_COOKIE_TYPE_DATAFILE 1 - - /* select the cache into which to insert an entry in this index - * - optional - * - should return a cache identifier or NULL to cause the cache to be - * inherited from the parent if possible or the first cache picked - * for a non-index file if not - */ - struct fscache_cache_tag *(*select_cache)( - const void *parent_netfs_data, - const void *cookie_netfs_data); - - /* consult the netfs about the state of an object - * - this function can be absent if the index carries no state data - * - the netfs data from the cookie being used as the target is - * presented, as is the auxiliary data and the object size - */ - enum fscache_checkaux (*check_aux)(void *cookie_netfs_data, - const void *data, - uint16_t datalen, - loff_t object_size); }; /* @@ -114,9 +87,9 @@ struct fscache_cookie { struct hlist_head backing_objects; /* object(s) backing this file/index */ const struct fscache_cookie_def *def; /* definition */ struct fscache_cookie *parent; /* parent of this entry */ + struct fscache_cache_tag *preferred_cache; /* The preferred cache or NULL */ struct hlist_bl_node hash_link; /* Link in hash table */ struct list_head proc_link; /* Link in proc list */ - void *netfs_data; /* back pointer to netfs */ unsigned long flags; #define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */ @@ -164,9 +137,10 @@ extern void __fscache_release_cache_tag(struct fscache_cache_tag *); extern struct fscache_cookie *__fscache_acquire_cookie( struct fscache_cookie *, const struct fscache_cookie_def *, + struct fscache_cache_tag *, const void *, size_t, const void *, size_t, - void *, loff_t, bool); + loff_t, bool); extern void __fscache_relinquish_cookie(struct fscache_cookie *, const void *, bool); extern int __fscache_check_consistency(struct fscache_cookie *, const void *); extern void __fscache_update_cookie(struct fscache_cookie *, const void *); @@ -252,6 +226,7 @@ void fscache_release_cache_tag(struct fscache_cache_tag *tag) * fscache_acquire_cookie - Acquire a cookie to represent a cache object * @parent: The cookie that's to be the parent of this one * @def: A description of the cache object, including callback operations + * @preferred_cache: The cache to use (or NULL) * @index_key: The index key for this cookie * @index_key_len: Size of the index key * @aux_data: The auxiliary data for the cookie (may be NULL) @@ -272,19 +247,19 @@ static inline struct fscache_cookie *fscache_acquire_cookie( struct fscache_cookie *parent, const struct fscache_cookie_def *def, + struct fscache_cache_tag *preferred_cache, const void *index_key, size_t index_key_len, const void *aux_data, size_t aux_data_len, - void *netfs_data, loff_t object_size, bool enable) { if (fscache_cookie_valid(parent) && fscache_cookie_enabled(parent)) - return __fscache_acquire_cookie(parent, def, + return __fscache_acquire_cookie(parent, def, preferred_cache, index_key, index_key_len, aux_data, aux_data_len, - netfs_data, object_size, enable); + object_size, enable); else return NULL; } From patchwork Fri Nov 20 15:04:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329228 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23BCAC8300E for ; Fri, 20 Nov 2020 15:05:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE8B9221F8 for ; Fri, 20 Nov 2020 15:05:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Jqh+vDb5" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728556AbgKTPEk (ORCPT ); Fri, 20 Nov 2020 10:04:40 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:60637 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728559AbgKTPEk (ORCPT ); Fri, 20 Nov 2020 10:04:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884677; 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=+Lwc8FigE37L+4nW2jzJksP6cB6pDm/AbbVYe2Mqo1k=; b=Jqh+vDb5sHBL87BWCAuFT1OaBF7c8fyhRVRnrvfw1PiY1/NlPhtvDuqDAlcQbfC8Wk4HK3 zNMDvgip6+0Axt7fPBGP2n0gvdIs/5DeAERSDUux+xZzJsaHehd5Dwokt/EmHJO758OP4P E8aCRrez/PxPVFdCakdZC1qh9tLdJJE= 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-403-Bnx6v679M_-ootiQ2y2CFA-1; Fri, 20 Nov 2020 10:04:34 -0500 X-MC-Unique: Bnx6v679M_-ootiQ2y2CFA-1 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 9B37B1009611; Fri, 20 Nov 2020 15:04:31 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED0F15C22A; Fri, 20 Nov 2020 15:04:22 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 08/76] fscache: Remove store_limit* from struct fscache_object From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:04:22 +0000 Message-ID: <160588466212.3465195.14611606565741215465.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Remove the store_limit values from struct fscache_object and store the object size in the cookie. The netfs can update this at will, and we don't want to call back into the netfs to fetch it. Signed-off-by: David Howells --- fs/cachefiles/interface.c | 10 ++-------- fs/fscache/cookie.c | 14 ++++++-------- fs/fscache/object.c | 2 -- include/linux/fscache-cache.h | 22 ---------------------- include/linux/fscache.h | 1 + 5 files changed, 9 insertions(+), 40 deletions(-) diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index b7aa5c733cb7..a5d348581bcc 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -359,7 +359,7 @@ static int cachefiles_attr_changed(struct fscache_object *_object) loff_t oi_size; int ret; - ni_size = _object->store_limit_l; + ni_size = _object->cookie->object_size; _enter("{OBJ%x},[%llu]", _object->debug_id, (unsigned long long) ni_size); @@ -376,8 +376,6 @@ static int cachefiles_attr_changed(struct fscache_object *_object) ASSERT(d_is_reg(object->backer)); - fscache_set_store_limit(&object->fscache, ni_size); - oi_size = i_size_read(d_backing_inode(object->backer)); if (oi_size == ni_size) return 0; @@ -406,7 +404,6 @@ static int cachefiles_attr_changed(struct fscache_object *_object) cachefiles_end_secure(cache, saved_cred); if (ret == -EIO) { - fscache_set_store_limit(&object->fscache, 0); cachefiles_io_error_obj(object, "Size set failed"); ret = -ENOBUFS; } @@ -431,7 +428,7 @@ static void cachefiles_invalidate_object(struct fscache_operation *op) cache = container_of(object->fscache.cache, struct cachefiles_cache, cache); - ni_size = op->object->store_limit_l; + ni_size = op->object->cookie->object_size; _enter("{OBJ%x},[%llu]", op->object->debug_id, (unsigned long long)ni_size); @@ -439,8 +436,6 @@ static void cachefiles_invalidate_object(struct fscache_operation *op) if (object->backer) { ASSERT(d_is_reg(object->backer)); - fscache_set_store_limit(&object->fscache, ni_size); - path.dentry = object->backer; path.mnt = cache->mnt; @@ -451,7 +446,6 @@ static void cachefiles_invalidate_object(struct fscache_operation *op) cachefiles_end_secure(cache, saved_cred); if (ret != 0) { - fscache_set_store_limit(&object->fscache, 0); if (ret == -EIO) cachefiles_io_error_obj(object, "Invalidate failed"); diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 32c070c929b9..7811fe935b47 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -22,8 +22,7 @@ static struct hlist_bl_head fscache_cookie_hash[1 << fscache_cookie_hash_shift]; static LIST_HEAD(fscache_cookies); static DEFINE_RWLOCK(fscache_cookies_lock); -static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie, - loff_t object_size); +static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie); static int fscache_alloc_object(struct fscache_cache *cache, struct fscache_cookie *cookie); static int fscache_attach_object(struct fscache_cookie *cookie, @@ -167,6 +166,7 @@ struct fscache_cookie *fscache_alloc_cookie( cookie->advice = advice; cookie->key_len = index_key_len; cookie->aux_len = aux_data_len; + cookie->object_size = object_size; strlcpy(cookie->type_name, type_name, sizeof(cookie->type_name)); if (fscache_set_key(cookie, index_key, index_key_len) < 0) @@ -337,7 +337,7 @@ struct fscache_cookie *__fscache_acquire_cookie( * - we create indices on disk when we need them as an index * may exist in multiple caches */ if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) { - if (fscache_acquire_non_index_cookie(cookie, object_size) == 0) { + if (fscache_acquire_non_index_cookie(cookie) == 0) { set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); } else { atomic_dec(&parent->n_children); @@ -376,6 +376,7 @@ void __fscache_enable_cookie(struct fscache_cookie *cookie, wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK, TASK_UNINTERRUPTIBLE); + cookie->object_size = object_size; fscache_update_aux(cookie, aux_data); if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags)) @@ -387,7 +388,7 @@ void __fscache_enable_cookie(struct fscache_cookie *cookie, /* Wait for outstanding disablement to complete */ __fscache_wait_on_invalidate(cookie); - if (fscache_acquire_non_index_cookie(cookie, object_size) == 0) + if (fscache_acquire_non_index_cookie(cookie) == 0) set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); } else { set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); @@ -404,8 +405,7 @@ EXPORT_SYMBOL(__fscache_enable_cookie); * - this must make sure the index chain is instantiated and instantiate the * object representation too */ -static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie, - loff_t object_size) +static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie) { struct fscache_object *object; struct fscache_cache *cache; @@ -456,8 +456,6 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie, object = hlist_entry(cookie->backing_objects.first, struct fscache_object, cookie_link); - fscache_set_store_limit(object, object_size); - /* initiate the process of looking up all the objects in the chain * (done by fscache_initialise_object()) */ fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD); diff --git a/fs/fscache/object.c b/fs/fscache/object.c index bb551e29454d..e2e04ac2c0a1 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -319,8 +319,6 @@ void fscache_object_init(struct fscache_object *object, object->n_children = 0; object->n_ops = object->n_in_progress = object->n_exclusive = 0; object->events = 0; - object->store_limit = 0; - object->store_limit_l = 0; object->cache = cache; object->cookie = cookie; fscache_cookie_get(cookie, fscache_cookie_get_attach_object); diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 0b395bcb4b16..fd07843e3d69 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -274,8 +274,6 @@ struct fscache_object { #ifdef CONFIG_FSCACHE_OBJECT_LIST struct rb_node objlist_link; /* link in global object list */ #endif - pgoff_t store_limit; /* current storage limit */ - loff_t store_limit_l; /* current storage limit */ }; extern void fscache_object_init(struct fscache_object *, struct fscache_cookie *, @@ -336,26 +334,6 @@ static inline void fscache_object_lookup_error(struct fscache_object *object) set_bit(FSCACHE_OBJECT_EV_ERROR, &object->events); } -/** - * fscache_set_store_limit - Set the maximum size to be stored in an object - * @object: The object to set the maximum on - * @i_size: The limit to set in bytes - * - * Set the maximum size an object is permitted to reach, implying the highest - * byte that may be written. Intended to be called by the attr_changed() op. - * - * See Documentation/filesystems/caching/backend-api.rst for a complete - * description. - */ -static inline -void fscache_set_store_limit(struct fscache_object *object, loff_t i_size) -{ - object->store_limit_l = i_size; - object->store_limit = i_size >> PAGE_SHIFT; - if (i_size & ~PAGE_MASK) - object->store_limit++; -} - static inline void __fscache_use_cookie(struct fscache_cookie *cookie) { atomic_inc(&cookie->n_active); diff --git a/include/linux/fscache.h b/include/linux/fscache.h index a930532a39d0..f855f6d04667 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -83,6 +83,7 @@ struct fscache_cookie { struct hlist_bl_node hash_link; /* Link in hash table */ struct list_head proc_link; /* Link in proc list */ char type_name[8]; /* Cookie type name */ + loff_t object_size; /* Size of the netfs object */ unsigned long flags; #define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */ From patchwork Fri Nov 20 15:04:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329227 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 143C7C64E69 for ; Fri, 20 Nov 2020 15:05:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B2C2222269 for ; Fri, 20 Nov 2020 15:05:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="hH3yCikX" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728606AbgKTPFD (ORCPT ); Fri, 20 Nov 2020 10:05:03 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:58666 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728595AbgKTPFB (ORCPT ); Fri, 20 Nov 2020 10:05:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884699; 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=0x+RB40tGqBs9eY+a+QbcqZos81z+ES4knWY5yzXwgg=; b=hH3yCikXZiDbFAKY1H6oelE/1Grglti27Fmo4N+g1MmibzSsLRqdFqBr44i+45UgFDsvne 4uek8f88iu9/8Vn2m0ECE2tRCDo5elXLi06j/u7IEZNyKmfBSRbq/eBrLSBMcCUxkbJkSt z+qcM3Hg47MtoGeeYhu9VqTw8J+FUNk= 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-382-G4rJUePFO_ymcfq8OOM2-Q-1; Fri, 20 Nov 2020 10:04:55 -0500 X-MC-Unique: G4rJUePFO_ymcfq8OOM2-Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CD49880EF83; Fri, 20 Nov 2020 15:04:53 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8D70260C15; Fri, 20 Nov 2020 15:04:47 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 10/76] fscache: Remove fscache_attr_changed() From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:04:46 +0000 Message-ID: <160588468676.3465195.6947215951308566547.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Remove fscache_attr_changed() as it's unused. Signed-off-by: David Howells --- fs/cachefiles/interface.c | 13 ++--- fs/fscache/Makefile | 3 - fs/fscache/page.c | 98 ----------------------------------------- include/linux/fscache-cache.h | 4 -- include/linux/fscache.h | 21 --------- 5 files changed, 6 insertions(+), 133 deletions(-) delete mode 100644 fs/fscache/page.c diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index a3837ed090a8..81322e3acadd 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -10,7 +10,7 @@ #include #include "internal.h" -static int cachefiles_attr_changed(struct fscache_object *_object); +static int cachefiles_attr_changed(struct cachefiles_object *object); /* * allocate an object record for a cookie lookup and prepare the lookup data @@ -110,7 +110,7 @@ static int cachefiles_lookup_object(struct fscache_object *_object) /* polish off by setting the attributes of non-index files */ if (ret == 0 && object->fscache.cookie->type != FSCACHE_COOKIE_TYPE_INDEX) - cachefiles_attr_changed(&object->fscache); + cachefiles_attr_changed(object); if (ret < 0 && ret != -ETIMEDOUT) { if (ret != -ENOBUFS) @@ -324,9 +324,8 @@ static void cachefiles_sync_cache(struct fscache_cache *_cache) * notification the attributes on an object have changed * - called with reads/writes excluded by FS-Cache */ -static int cachefiles_attr_changed(struct fscache_object *_object) +static int cachefiles_attr_changed(struct cachefiles_object *object) { - struct cachefiles_object *object; struct cachefiles_cache *cache; const struct cred *saved_cred; struct iattr newattrs; @@ -334,12 +333,11 @@ static int cachefiles_attr_changed(struct fscache_object *_object) loff_t oi_size; int ret; - ni_size = _object->cookie->object_size; + ni_size = object->fscache.cookie->object_size; _enter("{OBJ%x},[%llu]", - _object->debug_id, (unsigned long long) ni_size); + object->fscache.debug_id, (unsigned long long) ni_size); - object = container_of(_object, struct cachefiles_object, fscache); cache = container_of(object->fscache.cache, struct cachefiles_cache, cache); @@ -442,5 +440,4 @@ const struct fscache_cache_ops cachefiles_cache_ops = { .drop_object = cachefiles_drop_object, .put_object = cachefiles_put_object, .sync_cache = cachefiles_sync_cache, - .attr_changed = cachefiles_attr_changed, }; diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile index 79e08e05ef84..565a3441d31d 100644 --- a/fs/fscache/Makefile +++ b/fs/fscache/Makefile @@ -10,8 +10,7 @@ fscache-y := \ main.o \ netfs.o \ object.o \ - operation.o \ - page.o + operation.o fscache-$(CONFIG_PROC_FS) += proc.o fscache-$(CONFIG_FSCACHE_STATS) += stats.o diff --git a/fs/fscache/page.c b/fs/fscache/page.c deleted file mode 100644 index 73636e9d652d..000000000000 --- a/fs/fscache/page.c +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Cache page management and data I/O routines - * - * Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - */ - -#define FSCACHE_DEBUG_LEVEL PAGE -#include -#include -#include -#include -#include -#include "internal.h" - -/* - * actually apply the changed attributes to a cache object - */ -static void fscache_attr_changed_op(struct fscache_operation *op) -{ - struct fscache_object *object = op->object; - int ret; - - _enter("{OBJ%x OP%x}", object->debug_id, op->debug_id); - - fscache_stat(&fscache_n_attr_changed_calls); - - if (fscache_object_is_active(object)) { - fscache_stat(&fscache_n_cop_attr_changed); - ret = object->cache->ops->attr_changed(object); - fscache_stat_d(&fscache_n_cop_attr_changed); - if (ret < 0) - fscache_abort_object(object); - fscache_op_complete(op, ret < 0); - } else { - fscache_op_complete(op, true); - } - - _leave(""); -} - -/* - * notification that the attributes on an object have changed - */ -int __fscache_attr_changed(struct fscache_cookie *cookie) -{ - struct fscache_operation *op; - struct fscache_object *object; - bool wake_cookie = false; - - _enter("%p", cookie); - - ASSERTCMP(cookie->type, !=, FSCACHE_COOKIE_TYPE_INDEX); - - fscache_stat(&fscache_n_attr_changed); - - op = kzalloc(sizeof(*op), GFP_KERNEL); - if (!op) { - fscache_stat(&fscache_n_attr_changed_nomem); - _leave(" = -ENOMEM"); - return -ENOMEM; - } - - fscache_operation_init(cookie, op, fscache_attr_changed_op, NULL, NULL); - trace_fscache_page_op(cookie, NULL, op, fscache_page_op_attr_changed); - op->flags = FSCACHE_OP_ASYNC | - (1 << FSCACHE_OP_EXCLUSIVE) | - (1 << FSCACHE_OP_UNUSE_COOKIE); - - spin_lock(&cookie->lock); - - if (!fscache_cookie_enabled(cookie) || - hlist_empty(&cookie->backing_objects)) - goto nobufs; - object = hlist_entry(cookie->backing_objects.first, - struct fscache_object, cookie_link); - - __fscache_use_cookie(cookie); - if (fscache_submit_exclusive_op(object, op) < 0) - goto nobufs_dec; - spin_unlock(&cookie->lock); - fscache_stat(&fscache_n_attr_changed_ok); - fscache_put_operation(op); - _leave(" = 0"); - return 0; - -nobufs_dec: - wake_cookie = __fscache_unuse_cookie(cookie); -nobufs: - spin_unlock(&cookie->lock); - fscache_put_operation(op); - if (wake_cookie) - __fscache_wake_unused_cookie(cookie); - fscache_stat(&fscache_n_attr_changed_nobufs); - _leave(" = %d", -ENOBUFS); - return -ENOBUFS; -} -EXPORT_SYMBOL(__fscache_attr_changed); diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index bd9411cd466f..60b2f8288668 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -184,10 +184,6 @@ struct fscache_cache_ops { /* sync a cache */ void (*sync_cache)(struct fscache_cache *cache); - /* notification that the attributes of a non-index object (such as - * i_size) have changed */ - int (*attr_changed)(struct fscache_object *object); - /* reserve space for an object's data and associated metadata */ int (*reserve_space)(struct fscache_object *object, loff_t i_size); }; diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 76cfec6868de..c62b62938c4d 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -140,7 +140,6 @@ extern struct fscache_cookie *__fscache_acquire_cookie( loff_t, bool); extern void __fscache_relinquish_cookie(struct fscache_cookie *, const void *, bool); extern void __fscache_update_cookie(struct fscache_cookie *, const void *); -extern int __fscache_attr_changed(struct fscache_cookie *); extern void __fscache_invalidate(struct fscache_cookie *); extern void __fscache_wait_on_invalidate(struct fscache_cookie *); extern void __fscache_disable_cookie(struct fscache_cookie *, const void *, bool); @@ -337,26 +336,6 @@ void fscache_unpin_cookie(struct fscache_cookie *cookie) { } -/** - * fscache_attr_changed - Notify cache that an object's attributes changed - * @cookie: The cookie representing the cache object - * - * Send a notification to the cache indicating that an object's attributes have - * changed. This includes the data size. These attributes will be obtained - * through the get_attr() cookie definition op. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ -static inline -int fscache_attr_changed(struct fscache_cookie *cookie) -{ - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_attr_changed(cookie); - else - return -ENOBUFS; -} - /** * fscache_invalidate - Notify cache that an object needs invalidation * @cookie: The cookie representing the cache object From patchwork Fri Nov 20 15:05:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329226 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 38F33C63777 for ; Fri, 20 Nov 2020 15:06:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D480022252 for ; Fri, 20 Nov 2020 15:06:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="HDIGe90D" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728654AbgKTPF2 (ORCPT ); Fri, 20 Nov 2020 10:05:28 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:57109 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728643AbgKTPF1 (ORCPT ); Fri, 20 Nov 2020 10:05:27 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884724; 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=r9z/UlaDmok5OSTVt5zLdKIDTwGc8Xw7tD+bT8XCLuE=; b=HDIGe90DIS9c57sKGr8EEMO9rq38OdH1BIQ22/omcL5h4MfDThEqtdoEC2hDMpjKo5mzqM XQoUNLIXgn+XMafPrWfqpi+r/OHYbniZx+5iAlqDePDAq+fsaZXO6mzC6HPLdccMbehH4r mJ/YJyz+yl5jkUtNz/PEdT4tJXYYmgs= 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-367-HmEy75ZZOvaiRh-SmRBf_g-1; Fri, 20 Nov 2020 10:05:20 -0500 X-MC-Unique: HmEy75ZZOvaiRh-SmRBf_g-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 85548AFA81; Fri, 20 Nov 2020 15:05:18 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id C0DFD19C46; Fri, 20 Nov 2020 15:05:12 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 12/76] fscache: Remove old I/O tracepoints From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:05:12 +0000 Message-ID: <160588471199.3465195.6207399512338342767.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Remove now-unused fscache tracepoints that have been obsoleted by the removal of the old I/O code. Signed-off-by: David Howells --- fs/fscache/object.c | 1 include/trace/events/fscache.h | 195 ---------------------------------------- 2 files changed, 196 deletions(-) diff --git a/fs/fscache/object.c b/fs/fscache/object.c index e2e04ac2c0a1..e31164f0446b 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -942,7 +942,6 @@ static const struct fscache_state *_fscache_invalidate_object(struct fscache_obj op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE) | (1 << FSCACHE_OP_UNUSE_COOKIE); - trace_fscache_page_op(cookie, NULL, op, fscache_page_op_invalidate); spin_lock(&cookie->lock); if (fscache_submit_exclusive_op(object, op) < 0) diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h index 953e15fad063..2ebfd688a7c2 100644 --- a/include/trace/events/fscache.h +++ b/include/trace/events/fscache.h @@ -33,24 +33,6 @@ enum fscache_cookie_trace { fscache_cookie_put_parent, }; -enum fscache_page_trace { - fscache_page_cached, - fscache_page_inval, - fscache_page_maybe_release, - fscache_page_radix_clear_store, - fscache_page_radix_delete, - fscache_page_radix_insert, - fscache_page_radix_pend2store, - fscache_page_radix_set_pend, - fscache_page_uncache, - fscache_page_write, - fscache_page_write_end, - fscache_page_write_end_pend, - fscache_page_write_end_noc, - fscache_page_write_wait, - fscache_page_trace__nr -}; - enum fscache_op_trace { fscache_op_cancel, fscache_op_cancel_all, @@ -69,17 +51,6 @@ enum fscache_op_trace { fscache_op_trace__nr }; -enum fscache_page_op_trace { - fscache_page_op_alloc_one, - fscache_page_op_attr_changed, - fscache_page_op_check_consistency, - fscache_page_op_invalidate, - fscache_page_op_retr_multi, - fscache_page_op_retr_one, - fscache_page_op_write_one, - fscache_page_op_trace__nr -}; - #endif /* @@ -98,22 +69,6 @@ enum fscache_page_op_trace { EM(fscache_cookie_put_object, "PUT obj") \ E_(fscache_cookie_put_parent, "PUT prn") -#define fscache_page_traces \ - EM(fscache_page_cached, "Cached ") \ - EM(fscache_page_inval, "InvalPg") \ - EM(fscache_page_maybe_release, "MayRels") \ - EM(fscache_page_uncache, "Uncache") \ - EM(fscache_page_radix_clear_store, "RxCStr ") \ - EM(fscache_page_radix_delete, "RxDel ") \ - EM(fscache_page_radix_insert, "RxIns ") \ - EM(fscache_page_radix_pend2store, "RxP2S ") \ - EM(fscache_page_radix_set_pend, "RxSPend ") \ - EM(fscache_page_write, "WritePg") \ - EM(fscache_page_write_end, "EndPgWr") \ - EM(fscache_page_write_end_pend, "EndPgWP") \ - EM(fscache_page_write_end_noc, "EndPgNC") \ - E_(fscache_page_write_wait, "WtOnWrt") - #define fscache_op_traces \ EM(fscache_op_cancel, "Cancel1") \ EM(fscache_op_cancel_all, "CancelA") \ @@ -130,15 +85,6 @@ enum fscache_page_op_trace { EM(fscache_op_submit_ex, "SubmitX") \ E_(fscache_op_work, "Work ") -#define fscache_page_op_traces \ - EM(fscache_page_op_alloc_one, "Alloc1 ") \ - EM(fscache_page_op_attr_changed, "AttrChg") \ - EM(fscache_page_op_check_consistency, "CheckCn") \ - EM(fscache_page_op_invalidate, "Inval ") \ - EM(fscache_page_op_retr_multi, "RetrMul") \ - EM(fscache_page_op_retr_one, "Retr1 ") \ - E_(fscache_page_op_write_one, "Write1 ") - /* * Export enum symbols via userspace. */ @@ -363,70 +309,6 @@ TRACE_EVENT(fscache_osm, __entry->event_num) ); -TRACE_EVENT(fscache_page, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - enum fscache_page_trace why), - - TP_ARGS(cookie, page, why), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(pgoff_t, page ) - __field(enum fscache_page_trace, why ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page->index; - __entry->why = why; - ), - - TP_printk("c=%08x %s pg=%lx", - __entry->cookie, - __print_symbolic(__entry->why, fscache_page_traces), - __entry->page) - ); - -TRACE_EVENT(fscache_check_page, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - void *val, int n), - - TP_ARGS(cookie, page, val, n), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(void *, page ) - __field(void *, val ) - __field(int, n ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page; - __entry->val = val; - __entry->n = n; - ), - - TP_printk("c=%08x pg=%p val=%p n=%d", - __entry->cookie, __entry->page, __entry->val, __entry->n) - ); - -TRACE_EVENT(fscache_wake_cookie, - TP_PROTO(struct fscache_cookie *cookie), - - TP_ARGS(cookie), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - ), - - TP_printk("c=%08x", __entry->cookie) - ); - TRACE_EVENT(fscache_op, TP_PROTO(struct fscache_cookie *cookie, struct fscache_operation *op, enum fscache_op_trace why), @@ -450,83 +332,6 @@ TRACE_EVENT(fscache_op, __print_symbolic(__entry->why, fscache_op_traces)) ); -TRACE_EVENT(fscache_page_op, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - struct fscache_operation *op, enum fscache_page_op_trace what), - - TP_ARGS(cookie, page, op, what), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(pgoff_t, page ) - __field(enum fscache_page_op_trace, what ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page ? page->index : 0; - __entry->op = op->debug_id; - __entry->what = what; - ), - - TP_printk("c=%08x %s pg=%lx op=%08x", - __entry->cookie, - __print_symbolic(__entry->what, fscache_page_op_traces), - __entry->page, __entry->op) - ); - -TRACE_EVENT(fscache_wrote_page, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - struct fscache_operation *op, int ret), - - TP_ARGS(cookie, page, op, ret), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(pgoff_t, page ) - __field(int, ret ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page->index; - __entry->op = op->debug_id; - __entry->ret = ret; - ), - - TP_printk("c=%08x pg=%lx op=%08x ret=%d", - __entry->cookie, __entry->page, __entry->op, __entry->ret) - ); - -TRACE_EVENT(fscache_gang_lookup, - TP_PROTO(struct fscache_cookie *cookie, struct fscache_operation *op, - void **results, int n, pgoff_t store_limit), - - TP_ARGS(cookie, op, results, n, store_limit), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(pgoff_t, results0 ) - __field(int, n ) - __field(pgoff_t, store_limit ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->op = op->debug_id; - __entry->results0 = results[0] ? ((struct page *)results[0])->index : (pgoff_t)-1; - __entry->n = n; - __entry->store_limit = store_limit; - ), - - TP_printk("c=%08x op=%08x r0=%lx n=%d sl=%lx", - __entry->cookie, __entry->op, __entry->results0, __entry->n, - __entry->store_limit) - ); - #endif /* _TRACE_FSCACHE_H */ /* This part must be outside protection */ From patchwork Fri Nov 20 15:05:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329225 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 31EC1C71155 for ; Fri, 20 Nov 2020 15:06:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D965822252 for ; Fri, 20 Nov 2020 15:06:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="hU8zzJUK" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728686AbgKTPF7 (ORCPT ); Fri, 20 Nov 2020 10:05:59 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:25349 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728655AbgKTPFy (ORCPT ); Fri, 20 Nov 2020 10:05:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884749; 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=PSqGS9xhcW+E7O3WOq0ZK8FQsEYjiToVBe6ISKKIqAE=; b=hU8zzJUKj5PzjYjkx7wDAQc0U72a0P1UQfoqRlOpADbRxTjWc78Kv5AxYhQHnZdVWeST7t VDw2sBVmhk541v7dpZBc7EpIh/vH0cd/d6V7bQKNngJ7v6WMMNF7JOQfSD+04D+PStRjfg z/WIem1p6SLDb+OLQeJ3wmauYDUIZFc= 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-512-Z2hLWExoODa-lra_Y94oCQ-1; Fri, 20 Nov 2020 10:05:45 -0500 X-MC-Unique: Z2hLWExoODa-lra_Y94oCQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 33C50100C604; Fri, 20 Nov 2020 15:05:43 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id B9CAD60853; Fri, 20 Nov 2020 15:05:36 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 14/76] fscache: Remove the I/O operation manager From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:05:35 +0000 Message-ID: <160588473592.3465195.5326340714524270403.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Remove the fscache I/O operation manager. Getting operation-operation interactions and object-operation interactions correct has proven really difficult; furthermore, the operations are being replaced with kiocb-driven stuff on the cache front. Signed-off-by: David Howells --- fs/cachefiles/namei.c | 5 fs/fscache/Makefile | 3 fs/fscache/cache.c | 3 fs/fscache/cookie.c | 1 fs/fscache/internal.h | 13 - fs/fscache/object-list.c | 25 -- fs/fscache/object.c | 24 -- fs/fscache/operation.c | 633 ---------------------------------------- include/linux/fscache-cache.h | 71 ---- include/trace/events/fscache.h | 57 ---- 10 files changed, 7 insertions(+), 828 deletions(-) delete mode 100644 fs/fscache/operation.c diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 432002080b83..924042e8cced 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -36,9 +36,8 @@ void __cachefiles_printk_object(struct cachefiles_object *object, prefix, object->fscache.state->name, object->fscache.flags, work_busy(&object->fscache.work), object->fscache.events, object->fscache.event_mask); - pr_err("%sops=%u inp=%u exc=%u\n", - prefix, object->fscache.n_ops, object->fscache.n_in_progress, - object->fscache.n_exclusive); + pr_err("%sops=%u\n", + prefix, object->fscache.n_ops); pr_err("%sparent=%p\n", prefix, object->fscache.parent); diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile index 565a3441d31d..ac3fcd909fff 100644 --- a/fs/fscache/Makefile +++ b/fs/fscache/Makefile @@ -9,8 +9,7 @@ fscache-y := \ fsdef.o \ main.o \ netfs.o \ - object.o \ - operation.o + object.o fscache-$(CONFIG_PROC_FS) += proc.o fscache-$(CONFIG_FSCACHE_STATS) += stats.o diff --git a/fs/fscache/cache.c b/fs/fscache/cache.c index 2231691845b8..92f747b72ec3 100644 --- a/fs/fscache/cache.c +++ b/fs/fscache/cache.c @@ -182,12 +182,9 @@ void fscache_init_cache(struct fscache_cache *cache, vsnprintf(cache->identifier, sizeof(cache->identifier), idfmt, va); va_end(va); - INIT_WORK(&cache->op_gc, fscache_operation_gc); INIT_LIST_HEAD(&cache->link); INIT_LIST_HEAD(&cache->object_list); - INIT_LIST_HEAD(&cache->op_gc_list); spin_lock_init(&cache->object_list_lock); - spin_lock_init(&cache->op_gc_list_lock); } EXPORT_SYMBOL(fscache_init_cache); diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 30394b32a91c..aa33d16711e1 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -756,7 +756,6 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) { if (invalidate) set_bit(FSCACHE_OBJECT_RETIRED, &object->flags); - clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL); } } else { diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 360137fd19a7..bc5539d2157b 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -138,19 +138,6 @@ extern void fscache_objlist_remove(struct fscache_object *); #define fscache_objlist_remove(object) do {} while(0) #endif -/* - * operation.c - */ -extern int fscache_submit_exclusive_op(struct fscache_object *, - struct fscache_operation *); -extern int fscache_submit_op(struct fscache_object *, - struct fscache_operation *); -extern int fscache_cancel_op(struct fscache_operation *, bool); -extern void fscache_cancel_all_ops(struct fscache_object *); -extern void fscache_abort_object(struct fscache_object *); -extern void fscache_start_operations(struct fscache_object *); -extern void fscache_operation_gc(struct work_struct *); - /* * proc.c */ diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index fc28de4738ec..147c556ee01b 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c @@ -23,10 +23,6 @@ struct fscache_objlist_data { #define FSCACHE_OBJLIST_CONFIG_AUX 0x00000002 /* show object auxdata */ #define FSCACHE_OBJLIST_CONFIG_BUSY 0x00000010 /* show busy objects */ #define FSCACHE_OBJLIST_CONFIG_IDLE 0x00000020 /* show idle objects */ -#define FSCACHE_OBJLIST_CONFIG_PENDWR 0x00000040 /* show objects with pending writes */ -#define FSCACHE_OBJLIST_CONFIG_NOPENDWR 0x00000080 /* show objects without pending writes */ -#define FSCACHE_OBJLIST_CONFIG_READS 0x00000100 /* show objects with active reads */ -#define FSCACHE_OBJLIST_CONFIG_NOREADS 0x00000200 /* show objects without active reads */ #define FSCACHE_OBJLIST_CONFIG_EVENTS 0x00000400 /* show objects with events */ #define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */ #define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */ @@ -166,7 +162,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v) u8 *p; if ((unsigned long) v == 1) { - seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS" + seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP" " EM EV FL S" " | COOKIE TYPE TY FL"); if (config & (FSCACHE_OBJLIST_CONFIG_KEY | @@ -185,7 +181,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v) } if ((unsigned long) v == 2) { - seq_puts(m, "======== ======== ==== ===== === === === == =====" + seq_puts(m, "======== ======== ==== ===== === ===" " == == == =" " | ======== ======= == ==="); if (config & (FSCACHE_OBJLIST_CONFIG_KEY | @@ -217,26 +213,19 @@ static int fscache_objlist_show(struct seq_file *m, void *v) obj->flags || !list_empty(&obj->dependents), BUSY, IDLE); - FILTER(test_bit(FSCACHE_OBJECT_PENDING_WRITE, &obj->flags), - PENDWR, NOPENDWR); - FILTER(atomic_read(&obj->n_reads), - READS, NOREADS); FILTER(obj->events & obj->event_mask, EVENTS, NOEVENTS); FILTER(work_busy(&obj->work), WORK, NOWORK); } seq_printf(m, - "%08x %08x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %2lx %1x | ", + "%08x %08x %s %5u %3u %3u %2lx %2lx %2lx %1x | ", obj->debug_id, obj->parent ? obj->parent->debug_id : UINT_MAX, obj->state->short_name, obj->n_children, obj->n_ops, obj->n_obj_ops, - obj->n_in_progress, - obj->n_exclusive, - atomic_read(&obj->n_reads), obj->event_mask, obj->events, obj->flags, @@ -336,10 +325,6 @@ static void fscache_objlist_config(struct fscache_objlist_data *data) case 'A': config |= FSCACHE_OBJLIST_CONFIG_AUX; break; case 'B': config |= FSCACHE_OBJLIST_CONFIG_BUSY; break; case 'b': config |= FSCACHE_OBJLIST_CONFIG_IDLE; break; - case 'W': config |= FSCACHE_OBJLIST_CONFIG_PENDWR; break; - case 'w': config |= FSCACHE_OBJLIST_CONFIG_NOPENDWR; break; - case 'R': config |= FSCACHE_OBJLIST_CONFIG_READS; break; - case 'r': config |= FSCACHE_OBJLIST_CONFIG_NOREADS; break; case 'S': config |= FSCACHE_OBJLIST_CONFIG_WORK; break; case 's': config |= FSCACHE_OBJLIST_CONFIG_NOWORK; break; } @@ -350,10 +335,6 @@ static void fscache_objlist_config(struct fscache_objlist_data *data) if (!(config & (FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE))) config |= FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE; - if (!(config & (FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR))) - config |= FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR; - if (!(config & (FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS))) - config |= FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS; if (!(config & (FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS))) config |= FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS; if (!(config & (FSCACHE_OBJLIST_CONFIG_WORK | FSCACHE_OBJLIST_CONFIG_NOWORK))) diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 5eda1cd265ef..5d50976bf379 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -315,9 +315,8 @@ void fscache_object_init(struct fscache_object *object, INIT_WORK(&object->work, fscache_object_work_func); INIT_LIST_HEAD(&object->dependents); INIT_LIST_HEAD(&object->dep_link); - INIT_LIST_HEAD(&object->pending_ops); object->n_children = 0; - object->n_ops = object->n_in_progress = object->n_exclusive = 0; + object->n_ops = 0; object->events = 0; object->cache = cache; object->cookie = cookie; @@ -580,14 +579,6 @@ static const struct fscache_state *fscache_object_available(struct fscache_objec spin_lock(&object->lock); fscache_done_parent_op(object); - if (object->n_in_progress == 0) { - if (object->n_ops > 0) { - ASSERTCMP(object->n_ops, >=, object->n_obj_ops); - fscache_start_operations(object); - } else { - ASSERT(list_empty(&object->pending_ops)); - } - } spin_unlock(&object->lock); fscache_stat(&fscache_n_cop_lookup_complete); @@ -654,24 +645,11 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob fscache_mark_object_dead(object); object->oob_event_mask = 0; - if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) { - /* Reject any new read/write ops and abort any that are pending. */ - clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); - fscache_cancel_all_ops(object); - } - if (list_empty(&object->dependents) && object->n_ops == 0 && object->n_children == 0) return transit_to(DROP_OBJECT); - if (object->n_in_progress == 0) { - spin_lock(&object->lock); - if (object->n_ops > 0 && object->n_in_progress == 0) - fscache_start_operations(object); - spin_unlock(&object->lock); - } - if (!list_empty(&object->dependents)) return transit_to(KILL_DEPENDENTS); diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c deleted file mode 100644 index 4a5651d4904e..000000000000 --- a/fs/fscache/operation.c +++ /dev/null @@ -1,633 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* FS-Cache worker operation management routines - * - * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * See Documentation/filesystems/caching/operations.rst - */ - -#define FSCACHE_DEBUG_LEVEL OPERATION -#include -#include -#include -#include "internal.h" - -atomic_t fscache_op_debug_id; -EXPORT_SYMBOL(fscache_op_debug_id); - -static void fscache_operation_dummy_cancel(struct fscache_operation *op) -{ -} - -/** - * fscache_operation_init - Do basic initialisation of an operation - * @op: The operation to initialise - * @release: The release function to assign - * - * Do basic initialisation of an operation. The caller must still set flags, - * object and processor if needed. - */ -void fscache_operation_init(struct fscache_cookie *cookie, - struct fscache_operation *op, - fscache_operation_processor_t processor, - fscache_operation_cancel_t cancel, - fscache_operation_release_t release) -{ - INIT_WORK(&op->work, fscache_op_work_func); - atomic_set(&op->usage, 1); - op->state = FSCACHE_OP_ST_INITIALISED; - op->debug_id = atomic_inc_return(&fscache_op_debug_id); - op->processor = processor; - op->cancel = cancel ?: fscache_operation_dummy_cancel; - op->release = release; - INIT_LIST_HEAD(&op->pend_link); - fscache_stat(&fscache_n_op_initialised); - trace_fscache_op(cookie, op, fscache_op_init); -} -EXPORT_SYMBOL(fscache_operation_init); - -/** - * fscache_enqueue_operation - Enqueue an operation for processing - * @op: The operation to enqueue - * - * Enqueue an operation for processing by the FS-Cache thread pool. - * - * This will get its own ref on the object. - */ -void fscache_enqueue_operation(struct fscache_operation *op) -{ - struct fscache_cookie *cookie = op->object->cookie; - - _enter("{OBJ%x OP%x,%u}", - op->object->debug_id, op->debug_id, atomic_read(&op->usage)); - - ASSERT(list_empty(&op->pend_link)); - ASSERT(op->processor != NULL); - ASSERT(fscache_object_is_available(op->object)); - ASSERTCMP(atomic_read(&op->usage), >, 0); - ASSERTIFCMP(op->state != FSCACHE_OP_ST_IN_PROGRESS, - op->state, ==, FSCACHE_OP_ST_CANCELLED); - - fscache_stat(&fscache_n_op_enqueue); - switch (op->flags & FSCACHE_OP_TYPE) { - case FSCACHE_OP_ASYNC: - trace_fscache_op(cookie, op, fscache_op_enqueue_async); - _debug("queue async"); - atomic_inc(&op->usage); - if (!queue_work(fscache_op_wq, &op->work)) - fscache_put_operation(op); - break; - case FSCACHE_OP_MYTHREAD: - trace_fscache_op(cookie, op, fscache_op_enqueue_mythread); - _debug("queue for caller's attention"); - break; - default: - pr_err("Unexpected op type %lx", op->flags); - BUG(); - break; - } -} -EXPORT_SYMBOL(fscache_enqueue_operation); - -/* - * start an op running - */ -static void fscache_run_op(struct fscache_object *object, - struct fscache_operation *op) -{ - ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING); - - op->state = FSCACHE_OP_ST_IN_PROGRESS; - object->n_in_progress++; - if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) - wake_up_bit(&op->flags, FSCACHE_OP_WAITING); - if (op->processor) - fscache_enqueue_operation(op); - else - trace_fscache_op(object->cookie, op, fscache_op_run); - fscache_stat(&fscache_n_op_run); -} - -/* - * report an unexpected submission - */ -static void fscache_report_unexpected_submission(struct fscache_object *object, - struct fscache_operation *op, - const struct fscache_state *ostate) -{ - static bool once_only; - struct fscache_operation *p; - unsigned n; - - if (once_only) - return; - once_only = true; - - kdebug("unexpected submission OP%x [OBJ%x %s]", - op->debug_id, object->debug_id, object->state->name); - kdebug("objstate=%s [%s]", object->state->name, ostate->name); - kdebug("objflags=%lx", object->flags); - kdebug("objevent=%lx [%lx]", object->events, object->event_mask); - kdebug("ops=%u inp=%u exc=%u", - object->n_ops, object->n_in_progress, object->n_exclusive); - - if (!list_empty(&object->pending_ops)) { - n = 0; - list_for_each_entry(p, &object->pending_ops, pend_link) { - ASSERTCMP(p->object, ==, object); - kdebug("%p %p", op->processor, op->release); - n++; - } - - kdebug("n=%u", n); - } - - dump_stack(); -} - -/* - * submit an exclusive operation for an object - * - other ops are excluded from running simultaneously with this one - * - this gets any extra refs it needs on an op - */ -int fscache_submit_exclusive_op(struct fscache_object *object, - struct fscache_operation *op) -{ - const struct fscache_state *ostate; - unsigned long flags; - int ret; - - _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id); - - trace_fscache_op(object->cookie, op, fscache_op_submit_ex); - - ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED); - ASSERTCMP(atomic_read(&op->usage), >, 0); - - spin_lock(&object->lock); - ASSERTCMP(object->n_ops, >=, object->n_in_progress); - ASSERTCMP(object->n_ops, >=, object->n_exclusive); - ASSERT(list_empty(&op->pend_link)); - - ostate = object->state; - smp_rmb(); - - op->state = FSCACHE_OP_ST_PENDING; - flags = READ_ONCE(object->flags); - if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) { - fscache_stat(&fscache_n_op_rejected); - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -ENOBUFS; - } else if (unlikely(fscache_cache_is_broken(object))) { - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -EIO; - } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) { - op->object = object; - object->n_ops++; - object->n_exclusive++; /* reads and writes must wait */ - - if (object->n_in_progress > 0) { - atomic_inc(&op->usage); - list_add_tail(&op->pend_link, &object->pending_ops); - fscache_stat(&fscache_n_op_pend); - } else if (!list_empty(&object->pending_ops)) { - atomic_inc(&op->usage); - list_add_tail(&op->pend_link, &object->pending_ops); - fscache_stat(&fscache_n_op_pend); - fscache_start_operations(object); - } else { - ASSERTCMP(object->n_in_progress, ==, 0); - fscache_run_op(object, op); - } - - /* need to issue a new write op after this */ - clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); - ret = 0; - } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) { - op->object = object; - object->n_ops++; - object->n_exclusive++; /* reads and writes must wait */ - atomic_inc(&op->usage); - list_add_tail(&op->pend_link, &object->pending_ops); - fscache_stat(&fscache_n_op_pend); - ret = 0; - } else if (flags & BIT(FSCACHE_OBJECT_KILLED_BY_CACHE)) { - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -ENOBUFS; - } else { - fscache_report_unexpected_submission(object, op, ostate); - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -ENOBUFS; - } - - spin_unlock(&object->lock); - return ret; -} - -/* - * submit an operation for an object - * - objects may be submitted only in the following states: - * - during object creation (write ops may be submitted) - * - whilst the object is active - * - after an I/O error incurred in one of the two above states (op rejected) - * - this gets any extra refs it needs on an op - */ -int fscache_submit_op(struct fscache_object *object, - struct fscache_operation *op) -{ - const struct fscache_state *ostate; - unsigned long flags; - int ret; - - _enter("{OBJ%x OP%x},{%u}", - object->debug_id, op->debug_id, atomic_read(&op->usage)); - - trace_fscache_op(object->cookie, op, fscache_op_submit); - - ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED); - ASSERTCMP(atomic_read(&op->usage), >, 0); - - spin_lock(&object->lock); - ASSERTCMP(object->n_ops, >=, object->n_in_progress); - ASSERTCMP(object->n_ops, >=, object->n_exclusive); - ASSERT(list_empty(&op->pend_link)); - - ostate = object->state; - smp_rmb(); - - op->state = FSCACHE_OP_ST_PENDING; - flags = READ_ONCE(object->flags); - if (unlikely(!(flags & BIT(FSCACHE_OBJECT_IS_LIVE)))) { - fscache_stat(&fscache_n_op_rejected); - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -ENOBUFS; - } else if (unlikely(fscache_cache_is_broken(object))) { - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -EIO; - } else if (flags & BIT(FSCACHE_OBJECT_IS_AVAILABLE)) { - op->object = object; - object->n_ops++; - - if (object->n_exclusive > 0) { - atomic_inc(&op->usage); - list_add_tail(&op->pend_link, &object->pending_ops); - fscache_stat(&fscache_n_op_pend); - } else if (!list_empty(&object->pending_ops)) { - atomic_inc(&op->usage); - list_add_tail(&op->pend_link, &object->pending_ops); - fscache_stat(&fscache_n_op_pend); - fscache_start_operations(object); - } else { - ASSERTCMP(object->n_exclusive, ==, 0); - fscache_run_op(object, op); - } - ret = 0; - } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) { - op->object = object; - object->n_ops++; - atomic_inc(&op->usage); - list_add_tail(&op->pend_link, &object->pending_ops); - fscache_stat(&fscache_n_op_pend); - ret = 0; - } else if (flags & BIT(FSCACHE_OBJECT_KILLED_BY_CACHE)) { - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -ENOBUFS; - } else { - fscache_report_unexpected_submission(object, op, ostate); - ASSERT(!fscache_object_is_active(object)); - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - ret = -ENOBUFS; - } - - spin_unlock(&object->lock); - return ret; -} - -/* - * queue an object for withdrawal on error, aborting all following asynchronous - * operations - */ -void fscache_abort_object(struct fscache_object *object) -{ - _enter("{OBJ%x}", object->debug_id); - - fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR); -} - -/* - * Jump start the operation processing on an object. The caller must hold - * object->lock. - */ -void fscache_start_operations(struct fscache_object *object) -{ - struct fscache_operation *op; - bool stop = false; - - while (!list_empty(&object->pending_ops) && !stop) { - op = list_entry(object->pending_ops.next, - struct fscache_operation, pend_link); - - if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) { - if (object->n_in_progress > 0) - break; - stop = true; - } - list_del_init(&op->pend_link); - fscache_run_op(object, op); - - /* the pending queue was holding a ref on the object */ - fscache_put_operation(op); - } - - ASSERTCMP(object->n_in_progress, <=, object->n_ops); - - _debug("woke %d ops on OBJ%x", - object->n_in_progress, object->debug_id); -} - -/* - * cancel an operation that's pending on an object - */ -int fscache_cancel_op(struct fscache_operation *op, - bool cancel_in_progress_op) -{ - struct fscache_object *object = op->object; - bool put = false; - int ret; - - _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id); - - trace_fscache_op(object->cookie, op, fscache_op_cancel); - - ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING); - ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED); - ASSERTCMP(atomic_read(&op->usage), >, 0); - - spin_lock(&object->lock); - - ret = -EBUSY; - if (op->state == FSCACHE_OP_ST_PENDING) { - ASSERT(!list_empty(&op->pend_link)); - list_del_init(&op->pend_link); - put = true; - - fscache_stat(&fscache_n_op_cancelled); - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) - object->n_exclusive--; - if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) - wake_up_bit(&op->flags, FSCACHE_OP_WAITING); - ret = 0; - } else if (op->state == FSCACHE_OP_ST_IN_PROGRESS && cancel_in_progress_op) { - ASSERTCMP(object->n_in_progress, >, 0); - if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) - object->n_exclusive--; - object->n_in_progress--; - if (object->n_in_progress == 0) - fscache_start_operations(object); - - fscache_stat(&fscache_n_op_cancelled); - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) - object->n_exclusive--; - if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) - wake_up_bit(&op->flags, FSCACHE_OP_WAITING); - ret = 0; - } - - if (put) - fscache_put_operation(op); - spin_unlock(&object->lock); - _leave(" = %d", ret); - return ret; -} - -/* - * Cancel all pending operations on an object - */ -void fscache_cancel_all_ops(struct fscache_object *object) -{ - struct fscache_operation *op; - - _enter("OBJ%x", object->debug_id); - - spin_lock(&object->lock); - - while (!list_empty(&object->pending_ops)) { - op = list_entry(object->pending_ops.next, - struct fscache_operation, pend_link); - fscache_stat(&fscache_n_op_cancelled); - list_del_init(&op->pend_link); - - trace_fscache_op(object->cookie, op, fscache_op_cancel_all); - - ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING); - op->cancel(op); - op->state = FSCACHE_OP_ST_CANCELLED; - - if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) - object->n_exclusive--; - if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) - wake_up_bit(&op->flags, FSCACHE_OP_WAITING); - fscache_put_operation(op); - cond_resched_lock(&object->lock); - } - - spin_unlock(&object->lock); - _leave(""); -} - -/* - * Record the completion or cancellation of an in-progress operation. - */ -void fscache_op_complete(struct fscache_operation *op, bool cancelled) -{ - struct fscache_object *object = op->object; - - _enter("OBJ%x", object->debug_id); - - ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS); - ASSERTCMP(object->n_in_progress, >, 0); - ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags), - object->n_exclusive, >, 0); - ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags), - object->n_in_progress, ==, 1); - - spin_lock(&object->lock); - - if (!cancelled) { - trace_fscache_op(object->cookie, op, fscache_op_completed); - op->state = FSCACHE_OP_ST_COMPLETE; - } else { - op->cancel(op); - trace_fscache_op(object->cookie, op, fscache_op_cancelled); - op->state = FSCACHE_OP_ST_CANCELLED; - } - - if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) - object->n_exclusive--; - object->n_in_progress--; - if (object->n_in_progress == 0) - fscache_start_operations(object); - - spin_unlock(&object->lock); - _leave(""); -} -EXPORT_SYMBOL(fscache_op_complete); - -/* - * release an operation - * - queues pending ops if this is the last in-progress op - */ -void fscache_put_operation(struct fscache_operation *op) -{ - struct fscache_object *object; - struct fscache_cache *cache; - - _enter("{OBJ%x OP%x,%d}", - op->object ? op->object->debug_id : 0, - op->debug_id, atomic_read(&op->usage)); - - ASSERTCMP(atomic_read(&op->usage), >, 0); - - if (!atomic_dec_and_test(&op->usage)) - return; - - trace_fscache_op(op->object ? op->object->cookie : NULL, op, fscache_op_put); - - _debug("PUT OP"); - ASSERTIFCMP(op->state != FSCACHE_OP_ST_INITIALISED && - op->state != FSCACHE_OP_ST_COMPLETE, - op->state, ==, FSCACHE_OP_ST_CANCELLED); - - fscache_stat(&fscache_n_op_release); - - if (op->release) { - op->release(op); - op->release = NULL; - } - op->state = FSCACHE_OP_ST_DEAD; - - object = op->object; - if (likely(object)) { - if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) - atomic_dec(&object->n_reads); - if (test_bit(FSCACHE_OP_UNUSE_COOKIE, &op->flags)) - fscache_unuse_cookie(object); - - /* now... we may get called with the object spinlock held, so we - * complete the cleanup here only if we can immediately acquire the - * lock, and defer it otherwise */ - if (!spin_trylock(&object->lock)) { - _debug("defer put"); - fscache_stat(&fscache_n_op_deferred_release); - - cache = object->cache; - spin_lock(&cache->op_gc_list_lock); - list_add_tail(&op->pend_link, &cache->op_gc_list); - spin_unlock(&cache->op_gc_list_lock); - schedule_work(&cache->op_gc); - _leave(" [defer]"); - return; - } - - ASSERTCMP(object->n_ops, >, 0); - object->n_ops--; - if (object->n_ops == 0) - fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED); - - spin_unlock(&object->lock); - } - - kfree(op); - _leave(" [done]"); -} -EXPORT_SYMBOL(fscache_put_operation); - -/* - * garbage collect operations that have had their release deferred - */ -void fscache_operation_gc(struct work_struct *work) -{ - struct fscache_operation *op; - struct fscache_object *object; - struct fscache_cache *cache = - container_of(work, struct fscache_cache, op_gc); - int count = 0; - - _enter(""); - - do { - spin_lock(&cache->op_gc_list_lock); - if (list_empty(&cache->op_gc_list)) { - spin_unlock(&cache->op_gc_list_lock); - break; - } - - op = list_entry(cache->op_gc_list.next, - struct fscache_operation, pend_link); - list_del(&op->pend_link); - spin_unlock(&cache->op_gc_list_lock); - - object = op->object; - trace_fscache_op(object->cookie, op, fscache_op_gc); - - spin_lock(&object->lock); - - _debug("GC DEFERRED REL OBJ%x OP%x", - object->debug_id, op->debug_id); - fscache_stat(&fscache_n_op_gc); - - ASSERTCMP(atomic_read(&op->usage), ==, 0); - ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD); - - ASSERTCMP(object->n_ops, >, 0); - object->n_ops--; - if (object->n_ops == 0) - fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED); - - spin_unlock(&object->lock); - kfree(op); - - } while (count++ < 20); - - if (!list_empty(&cache->op_gc_list)) - schedule_work(&cache->op_gc); - - _leave(""); -} - -/* - * execute an operation using fs_op_wq to provide processing context - - * the caller holds a ref to this object, so we don't need to hold one - */ -void fscache_op_work_func(struct work_struct *work) -{ - struct fscache_operation *op = - container_of(work, struct fscache_operation, work); - unsigned long start; - - _enter("{OBJ%x OP%x,%d}", - op->object->debug_id, op->debug_id, atomic_read(&op->usage)); - - trace_fscache_op(op->object->cookie, op, fscache_op_work); - - ASSERT(op->processor != NULL); - start = jiffies; - op->processor(op); - fscache_hist(fscache_ops_histogram, start); - fscache_put_operation(op); - - _leave(""); -} diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 0fbe25b1271b..8b6aa11dee54 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -23,7 +23,6 @@ struct fscache_cache; struct fscache_cache_ops; struct fscache_object; -struct fscache_operation; enum fscache_obj_ref_trace { fscache_obj_get_add_to_deps, @@ -62,11 +61,8 @@ struct fscache_cache { char identifier[36]; /* cache label */ /* node management */ - struct work_struct op_gc; /* operation garbage collector */ struct list_head object_list; /* list of data/index objects */ - struct list_head op_gc_list; /* list of ops to be deleted */ spinlock_t object_list_lock; - spinlock_t op_gc_list_lock; atomic_t object_count; /* no. of live objects in this cache */ struct fscache_object *fsdef; /* object for the fsdef index */ unsigned long flags; @@ -76,68 +72,6 @@ struct fscache_cache { extern wait_queue_head_t fscache_cache_cleared_wq; -/* - * operation to be applied to a cache object - * - retrieval initiation operations are done in the context of the process - * that issued them, and not in an async thread pool - */ -typedef void (*fscache_operation_release_t)(struct fscache_operation *op); -typedef void (*fscache_operation_processor_t)(struct fscache_operation *op); -typedef void (*fscache_operation_cancel_t)(struct fscache_operation *op); - -enum fscache_operation_state { - FSCACHE_OP_ST_BLANK, /* Op is not yet submitted */ - FSCACHE_OP_ST_INITIALISED, /* Op is initialised */ - FSCACHE_OP_ST_PENDING, /* Op is blocked from running */ - FSCACHE_OP_ST_IN_PROGRESS, /* Op is in progress */ - FSCACHE_OP_ST_COMPLETE, /* Op is complete */ - FSCACHE_OP_ST_CANCELLED, /* Op has been cancelled */ - FSCACHE_OP_ST_DEAD /* Op is now dead */ -}; - -struct fscache_operation { - struct work_struct work; /* record for async ops */ - struct list_head pend_link; /* link in object->pending_ops */ - struct fscache_object *object; /* object to be operated upon */ - - unsigned long flags; -#define FSCACHE_OP_TYPE 0x000f /* operation type */ -#define FSCACHE_OP_ASYNC 0x0001 /* - async op, processor may sleep for disk */ -#define FSCACHE_OP_MYTHREAD 0x0002 /* - processing is done be issuing thread, not pool */ -#define FSCACHE_OP_WAITING 4 /* cleared when op is woken */ -#define FSCACHE_OP_EXCLUSIVE 5 /* exclusive op, other ops must wait */ -#define FSCACHE_OP_DEC_READ_CNT 6 /* decrement object->n_reads on destruction */ -#define FSCACHE_OP_UNUSE_COOKIE 7 /* call fscache_unuse_cookie() on completion */ -#define FSCACHE_OP_KEEP_FLAGS 0x00f0 /* flags to keep when repurposing an op */ - - enum fscache_operation_state state; - atomic_t usage; - unsigned debug_id; /* debugging ID */ - - /* operation processor callback - * - can be NULL if FSCACHE_OP_WAITING is going to be used to perform - * the op in a non-pool thread */ - fscache_operation_processor_t processor; - - /* Operation cancellation cleanup (optional) */ - fscache_operation_cancel_t cancel; - - /* operation releaser */ - fscache_operation_release_t release; -}; - -extern atomic_t fscache_op_debug_id; -extern void fscache_op_work_func(struct work_struct *work); - -extern void fscache_enqueue_operation(struct fscache_operation *); -extern void fscache_op_complete(struct fscache_operation *, bool); -extern void fscache_put_operation(struct fscache_operation *); -extern void fscache_operation_init(struct fscache_cookie *, - struct fscache_operation *, - fscache_operation_processor_t, - fscache_operation_cancel_t, - fscache_operation_release_t); - /* * cache operations */ @@ -232,9 +166,6 @@ struct fscache_object { int n_children; /* number of child objects */ int n_ops; /* number of extant ops on object */ int n_obj_ops; /* number of object ops outstanding on object */ - int n_in_progress; /* number of ops in progress */ - int n_exclusive; /* number of exclusive ops queued or in progress */ - atomic_t n_reads; /* number of read ops in progress */ spinlock_t lock; /* state and operations lock */ unsigned long lookup_jif; /* time at which lookup started */ @@ -245,7 +176,6 @@ struct fscache_object { unsigned long flags; #define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */ -#define FSCACHE_OBJECT_PENDING_WRITE 1 /* T if object has pending write */ #define FSCACHE_OBJECT_WAITING 2 /* T if object is waiting on its parent */ #define FSCACHE_OBJECT_IS_LIVE 3 /* T if object is not withdrawn or relinquished */ #define FSCACHE_OBJECT_IS_LOOKED_UP 4 /* T if object has been looked up */ @@ -262,7 +192,6 @@ struct fscache_object { struct work_struct work; /* attention scheduling record */ struct list_head dependents; /* FIFO of dependent objects */ struct list_head dep_link; /* link in parent's dependents list */ - struct list_head pending_ops; /* unstarted operations on this object */ #ifdef CONFIG_FSCACHE_OBJECT_LIST struct rb_node objlist_link; /* link in global object list */ #endif diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h index 2ebfd688a7c2..08d7de72409d 100644 --- a/include/trace/events/fscache.h +++ b/include/trace/events/fscache.h @@ -33,24 +33,6 @@ enum fscache_cookie_trace { fscache_cookie_put_parent, }; -enum fscache_op_trace { - fscache_op_cancel, - fscache_op_cancel_all, - fscache_op_cancelled, - fscache_op_completed, - fscache_op_enqueue_async, - fscache_op_enqueue_mythread, - fscache_op_gc, - fscache_op_init, - fscache_op_put, - fscache_op_run, - fscache_op_signal, - fscache_op_submit, - fscache_op_submit_ex, - fscache_op_work, - fscache_op_trace__nr -}; - #endif /* @@ -69,22 +51,6 @@ enum fscache_op_trace { EM(fscache_cookie_put_object, "PUT obj") \ E_(fscache_cookie_put_parent, "PUT prn") -#define fscache_op_traces \ - EM(fscache_op_cancel, "Cancel1") \ - EM(fscache_op_cancel_all, "CancelA") \ - EM(fscache_op_cancelled, "Canclld") \ - EM(fscache_op_completed, "Complet") \ - EM(fscache_op_enqueue_async, "EnqAsyn") \ - EM(fscache_op_enqueue_mythread, "EnqMyTh") \ - EM(fscache_op_gc, "GC ") \ - EM(fscache_op_init, "Init ") \ - EM(fscache_op_put, "Put ") \ - EM(fscache_op_run, "Run ") \ - EM(fscache_op_signal, "Signal ") \ - EM(fscache_op_submit, "Submit ") \ - EM(fscache_op_submit_ex, "SubmitX") \ - E_(fscache_op_work, "Work ") - /* * Export enum symbols via userspace. */ @@ -309,29 +275,6 @@ TRACE_EVENT(fscache_osm, __entry->event_num) ); -TRACE_EVENT(fscache_op, - TP_PROTO(struct fscache_cookie *cookie, struct fscache_operation *op, - enum fscache_op_trace why), - - TP_ARGS(cookie, op, why), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(enum fscache_op_trace, why ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->op = op->debug_id; - __entry->why = why; - ), - - TP_printk("c=%08x op=%08x %s", - __entry->cookie, __entry->op, - __print_symbolic(__entry->why, fscache_op_traces)) - ); - #endif /* _TRACE_FSCACHE_H */ /* This part must be outside protection */ From patchwork Fri Nov 20 15:06:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329224 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A230C63798 for ; Fri, 20 Nov 2020 15:06:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 35036221F8 for ; Fri, 20 Nov 2020 15:06:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="VDm4iLJL" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728719AbgKTPGP (ORCPT ); Fri, 20 Nov 2020 10:06:15 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:24508 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728709AbgKTPGO (ORCPT ); Fri, 20 Nov 2020 10:06:14 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884771; 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=3cmElf377VV5pCaI3ZacaDWr2Vk1dfkCNkh+Zy78XCE=; b=VDm4iLJLK7XBZkoEzOrWil6EeuNPkhm0ZYWx53uaiziTvjE5vOC2D+Q6DSJbyWsrp82hBh /aRJU4d3cq3iPxeMnHUrd9T21uDijKlvtmNY0cI/KD+rUauD8Pwr62+Y/DPhMrqPjuFcld jzGUDUOAgrv5EAfFHeZNqMpBZWv6G5A= 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-10-DZ7F8qW9NdqT_zr_ech__A-1; Fri, 20 Nov 2020 10:06:09 -0500 X-MC-Unique: DZ7F8qW9NdqT_zr_ech__A-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1B098100C612; Fri, 20 Nov 2020 15:06:08 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4391F60C15; Fri, 20 Nov 2020 15:06:01 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 16/76] cachefiles: Change %p in format strings to something else From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:06:00 +0000 Message-ID: <160588476042.3465195.6837847445880367183.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Change plain %p in format strings in cachefiles code to something more useful, since %p is now hashed before printing and thus no longer matches the contents of an oops register dump. Signed-off-by: David Howells --- fs/cachefiles/bind.c | 2 -- fs/cachefiles/interface.c | 6 +++--- fs/cachefiles/key.c | 2 +- fs/cachefiles/namei.c | 46 +++++++++++++++++++++------------------------ fs/cachefiles/xattr.c | 4 ++-- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c index dfb14dbddf51..2e9d01a9d53f 100644 --- a/fs/cachefiles/bind.c +++ b/fs/cachefiles/bind.c @@ -108,8 +108,6 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) atomic_set(&fsdef->usage, 1); fsdef->type = FSCACHE_COOKIE_TYPE_INDEX; - _debug("- fsdef %p", fsdef); - /* look up the directory at the root of the cache */ ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path); if (ret < 0) diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 99f42d216ef7..7e10793352fd 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -27,7 +27,7 @@ static struct fscache_object *cachefiles_alloc_object( cache = container_of(_cache, struct cachefiles_cache, cache); - _enter("{%s},%p,", cache->cache.identifier, cookie); + _enter("{%s},%x,", cache->cache.identifier, cookie->debug_id); /* create a new object record and a temporary leaf image */ object = kmem_cache_alloc(cachefiles_object_jar, cachefiles_gfp); @@ -68,7 +68,7 @@ static struct fscache_object *cachefiles_alloc_object( object->lookup_key = key; - _leave(" = %p [%s]", &object->fscache, key); + _leave(" = %x [%s]", object->fscache.debug_id, key); return &object->fscache; nomem_key: @@ -301,7 +301,7 @@ static void cachefiles_sync_cache(struct fscache_cache *_cache) const struct cred *saved_cred; int ret; - _enter("%p", _cache); + _enter("%s", _cache->tag->name); cache = container_of(_cache, struct cachefiles_cache, cache); diff --git a/fs/cachefiles/key.c b/fs/cachefiles/key.c index be96f5fc5cac..7f94efc97e23 100644 --- a/fs/cachefiles/key.c +++ b/fs/cachefiles/key.c @@ -150,6 +150,6 @@ char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type) key[len++] = 0; key[len] = 0; - _leave(" = %p %d", key, len); + _leave(" = %s %d", key, len); return key; } diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 924042e8cced..2f37451691b0 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -38,17 +38,17 @@ void __cachefiles_printk_object(struct cachefiles_object *object, object->fscache.events, object->fscache.event_mask); pr_err("%sops=%u\n", prefix, object->fscache.n_ops); - pr_err("%sparent=%p\n", - prefix, object->fscache.parent); + pr_err("%sparent=%x\n", + prefix, object->fscache.parent ? object->fscache.parent->debug_id : 0); spin_lock(&object->fscache.lock); cookie = object->fscache.cookie; if (cookie) { - pr_err("%scookie=%p [pr=%p fl=%lx]\n", + pr_err("%scookie=%x [pr=%x fl=%lx]\n", prefix, - object->fscache.cookie, - object->fscache.cookie->parent, - object->fscache.cookie->flags); + cookie->debug_id, + cookie->parent ? cookie->parent->debug_id : 0, + cookie->flags); pr_err("%skey=[%u] '", prefix, cookie->key_len); k = (cookie->key_len <= sizeof(cookie->inline_key)) ? cookie->inline_key : cookie->key; @@ -108,7 +108,7 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache, /* found the dentry for */ found_dentry: - kdebug("preemptive burial: OBJ%x [%s] %p", + kdebug("preemptive burial: OBJ%x [%s] %pd", object->fscache.debug_id, object->fscache.state->name, dentry); @@ -138,7 +138,7 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache, struct rb_node **_p, *_parent = NULL; struct dentry *dentry; - _enter(",%p", object); + _enter(",%x", object->fscache.debug_id); try_again: write_lock(&cache->active_lock); @@ -296,8 +296,6 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, _enter(",'%pd','%pd'", dir, rep); - _debug("remove %p from %p", rep, dir); - /* non-directories can just be unlinked */ if (!d_is_dir(rep)) { _debug("unlink stale object"); @@ -436,7 +434,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache, struct dentry *dir; int ret; - _enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry); + _enter(",OBJ%x{%pd}", object->fscache.debug_id, object->dentry); ASSERT(object->dentry); ASSERT(d_backing_inode(object->dentry)); @@ -489,7 +487,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, const char *name; int ret, nlen; - _enter("OBJ%x{%p},OBJ%x,%s,", + _enter("OBJ%x{%pd},OBJ%x,%s,", parent->fscache.debug_id, parent->dentry, object->fscache.debug_id, key); @@ -534,7 +532,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, inode = d_backing_inode(next); trace_cachefiles_lookup(object, next, inode); - _debug("next -> %p %s", next, inode ? "positive" : "negative"); + _debug("next -> %pd %s", next, inode ? "positive" : "negative"); if (!key) object->new = !inode; @@ -572,8 +570,8 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, } ASSERT(d_backing_inode(next)); - _debug("mkdir -> %p{%p{ino=%lu}}", - next, d_backing_inode(next), d_backing_inode(next)->i_ino); + _debug("mkdir -> %pd{ino=%lu}", + next, d_backing_inode(next)->i_ino); } else if (!d_can_lookup(next)) { pr_err("inode %lu is not a directory\n", @@ -602,8 +600,8 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, ASSERT(d_backing_inode(next)); - _debug("create -> %p{%p{ino=%lu}}", - next, d_backing_inode(next), d_backing_inode(next)->i_ino); + _debug("create -> %pd{ino=%lu}", + next, d_backing_inode(next)->i_ino); } else if (!d_can_lookup(next) && !d_is_reg(next) @@ -772,7 +770,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, goto lookup_error; } - _debug("subdir -> %p %s", + _debug("subdir -> %pd %s", subdir, d_backing_inode(subdir) ? "positive" : "negative"); /* we need to create the subdir if it doesn't exist yet */ @@ -798,10 +796,8 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, } ASSERT(d_backing_inode(subdir)); - _debug("mkdir -> %p{%p{ino=%lu}}", - subdir, - d_backing_inode(subdir), - d_backing_inode(subdir)->i_ino); + _debug("mkdir -> %pd{ino=%lu}", + subdir, d_backing_inode(subdir)->i_ino); } inode_unlock(d_inode(dir)); @@ -879,7 +875,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache, if (IS_ERR(victim)) goto lookup_error; - //_debug("victim -> %p %s", + //_debug("victim -> %pd %s", // victim, d_backing_inode(victim) ? "positive" : "negative"); /* if the object is no longer there then we probably retired the object @@ -910,7 +906,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache, read_unlock(&cache->active_lock); - //_leave(" = %p", victim); + //_leave(" = %pd", victim); return victim; object_in_use: @@ -956,7 +952,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, if (IS_ERR(victim)) return PTR_ERR(victim); - _debug("victim -> %p %s", + _debug("victim -> %pd %s", victim, d_backing_inode(victim) ? "positive" : "negative"); /* okay... the victim is not being used so we can cull it diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index a4f1eddebe6f..46913d4157dd 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -41,7 +41,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object) else snprintf(type, 3, "%02x", object->fscache.cookie->type); - _enter("%p{%s}", object, type); + _enter("%x{%s}", object->fscache.debug_id, type); /* attempt to install a type label directly */ ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2, @@ -112,7 +112,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, if (!dentry) return -ESTALE; - _enter("%p,#%d", object, len); + _enter("%x,#%d", object->fscache.debug_id, len); buf = kmalloc(sizeof(struct cachefiles_xattr) + len, GFP_KERNEL); if (!buf) From patchwork Fri Nov 20 15:06:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329223 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47CE5C64E69 for ; Fri, 20 Nov 2020 15:07:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0F08E221F8 for ; Fri, 20 Nov 2020 15:07:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LZU4fw0D" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728753AbgKTPGm (ORCPT ); Fri, 20 Nov 2020 10:06:42 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:54339 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728741AbgKTPGi (ORCPT ); Fri, 20 Nov 2020 10:06:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884797; 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=Qkm/e0rlz+ex0k24vJWE6EFN4cUfhFOX5aFRkHyuCPQ=; b=LZU4fw0DuT3DVnOeT21c8UticKLug/a3GNZFY5yFFiB3u3LR5sZNgzt7D/j4sG6JQQRemo ZRgpDafs32huHSpHy3lDuMkBR6mC/VuDRH2h34TXvuEpPA3+SyfG4WCWpfpsEqhmy6YSxD hAvHZ2Ia4pztXIQGXrdFyS2w6+4GlkU= 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-581-7eBAHh8oPeGYxEzWYPuVMQ-1; Fri, 20 Nov 2020 10:06:35 -0500 X-MC-Unique: 7eBAHh8oPeGYxEzWYPuVMQ-1 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 E4D0C100C605; Fri, 20 Nov 2020 15:06:32 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 10FA95C1D5; Fri, 20 Nov 2020 15:06:29 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 18/76] vm: Add wait/unlock functions for PG_fscache From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:06:29 +0000 Message-ID: <160588478922.3465195.5607105634825839113.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add functions to unlock and wait for unlock of PG_fscache analogously with those for PG_lock. Signed-off-by: David Howells --- include/linux/pagemap.h | 14 ++++++++++++++ mm/filemap.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index e1e19c1f9ec9..67fe07096103 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -591,6 +591,7 @@ extern int __lock_page_async(struct page *page, struct wait_page_queue *wait); extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm, unsigned int flags); extern void unlock_page(struct page *page); +extern void unlock_page_fscache(struct page *page); /* * Return true if the page was successfully locked @@ -681,6 +682,19 @@ static inline int wait_on_page_locked_killable(struct page *page) return wait_on_page_bit_killable(compound_head(page), PG_locked); } +/** + * wait_on_page_fscache - Wait for PG_fscache to be cleared on a page + * @page: The page + * + * Wait for the fscache mark to be removed from a page, usually signifying the + * completion of a write from that page to the cache. + */ +static inline void wait_on_page_fscache(struct page *page) +{ + if (PagePrivate2(page)) + wait_on_page_bit(compound_head(page), PG_fscache); +} + extern void put_and_wait_on_page_locked(struct page *page); void wait_on_page_writeback(struct page *page); diff --git a/mm/filemap.c b/mm/filemap.c index d5e7c2029d16..cfb753955e36 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1466,6 +1466,24 @@ void unlock_page(struct page *page) } EXPORT_SYMBOL(unlock_page); +/** + * unlock_page_fscache - Unlock a page pinned with PG_fscache + * @page: The page + * + * Unlocks the page and wakes up sleepers in wait_on_page_fscache(). Also + * wakes those waiting for the lock and writeback bits because the wakeup + * mechanism is shared. But that's OK - those sleepers will just go back to + * sleep. + */ +void unlock_page_fscache(struct page *page) +{ + page = compound_head(page); + VM_BUG_ON_PAGE(!PagePrivate2(page), page); + clear_bit_unlock(PG_fscache, &page->flags); + wake_up_page_bit(page, PG_fscache); +} +EXPORT_SYMBOL(unlock_page_fscache); + /** * end_page_writeback - end writeback against a page * @page: the page From patchwork Fri Nov 20 15:06:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329222 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68680C63777 for ; Fri, 20 Nov 2020 15:07:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1492022226 for ; Fri, 20 Nov 2020 15:07:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="gfXGrmd7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728438AbgKTPHH (ORCPT ); Fri, 20 Nov 2020 10:07:07 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:54499 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728238AbgKTPHG (ORCPT ); Fri, 20 Nov 2020 10:07:06 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884825; 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=OASbtfxyD6eIUPjL3PNzYRIfoGBOulxlBVzyzkIasn0=; b=gfXGrmd7wd463+ERjAiLwGn9UlcFup+6K8HcLAu4wZN7ix7BNIB1mZLzVLsxTY4JSBdL5r 8nyp/okgP85N1Tc1GHQQyPuPApzVvijPDBhSFoaJaUSjqrP2SSjkETy/uvjp/18FhLh2kC C3N4eTnWZRzTBTMzooWcknuK5WtC+ro= 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-160-mRGFeT5KP024Srat-9T2_g-1; Fri, 20 Nov 2020 10:07:02 -0500 X-MC-Unique: mRGFeT5KP024Srat-9T2_g-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 346E31DDE6; Fri, 20 Nov 2020 15:07:00 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6356F19C71; Fri, 20 Nov 2020 15:06:54 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 20/76] mm: Stop generic_file_buffered_read() from grabbing a superfluous page From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:06:53 +0000 Message-ID: <160588481358.3465195.16552616179674485179.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Under some circumstances, generic_file_buffered_read() will allocate sufficient pages to read to the end of the file, call readahead/readpages on them and copy the data over - and then it will allocate another page at the EOF and call readpage on that and then ignore it. This is unnecessary and a waste of time and resources. Catch the overallocation in the "no_cached_page:" part and prevent it from happening. Signed-off-by: David Howells --- mm/filemap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index cfb753955e36..5a63aa1dd71e 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2447,6 +2447,8 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb, * Ok, it wasn't cached, so we need to create a new * page.. */ + if ((index << PAGE_SHIFT) >= i_size_read(inode)) + goto out; page = page_cache_alloc(mapping); if (!page) { error = -ENOMEM; From patchwork Fri Nov 20 15:07:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329221 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8EF6C64E90 for ; Fri, 20 Nov 2020 15:07:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 78E6D22226 for ; Fri, 20 Nov 2020 15:07:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="NllF+6NT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728786AbgKTPHh (ORCPT ); Fri, 20 Nov 2020 10:07:37 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:50077 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728799AbgKTPHe (ORCPT ); Fri, 20 Nov 2020 10:07:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884854; 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=Bgweb1jmdpCHvruqVyoEI8flRFRne4dfCSEko00LckE=; b=NllF+6NT0Ol4tCKW+jdPwRWy6s06sHu+VvDUejrLKJ82ZzdsiSuyFkP1f5zeKhFoHux0hE j+qhUrnzNi6htAwPzAwc4s2Ueh31Tb34LiuClDGQpqZfdyJe49TIEeZxsGzABw+EAfllMq g1WaWnLykZ7vRYsM+zyCX7sJaPF7eP0= 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-567-eGxZw4f6MEayrXmKVepFlg-1; Fri, 20 Nov 2020 10:07:27 -0500 X-MC-Unique: eGxZw4f6MEayrXmKVepFlg-1 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 55ADB801B27; Fri, 20 Nov 2020 15:07:25 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 89D8A5C224; Fri, 20 Nov 2020 15:07:17 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 22/76] vfs: Provide S_CACHE_FILE inode flag From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:07:16 +0000 Message-ID: <160588483671.3465195.4384812052790548928.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Provide an S_CACHE_FILE inode flag that cachefiles can set to ward off other kernel services and drivers (including itself) from using its cache files. Signed-off-by: David Howells --- include/linux/fs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index 52fb357579c8..f6dad577ea07 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1991,6 +1991,7 @@ struct super_operations { #define S_ENCRYPTED (1 << 14) /* Encrypted file (using fs/crypto/) */ #define S_CASEFOLD (1 << 15) /* Casefolded file */ #define S_VERITY (1 << 16) /* Verity file (using fs/verity/) */ +#define S_CACHE_FILE (1 << 17) /* File is in use as cache file (eg. fs/cachefiles) */ /* * Note that nosuid etc flags are inode-specific: setting some file-system From patchwork Fri Nov 20 15:07:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329220 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E7AF4C64E69 for ; Fri, 20 Nov 2020 15:08:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A62AA2222F for ; Fri, 20 Nov 2020 15:08:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Gsrr0muM" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728873AbgKTPH4 (ORCPT ); Fri, 20 Nov 2020 10:07:56 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:22534 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728358AbgKTPHz (ORCPT ); Fri, 20 Nov 2020 10:07:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884874; 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=cSBKZMQQx7IJOONTQG4My1SW3PCF/Wugv/7xWXwL1pA=; b=Gsrr0muM7gdrKuLAOAxVbOni3WD4bTFuvmUn+6Lgj3bes/jOwDO7RnBPXMXN1y3D/pRTCd 3uoQidY2XHKldkNcZsAPht8IbTEF8mux5T77Dz9QaSbNBmudrEQLu9wuZ352bw5OCFfXZt jMx14hz6X+WJpyihmUzdxple3WVS+Bk= 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-227-VjKu89TTMnqjhHpXjpmX3g-1; Fri, 20 Nov 2020 10:07:52 -0500 X-MC-Unique: VjKu89TTMnqjhHpXjpmX3g-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 24D958144F3; Fri, 20 Nov 2020 15:07:50 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 072DB5D9D0; Fri, 20 Nov 2020 15:07:43 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 24/76] fscache: Provide a simple thread pool for running ops asynchronously From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:07:43 +0000 Message-ID: <160588486318.3465195.8936971598684341062.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Provide a simple thread pool that can be used to run cookie management operations in the background and a dispatcher infrastructure to punt operations to the pool if threads are available or to just run the operation in the calling thread if not. A future patch will replace all the object state machine stuff with whole routines that do all the work in one go without trying to interleave bits from various objects. Signed-off-by: David Howells --- fs/fscache/Makefile | 1 fs/fscache/dispatcher.c | 145 ++++++++++++++++++++++++++++++++++++++++ fs/fscache/internal.h | 8 ++ fs/fscache/main.c | 7 ++ include/trace/events/fscache.h | 6 +- 5 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 fs/fscache/dispatcher.c diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile index ac3fcd909fff..7b10c6aad157 100644 --- a/fs/fscache/Makefile +++ b/fs/fscache/Makefile @@ -6,6 +6,7 @@ fscache-y := \ cache.o \ cookie.o \ + dispatcher.o \ fsdef.o \ main.o \ netfs.o \ diff --git a/fs/fscache/dispatcher.c b/fs/fscache/dispatcher.c new file mode 100644 index 000000000000..3d957e499da3 --- /dev/null +++ b/fs/fscache/dispatcher.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Object dispatcher + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#define FSCACHE_DEBUG_LEVEL OPERATION +#include +#include +#include +#include +#include "internal.h" + +#define FSCACHE_DISPATCHER_POOL_SIZE 8 + +static LIST_HEAD(fscache_pending_work); +static DEFINE_SPINLOCK(fscache_work_lock); +static DECLARE_WAIT_QUEUE_HEAD(fscache_dispatcher_pool); +static struct completion fscache_dispatcher_pool_done[FSCACHE_DISPATCHER_POOL_SIZE]; +static bool fscache_dispatcher_stop; + +struct fscache_work { + struct list_head link; + struct fscache_cookie *cookie; + struct fscache_object *object; + int param; + void (*func)(struct fscache_cookie *, struct fscache_object *, int); +}; + +/* + * Attempt to queue some work to do. If there's too much asynchronous work + * already queued, we'll do it here in this thread instead. + */ +void fscache_dispatch(struct fscache_cookie *cookie, + struct fscache_object *object, + int param, + void (*func)(struct fscache_cookie *, + struct fscache_object *, int)) +{ + struct fscache_work *work; + bool queued = false; + + work = kzalloc(sizeof(struct fscache_work), GFP_KERNEL); + if (work) { + work->cookie = cookie; + work->object = object; + work->param = param; + work->func = func; + + spin_lock(&fscache_work_lock); + if (waitqueue_active(&fscache_dispatcher_pool) || + list_empty(&fscache_pending_work)) { + fscache_cookie_get(cookie, fscache_cookie_get_work); + list_add_tail(&work->link, &fscache_pending_work); + wake_up(&fscache_dispatcher_pool); + queued = true; + } + spin_unlock(&fscache_work_lock); + } + + if (!queued) { + kfree(work); + func(cookie, object, param); + } +} + +/* + * A dispatcher thread. + */ +static int fscache_dispatcher(void *data) +{ + struct completion *done = data; + + for (;;) { + if (!list_empty(&fscache_pending_work)) { + struct fscache_work *work = NULL; + + spin_lock(&fscache_work_lock); + if (!list_empty(&fscache_pending_work)) { + work = list_entry(fscache_pending_work.next, + struct fscache_work, link); + list_del_init(&work->link); + } + spin_unlock(&fscache_work_lock); + + if (work) { + work->func(work->cookie, work->object, work->param); + fscache_cookie_put(work->cookie, fscache_cookie_put_work); + kfree(work); + } + continue; + } else if (fscache_dispatcher_stop) { + break; + } + + wait_event_freezable(fscache_dispatcher_pool, + (fscache_dispatcher_stop || + !list_empty(&fscache_pending_work))); + } + + complete_and_exit(done, 0); +} + +/* + * Start up the dispatcher threads. + */ +int fscache_init_dispatchers(void) +{ + struct task_struct *t; + int i; + + for (i = 0; i < FSCACHE_DISPATCHER_POOL_SIZE; i++) { + init_completion(&fscache_dispatcher_pool_done[i]); + t = kthread_create(fscache_dispatcher, + &fscache_dispatcher_pool_done[i], + "kfsc/%d", i); + if (IS_ERR(t)) + goto failed; + wake_up_process(t); + } + + return 0; + +failed: + fscache_dispatcher_stop = true; + wake_up_all(&fscache_dispatcher_pool); + for (i--; i >= 0; i--) + wait_for_completion(&fscache_dispatcher_pool_done[i]); + return PTR_ERR(t); +} + +/* + * Kill off the dispatcher threads. + */ +void fscache_kill_dispatchers(void) +{ + int i; + + fscache_dispatcher_stop = true; + wake_up_all(&fscache_dispatcher_pool); + + for (i = 0; i < FSCACHE_DISPATCHER_POOL_SIZE; i++) + wait_for_completion(&fscache_dispatcher_pool_done[i]); +} diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index bc5539d2157b..2100e2222884 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -75,6 +75,14 @@ extern struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *); extern void fscache_cookie_put(struct fscache_cookie *, enum fscache_cookie_trace); +/* + * dispatcher.c + */ +extern void fscache_dispatch(struct fscache_cookie *, struct fscache_object *, int, + void (*func)(struct fscache_cookie *, struct fscache_object *, int)); +extern int fscache_init_dispatchers(void); +extern void fscache_kill_dispatchers(void); + /* * fsdef.c */ diff --git a/fs/fscache/main.c b/fs/fscache/main.c index c1e6cc9091aa..c8f1beafa8e1 100644 --- a/fs/fscache/main.c +++ b/fs/fscache/main.c @@ -125,6 +125,10 @@ static int __init fscache_init(void) for_each_possible_cpu(cpu) init_waitqueue_head(&per_cpu(fscache_object_cong_wait, cpu)); + ret = fscache_init_dispatchers(); + if (ret < 0) + goto error_dispatchers; + ret = fscache_proc_init(); if (ret < 0) goto error_proc; @@ -159,6 +163,8 @@ static int __init fscache_init(void) unregister_sysctl_table(fscache_sysctl_header); error_sysctl: #endif + fscache_kill_dispatchers(); +error_dispatchers: fscache_proc_cleanup(); error_proc: destroy_workqueue(fscache_op_wq); @@ -183,6 +189,7 @@ static void __exit fscache_exit(void) unregister_sysctl_table(fscache_sysctl_header); #endif fscache_proc_cleanup(); + fscache_kill_dispatchers(); destroy_workqueue(fscache_op_wq); destroy_workqueue(fscache_object_wq); pr_notice("Unloaded\n"); diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h index 08d7de72409d..fb3fdf2921ee 100644 --- a/include/trace/events/fscache.h +++ b/include/trace/events/fscache.h @@ -26,11 +26,13 @@ enum fscache_cookie_trace { fscache_cookie_get_attach_object, fscache_cookie_get_reacquire, fscache_cookie_get_register_netfs, + fscache_cookie_get_work, fscache_cookie_put_acquire_nobufs, fscache_cookie_put_dup_netfs, fscache_cookie_put_relinquish, fscache_cookie_put_object, fscache_cookie_put_parent, + fscache_cookie_put_work, }; #endif @@ -45,11 +47,13 @@ enum fscache_cookie_trace { EM(fscache_cookie_get_attach_object, "GET obj") \ EM(fscache_cookie_get_reacquire, "GET raq") \ EM(fscache_cookie_get_register_netfs, "GET net") \ + EM(fscache_cookie_get_work, "GET wrk") \ EM(fscache_cookie_put_acquire_nobufs, "PUT nbf") \ EM(fscache_cookie_put_dup_netfs, "PUT dnt") \ EM(fscache_cookie_put_relinquish, "PUT rlq") \ EM(fscache_cookie_put_object, "PUT obj") \ - E_(fscache_cookie_put_parent, "PUT prn") + EM(fscache_cookie_put_parent, "PUT prn") \ + E_(fscache_cookie_put_work, "PUT wrk") /* * Export enum symbols via userspace. From patchwork Fri Nov 20 15:08:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329219 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78A3DC64EBC for ; Fri, 20 Nov 2020 15:09:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1CB0622226 for ; Fri, 20 Nov 2020 15:09:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="M/mhaXXy" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728525AbgKTPIr (ORCPT ); Fri, 20 Nov 2020 10:08:47 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:22339 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728489AbgKTPIq (ORCPT ); Fri, 20 Nov 2020 10:08:46 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884925; 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=RNxh6y+qHJcG9v0Fk0/xbz4y2bRjeKy5839qm1nYWZE=; b=M/mhaXXy6fYMIq0grCh9if6QeWWfffIItGmqeH6oXeZXmZrl5gYWtlJjmFPMVQXpcyn6FM IOduxbKf+RtUHRAH2Bq0fVac3KMJ5JrjW/jy0Vktb75oPvm+s0eWymPZouE0/n8DEbtP4K wkl2LYVEJ7pJpjvXKsXU3ra4fxQkPSk= 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-341-eYysgVn1OVKmuoiBAxh11Q-1; Fri, 20 Nov 2020 10:08:43 -0500 X-MC-Unique: eYysgVn1OVKmuoiBAxh11Q-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 66A19801AF1; Fri, 20 Nov 2020 15:08:41 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id A8D8419C46; Fri, 20 Nov 2020 15:08:35 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 28/76] fscache, cachefiles: Fix disabled histogram warnings From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:08:34 +0000 Message-ID: <160588491489.3465195.3904823431891430888.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Fix variable unused warnings due to disabled histogram stuff. Signed-off-by: David Howells --- fs/cachefiles/internal.h | 7 +++++-- fs/fscache/internal.h | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index b89f76a03546..16d15291a629 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -143,11 +143,11 @@ extern int cachefiles_check_in_use(struct cachefiles_cache *cache, /* * proc.c */ -#ifdef CONFIG_CACHEFILES_HISTOGRAM extern atomic_t cachefiles_lookup_histogram[HZ]; extern atomic_t cachefiles_mkdir_histogram[HZ]; extern atomic_t cachefiles_create_histogram[HZ]; +#ifdef CONFIG_CACHEFILES_HISTOGRAM extern int __init cachefiles_proc_init(void); extern void cachefiles_proc_cleanup(void); static inline @@ -162,7 +162,10 @@ void cachefiles_hist(atomic_t histogram[], unsigned long start_jif) #else #define cachefiles_proc_init() (0) #define cachefiles_proc_cleanup() do {} while (0) -#define cachefiles_hist(hist, start_jif) do {} while (0) +static inline +void cachefiles_hist(atomic_t histogram[], unsigned long start_jif) +{ +} #endif /* diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 6c2a6ebe4f02..2c1f4151c092 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -109,13 +109,13 @@ extern struct fscache_cookie fscache_fsdef_index; /* * histogram.c */ -#ifdef CONFIG_FSCACHE_HISTOGRAM extern atomic_t fscache_obj_instantiate_histogram[HZ]; extern atomic_t fscache_objs_histogram[HZ]; extern atomic_t fscache_ops_histogram[HZ]; extern atomic_t fscache_retrieval_delay_histogram[HZ]; extern atomic_t fscache_retrieval_histogram[HZ]; +#ifdef CONFIG_FSCACHE_HISTOGRAM static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif) { unsigned long jif = jiffies - start_jif; @@ -127,7 +127,9 @@ static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif) extern const struct seq_operations fscache_histogram_ops; #else -#define fscache_hist(hist, start_jif) do {} while (0) +static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif) +{ +} #endif /* From patchwork Fri Nov 20 15:08:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329218 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D839C8300B for ; Fri, 20 Nov 2020 15:09:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 015A422226 for ; Fri, 20 Nov 2020 15:09:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EFwTx+S6" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728818AbgKTPJB (ORCPT ); Fri, 20 Nov 2020 10:09:01 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:24256 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728921AbgKTPI7 (ORCPT ); Fri, 20 Nov 2020 10:08:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884938; 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=ZOVb4/i1tOkNLeMBcqUh14yQwdQw5pAq8B7ip/oyDBk=; b=EFwTx+S6v/N/sicnKNOnteziGIz2hAehYHRbi+IwhMldAvdoEZKn3sBLJSOQf17z5H31xt NlLfxGLSh4V0Ho1HN6ip4XSonb1ov+XwEMpML1xBqRCfOuHv92wkMoMk0fIBAdu5SWGfix cBAXo96a92GhruLNlg1u0tJzREgscwg= 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-577-1t8ANGtgM26B7ktBwz-usg-1; Fri, 20 Nov 2020 10:08:56 -0500 X-MC-Unique: 1t8ANGtgM26B7ktBwz-usg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D2E4F911E3; Fri, 20 Nov 2020 15:08:53 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 76AE260C05; Fri, 20 Nov 2020 15:08:47 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 29/76] fscache: Recast assertion in terms of cookie not being an index From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:08:46 +0000 Message-ID: <160588492664.3465195.1529947521472671914.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Recast assertion in terms of cookie not being an index rather than being a datafile. Signed-off-by: David Howells --- fs/fscache/cookie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 230025a1495c..8d8aba14912a 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -546,7 +546,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size) * there, and if it's doing that, it may as well just retire the * cookie. */ - ASSERTCMP(cookie->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE); + ASSERTCMP(cookie->type, !=, FSCACHE_COOKIE_TYPE_INDEX); spin_lock(&cookie->lock); cookie->object_size = new_size; From patchwork Fri Nov 20 15:09:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329217 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 767C9C64E7B for ; Fri, 20 Nov 2020 15:09:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 368C022226 for ; Fri, 20 Nov 2020 15:09:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XscdmhwE" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728959AbgKTPJ1 (ORCPT ); Fri, 20 Nov 2020 10:09:27 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:27803 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728220AbgKTPJZ (ORCPT ); Fri, 20 Nov 2020 10:09:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605884963; 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=dBCoiCN5XVfELQLO7B7yiTCBVdkB/qJdZ/0ff4EAhAw=; b=XscdmhwEXbplfQfdbroE+CC6lXq9Q3dKEAd7jTytJqPNcubLoacZi+rqB6JY8F31wRAtsR Afg251muQr1IP3GaddpPC8UUGn/gUT3Y8ifDsLpFxot9sV2N6O5Mfz62vTsequLudCVo20 xNPfH9SkPB6QewkIt8AmvgWdcZ7Zx+s= 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-345-kvSitNPpM_uq_PVH6yI1Gg-1; Fri, 20 Nov 2020 10:09:19 -0500 X-MC-Unique: kvSitNPpM_uq_PVH6yI1Gg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 97953801B26; Fri, 20 Nov 2020 15:09:17 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8BC566064B; Fri, 20 Nov 2020 15:09:11 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 31/76] fscache: Allow ->put_super() to be used to wait for cache operations From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:09:10 +0000 Message-ID: <160588495077.3465195.15576038355511521763.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Provide a helper to allow ->put_super() to be used to wait for outstanding cache operations that are pinning inodes. The helper has a loop that waits for the first inode that has a non-zero usage and a cookie. It then calls evict_inodes() to reduce the list and loops round again until it finds no more candidate inodes. Without this, evict_inodes() won't get rid of such operations, and the "VFS: Busy inodes ..." message will be displayed and the inode abandoned. Signed-off-by: David Howells --- fs/fscache/io.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fscache.h | 2 ++ 2 files changed, 52 insertions(+) diff --git a/fs/fscache/io.c b/fs/fscache/io.c index 87ffe84c9f27..de9ffc16eb4f 100644 --- a/fs/fscache/io.c +++ b/fs/fscache/io.c @@ -180,3 +180,53 @@ int fscache_set_page_dirty(struct page *page, struct fscache_cookie *cookie) return 1; } EXPORT_SYMBOL(fscache_set_page_dirty); + +/** + * fscache_put_super - Wait for outstanding ops to complete + * @sb: The superblock to wait on + * @get_cookie: Function to get the cookie on an inode + * + * Wait for outstanding cache operations on the inodes of a superblock to + * complete as they might be pinning an inode. This is designed to be called + * from ->put_super(), right before the "VFS: Busy inodes" check. + */ +void fscache_put_super(struct super_block *sb, + struct fscache_cookie *(*get_cookie)(struct inode *inode)) +{ + struct fscache_cookie *cookie; + struct inode *inode, *p; + + while (!list_empty(&sb->s_inodes)) { + /* Find the first inode that we need to wait on */ + inode = NULL; + cookie = NULL; + spin_lock(&sb->s_inode_list_lock); + list_for_each_entry(p, &sb->s_inodes, i_sb_list) { + if (atomic_inc_not_zero(&p->i_count)) { + inode = p; + cookie = get_cookie(inode); + if (!cookie) { + iput(inode); + inode = NULL; + cookie = NULL; + continue; + } + break; + } + } + spin_unlock(&sb->s_inode_list_lock); + + if (inode) { + /* n_ops is kept artificially raised to stop wakeups */ + atomic_dec(&cookie->n_ops); + wait_var_event(&cookie->n_ops, atomic_read(&cookie->n_ops) == 0); + atomic_inc(&cookie->n_ops); + iput(inode); + } + + evict_inodes(sb); + if (!inode) + break; + } +} +EXPORT_SYMBOL(fscache_put_super); diff --git a/include/linux/fscache.h b/include/linux/fscache.h index d2fc98a5755a..38a252b06b54 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -204,6 +204,8 @@ extern int __fscache_begin_operation(struct fscache_cookie *, struct fscache_op_ extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool); extern void __fscache_update_cookie(struct fscache_cookie *, const void *, const loff_t *); extern void __fscache_invalidate(struct fscache_cookie *, loff_t); +extern void fscache_put_super(struct super_block *, + struct fscache_cookie *(*get_cookie)(struct inode *)); /** * fscache_register_netfs - Register a filesystem as desiring caching services From patchwork Fri Nov 20 15:09:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329216 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1B03C64E7A for ; Fri, 20 Nov 2020 15:10:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 648032222F for ; Fri, 20 Nov 2020 15:10:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="HujeuwhX" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728588AbgKTPKT (ORCPT ); Fri, 20 Nov 2020 10:10:19 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:23310 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728600AbgKTPKS (ORCPT ); Fri, 20 Nov 2020 10:10:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885015; 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=d1Fc0lNxMiIDpxqwWLHfiKydIckFFR6M8sjHQnyQcXA=; b=HujeuwhXWE61/unrG4meWqTW7WsANt+wHVvrYSBbaBglWzAJ7Qk42dZyFnGvxdTd/o74sb 7roHAcnIhIAH4LdeTpiFXnrbv4WyP3WOr91U8HluVet3+VEwXppN7OrV4X7K6Qu+2UTogP EJ9ylocanbKGJ6JSJi5u1Mr6jpaThEI= 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-148-Z9q_S-D1MqClzmz0s9PzVQ-1; Fri, 20 Nov 2020 10:10:14 -0500 X-MC-Unique: Z9q_S-D1MqClzmz0s9PzVQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id EB318190D345; Fri, 20 Nov 2020 15:10:08 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3E5BC60C61; Fri, 20 Nov 2020 15:09:55 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 34/76] netfs: Use the cache From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:09:54 +0000 Message-ID: <160588499435.3465195.10676629484149032256.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add support to the netfs support read helpers for reading data from the cache instead of downloading it from the server and support for writing data just downloaded or cleared to the cache. Signed-off-by: David Howells --- fs/fscache/io.c | 1 fs/netfs/read_helper.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fscache.h | 11 +++ include/linux/netfs.h | 5 + 4 files changed, 213 insertions(+), 1 deletion(-) diff --git a/fs/fscache/io.c b/fs/fscache/io.c index de9ffc16eb4f..90c056e85cea 100644 --- a/fs/fscache/io.c +++ b/fs/fscache/io.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "internal.h" /* diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index d0e3d5e0ced4..f5185402b504 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -79,6 +79,7 @@ static void netfs_put_read_request(struct netfs_read_request *rreq) netfs_rreq_clear_subreqs(rreq); if (rreq->netfs_priv) rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); + fscache_end_operation(&rreq->cache_resources); kfree(rreq); } } @@ -125,6 +126,31 @@ static void netfs_clear_unread(struct netfs_read_subrequest *subreq) iov_iter_zero(iov_iter_count(&iter), &iter); } +static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or_error) +{ + struct netfs_read_subrequest *subreq = priv; + + netfs_subreq_terminated(subreq, transferred_or_error); +} + +/* + * Issue a read against the cache. + * - Eats the caller's ref on subreq. + */ +static void netfs_read_from_cache(struct netfs_read_request *rreq, + struct netfs_read_subrequest *subreq, + bool seek_data) +{ + struct iov_iter iter; + + iov_iter_xarray(&iter, READ, &rreq->mapping->i_pages, + subreq->start + subreq->transferred, + subreq->len - subreq->transferred); + + fscache_read(&rreq->cache_resources, subreq->start, &iter, seek_data, + netfs_cache_read_terminated, subreq); +} + /* * Fill a subrequest region with zeroes. */ @@ -166,6 +192,122 @@ static void netfs_rreq_completed(struct netfs_read_request *rreq) netfs_put_read_request(rreq); } +/* + * Deal with the completion of writing the data to the cache. We have to clear + * the PG_fscache bits on the pages involved and release the caller's ref. + * + * May be called in softirq mode and we inherit a ref from the caller. + */ +static void netfs_rreq_unmark_after_write(struct netfs_read_request *rreq) +{ + struct netfs_read_subrequest *subreq; + struct page *page; + pgoff_t unlocked = 0; + bool have_unlocked = false; + + rcu_read_lock(); + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + XA_STATE(xas, &rreq->mapping->i_pages, subreq->start / PAGE_SIZE); + + xas_for_each(&xas, page, (subreq->start + subreq->len - 1) / PAGE_SIZE) { + /* We might have multiple writes from the same huge + * page, but we mustn't unlock a page more than once. + */ + if (have_unlocked && page->index <= unlocked) + continue; + unlocked = page->index; + unlock_page_fscache(page); + have_unlocked = true; + } + } + + rcu_read_unlock(); + netfs_rreq_completed(rreq); +} + +static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_error) +{ + struct netfs_read_subrequest *subreq = priv; + struct netfs_read_request *rreq = subreq->rreq; + + if (IS_ERR_VALUE(transferred_or_error)) + subreq->error = transferred_or_error; + else + subreq->error = 0; + + /* If we decrement nr_wr_ops to 0, the ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_wr_ops)) + netfs_rreq_unmark_after_write(rreq); + + netfs_put_subrequest(subreq); +} + +/* + * Perform any outstanding writes to the cache. We inherit a ref from the + * caller. + */ +static void netfs_rreq_do_write_to_cache(struct netfs_read_request *rreq) +{ + struct netfs_read_subrequest *subreq, *next, *p; + struct iov_iter iter; + + /* We don't want terminating writes trying to wake us up whilst we're + * still going through the list. + */ + atomic_inc(&rreq->nr_wr_ops); + + list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { + if (!test_bit(NETFS_SREQ_WRITE_TO_CACHE, &subreq->flags)) { + list_del_init(&subreq->rreq_link); + netfs_put_subrequest(subreq); + } + } + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + /* Amalgamate adjacent writes */ + while (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { + next = list_next_entry(subreq, rreq_link); + if (next->start > subreq->start + subreq->len) + break; + subreq->len += next->len; + list_del_init(&next->rreq_link); + netfs_put_subrequest(next); + } + + iov_iter_xarray(&iter, WRITE, &rreq->mapping->i_pages, + subreq->start, subreq->len); + + atomic_inc(&rreq->nr_wr_ops); + netfs_get_read_subrequest(subreq); + fscache_write(&rreq->cache_resources, subreq->start, &iter, + netfs_rreq_copy_terminated, subreq); + } + + /* If we decrement nr_wr_ops to 0, the usage ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_wr_ops)) + netfs_rreq_unmark_after_write(rreq); +} + +static void netfs_rreq_write_to_cache_work(struct work_struct *work) +{ + struct netfs_read_request *rreq = + container_of(work, struct netfs_read_request, work); + + netfs_rreq_do_write_to_cache(rreq); +} + +static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq) +{ + if (in_softirq()) { + rreq->work.func = netfs_rreq_write_to_cache_work; + if (!queue_work(system_unbound_wq, &rreq->work)) + BUG(); + } else { + netfs_rreq_do_write_to_cache(rreq); + } +} + /* * Unlock the pages in a read operation. We need to set PG_fscache on any * pages we're going to write back before we unlock them. @@ -258,7 +400,10 @@ static void netfs_rreq_short_read(struct netfs_read_request *rreq, netfs_get_read_subrequest(subreq); atomic_inc(&rreq->nr_rd_ops); - netfs_read_from_server(rreq, subreq); + if (subreq->source == NETFS_READ_FROM_CACHE) + netfs_read_from_cache(rreq, subreq, true); + else + netfs_read_from_server(rreq, subreq); } /* @@ -299,6 +444,25 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_read_request *rreq) return false; } +/* + * Check to see if the data read is still valid. + */ +static void netfs_rreq_is_still_valid(struct netfs_read_request *rreq) +{ + struct netfs_read_subrequest *subreq; + + if (!rreq->netfs_ops->is_still_valid || + rreq->netfs_ops->is_still_valid(rreq)) + return; + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + if (subreq->source == NETFS_READ_FROM_CACHE) { + subreq->error = -ESTALE; + __set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); + } + } +} + /* * Assess the state of a read request and decide what to do next. * @@ -308,6 +472,8 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_read_request *rreq) static void netfs_rreq_assess(struct netfs_read_request *rreq) { again: + netfs_rreq_is_still_valid(rreq); + if (!test_bit(NETFS_RREQ_FAILED, &rreq->flags) && test_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags)) { if (netfs_rreq_perform_resubmissions(rreq)) @@ -320,6 +486,9 @@ static void netfs_rreq_assess(struct netfs_read_request *rreq) clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); + if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags)) + return netfs_rreq_write_to_cache(rreq); + netfs_rreq_completed(rreq); } @@ -434,7 +603,11 @@ static enum netfs_read_source netfs_cache_prepare_read(struct netfs_read_subrequ loff_t i_size) { struct netfs_read_request *rreq = subreq->rreq; + struct fscache_op_resources *opr = &rreq->cache_resources; + const struct fscache_op_ops *ops = fscache_operation_valid(opr); + if (ops) + return ops->prepare_read(subreq, i_size); if (subreq->start >= rreq->i_size) return NETFS_FILL_WITH_ZEROES; return NETFS_DOWNLOAD_FROM_SERVER; @@ -524,6 +697,9 @@ static bool netfs_rreq_submit_slice(struct netfs_read_request *rreq, case NETFS_DOWNLOAD_FROM_SERVER: netfs_read_from_server(rreq, subreq); break; + case NETFS_READ_FROM_CACHE: + netfs_read_from_cache(rreq, subreq, false); + break; default: BUG(); } @@ -536,9 +712,24 @@ static bool netfs_rreq_submit_slice(struct netfs_read_request *rreq, return false; } +static void netfs_cache_expand_readahead(struct netfs_read_request *rreq, + loff_t *_start, size_t *_len, loff_t i_size) +{ + struct fscache_op_resources *opr = &rreq->cache_resources; + const struct fscache_op_ops *ops = fscache_operation_valid(opr); + + if (ops) + ops->expand_readahead(opr, _start, _len, i_size); +} + static void netfs_rreq_expand(struct netfs_read_request *rreq, struct readahead_control *ractl) { + /* Give the cache a chance to change the request parameters. The + * resultant request must contain the original region. + */ + netfs_cache_expand_readahead(rreq, &rreq->start, &rreq->len, rreq->i_size); + /* Give the netfs a chance to change the request parameters. The * resultant request must contain the original region. */ @@ -600,6 +791,8 @@ void netfs_readahead(struct readahead_control *ractl, rreq->start = readahead_pos(ractl); rreq->len = readahead_length(ractl); + if (ops->begin_cache_operation) + ops->begin_cache_operation(rreq); netfs_rreq_expand(rreq, ractl); atomic_set(&rreq->nr_rd_ops, 1); @@ -670,6 +863,8 @@ int netfs_readpage(struct file *file, rreq->start = page->index * PAGE_SIZE; rreq->len = thp_size(page); + if (ops->begin_cache_operation) + ops->begin_cache_operation(rreq); netfs_get_read_request(rreq); atomic_set(&rreq->nr_rd_ops, 1); diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 38a252b06b54..3c53386e4f6e 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -52,6 +52,7 @@ struct fscache_cookie; struct fscache_netfs; struct fscache_op_resources; struct fscache_op_ops; +struct netfs_read_subrequest; typedef void (*fscache_io_terminated_t)(void *priv, ssize_t transferred_or_error); @@ -174,6 +175,16 @@ struct fscache_op_ops { struct iov_iter *iter, fscache_io_terminated_t term_func, void *term_func_priv); + + /* Expand readahead request */ + void (*expand_readahead)(struct fscache_op_resources *opr, + loff_t *_start, size_t *_len, loff_t i_size); + + /* Prepare a read operation, shortening it to a cached/uncached + * boundary as appropriate. + */ + enum netfs_read_source (*prepare_read)(struct netfs_read_subrequest *subreq, + loff_t i_size); }; /* diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 722b8131a1ea..f2ffea11ea9b 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -12,6 +12,8 @@ #ifndef _LINUX_NETFS_H #define _LINUX_NETFS_H +#include + enum netfs_read_source { NETFS_FILL_WITH_ZEROES, NETFS_DOWNLOAD_FROM_SERVER, @@ -47,10 +49,12 @@ struct netfs_read_subrequest { struct netfs_read_request { struct inode *inode; /* The file being accessed */ struct address_space *mapping; /* The mapping being accessed */ + struct fscache_op_resources cache_resources; struct list_head subrequests; /* Requests to fetch I/O from disk or net */ struct work_struct work; void *netfs_priv; /* Private data for the netfs */ atomic_t nr_rd_ops; /* Number of read ops in progress */ + atomic_t nr_wr_ops; /* Number of write ops in progress */ size_t submitted; /* Amount submitted for I/O so far */ size_t len; /* Length of the request */ short error; /* 0 or error that occurred */ @@ -73,6 +77,7 @@ struct netfs_read_request { */ struct netfs_read_request_ops { void (*init_rreq)(struct netfs_read_request *rreq, struct file *file); + int (*begin_cache_operation)(struct netfs_read_request *rreq); void (*expand_readahead)(struct netfs_read_request *rreq); bool (*clamp_length)(struct netfs_read_subrequest *subreq); void (*issue_op)(struct netfs_read_subrequest *subreq); From patchwork Fri Nov 20 15:10:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329215 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, UNWANTED_LANGUAGE_BODY autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 886BDC71156 for ; Fri, 20 Nov 2020 15:10:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4ACAD22252 for ; Fri, 20 Nov 2020 15:10:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ZSljGOEn" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729059AbgKTPKb (ORCPT ); Fri, 20 Nov 2020 10:10:31 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:29859 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728695AbgKTPK2 (ORCPT ); Fri, 20 Nov 2020 10:10:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885027; 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=Im8HRq4DABDY5FtqrDa23AHB5iQAdOCiN8Sx3QngDQk=; b=ZSljGOEn4EaTEhI33/TxFTpYM6FK55QeYJbhxJfLAGx03IiK+uS61lVF3lHZFroEwmQ8+g nYVcda6vreu+loctXX4GFkdC2JAj1OB6xws9XAZEZGIk+9721+eNo6ape+CzTgJHMrNZ2q heNJXOXOhuQlLTtTvPYJUmqnjN8UeWI= 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-142-ArZa48PpP3efDEZj8W9pbg-1; Fri, 20 Nov 2020 10:10:23 -0500 X-MC-Unique: ArZa48PpP3efDEZj8W9pbg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 627CC873163; Fri, 20 Nov 2020 15:10:21 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 07C0E5D6BA; Fri, 20 Nov 2020 15:10:14 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 35/76] fscache: read-helper: Add tracepoints From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:10:14 +0000 Message-ID: <160588501418.3465195.3819311073293372410.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add three tracepoints to track the activity of the read helpers: (1) fscache_support/fscache_read This logs entry to the read helpers and also expansion of the range in a readahead request. (2) fscache_support/fscache_rreq This logs the progress of fscache_read_request objects which track read requests. A read request may be a compound of multiple subrequests. (3) fscache_support/fscache_sreq This logs the progress of fscache_read_subrequest objects, which track the contributions from various sources to a read request. Signed-off-by: David Howells --- fs/netfs/read_helper.c | 37 ++++++++ include/linux/netfs.h | 2 include/trace/events/netfs.h | 200 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 include/trace/events/netfs.h diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index f5185402b504..21d3578c6979 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -16,6 +16,8 @@ #include #include #include "internal.h" +#define CREATE_TRACE_POINTS +#include MODULE_DESCRIPTION("Network fs support"); MODULE_AUTHOR("Red Hat, Inc."); @@ -38,6 +40,7 @@ static struct netfs_read_request *netfs_alloc_read_request( const struct netfs_read_request_ops *ops, void *netfs_priv, struct file *file) { + static atomic_t debug_ids; struct netfs_read_request *rreq; rreq = kzalloc(sizeof(struct netfs_read_request), GFP_KERNEL); @@ -46,6 +49,7 @@ static struct netfs_read_request *netfs_alloc_read_request( rreq->netfs_priv = netfs_priv; rreq->inode = file_inode(file); rreq->i_size = i_size_read(rreq->inode); + rreq->debug_id = atomic_inc_return(&debug_ids); INIT_LIST_HEAD(&rreq->subrequests); INIT_WORK(&rreq->work, netfs_rreq_work); refcount_set(&rreq->usage, 1); @@ -80,6 +84,7 @@ static void netfs_put_read_request(struct netfs_read_request *rreq) if (rreq->netfs_priv) rreq->netfs_ops->cleanup(rreq->mapping, rreq->netfs_priv); fscache_end_operation(&rreq->cache_resources); + trace_netfs_rreq(rreq, netfs_rreq_trace_free); kfree(rreq); } } @@ -109,6 +114,7 @@ static void netfs_get_read_subrequest(struct netfs_read_subrequest *subreq) static void __netfs_put_subrequest(struct netfs_read_subrequest *subreq) { + trace_netfs_sreq(subreq, netfs_sreq_trace_free); netfs_put_read_request(subreq->rreq); kfree(subreq); } @@ -188,6 +194,7 @@ static void netfs_read_from_server(struct netfs_read_request *rreq, */ static void netfs_rreq_completed(struct netfs_read_request *rreq) { + trace_netfs_rreq(rreq, netfs_rreq_trace_done); netfs_rreq_clear_subreqs(rreq); netfs_put_read_request(rreq); } @@ -205,6 +212,8 @@ static void netfs_rreq_unmark_after_write(struct netfs_read_request *rreq) pgoff_t unlocked = 0; bool have_unlocked = false; + trace_netfs_rreq(rreq, netfs_rreq_trace_unmark); + rcu_read_lock(); list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { @@ -236,6 +245,8 @@ static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_error) else subreq->error = 0; + trace_netfs_sreq(subreq, netfs_sreq_trace_write_term); + /* If we decrement nr_wr_ops to 0, the ref belongs to us. */ if (atomic_dec_and_test(&rreq->nr_wr_ops)) netfs_rreq_unmark_after_write(rreq); @@ -252,6 +263,8 @@ static void netfs_rreq_do_write_to_cache(struct netfs_read_request *rreq) struct netfs_read_subrequest *subreq, *next, *p; struct iov_iter iter; + trace_netfs_rreq(rreq, netfs_rreq_trace_write); + /* We don't want terminating writes trying to wake us up whilst we're * still going through the list. */ @@ -275,6 +288,8 @@ static void netfs_rreq_do_write_to_cache(struct netfs_read_request *rreq) netfs_put_subrequest(next); } + trace_netfs_sreq(subreq, netfs_sreq_trace_write); + iov_iter_xarray(&iter, WRITE, &rreq->mapping->i_pages, subreq->start, subreq->len); @@ -342,6 +357,8 @@ static void netfs_rreq_unlock(struct netfs_read_request *rreq) iopos = 0; subreq_failed = (subreq->error < 0); + trace_netfs_rreq(rreq, netfs_rreq_trace_unlock); + rcu_read_lock(); xas_for_each(&xas, page, last_page) { unsigned int pgpos = (page->index - start_page) * PAGE_SIZE; @@ -398,6 +415,8 @@ static void netfs_rreq_short_read(struct netfs_read_request *rreq, __clear_bit(NETFS_SREQ_SHORT_READ, &subreq->flags); __set_bit(NETFS_SREQ_SEEK_DATA_READ, &subreq->flags); + trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short); + netfs_get_read_subrequest(subreq); atomic_inc(&rreq->nr_rd_ops); if (subreq->source == NETFS_READ_FROM_CACHE) @@ -416,6 +435,8 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_read_request *rreq) WARN_ON(in_softirq()); + trace_netfs_rreq(rreq, netfs_rreq_trace_resubmit); + /* We don't want terminating submissions trying to wake us up whilst * we're still going through the list. */ @@ -428,6 +449,7 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_read_request *rreq) break; subreq->source = NETFS_DOWNLOAD_FROM_SERVER; subreq->error = 0; + trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); netfs_get_read_subrequest(subreq); atomic_inc(&rreq->nr_rd_ops); netfs_read_from_server(rreq, subreq); @@ -471,6 +493,8 @@ static void netfs_rreq_is_still_valid(struct netfs_read_request *rreq) */ static void netfs_rreq_assess(struct netfs_read_request *rreq) { + trace_netfs_rreq(rreq, netfs_rreq_trace_assess); + again: netfs_rreq_is_still_valid(rreq); @@ -558,6 +582,8 @@ void netfs_subreq_terminated(struct netfs_read_subrequest *subreq, set_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags); out: + trace_netfs_sreq(subreq, netfs_sreq_trace_terminated); + /* If we decrement nr_rd_ops to 0, the ref belongs to us. */ u = atomic_dec_return(&rreq->nr_rd_ops); if (u == 0) @@ -650,6 +676,7 @@ netfs_rreq_prepare_read(struct netfs_read_request *rreq, out: subreq->source = source; + trace_netfs_sreq(subreq, netfs_sreq_trace_prepare); return source; } @@ -690,6 +717,7 @@ static bool netfs_rreq_submit_slice(struct netfs_read_request *rreq, rreq->submitted += subreq->len; + trace_netfs_sreq(subreq, netfs_sreq_trace_submit); switch (source) { case NETFS_FILL_WITH_ZEROES: netfs_fill_with_zeroes(rreq, subreq); @@ -750,6 +778,9 @@ static void netfs_rreq_expand(struct netfs_read_request *rreq, readahead_expand(ractl, rreq->start, rreq->len); rreq->start = readahead_pos(ractl); rreq->len = readahead_length(ractl); + + trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), + netfs_read_trace_expanded); } } @@ -791,6 +822,9 @@ void netfs_readahead(struct readahead_control *ractl, rreq->start = readahead_pos(ractl); rreq->len = readahead_length(ractl); + trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), + netfs_read_trace_readahead); + if (ops->begin_cache_operation) ops->begin_cache_operation(rreq); netfs_rreq_expand(rreq, ractl); @@ -863,6 +897,9 @@ int netfs_readpage(struct file *file, rreq->start = page->index * PAGE_SIZE; rreq->len = thp_size(page); + trace_netfs_read(rreq, page->index * PAGE_SIZE, thp_size(page), + netfs_read_trace_readpage); + if (ops->begin_cache_operation) ops->begin_cache_operation(rreq); netfs_get_read_request(rreq); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index f2ffea11ea9b..c4276eb9914d 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -53,6 +53,8 @@ struct netfs_read_request { struct list_head subrequests; /* Requests to fetch I/O from disk or net */ struct work_struct work; void *netfs_priv; /* Private data for the netfs */ + unsigned int debug_id; + unsigned int cookie_debug_id; atomic_t nr_rd_ops; /* Number of read ops in progress */ atomic_t nr_wr_ops; /* Number of write ops in progress */ size_t submitted; /* Amount submitted for I/O so far */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h new file mode 100644 index 000000000000..56a734a3fb0d --- /dev/null +++ b/include/trace/events/netfs.h @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Network filesystem support module tracepoints + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM netfs + +#if !defined(_TRACE_NETFS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_NETFS_H + +#include +#include + +/* + * Define enums for tracing information. + */ +#ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY +#define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY + +enum netfs_read_trace { + netfs_read_trace_expanded, + netfs_read_trace_readahead, + netfs_read_trace_readpage, +}; + +enum netfs_rreq_trace { + netfs_rreq_trace_assess, + netfs_rreq_trace_done, + netfs_rreq_trace_free, + netfs_rreq_trace_resubmit, + netfs_rreq_trace_unlock, + netfs_rreq_trace_unmark, + netfs_rreq_trace_write, +}; + +enum netfs_sreq_trace { + netfs_sreq_trace_download_instead, + netfs_sreq_trace_free, + netfs_sreq_trace_prepare, + netfs_sreq_trace_resubmit_short, + netfs_sreq_trace_submit, + netfs_sreq_trace_terminated, + netfs_sreq_trace_write, + netfs_sreq_trace_write_term, +}; + +#endif + +#define netfs_read_traces \ + EM(netfs_read_trace_expanded, "EXPANDED ") \ + EM(netfs_read_trace_readahead, "READAHEAD") \ + E_(netfs_read_trace_readpage, "READPAGE ") + +#define netfs_rreq_traces \ + EM(netfs_rreq_trace_assess, "ASSESS") \ + EM(netfs_rreq_trace_done, "DONE ") \ + EM(netfs_rreq_trace_free, "FREE ") \ + EM(netfs_rreq_trace_resubmit, "RESUBM") \ + EM(netfs_rreq_trace_unlock, "UNLOCK") \ + EM(netfs_rreq_trace_unmark, "UNMARK") \ + E_(netfs_rreq_trace_write, "WRITE ") + +#define netfs_sreq_sources \ + EM(NETFS_FILL_WITH_ZEROES, "ZERO") \ + EM(NETFS_DOWNLOAD_FROM_SERVER, "DOWN") \ + EM(NETFS_READ_FROM_CACHE, "READ") \ + E_(NETFS_INVALID_READ, "INVL") \ + +#define netfs_sreq_traces \ + EM(netfs_sreq_trace_download_instead, "RDOWN") \ + EM(netfs_sreq_trace_free, "FREE ") \ + EM(netfs_sreq_trace_prepare, "PREP ") \ + EM(netfs_sreq_trace_resubmit_short, "SHORT") \ + EM(netfs_sreq_trace_submit, "SUBMT") \ + EM(netfs_sreq_trace_terminated, "TERM ") \ + EM(netfs_sreq_trace_write, "WRITE") \ + E_(netfs_sreq_trace_write_term, "WTERM") + + +/* + * Export enum symbols via userspace. + */ +#undef EM +#undef E_ +#define EM(a, b) TRACE_DEFINE_ENUM(a); +#define E_(a, b) TRACE_DEFINE_ENUM(a); + +netfs_read_traces; +netfs_rreq_traces; +netfs_sreq_sources; +netfs_sreq_traces; + +/* + * Now redefine the EM() and E_() macros to map the enums to the strings that + * will be printed in the output. + */ +#undef EM +#undef E_ +#define EM(a, b) { a, b }, +#define E_(a, b) { a, b } + +TRACE_EVENT(netfs_read, + TP_PROTO(struct netfs_read_request *rreq, + loff_t start, size_t len, + enum netfs_read_trace what), + + TP_ARGS(rreq, start, len, what), + + TP_STRUCT__entry( + __field(unsigned int, rreq ) + __field(unsigned int, cookie ) + __field(loff_t, start ) + __field(size_t, len ) + __field(enum netfs_read_trace, what ) + ), + + TP_fast_assign( + __entry->rreq = rreq->debug_id; + __entry->cookie = rreq->cookie_debug_id; + __entry->start = start; + __entry->len = len; + __entry->what = what; + ), + + TP_printk("R=%08x %s c=%08x s=%llx %zx", + __entry->rreq, + __print_symbolic(__entry->what, netfs_read_traces), + __entry->cookie, + __entry->start, __entry->len) + ); + +TRACE_EVENT(netfs_rreq, + TP_PROTO(struct netfs_read_request *rreq, + enum netfs_rreq_trace what), + + TP_ARGS(rreq, what), + + TP_STRUCT__entry( + __field(unsigned int, rreq ) + __field(unsigned short, flags ) + __field(enum netfs_rreq_trace, what ) + ), + + TP_fast_assign( + __entry->rreq = rreq->debug_id; + __entry->flags = rreq->flags; + __entry->what = what; + ), + + TP_printk("R=%08x %s f=%02x", + __entry->rreq, + __print_symbolic(__entry->what, netfs_rreq_traces), + __entry->flags) + ); + +TRACE_EVENT(netfs_sreq, + TP_PROTO(struct netfs_read_subrequest *sreq, + enum netfs_sreq_trace what), + + TP_ARGS(sreq, what), + + TP_STRUCT__entry( + __field(unsigned int, rreq ) + __field(unsigned short, index ) + __field(short, error ) + __field(unsigned short, flags ) + __field(enum netfs_read_source, source ) + __field(enum netfs_sreq_trace, what ) + __field(size_t, len ) + __field(size_t, transferred ) + __field(loff_t, start ) + ), + + TP_fast_assign( + __entry->rreq = sreq->rreq->debug_id; + __entry->index = sreq->debug_index; + __entry->error = sreq->error; + __entry->flags = sreq->flags; + __entry->source = sreq->source; + __entry->what = what; + __entry->len = sreq->len; + __entry->transferred = sreq->transferred; + __entry->start = sreq->start; + ), + + TP_printk("R=%08x[%u] %s %s f=%02x s=%llx %zx/%zx e=%d", + __entry->rreq, __entry->index, + __print_symbolic(__entry->what, netfs_sreq_traces), + __print_symbolic(__entry->source, netfs_sreq_sources), + __entry->flags, + __entry->start, __entry->transferred, __entry->len, + __entry->error) + ); + +#endif /* _TRACE_NETFS_H */ + +/* This part must be outside protection */ +#include From patchwork Fri Nov 20 15:10:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329214 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35013C63798 for ; Fri, 20 Nov 2020 15:12:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D318A2224E for ; Fri, 20 Nov 2020 15:12:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="gwFnJYxb" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729070AbgKTPKw (ORCPT ); Fri, 20 Nov 2020 10:10:52 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:60177 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728835AbgKTPKv (ORCPT ); Fri, 20 Nov 2020 10:10:51 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885049; 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=jgN+MGC/N1JFsilTJseek8GZKekZVmyr4jCTwGQ/Tsg=; b=gwFnJYxb/BwqmRsh5hvBswVRaVOH8TM5ypG4v/8vK7RG71jjmW8npmRRHXcuUWn7ELkQgT nFIaTkGr3eDDWnjhQHTUiXI8kvZyS/MIIrrPvJeTrr5/eO6pUrVyh9QaRvjc+gb4LQPuhs B1cXu1IZcwIdbZL9L3CAEIrf7ojSfTw= 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-393-QrUTJnf6Naa9wkEsuTM3Zg-1; Fri, 20 Nov 2020 10:10:47 -0500 X-MC-Unique: QrUTJnf6Naa9wkEsuTM3Zg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A17DE1005D59; Fri, 20 Nov 2020 15:10:45 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id A435D189A4; Fri, 20 Nov 2020 15:10:39 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 37/76] cachefiles: trace: Log coherency checks From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:10:38 +0000 Message-ID: <160588503886.3465195.6396776488623638977.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add a cachefiles tracepoint that logs the result of coherency management when the coherency data on a file in the cache is checked or committed. Signed-off-by: David Howells --- fs/cachefiles/xattr.c | 45 ++++++++++++++++++++++-------- include/trace/events/cachefiles.h | 56 +++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 12 deletions(-) diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index 75a2a6b70e4a..19db19b7d7db 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -125,12 +125,21 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, ret = vfs_setxattr(dentry, cachefiles_xattr_cache, buf, sizeof(struct cachefiles_xattr) + len, xattr_flags); - kfree(buf); - if (ret < 0 && ret != -ENOMEM) - cachefiles_io_error_obj( - object, - "Failed to set xattr with error %d", ret); + if (ret < 0) { + trace_cachefiles_coherency(object, d_inode(dentry)->i_ino, + 0, + cachefiles_coherency_set_fail); + if (ret != -ENOMEM) + cachefiles_io_error_obj( + object, + "Failed to set xattr with error %d", ret); + } else { + trace_cachefiles_coherency(object, d_inode(dentry)->i_ino, + 0, + cachefiles_coherency_set_ok); + } + kfree(buf); _leave(" = %d", ret); return ret; } @@ -144,7 +153,9 @@ int cachefiles_check_auxdata(struct cachefiles_object *object) struct dentry *dentry = object->dentry; unsigned int len = object->fscache.cookie->aux_len, tlen; const void *p = fscache_get_aux(object->fscache.cookie); - ssize_t ret; + enum cachefiles_coherency_trace why; + ssize_t xlen; + int ret = -ESTALE; ASSERT(dentry); ASSERT(d_backing_inode(dentry)); @@ -154,14 +165,24 @@ int cachefiles_check_auxdata(struct cachefiles_object *object) if (!buf) return -ENOMEM; - ret = vfs_getxattr(dentry, cachefiles_xattr_cache, buf, tlen); - if (ret == tlen && - buf->type == object->fscache.cookie->type && - memcmp(buf->data, p, len) == 0) + xlen = vfs_getxattr(dentry, cachefiles_xattr_cache, buf, tlen); + if (xlen != tlen) { + if (xlen == -EIO) + cachefiles_io_error_obj( + object, + "Failed to read aux with error %zd", xlen); + why = cachefiles_coherency_check_xattr; + } else if (buf->type != object->fscache.cookie->type) { + why = cachefiles_coherency_check_type; + } else if (memcmp(buf->data, p, len) != 0) { + why = cachefiles_coherency_check_aux; + } else { + why = cachefiles_coherency_check_ok; ret = 0; - else - ret = -ESTALE; + } + trace_cachefiles_coherency(object, d_inode(dentry)->i_ino, + 0, why); kfree(buf); return ret; } diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h index 0aa3f3126f6e..bf588c3f4a07 100644 --- a/include/trace/events/cachefiles.h +++ b/include/trace/events/cachefiles.h @@ -24,6 +24,19 @@ enum cachefiles_obj_ref_trace { cachefiles_obj_ref__nr_traces }; +enum cachefiles_coherency_trace { + cachefiles_coherency_check_aux, + cachefiles_coherency_check_content, + cachefiles_coherency_check_dirty, + cachefiles_coherency_check_len, + cachefiles_coherency_check_objsize, + cachefiles_coherency_check_ok, + cachefiles_coherency_check_type, + cachefiles_coherency_check_xattr, + cachefiles_coherency_set_fail, + cachefiles_coherency_set_ok, +}; + #endif /* @@ -56,6 +69,18 @@ enum cachefiles_obj_ref_trace { EM(cachefiles_obj_put_wait_retry, "PUT wait_retry") \ E_(cachefiles_obj_put_wait_timeo, "PUT wait_timeo") +#define cachefiles_coherency_traces \ + EM(cachefiles_coherency_check_aux, "BAD aux ") \ + EM(cachefiles_coherency_check_content, "BAD cont") \ + EM(cachefiles_coherency_check_dirty, "BAD dirt") \ + EM(cachefiles_coherency_check_len, "BAD len ") \ + EM(cachefiles_coherency_check_objsize, "BAD osiz") \ + EM(cachefiles_coherency_check_ok, "OK ") \ + EM(cachefiles_coherency_check_type, "BAD type") \ + EM(cachefiles_coherency_check_xattr, "BAD xatt") \ + EM(cachefiles_coherency_set_fail, "SET fail") \ + E_(cachefiles_coherency_set_ok, "SET ok ") + /* * Export enum symbols via userspace. */ @@ -66,6 +91,7 @@ enum cachefiles_obj_ref_trace { cachefiles_obj_kill_traces; cachefiles_obj_ref_traces; +cachefiles_coherency_traces; /* * Now redefine the EM() and E_() macros to map the enums to the strings that @@ -295,6 +321,36 @@ TRACE_EVENT(cachefiles_mark_buried, __print_symbolic(__entry->why, cachefiles_obj_kill_traces)) ); +TRACE_EVENT(cachefiles_coherency, + TP_PROTO(struct cachefiles_object *obj, + ino_t ino, + int content, + enum cachefiles_coherency_trace why), + + TP_ARGS(obj, ino, content, why), + + /* Note that obj may be NULL */ + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(enum cachefiles_coherency_trace, why ) + __field(int, content ) + __field(u64, ino ) + ), + + TP_fast_assign( + __entry->obj = obj->fscache.debug_id; + __entry->why = why; + __entry->content = content; + __entry->ino = ino; + ), + + TP_printk("o=%08x %s i=%llx c=%u", + __entry->obj, + __print_symbolic(__entry->why, cachefiles_coherency_traces), + __entry->ino, + __entry->content) + ); + #endif /* _TRACE_CACHEFILES_H */ /* This part must be outside protection */ From patchwork Fri Nov 20 15:11:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329213 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA099C64E7D for ; Fri, 20 Nov 2020 15:12:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 70F902224E for ; Fri, 20 Nov 2020 15:12:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="PY1vuHzL" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728124AbgKTPLT (ORCPT ); Fri, 20 Nov 2020 10:11:19 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:45652 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726335AbgKTPLS (ORCPT ); Fri, 20 Nov 2020 10:11:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885076; 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=w/+8PT6hvdzsqumpIcFkRs+u8vk9juQnIN7YFLeVybY=; b=PY1vuHzLgNAANIBJEKWHZXMwo/Wq1cV8qPi2yEJehaakS4lWTJcLKKU/QI97XkTjKym+B0 UAjV8eo3+aPb5U/1vjcZhLJ2HA+QuyvXOqbB+mEPtnhR244iQDKVZtUPYZSz7wDhU2jz8J qOPEm5rJEhsNVVJt7JxleK2uH26RPmk= 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-129-WU-p8fn4Pnq8RhluvRhokw-1; Fri, 20 Nov 2020 10:11:12 -0500 X-MC-Unique: WU-p8fn4Pnq8RhluvRhokw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3B640801B1A; Fri, 20 Nov 2020 15:11:09 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3C34110021B3; Fri, 20 Nov 2020 15:11:03 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 39/76] cachefiles: Implement new fscache I/O backend API From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:11:02 +0000 Message-ID: <160588506244.3465195.14835834211702469652.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Implement the new fscache I/O backend API in cachefiles. The cachefiles_object struct carries a non-accounted file to the cachefiles object (so that it doesn't cause ENFILE). Signed-off-by: David Howells --- fs/cachefiles/Makefile | 1 + fs/cachefiles/interface.c | 13 +++++++ fs/cachefiles/internal.h | 19 ++++++++++ fs/cachefiles/io.c | 85 +++++++++++++++++++++++++++++++++++++++++++++ fs/cachefiles/namei.c | 3 ++ 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 fs/cachefiles/io.c diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile index 3455d3646547..d894d317d6e7 100644 --- a/fs/cachefiles/Makefile +++ b/fs/cachefiles/Makefile @@ -7,6 +7,7 @@ cachefiles-y := \ bind.o \ daemon.o \ interface.o \ + io.o \ key.o \ main.o \ namei.o \ diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 3f6d2be690bc..dc8c875223bb 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -453,6 +453,18 @@ static unsigned int cachefiles_get_object_usage(const struct fscache_object *_ob return atomic_read(&object->usage); } +static const struct fscache_op_ops cachefiles_io_ops = { + .wait_for_operation = __fscache_wait_for_operation, + .end_operation = __fscache_end_operation, + .read = cachefiles_read, + .write = cachefiles_write, +}; + +static void cachefiles_begin_operation(struct fscache_op_resources *opr) +{ + opr->ops = &cachefiles_io_ops; +} + const struct fscache_cache_ops cachefiles_cache_ops = { .name = "cachefiles", .alloc_object = cachefiles_alloc_object, @@ -466,4 +478,5 @@ const struct fscache_cache_ops cachefiles_cache_ops = { .put_object = cachefiles_put_object, .get_object_usage = cachefiles_get_object_usage, .sync_cache = cachefiles_sync_cache, + .begin_operation = cachefiles_begin_operation, }; diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index 16d15291a629..caa6dfbaf333 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -115,6 +115,22 @@ extern const struct fscache_cache_ops cachefiles_cache_ops; extern struct fscache_object *cachefiles_grab_object(struct fscache_object *_object, enum fscache_obj_ref_trace why); +/* + * io.c + */ +extern int cachefiles_read(struct fscache_op_resources *opr, + loff_t start_pos, + struct iov_iter *iter, + bool seek_data, + fscache_io_terminated_t term_func, + void *term_func_priv); +extern int cachefiles_write(struct fscache_op_resources *opr, + loff_t start_pos, + struct iov_iter *iter, + fscache_io_terminated_t term_func, + void *term_func_priv); +extern bool cachefiles_open_object(struct cachefiles_object *obj); + /* * key.c */ @@ -216,7 +232,8 @@ do { \ \ ___cache = container_of((object)->fscache.cache, \ struct cachefiles_cache, cache); \ - cachefiles_io_error(___cache, FMT, ##__VA_ARGS__); \ + cachefiles_io_error(___cache, FMT " [o=%08x]", ##__VA_ARGS__, \ + object->fscache.debug_id); \ } while (0) diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c new file mode 100644 index 000000000000..f1d5976aa28c --- /dev/null +++ b/fs/cachefiles/io.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Data I/O routines + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include +#include +#include +#include "internal.h" +#include + +/* + * Initiate a read from the cache. + */ +int cachefiles_read(struct fscache_op_resources *opr, + loff_t start_pos, + struct iov_iter *iter, + bool seek_data, + fscache_io_terminated_t term_func, + void *term_func_priv) +{ + fscache_wait_for_operation(opr, FSCACHE_WANT_READ); + fscache_count_io_operation(opr->object->cookie); + if (term_func) + term_func(term_func_priv, -ENODATA); + return -ENODATA; +} + +/* + * Initiate a write to the cache. + */ +int cachefiles_write(struct fscache_op_resources *opr, + loff_t start_pos, + struct iov_iter *iter, + fscache_io_terminated_t term_func, + void *term_func_priv) +{ + fscache_wait_for_operation(opr, FSCACHE_WANT_WRITE); + fscache_count_io_operation(opr->object->cookie); + if (term_func) + term_func(term_func_priv, -ENOBUFS); + return -ENOBUFS; +} + +/* + * Open a cache object. + */ +bool cachefiles_open_object(struct cachefiles_object *object) +{ + struct cachefiles_cache *cache = + container_of(object->fscache.cache, struct cachefiles_cache, cache); + struct file *file; + struct path path; + + path.mnt = cache->mnt; + path.dentry = object->backer; + + file = open_with_fake_path(&path, + O_RDWR | O_LARGEFILE | O_DIRECT, + d_backing_inode(object->backer), + cache->cache_cred); + if (IS_ERR(file)) + goto error; + + if (!S_ISREG(file_inode(file)->i_mode)) + goto error_file; + + if (unlikely(!file->f_op->read_iter) || + unlikely(!file->f_op->write_iter)) { + pr_notice("Cache does not support read_iter and write_iter\n"); + goto error_file; + } + + object->backing_file = file; + return true; + +error_file: + fput(file); +error: + return false; +} diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 0a7e2031efa2..4b515054d92e 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -490,6 +490,9 @@ bool cachefiles_walk_to_object(struct cachefiles_object *parent, } else { BUG(); // TODO: open file in data-class subdir } + + if (!cachefiles_open_object(object)) + goto check_error; } if (object->new) From patchwork Fri Nov 20 15:11:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329212 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 249D5C64E69 for ; Fri, 20 Nov 2020 15:12:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DF04A2222F for ; Fri, 20 Nov 2020 15:12:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="BGCAOxdn" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728781AbgKTPLp (ORCPT ); Fri, 20 Nov 2020 10:11:45 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:50406 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725890AbgKTPLm (ORCPT ); Fri, 20 Nov 2020 10:11:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885098; 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=gBRqQQCAwiewSr3Mz1MyPJP/r3DASh8azb14ddhRPVg=; b=BGCAOxdnlIYRTiKl/wkDpawrTKJICO71TFwnmerGchctYo+Ga4svOwXbma5SkbrmylXDbG Pxj8+V8AlnQxEeqxKyE6odOwqnOMpy1f9lHkTdSITdiXBJrkVVWEeSHMcnPxEfHu6ZXv3V IIQKoJIT2jAGTN7fB/pcg8FRb4nX2QI= 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-147-msQHBA0UORirEomDJM91DQ-1; Fri, 20 Nov 2020 10:11:35 -0500 X-MC-Unique: msQHBA0UORirEomDJM91DQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 822C485EE8F; Fri, 20 Nov 2020 15:11:33 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2F08860C15; Fri, 20 Nov 2020 15:11:27 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 41/76] cachefiles: Implement a content-present indicator and bitmap From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:11:26 +0000 Message-ID: <160588508638.3465195.13598196924706710300.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Implement a content indicator that indicates the presence or absence of content and a bitmap that indicates which blocks of granular content are present in a granular file. This is added to the xattr that stores the netfs coherency data, along with the file size and the file zero point (the point after which it can be assumed that the server doesn't have any data). In the content bitmap, if present, each bit indicates which 256KiB granules of a cache file are present. This is stored in a separate xattr, which is loaded when the first I/O handle is created on that cache object and saved when the object is discarded from memory. Non-index objects in the cache can be monolithic or granular. The content map isn't used for monolithic objects (FSCACHE_COOKIE_ADV_SINGLE_CHUNK) as they are expected to be all-or-nothing, so the content indicator alone suffices. Examples of this would be AFS directory or symlink content. Signed-off-by: David Howells --- fs/cachefiles/Makefile | 1 fs/cachefiles/bind.c | 1 fs/cachefiles/content-map.c | 246 +++++++++++++++++++++++++++++++++++++ fs/cachefiles/interface.c | 5 + fs/cachefiles/internal.h | 32 +++++ fs/cachefiles/io.c | 4 + fs/cachefiles/xattr.c | 24 +++- include/trace/events/cachefiles.h | 4 - 8 files changed, 309 insertions(+), 8 deletions(-) create mode 100644 fs/cachefiles/content-map.c diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile index d894d317d6e7..84615aca866a 100644 --- a/fs/cachefiles/Makefile +++ b/fs/cachefiles/Makefile @@ -5,6 +5,7 @@ cachefiles-y := \ bind.o \ + content-map.o \ daemon.o \ interface.o \ io.o \ diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c index c89a422fd1d1..88c7cb4fb0f7 100644 --- a/fs/cachefiles/bind.c +++ b/fs/cachefiles/bind.c @@ -102,6 +102,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) goto error_root_object; atomic_set(&fsdef->usage, 1); + rwlock_init(&fsdef->content_map_lock); fsdef->type = FSCACHE_COOKIE_TYPE_INDEX; /* look up the directory at the root of the cache */ diff --git a/fs/cachefiles/content-map.c b/fs/cachefiles/content-map.c new file mode 100644 index 000000000000..68fcab313361 --- /dev/null +++ b/fs/cachefiles/content-map.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Datafile content management + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include +#include +#include +#include "internal.h" + +static const char cachefiles_xattr_content_map[] = + XATTR_USER_PREFIX "CacheFiles.content"; + +/* + * Determine the map size for a granulated object. + * + * There's one bit per granule. We size it in terms of 8-byte chunks, where a + * 64-bit span * 256KiB bytes granules covers 16MiB of file space. At that, + * 512B will cover 1GiB. + */ +static size_t cachefiles_map_size(loff_t i_size) +{ + loff_t size; + size_t granules, bits, bytes, map_size; + + if (i_size <= CACHEFILES_GRAN_SIZE * 64) + return 8; + + size = min_t(loff_t, i_size + CACHEFILES_GRAN_SIZE - 1, CACHEFILES_SIZE_LIMIT); + granules = size / CACHEFILES_GRAN_SIZE; + bits = granules + (64 - 1); + bits &= ~(64 - 1); + bytes = bits / 8; + map_size = roundup_pow_of_two(bytes); + _leave(" = %zx [i=%llx g=%zu b=%zu]", map_size, i_size, granules, bits); + return map_size; +} + +/* + * Mark the content map to indicate stored granule. + */ +void cachefiles_mark_content_map(struct cachefiles_object *object, + loff_t start, loff_t len) +{ + _enter("%llx", start); + + read_lock_bh(&object->content_map_lock); + + if (object->fscache.cookie->advice & FSCACHE_ADV_SINGLE_CHUNK) { + if (start == 0) { + object->content_info = CACHEFILES_CONTENT_SINGLE; + set_bit(FSCACHE_OBJECT_NEEDS_UPDATE, &object->fscache.flags); + } + } else { + pgoff_t granule; + loff_t end = start + len; + + start = round_down(start, CACHEFILES_GRAN_SIZE); + do { + granule = start / CACHEFILES_GRAN_SIZE; + if (granule / 8 >= object->content_map_size) + break; + + set_bit_le(granule, object->content_map); + object->content_map_changed = true; + start += CACHEFILES_GRAN_SIZE; + + } while (start < end); + + if (object->content_info != CACHEFILES_CONTENT_MAP) { + object->content_info = CACHEFILES_CONTENT_MAP; + set_bit(FSCACHE_OBJECT_NEEDS_UPDATE, &object->fscache.flags); + } + } + + read_unlock_bh(&object->content_map_lock); +} + +/* + * Expand the content map to a larger file size. + */ +void cachefiles_expand_content_map(struct cachefiles_object *object, loff_t i_size) +{ + size_t size; + u8 *map, *zap; + + size = cachefiles_map_size(i_size); + + _enter("%llx,%zx,%x", i_size, size, object->content_map_size); + + if (size <= object->content_map_size) + return; + + map = kzalloc(size, GFP_KERNEL); + if (!map) + return; + + write_lock_bh(&object->content_map_lock); + if (size > object->content_map_size) { + zap = object->content_map; + memcpy(map, zap, object->content_map_size); + object->content_map = map; + object->content_map_size = size; + } else { + zap = map; + } + write_unlock_bh(&object->content_map_lock); + + kfree(zap); +} + +/* + * Adjust the content map when we shorten a backing object. + * + * We need to unmark any granules that are going to be discarded. + */ +void cachefiles_shorten_content_map(struct cachefiles_object *object, + loff_t new_size) +{ + struct fscache_cookie *cookie = object->fscache.cookie; + ssize_t granules_needed, bits_needed, bytes_needed; + + if (object->fscache.cookie->advice & FSCACHE_ADV_SINGLE_CHUNK) + return; + + write_lock_bh(&object->content_map_lock); + + if (object->content_info == CACHEFILES_CONTENT_MAP) { + if (cookie->zero_point > new_size) + cookie->zero_point = new_size; + + granules_needed = new_size; + granules_needed += CACHEFILES_GRAN_SIZE - 1; + granules_needed /= CACHEFILES_GRAN_SIZE; + bits_needed = round_up(granules_needed, 8); + bytes_needed = bits_needed / 8; + + if (bytes_needed < object->content_map_size) + memset(object->content_map + bytes_needed, 0, + object->content_map_size - bytes_needed); + + if (bits_needed > granules_needed) { + size_t byte = (granules_needed - 1) / 8; + unsigned int shift = granules_needed % 8; + unsigned int mask = (1 << shift) - 1; + object->content_map[byte] &= mask; + } + } + + write_unlock_bh(&object->content_map_lock); +} + +/* + * Load the content map. + */ +bool cachefiles_load_content_map(struct cachefiles_object *object) +{ + struct cachefiles_cache *cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + const struct cred *saved_cred; + ssize_t got; + size_t size; + u8 *map = NULL; + + _enter("c=%08x,%llx", + object->fscache.cookie->debug_id, + object->fscache.cookie->object_size); + + object->content_info = CACHEFILES_CONTENT_NO_DATA; + if (object->fscache.cookie->advice & FSCACHE_ADV_SINGLE_CHUNK) { + /* Single-chunk object. The presence or absence of the content + * map xattr is sufficient indication. + */ + size = 0; + } else { + /* Granulated object. There's one bit per granule. We size it + * in terms of 8-byte chunks, where a 64-bit span * 256KiB + * bytes granules covers 16MiB of file space. At that, 512B + * will cover 1GiB. + */ + size = cachefiles_map_size(object->fscache.cookie->object_size); + map = kzalloc(size, GFP_KERNEL); + if (!map) + return false; + } + + cachefiles_begin_secure(cache, &saved_cred); + got = vfs_getxattr(object->dentry, cachefiles_xattr_content_map, + map, size); + cachefiles_end_secure(cache, saved_cred); + if (got < 0 && got != -ENODATA) { + kfree(map); + _leave(" = f [%zd]", got); + return false; + } + + if (size == 0) { + if (got != -ENODATA) + object->content_info = CACHEFILES_CONTENT_SINGLE; + _leave(" = t [%zd]", got); + } else { + object->content_map = map; + object->content_map_size = size; + object->content_info = CACHEFILES_CONTENT_MAP; + _leave(" = t [%zd/%zu %*phN]", got, size, (int)size, map); + } + + return true; +} + +/* + * Save the content map. + */ +void cachefiles_save_content_map(struct cachefiles_object *object) +{ + ssize_t ret; + size_t size; + u8 *map; + + _enter("c=%08x", object->fscache.cookie->debug_id); + + if (object->content_info != CACHEFILES_CONTENT_MAP) + return; + + size = object->content_map_size; + map = object->content_map; + + /* Don't save trailing zeros, but do save at least one byte */ + for (; size > 0; size--) + if (map[size - 1]) + break; + + ret = vfs_setxattr(object->dentry, cachefiles_xattr_content_map, + map, size, 0); + if (ret < 0) { + cachefiles_io_error_obj(object, "Unable to set xattr e=%zd s=%zu", + ret, size); + return; + } + + _leave(" = %zd", ret); +} diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 7e8940a7fb55..1d06cf72eeb0 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -37,6 +37,7 @@ struct fscache_object *cachefiles_alloc_object(struct fscache_cookie *cookie, return NULL; } + rwlock_init(&object->content_map_lock); fscache_object_init(&object->fscache, cookie, &cache->cache); object->fscache.parent = parent; object->fscache.stage = FSCACHE_OBJECT_STAGE_LOOKING_UP; @@ -198,6 +199,8 @@ static void cachefiles_update_object(struct fscache_object *_object) static void cachefiles_commit_object(struct cachefiles_object *object, struct cachefiles_cache *cache) { + if (object->content_map_changed) + cachefiles_save_content_map(object); } /* @@ -298,6 +301,8 @@ static void cachefiles_put_object(struct fscache_object *_object, ASSERTCMP(object->dentry, ==, NULL); ASSERTCMP(object->fscache.n_children, ==, 0); + kfree(object->content_map); + cache = object->fscache.cache; fscache_object_destroy(&object->fscache); kmem_cache_free(cachefiles_object_jar, object); diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index 2dab3ee386ad..e065550a4bc0 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -19,6 +19,11 @@ #include #include +/* Cachefile granularity */ +#define CACHEFILES_GRAN_SIZE (256 * 1024) +#define CACHEFILES_DIO_BLOCK_SIZE 4096 +#define CACHEFILES_SIZE_LIMIT (512 * 8 * CACHEFILES_GRAN_SIZE) + struct cachefiles_cache; struct cachefiles_object; @@ -29,6 +34,16 @@ extern unsigned cachefiles_debug; #define cachefiles_gfp (__GFP_RECLAIM | __GFP_NORETRY | __GFP_NOMEMALLOC) +enum cachefiles_content { + /* These values are saved on disk */ + CACHEFILES_CONTENT_NO_DATA = 0, /* No content stored */ + CACHEFILES_CONTENT_SINGLE = 1, /* Content is monolithic, all is present */ + CACHEFILES_CONTENT_ALL = 2, /* Content is all present, no map */ + CACHEFILES_CONTENT_MAP = 3, /* Content is piecemeal, map in use */ + CACHEFILES_CONTENT_DIRTY = 4, /* Content is dirty (only seen on disk) */ + nr__cachefiles_content +}; + /* * node records */ @@ -41,6 +56,13 @@ struct cachefiles_object { atomic_t usage; /* object usage count */ uint8_t type; /* object type */ bool new; /* T if object new */ + + /* Map of the content blocks in the object */ + enum cachefiles_content content_info:8; /* Info about content presence */ + bool content_map_changed; + u8 *content_map; /* Content present bitmap */ + unsigned int content_map_size; /* Size of buffer */ + rwlock_t content_map_lock; }; extern struct kmem_cache *cachefiles_object_jar; @@ -100,6 +122,16 @@ static inline void cachefiles_state_changed(struct cachefiles_cache *cache) extern int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args); extern void cachefiles_daemon_unbind(struct cachefiles_cache *cache); +/* + * content-map.c + */ +extern void cachefiles_mark_content_map(struct cachefiles_object *object, + loff_t start, loff_t len); +extern void cachefiles_expand_content_map(struct cachefiles_object *object, loff_t size); +extern void cachefiles_shorten_content_map(struct cachefiles_object *object, loff_t new_size); +extern bool cachefiles_load_content_map(struct cachefiles_object *object); +extern void cachefiles_save_content_map(struct cachefiles_object *object); + /* * daemon.c */ diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 2d406d681597..bf1930699636 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -59,6 +59,10 @@ bool cachefiles_open_object(struct cachefiles_object *object) path.mnt = cache->mnt; path.dentry = object->dentry; + if (object->content_info == CACHEFILES_CONTENT_MAP && + !cachefiles_load_content_map(object)) + goto error; + file = open_with_fake_path(&path, O_RDWR | O_LARGEFILE | O_DIRECT, d_backing_inode(object->dentry), diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index 19db19b7d7db..cbd43855dc0d 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -16,8 +16,11 @@ #include "internal.h" struct cachefiles_xattr { - uint8_t type; - uint8_t data[]; + __be64 object_size; /* Actual size of the object */ + __be64 zero_point; /* Size after which server has no data not written by us */ + __u8 type; /* Type of object */ + __u8 content; /* Content presence (enum cachefiles_content) */ + __u8 data[]; /* netfs coherency data */ } __packed; static const char cachefiles_xattr_cache[] = @@ -118,7 +121,10 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, if (!buf) return -ENOMEM; - buf->type = object->fscache.cookie->type; + buf->object_size = cpu_to_be64(object->fscache.cookie->object_size); + buf->zero_point = cpu_to_be64(object->fscache.cookie->zero_point); + buf->type = object->fscache.cookie->type; + buf->content = object->content_info; if (len > 0) memcpy(buf->data, fscache_get_aux(object->fscache.cookie), len); @@ -127,7 +133,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, xattr_flags); if (ret < 0) { trace_cachefiles_coherency(object, d_inode(dentry)->i_ino, - 0, + buf->content, cachefiles_coherency_set_fail); if (ret != -ENOMEM) cachefiles_io_error_obj( @@ -135,7 +141,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, "Failed to set xattr with error %d", ret); } else { trace_cachefiles_coherency(object, d_inode(dentry)->i_ino, - 0, + buf->content, cachefiles_coherency_set_ok); } @@ -174,15 +180,21 @@ int cachefiles_check_auxdata(struct cachefiles_object *object) why = cachefiles_coherency_check_xattr; } else if (buf->type != object->fscache.cookie->type) { why = cachefiles_coherency_check_type; + } else if (buf->content >= nr__cachefiles_content) { + why = cachefiles_coherency_check_content; } else if (memcmp(buf->data, p, len) != 0) { why = cachefiles_coherency_check_aux; + } else if (be64_to_cpu(buf->object_size) != object->fscache.cookie->object_size) { + why = cachefiles_coherency_check_objsize; } else { + object->fscache.cookie->zero_point = be64_to_cpu(buf->zero_point); + object->content_info = buf->content; why = cachefiles_coherency_check_ok; ret = 0; } trace_cachefiles_coherency(object, d_inode(dentry)->i_ino, - 0, why); + buf->content, why); kfree(buf); return ret; } diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h index bf588c3f4a07..e7af1d683009 100644 --- a/include/trace/events/cachefiles.h +++ b/include/trace/events/cachefiles.h @@ -324,7 +324,7 @@ TRACE_EVENT(cachefiles_mark_buried, TRACE_EVENT(cachefiles_coherency, TP_PROTO(struct cachefiles_object *obj, ino_t ino, - int content, + enum cachefiles_content content, enum cachefiles_coherency_trace why), TP_ARGS(obj, ino, content, why), @@ -333,7 +333,7 @@ TRACE_EVENT(cachefiles_coherency, TP_STRUCT__entry( __field(unsigned int, obj ) __field(enum cachefiles_coherency_trace, why ) - __field(int, content ) + __field(enum cachefiles_content, content ) __field(u64, ino ) ), From patchwork Fri Nov 20 15:11:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329211 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6C508C83013 for ; Fri, 20 Nov 2020 15:12:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 41DCF22252 for ; Fri, 20 Nov 2020 15:12:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="OMHlM57B" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728928AbgKTPMD (ORCPT ); Fri, 20 Nov 2020 10:12:03 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:41669 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728858AbgKTPMC (ORCPT ); Fri, 20 Nov 2020 10:12:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885121; 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=a2dc9AgCjNKnB30Uuf5YoOyf+HNLd6rDUqP5SMruEOU=; b=OMHlM57BFroEyD08TAlG8cSU9fmkW7N43/RxEqjgQAg20TygZ3Qt9Yqb7/nDG+o5/IYnhb dbaZ0sayD06ChEvLvy9Ncd6ms1jpvdZF7OLZ1licw5z2/AbKD5Xyjykg2TSAXlviHZp9Ri dWgTKIb9OIBA+SL2mHrJmGeMR3y1Y6A= 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-166-jqWo9ix5PGmBrMMFMdn0HQ-1; Fri, 20 Nov 2020 10:11:59 -0500 X-MC-Unique: jqWo9ix5PGmBrMMFMdn0HQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id AEA7E1DDE5; Fri, 20 Nov 2020 15:11:57 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3BD8F10021B3; Fri, 20 Nov 2020 15:11:51 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 43/76] cachefiles: Round the cachefile size up to DIO block size From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:11:50 +0000 Message-ID: <160588511040.3465195.601522049910164888.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Round the size of a cachefile up to DIO block size so that we can always read back the last partial page of a file using direct I/O. Signed-off-by: David Howells --- fs/cachefiles/interface.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index a20917cb4667..0e3d5b5ffc55 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -184,6 +184,17 @@ static void cachefiles_update_object(struct fscache_object *_object) cachefiles_remove_object_xattr(cache, object->dentry); goto out; } + + object_size = round_up(object_size, CACHEFILES_DIO_BLOCK_SIZE); + _debug("trunc %llx -> %llx", i_size_read(d_inode(object->dentry)), object_size); + if (i_size_read(d_inode(object->dentry)) < object_size) { + ret = vfs_truncate(&path, object_size); + if (ret < 0) { + cachefiles_io_error_obj(object, "Trunc-to-dio-size failed"); + cachefiles_remove_object_xattr(cache, object->dentry); + goto out; + } + } } cachefiles_set_object_xattr(object, XATTR_REPLACE); @@ -354,6 +365,7 @@ static int cachefiles_attr_changed(struct cachefiles_object *object) int ret; ni_size = object->fscache.cookie->object_size; + ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); _enter("{OBJ%x},[%llu]", object->fscache.debug_id, (unsigned long long) ni_size); @@ -422,6 +434,7 @@ static bool cachefiles_invalidate_object(struct fscache_object *_object) struct cachefiles_cache, cache); ni_size = object->fscache.cookie->object_size; + ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); _enter("{OBJ%x},[%llu]", object->fscache.debug_id, (unsigned long long)ni_size); From patchwork Fri Nov 20 15:12:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329210 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 107B5C64E69 for ; Fri, 20 Nov 2020 15:13:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BD75420829 for ; Fri, 20 Nov 2020 15:12:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="VvtS3u26" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729103AbgKTPMc (ORCPT ); Fri, 20 Nov 2020 10:12:32 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:49446 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729024AbgKTPMb (ORCPT ); Fri, 20 Nov 2020 10:12:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885149; 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=UbA8dPdq7nnWxfhxybiQzhAe4RhNPqZGUpRHw0CU3+Q=; b=VvtS3u26AhkAZfQw7OFM91REXjnjd8b8Lk1GoOvskK8soPhP9DRyIxkunfTaEIqHvxOJo8 WXtw/wbsNzIkjX3t5GKLXFIWDVgTCvwvxed3CxAO1voEPChhUMOklv+3a1BKxGcMDFv5y1 OHqC7/I+ErPB2D+PhY/PWJnQX+Ychmo= 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-555-LvWAQHbHMCqL8ffYdrxQbQ-1; Fri, 20 Nov 2020 10:12:27 -0500 X-MC-Unique: LvWAQHbHMCqL8ffYdrxQbQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6B9F5107ACFC; Fri, 20 Nov 2020 15:12:25 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1FC119C46; Fri, 20 Nov 2020 15:12:16 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 45/76] cachefiles: Add I/O tracepoints From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:12:16 +0000 Message-ID: <160588513612.3465195.14647633831981307251.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add some cache I/O tracepoints. Signed-off-by: David Howells --- fs/cachefiles/interface.c | 2 + fs/cachefiles/io.c | 2 + include/trace/events/cachefiles.h | 125 +++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index c14e2b4f5b24..654c6efb5a0a 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -179,6 +179,7 @@ static void cachefiles_update_object(struct fscache_object *_object) .dentry = object->dentry }; _debug("trunc %llx -> %llx", i_size, object_size); + trace_cachefiles_trunc(object, inode, i_size, object_size); ret = vfs_truncate(&path, object_size); if (ret < 0) { cachefiles_io_error_obj(object, "Trunc-to-size failed"); @@ -190,6 +191,7 @@ static void cachefiles_update_object(struct fscache_object *_object) i_size = i_size_read(inode); _debug("trunc %llx -> %llx", i_size, object_size); if (i_size < object_size) { + trace_cachefiles_trunc(object, inode, i_size, object_size); ret = vfs_truncate(&path, object_size); if (ret < 0) { cachefiles_io_error_obj(object, "Trunc-to-dio-size failed"); diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 4c66b9183dd6..c9866bd5e010 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -139,6 +139,7 @@ int cachefiles_read(struct fscache_op_resources *opr, cachefiles_grab_object(&object->fscache, fscache_obj_get_ioreq); + trace_cachefiles_read(object, file_inode(file), ki->iocb.ki_pos, len - skipped); old_nofs = memalloc_nofs_save(); ret = call_read_iter(file, &ki->iocb, iter); memalloc_nofs_restore(old_nofs); @@ -267,6 +268,7 @@ int cachefiles_write(struct fscache_op_resources *opr, cachefiles_grab_object(&object->fscache, fscache_obj_get_ioreq); + trace_cachefiles_write(object, inode, ki->iocb.ki_pos, len); old_nofs = memalloc_nofs_save(); ret = call_write_iter(file, &ki->iocb, iter); memalloc_nofs_restore(old_nofs); diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h index e7af1d683009..f9f48c0f5080 100644 --- a/include/trace/events/cachefiles.h +++ b/include/trace/events/cachefiles.h @@ -351,6 +351,131 @@ TRACE_EVENT(cachefiles_coherency, __entry->content) ); +TRACE_EVENT(cachefiles_read, + TP_PROTO(struct cachefiles_object *obj, + struct inode *backer, + loff_t start, + size_t len), + + TP_ARGS(obj, backer, start, len), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(size_t, len ) + __field(loff_t, start ) + ), + + TP_fast_assign( + __entry->obj = obj->fscache.debug_id; + __entry->backer = backer->i_ino; + __entry->start = start; + __entry->len = len; + ), + + TP_printk("o=%08x b=%08x s=%llx l=%zx", + __entry->obj, + __entry->backer, + __entry->start, + __entry->len) + ); + +TRACE_EVENT(cachefiles_write, + TP_PROTO(struct cachefiles_object *obj, + struct inode *backer, + loff_t start, + size_t len), + + TP_ARGS(obj, backer, start, len), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(size_t, len ) + __field(loff_t, start ) + ), + + TP_fast_assign( + __entry->obj = obj->fscache.debug_id; + __entry->backer = backer->i_ino; + __entry->start = start; + __entry->len = len; + ), + + TP_printk("o=%08x b=%08x s=%llx l=%zx", + __entry->obj, + __entry->backer, + __entry->start, + __entry->len) + ); + +TRACE_EVENT(cachefiles_trunc, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer, + loff_t from, loff_t to), + + TP_ARGS(obj, backer, from, to), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(loff_t, from ) + __field(loff_t, to ) + ), + + TP_fast_assign( + __entry->obj = obj->fscache.debug_id; + __entry->backer = backer->i_ino; + __entry->from = from; + __entry->to = to; + ), + + TP_printk("o=%08x b=%08x l=%llx->%llx", + __entry->obj, + __entry->backer, + __entry->from, + __entry->to) + ); + +TRACE_EVENT(cachefiles_tmpfile, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer), + + TP_ARGS(obj, backer), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + ), + + TP_fast_assign( + __entry->obj = obj->fscache.debug_id; + __entry->backer = backer->i_ino; + ), + + TP_printk("o=%08x b=%08x", + __entry->obj, + __entry->backer) + ); + +TRACE_EVENT(cachefiles_link, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer), + + TP_ARGS(obj, backer), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + ), + + TP_fast_assign( + __entry->obj = obj->fscache.debug_id; + __entry->backer = backer->i_ino; + ), + + TP_printk("o=%08x b=%08x", + __entry->obj, + __entry->backer) + ); + #endif /* _TRACE_CACHEFILES_H */ /* This part must be outside protection */ From patchwork Fri Nov 20 15:12:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329209 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8859BC8300B for ; Fri, 20 Nov 2020 15:13:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 354392222F for ; Fri, 20 Nov 2020 15:13:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AQ+M5dVU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729132AbgKTPMz (ORCPT ); Fri, 20 Nov 2020 10:12:55 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:41046 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728627AbgKTPMy (ORCPT ); Fri, 20 Nov 2020 10:12:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885172; 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=hgTdeaebYh2VCRG9KSsvpNQmhVvkLE4rfSTCygGXkCU=; b=AQ+M5dVUKk7nWL01yTGmK+icnA+NuKQbnDRvrr5igv+pydpWi6voBOjUtbAPwA37usMG6/ /GpD6XaBc5u9jqy6KyPsYDBG13jITwBBOsTTnr0XVLbLZyzmu8ich7MdlGh8VbMSchJBef rf1GQqq9kNofFl5Bwo75PIOBaSF0orQ= 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-390-KijSN8yiMWab-J7QtJCBZA-1; Fri, 20 Nov 2020 10:12:48 -0500 X-MC-Unique: KijSN8yiMWab-J7QtJCBZA-1 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 4FF69814411; Fri, 20 Nov 2020 15:12:46 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8299A5C224; Fri, 20 Nov 2020 15:12:43 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 47/76] fscache: Remove more obsolete stats From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:12:42 +0000 Message-ID: <160588516273.3465195.185326813484138143.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Remove some more stats that have become obsolete. Signed-off-by: David Howells --- fs/fscache/internal.h | 20 ++--------------- fs/fscache/obj.c | 6 +++-- fs/fscache/stats.c | 58 +++++++++---------------------------------------- 3 files changed, 16 insertions(+), 68 deletions(-) diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 2c1f4151c092..ae05f636faac 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -175,32 +175,18 @@ extern void fscache_proc_cleanup(void); * stats.c */ #ifdef CONFIG_FSCACHE_STATS -extern atomic_t fscache_n_op_pend; -extern atomic_t fscache_n_op_run; -extern atomic_t fscache_n_op_enqueue; -extern atomic_t fscache_n_op_deferred_release; -extern atomic_t fscache_n_op_initialised; -extern atomic_t fscache_n_op_release; -extern atomic_t fscache_n_op_gc; -extern atomic_t fscache_n_op_cancelled; -extern atomic_t fscache_n_op_rejected; - extern atomic_t fscache_n_acquires; extern atomic_t fscache_n_acquires_null; extern atomic_t fscache_n_acquires_no_cache; extern atomic_t fscache_n_acquires_ok; -extern atomic_t fscache_n_acquires_nobufs; extern atomic_t fscache_n_acquires_oom; extern atomic_t fscache_n_invalidates; -extern atomic_t fscache_n_invalidates_run; extern atomic_t fscache_n_updates; -extern atomic_t fscache_n_updates_null; extern atomic_t fscache_n_updates_run; extern atomic_t fscache_n_relinquishes; -extern atomic_t fscache_n_relinquishes_null; extern atomic_t fscache_n_relinquishes_retire; extern atomic_t fscache_n_cookie_index; @@ -212,15 +198,13 @@ extern atomic_t fscache_n_object_no_alloc; extern atomic_t fscache_n_object_lookups; extern atomic_t fscache_n_object_lookups_negative; extern atomic_t fscache_n_object_lookups_positive; -extern atomic_t fscache_n_object_lookups_timed_out; -extern atomic_t fscache_n_object_created; +extern atomic_t fscache_n_object_creates; extern atomic_t fscache_n_object_avail; extern atomic_t fscache_n_object_dead; extern atomic_t fscache_n_cop_alloc_object; extern atomic_t fscache_n_cop_lookup_object; -extern atomic_t fscache_n_cop_lookup_complete; -extern atomic_t fscache_n_cop_grab_object; +extern atomic_t fscache_n_cop_create_object; extern atomic_t fscache_n_cop_invalidate_object; extern atomic_t fscache_n_cop_update_object; extern atomic_t fscache_n_cop_drop_object; diff --git a/fs/fscache/obj.c b/fs/fscache/obj.c index 7286d3e2eb31..23598bec639e 100644 --- a/fs/fscache/obj.c +++ b/fs/fscache/obj.c @@ -47,10 +47,10 @@ static int fscache_do_lookup_object(struct fscache_object *object, void *data) static int fscache_do_create_object(struct fscache_object *object, void *data) { int ret; - fscache_stat(&fscache_n_object_lookups); - fscache_stat(&fscache_n_cop_lookup_object); + fscache_stat(&fscache_n_object_creates); + fscache_stat(&fscache_n_cop_create_object); ret = object->cache->ops->create_object(object, data); - fscache_stat_d(&fscache_n_cop_lookup_object); + fscache_stat_d(&fscache_n_cop_create_object); return ret; } diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c index 583817f4f113..dffe6925aadb 100644 --- a/fs/fscache/stats.c +++ b/fs/fscache/stats.c @@ -14,32 +14,18 @@ /* * operation counters */ -atomic_t fscache_n_op_pend; -atomic_t fscache_n_op_run; -atomic_t fscache_n_op_enqueue; -atomic_t fscache_n_op_deferred_release; -atomic_t fscache_n_op_initialised; -atomic_t fscache_n_op_release; -atomic_t fscache_n_op_gc; -atomic_t fscache_n_op_cancelled; -atomic_t fscache_n_op_rejected; - atomic_t fscache_n_acquires; atomic_t fscache_n_acquires_null; atomic_t fscache_n_acquires_no_cache; atomic_t fscache_n_acquires_ok; -atomic_t fscache_n_acquires_nobufs; atomic_t fscache_n_acquires_oom; atomic_t fscache_n_invalidates; -atomic_t fscache_n_invalidates_run; atomic_t fscache_n_updates; -atomic_t fscache_n_updates_null; atomic_t fscache_n_updates_run; atomic_t fscache_n_relinquishes; -atomic_t fscache_n_relinquishes_null; atomic_t fscache_n_relinquishes_retire; atomic_t fscache_n_cookie_index; @@ -51,15 +37,13 @@ atomic_t fscache_n_object_no_alloc; atomic_t fscache_n_object_lookups; atomic_t fscache_n_object_lookups_negative; atomic_t fscache_n_object_lookups_positive; -atomic_t fscache_n_object_lookups_timed_out; -atomic_t fscache_n_object_created; +atomic_t fscache_n_object_creates; atomic_t fscache_n_object_avail; atomic_t fscache_n_object_dead; atomic_t fscache_n_cop_alloc_object; atomic_t fscache_n_cop_lookup_object; -atomic_t fscache_n_cop_lookup_complete; -atomic_t fscache_n_cop_grab_object; +atomic_t fscache_n_cop_create_object; atomic_t fscache_n_cop_invalidate_object; atomic_t fscache_n_cop_update_object; atomic_t fscache_n_cop_drop_object; @@ -90,53 +74,33 @@ int fscache_stats_show(struct seq_file *m, void *v) atomic_read(&fscache_n_object_avail), atomic_read(&fscache_n_object_dead)); - seq_printf(m, "Acquire: n=%u nul=%u noc=%u ok=%u nbf=%u" - " oom=%u\n", + seq_printf(m, "Acquire: n=%u nul=%u noc=%u ok=%u oom=%u\n", atomic_read(&fscache_n_acquires), atomic_read(&fscache_n_acquires_null), atomic_read(&fscache_n_acquires_no_cache), atomic_read(&fscache_n_acquires_ok), - atomic_read(&fscache_n_acquires_nobufs), atomic_read(&fscache_n_acquires_oom)); - seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u tmo=%u\n", + seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u\n", atomic_read(&fscache_n_object_lookups), atomic_read(&fscache_n_object_lookups_negative), atomic_read(&fscache_n_object_lookups_positive), - atomic_read(&fscache_n_object_created), - atomic_read(&fscache_n_object_lookups_timed_out)); + atomic_read(&fscache_n_object_creates)); - seq_printf(m, "Invals : n=%u run=%u\n", - atomic_read(&fscache_n_invalidates), - atomic_read(&fscache_n_invalidates_run)); + seq_printf(m, "Invals : n=%u\n", + atomic_read(&fscache_n_invalidates)); - seq_printf(m, "Updates: n=%u nul=%u run=%u\n", + seq_printf(m, "Updates: n=%u run=%u\n", atomic_read(&fscache_n_updates), - atomic_read(&fscache_n_updates_null), atomic_read(&fscache_n_updates_run)); - seq_printf(m, "Relinqs: n=%u nul=%u rtr=%u\n", + seq_printf(m, "Relinqs: n=%u rtr=%u\n", atomic_read(&fscache_n_relinquishes), - atomic_read(&fscache_n_relinquishes_null), atomic_read(&fscache_n_relinquishes_retire)); - seq_printf(m, "Ops : pend=%u run=%u enq=%u can=%u rej=%u\n", - atomic_read(&fscache_n_op_pend), - atomic_read(&fscache_n_op_run), - atomic_read(&fscache_n_op_enqueue), - atomic_read(&fscache_n_op_cancelled), - atomic_read(&fscache_n_op_rejected)); - seq_printf(m, "Ops : ini=%u dfr=%u rel=%u gc=%u\n", - atomic_read(&fscache_n_op_initialised), - atomic_read(&fscache_n_op_deferred_release), - atomic_read(&fscache_n_op_release), - atomic_read(&fscache_n_op_gc)); - - seq_printf(m, "CacheOp: alo=%d luo=%d luc=%d gro=%d\n", + seq_printf(m, "CacheOp: alo=%d luo=%d\n", atomic_read(&fscache_n_cop_alloc_object), - atomic_read(&fscache_n_cop_lookup_object), - atomic_read(&fscache_n_cop_lookup_complete), - atomic_read(&fscache_n_cop_grab_object)); + atomic_read(&fscache_n_cop_lookup_object)); seq_printf(m, "CacheOp: inv=%d upo=%d dro=%d pto=%d atc=%d syn=%d\n", atomic_read(&fscache_n_cop_invalidate_object), atomic_read(&fscache_n_cop_update_object), From patchwork Fri Nov 20 15:13:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329208 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6400C64E7A for ; Fri, 20 Nov 2020 15:13:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 71B7422252 for ; Fri, 20 Nov 2020 15:13:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="fWoOl8aF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729153AbgKTPNU (ORCPT ); Fri, 20 Nov 2020 10:13:20 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:52832 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728977AbgKTPNS (ORCPT ); Fri, 20 Nov 2020 10:13:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885196; 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=Q0q1FPl1J1kXlixzwocU0y2DdbR7NJYQ0Tf3Rxq3Vr4=; b=fWoOl8aFbX5ykR1nGwOIlA0uvg6ifmLl0Ej0ynGEF0ZtZ1VFl2wmWs2Ir8PVZaymZDjBCv XJU+HBONsCHr0PdA48YYU4yFq2/YouHDgqXhxxAQ/rUTJWtU/D+h7NqG3rhwCkBRWVkXlE hKh1xRMtE+nXxIz6vh7ncmt+CZ7A18Y= 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-310-pqUjrqaWN-acbBbkDJIREQ-1; Fri, 20 Nov 2020 10:13:12 -0500 X-MC-Unique: pqUjrqaWN-acbBbkDJIREQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A8B67107AD30; Fri, 20 Nov 2020 15:13:10 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8DF8360853; Fri, 20 Nov 2020 15:13:04 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 49/76] netfs: Stats From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:13:03 +0000 Message-ID: <160588518372.3465195.15930838383494185851.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org --- fs/netfs/Kconfig | 15 ++++++++++++++ fs/netfs/Makefile | 3 +-- fs/netfs/internal.h | 34 +++++++++++++++++++++++++++++++ fs/netfs/read_helper.c | 32 +++++++++++++++++++++++++++-- fs/netfs/stats.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 1 + 6 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 fs/netfs/stats.c diff --git a/fs/netfs/Kconfig b/fs/netfs/Kconfig index 2ebf90e6ca95..578112713703 100644 --- a/fs/netfs/Kconfig +++ b/fs/netfs/Kconfig @@ -6,3 +6,18 @@ config NETFS_SUPPORT This option enables support for network filesystems, including helpers for high-level buffered I/O, abstracting out read segmentation, local caching and transparent huge page support. + +config NETFS_STATS + bool "Gather statistical information on local caching" + depends on NETFS_SUPPORT && PROC_FS + help + This option causes statistical information to be gathered on local + caching and exported through file: + + /proc/fs/fscache/stats + + The gathering of statistics adds a certain amount of overhead to + execution as there are a quite a few stats gathered, and on a + multi-CPU system these may be on cachelines that keep bouncing + between CPUs. On the other hand, the stats are very useful for + debugging purposes. Saying 'Y' here is recommended. diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 4b4eff2ba369..c15bfc966d96 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -netfs-y := \ - read_helper.o +netfs-y := read_helper.o stats.o obj-$(CONFIG_NETFS_SUPPORT) := netfs.o diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index b07f43f9130e..d83317b1eb9d 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -16,8 +16,42 @@ */ extern unsigned int netfs_debug; +/* + * stats.c + */ +#ifdef CONFIG_NETFS_STATS +extern atomic_t netfs_n_rh_readahead; +extern atomic_t netfs_n_rh_readpage; +extern atomic_t netfs_n_rh_rreq; +extern atomic_t netfs_n_rh_sreq; +extern atomic_t netfs_n_rh_download; +extern atomic_t netfs_n_rh_download_done; +extern atomic_t netfs_n_rh_download_failed; +extern atomic_t netfs_n_rh_download_instead; +extern atomic_t netfs_n_rh_read; +extern atomic_t netfs_n_rh_read_done; +extern atomic_t netfs_n_rh_read_failed; +extern atomic_t netfs_n_rh_zero; +extern atomic_t netfs_n_rh_short_read; +extern atomic_t netfs_n_rh_write; +extern atomic_t netfs_n_rh_write_done; +extern atomic_t netfs_n_rh_write_failed; + + +static inline void netfs_stat(atomic_t *stat) +{ + atomic_inc(stat); +} + +static inline void netfs_stat_d(atomic_t *stat) +{ + atomic_dec(stat); +} + +#else #define netfs_stat(x) do {} while(0) #define netfs_stat_d(x) do {} while(0) +#endif /*****************************************************************************/ /* diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c index 21d3578c6979..e1ce197d8d18 100644 --- a/fs/netfs/read_helper.c +++ b/fs/netfs/read_helper.c @@ -55,6 +55,7 @@ static struct netfs_read_request *netfs_alloc_read_request( refcount_set(&rreq->usage, 1); __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); ops->init_rreq(rreq, file); + netfs_stat(&netfs_n_rh_rreq); } return rreq; @@ -86,6 +87,7 @@ static void netfs_put_read_request(struct netfs_read_request *rreq) fscache_end_operation(&rreq->cache_resources); trace_netfs_rreq(rreq, netfs_rreq_trace_free); kfree(rreq); + netfs_stat_d(&netfs_n_rh_rreq); } } @@ -102,6 +104,7 @@ static struct netfs_read_subrequest *netfs_alloc_subrequest( INIT_LIST_HEAD(&subreq->rreq_link); refcount_set(&subreq->usage, 2); subreq->rreq = rreq; + netfs_stat(&netfs_n_rh_sreq); } return subreq; @@ -117,6 +120,7 @@ static void __netfs_put_subrequest(struct netfs_read_subrequest *subreq) trace_netfs_sreq(subreq, netfs_sreq_trace_free); netfs_put_read_request(subreq->rreq); kfree(subreq); + netfs_stat_d(&netfs_n_rh_sreq); } /* @@ -153,6 +157,7 @@ static void netfs_read_from_cache(struct netfs_read_request *rreq, subreq->start + subreq->transferred, subreq->len - subreq->transferred); + netfs_stat(&netfs_n_rh_read); fscache_read(&rreq->cache_resources, subreq->start, &iter, seek_data, netfs_cache_read_terminated, subreq); } @@ -163,6 +168,7 @@ static void netfs_read_from_cache(struct netfs_read_request *rreq, static void netfs_fill_with_zeroes(struct netfs_read_request *rreq, struct netfs_read_subrequest *subreq) { + netfs_stat(&netfs_n_rh_zero); __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); netfs_subreq_terminated(subreq, 0); } @@ -186,6 +192,7 @@ static void netfs_fill_with_zeroes(struct netfs_read_request *rreq, static void netfs_read_from_server(struct netfs_read_request *rreq, struct netfs_read_subrequest *subreq) { + netfs_stat(&netfs_n_rh_download); rreq->netfs_ops->issue_op(subreq); } @@ -240,10 +247,13 @@ static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_error) struct netfs_read_subrequest *subreq = priv; struct netfs_read_request *rreq = subreq->rreq; - if (IS_ERR_VALUE(transferred_or_error)) + if (IS_ERR_VALUE(transferred_or_error)) { subreq->error = transferred_or_error; - else + netfs_stat(&netfs_n_rh_write_failed); + } else { subreq->error = 0; + netfs_stat(&netfs_n_rh_write_done); + } trace_netfs_sreq(subreq, netfs_sreq_trace_write_term); @@ -288,6 +298,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_read_request *rreq) netfs_put_subrequest(next); } + netfs_stat(&netfs_n_rh_write); trace_netfs_sreq(subreq, netfs_sreq_trace_write); iov_iter_xarray(&iter, WRITE, &rreq->mapping->i_pages, @@ -415,6 +426,7 @@ static void netfs_rreq_short_read(struct netfs_read_request *rreq, __clear_bit(NETFS_SREQ_SHORT_READ, &subreq->flags); __set_bit(NETFS_SREQ_SEEK_DATA_READ, &subreq->flags); + netfs_stat(&netfs_n_rh_short_read); trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short); netfs_get_read_subrequest(subreq); @@ -449,6 +461,7 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_read_request *rreq) break; subreq->source = NETFS_DOWNLOAD_FROM_SERVER; subreq->error = 0; + netfs_stat(&netfs_n_rh_download_instead); trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead); netfs_get_read_subrequest(subreq); atomic_inc(&rreq->nr_rd_ops); @@ -563,6 +576,17 @@ void netfs_subreq_terminated(struct netfs_read_subrequest *subreq, subreq->debug_index, subreq->start, subreq->flags, transferred_or_error); + switch (subreq->source) { + case NETFS_READ_FROM_CACHE: + netfs_stat(&netfs_n_rh_read_done); + break; + case NETFS_DOWNLOAD_FROM_SERVER: + netfs_stat(&netfs_n_rh_download_done); + break; + default: + break; + } + if (IS_ERR_VALUE(transferred_or_error)) { subreq->error = transferred_or_error; goto failed; @@ -616,8 +640,10 @@ void netfs_subreq_terminated(struct netfs_read_subrequest *subreq, failed: if (subreq->source == NETFS_READ_FROM_CACHE) { + netfs_stat(&netfs_n_rh_read_failed); set_bit(NETFS_RREQ_INCOMPLETE_IO, &rreq->flags); } else { + netfs_stat(&netfs_n_rh_download_failed); set_bit(NETFS_RREQ_FAILED, &rreq->flags); rreq->error = subreq->error; } @@ -822,6 +848,7 @@ void netfs_readahead(struct readahead_control *ractl, rreq->start = readahead_pos(ractl); rreq->len = readahead_length(ractl); + netfs_stat(&netfs_n_rh_readahead); trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl), netfs_read_trace_readahead); @@ -897,6 +924,7 @@ int netfs_readpage(struct file *file, rreq->start = page->index * PAGE_SIZE; rreq->len = thp_size(page); + netfs_stat(&netfs_n_rh_readpage); trace_netfs_read(rreq, page->index * PAGE_SIZE, thp_size(page), netfs_read_trace_readpage); diff --git a/fs/netfs/stats.c b/fs/netfs/stats.c new file mode 100644 index 000000000000..3a7a3c10e1cd --- /dev/null +++ b/fs/netfs/stats.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Netfs support statistics + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include "internal.h" + +atomic_t netfs_n_rh_readahead; +atomic_t netfs_n_rh_readpage; +atomic_t netfs_n_rh_rreq; +atomic_t netfs_n_rh_sreq; +atomic_t netfs_n_rh_download; +atomic_t netfs_n_rh_download_done; +atomic_t netfs_n_rh_download_failed; +atomic_t netfs_n_rh_download_instead; +atomic_t netfs_n_rh_read; +atomic_t netfs_n_rh_read_done; +atomic_t netfs_n_rh_read_failed; +atomic_t netfs_n_rh_zero; +atomic_t netfs_n_rh_short_read; +atomic_t netfs_n_rh_write; +atomic_t netfs_n_rh_write_done; +atomic_t netfs_n_rh_write_failed; + +void netfs_stats_show(struct seq_file *m) +{ + seq_printf(m, "RdHelp : RA=%u RP=%u rr=%u sr=%u\n", + atomic_read(&netfs_n_rh_readahead), + atomic_read(&netfs_n_rh_readpage), + atomic_read(&netfs_n_rh_rreq), + atomic_read(&netfs_n_rh_sreq)); + seq_printf(m, "RdHelp : ZR=%u sh=%u\n", + atomic_read(&netfs_n_rh_zero), + atomic_read(&netfs_n_rh_short_read)); + seq_printf(m, "RdHelp : DL=%u ds=%u df=%u di=%u\n", + atomic_read(&netfs_n_rh_download), + atomic_read(&netfs_n_rh_download_done), + atomic_read(&netfs_n_rh_download_failed), + atomic_read(&netfs_n_rh_download_instead)); + seq_printf(m, "RdHelp : RD=%u rs=%u rf=%u\n", + atomic_read(&netfs_n_rh_read), + atomic_read(&netfs_n_rh_read_done), + atomic_read(&netfs_n_rh_read_failed)); + seq_printf(m, "RdHelp : WR=%u ws=%u wf=%u\n", + atomic_read(&netfs_n_rh_write), + atomic_read(&netfs_n_rh_write_done), + atomic_read(&netfs_n_rh_write_failed)); +} +EXPORT_SYMBOL(netfs_stats_show); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index c4276eb9914d..d9cd9a1d1f6d 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -98,5 +98,6 @@ extern int netfs_readpage(struct file *, void *); extern void netfs_subreq_terminated(struct netfs_read_subrequest *, ssize_t); +extern void netfs_stats_show(struct seq_file *); #endif /* _LINUX_NETFS_H */ From patchwork Fri Nov 20 15:13:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329207 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1890BC63798 for ; Fri, 20 Nov 2020 15:13:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BDB842222F for ; Fri, 20 Nov 2020 15:13:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ZWKx6n7e" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729189AbgKTPNq (ORCPT ); Fri, 20 Nov 2020 10:13:46 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:47807 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729190AbgKTPNo (ORCPT ); Fri, 20 Nov 2020 10:13:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885221; 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=QLsfHIAZ2NpC9Yp7pCQAyh0mYl0RZEvHJ8U8JSNhZ1I=; b=ZWKx6n7etGN5JNwRNObuofExai8J6Lr0DFn2RfuaKo45Mrh3xlJDEhro0OzcbawBKqL2mp TkbiI2Vc35/qTsw2IqQ3Qg1TyUaFlu97awLLiqGCxxrY3IQS2oR5b4yGW4N/q7AcyixbBw TPHfUzzGHr/Oi+BdbwrodQVnEm1blAI= 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-126-uGgk-OiBOkSNp3VH58vjXQ-1; Fri, 20 Nov 2020 10:13:40 -0500 X-MC-Unique: uGgk-OiBOkSNp3VH58vjXQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2336A801B1E; Fri, 20 Nov 2020 15:13:38 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id DA79860853; Fri, 20 Nov 2020 15:13:28 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 51/76] fscache, cachefiles: Rewrite invalidation From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:13:27 +0000 Message-ID: <160588520789.3465195.15242944688760722625.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Rewrite the cache object invalidation code in fscache and cachefiles. The following changes are made to fscache: (1) Invalidation is now ignored or allowed to proceed depending on the 'stage' a non-index cookie is in with respect to the backing object. (2) If invalidation is proceeds, it pins the object and holds an operation count for the duration. (3) The fscache_object struct is given an invalidation counter that is incremented any time fscache_invalidate() is called, even if the cookie is at a stage in which it cannot be applied. The counter, however, can be noted and applied retroactively later. (4) The invalidation counter is noted in the operation struct when a cache operation is begun and can be checked on operation completion to find out if any consequent metadata changes should be dropped. (5) New operations aren't allowed to proceed if the object is being invalidated. and to cachefiles: (1) If an open object is invalidated, the open backing file is replaced with a tmpfile (as if opened O_TMPFILE). This is held unlinked until the object released from memory, at which point the file is simply abandoned if it was retired or the old file is unlinked and the new one linked into its place. Note: This would be easier if linkat() could be given a flag to indicate the destination should be overwritten or if RENAME_EXCHANGE could be applied to tmpfiles, effectively unlinking the destination. (2) Upon invalidation, the content map is replaced with a blank one. Signed-off-by: David Howells --- fs/afs/inode.c | 8 ++ fs/cachefiles/content-map.c | 38 ++++++++++- fs/cachefiles/interface.c | 133 +++++++++++++++++++++++++++++++++------- fs/cachefiles/internal.h | 12 +++- fs/cachefiles/io.c | 17 ++++- fs/cachefiles/namei.c | 69 +++++++++++++++++++-- fs/cachefiles/xattr.c | 6 +- fs/fscache/cookie.c | 22 +++++-- fs/fscache/io.c | 1 fs/fscache/obj.c | 25 ++------ include/linux/fscache-cache.h | 5 +- include/linux/fscache.h | 20 +++++- include/trace/events/fscache.h | 19 ++++++ 13 files changed, 299 insertions(+), 76 deletions(-) diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 0ba2815f8152..3930f051f39a 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -569,7 +569,13 @@ static void afs_zap_data(struct afs_vnode *vnode) _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); #ifdef CONFIG_AFS_FSCACHE - fscache_invalidate(vnode->cache, i_size_read(&vnode->vfs_inode)); + { + struct afs_vnode_cache_aux aux = { + .data_version = vnode->status.data_version, + }; + fscache_invalidate(afs_vnode_cache(vnode), &aux, + i_size_read(&vnode->vfs_inode), 0); + } #endif /* nuke all the non-dirty pages that aren't locked, mapped or being diff --git a/fs/cachefiles/content-map.c b/fs/cachefiles/content-map.c index 4c8dc11d2d4c..da0a81e3f751 100644 --- a/fs/cachefiles/content-map.c +++ b/fs/cachefiles/content-map.c @@ -204,21 +204,47 @@ enum netfs_read_source cachefiles_prepare_read(struct netfs_read_subrequest *sub return NETFS_READ_FROM_CACHE; } +/* + * Allocate a new content map. + */ +u8 *cachefiles_new_content_map(struct cachefiles_object *object, + unsigned int *_size) +{ + size_t size; + u8 *map = NULL; + + _enter(""); + + if (!(object->fscache.cookie->advice & FSCACHE_ADV_SINGLE_CHUNK)) { + /* Single-chunk object. The presence or absence of the content + * map xattr is sufficient indication. + */ + *_size = 0; + return NULL; + } + + /* Granular object. */ + size = cachefiles_map_size(object->fscache.cookie->object_size); + map = kzalloc(size, GFP_KERNEL); + if (!map) + return ERR_PTR(-ENOMEM); + *_size = size; + return map; +} + /* * Mark the content map to indicate stored granule. */ void cachefiles_mark_content_map(struct cachefiles_object *object, - loff_t start, loff_t len) + loff_t start, loff_t len, + unsigned int inval_counter) { _enter("%llx", start); read_lock_bh(&object->content_map_lock); - if (object->fscache.cookie->advice & FSCACHE_ADV_SINGLE_CHUNK) { - if (start == 0) { - object->content_info = CACHEFILES_CONTENT_SINGLE; - set_bit(FSCACHE_OBJECT_NEEDS_UPDATE, &object->fscache.flags); - } + if (object->fscache.inval_counter != inval_counter) { + _debug("inval mark"); } else { pgoff_t granule; loff_t end = start + len; diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index c083d9833b87..4da10640611c 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -201,7 +201,7 @@ static void cachefiles_update_object(struct fscache_object *_object) } } - cachefiles_set_object_xattr(object, XATTR_REPLACE); + cachefiles_set_object_xattr(object); out: cachefiles_end_secure(cache, saved_cred); @@ -211,11 +211,15 @@ static void cachefiles_update_object(struct fscache_object *_object) /* * Commit changes to the object as we drop it. */ -static void cachefiles_commit_object(struct cachefiles_object *object, +static bool cachefiles_commit_object(struct cachefiles_object *object, struct cachefiles_cache *cache) { if (object->content_map_changed) cachefiles_save_content_map(object); + + if (test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) + return cachefiles_commit_tmpfile(cache, object); + return true; } /* @@ -422,48 +426,133 @@ static int cachefiles_attr_changed(struct cachefiles_object *object) } /* - * Invalidate an object + * Create a temporary file and leave it unattached and un-xattr'd until the + * time comes to discard the object from memory. */ -static bool cachefiles_invalidate_object(struct fscache_object *_object) +static struct file *cachefiles_create_tmpfile(struct cachefiles_object *object) { - struct cachefiles_object *object; struct cachefiles_cache *cache; const struct cred *saved_cred; + struct file *file; struct path path; uint64_t ni_size; - int ret; + long ret; - object = container_of(_object, struct cachefiles_object, fscache); cache = container_of(object->fscache.cache, struct cachefiles_cache, cache); ni_size = object->fscache.cookie->object_size; ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); + cachefiles_begin_secure(cache, &saved_cred); + + path.mnt = cache->mnt; + path.dentry = vfs_tmpfile(cache->graveyard, S_IFREG, O_RDWR); + if (IS_ERR(path.dentry)) { + if (PTR_ERR(path.dentry) == -EIO) + cachefiles_io_error_obj(object, "Failed to create tmpfile"); + file = ERR_CAST(path.dentry); + goto out; + } + + trace_cachefiles_tmpfile(object, d_inode(path.dentry)); + + if (ni_size > 0) { + trace_cachefiles_trunc(object, d_inode(path.dentry), 0, ni_size); + ret = vfs_truncate(&path, ni_size); + if (ret < 0) { + file = ERR_PTR(ret); + goto out_dput; + } + } + + file = open_with_fake_path(&path, + O_RDWR | O_LARGEFILE | O_DIRECT, + d_backing_inode(path.dentry), + cache->cache_cred); +out_dput: + dput(path.dentry); +out: + cachefiles_end_secure(cache, saved_cred); + return file; +} + +/* + * Invalidate an object + */ +static bool cachefiles_invalidate_object(struct fscache_object *_object, + unsigned int flags) +{ + struct cachefiles_object *object; + struct file *file, *old_file; + struct dentry *old_dentry; + u8 *map, *old_map; + unsigned int map_size; + + object = container_of(_object, struct cachefiles_object, fscache); + _enter("{OBJ%x},[%llu]", - object->fscache.debug_id, (unsigned long long)ni_size); + object->fscache.debug_id, _object->cookie->object_size); + + if ((flags & FSCACHE_INVAL_LIGHT) && + test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) { + _leave(" = t [light]"); + return true; + } if (object->dentry) { ASSERT(d_is_reg(object->dentry)); - path.dentry = object->dentry; - path.mnt = cache->mnt; - - cachefiles_begin_secure(cache, &saved_cred); - ret = vfs_truncate(&path, 0); - if (ret == 0) - ret = vfs_truncate(&path, ni_size); - cachefiles_end_secure(cache, saved_cred); - - if (ret != 0) { - if (ret == -EIO) - cachefiles_io_error_obj(object, - "Invalidate failed"); - return false; + file = cachefiles_create_tmpfile(object); + if (IS_ERR(file)) + goto failed; + + map = cachefiles_new_content_map(object, &map_size); + if (IS_ERR(map)) + goto failed_fput; + + /* Substitute the VFS target */ + _debug("sub"); + dget(file->f_path.dentry); /* Do outside of content_map_lock */ + spin_lock(&object->fscache.lock); + write_lock_bh(&object->content_map_lock); + + if (!object->old) { + /* Save the dentry carrying the path information */ + object->old = object->dentry; + old_dentry = NULL; + } else { + old_dentry = object->dentry; } + + old_file = object->backing_file; + old_map = object->content_map; + object->backing_file = file; + object->dentry = file->f_path.dentry; + object->content_info = CACHEFILES_CONTENT_NO_DATA; + object->content_map = map; + object->content_map_size = map_size; + object->content_map_changed = true; + set_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags); + set_bit(FSCACHE_OBJECT_NEEDS_UPDATE, &object->fscache.flags); + + write_unlock_bh(&object->content_map_lock); + spin_unlock(&object->fscache.lock); + _debug("subbed"); + + kfree(old_map); + fput(old_file); + dput(old_dentry); } + _leave(" = t [tmpfile]"); return true; + +failed_fput: + fput(file); +failed: + _leave(" = f"); + return false; } static unsigned int cachefiles_get_object_usage(const struct fscache_object *_object) diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index b58177f65135..af68564598d5 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -54,6 +54,8 @@ struct cachefiles_object { struct file *backing_file; /* File open on backing storage */ loff_t i_size; /* object size */ atomic_t usage; /* object usage count */ + unsigned long flags; +#define CACHEFILES_OBJECT_USING_TMPFILE 0 /* Object has a tmpfile that need linking */ uint8_t type; /* object type */ bool new; /* T if object new */ @@ -129,8 +131,10 @@ extern void cachefiles_expand_readahead(struct fscache_op_resources *opr, loff_t *_start, size_t *_len, loff_t i_size); extern enum netfs_read_source cachefiles_prepare_read(struct netfs_read_subrequest *subreq, loff_t i_size); +extern u8 *cachefiles_new_content_map(struct cachefiles_object *object, + unsigned int *_size); extern void cachefiles_mark_content_map(struct cachefiles_object *object, - loff_t start, loff_t len); + loff_t start, loff_t len, unsigned int inval_counter); extern void cachefiles_expand_content_map(struct cachefiles_object *object, loff_t size); extern void cachefiles_shorten_content_map(struct cachefiles_object *object, loff_t new_size); extern bool cachefiles_load_content_map(struct cachefiles_object *object); @@ -195,6 +199,9 @@ extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, extern int cachefiles_check_in_use(struct cachefiles_cache *cache, struct dentry *dir, char *filename); +extern bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache, + struct cachefiles_object *object); + /* * proc.c */ @@ -247,8 +254,7 @@ static inline void cachefiles_end_secure(struct cachefiles_cache *cache, * xattr.c */ extern int cachefiles_check_object_type(struct cachefiles_object *object); -extern int cachefiles_set_object_xattr(struct cachefiles_object *object, - unsigned int xattr_flags); +extern int cachefiles_set_object_xattr(struct cachefiles_object *object); extern int cachefiles_check_auxdata(struct cachefiles_object *object); extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, struct dentry *dentry); diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 1060c1c57008..3ad62a39133e 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -17,6 +17,7 @@ struct cachefiles_kiocb { struct kiocb iocb; refcount_t ki_refcnt; + unsigned int inval_counter; loff_t start; union { size_t skipped; @@ -46,10 +47,15 @@ static void cachefiles_read_complete(struct kiocb *iocb, long ret, long ret2) _enter("%ld,%ld", ret, ret2); if (ki->term_func) { - if (ret < 0) + if (ret < 0) { ki->term_func(ki->term_func_priv, ret); - else - ki->term_func(ki->term_func_priv, ki->skipped + ret); + } else { + if (ki->object->fscache.inval_counter == ki->inval_counter) + ki->skipped += ret; + else + ret = -ESTALE; + ki->term_func(ki->term_func_priv, ret); + } } fscache_uncount_io_operation(ki->object->fscache.cookie); @@ -126,6 +132,7 @@ int cachefiles_read(struct fscache_op_resources *opr, ki->iocb.ki_flags = IOCB_DIRECT; ki->iocb.ki_hint = ki_hint_validate(file_write_hint(file)); ki->iocb.ki_ioprio = get_current_ioprio(); + ki->inval_counter = opr->inval_counter; ki->skipped = skipped; ki->object = object; ki->term_func = term_func; @@ -197,7 +204,8 @@ static void cachefiles_write_complete(struct kiocb *iocb, long ret, long ret2) ki->term_func(ki->term_func_priv, ret); } else { if (ret == ki->len) - cachefiles_mark_content_map(ki->object, ki->start, ki->len); + cachefiles_mark_content_map(ki->object, ki->start, ki->len, + ki->inval_counter); if (ki->term_func) ki->term_func(ki->term_func_priv, ret); } @@ -246,6 +254,7 @@ int cachefiles_write(struct fscache_op_resources *opr, ki->iocb.ki_flags = IOCB_DIRECT | IOCB_WRITE; ki->iocb.ki_hint = ki_hint_validate(file_write_hint(file)); ki->iocb.ki_ioprio = get_current_ioprio(); + ki->inval_counter = opr->inval_counter; ki->start = start_pos; ki->len = len; ki->object = object; diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 9f6c91cff55d..69a7ce9a62c3 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -466,7 +466,7 @@ bool cachefiles_walk_to_object(struct cachefiles_object *parent, if (object->new) { /* attach data to a newly constructed terminal object */ - ret = cachefiles_set_object_xattr(object, XATTR_CREATE); + ret = cachefiles_set_object_xattr(object); if (ret < 0) goto check_error; } else { @@ -485,8 +485,6 @@ bool cachefiles_walk_to_object(struct cachefiles_object *parent, pr_warn("cachefiles: Block size too large\n"); goto check_error; } - - object->old = dget(object->dentry); } else { BUG(); // TODO: open file in data-class subdir } @@ -521,9 +519,7 @@ bool cachefiles_walk_to_object(struct cachefiles_object *parent, cachefiles_unmark_inode_in_use(object, object->dentry); cachefiles_mark_object_inactive(cache, object); dput(object->dentry); - dput(object->old); object->dentry = NULL; - object->old = NULL; goto error_out; lookup_error: @@ -807,3 +803,66 @@ int cachefiles_check_in_use(struct cachefiles_cache *cache, struct dentry *dir, //_leave(" = 0"); return ret; } + +/* + * Attempt to link a temporary file into its rightful place in the cache. + */ +bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache, + struct cachefiles_object *object) +{ + struct dentry *dir, *dentry, *old; + char *name; + unsigned int namelen; + bool success = false; + int ret; + + _enter(",%pd", object->old); + + namelen = object->old->d_name.len; + name = kmemdup_nul(object->old->d_name.name, namelen, GFP_KERNEL); + if (!name) + goto out; + + dir = dget_parent(object->old); + + inode_lock_nested(d_inode(dir), I_MUTEX_PARENT); + ret = cachefiles_bury_object(cache, object, dir, object->old, + FSCACHE_OBJECT_IS_STALE); + dput(object->old); + object->old = NULL; + if (ret < 0 && ret != -ENOENT) { + _debug("bury fail %d", ret); + goto out_name; + } + + inode_lock_nested(d_inode(dir), I_MUTEX_PARENT); + dentry = lookup_one_len(name, dir, namelen); + if (IS_ERR(dentry)) { + _debug("lookup fail %ld", PTR_ERR(dentry)); + goto out_unlock; + } + + ret = vfs_link(object->dentry, d_inode(dir), dentry, NULL); + if (ret < 0) { + _debug("link fail %d", ret); + dput(dentry); + } else { + trace_cachefiles_link(object, d_inode(object->dentry)); + spin_lock(&object->fscache.lock); + old = object->dentry; + object->dentry = dentry; + success = true; + clear_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags); + spin_unlock(&object->fscache.lock); + dput(old); + } + +out_unlock: + inode_unlock(d_inode(dir)); +out_name: + kfree(name); + dput(dir); +out: + _leave(" = %u", success); + return success; +} diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index cbd43855dc0d..991ecda1f140 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -104,8 +104,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object) /* * set the state xattr on a cache file */ -int cachefiles_set_object_xattr(struct cachefiles_object *object, - unsigned int xattr_flags) +int cachefiles_set_object_xattr(struct cachefiles_object *object) { struct cachefiles_xattr *buf; struct dentry *dentry = object->dentry; @@ -129,8 +128,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object, memcpy(buf->data, fscache_get_aux(object->fscache.cookie), len); ret = vfs_setxattr(dentry, cachefiles_xattr_cache, - buf, sizeof(struct cachefiles_xattr) + len, - xattr_flags); + buf, sizeof(struct cachefiles_xattr) + len, 0); if (ret < 0) { trace_cachefiles_coherency(object, d_inode(dentry)->i_ino, buf->content, diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 8d8aba14912a..1b30b28f7cf6 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -531,9 +531,11 @@ void fscache_set_cookie_stage(struct fscache_cookie *cookie, } /* - * Invalidate an object. Callable with spinlocks held. + * Invalidate an object. */ -void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size) +void __fscache_invalidate(struct fscache_cookie *cookie, + const void *aux_data, loff_t new_size, + unsigned int flags) { struct fscache_object *object = NULL; @@ -541,6 +543,10 @@ void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size) fscache_stat(&fscache_n_invalidates); + if (WARN(test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags), + "Trying to invalidate relinquished cookie\n")) + return; + /* Only permit invalidation of data files. Invalidating an index will * require the caller to release all its attachments to the tree rooted * there, and if it's doing that, it may as well just retire the @@ -549,12 +555,16 @@ void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size) ASSERTCMP(cookie->type, !=, FSCACHE_COOKIE_TYPE_INDEX); spin_lock(&cookie->lock); - cookie->object_size = new_size; + fscache_update_aux(cookie, aux_data, &new_size); cookie->zero_point = new_size; - if (!hlist_empty(&cookie->backing_objects)) + trace_fscache_invalidate(cookie, new_size); + + if (!hlist_empty(&cookie->backing_objects)) { object = hlist_entry(cookie->backing_objects.first, struct fscache_object, cookie_link); + object->inval_counter++; + } switch (cookie->stage) { case FSCACHE_COOKIE_STAGE_INITIALISING: /* Assume later checks will catch it */ @@ -566,7 +576,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size) case FSCACHE_COOKIE_STAGE_LOOKING_UP: spin_unlock(&cookie->lock); - _leave(" [look]"); + _leave(" [look %x]", object->inval_counter); return; case FSCACHE_COOKIE_STAGE_NO_DATA_YET: @@ -578,7 +588,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size) spin_unlock(&cookie->lock); wake_up_cookie_stage(cookie); - fscache_dispatch(cookie, object, 0, fscache_invalidate_object); + fscache_dispatch(cookie, object, flags, fscache_invalidate_object); _leave(" [inv]"); return; } diff --git a/fs/fscache/io.c b/fs/fscache/io.c index 90c056e85cea..f13a7729bad3 100644 --- a/fs/fscache/io.c +++ b/fs/fscache/io.c @@ -111,6 +111,7 @@ int __fscache_begin_operation(struct fscache_cookie *cookie, goto not_live; opr->object = object; + opr->inval_counter = object->inval_counter; object->cache->ops->grab_object(object, fscache_obj_get_ioreq); object->cache->ops->begin_operation(opr); diff --git a/fs/fscache/obj.c b/fs/fscache/obj.c index 23598bec639e..60c70c0e474d 100644 --- a/fs/fscache/obj.c +++ b/fs/fscache/obj.c @@ -245,30 +245,15 @@ void fscache_lookup_object(struct fscache_cookie *cookie, } /* - * Invalidate an object + * Invalidate an object. param passes the invalidation flags. */ void fscache_invalidate_object(struct fscache_cookie *cookie, - struct fscache_object *unused, int param) + struct fscache_object *object, int flags) { - struct fscache_object *object = NULL; - bool success = true; + bool success; - spin_lock(&cookie->lock); - - if (!hlist_empty(&cookie->backing_objects)) { - object = hlist_entry(cookie->backing_objects.first, - struct fscache_object, - cookie_link); - object = object->cache->ops->grab_object(object, - fscache_obj_get_inval); - } - - spin_unlock(&cookie->lock); - - if (object) { - success = object->cache->ops->invalidate_object(object); - fscache_do_put_object(object, fscache_obj_put_inval); - } + success = object->cache->ops->invalidate_object(object, flags); + fscache_do_put_object(object, fscache_obj_put_inval); if (success) fscache_set_cookie_stage(cookie, FSCACHE_COOKIE_STAGE_NO_DATA_YET); diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index dacfda1d3c20..a0bb526735b5 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -119,7 +119,8 @@ struct fscache_cache_ops { void (*update_object)(struct fscache_object *object); /* Invalidate an object */ - bool (*invalidate_object)(struct fscache_object *object); + bool (*invalidate_object)(struct fscache_object *object, + unsigned int flags); /* discard the resources pinned by an object and effect retirement if * necessary */ @@ -164,10 +165,12 @@ enum fscache_object_stage { struct fscache_object { int debug_id; /* debugging ID */ int n_children; /* number of child objects */ + unsigned int inval_counter; /* Number of invalidations applied */ enum fscache_object_stage stage; /* Stage of object's lifecycle */ spinlock_t lock; /* state and operations lock */ unsigned long flags; +#define FSCACHE_OBJECT_NEEDS_INVAL 8 /* T if object needs invalidation */ #define FSCACHE_OBJECT_NEEDS_UPDATE 9 /* T if object attrs need writing to disk */ struct list_head cache_link; /* link in cache->object_list */ diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 3c53386e4f6e..1d141d17f63b 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -71,6 +71,9 @@ enum fscache_want_stage { FSCACHE_WANT_READ, }; +#define FSCACHE_INVAL_LIGHT 0x01 /* Don't re-invalidate if temp object */ +#define FSCACHE_INVAL_DIO_WRITE 0x02 /* Invalidate due to DIO write */ + /* * fscache cached network filesystem type * - name, version and ops must be filled in before registration @@ -148,6 +151,7 @@ struct fscache_op_resources { #if __fscache_available const struct fscache_op_ops *ops; struct fscache_object *object; + unsigned int inval_counter; /* object->inval_counter at begin_op */ #endif }; @@ -214,7 +218,7 @@ extern int __fscache_begin_operation(struct fscache_cookie *, struct fscache_op_ enum fscache_want_stage); extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool); extern void __fscache_update_cookie(struct fscache_cookie *, const void *, const loff_t *); -extern void __fscache_invalidate(struct fscache_cookie *, loff_t); +extern void __fscache_invalidate(struct fscache_cookie *, const void *, loff_t, unsigned int); extern void fscache_put_super(struct super_block *, struct fscache_cookie *(*get_cookie)(struct inode *)); @@ -442,22 +446,30 @@ void fscache_unpin_cookie(struct fscache_cookie *cookie) /** * fscache_invalidate - Notify cache that an object needs invalidation * @cookie: The cookie representing the cache object + * @aux_data: The updated auxiliary data for the cookie (may be NULL) * @size: The revised size of the object. + * @flags: Invalidation flags (FSCACHE_INVAL_*) * * Notify the cache that an object is needs to be invalidated and that it * should abort any retrievals or stores it is doing on the cache. The object * is then marked non-caching until such time as the invalidation is complete. * - * This can be called with spinlocks held. + * FSCACHE_INVAL_LIGHT indicates that if the object has been invalidated and + * replaced by a temporary object, the temporary object need not be replaced + * again. This is primarily intended for use with FSCACHE_ADV_SINGLE_CHUNK. + * + * FSCACHE_INVAL_DIO_WRITE indicates that this is due to a direct I/O write and + * may cause caching to be suspended on this cookie. * * See Documentation/filesystems/caching/netfs-api.rst for a complete * description. */ static inline -void fscache_invalidate(struct fscache_cookie *cookie, loff_t size) +void fscache_invalidate(struct fscache_cookie *cookie, + const void *aux_data, loff_t size, unsigned int flags) { if (fscache_cookie_valid(cookie)) - __fscache_invalidate(cookie, size); + __fscache_invalidate(cookie, aux_data, size, flags); } /** diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h index 2edf74c40e83..adb5618ce0c1 100644 --- a/include/trace/events/fscache.h +++ b/include/trace/events/fscache.h @@ -200,6 +200,25 @@ TRACE_EVENT(fscache_relinquish, __entry->flags, __entry->retire) ); +TRACE_EVENT(fscache_invalidate, + TP_PROTO(struct fscache_cookie *cookie, loff_t new_size), + + TP_ARGS(cookie, new_size), + + TP_STRUCT__entry( + __field(unsigned int, cookie ) + __field(loff_t, new_size ) + ), + + TP_fast_assign( + __entry->cookie = cookie->debug_id; + __entry->new_size = new_size; + ), + + TP_printk("c=%08x sz=%llx", + __entry->cookie, __entry->new_size) + ); + #endif /* _TRACE_FSCACHE_H */ /* This part must be outside protection */ From patchwork Fri Nov 20 15:13:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329206 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72350C64E7D for ; Fri, 20 Nov 2020 15:15:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 377B422252 for ; Fri, 20 Nov 2020 15:15:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="HL2klsza" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729219AbgKTPOK (ORCPT ); Fri, 20 Nov 2020 10:14:10 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:52833 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729048AbgKTPOJ (ORCPT ); Fri, 20 Nov 2020 10:14:09 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885246; 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=LeGBhHGv6GBclHlt/8dfQ5fo0A4VKX6nHaerEPTu+aA=; b=HL2klszaAleQ20sR5WvmCoHCttpTMe8167nGyfFHT7hwMcGj5to2Zal4H1jois9N9h8xX5 M0rZ6F4Q/PY0A1anDGaTLL0GYP8PQiGlEyi/3x+FhMVyAApQURSNoCLj2wVOjPESWDrja6 Xti2RXLxRGhyYrzG2oXba3jouNMCB5o= 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-109-EmWzCOx-PcyukhOwVvBF1Q-1; Fri, 20 Nov 2020 10:14:04 -0500 X-MC-Unique: EmWzCOx-PcyukhOwVvBF1Q-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 896A6801B19; Fri, 20 Nov 2020 15:14:02 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 58F9110021B3; Fri, 20 Nov 2020 15:13:56 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 53/76] fscache: Implement "will_modify" parameter on fscache_use_cookie() From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:13:55 +0000 Message-ID: <160588523556.3465195.5875233390723322661.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Implement the "will_modify" parameter passed to fscache_use_cookie(). Setting this to true will henceforth cause the affected object to be marked as dirty on disk, subject to conflict resolution in the event that power failure or a crash occurs or the filesystem operates in disconnected mode. The dirty flag is removed when the fscache_object is discarded from memory. A cache hook is provided to prepare for writing - and this can be used to mark the object on disk. Signed-off-by: David Howells --- fs/cachefiles/interface.c | 68 +++++++++++++++++++++++++++++++++++++++++ fs/cachefiles/internal.h | 2 + fs/cachefiles/xattr.c | 27 ++++++++++++++++ fs/fscache/cookie.c | 15 ++++++++- fs/fscache/internal.h | 1 + fs/fscache/obj.c | 28 ++++++++++++++--- include/linux/fscache-cache.h | 4 ++ 7 files changed, 137 insertions(+), 8 deletions(-) diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 4da10640611c..56ae8d956174 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -208,14 +208,81 @@ static void cachefiles_update_object(struct fscache_object *_object) _leave(""); } +/* + * Shorten the backing object to discard any dirty data and free up + * any unused granules. + */ +static bool cachefiles_shorten_object(struct cachefiles_object *object, loff_t new_size) +{ + struct cachefiles_cache *cache; + struct inode *inode; + struct path path; + loff_t i_size; + int ret; + + cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + path.mnt = cache->mnt; + path.dentry = object->dentry; + + inode = d_inode(object->dentry); + trace_cachefiles_trunc(object, inode, i_size_read(inode), new_size); + ret = vfs_truncate(&path, new_size); + if (ret < 0) { + cachefiles_io_error_obj(object, "Trunc-to-size failed %d", ret); + cachefiles_remove_object_xattr(cache, object->dentry); + return false; + } + + new_size = round_up(new_size, CACHEFILES_DIO_BLOCK_SIZE); + i_size = i_size_read(inode); + if (i_size < new_size) { + trace_cachefiles_trunc(object, inode, i_size, new_size); + ret = vfs_truncate(&path, new_size); + if (ret < 0) { + cachefiles_io_error_obj(object, "Trunc-to-dio-size failed %d", ret); + cachefiles_remove_object_xattr(cache, object->dentry); + return false; + } + } + + return true; +} + +/* + * Trim excess stored data off of an object. + */ +static bool cachefiles_trim_object(struct cachefiles_object *object) +{ + loff_t object_size; + + _enter("{OBJ%x}", object->fscache.debug_id); + + object_size = object->fscache.cookie->object_size; + if (i_size_read(d_inode(object->dentry)) <= object_size) + return true; + + return cachefiles_shorten_object(object, object_size); +} + /* * Commit changes to the object as we drop it. */ static bool cachefiles_commit_object(struct cachefiles_object *object, struct cachefiles_cache *cache) { + bool update = false; + if (object->content_map_changed) cachefiles_save_content_map(object); + if (test_and_clear_bit(FSCACHE_OBJECT_LOCAL_WRITE, &object->fscache.flags)) + update = true; + if (test_and_clear_bit(FSCACHE_OBJECT_NEEDS_UPDATE, &object->fscache.flags)) + update = true; + if (update) { + if (cachefiles_trim_object(object)) + cachefiles_set_object_xattr(object); + } if (test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) return cachefiles_commit_tmpfile(cache, object); @@ -591,5 +658,6 @@ const struct fscache_cache_ops cachefiles_cache_ops = { .get_object_usage = cachefiles_get_object_usage, .sync_cache = cachefiles_sync_cache, .begin_operation = cachefiles_begin_operation, + .prepare_to_write = cachefiles_prepare_to_write, .display_object = cachefiles_display_object, }; diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index af68564598d5..e2d06c0860a2 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -258,7 +258,7 @@ extern int cachefiles_set_object_xattr(struct cachefiles_object *object); extern int cachefiles_check_auxdata(struct cachefiles_object *object); extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, struct dentry *dentry); - +extern int cachefiles_prepare_to_write(struct fscache_object *object); /* * error handling diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index 991ecda1f140..2f8623a7b864 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -124,6 +124,8 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object) buf->zero_point = cpu_to_be64(object->fscache.cookie->zero_point); buf->type = object->fscache.cookie->type; buf->content = object->content_info; + if (test_bit(FSCACHE_OBJECT_LOCAL_WRITE, &object->fscache.flags)) + buf->content = CACHEFILES_CONTENT_DIRTY; if (len > 0) memcpy(buf->data, fscache_get_aux(object->fscache.cookie), len); @@ -184,6 +186,10 @@ int cachefiles_check_auxdata(struct cachefiles_object *object) why = cachefiles_coherency_check_aux; } else if (be64_to_cpu(buf->object_size) != object->fscache.cookie->object_size) { why = cachefiles_coherency_check_objsize; + } else if (buf->content == CACHEFILES_CONTENT_DIRTY) { + // TODO: Begin conflict resolution + pr_warn("Dirty object in cache\n"); + why = cachefiles_coherency_check_dirty; } else { object->fscache.cookie->zero_point = be64_to_cpu(buf->zero_point); object->content_info = buf->content; @@ -219,3 +225,24 @@ int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, _leave(" = %d", ret); return ret; } + +/* + * Stick a marker on the cache object to indicate that it's dirty. + */ +int cachefiles_prepare_to_write(struct fscache_object *_object) +{ + int ret; + const struct cred *saved_cred; + struct cachefiles_object *object = + container_of(_object, struct cachefiles_object, fscache); + struct cachefiles_cache *cache = + container_of(_object->cache, struct cachefiles_cache, cache); + + _enter("c=%08x", object->fscache.cookie->debug_id); + + cachefiles_begin_secure(cache, &saved_cred); + ret = cachefiles_set_object_xattr(object); + cachefiles_end_secure(cache, saved_cred); + + return ret; +} diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index d20028535a86..bfea035af06d 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c @@ -363,6 +363,8 @@ EXPORT_SYMBOL(__fscache_acquire_cookie); void __fscache_use_cookie(struct fscache_cookie *cookie, bool will_modify) { enum fscache_cookie_stage stage; + struct fscache_object *object; + bool write_set; _enter("c=%08x", cookie->debug_id); @@ -398,8 +400,17 @@ void __fscache_use_cookie(struct fscache_cookie *cookie, bool will_modify) case FSCACHE_COOKIE_STAGE_NO_DATA_YET: case FSCACHE_COOKIE_STAGE_ACTIVE: case FSCACHE_COOKIE_STAGE_INVALIDATING: - // TODO: Handle will_modify - spin_unlock(&cookie->lock); + if (will_modify) { + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + write_set = test_and_set_bit(FSCACHE_OBJECT_LOCAL_WRITE, + &object->flags); + spin_unlock(&cookie->lock); + if (!write_set) + fscache_dispatch(cookie, object, 0, fscache_prepare_to_write); + } else { + spin_unlock(&cookie->lock); + } break; case FSCACHE_COOKIE_STAGE_FAILED: diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 73568e84fe3d..3c408da2c837 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -152,6 +152,7 @@ extern void fscache_lookup_object(struct fscache_cookie *, struct fscache_object extern void fscache_invalidate_object(struct fscache_cookie *, struct fscache_object *, int); extern void fscache_drop_object(struct fscache_cookie *, struct fscache_object *, bool); extern void fscache_relinquish_objects(struct fscache_cookie *, struct fscache_object *, int); +extern void fscache_prepare_to_write(struct fscache_cookie *, struct fscache_object *, int); /* * object-list.c diff --git a/fs/fscache/obj.c b/fs/fscache/obj.c index 60c70c0e474d..a36de6af2182 100644 --- a/fs/fscache/obj.c +++ b/fs/fscache/obj.c @@ -117,7 +117,8 @@ static bool fscache_wrangle_object(struct fscache_cookie *cookie, * Create an object chain, making sure that the index chain is fully created. */ static struct fscache_object *fscache_lookup_object_chain(struct fscache_cookie *cookie, - struct fscache_cache *cache) + struct fscache_cache *cache, + bool will_modify) { struct fscache_object *object = NULL, *parent, *xobject; @@ -131,7 +132,7 @@ static struct fscache_object *fscache_lookup_object_chain(struct fscache_cookie spin_unlock(&cookie->lock); /* Recurse to look up/create the parent index. */ - parent = fscache_lookup_object_chain(cookie->parent, cache); + parent = fscache_lookup_object_chain(cookie->parent, cache, false); if (!parent) goto error; @@ -146,6 +147,9 @@ static struct fscache_object *fscache_lookup_object_chain(struct fscache_cookie if (!object) goto error; + if (will_modify) + __set_bit(FSCACHE_OBJECT_LOCAL_WRITE, &object->flags); + xobject = fscache_attach_object(cookie, object); if (xobject != object) { fscache_do_put_object(object, fscache_obj_put_alloc_dup); @@ -207,7 +211,8 @@ static struct fscache_object *fscache_lookup_object_chain(struct fscache_cookie * - this must make sure the index chain is instantiated and instantiate the * object representation too */ -static void fscache_lookup_object_locked(struct fscache_cookie *cookie) +static void fscache_lookup_object_locked(struct fscache_cookie *cookie, + bool will_modify) { struct fscache_object *object; struct fscache_cache *cache; @@ -225,12 +230,16 @@ static void fscache_lookup_object_locked(struct fscache_cookie *cookie) _debug("cache %s", cache->tag->name); - object = fscache_lookup_object_chain(cookie, cache); + object = fscache_lookup_object_chain(cookie, cache, will_modify); if (!object) { _leave(" [fail]"); return; } + if (will_modify && + test_and_set_bit(FSCACHE_OBJECT_LOCAL_WRITE, &object->flags)) + fscache_prepare_to_write(cookie, object, 0); + fscache_do_put_object(object, fscache_obj_put); _leave(" [done]"); } @@ -239,7 +248,7 @@ void fscache_lookup_object(struct fscache_cookie *cookie, struct fscache_object *object, int param) { down_read(&fscache_addremove_sem); - fscache_lookup_object_locked(cookie); + fscache_lookup_object_locked(cookie, param); up_read(&fscache_addremove_sem); __fscache_unuse_cookie(cookie, NULL, NULL); } @@ -354,3 +363,12 @@ void fscache_relinquish_objects(struct fscache_cookie *cookie, fscache_drop_cookie(cookie); } + +/* + * Prepare a cache object to be written to. + */ +void fscache_prepare_to_write(struct fscache_cookie *cookie, + struct fscache_object *object, int param) +{ + object->cache->ops->prepare_to_write(object); +} diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index a0bb526735b5..eb303deb39c1 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -142,6 +142,9 @@ struct fscache_cache_ops { /* Begin an operation on a cache object */ void (*begin_operation)(struct fscache_op_resources *opr); + /* Prepare to write to a live cache object */ + int (*prepare_to_write)(struct fscache_object *object); + /* Display object info in /proc/fs/fscache/objects */ int (*display_object)(struct seq_file *m, struct fscache_object *object); }; @@ -170,6 +173,7 @@ struct fscache_object { spinlock_t lock; /* state and operations lock */ unsigned long flags; +#define FSCACHE_OBJECT_LOCAL_WRITE 1 /* T if the object is being modified locally */ #define FSCACHE_OBJECT_NEEDS_INVAL 8 /* T if object needs invalidation */ #define FSCACHE_OBJECT_NEEDS_UPDATE 9 /* T if object attrs need writing to disk */ From patchwork Fri Nov 20 15:14:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329205 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB389C6379F for ; Fri, 20 Nov 2020 15:15:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 574982222F for ; Fri, 20 Nov 2020 15:15:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="DNKAOFHi" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728727AbgKTPOd (ORCPT ); Fri, 20 Nov 2020 10:14:33 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:31194 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728367AbgKTPOd (ORCPT ); Fri, 20 Nov 2020 10:14:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885270; 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=kHfpulYYWv1XYUZpZHjx8JJlCiKyf38JLaCifjX8p1U=; b=DNKAOFHiIYMmQPCDUCcnkqxftVAAiP71hyEDFus3+QnufKbMrVEq6aSjdXepQm+SklWas8 YLip3tss/1gcsmaDq+Qx7oEwfqA5L/lazLQ8uSXyHOQQEPM2WaBfdl00lESZc1REcMk0yO dpkIxqlOAF3bwJixTcSKCpxkaeq/Pxk= 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-231-ccBDG6boPhmWPz0l6NQG8A-1; Fri, 20 Nov 2020 10:14:28 -0500 X-MC-Unique: ccBDG6boPhmWPz0l6NQG8A-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9862B8144F1; Fri, 20 Nov 2020 15:14:26 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id AA2336085D; Fri, 20 Nov 2020 15:14:20 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 55/76] fscache: Remove the update operation From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:14:19 +0000 Message-ID: <160588525990.3465195.11175224125263070400.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Remove the cache-side of the object update operation as it doesn't serialise with other setattr, O_TRUNC and write operations. Signed-off-by: David Howells --- fs/cachefiles/interface.c | 59 ----------------------------------------- fs/fscache/internal.h | 2 - fs/fscache/obj.c | 14 ---------- fs/fscache/stats.c | 6 +--- include/linux/fscache-cache.h | 2 - 5 files changed, 2 insertions(+), 81 deletions(-) diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index aca08e4227b9..3609ff2fb491 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -150,64 +150,6 @@ struct fscache_object *cachefiles_grab_object(struct fscache_object *_object, return &object->fscache; } -/* - * update the auxiliary data for an object object on disk - */ -static void cachefiles_update_object(struct fscache_object *_object) -{ - struct cachefiles_object *object; - struct cachefiles_cache *cache; - const struct cred *saved_cred; - struct inode *inode; - loff_t object_size, i_size; - int ret; - - _enter("{OBJ%x}", _object->debug_id); - - object = container_of(_object, struct cachefiles_object, fscache); - cache = container_of(object->fscache.cache, struct cachefiles_cache, - cache); - - cachefiles_begin_secure(cache, &saved_cred); - - object_size = object->fscache.cookie->object_size; - inode = d_inode(object->dentry); - i_size = i_size_read(inode); - if (i_size > object_size) { - struct path path = { - .mnt = cache->mnt, - .dentry = object->dentry - }; - _debug("trunc %llx -> %llx", i_size, object_size); - trace_cachefiles_trunc(object, inode, i_size, object_size); - ret = vfs_truncate(&path, object_size); - if (ret < 0) { - cachefiles_io_error_obj(object, "Trunc-to-size failed"); - cachefiles_remove_object_xattr(cache, object->dentry); - goto out; - } - - object_size = round_up(object_size, CACHEFILES_DIO_BLOCK_SIZE); - i_size = i_size_read(inode); - _debug("trunc %llx -> %llx", i_size, object_size); - if (i_size < object_size) { - trace_cachefiles_trunc(object, inode, i_size, object_size); - ret = vfs_truncate(&path, object_size); - if (ret < 0) { - cachefiles_io_error_obj(object, "Trunc-to-dio-size failed"); - cachefiles_remove_object_xattr(cache, object->dentry); - goto out; - } - } - } - - cachefiles_set_object_xattr(object); - -out: - cachefiles_end_secure(cache, saved_cred); - _leave(""); -} - /* * Shorten the backing object to discard any dirty data and free up * any unused granules. @@ -681,7 +623,6 @@ const struct fscache_cache_ops cachefiles_cache_ops = { .lookup_object = cachefiles_lookup_object, .free_lookup_data = cachefiles_free_lookup_data, .grab_object = cachefiles_grab_object, - .update_object = cachefiles_update_object, .resize_object = cachefiles_resize_object, .invalidate_object = cachefiles_invalidate_object, .drop_object = cachefiles_drop_object, diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index ff193f61a4c5..510f166103bf 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -189,7 +189,6 @@ extern atomic_t fscache_n_acquires_oom; extern atomic_t fscache_n_invalidates; extern atomic_t fscache_n_updates; -extern atomic_t fscache_n_updates_run; extern atomic_t fscache_n_relinquishes; extern atomic_t fscache_n_relinquishes_retire; @@ -214,7 +213,6 @@ extern atomic_t fscache_n_cop_alloc_object; extern atomic_t fscache_n_cop_lookup_object; extern atomic_t fscache_n_cop_create_object; extern atomic_t fscache_n_cop_invalidate_object; -extern atomic_t fscache_n_cop_update_object; extern atomic_t fscache_n_cop_drop_object; extern atomic_t fscache_n_cop_put_object; extern atomic_t fscache_n_cop_sync_cache; diff --git a/fs/fscache/obj.c b/fs/fscache/obj.c index a36de6af2182..2b0c99095a42 100644 --- a/fs/fscache/obj.c +++ b/fs/fscache/obj.c @@ -54,14 +54,6 @@ static int fscache_do_create_object(struct fscache_object *object, void *data) return ret; } -static void fscache_do_update_object(struct fscache_object *object) -{ - fscache_stat(&fscache_n_updates_run); - fscache_stat(&fscache_n_cop_update_object); - object->cache->ops->update_object(object); - fscache_stat_d(&fscache_n_cop_update_object); -} - static void fscache_do_drop_object(struct fscache_cache *cache, struct fscache_object *object, bool invalidate) @@ -291,12 +283,6 @@ void fscache_drop_object(struct fscache_cookie *cookie, _enter("{o=%08x,%d},%u", object->debug_id, object->n_children, invalidate); - if (!invalidate && - test_bit(FSCACHE_OBJECT_NEEDS_UPDATE, &object->flags)) { - _debug("final update"); - fscache_do_update_object(object); - } - spin_lock(&cache->object_list_lock); list_del_init(&object->cache_link); spin_unlock(&cache->object_list_lock); diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c index 2a2df9d1649e..350e65870dff 100644 --- a/fs/fscache/stats.c +++ b/fs/fscache/stats.c @@ -102,9 +102,8 @@ static int fscache_stats_show(struct seq_file *m, void *v) seq_printf(m, "Invals : n=%u\n", atomic_read(&fscache_n_invalidates)); - seq_printf(m, "Updates: n=%u nul=%u rsz=%u rsn=%u\n", + seq_printf(m, "Updates: n=%u rsz=%u rsn=%u\n", atomic_read(&fscache_n_updates), - atomic_read(&fscache_n_updates_run), atomic_read(&fscache_n_resizes), atomic_read(&fscache_n_resizes_null)); @@ -115,9 +114,8 @@ static int fscache_stats_show(struct seq_file *m, void *v) seq_printf(m, "CacheOp: alo=%d luo=%d\n", atomic_read(&fscache_n_cop_alloc_object), atomic_read(&fscache_n_cop_lookup_object)); - seq_printf(m, "CacheOp: inv=%d upo=%d dro=%d pto=%d atc=%d syn=%d\n", + seq_printf(m, "CacheOp: inv=%d dro=%d pto=%d atc=%d syn=%d\n", atomic_read(&fscache_n_cop_invalidate_object), - atomic_read(&fscache_n_cop_update_object), atomic_read(&fscache_n_cop_drop_object), atomic_read(&fscache_n_cop_put_object), atomic_read(&fscache_n_cop_attr_changed), diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 958fa899917d..74a09738c899 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -115,8 +115,6 @@ struct fscache_cache_ops { /* unpin an object in the cache */ void (*unpin_object)(struct fscache_object *object); - /* store the updated auxiliary data on an object */ - void (*update_object)(struct fscache_object *object); /* Change the size of a data object */ void (*resize_object)(struct fscache_object *object, loff_t new_size); From patchwork Fri Nov 20 15:14:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329204 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F3ADEC64E69 for ; Fri, 20 Nov 2020 15:15:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B6A3B22252 for ; Fri, 20 Nov 2020 15:15:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="INchAjGT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729264AbgKTPOq (ORCPT ); Fri, 20 Nov 2020 10:14:46 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:56599 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729037AbgKTPOp (ORCPT ); Fri, 20 Nov 2020 10:14:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885284; 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=w4fg5oGh21XBgs3jGclZ3hwXa0kjESICZpD7AJSYvNk=; b=INchAjGTAMtPb7864LJvUhUlHWL0PMgEtDzuCWc4Zm/fMTvJVIGuhP25f2c+voZuiSe3st 1/u6YifbGGZo1mMwGngaIwzmD9u2Ad35y31Eo6O+yaqF2MvlUd6wBXiDuD2GolAMTn41+8 1JePWRlNGjk2mEA1jwwV6iqHBSloXFg= 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-42-pXsfS9KTPC-PUFgAVtKuzw-1; Fri, 20 Nov 2020 10:14:40 -0500 X-MC-Unique: pXsfS9KTPC-PUFgAVtKuzw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 88B081005D5A; Fri, 20 Nov 2020 15:14:38 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id A3E9560C05; Fri, 20 Nov 2020 15:14:32 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 56/76] afs: Pass page into dirty region helpers to provide THP size From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:14:31 +0000 Message-ID: <160588527183.3465195.16107942526481976308.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Pass a pointer to the page being accessed into the dirty region helpers so that the size of the page can be determined in case it's a transparent huge page. This also required the page to be passed into the afs_page_dirty trace point - so there's no need to specifically pass in the index or private data as these can be retrieved directly from the page struct. Signed-off-by: David Howells --- fs/afs/file.c | 20 +++++++-------- fs/afs/internal.h | 16 ++++++------ fs/afs/write.c | 60 ++++++++++++++++++-------------------------- include/trace/events/afs.h | 23 ++++++++++------- 4 files changed, 55 insertions(+), 64 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index ba8874720626..c06197e4339b 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -528,8 +528,8 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset, return; /* We may need to shorten the dirty region */ - f = afs_page_dirty_from(priv); - t = afs_page_dirty_to(priv); + f = afs_page_dirty_from(page, priv); + t = afs_page_dirty_to(page, priv); if (t <= offset || f >= end) return; /* Doesn't overlap */ @@ -547,17 +547,17 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset, if (f == t) goto undirty; - priv = afs_page_dirty(f, t); + priv = afs_page_dirty(page, f, t); set_page_private(page, priv); - trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page); return; undirty: - trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page); clear_page_dirty_for_io(page); full_invalidate: - priv = (unsigned long)detach_page_private(page); - trace_afs_page_dirty(vnode, tracepoint_string("inval"), page->index, priv); + detach_page_private(page); + trace_afs_page_dirty(vnode, tracepoint_string("inval"), page); } /* @@ -585,7 +585,6 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, static int afs_releasepage(struct page *page, gfp_t gfp_flags) { struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); - unsigned long priv; _enter("{{%llx:%llu}[%lu],%lx},%x", vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, @@ -594,9 +593,8 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) /* deny if page is being written to the cache and the caller hasn't * elected to wait */ if (PagePrivate(page)) { - priv = (unsigned long)detach_page_private(page); - trace_afs_page_dirty(vnode, tracepoint_string("rel"), - page->index, priv); + detach_page_private(page); + trace_afs_page_dirty(vnode, tracepoint_string("rel"), page); } /* indicate that the page can be released */ diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 12bb08eaeeff..9f75d99f5b2e 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -874,31 +874,31 @@ struct afs_vnode_cache_aux { #define __AFS_PAGE_PRIV_MMAPPED 0x8000UL #endif -static inline unsigned int afs_page_dirty_resolution(void) +static inline unsigned int afs_page_dirty_resolution(struct page *page) { - int shift = PAGE_SHIFT - (__AFS_PAGE_PRIV_SHIFT - 1); + int shift = thp_order(page) + PAGE_SHIFT - (__AFS_PAGE_PRIV_SHIFT - 1); return (shift > 0) ? shift : 0; } -static inline size_t afs_page_dirty_from(unsigned long priv) +static inline size_t afs_page_dirty_from(struct page *page, unsigned long priv) { unsigned long x = priv & __AFS_PAGE_PRIV_MASK; /* The lower bound is inclusive */ - return x << afs_page_dirty_resolution(); + return x << afs_page_dirty_resolution(page); } -static inline size_t afs_page_dirty_to(unsigned long priv) +static inline size_t afs_page_dirty_to(struct page *page, unsigned long priv) { unsigned long x = (priv >> __AFS_PAGE_PRIV_SHIFT) & __AFS_PAGE_PRIV_MASK; /* The upper bound is immediately beyond the region */ - return (x + 1) << afs_page_dirty_resolution(); + return (x + 1) << afs_page_dirty_resolution(page); } -static inline unsigned long afs_page_dirty(size_t from, size_t to) +static inline unsigned long afs_page_dirty(struct page *page, size_t from, size_t to) { - unsigned int res = afs_page_dirty_resolution(); + unsigned int res = afs_page_dirty_resolution(page); from >>= res; to = (to - 1) >> res; return (to << __AFS_PAGE_PRIV_SHIFT) | from; diff --git a/fs/afs/write.c b/fs/afs/write.c index 92eaa88000d7..9d0cef35ecba 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -112,15 +112,14 @@ int afs_write_begin(struct file *file, struct address_space *mapping, t = f = 0; if (PagePrivate(page)) { priv = page_private(page); - f = afs_page_dirty_from(priv); - t = afs_page_dirty_to(priv); + f = afs_page_dirty_from(page, priv); + t = afs_page_dirty_to(page, priv); ASSERTCMP(f, <=, t); } if (f != t) { if (PageWriteback(page)) { - trace_afs_page_dirty(vnode, tracepoint_string("alrdy"), - page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("alrdy"), page); goto flush_conflicting_write; } /* If the file is being filled locally, allow inter-write @@ -204,21 +203,19 @@ int afs_write_end(struct file *file, struct address_space *mapping, if (PagePrivate(page)) { priv = page_private(page); - f = afs_page_dirty_from(priv); - t = afs_page_dirty_to(priv); + f = afs_page_dirty_from(page, priv); + t = afs_page_dirty_to(page, priv); if (from < f) f = from; if (to > t) t = to; - priv = afs_page_dirty(f, t); + priv = afs_page_dirty(page, f, t); set_page_private(page, priv); - trace_afs_page_dirty(vnode, tracepoint_string("dirty+"), - page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("dirty+"), page); } else { - priv = afs_page_dirty(from, to); + priv = afs_page_dirty(page, from, to); attach_page_private(page, (void *)priv); - trace_afs_page_dirty(vnode, tracepoint_string("dirty"), - page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("dirty"), page); } set_page_dirty(page); @@ -321,7 +318,6 @@ static void afs_pages_written_back(struct afs_vnode *vnode, pgoff_t first, pgoff_t last) { struct pagevec pv; - unsigned long priv; unsigned count, loop; _enter("{%llx:%llu},{%lx-%lx}", @@ -340,9 +336,9 @@ static void afs_pages_written_back(struct afs_vnode *vnode, ASSERTCMP(pv.nr, ==, count); for (loop = 0; loop < count; loop++) { - priv = (unsigned long)detach_page_private(pv.pages[loop]); + detach_page_private(pv.pages[loop]); trace_afs_page_dirty(vnode, tracepoint_string("clear"), - pv.pages[loop]->index, priv); + pv.pages[loop]); end_page_writeback(pv.pages[loop]); } first += count; @@ -516,15 +512,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, */ start = primary_page->index; priv = page_private(primary_page); - offset = afs_page_dirty_from(priv); - to = afs_page_dirty_to(priv); - trace_afs_page_dirty(vnode, tracepoint_string("store"), - primary_page->index, priv); + offset = afs_page_dirty_from(primary_page, priv); + to = afs_page_dirty_to(primary_page, priv); + trace_afs_page_dirty(vnode, tracepoint_string("store"), primary_page); WARN_ON(offset == to); if (offset == to) - trace_afs_page_dirty(vnode, tracepoint_string("WARN"), - primary_page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("WARN"), primary_page); if (start >= final_page || (to < PAGE_SIZE && !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags))) @@ -562,8 +556,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, } priv = page_private(page); - f = afs_page_dirty_from(priv); - t = afs_page_dirty_to(priv); + f = afs_page_dirty_from(page, priv); + t = afs_page_dirty_to(page, priv); if (f != 0 && !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)) { unlock_page(page); @@ -571,8 +565,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, } to = t; - trace_afs_page_dirty(vnode, tracepoint_string("store+"), - page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("store+"), page); if (!clear_page_dirty_for_io(page)) BUG(); @@ -861,14 +854,13 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) */ wait_on_page_writeback(vmf->page); - priv = afs_page_dirty(0, PAGE_SIZE); + priv = afs_page_dirty(vmf->page, 0, PAGE_SIZE); priv = afs_page_dirty_mmapped(priv); - trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), - vmf->page->index, priv); if (PagePrivate(vmf->page)) set_page_private(vmf->page, priv); else attach_page_private(vmf->page, (void *)priv); + trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), vmf->page); file_update_time(file); sb_end_pagefault(inode->i_sb); @@ -921,17 +913,15 @@ int afs_launder_page(struct page *page) f = 0; t = PAGE_SIZE; if (PagePrivate(page)) { - f = afs_page_dirty_from(priv); - t = afs_page_dirty_to(priv); + f = afs_page_dirty_from(page, priv); + t = afs_page_dirty_to(page, priv); } - trace_afs_page_dirty(vnode, tracepoint_string("launder"), - page->index, priv); + trace_afs_page_dirty(vnode, tracepoint_string("launder"), page); ret = afs_store_data(mapping, page->index, page->index, t, f, true); } - priv = (unsigned long)detach_page_private(page); - trace_afs_page_dirty(vnode, tracepoint_string("laundered"), - page->index, priv); + detach_page_private(page); + trace_afs_page_dirty(vnode, tracepoint_string("laundered"), page); return ret; } diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 4eef374d4413..f0b2565db2d9 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -967,30 +967,33 @@ TRACE_EVENT(afs_dir_check_failed, ); TRACE_EVENT(afs_page_dirty, - TP_PROTO(struct afs_vnode *vnode, const char *where, - pgoff_t page, unsigned long priv), + TP_PROTO(struct afs_vnode *vnode, const char *where, struct page *page), - TP_ARGS(vnode, where, page, priv), + TP_ARGS(vnode, where, page), TP_STRUCT__entry( __field(struct afs_vnode *, vnode ) __field(const char *, where ) __field(pgoff_t, page ) - __field(unsigned long, priv ) + __field(unsigned long, from ) + __field(unsigned long, to ) ), TP_fast_assign( __entry->vnode = vnode; __entry->where = where; - __entry->page = page; - __entry->priv = priv; + __entry->page = page->index; + __entry->from = afs_page_dirty_from(page, page->private); + __entry->to = afs_page_dirty_to(page, page->private); + __entry->to |= (afs_is_page_dirty_mmapped(page->private) ? + (1UL << (BITS_PER_LONG - 1)) : 0); ), - TP_printk("vn=%p %lx %s %zx-%zx%s", + TP_printk("vn=%p %lx %s %lx-%lx%s", __entry->vnode, __entry->page, __entry->where, - afs_page_dirty_from(__entry->priv), - afs_page_dirty_to(__entry->priv), - afs_is_page_dirty_mmapped(__entry->priv) ? " M" : "") + __entry->from, + __entry->to & ~(1UL << (BITS_PER_LONG - 1)), + __entry->to & (1UL << (BITS_PER_LONG - 1)) ? " M" : "") ); TRACE_EVENT(afs_call_state, From patchwork Fri Nov 20 15:15:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329203 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA4CCC5519F for ; Fri, 20 Nov 2020 15:15:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 79F4E2222F for ; Fri, 20 Nov 2020 15:15:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="H5HNGAPf" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729381AbgKTPPl (ORCPT ); Fri, 20 Nov 2020 10:15:41 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:37704 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729369AbgKTPPi (ORCPT ); Fri, 20 Nov 2020 10:15:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885336; 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=LVrYBw50M3qAWt5OO3susLl641/S5k5EWEOat7h2fvM=; b=H5HNGAPfdS9BpDDvRbEbdInQGeLKU/JeKH7/vD4LCU3w6883lhfdQykj57eQkdqanHM524 gZClQi6Lfrjv3ULbJzIBiszlEhKzxDFx3XaAJGW4Y85/GJ3IuICex7CFSCtuBkxNWfexBk aU7lyNsGT8n7lT0QCMjYWxKWDMn3RbU= 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-177-HUm0pn3kMw6WdLRutqTL8w-1; Fri, 20 Nov 2020 10:15:34 -0500 X-MC-Unique: HUm0pn3kMw6WdLRutqTL8w-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 85F961DDE5; Fri, 20 Nov 2020 15:15:32 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id BB1D060C15; Fri, 20 Nov 2020 15:15:26 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 60/76] afs: Log remote unmarshalling errors From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:15:25 +0000 Message-ID: <160588532584.3465195.15618385466614028590.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Log unmarshalling errors reported by the peer (ie. it can't parse what we sent it). Limit the maximum number of messages to 3. Signed-off-by: David Howells --- fs/afs/rxrpc.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 0ec38b758f29..ae68576f822f 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -500,6 +500,39 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp) _leave(" = %d", ret); } +/* + * Log remote abort codes that indicate that we have a protocol disagreement + * with the server. + */ +static void afs_log_error(struct afs_call *call, s32 remote_abort) +{ + static int max = 0; + const char *msg; + int m; + + switch (remote_abort) { + case RX_EOF: msg = "unexpected EOF"; break; + case RXGEN_CC_MARSHAL: msg = "client marshalling"; break; + case RXGEN_CC_UNMARSHAL: msg = "client unmarshalling"; break; + case RXGEN_SS_MARSHAL: msg = "server marshalling"; break; + case RXGEN_SS_UNMARSHAL: msg = "server unmarshalling"; break; + case RXGEN_DECODE: msg = "opcode decode"; break; + case RXGEN_SS_XDRFREE: msg = "server XDR cleanup"; break; + case RXGEN_CC_XDRFREE: msg = "client XDR cleanup"; break; + case -32: msg = "insufficient data"; break; + default: + return; + } + + m = max; + if (m < 3) { + max = m + 1; + pr_notice("kAFS: Peer reported %s failure on %s [%pISp]\n", + msg, call->type->name, + &call->alist->addrs[call->addr_ix].transport); + } +} + /* * deliver messages to a call */ @@ -563,6 +596,7 @@ static void afs_deliver_to_call(struct afs_call *call) goto out; case -ECONNABORTED: ASSERTCMP(state, ==, AFS_CALL_COMPLETE); + afs_log_error(call, call->abort_code); goto done; case -ENOTSUPP: abort_code = RXGEN_OPCODE; From patchwork Fri Nov 20 15:15:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329202 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B699C2D0E4 for ; Fri, 20 Nov 2020 15:16:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 30F1F22269 for ; Fri, 20 Nov 2020 15:16:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="fnolqDI6" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729397AbgKTPPy (ORCPT ); Fri, 20 Nov 2020 10:15:54 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:42804 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726426AbgKTPPx (ORCPT ); Fri, 20 Nov 2020 10:15:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885350; 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=ETpW/V9Jlt7dZ/yYeEqUkKPWOT8XJEJRZOOV1lssZ0I=; b=fnolqDI6xP0xPhvu1u4+Vq6rsMkr8OiT51KH6pgJOWGUU6zONDKg2NJUa7ES+1VnsokSFh OzVgoMifz6op0eHCJEnnVWeODYWw3q9KjlTop26hipdR+xfERlEZFIAGGXjZOITCASlnE1 Ne8TJrNIMznn/UL7nkTu5Bbu/1CX/Hc= 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-314-c_DHPHVBMuGWVTgBhTrXUg-1; Fri, 20 Nov 2020 10:15:48 -0500 X-MC-Unique: c_DHPHVBMuGWVTgBhTrXUg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id ED04B1DDE5; Fri, 20 Nov 2020 15:15:44 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 992E45D9D5; Fri, 20 Nov 2020 15:15:38 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 61/76] afs: Set up the iov_iter before calling afs_extract_data() From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:15:37 +0000 Message-ID: <160588533776.3465195.3612752083351956948.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org afs_extract_data() sets up a temporary iov_iter and passes it to AF_RXRPC each time it is called to describe the remaining buffer to be filled. Instead: (1) Put an iterator in the afs_call struct. (2) Set the iterator for each marshalling stage to load data into the appropriate places. A number of convenience functions are provided to this end (eg. afs_extract_to_buf()). This iterator is then passed to afs_extract_data(). (3) Use the new ITER_MAPPING iterator when reading data to load directly into the inode's pages without needing to create a list of them. This will allow O_DIRECT calls to be supported in future patches. Signed-off-by: David Howells --- fs/afs/dir.c | 222 +++++++++++++++++++++++++++++++++++----------------- fs/afs/file.c | 190 ++++++++++++++++++++++++++------------------- fs/afs/fsclient.c | 54 +++---------- fs/afs/internal.h | 16 ++-- fs/afs/write.c | 27 ++++-- fs/afs/yfsclient.c | 54 +++---------- 6 files changed, 314 insertions(+), 249 deletions(-) diff --git a/fs/afs/dir.c b/fs/afs/dir.c index ec4be0d50d2f..215f73121391 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -102,6 +102,35 @@ struct afs_lookup_cookie { struct afs_fid fids[50]; }; +/* + * Drop the refs that we're holding on the pages we were reading into. We've + * got refs on the first nr_pages pages. + */ +static void afs_dir_read_cleanup(struct afs_read *req) +{ + struct address_space *mapping = req->vnode->vfs_inode.i_mapping; + struct page *page; + pgoff_t last = req->nr_pages - 1; + + XA_STATE(xas, &mapping->i_pages, 0); + + if (unlikely(!req->nr_pages)) + return; + + rcu_read_lock(); + xas_for_each(&xas, page, last) { + if (xas_retry(&xas, page)) + continue; + BUG_ON(xa_is_value(page)); + BUG_ON(PageCompound(page)); + ASSERTCMP(page->mapping, ==, mapping); + + put_page(page); + } + + rcu_read_unlock(); +} + /* * check that a directory page is valid */ @@ -127,7 +156,7 @@ static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page, qty /= sizeof(union afs_xdr_dir_block); /* check them */ - dbuf = kmap(page); + dbuf = kmap_atomic(page); for (tmp = 0; tmp < qty; tmp++) { if (dbuf->blocks[tmp].hdr.magic != AFS_DIR_MAGIC) { printk("kAFS: %s(%lx): bad magic %d/%d is %04hx\n", @@ -146,7 +175,7 @@ static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page, ((u8 *)&dbuf->blocks[tmp])[AFS_DIR_BLOCK_SIZE - 1] = 0; } - kunmap(page); + kunmap_atomic(dbuf); checked: afs_stat_v(dvnode, n_read_dir); @@ -157,35 +186,74 @@ static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page, } /* - * Check the contents of a directory that we've just read. + * Dump the contents of a directory. */ -static bool afs_dir_check_pages(struct afs_vnode *dvnode, struct afs_read *req) +static void afs_dir_dump(struct afs_vnode *dvnode, struct afs_read *req) { struct afs_xdr_dir_page *dbuf; - unsigned int i, j, qty = PAGE_SIZE / sizeof(union afs_xdr_dir_block); + struct address_space *mapping = dvnode->vfs_inode.i_mapping; + struct page *page; + unsigned int i, qty = PAGE_SIZE / sizeof(union afs_xdr_dir_block); + pgoff_t last = req->nr_pages - 1; - for (i = 0; i < req->nr_pages; i++) - if (!afs_dir_check_page(dvnode, req->pages[i], req->actual_len)) - goto bad; - return true; + XA_STATE(xas, &mapping->i_pages, 0); -bad: - pr_warn("DIR %llx:%llx f=%llx l=%llx al=%llx r=%llx\n", + pr_warn("DIR %llx:%llx f=%llx l=%llx al=%llx\n", dvnode->fid.vid, dvnode->fid.vnode, - req->file_size, req->len, req->actual_len, req->remain); - pr_warn("DIR %llx %x %x %x\n", - req->pos, req->index, req->nr_pages, req->offset); + req->file_size, req->len, req->actual_len); + pr_warn("DIR %llx %x %zx %zx\n", + req->pos, req->nr_pages, + req->iter->iov_offset, iov_iter_count(req->iter)); - for (i = 0; i < req->nr_pages; i++) { - dbuf = kmap(req->pages[i]); - for (j = 0; j < qty; j++) { - union afs_xdr_dir_block *block = &dbuf->blocks[j]; + xas_for_each(&xas, page, last) { + if (xas_retry(&xas, page)) + continue; + + BUG_ON(PageCompound(page)); + BUG_ON(page->mapping != mapping); + + dbuf = kmap_atomic(page); + for (i = 0; i < qty; i++) { + union afs_xdr_dir_block *block = &dbuf->blocks[i]; - pr_warn("[%02x] %32phN\n", i * qty + j, block); + pr_warn("[%02lx] %32phN\n", page->index * qty + i, block); } - kunmap(req->pages[i]); + kunmap_atomic(dbuf); } - return false; +} + +/* + * Check all the pages in a directory. All the pages are held pinned. + */ +static int afs_dir_check(struct afs_vnode *dvnode, struct afs_read *req) +{ + struct address_space *mapping = dvnode->vfs_inode.i_mapping; + struct page *page; + pgoff_t last = req->nr_pages - 1; + int ret = 0; + + XA_STATE(xas, &mapping->i_pages, 0); + + if (unlikely(!req->nr_pages)) + return 0; + + rcu_read_lock(); + xas_for_each(&xas, page, last) { + if (xas_retry(&xas, page)) + continue; + + BUG_ON(PageCompound(page)); + BUG_ON(page->mapping != mapping); + + ret = afs_dir_check_page(dvnode, page, req->file_size); + if (ret < 0) { + afs_dir_dump(dvnode, req); + break; + } + } + + rcu_read_unlock(); + return ret; } /* @@ -214,58 +282,57 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) { struct afs_read *req; loff_t i_size; - int nr_pages, nr_inline, i, n; - int ret = -ENOMEM; + int nr_pages, i, n; + int ret; + + _enter(""); -retry: + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return ERR_PTR(-ENOMEM); + + refcount_set(&req->usage, 1); + req->vnode = dvnode; + req->key = key_get(key); + req->cleanup = afs_dir_read_cleanup; + +expand: i_size = i_size_read(&dvnode->vfs_inode); - if (i_size < 2048) - return ERR_PTR(afs_bad(dvnode, afs_file_error_dir_small)); + if (i_size < 2048) { + ret = afs_bad(dvnode, afs_file_error_dir_small); + goto error; + } if (i_size > 2048 * 1024) { trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big); - return ERR_PTR(-EFBIG); + ret = -EFBIG; + goto error; } _enter("%llu", i_size); - /* Get a request record to hold the page list. We want to hold it - * inline if we can, but we don't want to make an order 1 allocation. - */ nr_pages = (i_size + PAGE_SIZE - 1) / PAGE_SIZE; - nr_inline = nr_pages; - if (nr_inline > (PAGE_SIZE - sizeof(*req)) / sizeof(struct page *)) - nr_inline = 0; - req = kzalloc(struct_size(req, array, nr_inline), GFP_KERNEL); - if (!req) - return ERR_PTR(-ENOMEM); - - refcount_set(&req->usage, 1); - req->key = key_get(key); - req->nr_pages = nr_pages; req->actual_len = i_size; /* May change */ req->len = nr_pages * PAGE_SIZE; /* We can ask for more than there is */ req->data_version = dvnode->status.data_version; /* May change */ - if (nr_inline > 0) { - req->pages = req->array; - } else { - req->pages = kcalloc(nr_pages, sizeof(struct page *), - GFP_KERNEL); - if (!req->pages) - goto error; - } + iov_iter_xarray(&req->def_iter, READ, &dvnode->vfs_inode.i_mapping->i_pages, + 0, i_size); + req->iter = &req->def_iter; - /* Get a list of all the pages that hold or will hold the directory - * content. We need to fill in any gaps that we might find where the - * memory reclaimer has been at work. If there are any gaps, we will + /* Fill in any gaps that we might find where the memory reclaimer has + * been at work and pin all the pages. If there are any gaps, we will * need to reread the entire directory contents. */ - i = 0; - do { + i = req->nr_pages; + while (i < nr_pages) { + struct page *pages[8], *page; + n = find_get_pages_contig(dvnode->vfs_inode.i_mapping, i, - req->nr_pages - i, - req->pages + i); - _debug("find %u at %u/%u", n, i, req->nr_pages); + min_t(unsigned int, nr_pages - i, + ARRAY_SIZE(pages)), + pages); + _debug("find %u at %u/%u", n, i, nr_pages); + if (n == 0) { gfp_t gfp = dvnode->vfs_inode.i_mapping->gfp_mask; @@ -273,22 +340,24 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) afs_stat_v(dvnode, n_inval); ret = -ENOMEM; - req->pages[i] = __page_cache_alloc(gfp); - if (!req->pages[i]) + page = __page_cache_alloc(gfp); + if (!page) goto error; - ret = add_to_page_cache_lru(req->pages[i], + ret = add_to_page_cache_lru(page, dvnode->vfs_inode.i_mapping, i, gfp); if (ret < 0) goto error; - attach_page_private(req->pages[i], (void *)1); - unlock_page(req->pages[i]); + attach_page_private(page, (void *)1); + unlock_page(page); + req->nr_pages++; i++; } else { + req->nr_pages += n; i += n; } - } while (i < req->nr_pages); + } /* If we're going to reload, we need to lock all the pages to prevent * races. @@ -312,12 +381,17 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) task_io_account_read(PAGE_SIZE * req->nr_pages); - if (req->len < req->file_size) - goto content_has_grown; + if (req->len < req->file_size) { + /* The content has grown, so we need to expand the + * buffer. + */ + up_write(&dvnode->validate_lock); + goto expand; + } /* Validate the data we just read. */ - ret = -EIO; - if (!afs_dir_check_pages(dvnode, req)) + ret = afs_dir_check(dvnode, req); + if (ret < 0) goto error_unlock; // TODO: Trim excess pages @@ -335,11 +409,6 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) afs_put_read(req); _leave(" = %d", ret); return ERR_PTR(ret); - -content_has_grown: - up_write(&dvnode->validate_lock); - afs_put_read(req); - goto retry; } /* @@ -446,6 +515,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, struct afs_read *req; struct page *page; unsigned blkoff, limit; + void __rcu **slot; int ret; _enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos); @@ -470,9 +540,15 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, blkoff = ctx->pos & ~(sizeof(union afs_xdr_dir_block) - 1); /* Fetch the appropriate page from the directory and re-add it - * to the LRU. + * to the LRU. We have all the pages pinned with an extra ref. */ - page = req->pages[blkoff / PAGE_SIZE]; + rcu_read_lock(); + page = NULL; + slot = radix_tree_lookup_slot(&dvnode->vfs_inode.i_mapping->i_pages, + blkoff / PAGE_SIZE); + if (slot) + page = radix_tree_deref_slot(slot); + rcu_read_unlock(); if (!page) { ret = afs_bad(dvnode, afs_file_error_dir_missing_page); break; diff --git a/fs/afs/file.c b/fs/afs/file.c index 55f4c6cd617f..3f409ddc1c1f 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -197,21 +197,72 @@ int afs_release(struct inode *inode, struct file *file) return ret; } +/* + * Handle completion of a read operation. + */ +static void afs_file_read_done(struct afs_read *req) +{ + struct afs_vnode *vnode = req->vnode; + struct page *page; + pgoff_t index = req->pos >> PAGE_SHIFT; + pgoff_t last = index + req->nr_pages - 1; + + XA_STATE(xas, &vnode->vfs_inode.i_mapping->i_pages, index); + + if (iov_iter_count(req->iter) > 0) { + /* The read was short - clear the excess buffer. */ + _debug("afterclear %zx %zx %llx/%llx", + req->iter->iov_offset, + iov_iter_count(req->iter), + req->actual_len, req->len); + iov_iter_zero(iov_iter_count(req->iter), req->iter); + } + + rcu_read_lock(); + xas_for_each(&xas, page, last) { + page_endio(page, false, 0); + put_page(page); + } + rcu_read_unlock(); + + task_io_account_read(req->len); + req->cleanup = NULL; +} + +/* + * Dispose of our locks and refs on the pages if the read failed. + */ +static void afs_file_read_cleanup(struct afs_read *req) +{ + struct page *page; + pgoff_t index = req->pos >> PAGE_SHIFT; + pgoff_t last = index + req->nr_pages - 1; + + if (req->iter) { + XA_STATE(xas, &req->vnode->vfs_inode.i_mapping->i_pages, index); + + _enter("%lu,%u,%zu", index, req->nr_pages, iov_iter_count(req->iter)); + + rcu_read_lock(); + xas_for_each(&xas, page, last) { + BUG_ON(xa_is_value(page)); + BUG_ON(PageCompound(page)); + + page_endio(page, false, req->error); + put_page(page); + } + rcu_read_unlock(); + } +} + /* * Dispose of a ref to a read record. */ void afs_put_read(struct afs_read *req) { - int i; - if (refcount_dec_and_test(&req->usage)) { - if (req->pages) { - for (i = 0; i < req->nr_pages; i++) - if (req->pages[i]) - put_page(req->pages[i]); - if (req->pages != req->array) - kfree(req->pages); - } + if (req->cleanup) + req->cleanup(req); key_put(req->key); kfree(req); } @@ -229,6 +280,7 @@ static void afs_fetch_data_success(struct afs_operation *op) static void afs_fetch_data_put(struct afs_operation *op) { + op->fetch.req->error = op->error; afs_put_read(op->fetch.req); } @@ -268,12 +320,11 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req) /* * read page from file, directory or symlink, given a key to use */ -int afs_page_filler(void *data, struct page *page) +static int afs_page_filler(struct key *key, struct page *page) { struct inode *inode = page->mapping->host; struct afs_vnode *vnode = AFS_FS_I(inode); struct afs_read *req; - struct key *key = data; int ret; _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); @@ -284,53 +335,52 @@ int afs_page_filler(void *data, struct page *page) if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) goto error; - req = kzalloc(struct_size(req, array, 1), GFP_KERNEL); + req = kzalloc(sizeof(struct afs_read), GFP_KERNEL); if (!req) goto enomem; - /* We request a full page. If the page is a partial one at the - * end of the file, the server will return a short read and the - * unmarshalling code will clear the unfilled space. - */ refcount_set(&req->usage, 1); - req->key = key_get(key); - req->pos = (loff_t)page->index << PAGE_SHIFT; - req->len = PAGE_SIZE; - req->nr_pages = 1; - req->pages = req->array; - req->pages[0] = page; + req->vnode = vnode; + req->key = key_get(key); + req->pos = (loff_t)page->index << PAGE_SHIFT; + req->len = PAGE_SIZE; + req->nr_pages = 1; + req->done = afs_file_read_done; + req->cleanup = afs_file_read_cleanup; + get_page(page); + iov_iter_xarray(&req->def_iter, READ, &page->mapping->i_pages, + req->pos, req->len); + req->iter = &req->def_iter; - /* read the contents of the file from the server into the - * page */ ret = afs_fetch_data(vnode, req); - afs_put_read(req); - - if (ret < 0) { - if (ret == -ENOENT) { - _debug("got NOENT from server" - " - marking file deleted and stale"); - set_bit(AFS_VNODE_DELETED, &vnode->flags); - ret = -ESTALE; - } - - if (ret == -EINTR || - ret == -ENOMEM || - ret == -ERESTARTSYS || - ret == -EAGAIN) - goto error; - goto io_error; - } - - SetPageUptodate(page); - unlock_page(page); + if (ret < 0) + goto fetch_error; + afs_put_read(req); _leave(" = 0"); return 0; -io_error: - SetPageError(page); - goto error; +fetch_error: + switch (ret) { + case -EINTR: + case -ENOMEM: + case -ERESTARTSYS: + case -EAGAIN: + afs_put_read(req); + goto error; + case -ENOENT: + _debug("got NOENT from server - marking file deleted and stale"); + set_bit(AFS_VNODE_DELETED, &vnode->flags); + ret = -ESTALE; + /* Fall through */ + default: + page_endio(page, false, ret); + afs_put_read(req); + _leave(" = %d", ret); + return ret; + } + enomem: ret = -ENOMEM; error: @@ -365,19 +415,6 @@ static int afs_readpage(struct file *file, struct page *page) return ret; } -/* - * Make pages available as they're filled. - */ -static void afs_readpages_page_done(struct afs_read *req) -{ - struct page *page = req->pages[req->index]; - - req->pages[req->index] = NULL; - SetPageUptodate(page); - unlock_page(page); - put_page(page); -} - /* * Read a contiguous set of pages. */ @@ -389,7 +426,7 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, struct list_head *p; struct page *first, *page; pgoff_t index; - int ret, n, i; + int ret, n; /* Count the number of contiguous pages at the front of the list. Note * that the list goes prev-wards rather than next-wards. @@ -405,21 +442,20 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, n++; } - req = kzalloc(struct_size(req, array, n), GFP_NOFS); + req = kzalloc(sizeof(struct afs_read), GFP_NOFS); if (!req) return -ENOMEM; refcount_set(&req->usage, 1); req->vnode = vnode; req->key = key_get(afs_file_key(file)); - req->page_done = afs_readpages_page_done; + req->done = afs_file_read_done; + req->cleanup = afs_file_read_cleanup; req->pos = first->index; req->pos <<= PAGE_SHIFT; - req->pages = req->array; - /* Transfer the pages to the request. We add them in until one fails - * to add to the LRU and then we stop (as that'll make a hole in the - * contiguous run. + /* Add pages to the LRU until it fails. We keep the pages ref'd and + * locked until the read is complete. * * Note that it's possible for the file size to change whilst we're * doing this, but we rely on the server returning less than we asked @@ -436,8 +472,7 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, break; } - req->pages[req->nr_pages++] = page; - req->len += PAGE_SIZE; + req->nr_pages++; } while (req->nr_pages < n); if (req->nr_pages == 0) { @@ -445,30 +480,25 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, return 0; } + req->len = req->nr_pages * PAGE_SIZE; + iov_iter_xarray(&req->def_iter, READ, &file->f_mapping->i_pages, + req->pos, req->len); + req->iter = &req->def_iter; + ret = afs_fetch_data(vnode, req); if (ret < 0) goto error; - task_io_account_read(PAGE_SIZE * req->nr_pages); afs_put_read(req); return 0; error: if (ret == -ENOENT) { - _debug("got NOENT from server" - " - marking file deleted and stale"); + _debug("got NOENT from server - marking file deleted and stale"); set_bit(AFS_VNODE_DELETED, &vnode->flags); ret = -ESTALE; } - for (i = 0; i < req->nr_pages; i++) { - page = req->pages[i]; - if (page) { - SetPageError(page); - unlock_page(page); - } - } - afs_put_read(req); return ret; } diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 4a57c6c6f12b..897b37301851 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -302,7 +302,6 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) struct afs_vnode_param *vp = &op->file[0]; struct afs_read *req = op->fetch.req; const __be32 *bp; - unsigned int size; int ret; _enter("{%u,%zu,%zu/%llu}", @@ -312,8 +311,6 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) switch (call->unmarshall) { case 0: req->actual_len = 0; - req->index = 0; - req->offset = req->pos & (PAGE_SIZE - 1); call->unmarshall++; if (call->operation_ID == FSFETCHDATA64) { afs_extract_to_tmp64(call); @@ -323,7 +320,10 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) } fallthrough; - /* extract the returned data length */ + /* Extract the returned data length into + * ->actual_len. This may indicate more or less data than was + * requested will be returned. + */ case 1: _debug("extract data length"); ret = afs_extract_data(call, true); @@ -332,45 +332,25 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) req->actual_len = be64_to_cpu(call->tmp64); _debug("DATA length: %llu", req->actual_len); - req->remain = min(req->len, req->actual_len); - if (req->remain == 0) + + if (req->actual_len == 0) goto no_more_data; + call->iter = req->iter; + call->iov_len = min(req->actual_len, req->len); call->unmarshall++; - - begin_page: - ASSERTCMP(req->index, <, req->nr_pages); - if (req->remain > PAGE_SIZE - req->offset) - size = PAGE_SIZE - req->offset; - else - size = req->remain; - call->iov_len = size; - call->bvec[0].bv_len = size; - call->bvec[0].bv_offset = req->offset; - call->bvec[0].bv_page = req->pages[req->index]; - iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); - ASSERTCMP(size, <=, PAGE_SIZE); fallthrough; /* extract the returned data */ case 2: _debug("extract data %zu/%llu", - iov_iter_count(call->iter), req->remain); + iov_iter_count(call->iter), req->actual_len); ret = afs_extract_data(call, true); if (ret < 0) return ret; - req->remain -= call->bvec[0].bv_len; - req->offset += call->bvec[0].bv_len; - ASSERTCMP(req->offset, <=, PAGE_SIZE); - if (req->offset == PAGE_SIZE) { - req->offset = 0; - req->index++; - if (req->remain > 0) - goto begin_page; - } - ASSERTCMP(req->remain, ==, 0); + call->iter = &call->def_iter; if (req->actual_len <= req->len) goto no_more_data; @@ -412,16 +392,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) break; } - for (; req->index < req->nr_pages; req->index++) { - if (req->offset < PAGE_SIZE) - zero_user_segment(req->pages[req->index], - req->offset, PAGE_SIZE); - req->offset = 0; - } - - if (req->page_done) - for (req->index = 0; req->index < req->nr_pages; req->index++) - req->page_done(req); + if (req->done) + req->done(req); _leave(" = 0 [done]"); return 0; @@ -496,6 +468,8 @@ void afs_fs_fetch_data(struct afs_operation *op) if (!call) return afs_op_nomem(op); + req->call_debug_id = call->debug_id; + /* marshall the parameters */ bp = call->request; bp[0] = htonl(FSFETCHDATA); diff --git a/fs/afs/internal.h b/fs/afs/internal.h index ea5b780518c7..a643d87315ed 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -31,6 +31,7 @@ struct pagevec; struct afs_call; +struct afs_vnode; /* * Partial file-locking emulation mode. (The problem being that AFS3 only @@ -203,18 +204,18 @@ struct afs_read { loff_t pos; /* Where to start reading */ loff_t len; /* How much we're asking for */ loff_t actual_len; /* How much we're actually getting */ - loff_t remain; /* Amount remaining */ loff_t file_size; /* File size returned by server */ struct key *key; /* The key to use to reissue the read */ + struct afs_vnode *vnode; /* The file being read into. */ afs_dataversion_t data_version; /* Version number returned by server */ refcount_t usage; - unsigned int index; /* Which page we're reading into */ + unsigned int call_debug_id; unsigned int nr_pages; - unsigned int offset; /* offset into current page */ - struct afs_vnode *vnode; - void (*page_done)(struct afs_read *); - struct page **pages; - struct page *array[]; + int error; + void (*done)(struct afs_read *); + void (*cleanup)(struct afs_read *); + struct iov_iter *iter; /* Iterator representing the buffer */ + struct iov_iter def_iter; /* Default iterator */ }; /* @@ -1040,7 +1041,6 @@ extern void afs_put_wb_key(struct afs_wb_key *); extern int afs_open(struct inode *, struct file *); extern int afs_release(struct inode *, struct file *); extern int afs_fetch_data(struct afs_vnode *, struct afs_read *); -extern int afs_page_filler(void *, struct page *); extern void afs_put_read(struct afs_read *); static inline struct afs_read *afs_get_read(struct afs_read *req) diff --git a/fs/afs/write.c b/fs/afs/write.c index 7eba0d3201ba..e78a9bc3b02d 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -22,6 +22,16 @@ int afs_set_page_dirty(struct page *page) return __set_page_dirty_nobuffers(page); } +/* + * Handle completion of a read operation to fill a page. + */ +static void afs_fill_hole(struct afs_read *req) +{ + if (iov_iter_count(req->iter) > 0) + /* The read was short - clear the excess buffer. */ + iov_iter_zero(iov_iter_count(req->iter), req->iter); +} + /* * partly or wholly fill a page that's under preparation for writing */ @@ -45,18 +55,19 @@ static int afs_fill_page(struct file *file, return 0; } - req = kzalloc(struct_size(req, array, 1), GFP_KERNEL); + req = kzalloc(sizeof(struct afs_read), GFP_KERNEL); if (!req) return -ENOMEM; refcount_set(&req->usage, 1); - req->key = key_get(afs_file_key(file)); - req->pos = pos; - req->len = len; - req->nr_pages = 1; - req->pages = req->array; - req->pages[0] = page; - get_page(page); + req->vnode = vnode; + req->done = afs_fill_hole; + req->key = key_get(afs_file_key(file)); + req->pos = pos; + req->len = len; + req->nr_pages = 1; + req->iter = &req->def_iter; + iov_iter_xarray(&req->def_iter, READ, &file->f_mapping->i_pages, pos, len); ret = afs_fetch_data(vnode, req); afs_put_read(req); diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c index 6c45d32da13c..abcec145db4b 100644 --- a/fs/afs/yfsclient.c +++ b/fs/afs/yfsclient.c @@ -360,7 +360,6 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) struct afs_vnode_param *vp = &op->file[0]; struct afs_read *req = op->fetch.req; const __be32 *bp; - unsigned int size; int ret; _enter("{%u,%zu, %zu/%llu}", @@ -370,13 +369,14 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) switch (call->unmarshall) { case 0: req->actual_len = 0; - req->index = 0; - req->offset = req->pos & (PAGE_SIZE - 1); afs_extract_to_tmp64(call); call->unmarshall++; fallthrough; - /* extract the returned data length */ + /* Extract the returned data length into ->actual_len. This + * may indicate more or less data than was requested will be + * returned. + */ case 1: _debug("extract data length"); ret = afs_extract_data(call, true); @@ -385,45 +385,25 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) req->actual_len = be64_to_cpu(call->tmp64); _debug("DATA length: %llu", req->actual_len); - req->remain = min(req->len, req->actual_len); - if (req->remain == 0) + + if (req->actual_len == 0) goto no_more_data; + call->iter = req->iter; + call->iov_len = min(req->actual_len, req->len); call->unmarshall++; - - begin_page: - ASSERTCMP(req->index, <, req->nr_pages); - if (req->remain > PAGE_SIZE - req->offset) - size = PAGE_SIZE - req->offset; - else - size = req->remain; - call->iov_len = size; - call->bvec[0].bv_len = size; - call->bvec[0].bv_offset = req->offset; - call->bvec[0].bv_page = req->pages[req->index]; - iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); - ASSERTCMP(size, <=, PAGE_SIZE); fallthrough; /* extract the returned data */ case 2: _debug("extract data %zu/%llu", - iov_iter_count(call->iter), req->remain); + iov_iter_count(call->iter), req->actual_len); ret = afs_extract_data(call, true); if (ret < 0) return ret; - req->remain -= call->bvec[0].bv_len; - req->offset += call->bvec[0].bv_len; - ASSERTCMP(req->offset, <=, PAGE_SIZE); - if (req->offset == PAGE_SIZE) { - req->offset = 0; - req->index++; - if (req->remain > 0) - goto begin_page; - } - ASSERTCMP(req->remain, ==, 0); + call->iter = &call->def_iter; if (req->actual_len <= req->len) goto no_more_data; @@ -469,16 +449,8 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) break; } - for (; req->index < req->nr_pages; req->index++) { - if (req->offset < PAGE_SIZE) - zero_user_segment(req->pages[req->index], - req->offset, PAGE_SIZE); - req->offset = 0; - } - - if (req->page_done) - for (req->index = 0; req->index < req->nr_pages; req->index++) - req->page_done(req); + if (req->done) + req->done(req); _leave(" = 0 [done]"); return 0; @@ -518,6 +490,8 @@ void yfs_fs_fetch_data(struct afs_operation *op) if (!call) return afs_op_nomem(op); + req->call_debug_id = call->debug_id; + /* marshall the parameters */ bp = call->request; bp = xdr_encode_u32(bp, YFSFETCHDATA64); From patchwork Fri Nov 20 15:16:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329201 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ACF4DC8300C for ; Fri, 20 Nov 2020 15:16:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4D69C22272 for ; Fri, 20 Nov 2020 15:16:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="C9AZ9YPO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729456AbgKTPQ2 (ORCPT ); Fri, 20 Nov 2020 10:16:28 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:33509 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728778AbgKTPQ1 (ORCPT ); Fri, 20 Nov 2020 10:16:27 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885386; 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=kklQjGV+n4wPbbtZKYuh9y38W/ahSgqyUfhBizGSNXs=; b=C9AZ9YPO+CY5+S6YdF6i3XlzJmR0ortd3lE/HIoC/fNkGh+LPW+WGrRUBnNwPdCvm7lulX 3jUzE7PYuzUffORz5o/bPAJRtbFbN/GXrDiw8NIrWMe+mvQoj8An65liSJBNbhljvsYUBQ FAsgcvIeTGUxxtXOYdXVZ2bR+xco57w= 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-324-BjLZKzX4Mr2wya366Ikp4w-1; Fri, 20 Nov 2020 10:16:21 -0500 X-MC-Unique: BjLZKzX4Mr2wya366Ikp4w-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 77912107AD32; Fri, 20 Nov 2020 15:16:19 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id B515919D80; Fri, 20 Nov 2020 15:16:03 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 63/76] afs: Wait on PG_fscache before modifying/releasing a page From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:16:02 +0000 Message-ID: <160588536286.3465195.13231895135369807920.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org PG_fscache is going to be used to indicate that a page is being written to the cache, and that the page should not be modified or released until it's finished. Make afs_invalidatepage() and afs_releasepage() wait for it. Signed-off-by: David Howells --- fs/afs/file.c | 9 +++++++++ fs/afs/write.c | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/fs/afs/file.c b/fs/afs/file.c index 3f409ddc1c1f..a6c6cc9b1d1c 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -607,6 +607,7 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, if (PagePrivate(page)) afs_invalidate_dirty(page, offset, length); + wait_on_page_fscache(page); _leave(""); } @@ -624,6 +625,14 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) /* deny if page is being written to the cache and the caller hasn't * elected to wait */ +#ifdef CONFIG_AFS_FSCACHE + if (PageFsCache(page)) { + if (!(gfp_flags & __GFP_DIRECT_RECLAIM) || !(gfp_flags & __GFP_FS)) + return false; + wait_on_page_fscache(page); + } +#endif + if (PagePrivate(page)) { detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("rel"), page); diff --git a/fs/afs/write.c b/fs/afs/write.c index dd4dc1c868b5..e1791de90478 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -117,6 +117,10 @@ int afs_write_begin(struct file *file, struct address_space *mapping, SetPageUptodate(page); } +#ifdef CONFIG_AFS_FSCACHE + wait_on_page_fscache(page); +#endif + try_again: /* See if this page is already partially written in a way that we can * merge the new write with. @@ -857,6 +861,11 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) /* Wait for the page to be written to the cache before we allow it to * be modified. We then assume the entire page will need writing back. */ +#ifdef CONFIG_AFS_FSCACHE + if (PageFsCache(vmf->page) && + wait_on_page_bit_killable(vmf->page, PG_fscache) < 0) + return VM_FAULT_RETRY; +#endif if (PageWriteback(vmf->page) && wait_on_page_bit_killable(vmf->page, PG_writeback) < 0) @@ -948,5 +957,6 @@ int afs_launder_page(struct page *page) detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("laundered"), page); + wait_on_page_fscache(page); return ret; } From patchwork Fri Nov 20 15:16:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329200 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B46DC5519F for ; Fri, 20 Nov 2020 15:18:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E3F12222F for ; Fri, 20 Nov 2020 15:18:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dRNfpSVM" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729519AbgKTPQ7 (ORCPT ); Fri, 20 Nov 2020 10:16:59 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:50986 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729201AbgKTPQ5 (ORCPT ); Fri, 20 Nov 2020 10:16:57 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885414; 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=CM375nfwMS5RJa9MUuO5xh4lxRYQ9afg9IYsZdlP/GQ=; b=dRNfpSVMcPwMZRMRKyzPbwQmghIeVs3O26xN8KWAZk3luMhEwkJFihyf9MLrXBUn98lLVl 25E2XquKBEywqC3TqsUkxDNyjQNe9DE2X4V9eVReQhhmu3SAF9GbfPqb/qSo3MQTJ1Q74E rvQlOqLDL0oWflPovYkgNQYGIIXhWeA= 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-63-6LdEah2mM5Odf4r1XaOaXg-1; Fri, 20 Nov 2020 10:16:52 -0500 X-MC-Unique: 6LdEah2mM5Odf4r1XaOaXg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 76AC18799F8; Fri, 20 Nov 2020 15:16:49 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 25999100AE2C; Fri, 20 Nov 2020 15:16:42 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 65/76] afs: Prepare for use of THPs From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:16:42 +0000 Message-ID: <160588540227.3465195.4752143929716269062.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org As a prelude to supporting transparent huge pages, use thp_size() and similar rather than PAGE_SIZE/SHIFT. Further, try and frame everything in terms of file positions and lengths rather than page indices and numbers of pages. Signed-off-by: David Howells --- fs/afs/dir.c | 2 fs/afs/file.c | 8 - fs/afs/internal.h | 2 fs/afs/write.c | 436 +++++++++++++++++++++++++++++------------------------ 4 files changed, 245 insertions(+), 203 deletions(-) diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 215f73121391..26ac5cfdf3af 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -2078,6 +2078,6 @@ static void afs_dir_invalidatepage(struct page *page, unsigned int offset, afs_stat_v(dvnode, n_inval); /* we clean up only if the entire page is being invalidated */ - if (offset == 0 && length == PAGE_SIZE) + if (offset == 0 && length == thp_size(page)) detach_page_private(page); } diff --git a/fs/afs/file.c b/fs/afs/file.c index a6c6cc9b1d1c..b4a78afad643 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -343,8 +343,8 @@ static int afs_page_filler(struct key *key, struct page *page) req->vnode = vnode; req->key = key_get(key); req->pos = (loff_t)page->index << PAGE_SHIFT; - req->len = PAGE_SIZE; - req->nr_pages = 1; + req->len = thp_size(page); + req->nr_pages = thp_nr_pages(page); req->done = afs_file_read_done; req->cleanup = afs_file_read_cleanup; @@ -588,8 +588,8 @@ static void afs_invalidate_dirty(struct page *page, unsigned int offset, trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page); clear_page_dirty_for_io(page); full_invalidate: - detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("inval"), page); + detach_page_private(page); } /* @@ -634,8 +634,8 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) #endif if (PagePrivate(page)) { - detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("rel"), page); + detach_page_private(page); } /* indicate that the page can be released */ diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 3556500a1247..ce1f05d5c94b 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -814,8 +814,6 @@ struct afs_operation { loff_t pos; loff_t size; loff_t i_size; - pgoff_t first; /* first page in mapping to deal with */ - pgoff_t last; /* last page in mapping to deal with */ bool laundering; /* Laundering page, PG_writeback not set */ } store; struct { diff --git a/fs/afs/write.c b/fs/afs/write.c index 89c804bfe253..e672833c99bc 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -94,15 +94,15 @@ int afs_write_begin(struct file *file, struct address_space *mapping, struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); struct page *page; unsigned long priv; - unsigned f, from = pos & (PAGE_SIZE - 1); - unsigned t, to = from + len; - pgoff_t index = pos >> PAGE_SHIFT; + unsigned f, from; + unsigned t, to; + pgoff_t index; int ret; - _enter("{%llx:%llu},{%lx},%u,%u", - vnode->fid.vid, vnode->fid.vnode, index, from, to); + _enter("{%llx:%llu},%llx,%x", + vnode->fid.vid, vnode->fid.vnode, pos, len); - page = grab_cache_page_write_begin(mapping, index, flags); + page = grab_cache_page_write_begin(mapping, pos / PAGE_SIZE, flags); if (!page) return -ENOMEM; @@ -121,19 +121,20 @@ int afs_write_begin(struct file *file, struct address_space *mapping, wait_on_page_fscache(page); #endif + index = page->index; + from = pos - index * PAGE_SIZE; + to = from + len; + try_again: /* See if this page is already partially written in a way that we can * merge the new write with. */ - t = f = 0; if (PagePrivate(page)) { priv = page_private(page); f = afs_page_dirty_from(page, priv); t = afs_page_dirty_to(page, priv); ASSERTCMP(f, <=, t); - } - if (f != t) { if (PageWriteback(page)) { trace_afs_page_dirty(vnode, tracepoint_string("alrdy"), page); goto flush_conflicting_write; @@ -180,7 +181,7 @@ int afs_write_end(struct file *file, struct address_space *mapping, { struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); unsigned long priv; - unsigned int f, from = pos & (PAGE_SIZE - 1); + unsigned int f, from = pos & (thp_size(page) - 1); unsigned int t, to = from + copied; loff_t i_size, maybe_i_size; int ret = 0; @@ -233,9 +234,8 @@ int afs_write_end(struct file *file, struct address_space *mapping, trace_afs_page_dirty(vnode, tracepoint_string("dirty"), page); } - set_page_dirty(page); - if (PageDirty(page)) - _debug("dirtied"); + if (set_page_dirty(page)) + _debug("dirtied %lx", page->index); ret = copied; out: @@ -248,40 +248,43 @@ int afs_write_end(struct file *file, struct address_space *mapping, * kill all the pages in the given range */ static void afs_kill_pages(struct address_space *mapping, - pgoff_t first, pgoff_t last) + loff_t start, loff_t len) { struct afs_vnode *vnode = AFS_FS_I(mapping->host); struct pagevec pv; - unsigned count, loop; + unsigned int loop, psize; - _enter("{%llx:%llu},%lx-%lx", - vnode->fid.vid, vnode->fid.vnode, first, last); + _enter("{%llx:%llu},%llx @%llx", + vnode->fid.vid, vnode->fid.vnode, len, start); pagevec_init(&pv); do { - _debug("kill %lx-%lx", first, last); + _debug("kill %llx @%llx", len, start); - count = last - first + 1; - if (count > PAGEVEC_SIZE) - count = PAGEVEC_SIZE; - pv.nr = find_get_pages_contig(mapping, first, count, pv.pages); - ASSERTCMP(pv.nr, ==, count); + pv.nr = find_get_pages_contig(mapping, start / PAGE_SIZE, + PAGEVEC_SIZE, pv.pages); + if (pv.nr == 0) + break; - for (loop = 0; loop < count; loop++) { + for (loop = 0; loop < pv.nr; loop++) { struct page *page = pv.pages[loop]; + + if (page->index * PAGE_SIZE >= start + len) + break; + + psize = thp_size(page); + start += psize; + len -= psize; ClearPageUptodate(page); - SetPageError(page); end_page_writeback(page); - if (page->index >= first) - first = page->index + 1; lock_page(page); generic_error_remove_page(mapping, page); unlock_page(page); } __pagevec_release(&pv); - } while (first <= last); + } while (len > 0); _leave(""); } @@ -291,37 +294,40 @@ static void afs_kill_pages(struct address_space *mapping, */ static void afs_redirty_pages(struct writeback_control *wbc, struct address_space *mapping, - pgoff_t first, pgoff_t last) + loff_t start, loff_t len) { struct afs_vnode *vnode = AFS_FS_I(mapping->host); struct pagevec pv; - unsigned count, loop; + unsigned int loop, psize; - _enter("{%llx:%llu},%lx-%lx", - vnode->fid.vid, vnode->fid.vnode, first, last); + _enter("{%llx:%llu},%llx @%llx", + vnode->fid.vid, vnode->fid.vnode, len, start); pagevec_init(&pv); do { - _debug("redirty %lx-%lx", first, last); + _debug("redirty %llx @%llx", len, start); - count = last - first + 1; - if (count > PAGEVEC_SIZE) - count = PAGEVEC_SIZE; - pv.nr = find_get_pages_contig(mapping, first, count, pv.pages); - ASSERTCMP(pv.nr, ==, count); + pv.nr = find_get_pages_contig(mapping, start / PAGE_SIZE, + PAGEVEC_SIZE, pv.pages); + if (pv.nr == 0) + break; - for (loop = 0; loop < count; loop++) { + for (loop = 0; loop < pv.nr; loop++) { struct page *page = pv.pages[loop]; + if (page->index * PAGE_SIZE >= start + len) + break; + + psize = thp_size(page); + start += psize; + len -= psize; redirty_page_for_writepage(wbc, page); end_page_writeback(page); - if (page->index >= first) - first = page->index + 1; } __pagevec_release(&pv); - } while (first <= last); + } while (len > 0); _leave(""); } @@ -329,23 +335,28 @@ static void afs_redirty_pages(struct writeback_control *wbc, /* * completion of write to server */ -static void afs_pages_written_back(struct afs_vnode *vnode, pgoff_t start, pgoff_t last) +static void afs_pages_written_back(struct afs_vnode *vnode, loff_t start, unsigned int len) { struct address_space *mapping = vnode->vfs_inode.i_mapping; struct page *page; + pgoff_t end; - XA_STATE(xas, &mapping->i_pages, start); + XA_STATE(xas, &mapping->i_pages, start / PAGE_SIZE); - _enter("{%llx:%llu},{%lx-%lx}", - vnode->fid.vid, vnode->fid.vnode, start, last); + _enter("{%llx:%llu},{%x @%llx}", + vnode->fid.vid, vnode->fid.vnode, len, start); rcu_read_lock(); - xas_for_each(&xas, page, last) { - ASSERT(PageWriteback(page)); + end = (start + len - 1) / PAGE_SIZE; + xas_for_each(&xas, page, end) { + if (!PageWriteback(page)) { + kdebug("bad %x @%llx page %lx %lx", len, start, page->index, end); + ASSERT(PageWriteback(page)); + } - detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("clear"), page); + detach_page_private(page); page_endio(page, true, 0); } @@ -404,7 +415,7 @@ static void afs_store_data_success(struct afs_operation *op) afs_vnode_commit_status(op, &op->file[0]); if (op->error == 0) { if (!op->store.laundering) - afs_pages_written_back(vnode, op->store.first, op->store.last); + afs_pages_written_back(vnode, op->store.pos, op->store.size); afs_stat_v(vnode, n_stores); atomic_long_add(op->store.size, &afs_v2net(vnode)->n_store_bytes); } @@ -419,8 +430,7 @@ static const struct afs_operation_ops afs_store_data_operation = { /* * write to a file */ -static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, - loff_t pos, pgoff_t first, pgoff_t last, +static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t pos, bool laundering) { struct afs_operation *op; @@ -453,8 +463,6 @@ static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, op->file[0].dv_delta = 1; op->store.write_iter = iter; op->store.pos = pos; - op->store.first = first; - op->store.last = last; op->store.size = size; op->store.i_size = max(pos + size, i_size); op->store.laundering = laundering; @@ -499,40 +507,49 @@ static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, static void afs_extend_writeback(struct address_space *mapping, struct afs_vnode *vnode, long *_count, - pgoff_t start, - pgoff_t final_page, - unsigned *_offset, - unsigned *_to, - bool new_content) + loff_t start, + loff_t max_len, + bool new_content, + unsigned int *_len) { - struct page *pages[8], *page; - unsigned long count = *_count, priv; - unsigned offset = *_offset, to = *_to, n, f, t; - int loop; + struct pagevec pvec; + struct page *page; + unsigned long priv; + unsigned int psize, filler = 0; + unsigned int f, t; + loff_t len = *_len; + pgoff_t index = (start + len) / PAGE_SIZE; + bool stop = true; + unsigned int i; + + XA_STATE(xas, &mapping->i_pages, index); + pagevec_init(&pvec); - start++; do { - _debug("more %lx [%lx]", start, count); - n = final_page - start + 1; - if (n > ARRAY_SIZE(pages)) - n = ARRAY_SIZE(pages); - n = find_get_pages_contig(mapping, start, ARRAY_SIZE(pages), pages); - _debug("fgpc %u", n); - if (n == 0) - goto no_more; - if (pages[0]->index != start) { - do { - put_page(pages[--n]); - } while (n > 0); - goto no_more; - } + /* Firstly, we gather up a batch of contiguous dirty pages + * under the RCU read lock - but we can't clear the dirty flags + * there if any of those pages are mapped. + */ + rcu_read_lock(); - for (loop = 0; loop < n; loop++) { - page = pages[loop]; - if (to != PAGE_SIZE && !new_content) + xas_for_each(&xas, page, ULONG_MAX) { + stop = true; + if (xas_retry(&xas, page)) + continue; + if (xa_is_value(page)) + break; + if (page->index != index) break; - if (page->index > final_page) + + if (!page_cache_get_speculative(page)) { + xas_reset(&xas); + continue; + } + + /* Has the page moved or been split? */ + if (unlikely(page != xas_reload(&xas))) break; + if (!trylock_page(page)) break; if (!PageDirty(page) || PageWriteback(page)) { @@ -540,6 +557,7 @@ static void afs_extend_writeback(struct address_space *mapping, break; } + psize = thp_size(page); priv = page_private(page); f = afs_page_dirty_from(page, priv); t = afs_page_dirty_to(page, priv); @@ -547,110 +565,126 @@ static void afs_extend_writeback(struct address_space *mapping, unlock_page(page); break; } - to = t; + len += filler + t; + filler = psize - t; + if (len >= max_len || *_count <= 0) + stop = true; + else if (t == psize || new_content) + stop = false; + + index += thp_nr_pages(page); + if (!pagevec_add(&pvec, page)) + break; + if (stop) + break; + } + + if (!stop) + xas_pause(&xas); + rcu_read_unlock(); + + /* Now, if we obtained any pages, we can shift them to being + * writable and mark them for caching. + */ + if (!pagevec_count(&pvec)) + break; + + for (i = 0; i < pagevec_count(&pvec); i++) { + page = pvec.pages[i]; trace_afs_page_dirty(vnode, tracepoint_string("store+"), page); if (!clear_page_dirty_for_io(page)) BUG(); if (test_set_page_writeback(page)) BUG(); + + *_count -= thp_nr_pages(page); unlock_page(page); - put_page(page); - } - count += loop; - if (loop < n) { - for (; loop < n; loop++) - put_page(pages[loop]); - goto no_more; } - start += loop; - } while (start <= final_page && count < 65536); + pagevec_release(&pvec); + cond_resched(); + } while (!stop); -no_more: - *_count = count; - *_offset = offset; - *_to = to; + *_len = len; } /* * Synchronously write back the locked page and any subsequent non-locked dirty * pages. */ -static int afs_write_back_from_locked_page(struct address_space *mapping, - struct writeback_control *wbc, - struct page *primary_page, - pgoff_t final_page) +static ssize_t afs_write_back_from_locked_page(struct address_space *mapping, + struct writeback_control *wbc, + struct page *page, + loff_t start, loff_t end) { struct afs_vnode *vnode = AFS_FS_I(mapping->host); struct iov_iter iter; - unsigned long count, priv; - unsigned offset, to; - pgoff_t start, first, last; - loff_t i_size, pos, end; + unsigned long priv; + unsigned int offset, to, len, max_len; + loff_t i_size = i_size_read(&vnode->vfs_inode); bool new_content = test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); + long count = wbc->nr_to_write; int ret; - _enter(",%lx", primary_page->index); + _enter(",%lx,%llx-%llx", page->index, start, end); - count = 1; - if (test_set_page_writeback(primary_page)) + if (test_set_page_writeback(page)) BUG(); + count -= thp_nr_pages(page); + /* Find all consecutive lockable dirty pages that have contiguous * written regions, stopping when we find a page that is not * immediately lockable, is not dirty or is missing, or we reach the * end of the range. */ - start = primary_page->index; - priv = page_private(primary_page); - offset = afs_page_dirty_from(primary_page, priv); - to = afs_page_dirty_to(primary_page, priv); - trace_afs_page_dirty(vnode, tracepoint_string("store"), primary_page); - - WARN_ON(offset == to); - if (offset == to) - trace_afs_page_dirty(vnode, tracepoint_string("WARN"), primary_page); - - if (start < final_page && - (to == PAGE_SIZE || new_content)) - afs_extend_writeback(mapping, vnode, &count, start, final_page, - &offset, &to, new_content); + priv = page_private(page); + offset = afs_page_dirty_from(page, priv); + to = afs_page_dirty_to(page, priv); + trace_afs_page_dirty(vnode, tracepoint_string("store"), page); + + len = to - offset; + start += offset; + if (start < i_size) { + /* Trim the write to the EOF; the extra data is ignored. Also + * put an upper limit on the size of a single storedata op. + */ + max_len = 65536 * 4096; + max_len = min_t(unsigned long long, max_len, end - start + 1); + max_len = min_t(unsigned long long, max_len, i_size - start); + + if (len < max_len && + (to == thp_size(page) || new_content)) + afs_extend_writeback(mapping, vnode, &count, + start, max_len, new_content, &len); + len = min_t(loff_t, len, max_len); + } /* We now have a contiguous set of dirty pages, each with writeback * set; the first page is still locked at this point, but all the rest * have been unlocked. */ - unlock_page(primary_page); - - first = primary_page->index; - last = first + count - 1; - _debug("write back %lx[%u..] to %lx[..%u]", first, offset, last, to); - - pos = first; - pos <<= PAGE_SHIFT; - pos += offset; - end = last; - end <<= PAGE_SHIFT; - end += to; + unlock_page(page); - /* Trim the actual write down to the EOF */ - i_size = i_size_read(&vnode->vfs_inode); - if (end > i_size) - end = i_size; + if (start < i_size) { + _debug("write back %x @%llx [%llx]", len, start, i_size); - if (pos < i_size) { - iov_iter_xarray(&iter, WRITE, &mapping->i_pages, pos, end - pos); - ret = afs_store_data(vnode, &iter, pos, first, last, false); + iov_iter_xarray(&iter, WRITE, &mapping->i_pages, start, len); + ret = afs_store_data(vnode, &iter, start, false); } else { + _debug("write discard %x @%llx [%llx]", len, start, i_size); + /* The dirty region was entirely beyond the EOF. */ + afs_pages_written_back(vnode, start, len); ret = 0; } switch (ret) { case 0: - ret = count; + wbc->nr_to_write = count; + ret = len; break; default: @@ -662,13 +696,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, case -EKEYEXPIRED: case -EKEYREJECTED: case -EKEYREVOKED: - afs_redirty_pages(wbc, mapping, first, last); + afs_redirty_pages(wbc, mapping, start, len); mapping_set_error(mapping, ret); break; case -EDQUOT: case -ENOSPC: - afs_redirty_pages(wbc, mapping, first, last); + afs_redirty_pages(wbc, mapping, start, len); mapping_set_error(mapping, -ENOSPC); break; @@ -680,7 +714,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, case -ENOMEDIUM: case -ENXIO: trace_afs_file_error(vnode, ret, afs_file_error_writeback_fail); - afs_kill_pages(mapping, first, last); + afs_kill_pages(mapping, start, len); mapping_set_error(mapping, ret); break; } @@ -695,19 +729,19 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, */ int afs_writepage(struct page *page, struct writeback_control *wbc) { - int ret; + ssize_t ret; + loff_t start; _enter("{%lx},", page->index); + start = page->index * PAGE_SIZE; ret = afs_write_back_from_locked_page(page->mapping, wbc, page, - wbc->range_end >> PAGE_SHIFT); + start, LLONG_MAX - start); if (ret < 0) { - _leave(" = %d", ret); - return 0; + _leave(" = %zd", ret); + return ret; } - wbc->nr_to_write -= ret; - _leave(" = 0"); return 0; } @@ -717,35 +751,46 @@ int afs_writepage(struct page *page, struct writeback_control *wbc) */ static int afs_writepages_region(struct address_space *mapping, struct writeback_control *wbc, - pgoff_t index, pgoff_t end, pgoff_t *_next) + loff_t start, loff_t end, loff_t *_next) { struct page *page; - int ret, n; + ssize_t ret; + int n; - _enter(",,%lx,%lx,", index, end); + _enter("%llx,%llx,", start, end); do { - n = find_get_pages_range_tag(mapping, &index, end, - PAGECACHE_TAG_DIRTY, 1, &page); + pgoff_t index = start / PAGE_SIZE; + + n = find_get_pages_range_tag(mapping, &index, end / PAGE_SIZE, + PAGECACHE_TAG_DIRTY, 1, &page); if (!n) break; + start = (loff_t)page->index * PAGE_SIZE; /* May regress with THPs */ + _debug("wback %lx", page->index); - /* - * at this point we hold neither the i_pages lock nor the + /* At this point we hold neither the i_pages lock nor the * page lock: the page may be truncated or invalidated * (changing page->mapping to NULL), or even swizzled * back from swapper_space to tmpfs file mapping */ - ret = lock_page_killable(page); - if (ret < 0) { - put_page(page); - _leave(" = %d", ret); - return ret; + if (wbc->sync_mode != WB_SYNC_NONE) { + ret = lock_page_killable(page); + if (ret < 0) { + put_page(page); + return ret; + } + } else { + if (!trylock_page(page)) { + put_page(page); + return 0; + } } if (page->mapping != mapping || !PageDirty(page)) { + start += thp_size(page); unlock_page(page); put_page(page); continue; @@ -761,20 +806,20 @@ static int afs_writepages_region(struct address_space *mapping, if (!clear_page_dirty_for_io(page)) BUG(); - ret = afs_write_back_from_locked_page(mapping, wbc, page, end); + ret = afs_write_back_from_locked_page(mapping, wbc, page, start, end); put_page(page); if (ret < 0) { - _leave(" = %d", ret); + _leave(" = %zd", ret); return ret; } - wbc->nr_to_write -= ret; + start += ret * PAGE_SIZE; cond_resched(); - } while (index < end && wbc->nr_to_write > 0); + } while (wbc->nr_to_write > 0); - *_next = index; - _leave(" = 0 [%lx]", *_next); + *_next = start; + _leave(" = 0 [%llx]", *_next); return 0; } @@ -785,7 +830,7 @@ int afs_writepages(struct address_space *mapping, struct writeback_control *wbc) { struct afs_vnode *vnode = AFS_FS_I(mapping->host); - pgoff_t start, end, next; + loff_t start, next; int ret; _enter(""); @@ -800,22 +845,19 @@ int afs_writepages(struct address_space *mapping, return 0; if (wbc->range_cyclic) { - start = mapping->writeback_index; - end = -1; - ret = afs_writepages_region(mapping, wbc, start, end, &next); + start = mapping->writeback_index * PAGE_SIZE; + ret = afs_writepages_region(mapping, wbc, start, LLONG_MAX, &next); if (start > 0 && wbc->nr_to_write > 0 && ret == 0) ret = afs_writepages_region(mapping, wbc, 0, start, &next); - mapping->writeback_index = next; + mapping->writeback_index = next / PAGE_SIZE; } else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) { - end = (pgoff_t)(LLONG_MAX >> PAGE_SHIFT); - ret = afs_writepages_region(mapping, wbc, 0, end, &next); + ret = afs_writepages_region(mapping, wbc, 0, LLONG_MAX, &next); if (wbc->nr_to_write > 0) mapping->writeback_index = next; } else { - start = wbc->range_start >> PAGE_SHIFT; - end = wbc->range_end >> PAGE_SHIFT; - ret = afs_writepages_region(mapping, wbc, start, end, &next); + ret = afs_writepages_region(mapping, wbc, + wbc->range_start, wbc->range_end, &next); } up_read(&vnode->validate_lock); @@ -873,13 +915,13 @@ int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync) */ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) { + struct page *page = thp_head(vmf->page); struct file *file = vmf->vma->vm_file; struct inode *inode = file_inode(file); struct afs_vnode *vnode = AFS_FS_I(inode); unsigned long priv; - _enter("{{%llx:%llu}},{%lx}", - vnode->fid.vid, vnode->fid.vnode, vmf->page->index); + _enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, page->index); sb_start_pagefault(inode->i_sb); @@ -887,31 +929,33 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) * be modified. We then assume the entire page will need writing back. */ #ifdef CONFIG_AFS_FSCACHE - if (PageFsCache(vmf->page) && - wait_on_page_bit_killable(vmf->page, PG_fscache) < 0) + if (PageFsCache(page) && + wait_on_page_bit_killable(page, PG_fscache) < 0) return VM_FAULT_RETRY; #endif - if (PageWriteback(vmf->page) && - wait_on_page_bit_killable(vmf->page, PG_writeback) < 0) + if (PageWriteback(page) && + wait_on_page_bit_killable(page, PG_writeback) < 0) return VM_FAULT_RETRY; - if (lock_page_killable(vmf->page) < 0) + if (lock_page_killable(page) < 0) return VM_FAULT_RETRY; /* We mustn't change page->private until writeback is complete as that * details the portion of the page we need to write back and we might * need to redirty the page if there's a problem. */ - wait_on_page_writeback(vmf->page); + wait_on_page_writeback(page); - priv = afs_page_dirty(vmf->page, 0, PAGE_SIZE); + priv = afs_page_dirty(page, 0, thp_size(page)); priv = afs_page_dirty_mmapped(priv); - if (PagePrivate(vmf->page)) - set_page_private(vmf->page, priv); - else - attach_page_private(vmf->page, (void *)priv); - trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), vmf->page); + if (PagePrivate(page)) { + set_page_private(page, priv); + trace_afs_page_dirty(vnode, tracepoint_string("mkwrite+"), page); + } else { + attach_page_private(page, (void *)priv); + trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), page); + } file_update_time(file); sb_end_pagefault(inode->i_sb); @@ -964,7 +1008,7 @@ int afs_launder_page(struct page *page) priv = page_private(page); if (clear_page_dirty_for_io(page)) { f = 0; - t = PAGE_SIZE; + t = thp_size(page); if (PagePrivate(page)) { f = afs_page_dirty_from(page, priv); t = afs_page_dirty_to(page, priv); @@ -976,12 +1020,12 @@ int afs_launder_page(struct page *page) iov_iter_bvec(&iter, WRITE, bv, 1, bv[0].bv_len); trace_afs_page_dirty(vnode, tracepoint_string("launder"), page); - ret = afs_store_data(vnode, &iter, (loff_t)page->index << PAGE_SHIFT, - page->index, page->index, true); + ret = afs_store_data(vnode, &iter, (loff_t)page->index * PAGE_SIZE, + true); } - detach_page_private(page); trace_afs_page_dirty(vnode, tracepoint_string("laundered"), page); + detach_page_private(page); wait_on_page_fscache(page); return ret; } From patchwork Fri Nov 20 15:17:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329199 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 227A3C71155 for ; Fri, 20 Nov 2020 15:18:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB79D21D46 for ; Fri, 20 Nov 2020 15:18:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="boh/Nv65" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729541AbgKTPR0 (ORCPT ); Fri, 20 Nov 2020 10:17:26 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:33504 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729540AbgKTPRX (ORCPT ); Fri, 20 Nov 2020 10:17:23 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885440; 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=xpi/zx0WpQeJ21WaLq1opQoFrKYl78TsXTkkyqo5A6w=; b=boh/Nv65T2W6/I9M1bw9lzbu99nlO/cXQHlQHGghgKpy6h4WwXa3r/jQomEpLg+BaCisqS EnJ8zdQOyxJQxWqV1EltcL/bb4B6lMU9SQa+5m33cqwo7vt1j8CgRfYg9k7YAlWJCD//UV YuHzAkuRcIIXAspso9n+7eEHkY+uIzU= 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-260-os8OFOdINe6j3pR4x3CIFw-1; Fri, 20 Nov 2020 10:17:16 -0500 X-MC-Unique: os8OFOdINe6j3pR4x3CIFw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5BF35803631; Fri, 20 Nov 2020 15:17:14 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3679E60853; Fri, 20 Nov 2020 15:17:08 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 67/76] afs: Use new fscache read helper API From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:17:07 +0000 Message-ID: <160588542733.3465195.7526541422073350302.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Make AFS use the new fscache read helpers to implement the VM read operations: - afs_readpage() now hands off responsibility to fscache_readpage(). - afs_readpages() is gone and replaced with afs_readahead(). - afs_readahead() just hands off responsibility to fscache_readahead(). These make use of the cache if a cookie is supplied, otherwise just call the ->issue_op() method a sufficient number of times to complete the entire request. Signed-off-by: David Howells --- fs/afs/file.c | 326 +++++++++++++---------------------------------------- fs/afs/fsclient.c | 1 fs/afs/internal.h | 2 fs/afs/super.c | 24 ++++ 4 files changed, 108 insertions(+), 245 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index 38dda8990b4c..8772f5e1cbd3 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "internal.h" static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); @@ -22,8 +23,7 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, unsigned int length); static int afs_releasepage(struct page *page, gfp_t gfp_flags); -static int afs_readpages(struct file *filp, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages); +static void afs_readahead(struct readahead_control *ractl); const struct file_operations afs_file_operations = { .open = afs_open, @@ -48,7 +48,7 @@ const struct inode_operations afs_file_inode_operations = { const struct address_space_operations afs_fs_aops = { .readpage = afs_readpage, - .readpages = afs_readpages, + .readahead = afs_readahead, .set_page_dirty = afs_set_page_dirty, .launder_page = afs_launder_page, .releasepage = afs_releasepage, @@ -198,61 +198,17 @@ int afs_release(struct inode *inode, struct file *file) } /* - * Handle completion of a read operation. + * Allocate a new read record. */ -static void afs_file_read_done(struct afs_read *req) +struct afs_read *afs_alloc_read(gfp_t gfp) { - struct afs_vnode *vnode = req->vnode; - struct page *page; - pgoff_t index = req->pos >> PAGE_SHIFT; - pgoff_t last = index + req->nr_pages - 1; - - XA_STATE(xas, &vnode->vfs_inode.i_mapping->i_pages, index); - - if (iov_iter_count(req->iter) > 0) { - /* The read was short - clear the excess buffer. */ - _debug("afterclear %zx %zx %llx/%llx", - req->iter->iov_offset, - iov_iter_count(req->iter), - req->actual_len, req->len); - iov_iter_zero(iov_iter_count(req->iter), req->iter); - } - - rcu_read_lock(); - xas_for_each(&xas, page, last) { - page_endio(page, false, 0); - put_page(page); - } - rcu_read_unlock(); - - task_io_account_read(req->len); - req->cleanup = NULL; -} - -/* - * Dispose of our locks and refs on the pages if the read failed. - */ -static void afs_file_read_cleanup(struct afs_read *req) -{ - struct page *page; - pgoff_t index = req->pos >> PAGE_SHIFT; - pgoff_t last = index + req->nr_pages - 1; - - if (req->iter) { - XA_STATE(xas, &req->vnode->vfs_inode.i_mapping->i_pages, index); - - _enter("%lu,%u,%zu", index, req->nr_pages, iov_iter_count(req->iter)); + struct afs_read *req; - rcu_read_lock(); - xas_for_each(&xas, page, last) { - BUG_ON(xa_is_value(page)); - BUG_ON(PageCompound(page)); + req = kzalloc(sizeof(struct afs_read), gfp); + if (req) + refcount_set(&req->usage, 1); - page_endio(page, false, req->error); - put_page(page); - } - rcu_read_unlock(); - } + return req; } /* @@ -271,14 +227,20 @@ void afs_put_read(struct afs_read *req) static void afs_fetch_data_notify(struct afs_operation *op) { struct afs_read *req = op->fetch.req; + struct netfs_read_subrequest *subreq = req->subreq; int error = op->error; if (error == -ECONNABORTED) error = afs_abort_to_error(op->ac.abort_code); req->error = error; - if (req->done) + if (subreq) { + __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); + netfs_subreq_terminated(subreq, error ?: req->actual_len); + req->subreq = NULL; + } else if (req->done) { req->done(req); + } } static void afs_fetch_data_success(struct afs_operation *op) @@ -332,222 +294,96 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req) return afs_do_sync_operation(op); } -/* - * read page from file, directory or symlink, given a key to use - */ -static int afs_page_filler(struct key *key, struct page *page) +static void afs_req_issue_op(struct netfs_read_subrequest *subreq) { - struct inode *inode = page->mapping->host; - struct afs_vnode *vnode = AFS_FS_I(inode); - struct afs_read *req; + struct afs_vnode *vnode = AFS_FS_I(subreq->rreq->inode); + struct afs_read *fsreq; int ret; - _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); + fsreq = afs_alloc_read(GFP_NOFS); + if (!fsreq) { + subreq->error = -ENOMEM; + return; + } - BUG_ON(!PageLocked(page)); + fsreq->subreq = subreq; + fsreq->pos = subreq->start + subreq->transferred; + fsreq->len = subreq->len - subreq->transferred; + fsreq->key = subreq->rreq->netfs_priv; + fsreq->vnode = vnode; + fsreq->iter = &fsreq->def_iter; - ret = -ESTALE; - if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) - goto error; + iov_iter_xarray(&fsreq->def_iter, READ, + &fsreq->vnode->vfs_inode.i_mapping->i_pages, + fsreq->pos, fsreq->len); - req = kzalloc(sizeof(struct afs_read), GFP_KERNEL); - if (!req) - goto enomem; - - refcount_set(&req->usage, 1); - req->vnode = vnode; - req->key = key_get(key); - req->pos = (loff_t)page->index << PAGE_SHIFT; - req->len = thp_size(page); - req->nr_pages = thp_nr_pages(page); - req->done = afs_file_read_done; - req->cleanup = afs_file_read_cleanup; - - get_page(page); - iov_iter_xarray(&req->def_iter, READ, &page->mapping->i_pages, - req->pos, req->len); - req->iter = &req->def_iter; - - ret = afs_fetch_data(vnode, req); + ret = afs_fetch_data(fsreq->vnode, fsreq); if (ret < 0) - goto fetch_error; - - afs_put_read(req); - _leave(" = 0"); - return 0; - -fetch_error: - switch (ret) { - case -EINTR: - case -ENOMEM: - case -ERESTARTSYS: - case -EAGAIN: - afs_put_read(req); - goto error; - case -ENOENT: - _debug("got NOENT from server - marking file deleted and stale"); - set_bit(AFS_VNODE_DELETED, &vnode->flags); - ret = -ESTALE; - /* Fall through */ - default: - page_endio(page, false, ret); - afs_put_read(req); - _leave(" = %d", ret); - return ret; - } - -enomem: - ret = -ENOMEM; -error: - unlock_page(page); - _leave(" = %d", ret); - return ret; + subreq->error = ret; } -/* - * read page from file, directory or symlink, given a file to nominate the key - * to be used - */ -static int afs_readpage(struct file *file, struct page *page) +static int afs_symlink_readpage(struct page *page) { - struct key *key; + struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); + struct afs_read *fsreq; int ret; - if (file) { - key = afs_file_key(file); - ASSERT(key != NULL); - ret = afs_page_filler(key, page); - } else { - struct inode *inode = page->mapping->host; - key = afs_request_key(AFS_FS_S(inode->i_sb)->cell); - if (IS_ERR(key)) { - ret = PTR_ERR(key); - } else { - ret = afs_page_filler(key, page); - key_put(key); - } - } - return ret; -} - -/* - * Read a contiguous set of pages. - */ -static int afs_readpages_one(struct file *file, struct address_space *mapping, - struct list_head *pages) -{ - struct afs_vnode *vnode = AFS_FS_I(mapping->host); - struct afs_read *req; - struct list_head *p; - struct page *first, *page; - pgoff_t index; - int ret, n; - - /* Count the number of contiguous pages at the front of the list. Note - * that the list goes prev-wards rather than next-wards. - */ - first = lru_to_page(pages); - index = first->index + 1; - n = 1; - for (p = first->lru.prev; p != pages; p = p->prev) { - page = list_entry(p, struct page, lru); - if (page->index != index) - break; - index++; - n++; - } - - req = kzalloc(sizeof(struct afs_read), GFP_NOFS); - if (!req) + fsreq = afs_alloc_read(GFP_NOFS); + if (!fsreq) return -ENOMEM; - refcount_set(&req->usage, 1); - req->vnode = vnode; - req->key = key_get(afs_file_key(file)); - req->done = afs_file_read_done; - req->cleanup = afs_file_read_cleanup; - req->pos = first->index; - req->pos <<= PAGE_SHIFT; - - /* Add pages to the LRU until it fails. We keep the pages ref'd and - * locked until the read is complete. - * - * Note that it's possible for the file size to change whilst we're - * doing this, but we rely on the server returning less than we asked - * for if the file shrank. We also rely on this to deal with a partial - * page at the end of the file. - */ - do { - page = lru_to_page(pages); - list_del(&page->lru); - index = page->index; - if (add_to_page_cache_lru(page, mapping, index, - readahead_gfp_mask(mapping))) { - put_page(page); - break; - } - - req->nr_pages++; - } while (req->nr_pages < n); - - if (req->nr_pages == 0) { - afs_put_read(req); - return 0; - } + fsreq->pos = page->index * PAGE_SIZE; + fsreq->len = PAGE_SIZE; + fsreq->vnode = vnode; + fsreq->iter = &fsreq->def_iter; + iov_iter_xarray(&fsreq->def_iter, READ, &page->mapping->i_pages, + fsreq->pos, fsreq->len); - req->len = req->nr_pages * PAGE_SIZE; - iov_iter_xarray(&req->def_iter, READ, &file->f_mapping->i_pages, - req->pos, req->len); - req->iter = &req->def_iter; + ret = afs_fetch_data(fsreq->vnode, fsreq); + page_endio(page, false, ret); + return ret; +} - ret = afs_fetch_data(vnode, req); - if (ret < 0) - goto error; +static void afs_init_rreq(struct netfs_read_request *rreq, struct file *file) +{ + struct afs_vnode *vnode = AFS_FS_I(rreq->inode); - afs_put_read(req); - return 0; + rreq->netfs_priv = key_get(afs_file_key(file)); + if (afs_vnode_cache(vnode)) + rreq->cookie_debug_id = afs_vnode_cache(vnode)->debug_id; +} -error: - if (ret == -ENOENT) { - _debug("got NOENT from server - marking file deleted and stale"); - set_bit(AFS_VNODE_DELETED, &vnode->flags); - ret = -ESTALE; - } +static int afs_begin_cache_operation(struct netfs_read_request *rreq) +{ + struct afs_vnode *vnode = AFS_FS_I(rreq->inode); - afs_put_read(req); - return ret; + return fscache_begin_operation(afs_vnode_cache(vnode), &rreq->cache_resources, + FSCACHE_WANT_PARAMS); } -/* - * read a set of pages - */ -static int afs_readpages(struct file *file, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages) +static void afs_priv_cleanup(struct address_space *mapping, void *netfs_priv) { - struct key *key = afs_file_key(file); - struct afs_vnode *vnode; - int ret = 0; - - _enter("{%d},{%lu},,%d", - key_serial(key), mapping->host->i_ino, nr_pages); + key_put(netfs_priv); +} - ASSERT(key != NULL); +static const struct netfs_read_request_ops afs_req_ops = { + .init_rreq = afs_init_rreq, + .begin_cache_operation = afs_begin_cache_operation, + .issue_op = afs_req_issue_op, + .cleanup = afs_priv_cleanup, +}; - vnode = AFS_FS_I(mapping->host); - if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { - _leave(" = -ESTALE"); - return -ESTALE; - } +static int afs_readpage(struct file *file, struct page *page) +{ + if (!file) + return afs_symlink_readpage(page); - /* attempt to read as many of the pages as possible */ - while (!list_empty(pages)) { - ret = afs_readpages_one(file, mapping, pages); - if (ret < 0) - break; - } + return netfs_readpage(file, page, &afs_req_ops, NULL); +} - _leave(" = %d [netting]", ret); - return ret; +static void afs_readahead(struct readahead_control *ractl) +{ + netfs_readahead(ractl, &afs_req_ops, NULL); } /* diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 5e34f4dbd385..2f695a260442 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "internal.h" #include "afs_fs.h" #include "xdr_fs.h" diff --git a/fs/afs/internal.h b/fs/afs/internal.h index e7ec2f4acc4d..1f7caa560c5c 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -207,6 +207,7 @@ struct afs_read { loff_t file_size; /* File size returned by server */ struct key *key; /* The key to use to reissue the read */ struct afs_vnode *vnode; /* The file being read into. */ + struct netfs_read_subrequest *subreq; /* Fscache helper read request this belongs to */ afs_dataversion_t data_version; /* Version number returned by server */ refcount_t usage; unsigned int call_debug_id; @@ -1041,6 +1042,7 @@ extern void afs_put_wb_key(struct afs_wb_key *); extern int afs_open(struct inode *, struct file *); extern int afs_release(struct inode *, struct file *); extern int afs_fetch_data(struct afs_vnode *, struct afs_read *); +extern struct afs_read *afs_alloc_read(gfp_t); extern void afs_put_read(struct afs_read *); static inline struct afs_read *afs_get_read(struct afs_read *req) diff --git a/fs/afs/super.c b/fs/afs/super.c index 6c5900df6aa5..d745e228961a 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -40,6 +40,12 @@ static int afs_show_options(struct seq_file *m, struct dentry *root); static int afs_init_fs_context(struct fs_context *fc); static const struct fs_parameter_spec afs_fs_parameters[]; +#ifdef CONFIG_AFS_FSCACHE +static void afs_put_super (struct super_block *sb); +#else +#define afs_put_super NULL +#endif + struct file_system_type afs_fs_type = { .owner = THIS_MODULE, .name = "afs", @@ -61,6 +67,7 @@ static const struct super_operations afs_super_ops = { .evict_inode = afs_evict_inode, .show_devname = afs_show_devname, .show_options = afs_show_options, + .put_super = afs_put_super, }; static struct kmem_cache *afs_inode_cachep; @@ -546,6 +553,23 @@ static void afs_kill_super(struct super_block *sb) afs_destroy_sbi(as); } +#ifdef CONFIG_AFS_FSCACHE +static struct fscache_cookie *afs_put_super_get_cookie(struct inode *inode) +{ + return afs_vnode_cache(AFS_FS_I(inode)); +} + +static void afs_put_super(struct super_block *sb) +{ + struct afs_super_info *as = AFS_FS_S(sb); + + if (as && + as->volume && + as->volume->cache) + fscache_put_super(sb, afs_put_super_get_cookie); +} +#endif + /* * Get an AFS superblock and root directory. */ From patchwork Fri Nov 20 15:17:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329198 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B525C8300F for ; Fri, 20 Nov 2020 15:18:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4B27E221FE for ; Fri, 20 Nov 2020 15:18:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="JWtfdLzG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729569AbgKTPRp (ORCPT ); Fri, 20 Nov 2020 10:17:45 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:43641 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729259AbgKTPRo (ORCPT ); Fri, 20 Nov 2020 10:17:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885462; 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=prtcvWIYR6gesJ4HmwUyCJ9G6MSDu9AVnPYB4lPA1DA=; b=JWtfdLzGYtvOjUxsOFOOQsSaxE0zl+niF4fGdZWVikHMzfr37lMuFVzp0LO3WtPHQlfJZi GOjqkgqc6QrsQ4TfnwKegBJK5NhZFPW0wg5wC+6PWbH/jnAphHnRFTUGD6/9PpUnSpxDZv 9pJthQw8texechbt4qiK1EY/XDDt/i4= 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-578-gjj8eo7_OpyOVJOZLDS42g-1; Fri, 20 Nov 2020 10:17:40 -0500 X-MC-Unique: gjj8eo7_OpyOVJOZLDS42g-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 026BC8144E3; Fri, 20 Nov 2020 15:17:39 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id D3EB35D9D5; Fri, 20 Nov 2020 15:17:32 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 69/76] fscache: Add support for writing to the cache From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:17:32 +0000 Message-ID: <160588545208.3465195.7723308498025669512.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add a pair of helpers for use by a netfs to write data to the cache. Signed-off-by: David Howells --- fs/cachefiles/content-map.c | 38 +++++++++++++ fs/cachefiles/interface.c | 1 fs/cachefiles/internal.h | 2 + fs/fscache/io.c | 128 +++++++++++++++++++++++++++++++++++++++++++ include/linux/fscache.h | 34 +++++++++++ 5 files changed, 203 insertions(+) diff --git a/fs/cachefiles/content-map.c b/fs/cachefiles/content-map.c index da0a81e3f751..d1e8a509a8cc 100644 --- a/fs/cachefiles/content-map.c +++ b/fs/cachefiles/content-map.c @@ -204,6 +204,44 @@ enum netfs_read_source cachefiles_prepare_read(struct netfs_read_subrequest *sub return NETFS_READ_FROM_CACHE; } +/* + * Prepare for a write to occur. + */ +int cachefiles_prepare_write(struct fscache_op_resources *opr, + loff_t *_start, size_t *_len, loff_t i_size) +{ + struct cachefiles_object *object = + container_of(opr->object, struct cachefiles_object, fscache); + loff_t start = *_start, map_limit; + size_t len = *_len, down; + long granule = start / CACHEFILES_GRAN_SIZE; + + if (start >= CACHEFILES_SIZE_LIMIT) + return -ENOBUFS; + + if (granule / 8 >= object->content_map_size) { + cachefiles_expand_content_map(object, i_size); + if (granule / 8 >= object->content_map_size) + return -ENOBUFS; + } + + map_limit = object->content_map_size * 8 * CACHEFILES_GRAN_SIZE; + if (start >= map_limit) + return -ENOBUFS; + if (len > map_limit - start) + len = map_limit - start; + + /* Assume that the preparation to write involved preloading any + * bits of the cache that weren't to be written and filling any + * gaps that didn't end up being written. + */ + + down = start - round_down(start, CACHEFILES_DIO_BLOCK_SIZE); + *_start = start - down; + *_len = round_up(down + len, CACHEFILES_DIO_BLOCK_SIZE); + return 0; +} + /* * Allocate a new content map. */ diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 3609ff2fb491..a9725ca72ad5 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -609,6 +609,7 @@ static const struct fscache_op_ops cachefiles_io_ops = { .write = cachefiles_write, .expand_readahead = cachefiles_expand_readahead, .prepare_read = cachefiles_prepare_read, + .prepare_write = cachefiles_prepare_write, }; static void cachefiles_begin_operation(struct fscache_op_resources *opr) diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index e2d06c0860a2..38149868c331 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -137,6 +137,8 @@ extern void cachefiles_mark_content_map(struct cachefiles_object *object, loff_t start, loff_t len, unsigned int inval_counter); extern void cachefiles_expand_content_map(struct cachefiles_object *object, loff_t size); extern void cachefiles_shorten_content_map(struct cachefiles_object *object, loff_t new_size); +extern int cachefiles_prepare_write(struct fscache_op_resources *opr, + loff_t *_start, size_t *_len, loff_t i_size); extern bool cachefiles_load_content_map(struct cachefiles_object *object); extern void cachefiles_save_content_map(struct cachefiles_object *object); extern int cachefiles_display_object(struct seq_file *m, struct fscache_object *object); diff --git a/fs/fscache/io.c b/fs/fscache/io.c index 5401c9ed347b..295a89af4269 100644 --- a/fs/fscache/io.c +++ b/fs/fscache/io.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "internal.h" /* @@ -260,3 +261,130 @@ void __fscache_resize_cookie(struct fscache_cookie *cookie, loff_t new_size) } } EXPORT_SYMBOL(__fscache_resize_cookie); + +struct fscache_write_request { + struct fscache_op_resources cache_resources; + struct address_space *mapping; + loff_t start; + size_t len; + fscache_io_terminated_t term_func; + void *term_func_priv; +}; + +/** + * fscache_clear_page_bits - Clear the PG_fscache bits from a set of pages + * @mapping: The netfs inode to use as the source + * @start: The start position in @mapping + * @len: The amount of data to unlock + * + * Clear the PG_fscache flag from a sequence of pages and wake up anyone who's + * waiting. + */ +void __fscache_clear_page_bits(struct address_space *mapping, + loff_t start, size_t len) +{ + pgoff_t first = start / PAGE_SIZE; + pgoff_t last = (start + len - 1) / PAGE_SIZE; + struct page *page; + + if (len) { + XA_STATE(xas, &mapping->i_pages, first); + + rcu_read_lock(); + xas_for_each(&xas, page, last) { + unlock_page_fscache(page); + } + rcu_read_unlock(); + } +} +EXPORT_SYMBOL(__fscache_clear_page_bits); + +/* + * Deal with the completion of writing the data to the cache. + */ +static void fscache_wreq_done(void *priv, ssize_t transferred_or_error) +{ + struct fscache_write_request *wreq = priv; + + fscache_clear_page_bits(wreq->mapping, wreq->start, wreq->len); + + if (wreq->term_func) + wreq->term_func(wreq->term_func_priv, transferred_or_error); + fscache_end_operation(&wreq->cache_resources); + kfree(wreq); +} + +/** + * fscache_write_to_cache - Save a write to the cache and clear PG_fscache + * @cookie: The cookie representing the cache object + * @mapping: The netfs inode to use as the source + * @start: The start position in @mapping + * @len: The amount of data to write back + * @i_size: The new size of the inode + * @term_func: The function to call upon completion + * @term_func_priv: The private data for @term_func + * + * Helper function for a netfs to write dirty data from an inode into the cache + * object that's backing it. + * + * @start and @len describe the range of the data. This does not need to be + * page-aligned, but to satisfy DIO requirements, the cache may expand it up to + * the page boundaries on either end. All the pages covering the range must be + * marked with PG_fscache. + * + * If given, @term_func will be called upon completion and supplied with + * @term_func_priv. Note that the PG_fscache flags will have been cleared by + * this point, so the netfs must retain its own pin on the mapping. + */ +void __fscache_write_to_cache(struct fscache_cookie *cookie, + struct address_space *mapping, + loff_t start, size_t len, loff_t i_size, + fscache_io_terminated_t term_func, + void *term_func_priv) +{ + struct fscache_write_request *wreq; + struct fscache_op_resources *opr; + struct iov_iter iter; + int ret = -ENOBUFS; + + if (!fscache_cookie_valid(cookie) || len == 0) + goto abandon; + + _enter("%llx,%zx", start, len); + + wreq = kzalloc(sizeof(struct fscache_write_request), GFP_NOFS); + if (!wreq) + goto abandon; + wreq->mapping = mapping; + wreq->start = start; + wreq->len = len; + wreq->term_func = term_func; + wreq->term_func_priv = term_func_priv; + + opr = &wreq->cache_resources; + if (fscache_begin_operation(cookie, opr, FSCACHE_WANT_WRITE) < 0) + goto abandon_free; + + ret = opr->ops->prepare_write(opr, &start, &len, i_size); + if (ret < 0) + goto abandon_end; + + /* TODO: Consider clearing page bits now for space the write isn't + * covering. This is more complicated than it appears when THPs are + * taken into account. + */ + + iov_iter_xarray(&iter, WRITE, &mapping->i_pages, start, len); + fscache_write(opr, start, &iter, fscache_wreq_done, wreq); + return; + +abandon_end: + return fscache_wreq_done(wreq, ret); +abandon_free: + kfree(wreq); +abandon: + fscache_clear_page_bits(mapping, start, len); + if (term_func) + term_func(term_func_priv, ret); +} +EXPORT_SYMBOL(__fscache_write_to_cache); diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 1c1ea3558421..0613ccea88c1 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -192,6 +192,12 @@ struct fscache_op_ops { */ enum netfs_read_source (*prepare_read)(struct netfs_read_subrequest *subreq, loff_t i_size); + + /* Prepare a write operation, working out what part of the write we can + * actually do. + */ + int (*prepare_write)(struct fscache_op_resources *opr, + loff_t *_start, size_t *_len, loff_t i_size); }; /* @@ -226,6 +232,10 @@ extern void __fscache_invalidate(struct fscache_cookie *, const void *, loff_t, extern void fscache_put_super(struct super_block *, struct fscache_cookie *(*get_cookie)(struct inode *)); +extern void __fscache_write_to_cache(struct fscache_cookie *, struct address_space *, + loff_t, size_t, loff_t, fscache_io_terminated_t, void *); +extern void __fscache_clear_page_bits(struct address_space *, loff_t, size_t); + /** * fscache_register_netfs - Register a filesystem as desiring caching services * @netfs: The description of the filesystem @@ -627,6 +637,30 @@ int fscache_write(struct fscache_op_resources *opr, return ops->write(opr, start_pos, iter, term_func, term_func_priv); } +static inline void fscache_clear_page_bits(struct address_space *mapping, + loff_t start, size_t len) +{ + if (fscache_available()) + __fscache_clear_page_bits(mapping, start, len); +} + +static inline void fscache_write_to_cache(struct fscache_cookie *cookie, + struct address_space *mapping, + loff_t start, size_t len, loff_t i_size, + fscache_io_terminated_t term_func, + void *term_func_priv) +{ + if (fscache_available()) { + __fscache_write_to_cache(cookie, mapping, start, len, i_size, + term_func, term_func_priv); + } else { + fscache_clear_page_bits(mapping, start, len); + if (term_func) + term_func(term_func_priv, -ENOBUFS); + } + +} + #if __fscache_available extern int fscache_set_page_dirty(struct page *page, struct fscache_cookie *cookie); #else From patchwork Fri Nov 20 15:18:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329197 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFB2BC64E69 for ; Fri, 20 Nov 2020 15:18:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6F26A221FE for ; Fri, 20 Nov 2020 15:18:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Oe1A6q75" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729347AbgKTPS1 (ORCPT ); Fri, 20 Nov 2020 10:18:27 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:52749 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729114AbgKTPS0 (ORCPT ); Fri, 20 Nov 2020 10:18:26 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885505; 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=xFy7qM0/8Y7ysTXRC0McVVXyDOlGEw1UMMIueaGD11M=; b=Oe1A6q756ctEcOtqsshHy9BbeYJAZKJOT/q5zVrHi2yKutUk3WSsiY1U36dcwDE0jsdTvv o9iplo5WhckVBbNlW6Mwx69GzS20NCZTFmWKc2XCI2PKyw+ex4GS8IdljPq/uMo0XhI1bP T+ksDnfr3jCKpW7wB1z4VTchEQyTi/Y= 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-486-v50qV0SgMleMRT3NQpIoWw-1; Fri, 20 Nov 2020 10:18:23 -0500 X-MC-Unique: v50qV0SgMleMRT3NQpIoWw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B4B59801B29; Fri, 20 Nov 2020 15:18:21 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 63E136085D; Fri, 20 Nov 2020 15:18:14 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 72/76] afs: Invoke fscache_resize_cookie() when handling ATTR_SIZE for setattr From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:18:13 +0000 Message-ID: <160588549356.3465195.17026181625185725385.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Invoke fscache_resize_cookie() to adjust the size of the backing cache object when setattr is called with ATTR_SIZE. This discards any data that then lies beyond the revised EOF and frees up space. Signed-off-by: David Howells --- fs/afs/inode.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 51e55bfadb54..c639de101065 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -847,6 +847,9 @@ static void afs_setattr_edit_file(struct afs_operation *op) if (size < i_size) truncate_pagecache(inode, size); + if (size != i_size) + fscache_resize_cookie(afs_vnode_cache(vp->vnode), + vp->scb.status.size); } } @@ -889,6 +892,8 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr) attr->ia_valid &= ~ATTR_SIZE; } + fscache_use_cookie(afs_vnode_cache(vnode), true); + /* flush any dirty data outstanding on a regular file */ if (S_ISREG(vnode->vfs_inode.i_mode)) filemap_write_and_wait(vnode->vfs_inode.i_mapping); @@ -919,6 +924,7 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr) out_unlock: up_write(&vnode->validate_lock); + fscache_unuse_cookie(afs_vnode_cache(vnode), NULL, NULL); _leave(" = %d", ret); return ret; } From patchwork Fri Nov 20 15:18:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329196 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 500ACC2D0E4 for ; Fri, 20 Nov 2020 15:19:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E154E221FE for ; Fri, 20 Nov 2020 15:19:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ffsuquJu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729298AbgKTPTA (ORCPT ); Fri, 20 Nov 2020 10:19:00 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:22097 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729095AbgKTPS7 (ORCPT ); Fri, 20 Nov 2020 10:18:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885538; 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=/VcxcbR3I+/KolholQXr9kk5hjFx0z0dRM8YbywDjdA=; b=ffsuquJuuzj1fl0yBUWNbURwfQN0JaV2ahejk8duNULhYtpmm8YmzHB2XjzCAOsElIRCdK 2U0g7RMOlyvdfMXL4tv31GZ7ZefJ++nruUAbkqYnPZjVoozzxhuw5bo2RUicXbBvWQVB8s DSL0yyu/EiPkgpaLaO9JldWX/4ijWm8= 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-324-W6-MaewuMzewGjZeTS4FLg-1; Fri, 20 Nov 2020 10:18:56 -0500 X-MC-Unique: W6-MaewuMzewGjZeTS4FLg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 45DFE8145E5; Fri, 20 Nov 2020 15:18:53 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id CF4135D6D1; Fri, 20 Nov 2020 15:18:27 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 73/76] afs: Add O_DIRECT read support From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:18:26 +0000 Message-ID: <160588550694.3465195.1373401214547164382.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Add synchronous O_DIRECT read support to AFS (no AIO yet). It can theoretically handle reads up to the maximum size describable by loff_t - and given an iterator with sufficiently capacity to handle that and given support on the server. Signed-off-by: David Howells --- fs/afs/file.c | 59 +++++++++++++++++++++++++++++++++++ fs/afs/fsclient.c | 18 ++++++++--- fs/afs/internal.h | 2 + fs/afs/write.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++----- fs/afs/yfsclient.c | 12 +++++-- 5 files changed, 161 insertions(+), 18 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index bd070684de53..27445866531c 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -24,6 +24,7 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, static int afs_releasepage(struct page *page, gfp_t gfp_flags); static void afs_readahead(struct readahead_control *ractl); +static ssize_t afs_direct_IO(struct kiocb *iocb, struct iov_iter *iter); const struct file_operations afs_file_operations = { .open = afs_open, @@ -53,6 +54,7 @@ const struct address_space_operations afs_fs_aops = { .launder_page = afs_launder_page, .releasepage = afs_releasepage, .invalidatepage = afs_invalidatepage, + .direct_IO = afs_direct_IO, .write_begin = afs_write_begin, .write_end = afs_write_end, .writepage = afs_writepage, @@ -529,3 +531,60 @@ static int afs_file_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_ops = &afs_vm_ops; return ret; } + +/* + * Direct file read operation for an AFS file. + * + * TODO: To support AIO, the pages in the iterator have to be copied and + * refs taken on them. Then -EIOCBQUEUED needs to be returned. + * iocb->ki_complete must then be called upon completion of the operation. + */ +static ssize_t afs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) +{ + struct file *file = iocb->ki_filp; + struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); + struct afs_read *req; + ssize_t ret, transferred; + + _enter("%llx,%zx", iocb->ki_pos, iov_iter_count(iter)); + + req = afs_alloc_read(GFP_KERNEL); + if (!req) + return -ENOMEM; + + req->vnode = vnode; + req->key = key_get(afs_file_key(file)); + req->pos = iocb->ki_pos; + req->len = iov_iter_count(iter); + req->iter = iter; + + task_io_account_read(req->len); + + // TODO nfs_start_io_direct(inode); + ret = afs_fetch_data(vnode, req); + if (ret == 0) + transferred = req->actual_len; + afs_put_read(req); + + // TODO nfs_end_io_direct(inode); + + if (ret == 0) + ret = transferred; + + BUG_ON(ret == -EIOCBQUEUED); // TODO + //if (iocb->ki_complete) + // iocb->ki_complete(iocb, ret, 0); // only if ret == -EIOCBQUEUED + + _leave(" = %zu", ret); + return ret; +} + +/* + * Do direct I/O. + */ +static ssize_t afs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +{ + if (iov_iter_rw(iter) == READ) + return afs_file_direct_read(iocb, iter); + return afs_file_direct_write(iocb, iter); +} diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 2f695a260442..5e42af4d1ded 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -438,7 +438,7 @@ static void afs_fs_fetch_data64(struct afs_operation *op) bp[3] = htonl(vp->fid.unique); bp[4] = htonl(upper_32_bits(req->pos)); bp[5] = htonl(lower_32_bits(req->pos)); - bp[6] = 0; + bp[6] = htonl(upper_32_bits(req->len)); bp[7] = htonl(lower_32_bits(req->len)); trace_afs_make_fs_call(call, &vp->fid); @@ -1058,6 +1058,7 @@ static void afs_fs_store_data64(struct afs_operation *op) struct afs_vnode_param *vp = &op->file[0]; struct afs_call *call; __be32 *bp; + u32 mask = 0; _enter(",%x,{%llx:%llu},,", key_serial(op->key), vp->fid.vid, vp->fid.vnode); @@ -1070,6 +1071,9 @@ static void afs_fs_store_data64(struct afs_operation *op) call->write_iter = op->store.write_iter; + if (op->flags & AFS_OPERATION_SET_MTIME) + mask |= AFS_SET_MTIME; + /* marshall the parameters */ bp = call->request; *bp++ = htonl(FSSTOREDATA64); @@ -1077,8 +1081,8 @@ static void afs_fs_store_data64(struct afs_operation *op) *bp++ = htonl(vp->fid.vnode); *bp++ = htonl(vp->fid.unique); - *bp++ = htonl(AFS_SET_MTIME); /* mask */ - *bp++ = htonl(op->mtime.tv_sec); /* mtime */ + *bp++ = htonl(mask); + *bp++ = htonl(op->mtime.tv_sec); *bp++ = 0; /* owner */ *bp++ = 0; /* group */ *bp++ = 0; /* unix mode */ @@ -1103,6 +1107,7 @@ void afs_fs_store_data(struct afs_operation *op) struct afs_vnode_param *vp = &op->file[0]; struct afs_call *call; __be32 *bp; + u32 mask = 0; _enter(",%x,{%llx:%llu},,", key_serial(op->key), vp->fid.vid, vp->fid.vnode); @@ -1125,6 +1130,9 @@ void afs_fs_store_data(struct afs_operation *op) call->write_iter = op->store.write_iter; + if (op->flags & AFS_OPERATION_SET_MTIME) + mask |= AFS_SET_MTIME; + /* marshall the parameters */ bp = call->request; *bp++ = htonl(FSSTOREDATA); @@ -1132,8 +1140,8 @@ void afs_fs_store_data(struct afs_operation *op) *bp++ = htonl(vp->fid.vnode); *bp++ = htonl(vp->fid.unique); - *bp++ = htonl(AFS_SET_MTIME); /* mask */ - *bp++ = htonl(op->mtime.tv_sec); /* mtime */ + *bp++ = htonl(mask); + *bp++ = htonl(op->mtime.tv_sec); *bp++ = 0; /* owner */ *bp++ = 0; /* group */ *bp++ = 0; /* unix mode */ diff --git a/fs/afs/internal.h b/fs/afs/internal.h index bc76c08b9f38..e80fb6fe15b3 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -853,6 +853,7 @@ struct afs_operation { #define AFS_OPERATION_TRIED_ALL 0x0400 /* Set if we've tried all the fileservers */ #define AFS_OPERATION_RETRY_SERVER 0x0800 /* Set if we should retry the current server */ #define AFS_OPERATION_DIR_CONFLICT 0x1000 /* Set if we detected a 3rd-party dir change */ +#define AFS_OPERATION_SET_MTIME 0x2000 /* Set if we should try to store the mtime */ }; /* @@ -1506,6 +1507,7 @@ extern int afs_fsync(struct file *, loff_t, loff_t, int); extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf); extern void afs_prune_wb_keys(struct afs_vnode *); extern int afs_launder_page(struct page *); +extern ssize_t afs_file_direct_write(struct kiocb *, struct iov_iter *); /* * xattr.c diff --git a/fs/afs/write.c b/fs/afs/write.c index 627b08d8de1f..bab110c00abd 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -387,7 +387,7 @@ static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t op->store.i_size = max(pos + size, i_size); op->store.laundering = laundering; op->mtime = vnode->vfs_inode.i_mtime; - op->flags |= AFS_OPERATION_UNINTR; + op->flags |= AFS_OPERATION_SET_MTIME | AFS_OPERATION_UNINTR; op->ops = &afs_store_data_operation; try_next_key: @@ -810,7 +810,6 @@ int afs_writepages(struct address_space *mapping, ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) { struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp)); - ssize_t result; size_t count = iov_iter_count(from); _enter("{%llx:%llu},{%zu},", @@ -822,13 +821,7 @@ ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) return -EBUSY; } - if (!count) - return 0; - - result = generic_file_write_iter(iocb, from); - - _leave(" = %zd", result); - return result; + return generic_file_write_iter(iocb, from); } /* @@ -997,3 +990,80 @@ static void afs_write_to_cache(struct afs_vnode *vnode, vnode->vfs_inode.i_mapping, start, len, i_size, afs_write_to_cache_done, vnode); } + +static void afs_dio_store_data_success(struct afs_operation *op) +{ + struct afs_vnode *vnode = op->file[0].vnode; + + op->ctime = op->file[0].scb.status.mtime_client; + afs_vnode_commit_status(op, &op->file[0]); + if (op->error == 0) { + afs_stat_v(vnode, n_stores); + atomic_long_add(op->store.size, &afs_v2net(vnode)->n_store_bytes); + } +} + +static const struct afs_operation_ops afs_dio_store_data_operation = { + .issue_afs_rpc = afs_fs_store_data, + .issue_yfs_rpc = yfs_fs_store_data, + .success = afs_dio_store_data_success, +}; + +/* + * Direct file write operation for an AFS file. + * + * TODO: To support AIO, the pages in the iterator have to be copied and + * refs taken on them. Then -EIOCBQUEUED needs to be returned. + * iocb->ki_complete must then be called upon completion of the operation. + */ +ssize_t afs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) +{ + struct file *file = iocb->ki_filp; + struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); + struct afs_operation *op; + loff_t size = iov_iter_count(iter), i_size; + ssize_t ret; + + _enter("%s{%llx:%llu.%u},%llx,%llx", + vnode->volume->name, + vnode->fid.vid, + vnode->fid.vnode, + vnode->fid.unique, + size, iocb->ki_pos); + + op = afs_alloc_operation(afs_file_key(file), vnode->volume); + if (IS_ERR(op)) + return -ENOMEM; + + i_size = i_size_read(&vnode->vfs_inode); + + afs_op_set_vnode(op, 0, vnode); + op->file[0].dv_delta = 1; + op->file[0].set_size = true; + op->store.write_iter = iter; + op->store.pos = iocb->ki_pos; + op->store.size = size; + op->store.i_size = max(iocb->ki_pos + size, i_size); + op->ops = &afs_dio_store_data_operation; + + //if (!is_sync_kiocb(iocb)) { + + ret = afs_do_sync_operation(op); + if (ret == 0) + ret = size; + + { + struct afs_vnode_cache_aux aux = { + .data_version = vnode->status.data_version, + }; + fscache_invalidate(afs_vnode_cache(vnode), &aux, + i_size_read(&vnode->vfs_inode), + FSCACHE_INVAL_DIO_WRITE); + } + + //if (iocb->ki_complete) + // iocb->ki_complete(iocb, ret, 0); // only if ret == -EIOCBQUEUED + + _leave(" = %zd", ret); + return ret; +} diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c index 2b35cba8ad62..a8c4e230002d 100644 --- a/fs/afs/yfsclient.c +++ b/fs/afs/yfsclient.c @@ -95,12 +95,16 @@ static __be32 *xdr_encode_YFSStoreStatus_mode(__be32 *bp, mode_t mode) return bp + xdr_size(x); } -static __be32 *xdr_encode_YFSStoreStatus_mtime(__be32 *bp, const struct timespec64 *t) +static __be32 *xdr_encode_YFSStoreStatus_mtime(__be32 *bp, struct afs_operation *op) { struct yfs_xdr_YFSStoreStatus *x = (void *)bp; - s64 mtime = linux_to_yfs_time(t); + s64 mtime = linux_to_yfs_time(&op->mtime); + u32 mask = 0; - x->mask = htonl(AFS_SET_MTIME); + if (op->flags & AFS_OPERATION_SET_MTIME) + mask |= AFS_SET_MTIME; + + x->mask = htonl(mask); x->mode = htonl(0); x->mtime_client = u64_to_xdr(mtime); x->owner = u64_to_xdr(0); @@ -1103,7 +1107,7 @@ void yfs_fs_store_data(struct afs_operation *op) bp = xdr_encode_u32(bp, YFSSTOREDATA64); bp = xdr_encode_u32(bp, 0); /* RPC flags */ bp = xdr_encode_YFSFid(bp, &vp->fid); - bp = xdr_encode_YFSStoreStatus_mtime(bp, &op->mtime); + bp = xdr_encode_YFSStoreStatus_mtime(bp, op); bp = xdr_encode_u64(bp, op->store.pos); bp = xdr_encode_u64(bp, op->store.size); bp = xdr_encode_u64(bp, op->store.i_size); From patchwork Fri Nov 20 15:19:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 329195 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F863C64E8A for ; Fri, 20 Nov 2020 15:19:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 53F6F22269 for ; Fri, 20 Nov 2020 15:19:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AKl9RK3J" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729630AbgKTPTp (ORCPT ); Fri, 20 Nov 2020 10:19:45 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:24581 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729378AbgKTPTp (ORCPT ); Fri, 20 Nov 2020 10:19:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605885584; 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=bIkx8tZwUOn3GO1HchdWNQxPfUS0TK2X8uwNc5x6YvQ=; b=AKl9RK3JVQvVeYIfRkQfuLM/Ee0RTxKBtEeQKcT6kcBwS5vn7lO7UC3R7DQGcaNX9z8B/k ik+RQ3nMwzxHJd1aFsLhvjEwRcMVo7+jTKpft9qEY+2BxMnzXB/2oK5Rd9fqnUbgh3aIT9 I/Iksa7YTMgleqFE8Rut4I93ylSmx84= 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-581-K-cx1Y4ePPmYDs1KCfDqfg-1; Fri, 20 Nov 2020 10:19:40 -0500 X-MC-Unique: K-cx1Y4ePPmYDs1KCfDqfg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4480D80EDB3; Fri, 20 Nov 2020 15:19:38 +0000 (UTC) Received: from warthog.procyon.org.uk (ovpn-112-246.rdu2.redhat.com [10.10.112.246]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2DC7710023AB; Fri, 20 Nov 2020 15:19:32 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 Subject: [RFC PATCH 75/76] afs: Make afs_write_begin() return the THP subpage From: David Howells To: Trond Myklebust , Anna Schumaker , Steve French , Dominique Martinet Cc: dhowells@redhat.com, Jeff Layton , Matthew Wilcox , Alexander Viro , linux-cachefs@redhat.com, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Fri, 20 Nov 2020 15:19:31 +0000 Message-ID: <160588557132.3465195.5617528680363774731.stgit@warthog.procyon.org.uk> In-Reply-To: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> References: <160588455242.3465195.3214733858273019178.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org generic_perform_write() can't handle a THP, so we have to return the subpage of that THP from afs_write_begin() and then convert it back into the head on entry to afs_write_end(). Signed-off-by: David Howells --- fs/afs/write.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/afs/write.c b/fs/afs/write.c index bab110c00abd..a88c6ae71868 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -81,7 +81,7 @@ int afs_write_begin(struct file *file, struct address_space *mapping, goto flush_conflicting_write; } - *_page = page; + *_page = find_subpage(page, pos / PAGE_SIZE); _leave(" = 0"); return 0; @@ -110,9 +110,10 @@ int afs_write_begin(struct file *file, struct address_space *mapping, */ int afs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) + struct page *subpage, void *fsdata) { struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); + struct page *page = thp_head(subpage); unsigned long priv; unsigned int f, from = pos & (thp_size(page) - 1); unsigned int t, to = from + copied;