1use 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
40const 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 reader_count: usize,
55
56 had_reader: bool,
58
59 writer_count: usize,
61
62 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 if flags.contains(OpenFlags::NONBLOCK) && pipe_locked.reader_count == 0 {
107 assert!(!flags.can_read()); 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 let ops = scopeguard::guard(ops, |ops| {
128 ops.on_close(flags);
129 });
130
131 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 pub fn add_reader(&mut self) {
155 self.reader_count += 1;
156 self.had_reader = true;
157 }
158
159 pub fn add_writer(&mut self) {
161 self.writer_count += 1;
162 self.had_writer = true;
163 }
164
165 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 fn is_writable(&self, data_size: usize) -> bool {
215 let available_capacity = self.messages.available_capacity();
216 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 !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 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 break;
337 }
338 let Some(mut message) = from.messages.read_message() else {
339 break;
341 };
342 if let Some(data) = MessageData::split_off(&mut message.data, limit) {
343 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 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
384pub 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 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 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 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#[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 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#[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 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 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 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 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 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 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 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 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 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 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 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 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}