All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: Jeff Layton <jlayton@kernel.org>, Steve French <smfrench@gmail.com>
Cc: David Howells <dhowells@redhat.com>,
	Matthew Wilcox <willy@infradead.org>,
	Marc Dionne <marc.dionne@auristor.com>,
	Paulo Alcantara <pc@manguebit.com>,
	Shyam Prasad N <sprasad@microsoft.com>,
	Tom Talpey <tom@talpey.com>,
	Dominique Martinet <asmadeus@codewreck.org>,
	Ilya Dryomov <idryomov@gmail.com>,
	Christian Brauner <christian@brauner.io>,
	linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org,
	linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org,
	v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org,
	linux-mm@kvack.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-cachefs@redhat.com
Subject: [RFC PATCH 02/53] netfs: Track the fpos above which the server has no data
Date: Fri, 13 Oct 2023 17:03:31 +0100	[thread overview]
Message-ID: <20231013160423.2218093-3-dhowells@redhat.com> (raw)
In-Reply-To: <20231013160423.2218093-1-dhowells@redhat.com>

Track the file position above which the server is not expected to have any
data and preemptively assume that we can simply fill blocks with zeroes
locally rather than attempting to download them - even if we've written
data back to the server.  Assume that any data that was written back above
that position is held in the local cache.  Call this the "zero point".

Make use of this to optimise away some reads from the server.  We need to
set the zero point in the following circumstances:

 (1) When we see an extant remote inode and have no cache for it, we set
     the zero_point to i_size.

 (2) On local inode creation, we set zero_point to 0.

 (3) On local truncation down, we reduce zero_point to the new i_size if
     the new i_size is lower.

 (4) On local truncation up, we don't change zero_point.

 (5) On local modification, we don't change zero_point.

 (6) On remote invalidation, we set zero_point to the new i_size.

 (7) If stored data is culled from the local cache, we must set zero_point
     above that if the data also got written to the server.

 (8) If dirty data is written back to the server, but not the local cache,
     we must set zero_point above that.

Assuming the above, any read from the server at or above the zero_point
position will return all zeroes.

The zero_point value can be stored in the cache, provided the above rules
are applied to it by any code that culls part of the local cache.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
cc: linux-fsdevel@vger.kernel.org
cc: linux-mm@kvack.org
---
 fs/afs/inode.c           | 13 +++++++------
 fs/netfs/buffered_read.c | 40 +++++++++++++++++++++++++---------------
 include/linux/netfs.h    |  5 +++++
 3 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 1c794a1896aa..46bc5574d6f5 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -252,6 +252,7 @@ static void afs_apply_status(struct afs_operation *op,
 		vnode->netfs.remote_i_size = status->size;
 		if (change_size) {
 			afs_set_i_size(vnode, status->size);
+			vnode->netfs.zero_point = status->size;
 			inode_set_ctime_to_ts(inode, t);
 			inode->i_atime = t;
 		}
@@ -865,17 +866,17 @@ static void afs_setattr_success(struct afs_operation *op)
 static void afs_setattr_edit_file(struct afs_operation *op)
 {
 	struct afs_vnode_param *vp = &op->file[0];
-	struct inode *inode = &vp->vnode->netfs.inode;
+	struct afs_vnode *vnode = vp->vnode;
 
 	if (op->setattr.attr->ia_valid & ATTR_SIZE) {
 		loff_t size = op->setattr.attr->ia_size;
 		loff_t i_size = op->setattr.old_i_size;
 
-		if (size < i_size)
-			truncate_pagecache(inode, size);
-		if (size != i_size)
-			fscache_resize_cookie(afs_vnode_cache(vp->vnode),
-					      vp->scb.status.size);
+		if (size != i_size) {
+			truncate_pagecache(&vnode->netfs.inode, size);
+			netfs_resize_file(&vnode->netfs, size);
+			fscache_resize_cookie(afs_vnode_cache(vnode), size);
+		}
 	}
 }
 
diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c
index 2cd3ccf4c439..a2852fa64ad0 100644
--- a/fs/netfs/buffered_read.c
+++ b/fs/netfs/buffered_read.c
@@ -147,6 +147,22 @@ static void netfs_rreq_expand(struct netfs_io_request *rreq,
 	}
 }
 
