All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: linux-fsdevel@vger.kernel.org
Cc: Marc Dionne <marc.dionne@auristor.com>,
	linux-afs@lists.infradead.org, linux-cachefs@redhat.com,
	dhowells@redhat.com,
	Trond Myklebust <trond.myklebust@hammerspace.com>,
	Anna Schumaker <anna.schumaker@netapp.com>,
	Steve French <sfrench@samba.org>,
	Dominique Martinet <asmadeus@codewreck.org>,
	Jeff Layton <jlayton@redhat.com>,
	David Wysochanski <dwysocha@redhat.com>,
	"Matthew Wilcox (Oracle)" <willy@infradead.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	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-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: [PATCH v7 31/31] afs: Use the netfs_write_begin() helper
Date: Fri, 23 Apr 2021 14:34:55 +0100	[thread overview]
Message-ID: <161918489504.3145707.5655048601094961805.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <161918446704.3145707.14418606303992174310.stgit@warthog.procyon.org.uk>

Make AFS use the new netfs_write_begin() helper to do the pre-reading
required before the write.  If successful, the helper returns with the
required page filled in and locked.  It may read more than just one page,
expanding the read to meet cache granularity requirements as necessary.

Note: A more advanced version of this could be made that does
generic_perform_write() for a whole cache granule.  This would make it
easier to avoid doing the download/read for the data to be overwritten.

Signed-off-by: David Howells <dhowells@redhat.com>
Tested-By: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-cachefs@redhat.com
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/160588546422.3465195.1546354372589291098.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/161539563244.286939.16537296241609909980.stgit@warthog.procyon.org.uk/ # v4
Link: https://lore.kernel.org/r/161653819291.2770958.406013201547420544.stgit@warthog.procyon.org.uk/ # v5
Link: https://lore.kernel.org/r/161789102743.6155.17396591236631761195.stgit@warthog.procyon.org.uk/ # v6
---

 fs/afs/file.c     |   19 +++++++++
 fs/afs/internal.h |    1 
 fs/afs/write.c    |  108 ++++++-----------------------------------------------
 3 files changed, 31 insertions(+), 97 deletions(-)

diff --git a/fs/afs/file.c b/fs/afs/file.c
index 10c6eaaac2cc..db035ae2a134 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -333,6 +333,13 @@ static void afs_init_rreq(struct netfs_read_request *rreq, struct file *file)
 	rreq->netfs_priv = key_get(afs_file_key(file));
 }
 
+static bool afs_is_cache_enabled(struct inode *inode)
+{
+	struct fscache_cookie *cookie = afs_vnode_cache(AFS_FS_I(inode));
+
+	return fscache_cookie_enabled(cookie) && !hlist_empty(&cookie->backing_objects);
+}
+
 static int afs_begin_cache_operation(struct netfs_read_request *rreq)
 {
 	struct afs_vnode *vnode = AFS_FS_I(rreq->inode);
@@ -340,14 +347,24 @@ static int afs_begin_cache_operation(struct netfs_read_request *rreq)
 	return fscache_begin_read_operation(rreq, afs_vnode_cache(vnode));
 }
 
+static int afs_check_write_begin(struct file *file, loff_t pos, unsigned len,
+				 struct page *page, void **_fsdata)
+{
+	struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
+
+	return test_bit(AFS_VNODE_DELETED, &vnode->flags) ? -ESTALE : 0;
+}
+
 static void afs_priv_cleanup(struct address_space *mapping, void *netfs_priv)
 {
 	key_put(netfs_priv);
 }
 
-static const struct netfs_read_request_ops afs_req_ops = {
+const struct netfs_read_request_ops afs_req_ops = {
 	.init_rreq		= afs_init_rreq,
+	.is_cache_enabled	= afs_is_cache_enabled,
 	.begin_cache_operation	= afs_begin_cache_operation,
+	.check_write_begin	= afs_check_write_begin,
 	.issue_op		= afs_req_issue_op,
 	.cleanup		= afs_priv_cleanup,
 };
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index f9a692fc08f4..52157a05796a 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1045,6 +1045,7 @@ extern void afs_dynroot_depopulate(struct super_block *);
 extern const struct address_space_operations afs_fs_aops;
 extern const struct inode_operations afs_file_inode_operations;
 extern const struct file_operations afs_file_operations;
+extern const struct netfs_read_request_ops afs_req_ops;
 
 extern int afs_cache_wb_key(struct afs_vnode *, struct afs_file *);
 extern void afs_put_wb_key(struct afs_wb_key *);
diff --git a/fs/afs/write.c b/fs/afs/write.c
index bc84c771b0fd..dc66ff15dd16 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -11,6 +11,8 @@
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/pagevec.h>
+#include <linux/netfs.h>
+#include <linux/fscache.h>
 #include "internal.h"
 
 /*
@@ -22,68 +24,6 @@ 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
- */
-static int afs_fill_page(struct file *file,
-			 loff_t pos, unsigned int len, struct page *page)
-{
-	struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
-	struct afs_read *req;
-	size_t p;
-	void *data;
-	int ret;
-
-	_enter(",,%llu", (unsigned long long)pos);
-
-	if (pos >= vnode->vfs_inode.i_size) {
-		p = pos & ~PAGE_MASK;
-		ASSERTCMP(p + len, <=, PAGE_SIZE);
-		data = kmap(page);
-		memset(data + p, 0, len);
-		kunmap(page);
-		return 0;
-	}
-
-	req = kzalloc(sizeof(struct afs_read), GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
-
-	refcount_set(&req->usage, 1);
-	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);
-	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;
-		}
-	}
-
-	_leave(" = %d", ret);
-	return ret;
-}
-
 /*
  * prepare to perform part of a write to a page
  */
