Skip to content

Commit 6698c02

Browse files
dhowellsbrauner
authored andcommitted
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: David Howells <[email protected]> Link: https://lore.kernel.org/r/[email protected] cc: Marc Dionne <[email protected]> cc: [email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent a5b5bee commit 6698c02

File tree

5 files changed

+45
-8
lines changed

5 files changed

+45
-8
lines changed

fs/afs/dir.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,8 @@ static void afs_vnode_new_inode(struct afs_operation *op)
12761276
set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
12771277
if (S_ISDIR(inode->i_mode))
12781278
afs_mkdir_init_dir(vnode, dvp->vnode);
1279+
else if (S_ISLNK(inode->i_mode))
1280+
afs_init_new_symlink(vnode, op);
12791281
if (!afs_op_error(op))
12801282
afs_cache_permit(vnode, op->key, vnode->cb_break, &vp->scb);
12811283
d_instantiate(op->dentry, inode);

fs/afs/inode.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@
2525
#include "internal.h"
2626
#include "afs_fs.h"
2727

28+
void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op)
29+
{
30+
size_t size = strlen(op->create.symlink) + 1;
31+
size_t dsize = 0;
32+
char *p;
33+
34+
if (netfs_alloc_folioq_buffer(NULL, &vnode->directory, &dsize, size,
35+
mapping_gfp_mask(vnode->netfs.inode.i_mapping)) < 0)
36+
return;
37+
38+
vnode->directory_size = dsize;
39+
p = kmap_local_folio(folioq_folio(vnode->directory, 0), 0);
40+
memcpy(p, op->create.symlink, size);
41+
kunmap_local(p);
42+
set_bit(AFS_VNODE_DIR_READ, &vnode->flags);
43+
netfs_single_mark_inode_dirty(&vnode->netfs.inode);
44+
}
45+
2846
static void afs_put_link(void *arg)
2947
{
3048
struct folio *folio = virt_to_folio(arg);
@@ -41,15 +59,31 @@ const char *afs_get_link(struct dentry *dentry, struct inode *inode,
4159
char *content;
4260
ssize_t ret;
4361

44-
if (atomic64_read(&vnode->cb_expires_at) == AFS_NO_CB_PROMISE ||
45-
!test_bit(AFS_VNODE_DIR_READ, &vnode->flags)) {
46-
if (!dentry)
62+
if (!dentry) {
63+
/* RCU pathwalk. */
64+
if (!test_bit(AFS_VNODE_DIR_READ, &vnode->flags) || !afs_check_validity(vnode))
4765
return ERR_PTR(-ECHILD);
48-
ret = afs_read_single(vnode, NULL);
49-
if (ret < 0)
50-
return ERR_PTR(ret);
66+
goto good;
5167
}
5268

69+
if (test_bit(AFS_VNODE_DIR_READ, &vnode->flags))
70+
goto fetch;
71+
72+
ret = afs_validate(vnode, NULL);
73+
if (ret < 0)
74+
return ERR_PTR(ret);
75+
76+
if (!test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
77+
test_bit(AFS_VNODE_DIR_READ, &vnode->flags))
78+
goto good;
79+
80+
fetch:
81+
ret = afs_read_single(vnode, NULL);
82+
if (ret < 0)
83+
return ERR_PTR(ret);
84+
set_bit(AFS_VNODE_DIR_READ, &vnode->flags);
85+
86+
good:
5387
folio = folioq_folio(vnode->directory, 0);
5488
folio_get(folio);
5589
content = kmap_local_folio(folio, 0);

fs/afs/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,7 @@ extern void afs_fs_probe_cleanup(struct afs_net *);
12211221
*/
12221222
extern const struct afs_operation_ops afs_fetch_status_operation;
12231223

1224+
void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op);
12241225
const char *afs_get_link(struct dentry *dentry, struct inode *inode,
12251226
struct delayed_call *callback);
12261227
int afs_readlink(struct dentry *dentry, char __user *buffer, int buflen);

fs/netfs/buffered_read.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
210210

211211
do {
212212
struct netfs_io_subrequest *subreq;
213-
enum netfs_io_source source = NETFS_DOWNLOAD_FROM_SERVER;
213+
enum netfs_io_source source = NETFS_SOURCE_UNKNOWN;
214214
ssize_t slice;
215215

216216
subreq = netfs_alloc_subrequest(rreq);

fs/netfs/read_single.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static int netfs_single_dispatch_read(struct netfs_io_request *rreq)
9797
if (!subreq)
9898
return -ENOMEM;
9999

100-
subreq->source = NETFS_DOWNLOAD_FROM_SERVER;
100+
subreq->source = NETFS_SOURCE_UNKNOWN;
101101
subreq->start = 0;
102102
subreq->len = rreq->len;
103103
subreq->io_iter = rreq->buffer.iter;

0 commit comments

Comments
 (0)