+/*
+ * Begin an operation, and fetch the stored zero point value from the cookie if
+ * available.
+ */
+static int netfs_begin_cache_operation(struct netfs_io_request *rreq,
+				       struct netfs_inode *ctx)
+{
+	int ret = -ENOBUFS;
+
+	if (ctx->ops->begin_cache_operation) {
+		ret = ctx->ops->begin_cache_operation(rreq);
+		/* TODO: Get the zero point value from the cache */
+	}
+	return ret;
+}
+
 /**
  * netfs_readahead - Helper to manage a read request
  * @ractl: The description of the readahead request
@@ -180,11 +196,9 @@ void netfs_readahead(struct readahead_control *ractl)
 	if (IS_ERR(rreq))
 		return;
 
-	if (ctx->ops->begin_cache_operation) {
-		ret = ctx->ops->begin_cache_operation(rreq);
-		if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
-			goto cleanup_free;
-	}
+	ret = netfs_begin_cache_operation(rreq, ctx);
+	if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
+		goto cleanup_free;
 
 	netfs_stat(&netfs_n_rh_readahead);
 	trace_netfs_read(rreq, readahead_pos(ractl), readahead_length(ractl),
@@ -238,11 +252,9 @@ int netfs_read_folio(struct file *file, struct folio *folio)
 		goto alloc_error;
 	}
 
-	if (ctx->ops->begin_cache_operation) {
-		ret = ctx->ops->begin_cache_operation(rreq);
-		if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
-			goto discard;
-	}
+	ret = netfs_begin_cache_operation(rreq, ctx);
+	if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
+		goto discard;
 
 	netfs_stat(&netfs_n_rh_readpage);
 	trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage);
@@ -390,11 +402,9 @@ int netfs_write_begin(struct netfs_inode *ctx,
 	rreq->no_unlock_folio	= folio_index(folio);
 	__set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags);
 
-	if (ctx->ops->begin_cache_operation) {
-		ret = ctx->ops->begin_cache_operation(rreq);
-		if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
-			goto error_put;
-	}
+	ret = netfs_begin_cache_operation(rreq, ctx);
+	if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
+		goto error_put;
 
 	netfs_stat(&netfs_n_rh_write_begin);
 	trace_netfs_read(rreq, pos, len, netfs_read_trace_write_begin);
diff --git a/include/linux/netfs.h b/include/linux/netfs.h
index b447cb67f599..282511090ead 100644
--- a/include/linux/netfs.h
+++ b/include/linux/netfs.h
@@ -129,6 +129,8 @@ struct netfs_inode {
 	struct fscache_cookie	*cache;
 #endif
 	loff_t			remote_i_size;	/* Size of the remote file */