@@ -102,24 +42,14 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
 	_enter("{%llx:%llu},%llx,%x",
 	       vnode->fid.vid, vnode->fid.vnode, pos, len);
 
-	page = grab_cache_page_write_begin(mapping, pos / PAGE_SIZE, flags);
-	if (!page)
-		return -ENOMEM;
-
-	if (!PageUptodate(page) && len != PAGE_SIZE) {
-		ret = afs_fill_page(file, pos & PAGE_MASK, PAGE_SIZE, page);
-		if (ret < 0) {
-			unlock_page(page);
-			put_page(page);
-			_leave(" = %d [prep]", ret);
-			return ret;
-		}
-		SetPageUptodate(page);
-	}
-
-#ifdef CONFIG_AFS_FSCACHE
-	wait_on_page_fscache(page);
-#endif
+	/* Prefetch area to be written into the cache if we're caching this
+	 * file.  We need to do this before we get a lock on the page in case
+	 * there's more than one writer competing for the same cache block.
+	 */
+	ret = netfs_write_begin(file, mapping, pos, len, flags, &page, fsdata,
+				&afs_req_ops, NULL);
+	if (ret < 0)
+		return ret;
 
 	index = page->index;
 	from = pos - index * PAGE_SIZE;
@@ -184,7 +114,6 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 	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;
 
 	_enter("{%llx:%llu},{%lx}",
 	       vnode->fid.vid, vnode->fid.vnode, page->index);
@@ -203,19 +132,7 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 		write_sequnlock(&vnode->cb_lock);
 	}
 
