Skip to content

Commit 35219bc

Browse files
committed
Merge tag 'vfs-6.12.netfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull netfs updates from Christian Brauner: "This contains the work to improve read/write performance for the new netfs library. The main performance enhancing changes are: - Define a structure, struct folio_queue, and a new iterator type, ITER_FOLIOQ, to hold a buffer as a replacement for ITER_XARRAY. See that patch for questions about naming and form. ITER_FOLIOQ is provided as a replacement for ITER_XARRAY. The problem with an xarray is that accessing it requires the use of a lock (typically the RCU read lock) - and this means that we can't supply iterate_and_advance() with a step function that might sleep (crypto for example) without having to drop the lock between pages. ITER_FOLIOQ is the iterator for a chain of folio_queue structs, where each folio_queue holds a small list of folios. A folio_queue struct is a simpler structure than xarray and is not subject to concurrent manipulation by the VM. folio_queue is used rather than a bvec[] as it can form lists of indefinite size, adding to one end and removing from the other on the fly. - Provide a copy_folio_from_iter() wrapper. - Make cifs RDMA support ITER_FOLIOQ. - Use folio queues in the write-side helpers instead of xarrays. - Add a function to reset the iterator in a subrequest. - Simplify the write-side helpers to use sheaves to skip gaps rather than trying to work out where gaps are. - In afs, make the read subrequests asynchronous, putting them into work items to allow the next patch to do progressive unlocking/reading. - Overhaul the read-side helpers to improve performance. - Fix the caching of a partial block at the end of a file. - Allow a store to be cancelled. Then some changes for cifs to make it use folio queues instead of xarrays for crypto bufferage: - Use raw iteration functions rather than manually coding iteration when hashing data. - Switch to using folio_queue for crypto buffers. - Remove the xarray bits. Make some adjustments to the /proc/fs/netfs/stats file such that: - All the netfs stats lines begin 'Netfs:' but change this to something a bit more useful. - Add a couple of stats counters to track the numbers of skips and waits on the per-inode writeback serialisation lock to make it easier to check for this as a source of performance loss. Miscellaneous work: - Ensure that the sb_writers lock is taken around vfs_{set,remove}xattr() in the cachefiles code. - Reduce the number of conditional branches in netfs_perform_write(). - Move the CIFS_INO_MODIFIED_ATTR flag to the netfs_inode struct and remove cifs_post_modify(). - Move the max_len/max_nr_segs members from netfs_io_subrequest to netfs_io_request as they're only needed for one subreq at a time. - Add an 'unknown' source value for tracing purposes. - Remove NETFS_COPY_TO_CACHE as it's no longer used. - Set the request work function up front at allocation time. - Use bh-disabling spinlocks for rreq->lock as cachefiles completion may be run from block-filesystem DIO completion in softirq context. - Remove fs/netfs/io.c" * tag 'vfs-6.12.netfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (25 commits) docs: filesystems: corrected grammar of netfs page cifs: Don't support ITER_XARRAY cifs: Switch crypto buffer to use a folio_queue rather than an xarray cifs: Use iterate_and_advance*() routines directly for hashing netfs: Cancel dirty folios that have no storage destination cachefiles, netfs: Fix write to partial block at EOF netfs: Remove fs/netfs/io.c netfs: Speed up buffered reading afs: Make read subreqs async netfs: Simplify the writeback code netfs: Provide an iterator-reset function netfs: Use new folio_queue data type and iterator instead of xarray iter cifs: Provide the capability to extract from ITER_FOLIOQ to RDMA SGEs iov_iter: Provide copy_folio_from_iter() mm: Define struct folio_queue and ITER_FOLIOQ to handle a sequence of folios netfs: Use bh-disabling spinlocks for rreq->lock netfs: Set the request work function upon allocation netfs: Remove NETFS_COPY_TO_CACHE netfs: Reserve netfs_sreq_source 0 as unset/unknown netfs: Move max_len/max_nr_segs from netfs_io_subrequest to netfs_io_stream ...
2 parents 9020d0d + 4b40d43 commit 35219bc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3523
-1986
lines changed

Documentation/filesystems/netfs_library.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ The following services are provided:
116116
* Handle local caching, allowing cached data and server-read data to be
117117
interleaved for a single request.
118118