+	loff_t			zero_point;	/* Size after which we assume there's no data
+						 * on the server */
 };
 
 /*
@@ -330,6 +332,7 @@ static inline void netfs_inode_init(struct netfs_inode *ctx,
 {
 	ctx->ops = ops;
 	ctx->remote_i_size = i_size_read(&ctx->inode);
+	ctx->zero_point = ctx->remote_i_size;
 #if IS_ENABLED(CONFIG_FSCACHE)
 	ctx->cache = NULL;
 #endif
@@ -345,6 +348,8 @@ static inline void netfs_inode_init(struct netfs_inode *ctx,
 static inline void netfs_resize_file(struct netfs_inode *ctx, loff_t new_i_size)
 {
 	ctx->remote_i_size = new_i_size;
+	if (new_i_size < ctx->zero_point)
+		ctx->zero_point = new_i_size;
 }
 
 /**


  parent reply	other threads:[~2023-10-13 16:04 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-13 16:03 [RFC PATCH 00/53] netfs, afs, cifs: Delegate high-level I/O to netfslib David Howells
2023-10-13 16:03 ` [RFC PATCH 01/53] netfs: Add a procfile to list in-progress requests David Howells
2023-10-13 16:03 ` David Howells [this message]
2023-10-13 16:03 ` [RFC PATCH 03/53] netfs: Note nonblockingness in the netfs_io_request struct David Howells
2023-10-13 16:03 ` [RFC PATCH 04/53] netfs: Allow the netfs to make the io (sub)request alloc larger David Howells
2023-10-13 16:03 ` [RFC PATCH 05/53] netfs: Add a ->free_subrequest() op David Howells
2023-10-13 16:03 ` [RFC PATCH 06/53] afs: Don't use folio->private to record partial modification David Howells
2023-10-13 16:03 ` [RFC PATCH 07/53] netfs: Provide invalidate_folio and release_folio calls David Howells
2023-10-16 15:50   ` Jeff Layton
2023-10-13 16:03 ` [RFC PATCH 08/53] netfs: Add rsize to netfs_io_request David Howells
2023-10-16 15:54   ` Jeff Layton
2023-10-16 16:19   ` David Howells
2023-10-13 16:03 ` [RFC PATCH 09/53] netfs: Implement unbuffered/DIO vs buffered I/O locking David Howells
2023-10-16 15:56   ` Jeff Layton
2023-10-16 16:09   ` David Howells
2023-10-13 16:03 ` [RFC PATCH 10/53] netfs: Add iov_iters to (sub)requests to describe various buffers David Howells
2023-10-13 16:03 ` [RFC PATCH 11/53] netfs: Add support for DIO buffering David Howells
2023-10-16 16:10   ` Jeff Layton
2023-11-17 20:20   ` David Howells
2023-10-13 16:03 ` [RFC PATCH 12/53] netfs: Provide tools to create a buffer in an xarray David Howells
2023-10-13 17:27   ` Matthew Wilcox
2023-10-18 15:03   ` Jeff Layton
2023-11-17 20:11   ` David Howells
2023-10-13 16:03 ` [RFC PATCH 13/53] netfs: Add bounce buffering support David Howells
2023-10-13 16:03 ` [RFC PATCH 14/53] netfs: Add func to calculate pagecount/size-limited span of an iterator David Howells
2023-10-13 16:03 ` [RFC PATCH 15/53] netfs: Limit subrequest by size or number of segments David Howells
2023-10-13 16:03 ` [RFC PATCH 16/53] netfs: Export netfs_put_subrequest() and some tracepoints David Howells
2023-10-13 16:03 ` [RFC PATCH 17/53] netfs: Extend the netfs_io_*request structs to handle writes David Howells
2023-10-13 16:03 ` [RFC PATCH 18/53] netfs: Add a hook to allow tell the netfs to update its i_size David Howells
2023-10-13 16:03 ` [RFC PATCH 19/53] netfs: Make netfs_put_request() handle a NULL pointer David Howells
2023-10-13 16:03 ` [RFC PATCH 20/53] fscache: Add a function to begin an cache op from a netfslib request David Howells
2023-10-13 16:03 ` [RFC PATCH 21/53] netfs: Make the refcounting of netfs_begin_read() easier to use David Howells
2023-10-13 16:03 ` [RFC PATCH 22/53] netfs: Prep to use folio->private for write grouping and streaming write David Howells
2023-10-13 16:03 ` [RFC PATCH 23/53] netfs: Dispatch write requests to process a writeback slice David Howells
2023-10-13 16:03 ` [RFC PATCH 24/53] netfs: Provide func to copy data to pagecache for buffered write David Howells
2023-10-13 16:03 ` [RFC PATCH 25/53] netfs: Make netfs_read_folio() handle streaming-write pages David Howells
2023-10-13 16:03 ` [RFC PATCH 26/53] netfs: Allocate multipage folios in the writepath David Howells
2023-10-13 16:03 ` [RFC PATCH 27/53] netfs: Implement support for unbuffered/DIO read David Howells
2023-10-13 16:03 ` [RFC PATCH 28/53] netfs: Implement unbuffered/DIO write support David Howells
2023-10-13 16:03 ` [RFC PATCH 29/53] netfs: Implement buffered write API David Howells
2023-10-13 16:03 ` [RFC PATCH 30/53] netfs: Allow buffered shared-writeable mmap through netfs_page_mkwrite() David Howells
2023-10-13 16:04 ` [RFC PATCH 31/53] netfs: Provide netfs_file_read_iter() David Howells
2023-10-13 16:04 ` [RFC PATCH 32/53] netfs: Provide a writepages implementation David Howells
2023-10-13 16:04 ` [RFC PATCH 33/53] netfs: Provide minimum blocksize parameter David Howells
2023-10-13 16:04 ` [RFC PATCH 34/53] netfs: Make netfs_skip_folio_read() take account of blocksize David Howells
2023-10-13 16:04 ` [RFC PATCH 35/53] netfs: Perform content encryption David Howells
2023-10-13 16:04 ` [RFC PATCH 36/53] netfs: Decrypt encrypted content David Howells
2023-10-13 16:04 ` [RFC PATCH 37/53] netfs: Support decryption on ubuffered/DIO read David Howells
2023-10-13 16:04 ` [RFC PATCH 38/53] netfs: Support encryption on Unbuffered/DIO write David Howells
2023-10-13 16:04 ` [RFC PATCH 39/53] netfs: Provide a launder_folio implementation David Howells
2023-10-13 16:04 ` [RFC PATCH 40/53] netfs: Implement a write-through caching option David Howells
2023-10-13 16:04 ` [RFC PATCH 41/53] netfs: Rearrange netfs_io_subrequest to put request pointer first David Howells
2023-10-13 16:04 ` [RFC PATCH 42/53] afs: Use the netfs write helpers David Howells
2023-10-13 16:04 ` [RFC PATCH 43/53] cifs: Replace cifs_readdata with a wrapper around netfs_io_subrequest David Howells
2023-10-13 16:04 ` [RFC PATCH 44/53] cifs: Share server EOF pos with netfslib David Howells
2023-10-13 16:04 ` [RFC PATCH 45/53] cifs: Replace cifs_writedata with a wrapper around netfs_io_subrequest David Howells
2023-10-13 16:04 ` [RFC PATCH 46/53] cifs: Use more fields from netfs_io_subrequest David Howells
2023-10-13 16:04 ` [RFC PATCH 47/53] cifs: Make wait_mtu_credits take size_t args David Howells
2023-10-13 16:04 ` [RFC PATCH 48/53] cifs: Implement netfslib hooks David Howells
2023-10-13 16:04 ` [RFC PATCH 49/53] cifs: Move cifs_loose_read_iter() and cifs_file_write_iter() to file.c David Howells
2023-10-13 16:04 ` [RFC PATCH 50/53] cifs: Cut over to using netfslib David Howells
2023-10-13 16:04 ` [RFC PATCH 51/53] cifs: Remove some code that's no longer used, part 1 David Howells
2023-10-13 16:04 ` [RFC PATCH 52/53] cifs: Remove some code that's no longer used, part 2 David Howells
2023-10-13 16:04 ` [RFC PATCH 53/53] cifs: Remove some code that's no longer used, part 3 David Howells
  -- strict thread matches above, loose matches on Subject: below --
2023-10-13 15:56 [RFC PATCH 00/53] netfs, afs, cifs: Delegate high-level I/O to netfslib David Howells
2023-10-13 15:56 ` [RFC PATCH 02/53] netfs: Track the fpos above which the server has no data David Howells
2023-10-16 15:43   ` Jeff Layton
2023-10-16 16:31   ` David Howells

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=20231013160423.2218093-3-dhowells@redhat.com \
    --to=dhowells@redhat.com \
    --cc=asmadeus@codewreck.org \
    --cc=ceph-devel@vger.kernel.org \
    --cc=christian@brauner.io \
    --cc=idryomov@gmail.com \
    --cc=jlayton@kernel.org \
    --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=netdev@vger.kernel.org \
    --cc=pc@manguebit.com \
    --cc=smfrench@gmail.com \
    --cc=sprasad@microsoft.com \
    --cc=tom@talpey.com \
    --cc=v9fs@lists.linux.dev \
    --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.