Merge tag 'vfs-6.12.netfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 16 Sep 2024 10:13:31 +0000 (12:13 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 16 Sep 2024 10:13:31 +0000 (12:13 +0200)
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
  ...

1  2 
fs/ceph/addr.c
fs/netfs/main.c
fs/smb/client/cifssmb.c
fs/smb/client/smb2ops.c

diff --cc fs/ceph/addr.c
Simple merge
diff --cc fs/netfs/main.c
Simple merge
index cfae2e91820994f4aeded6dad23ed09ea65c5220,04f2a5441a89ee459759ed0907711efa65d03760..d81da161d3ed662505058a2c155a09021d0a64ca
@@@ -1261,16 -1261,6 +1261,14 @@@ openRetry
        return rc;
  }
  
-       netfs_subreq_terminated(&rdata->subreq,
-                               (rdata->result == 0 || rdata->result == -EAGAIN) ?
-                               rdata->got_bytes : rdata->result, true);
 +static void cifs_readv_worker(struct work_struct *work)
 +{
 +      struct cifs_io_subrequest *rdata =
 +              container_of(work, struct cifs_io_subrequest, subreq.work);
 +
++      netfs_read_subreq_terminated(&rdata->subreq, rdata->result, true);
 +}
 +
  static void
  cifs_readv_callback(struct mid_q_entry *mid)
  {
                rdata->result = -EIO;
        }
  
 -      if (rdata->result == 0 || rdata->result == -EAGAIN)
 -              iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
 +      if (rdata->result == -ENODATA) {
 +              __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
 +              rdata->result = 0;
 +      } else {
-               if (rdata->got_bytes < rdata->actual_len &&
-                   rdata->subreq.start + rdata->subreq.transferred + rdata->got_bytes ==
-                   ictx->remote_i_size) {
++              size_t trans = rdata->subreq.transferred + rdata->got_bytes;
++              if (trans < rdata->subreq.len &&
++                  rdata->subreq.start + trans == ictx->remote_i_size) {
 +                      __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
 +                      rdata->result = 0;
 +              }
 +      }
 +
        rdata->credits.value = 0;
 -      netfs_read_subreq_terminated(&rdata->subreq, rdata->result, false);
+       rdata->subreq.transferred += rdata->got_bytes;
 +      INIT_WORK(&rdata->subreq.work, cifs_readv_worker);
 +      queue_work(cifsiod_wq, &rdata->subreq.work);
        release_mid(mid);
        add_credits(server, &credits, 0);
  }
Simple merge