-	if (!PageUptodate(page)) {
-		if (copied < len) {
-			/* Try and load any missing data from the server.  The
-			 * unmarshalling routine will take care of clearing any
-			 * bits that are beyond the EOF.
-			 */
-			ret = afs_fill_page(file, pos + copied,
-					    len - copied, page);
-			if (ret < 0)
-				goto out;
-		}
-		SetPageUptodate(page);
-	}
+	ASSERT(PageUptodate(page));
 
 	if (PagePrivate(page)) {
 		priv = page_private(page);
@@ -236,12 +153,11 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 
 	if (set_page_dirty(page))
 		_debug("dirtied %lx", page->index);
-	ret = copied;
 
 out:
 	unlock_page(page);
 	put_page(page);
-	return ret;
+	return copied;
 }
 
 /*



  parent reply	other threads:[~2021-04-23 13:36 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-23 13:27 [PATCH v7 00/31] Network fs helper library & fscache kiocb API David Howells
2021-04-23 13:28 ` [PATCH v7 01/31] iov_iter: Add ITER_XARRAY David Howells
2021-04-23 14:06   ` Matthew Wilcox
2021-04-23 14:33   ` David Howells
2021-04-25 13:14   ` Al Viro
2021-04-25 13:58   ` David Howells
2021-04-25 14:16     ` Al Viro
2021-04-26 18:54   ` Al Viro
2021-04-26 19:15     ` Jeff Layton
2021-04-26 19:15       ` Jeff Layton
2021-04-26 19:23   ` David Howells
2021-04-26 19:52     ` Al Viro
2021-04-23 13:28 ` [PATCH v7 02/31] mm: Add set/end/wait functions for PG_private_2 David Howells
2021-04-23 13:28 ` [PATCH v7 03/31] mm/filemap: Pass the file_ra_state in the ractl David Howells
2021-04-23 13:28 ` [PATCH v7 04/31] fs: Document file_ra_state David Howells
2021-04-23 13:28 ` [PATCH v7 05/31] mm/readahead: Handle ractl nr_pages being modified David Howells
2021-04-23 13:29 ` [PATCH v7 06/31] mm: Implement readahead_control pageset expansion David Howells
2021-04-23 13:29 ` [PATCH v7 07/31] netfs: Make a netfs helper module David Howells
2021-04-29  8:04   ` Geert Uytterhoeven
2021-04-29  8:04     ` Geert Uytterhoeven
2021-04-29  8:41   ` David Howells
2021-04-29  8:43     ` Dominique Martinet
2021-04-23 13:29 ` [PATCH v7 08/31] netfs: Documentation for helper library David Howells
2021-04-23 13:29 ` [PATCH v7 09/31] netfs, mm: Move PG_fscache helper funcs to linux/netfs.h David Howells
2021-04-23 13:29 ` [PATCH v7 10/31] netfs, mm: Add set/end/wait_on_page_fscache() aliases David Howells
2021-04-23 13:30 ` [PATCH v7 11/31] netfs: Provide readahead and readpage netfs helpers David Howells
2021-04-23 13:30 ` [PATCH v7 12/31] netfs: Add tracepoints David Howells
2021-04-23 13:30 ` [PATCH v7 13/31] netfs: Gather stats David Howells
2021-04-23 13:30 ` [PATCH v7 14/31] netfs: Add write_begin helper David Howells
2021-04-23 13:31 ` [PATCH v7 15/31] netfs: Define an interface to talk to a cache David Howells
2021-04-23 13:31 ` [PATCH v7 16/31] netfs: Add a tracepoint to log failures that would be otherwise unseen David Howells
2021-04-23 13:31 ` [PATCH v7 17/31] fscache, cachefiles: Add alternate API to use kiocb for read/write to cache David Howells
2021-04-23 13:32 ` [PATCH v7 18/31] afs: Disable use of the fscache I/O routines David Howells
2021-04-23 13:32 ` [PATCH v7 19/31] afs: Pass page into dirty region helpers to provide THP size David Howells
2021-04-23 13:32 ` [PATCH v7 20/31] afs: Print the operation debug_id when logging an unexpected data version David Howells
2021-04-23 13:32 ` [PATCH v7 21/31] afs: Move key to afs_read struct David Howells
2021-04-23 13:33 ` [PATCH v7 22/31] afs: Don't truncate iter during data fetch David Howells
2021-04-23 13:33 ` [PATCH v7 23/31] afs: Log remote unmarshalling errors David Howells
2021-04-23 13:33 ` [PATCH v7 24/31] afs: Set up the iov_iter before calling afs_extract_data() David Howells
2021-04-23 13:33 ` [PATCH v7 25/31] afs: Use ITER_XARRAY for writing David Howells
2021-04-23 13:33 ` [PATCH v7 26/31] afs: Wait on PG_fscache before modifying/releasing a page David Howells
2021-04-23 13:34 ` [PATCH v7 27/31] afs: Extract writeback extension into its own function David Howells
2021-04-23 13:34 ` [PATCH v7 28/31] afs: Prepare for use of THPs David Howells
2021-04-23 13:34 ` [PATCH v7 29/31] afs: Use the fs operation ops to handle FetchData completion David Howells
2021-04-23 13:34 ` [PATCH v7 30/31] afs: Use new netfs lib read helper API David Howells
2021-04-23 13:34 ` David Howells [this message]
2021-04-25 23:14 ` [PATCH] iov_iter: Four fixes for ITER_XARRAY David Howells
2021-04-26 17:14   ` Al Viro
2021-04-26 19:02   ` Jeff Layton
2021-04-26 19:02     ` Jeff Layton
2021-04-26 21:38   ` David Wysochanski
2021-04-26 21:38     ` David Wysochanski
2021-04-26 21:06 ` [PATCH] netfs: Miscellaneous fixes David Howells
2021-04-26 21:09   ` Matthew Wilcox
2021-04-26 21:20   ` [PATCH v2] " David Howells
2021-04-26 22:06     ` Matthew Wilcox
2021-04-26 22:17     ` Jeff Layton
2021-04-26 22:17       ` Jeff Layton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=161918489504.3145707.5655048601094961805.stgit@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=anna.schumaker@netapp.com \
    --cc=asmadeus@codewreck.org \
    --cc=ceph-devel@vger.kernel.org \
    --cc=dwysocha@redhat.com \
    --cc=jlayton@redhat.com \
    --cc=linux-afs@lists.infradead.org \
    --cc=linux-cachefs@redhat.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=marc.dionne@auristor.com \
    --cc=sfrench@samba.org \
    --cc=trond.myklebust@hammerspace.com \
    --cc=v9fs-developer@lists.sourceforge.net \
    --cc=viro@zeniv.linux.org.uk \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.