Skip to main content

starnix_core/vfs/
pipe.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::mm::{
6    MemoryAccessorExt, NumberOfElementsRead, PAGE_SIZE, TaskMemoryAccessor, read_to_vec,
7};
8use crate::security;
9use crate::signals::{SignalInfo, send_standard_signal};
10use crate::task::{CurrentTask, EventHandler, WaitCallback, WaitCanceler, WaitQueue, Waiter};
11use crate::vfs::buffers::{
12    Buffer, InputBuffer, InputBufferCallback, MessageData, MessageQueue, OutputBuffer,
13    OutputBufferCallback, PeekBufferSegmentsCallback, PipeMessageData, UserBuffersOutputBuffer,
14};
15use crate::vfs::fs_registry::FsRegistry;
16use crate::vfs::{
17    CacheMode, FileHandle, FileObject, FileObjectState, FileOps, FileSystem, FileSystemHandle,
18    FileSystemOps, FileSystemOptions, FsNodeInfo, FsStr, SpecialNode, default_fcntl,
19    fileops_impl_nonseekable, fileops_impl_noop_sync,
20};
21use starnix_sync::{Mutex, MutexGuard};
22use starnix_syscalls::{SUCCESS, SyscallArg, SyscallResult};
23use starnix_types::user_buffer::{UserBuffer, UserBuffers};
24use starnix_types::vfs::default_statfs;
25use starnix_uapi::auth::CAP_SYS_RESOURCE;
26use starnix_uapi::errors::Errno;
27use starnix_uapi::file_mode::mode;
28use starnix_uapi::open_flags::OpenFlags;
29use starnix_uapi::signals::SIGPIPE;
30use starnix_uapi::user_address::{UserAddress, UserRef};
31use starnix_uapi::vfs::FdEvents;
32use starnix_uapi::{
33    F_GETPIPE_SZ, F_SETPIPE_SZ, FIONREAD, PIPEFS_MAGIC, errno, error, statfs, uapi,
34};
35use std::cmp::Ordering;
36use std::sync::Arc;
37
38const ATOMIC_IO_BYTES: u16 = 4096;
39
40/// The maximum size of a pipe, independent of task capabilities and sysctl limits.
41const PIPE_MAX_SIZE: usize = 1 << 31;
42
43fn round_up(value: usize, increment: usize) -> usize {
44    (value + (increment - 1)) & !(increment - 1)
45}
46
47#[derive(Debug)]
48pub struct Pipe {
49    messages: MessageQueue<PipeMessageData>,
50
51    waiters: WaitQueue,
52
53    /// The number of open readers.
54    reader_count: usize,
55
56    /// Whether the pipe has ever had a reader.
57    had_reader: bool,
58
59    /// The number of open writers.
60    writer_count: usize,
61
62    /// Whether the pipe has ever had a writer.
63    had_writer: bool,
64}
65
66pub type PipeHandle = Arc<Mutex<Pipe>>;
67
68impl Pipe {
69    pub fn new(default_pipe_capacity: usize) -> PipeHandle {
70        Arc::new(
71            Pipe {
72                messages: MessageQueue::new(default_pipe_capacity),
73                waiters: WaitQueue::default(),
74                reader_count: 0,
75                had_reader: false,
76                writer_count: 0,
77                had_writer: false,
78            }
79            .into(),
80        )
81    }
82
83    pub fn open(
84        current_task: &CurrentTask,
85        pipe: &PipeHandle,
86        flags: OpenFlags,
87    ) -> Result<Box<dyn FileOps>, Errno> {
88        let mut events = FdEvents::empty();
89        let mut pipe_locked = pipe.lock();
90        let mut must_wait_events = FdEvents::empty();
91        if flags.can_read() {
92            if !pipe_locked.had_reader {
93                events |= FdEvents::POLLOUT;
94            }
95            pipe_locked.add_reader();
96            if !flags.contains(OpenFlags::NONBLOCK) && !flags.can_write() && !pipe_locked.had_writer
97            {
98                must_wait_events |= FdEvents::POLLIN;
99            }
100        }
101        if flags.can_write() {
102            // https://man7.org/linux/man-pages/man2/open.2.html says:
103            //
104            //  ENXIO  O_NONBLOCK | O_WRONLY is set, the named file is a FIFO,
105            //         and no process has the FIFO open for reading.
106            if flags.contains(OpenFlags::NONBLOCK) && pipe_locked.reader_count == 0 {
107                assert!(!flags.can_read()); // Otherwise we would have called add_reader() above.
108                return error!(ENXIO);
109            }
110            if !pipe_locked.had_writer {
111                events |= FdEvents::POLLIN;
112            }
113            pipe_locked.add_writer();
114            if !flags.contains(OpenFlags::NONBLOCK) && !pipe_locked.had_reader {
115                must_wait_events |= FdEvents::POLLOUT;
116            }
117        }
118        if events != FdEvents::empty() {
119            pipe_locked.waiters.notify_fd_events(events);
120        }
121        let ops = PipeFileObject { pipe: Arc::clone(pipe) };
122        if must_wait_events == FdEvents::empty() {
123            return Ok(Box::new(ops));
124        }
125
126        // Ensures that the new PipeFileObject is closed if is it dropped before being returned.
127        let ops = scopeguard::guard(ops, |ops| {
128            ops.on_close(flags);
129        });
130
131        // Wait for the pipe to be connected.
132        let waiter = Waiter::new();
133        loop {
134            pipe_locked.waiters.wait_async_fd_events(
135                &waiter,
136                must_wait_events,
137                WaitCallback::none(),
138            );
139            std::mem::drop(pipe_locked);
140            match waiter.wait(current_task) {
141                Err(e) => {
142                    return Err(e);
143                }
144                _ => {}
145            }
146            pipe_locked = pipe.lock();
147            if pipe_locked.had_writer && pipe_locked.had_reader {
148                return Ok(Box::new(scopeguard::ScopeGuard::into_inner(ops)));
149            }
150        }
151    }
152
153    /// Increments the reader count for this pipe by 1.
154    pub fn add_reader(&mut self) {
155        self.reader_count += 1;
156        self.had_reader = true;
157    }
158
159    /// Increments the writer count for this pipe by 1.
160    pub fn add_writer(&mut self) {
161        self.writer_count += 1;
162        self.had_writer = true;
163    }
164
165    /// Called whenever a fd to the pipe is closed. Reset the pipe state if there is not more
166    /// reader or writer.
167    pub fn on_close(&mut self) {
168        if self.reader_count == 0 && self.writer_count == 0 {
169            self.had_reader = false;
170            self.had_writer = false;
171            self.messages = MessageQueue::new(self.messages.capacity());
172            self.waiters = WaitQueue::default();
173        }
174    }
175
176    fn is_empty(&self) -> bool {
177        self.messages.is_empty()
178    }
179
180    fn capacity(&self) -> usize {
181        self.messages.capacity()
182    }
183
184    fn set_capacity(
185        &mut self,
186        current_task: &CurrentTask,
187        mut requested_capacity: usize,
188    ) -> Result<(), Errno> {
189        if requested_capacity > PIPE_MAX_SIZE {
190            return error!(EINVAL);
191        }
192        if requested_capacity
193            > current_task
194                .kernel()
195                .system_limits
196                .pipe_max_size
197                .load(std::sync::atomic::Ordering::Relaxed)
198        {
199            security::check_task_capable(current_task, CAP_SYS_RESOURCE)?;
200        }
201        let page_size = *PAGE_SIZE as usize;
202        if requested_capacity < page_size {
203            requested_capacity = page_size;
204        }
205        requested_capacity = round_up(requested_capacity, page_size);
206        self.messages.set_capacity(requested_capacity)
207    }
208
209    fn is_readable(&self) -> bool {
210        !self.is_empty() || (self.writer_count == 0 && self.had_writer)
211    }
212
213    /// Returns whether the pipe can accommodate at least part of a message of length `data_size`.
214    fn is_writable(&self, data_size: usize) -> bool {
215        let available_capacity = self.messages.available_capacity();
216        // POSIX requires that a write smaller than PIPE_BUF be atomic, but requires no
217        // atomicity for writes larger than this.
218        self.had_reader
219            && (available_capacity >= data_size
220                || (available_capacity > 0 && data_size > uapi::PIPE_BUF as usize))
221    }
222
223    pub fn read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
224        // If there isn't any data to read from the pipe, then the behavior
225        // depends on whether there are any open writers. If there is an
226        // open writer, then we return EAGAIN, to signal that the callers
227        // should wait for the writer to write something into the pipe.
228        // Otherwise, we'll fall through the rest of this function and
229        // return that we have read zero bytes, which will let the caller
230        // know that they're done reading the pipe.
231
232        if !self.is_readable() {
233            return error!(EAGAIN);
234        }
235
236        self.messages.read_stream(data).map(|info| info.bytes_read)
237    }
238
239    pub fn write(
240        &mut self,
241        current_task: &CurrentTask,
242        data: &mut dyn InputBuffer,
243    ) -> Result<usize, Errno> {
244        if !self.had_reader {
245            return error!(EAGAIN);
246        }
247
248        if self.reader_count == 0 {
249            send_standard_signal(current_task, SignalInfo::kernel(SIGPIPE));
250            return error!(EPIPE);
251        }
252
253        if !self.is_writable(data.available()) {
254            return error!(EAGAIN);
255        }
256
257        self.messages.write_stream(data, None, &mut vec![])
258    }
259
260    fn query_events(&self, flags: OpenFlags) -> FdEvents {
261        let mut events = FdEvents::empty();
262
263        if flags.can_read() && self.is_readable() {
264            let writer_closed = self.writer_count == 0 && self.had_writer;
265            let has_data = !self.is_empty();
266            if writer_closed {
267                events |= FdEvents::POLLHUP;
268            }
269            if !writer_closed || has_data {
270                events |= FdEvents::POLLIN;
271            }
272        }
273
274        if flags.can_write() && self.is_writable(1) {
275            if self.reader_count == 0 && self.had_reader {
276                events |= FdEvents::POLLERR;
277            }
278
279            events |= FdEvents::POLLOUT;
280        }
281
282        events
283    }
284
285    fn fcntl(
286        &mut self,
287        _file: &FileObject,
288        current_task: &CurrentTask,
289        cmd: u32,
290        arg: u64,
291    ) -> Result<SyscallResult, Errno> {
292        match cmd {
293            F_GETPIPE_SZ => Ok(self.capacity().into()),
294            F_SETPIPE_SZ => {
295                self.set_capacity(current_task, arg as usize)?;
296                Ok(self.capacity().into())
297            }
298            _ => default_fcntl(cmd),
299        }
300    }
301
302    fn ioctl(
303        &self,
304        _file: &FileObject,
305        current_task: &CurrentTask,
306        request: u32,
307        arg: SyscallArg,
308    ) -> Result<SyscallResult, Errno> {
309        let user_addr = UserAddress::from(arg);
310        match request {
311            FIONREAD => {
312                let addr = UserRef::<i32>::new(user_addr);
313                let value: i32 = self.messages.len().try_into().map_err(|_| errno!(EINVAL))?;
314                current_task.write_object(addr, &value)?;
315                Ok(SUCCESS)
316            }
317            _ => error!(ENOTTY),
318        }
319    }
320
321    fn notify_fd_events(&self, events: FdEvents) {
322        self.waiters.notify_fd_events(events);
323    }
324
325    /// Splice from the `from` pipe to the `to` pipe.
326    pub fn splice(from: &mut Pipe, to: &mut Pipe, len: usize) -> Result<usize, Errno> {
327        if len == 0 {
328            return Ok(0);
329        }
330        let to_was_empty = to.is_empty();
331        let mut bytes_transferred = 0;
332        loop {
333            let limit = std::cmp::min(len - bytes_transferred, to.messages.available_capacity());
334            if limit == 0 {
335                // We no longer want to transfer any bytes.
336                break;
337            }
338            let Some(mut message) = from.messages.read_message() else {
339                // The `from` pipe is empty.
340                break;
341            };
342            if let Some(data) = MessageData::split_off(&mut message.data, limit) {
343                // Some data is left in the message. Push it back.
344                assert!(data.len() > 0);
345                from.messages.write_front(data.into());
346            }
347            bytes_transferred += message.len();
348            to.messages.write_message(message);
349        }
350        if bytes_transferred > 0 {
351            if from.is_empty() {
352                from.notify_fd_events(FdEvents::POLLOUT);
353            }
354            if to_was_empty {
355                to.notify_fd_events(FdEvents::POLLIN);
356            }
357        }
358        return Ok(bytes_transferred);
359    }
360
361    /// Tee from the `from` pipe to the `to` pipe.
362    pub fn tee(from: &mut Pipe, to: &mut Pipe, len: usize) -> Result<usize, Errno> {
363        if len == 0 {
364            return Ok(0);
365        }
366        let to_was_empty = to.is_empty();
367        let mut bytes_transferred = 0;
368        for message in from.messages.peek_queue().iter() {
369            let limit = std::cmp::min(len - bytes_transferred, to.messages.available_capacity());
370            if limit == 0 {
371                break;
372            }
373            let message = message.clone_at_most(limit);
374            bytes_transferred += message.len();
375            to.messages.write_message(message);
376        }
377        if bytes_transferred > 0 && to_was_empty {
378            to.notify_fd_events(FdEvents::POLLIN);
379        }
380        return Ok(bytes_transferred);
381    }
382}
383
384/// Creates a new pipe between the two returned FileObjects.
385///
386/// The first FileObject is the read endpoint of the pipe. The second is the
387/// write endpoint of the pipe. This order matches the order expected by
388/// sys_pipe2().
389pub fn new_pipe(current_task: &CurrentTask) -> Result<(FileHandle, FileHandle), Errno> {
390    let fs = current_task
391        .kernel()
392        .expando
393        .get::<FsRegistry>()
394        .create(current_task, "pipefs".into(), FileSystemOptions::default())
395        .ok_or_else(|| errno!(EINVAL))??;
396    let mut info = FsNodeInfo::new(mode!(IFIFO, 0o600), current_task.current_fscred());
397    info.blksize = ATOMIC_IO_BYTES.into();
398    let node = fs.create_node_and_allocate_node_id(SpecialNode, info);
399    let pipe = node.fifo(current_task);
400    {
401        let mut state = pipe.lock();
402        state.add_reader();
403        state.add_writer();
404    }
405
406    // Creating the readable `FileObject` takes care of initializing the `node` security label.
407    let read_ops = PipeFileObject { pipe: Arc::clone(pipe) };
408    let read_file = FileObject::new_anonymous(
409        current_task,
410        Box::new(read_ops),
411        Arc::clone(&node),
412        OpenFlags::RDONLY,
413    );
414
415    // Create the writable `FileObject` using the readable object's `name` to reduce overhead.
416    let write_ops = PipeFileObject { pipe: Arc::clone(pipe) };
417    let write_file = FileObject::new(
418        current_task,
419        Box::new(write_ops),
420        read_file.name.to_passive(),
421        OpenFlags::WRONLY,
422    )?;
423
424    Ok((read_file, write_file))
425}
426
427struct PipeFs;
428impl FileSystemOps for PipeFs {
429    fn statfs(&self, _fs: &FileSystem, _current_task: &CurrentTask) -> Result<statfs, Errno> {
430        Ok(default_statfs(PIPEFS_MAGIC))
431    }
432    fn name(&self) -> &'static FsStr {
433        "pipefs".into()
434    }
435}
436
437fn pipe_fs(
438    current_task: &CurrentTask,
439    _options: FileSystemOptions,
440) -> Result<FileSystemHandle, Errno> {
441    struct PipeFsHandle(FileSystemHandle);
442
443    let kernel = current_task.kernel();
444    Ok(kernel
445        .expando
446        .get_or_init(|| {
447            PipeFsHandle(
448                FileSystem::new(kernel, CacheMode::Uncached, PipeFs, FileSystemOptions::default())
449                    .expect("pipefs constructed with valid options"),
450            )
451        })
452        .0
453        .clone())
454}
455
456pub fn register_pipe_fs(fs_registry: &FsRegistry) {
457    fs_registry.register("pipefs".into(), pipe_fs);
458}
459
460pub struct PipeFileObject {
461    pipe: PipeHandle,
462}
463
464impl FileOps for PipeFileObject {
465    fileops_impl_nonseekable!();
466    fileops_impl_noop_sync!();
467
468    fn close(self: Box<Self>, file: &FileObjectState, _current_task: &CurrentTask) {
469        self.on_close(file.flags());
470    }
471
472    fn read(
473        &self,
474        file: &FileObject,
475        current_task: &CurrentTask,
476        offset: usize,
477        data: &mut dyn OutputBuffer,
478    ) -> Result<usize, Errno> {
479        debug_assert!(offset == 0);
480        file.blocking_op(current_task, FdEvents::POLLIN | FdEvents::POLLHUP, None, || {
481            let mut pipe = self.pipe.lock();
482            let actual = pipe.read(data)?;
483            if actual > 0 && pipe.is_empty() {
484                pipe.notify_fd_events(FdEvents::POLLOUT);
485            }
486            Ok(actual)
487        })
488    }
489
490    fn write(
491        &self,
492        file: &FileObject,
493        current_task: &CurrentTask,
494        offset: usize,
495        data: &mut dyn InputBuffer,
496    ) -> Result<usize, Errno> {
497        debug_assert!(offset == 0);
498        debug_assert!(data.bytes_read() == 0);
499
500        let result = file.blocking_op(current_task, FdEvents::POLLOUT, None, || {
501            let mut pipe = self.pipe.lock();
502            let was_empty = pipe.is_empty();
503            let offset_before = data.bytes_read();
504            let bytes_written = pipe.write(current_task, data)?;
505            debug_assert!(data.bytes_read() - offset_before == bytes_written);
506            if bytes_written > 0 && was_empty {
507                pipe.notify_fd_events(FdEvents::POLLIN);
508            }
509            if data.available() > 0 {
510                return error!(EAGAIN);
511            }
512            Ok(())
513        });
514
515        let bytes_written = data.bytes_read();
516        if bytes_written == 0 {
517            // We can only return an error if no data was actually sent. If partial data was
518            // sent, swallow the error and return how much was sent.
519            result?;
520        }
521        Ok(bytes_written)
522    }
523
524    fn wait_async(
525        &self,
526        file: &FileObject,
527        _current_task: &CurrentTask,
528        waiter: &Waiter,
529        mut events: FdEvents,
530        handler: EventHandler,
531    ) -> Option<WaitCanceler> {
532        let flags = file.flags();
533        if !flags.can_read() {
534            events.remove(FdEvents::POLLIN);
535        }
536        if !flags.can_write() {
537            events.remove(FdEvents::POLLOUT);
538        }
539        Some(self.pipe.lock().waiters.wait_async_fd_events(waiter, events, handler))
540    }
541
542    fn query_events(
543        &self,
544        file: &FileObject,
545        _current_task: &CurrentTask,
546    ) -> Result<FdEvents, Errno> {
547        Ok(self.pipe.lock().query_events(file.flags()))
548    }
549
550    fn fcntl(
551        &self,
552        file: &FileObject,
553        current_task: &CurrentTask,
554        cmd: u32,
555        arg: u64,
556    ) -> Result<SyscallResult, Errno> {
557        self.pipe.lock().fcntl(file, current_task, cmd, arg)
558    }
559
560    fn ioctl(
561        &self,
562        file: &FileObject,
563        current_task: &CurrentTask,
564        request: u32,
565        arg: SyscallArg,
566    ) -> Result<SyscallResult, Errno> {
567        self.pipe.lock().ioctl(file, current_task, request, arg)
568    }
569}
570
571/// An OutputBuffer that will write the data to `pipe`.
572#[derive(Debug)]
573struct SpliceOutputBuffer<'a> {
574    pipe: &'a mut Pipe,
575    len: usize,
576    available: usize,
577}
578
579impl<'a> Buffer for SpliceOutputBuffer<'a> {
580    fn segments_count(&self) -> Result<usize, Errno> {
581        error!(ENOTSUP)
582    }
583
584    fn peek_each_segment(
585        &mut self,
586        _callback: &mut PeekBufferSegmentsCallback<'_>,
587    ) -> Result<(), Errno> {
588        error!(ENOTSUP)
589    }
590}
591
592impl<'a> OutputBuffer for SpliceOutputBuffer<'a> {
593    fn write_each(&mut self, callback: &mut OutputBufferCallback<'_>) -> Result<usize, Errno> {
594        // SAFETY: `callback` returns the number of bytes read on success.
595        let bytes = unsafe {
596            read_to_vec::<u8, _>(self.available, |buf| callback(buf).map(NumberOfElementsRead))
597        }?;
598        let bytes_len = bytes.len();
599        if bytes_len > 0 {
600            let was_empty = self.pipe.is_empty();
601            self.pipe.messages.write_message(PipeMessageData::from(bytes).into());
602            if was_empty {
603                self.pipe.notify_fd_events(FdEvents::POLLIN);
604            }
605            self.available -= bytes_len;
606        }
607        Ok(bytes_len)
608    }
609
610    fn available(&self) -> usize {
611        self.available
612    }
613
614    fn bytes_written(&self) -> usize {
615        self.len - self.available
616    }
617
618    fn zero(&mut self) -> Result<usize, Errno> {
619        let bytes = vec![0; self.available];
620        let len = bytes.len();
621        if len > 0 {
622            let was_empty = self.pipe.is_empty();
623            self.pipe.messages.write_message(PipeMessageData::from(bytes).into());
624            if was_empty {
625                self.pipe.notify_fd_events(FdEvents::POLLIN);
626            }
627            self.available -= len;
628        }
629        Ok(len)
630    }
631
632    unsafe fn advance(&mut self, _length: usize) -> Result<(), Errno> {
633        error!(ENOTSUP)
634    }
635}
636
637/// An InputBuffer that will read the data from `pipe`.
638#[derive(Debug)]
639struct SpliceInputBuffer<'a> {
640    pipe: &'a mut Pipe,
641    len: usize,
642    available: usize,
643}
644
645impl<'a> Buffer for SpliceInputBuffer<'a> {
646    fn segments_count(&self) -> Result<usize, Errno> {
647        Ok(self.pipe.messages.len())
648    }
649
650    fn peek_each_segment(
651        &mut self,
652        callback: &mut PeekBufferSegmentsCallback<'_>,
653    ) -> Result<(), Errno> {
654        let mut available = self.available;
655        for message in self.pipe.messages.messages() {
656            let to_read = std::cmp::min(available, message.len());
657            callback(&UserBuffer {
658                address: UserAddress::from(message.data.ptr()? as u64),
659                length: to_read,
660            });
661            available -= to_read;
662        }
663        Ok(())
664    }
665}
666
667impl<'a> InputBuffer for SpliceInputBuffer<'a> {
668    fn peek_each(&mut self, callback: &mut InputBufferCallback<'_>) -> Result<usize, Errno> {
669        let mut read = 0;
670        let mut available = self.available;
671        for message in self.pipe.messages.messages() {
672            let to_read = std::cmp::min(available, message.len());
673            let result = message.data.with_bytes(|bytes| callback(&bytes[0..to_read]))?;
674            if result > to_read {
675                return error!(EINVAL);
676            }
677            read += result;
678            available -= result;
679            if result != to_read {
680                break;
681            }
682        }
683        Ok(read)
684    }
685
686    fn available(&self) -> usize {
687        self.available
688    }
689
690    fn bytes_read(&self) -> usize {
691        self.len - self.available
692    }
693
694    fn drain(&mut self) -> usize {
695        let result = self.available;
696        self.available = 0;
697        result
698    }
699
700    fn advance(&mut self, mut length: usize) -> Result<(), Errno> {
701        if length == 0 {
702            return Ok(());
703        }
704        if length > self.available {
705            return error!(EINVAL);
706        }
707        self.available -= length;
708        while let Some(mut message) = self.pipe.messages.read_message() {
709            if let Some(data) = MessageData::split_off(&mut message.data, length) {
710                // Some data is left in the message. Push it back.
711                self.pipe.messages.write_front(data.into());
712            }
713            length -= message.len();
714            if length == 0 {
715                if self.pipe.is_empty() {
716                    self.pipe.notify_fd_events(FdEvents::POLLOUT);
717                }
718                return Ok(());
719            }
720        }
721        panic!();
722    }
723}
724
725impl PipeFileObject {
726    /// Called whenever a fd to a pipe is closed.
727    fn on_close(&self, flags: OpenFlags) {
728        let mut events = FdEvents::empty();
729        let mut pipe = self.pipe.lock();
730        if flags.can_read() {
731            assert!(pipe.reader_count > 0);
732            pipe.reader_count -= 1;
733            if pipe.reader_count == 0 {
734                events |= FdEvents::POLLOUT | FdEvents::POLLERR;
735            }
736        }
737        if flags.can_write() {
738            assert!(pipe.writer_count > 0);
739            pipe.writer_count -= 1;
740            if pipe.writer_count == 0 {
741                if pipe.reader_count > 0 {
742                    events |= FdEvents::POLLHUP;
743                }
744                if !pipe.is_empty() {
745                    events |= FdEvents::POLLIN;
746                }
747            }
748        }
749        if events != FdEvents::empty() {
750            pipe.waiters.notify_fd_events(events);
751        }
752        pipe.on_close();
753    }
754
755    /// Returns the result of `pregen` and a lock on pipe, once `condition` returns true, ensuring
756    /// `pregen` is run before the pipe is locked.
757    ///
758    /// This will wait on `events` if the file is opened in blocking mode. If the file is opened in
759    /// not blocking mode and `condition` is not realized, this will return EAGAIN.
760    fn wait_for_condition<'a, F, G, V>(
761        &'a self,
762        current_task: &CurrentTask,
763        file: &FileHandle,
764        condition: F,
765        pregen: G,
766        events: FdEvents,
767    ) -> Result<(V, MutexGuard<'a, Pipe>), Errno>
768    where
769        F: Fn(&Pipe) -> bool,
770        G: Fn() -> Result<V, Errno>,
771    {
772        file.blocking_op(current_task, events, None, || {
773            let other = pregen()?;
774            let pipe = self.pipe.lock();
775            if condition(&pipe) { Ok((other, pipe)) } else { error!(EAGAIN) }
776        })
777    }
778
779    /// Lock the pipe for reading, after having run `pregen`.
780    fn lock_pipe_for_reading_with<'a, G, V>(
781        &'a self,
782        current_task: &CurrentTask,
783        file: &FileHandle,
784        pregen: G,
785        non_blocking: bool,
786    ) -> Result<(V, MutexGuard<'a, Pipe>), Errno>
787    where
788        G: Fn() -> Result<V, Errno>,
789    {
790        if non_blocking {
791            let other = pregen()?;
792            let pipe = self.pipe.lock();
793            if !pipe.is_readable() {
794                return error!(EAGAIN);
795            }
796            Ok((other, pipe))
797        } else {
798            self.wait_for_condition(
799                current_task,
800                file,
801                |pipe| pipe.is_readable(),
802                pregen,
803                FdEvents::POLLIN | FdEvents::POLLHUP,
804            )
805        }
806    }
807
808    fn lock_pipe_for_reading<'a>(
809        &'a self,
810        current_task: &CurrentTask,
811        file: &FileHandle,
812        non_blocking: bool,
813    ) -> Result<MutexGuard<'a, Pipe>, Errno> {
814        self.lock_pipe_for_reading_with(current_task, file, || Ok(()), non_blocking).map(|(_, l)| l)
815    }
816
817    /// Lock the pipe for writing, after having run `pregen`.
818    fn lock_pipe_for_writing_with<'a, G, V>(
819        &'a self,
820        current_task: &CurrentTask,
821        file: &FileHandle,
822        pregen: G,
823        non_blocking: bool,
824        len: usize,
825    ) -> Result<(V, MutexGuard<'a, Pipe>), Errno>
826    where
827        G: Fn() -> Result<V, Errno>,
828    {
829        if non_blocking {
830            let other = pregen()?;
831            let pipe = self.pipe.lock();
832            if !pipe.is_writable(len) {
833                return error!(EAGAIN);
834            }
835            Ok((other, pipe))
836        } else {
837            self.wait_for_condition(
838                current_task,
839                file,
840                |pipe| pipe.is_writable(len),
841                pregen,
842                FdEvents::POLLOUT,
843            )
844        }
845    }
846
847    fn lock_pipe_for_writing<'a>(
848        &'a self,
849        current_task: &CurrentTask,
850        file: &FileHandle,
851        non_blocking: bool,
852        len: usize,
853    ) -> Result<MutexGuard<'a, Pipe>, Errno> {
854        self.lock_pipe_for_writing_with(current_task, file, || Ok(()), non_blocking, len)
855            .map(|(_, l)| l)
856    }
857
858    /// Splice from the given file handle to this pipe.
859    ///
860    /// The given file handle must not be a pipe. If you wish to splice between two pipes, use
861    /// `lock_pipes` and `Pipe::splice`.
862    pub fn splice_from(
863        &self,
864        current_task: &CurrentTask,
865        self_file: &FileHandle,
866        from: &FileHandle,
867        maybe_offset: Option<usize>,
868        len: usize,
869        non_blocking: bool,
870    ) -> Result<usize, Errno> {
871        // If both ends are pipes, use `lock_pipes` and `Pipe::splice`.
872        assert!(from.downcast_file::<PipeFileObject>().is_none());
873
874        let mut pipe = self.lock_pipe_for_writing(current_task, self_file, non_blocking, len)?;
875        let len = std::cmp::min(len, pipe.messages.available_capacity());
876        let mut buffer = SpliceOutputBuffer { pipe: &mut pipe, len, available: len };
877        if let Some(offset) = maybe_offset {
878            from.read_at(current_task, offset, &mut buffer)
879        } else {
880            from.read(current_task, &mut buffer)
881        }
882    }
883
884    /// Splice from this pipe to the given file handle.
885    ///
886    /// The given file handle must not be a pipe. If you wish to splice between two pipes, use
887    /// `lock_pipes` and `Pipe::splice`.
888    pub fn splice_to(
889        &self,
890        current_task: &CurrentTask,
891        self_file: &FileHandle,
892        to: &FileHandle,
893        maybe_offset: Option<usize>,
894        len: usize,
895        non_blocking: bool,
896    ) -> Result<usize, Errno> {
897        // If both ends are pipes, use `lock_pipes` and `Pipe::splice`.
898        assert!(to.downcast_file::<PipeFileObject>().is_none());
899
900        let mut pipe = self.lock_pipe_for_reading(current_task, self_file, non_blocking)?;
901        let len = std::cmp::min(len, pipe.messages.len());
902        let mut buffer = SpliceInputBuffer { pipe: &mut pipe, len, available: len };
903        if let Some(offset) = maybe_offset {
904            to.write_at(current_task, offset, &mut buffer)
905        } else {
906            to.write(current_task, &mut buffer)
907        }
908    }
909
910    /// Share the mappings backing the given input buffer into the pipe.
911    ///
912    /// Returns the number of bytes enqueued.
913    pub fn vmsplice_from(
914        &self,
915        current_task: &CurrentTask,
916        self_file: &FileHandle,
917        mut iovec: UserBuffers,
918        non_blocking: bool,
919    ) -> Result<usize, Errno> {
920        let available = UserBuffer::cap_buffers_to_max_rw_count(
921            current_task.maximum_valid_address().ok_or_else(|| errno!(EINVAL))?,
922            &mut iovec,
923        )?;
924        let mappings = current_task.mm()?.get_mappings_for_vmsplice(&iovec)?;
925
926        let mut pipe =
927            self.lock_pipe_for_writing(current_task, self_file, non_blocking, available)?;
928
929        if pipe.reader_count == 0 {
930            send_standard_signal(current_task, SignalInfo::kernel(SIGPIPE));
931            return error!(EPIPE);
932        }
933
934        let was_empty = pipe.is_empty();
935        let mut remaining = std::cmp::min(available, pipe.messages.available_capacity());
936
937        let mut bytes_transferred = 0;
938        for mut mapping in mappings.into_iter() {
939            mapping.truncate(remaining);
940            let actual = mapping.len();
941
942            pipe.messages.write_message(PipeMessageData::Vmspliced(mapping).into());
943            remaining -= actual;
944            bytes_transferred += actual;
945
946            if remaining == 0 {
947                break;
948            }
949        }
950        if bytes_transferred > 0 && was_empty {
951            pipe.notify_fd_events(FdEvents::POLLIN);
952        }
953        Ok(bytes_transferred)
954    }
955
956    /// Copy data from the pipe to the given output buffer.
957    ///
958    /// Returns the number of bytes transferred.
959    pub fn vmsplice_to(
960        &self,
961        current_task: &CurrentTask,
962        self_file: &FileHandle,
963        iovec: UserBuffers,
964        non_blocking: bool,
965    ) -> Result<usize, Errno> {
966        let mut pipe = self.lock_pipe_for_reading(current_task, self_file, non_blocking)?;
967
968        let mut data = UserBuffersOutputBuffer::unified_new(current_task, iovec)?;
969        let len = std::cmp::min(data.available(), pipe.messages.len());
970        let mut buffer = SpliceInputBuffer { pipe: &mut pipe, len, available: len };
971        data.write_buffer(&mut buffer)
972    }
973
974    /// Obtain the pipe objects from the given file handles, if they are both pipes.
975    ///
976    /// Returns EINVAL if one (or both) of the given file handles is not a pipe.
977    ///
978    /// Obtains the locks on the pipes in the correct order to avoid deadlocks.
979    pub fn lock_pipes<'a, 'b>(
980        current_task: &CurrentTask,
981        file_in: &'a FileHandle,
982        file_out: &'b FileHandle,
983        len: usize,
984        non_blocking: bool,
985    ) -> Result<PipeOperands<'a, 'b>, Errno> {
986        let pipe_in = file_in.downcast_file::<PipeFileObject>().ok_or_else(|| errno!(EINVAL))?;
987        let pipe_out = file_out.downcast_file::<PipeFileObject>().ok_or_else(|| errno!(EINVAL))?;
988
989        let node_cmp =
990            Arc::as_ptr(&file_in.name.entry.node).cmp(&Arc::as_ptr(&file_out.name.entry.node));
991
992        match node_cmp {
993            Ordering::Equal => error!(EINVAL),
994            Ordering::Less => {
995                let (write, read) = pipe_in.lock_pipe_for_reading_with(
996                    current_task,
997                    file_in,
998                    || pipe_out.lock_pipe_for_writing(current_task, file_out, non_blocking, len),
999                    non_blocking,
1000                )?;
1001                Ok(PipeOperands { read, write })
1002            }
1003            Ordering::Greater => {
1004                let (read, write) = pipe_out.lock_pipe_for_writing_with(
1005                    current_task,
1006                    file_out,
1007                    || pipe_in.lock_pipe_for_reading(current_task, file_in, non_blocking),
1008                    non_blocking,
1009                    len,
1010                )?;
1011                Ok(PipeOperands { read, write })
1012            }
1013        }
1014    }
1015}
1016
1017pub struct PipeOperands<'a, 'b> {
1018    pub read: MutexGuard<'a, Pipe>,
1019    pub write: MutexGuard<'b, Pipe>,
1020}