Merge tag 'notifications-pipe-prep-20191115' of git://git.kernel.org/pub/scm/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Nov 2019 22:12:13 +0000 (14:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Nov 2019 22:12:13 +0000 (14:12 -0800)
Pull pipe rework from David Howells:
 "This is my set of preparatory patches for building a general
  notification queue on top of pipes. It makes a number of significant
  changes:

   - It removes the nr_exclusive argument from __wake_up_sync_key() as
     this is always 1. This prepares for the next step:

   - Adds wake_up_interruptible_sync_poll_locked() so that poll can be
     woken up from a function that's holding the poll waitqueue
     spinlock.

   - Change the pipe buffer ring to be managed in terms of unbounded
     head and tail indices rather than bounded index and length. This
     means that reading the pipe only needs to modify one index, not
     two.

   - A selection of helper functions are provided to query the state of
     the pipe buffer, plus a couple to apply updates to the pipe
     indices.

   - The pipe ring is allowed to have kernel-reserved slots. This allows
     many notification messages to be spliced in by the kernel without
     allowing userspace to pin too many pages if it writes to the same
     pipe.

   - Advance the head and tail indices inside the pipe waitqueue lock
     and use wake_up_interruptible_sync_poll_locked() to poke poll
     without having to take the lock twice.

   - Rearrange pipe_write() to preallocate the buffer it is going to
     write into and then drop the spinlock. This allows kernel
     notifications to then be added the ring whilst it is filling the
     buffer it allocated. The read side is stalled because the pipe
     mutex is still held.

   - Don't wake up readers on a pipe if there was already data in it
     when we added more.

   - Don't wake up writers on a pipe if the ring wasn't full before we
     removed a buffer"

* tag 'notifications-pipe-prep-20191115' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
  pipe: Remove sync on wake_ups
  pipe: Increase the writer-wakeup threshold to reduce context-switch count
  pipe: Check for ring full inside of the spinlock in pipe_write()
  pipe: Remove redundant wakeup from pipe_write()
  pipe: Rearrange sequence in pipe_write() to preallocate slot
  pipe: Conditionalise wakeup in pipe_read()
  pipe: Advance tail pointer inside of wait spinlock in pipe_read()
  pipe: Allow pipes to have kernel-reserved slots
  pipe: Use head and tail pointers for the ring, not cursor and length
  Add wake_up_interruptible_sync_poll_locked()
  Remove the nr_exclusive argument from __wake_up_sync_key()
  pipe: Reduce #inclusion of pipe_fs_i.h

1  2 
drivers/char/virtio_console.c
fs/exec.c
fs/fuse/dev.c
fs/ocfs2/aops.c
fs/pipe.c
fs/splice.c
kernel/exit.c

@@@ -943,7 -939,9 +939,9 @@@ static ssize_t port_fops_splice_write(s
        if (ret < 0)
                goto error_out;
  
-       buf = alloc_buf(port->portdev->vdev, 0, pipe->nrbufs);
+       occupancy = pipe_occupancy(pipe->head, pipe->tail);
+       buf = alloc_buf(port->portdev->vdev, 0, occupancy);
 -                      
++
        if (!buf) {
                ret = -ENOMEM;
                goto error_out;
diff --cc fs/exec.c
Simple merge
diff --cc fs/fuse/dev.c
Simple merge
diff --cc fs/ocfs2/aops.c
Simple merge
diff --cc fs/pipe.c
Simple merge
diff --cc fs/splice.c
@@@ -1181,15 -1195,8 +1195,15 @@@ static long do_splice(struct file *in, 
  
                pipe_lock(opipe);
                ret = wait_for_space(opipe, flags);
 -              if (!ret)
 +              if (!ret) {
-                       unsigned int pipe_pages;
++                      unsigned int p_space;
 +
 +                      /* Don't try to read more the pipe has space for. */
-                       pipe_pages = opipe->buffers - opipe->nrbufs;
-                       len = min(len, (size_t)pipe_pages << PAGE_SHIFT);
++                      p_space = opipe->max_usage - pipe_occupancy(opipe->head, opipe->tail);
++                      len = min_t(size_t, len, p_space << PAGE_SHIFT);
 +
                        ret = do_splice_to(in, &offset, opipe, len, flags);
 +              }
                pipe_unlock(opipe);
                if (ret > 0)
                        wakeup_pipe_readers(opipe);
diff --cc kernel/exit.c
Simple merge