119-
* Handle clearing of bufferage that aren't on the server.
119+
* Handle clearing of bufferage that isn't on the server.
120120

121121
* Handle retrying of reads that failed, switching reads from the cache to the
122122
server as necessary.

fs/9p/vfs_addr.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,22 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq)
6868
{
6969
struct netfs_io_request *rreq = subreq->rreq;
7070
struct p9_fid *fid = rreq->netfs_priv;
71+
unsigned long long pos = subreq->start + subreq->transferred;
7172
int total, err;
7273

73-
total = p9_client_read(fid, subreq->start + subreq->transferred,
74-
&subreq->io_iter, &err);
74+
total = p9_client_read(fid, pos, &subreq->io_iter, &err);
7575

7676
/* if we just extended the file size, any portion not in
7777
* cache won't be on server and is zeroes */
7878
if (subreq->rreq->origin != NETFS_DIO_READ)
7979
__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
80+
if (pos + total >= i_size_read(rreq->inode))
81+
__set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags);
8082

81-
netfs_subreq_terminated(subreq, err ?: total, false);
83+
if (!err)
84+
subreq->transferred += total;
85+
86+
netfs_read_subreq_terminated(subreq, err, false);
8287
}
8388

8489
/**

fs/afs/file.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/mm.h>
1717
#include <linux/swap.h>
1818
#include <linux/netfs.h>
19+
#include <trace/events/netfs.h>
1920
#include "internal.h"
2021

2122
static int afs_file_mmap(struct file *file, struct vm_area_struct *vma);
@@ -242,9 +243,10 @@ static void afs_fetch_data_notify(struct afs_operation *op)
242243

243244
req->error = error;
244245
if (subreq) {
245-
if (subreq->rreq->origin != NETFS_DIO_READ)
246-
__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
247-
netfs_subreq_terminated(subreq, error ?: req->actual_len, false);
246+
subreq->rreq->i_size = req->file_size;
247+
if (req->pos + req->actual_len >= req->file_size)
248+
__set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags);
249+
netfs_read_subreq_terminated(subreq, error, false);
248250
req->subreq = NULL;
249251
} else if (req->done) {
250252
req->done(req);
@@ -262,6 +264,12 @@ static void afs_fetch_data_success(struct afs_operation *op)
262264
afs_fetch_data_notify(op);
263265
}
264266

267+
static void afs_fetch_data_aborted(struct afs_operation *op)
268+
{
269+
afs_check_for_remote_deletion(op);
270+
afs_fetch_data_notify(op);
271+
}
272+
265273
static void afs_fetch_data_put(struct afs_operation *op)
266274
{
267275
op->fetch.req->error = afs_op_error(op);
@@ -272,7 +280,7 @@ static const struct afs_operation_ops afs_fetch_data_operation = {
272280
.issue_afs_rpc = afs_fs_fetch_data,
273281
.issue_yfs_rpc = yfs_fs_fetch_data,
274282
.success = afs_fetch_data_success,
275-
.aborted = afs_check_for_remote_deletion,
283+
.aborted = afs_fetch_data_aborted,
276284
.failed = afs_fetch_data_notify,
277285
.put = afs_fetch_data_put,
278286
};
@@ -294,7 +302,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req)
294302
op = afs_alloc_operation(req->key, vnode->volume);
295303
if (IS_ERR(op)) {
296304
if (req->subreq)
297-
netfs_subreq_terminated(req->subreq, PTR_ERR(op), false);
305+
netfs_read_subreq_terminated(req->subreq, PTR_ERR(op), false);
298306
return PTR_ERR(op);
299307
}
300308

@@ -305,14 +313,15 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req)
305313
return afs_do_sync_operation(op);
306314
}
307315

308-
static void afs_issue_read(struct netfs_io_subrequest *subreq)
316+
static void afs_read_worker(struct work_struct *work)
309317
{
318+
struct netfs_io_subrequest *subreq = container_of(work, struct netfs_io_subrequest, work);
310319
struct afs_vnode *vnode = AFS_FS_I(subreq->rreq->inode);
311320
struct afs_read *fsreq;
312321

313322
fsreq = afs_alloc_read(GFP_NOFS);
314323
if (!fsreq)
315-
return netfs_subreq_terminated(subreq, -ENOMEM, false);
324+
return netfs_read_subreq_terminated(subreq, -ENOMEM, false);
316325

317326
fsreq->subreq = subreq;
318327
fsreq->pos = subreq->start + subreq->transferred;
@@ -321,10 +330,17 @@ static void afs_issue_read(struct netfs_io_subrequest *subreq)
321330
fsreq->vnode = vnode;
322331
fsreq->iter = &subreq->io_iter;
323332

333+
trace_netfs_sreq(subreq, netfs_sreq_trace_submit);
324334
afs_fetch_data(fsreq->vnode, fsreq);
325335
afs_put_read(fsreq);
326336
}
327337

338+
static void afs_issue_read(struct netfs_io_subrequest *subreq)
339+
{
340+
INIT_WORK(&subreq->work, afs_read_worker);
341+
queue_work(system_long_wq, &subreq->work);
342+
}
343+
328344
static int afs_symlink_read_folio(struct file *file, struct folio *folio)
329345
{
330346
struct afs_vnode *vnode = AFS_FS_I(folio->mapping->host);

fs/afs/fsclient.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
304304
struct afs_vnode_param *vp = &op->file[0];
305305
struct afs_read *req = op->fetch.req;
306306
const __be32 *bp;
307+
size_t count_before;
307308
int ret;
308309

309310
_enter("{%u,%zu,%zu/%llu}",
@@ -345,10 +346,14 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
345346

346347
/* extract the returned data */
347348
case 2:
348-
_debug("extract data %zu/%llu",
349-
iov_iter_count(call->iter), req->actual_len);
349+
count_before = call->iov_len;
350+
_debug("extract data %zu/%llu", count_before, req->actual_len);
350351

