Unverified Commit 6698c02d authored by David Howells's avatar David Howells Committed by Christian Brauner
Browse files

afs: Locally initialise the contents of a new symlink on creation



Since we know what the contents of a symlink will be when we create it on
the server, initialise its contents locally too to avoid the need to
download it.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/r/20241216204124.3752367-31-dhowells@redhat.com


cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent a5b5beeb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1276,6 +1276,8 @@ static void afs_vnode_new_inode(struct afs_operation *op)
	set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
	if (S_ISDIR(inode->i_mode))
		afs_mkdir_init_dir(vnode, dvp->vnode);
	else if (S_ISLNK(inode->i_mode))
		afs_init_new_symlink(vnode, op);
	if (!afs_op_error(op))
		afs_cache_permit(vnode, op->key, vnode->cb_break, &vp->scb);
	d_instantiate(op->dentry, inode);
+40 −6
Original line number Diff line number Diff line
@@ -25,6 +25,24 @@
#include "internal.h"
#include "afs_fs.h"

void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op)
{
	size_t size = strlen(op->create.symlink) + 1;
	size_t dsize = 0;
	char *p;

	if (netfs_alloc_folioq_buffer(NULL, &vnode->directory, &dsize, size,
				      mapping_gfp_mask(vnode->netfs.inode.i_mapping)) < 0)
		return;

	vnode->directory_size = dsize;
	p = kmap_local_folio(folioq_folio(vnode->directory, 0), 0);
	memcpy(p, op->create.symlink, size);
	kunmap_local(p);
	set_bit(AFS_VNODE_DIR_READ, &vnode->flags);
	netfs_single_mark_inode_dirty(&vnode->netfs.inode);
}

static void afs_put_link(void *arg)
{
	struct folio *folio = virt_to_folio(arg);
@@ -41,15 +59,31 @@ const char *afs_get_link(struct dentry *dentry, struct inode *inode,
	char *content;
	ssize_t ret;

	if (atomic64_read(&vnode->cb_expires_at) == AFS_NO_CB_PROMISE ||
	    !test_bit(AFS_VNODE_DIR_READ, &vnode->flags)) {
		if (!dentry)
	if (!dentry) {
		/* RCU pathwalk. */
		if (!test_bit(AFS_VNODE_DIR_READ, &vnode->flags) || !afs_check_validity(vnode))
			return ERR_PTR(-ECHILD);
		goto good;
	}

	if (test_bit(AFS_VNODE_DIR_READ, &vnode->flags))
		goto fetch;

	ret = afs_validate(vnode, NULL);
	if (ret < 0)
		return ERR_PTR(ret);

	if (!test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
	    test_bit(AFS_VNODE_DIR_READ, &vnode->flags))
		goto good;

fetch:
	ret = afs_read_single(vnode, NULL);
	if (ret < 0)
		return ERR_PTR(ret);
	}
	set_bit(AFS_VNODE_DIR_READ, &vnode->flags);

good:
	folio = folioq_folio(vnode->directory, 0);
	folio_get(folio);
	content = kmap_local_folio(folio, 0);
+1 −0
Original line number Diff line number Diff line
@@ -1221,6 +1221,7 @@ extern void afs_fs_probe_cleanup(struct afs_net *);
 */
extern const struct afs_operation_ops afs_fetch_status_operation;

void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op);
const char *afs_get_link(struct dentry *dentry, struct inode *inode,
			 struct delayed_call *callback);
int afs_readlink(struct dentry *dentry, char __user *buffer, int buflen);
+1 −1
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)

	do {
		struct netfs_io_subrequest *subreq;
		enum netfs_io_source source = NETFS_DOWNLOAD_FROM_SERVER;
		enum netfs_io_source source = NETFS_SOURCE_UNKNOWN;
		ssize_t slice;

		subreq = netfs_alloc_subrequest(rreq);
+1 −1
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ static int netfs_single_dispatch_read(struct netfs_io_request *rreq)
	if (!subreq)
		return -ENOMEM;

	subreq->source	= NETFS_DOWNLOAD_FROM_SERVER;
	subreq->source	= NETFS_SOURCE_UNKNOWN;
	subreq->start	= 0;
	subreq->len	= rreq->len;
	subreq->io_iter	= rreq->buffer.iter;