351352
ret = afs_extract_data(call, true);
353+
if (req->subreq) {
354+
req->subreq->transferred += count_before - call->iov_len;
355+
netfs_read_subreq_progress(req->subreq, false);
356+
}
352357
if (ret < 0)
353358
return ret;
354359

fs/afs/write.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ static const struct afs_operation_ops afs_store_data_operation = {
8989
*/
9090
void afs_prepare_write(struct netfs_io_subrequest *subreq)
9191
{
92+
struct netfs_io_stream *stream = &subreq->rreq->io_streams[subreq->stream_nr];
93+
9294
//if (test_bit(NETFS_SREQ_RETRYING, &subreq->flags))
9395
// subreq->max_len = 512 * 1024;
9496
//else
95-
subreq->max_len = 256 * 1024 * 1024;
97+
stream->sreq_max_len = 256 * 1024 * 1024;
9698
}
9799

98100
/*

fs/afs/yfsclient.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
355355
struct afs_vnode_param *vp = &op->file[0];
356356
struct afs_read *req = op->fetch.req;
357357
const __be32 *bp;
358+
size_t count_before;
358359
int ret;
359360

360361
_enter("{%u,%zu, %zu/%llu}",
@@ -391,10 +392,14 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
391392

392393
/* extract the returned data */
393394
case 2:
394-
_debug("extract data %zu/%llu",
395-
iov_iter_count(call->iter), req->actual_len);
395+
count_before = call->iov_len;
396+
_debug("extract data %zu/%llu", count_before, req->actual_len);
396397

397398
ret = afs_extract_data(call, true);
399+
if (req->subreq) {
400+
req->subreq->transferred += count_before - call->iov_len;
401+
netfs_read_subreq_progress(req->subreq, false);
402+
}
398403
if (ret < 0)
399404
return ret;
400405

fs/cachefiles/io.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,11 +627,12 @@ static void cachefiles_prepare_write_subreq(struct netfs_io_subrequest *subreq)
627627
{
628628
struct netfs_io_request *wreq = subreq->rreq;
629629
struct netfs_cache_resources *cres = &wreq->cache_resources;
630+
struct netfs_io_stream *stream = &wreq->io_streams[subreq->stream_nr];
630631

631632
_enter("W=%x[%x] %llx", wreq->debug_id, subreq->debug_index, subreq->start);
632633

633-
subreq->max_len = MAX_RW_COUNT;
634-
subreq->max_nr_segs = BIO_MAX_VECS;
634+
stream->sreq_max_len = MAX_RW_COUNT;
635+
stream->sreq_max_segs = BIO_MAX_VECS;
635636

636637
if (!cachefiles_cres_file(cres)) {
637638
if (!fscache_wait_for_operation(cres, FSCACHE_WANT_WRITE))
@@ -647,6 +648,7 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq)
647648
struct netfs_cache_resources *cres = &wreq->cache_resources;
648649
struct cachefiles_object *object = cachefiles_cres_object(cres);
649650
struct cachefiles_cache *cache = object->volume->cache;
651+
struct netfs_io_stream *stream = &wreq->io_streams[subreq->stream_nr];
650652
const struct cred *saved_cred;
651653
size_t off, pre, post, len = subreq->len;
652654
loff_t start = subreq->start;
@@ -660,6 +662,7 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq)
660662
if (off) {
661663
pre = CACHEFILES_DIO_BLOCK_SIZE - off;
662664
if (pre >= len) {
665+
fscache_count_dio_misfit();
663666
netfs_write_subrequest_terminated(subreq, len, false);
664667
return;
665668
}
@@ -670,10 +673,22 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq)
670673
}
671674

672675
/* We also need to end on the cache granularity boundary */
676+
if (start + len == wreq->i_size) {
677+
size_t part = len % CACHEFILES_DIO_BLOCK_SIZE;
678+
size_t need = CACHEFILES_DIO_BLOCK_SIZE - part;
679+
680+
if (part && stream->submit_extendable_to >= need) {
681+
len += need;
682+
subreq->len += need;
683+
subreq->io_iter.count += need;
684+
}
685+
}
686+
673687
post = len & (CACHEFILES_DIO_BLOCK_SIZE - 1);
674688
if (post) {
675689
len -= post;
676690
if (len == 0) {
691+
fscache_count_dio_misfit();
677692
netfs_write_subrequest_terminated(subreq, post, false);
678693
return;
679694
}

fs/cachefiles/xattr.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,15 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
6464
memcpy(buf->data, fscache_get_aux(object->cookie), len);
6565

6666
ret = cachefiles_inject_write_error();
67-
if (ret == 0)
68-
ret = vfs_setxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache,
69-
buf, sizeof(struct cachefiles_xattr) + len, 0);
67+
if (ret == 0) {
68+
ret = mnt_want_write_file(file);
69+
if (ret == 0) {
70+
ret = vfs_setxattr(&nop_mnt_idmap, dentry,
71+
cachefiles_xattr_cache, buf,
72+
sizeof(struct cachefiles_xattr) + len, 0);
73+
mnt_drop_write_file(file);
74+
}
75+
}
7076
if (ret < 0) {
7177
trace_cachefiles_vfs_error(object, file_inode(file), ret,
7278
cachefiles_trace_setxattr_error);
@@ -151,8 +157,14 @@ int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
151157
int ret;
152158

153159
ret = cachefiles_inject_remove_error();
154-
if (ret == 0)
155-
ret = vfs_removexattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache);
160+
if (ret == 0) {
161+
ret = mnt_want_write(cache->mnt);
162+
if (ret == 0) {
163+
ret = vfs_removexattr(&nop_mnt_idmap, dentry,
164+
cachefiles_xattr_cache);
165+
mnt_drop_write(cache->mnt);
166+
}
167+
}
156168
if (ret < 0) {
157169
trace_cachefiles_vfs_error(object, d_inode(dentry), ret,
158170
cachefiles_trace_remxattr_error);
@@ -208,9 +220,15 @@ bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume)
208220
memcpy(buf->data, p, volume->vcookie->coherency_len);
209221

210222
ret = cachefiles_inject_write_error();
211-
if (ret == 0)
212-
ret = vfs_setxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache,
213-
buf, len, 0);
223+
if (ret == 0) {
224+
ret = mnt_want_write(volume->cache->mnt);
225+
if (ret == 0) {
226+
ret = vfs_setxattr(&nop_mnt_idmap, dentry,
227+
cachefiles_xattr_cache,
228+
buf, len, 0);
229+
mnt_drop_write(volume->cache->mnt);
230+
}
231+
}
214232
if (ret < 0) {
215233
trace_cachefiles_vfs_error(NULL, d_inode(dentry), ret,
216234
cachefiles_trace_setxattr_error);

0 commit comments

Comments
 (0)