2 * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
3 * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
4 * Copyright (C) 2008-2009 - Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
6 * Re-using content from kernel/relay.c
8 * This file is released under the GPL.
11 #include <linux/errno.h>
12 #include <linux/stddef.h>
13 #include <linux/slab.h>
14 #include <linux/module.h>
15 #include <linux/string.h>
16 #include <linux/vmalloc.h>
18 #include <linux/cpu.h>
19 #include <linux/splice.h>
20 #include <linux/pipe_fs_i.h>
21 #include <linux/bitops.h>
23 #include "ltt-relay.h"
24 #include "ltt-relay-lockless.h"
26 loff_t
ltt_relay_no_llseek(struct file
*file
, loff_t offset
, int origin
)
31 static void ltt_relay_pipe_buf_release(struct pipe_inode_info
*pipe
,
32 struct pipe_buffer
*pbuf
)
36 static struct pipe_buf_operations ltt_relay_pipe_buf_ops
= {
38 .map
= generic_pipe_buf_map
,
39 .unmap
= generic_pipe_buf_unmap
,
40 .confirm
= generic_pipe_buf_confirm
,
41 .release
= ltt_relay_pipe_buf_release
,
42 .steal
= generic_pipe_buf_steal
,
43 .get
= generic_pipe_buf_get
,
46 static void ltt_relay_page_release(struct splice_pipe_desc
*spd
, unsigned int i
)
51 * subbuf_splice_actor - splice up to one subbuf's worth of data
53 static int subbuf_splice_actor(struct file
*in
,
55 struct pipe_inode_info
*pipe
,
59 struct ltt_chanbuf
*buf
= in
->private_data
;
60 struct ltt_chan
*chan
= container_of(buf
->a
.chan
, struct ltt_chan
, a
);
61 unsigned int poff
, subbuf_pages
, nr_pages
;
62 struct page
*pages
[PIPE_DEF_BUFFERS
];
63 struct partial_page partial
[PIPE_DEF_BUFFERS
];
64 struct splice_pipe_desc spd
= {
69 .ops
= <t_relay_pipe_buf_ops
,
70 .spd_release
= ltt_relay_page_release
,
72 long consumed_old
, consumed_idx
, roffset
;
73 unsigned long bytes_avail
;
76 * Check that a GET_SUBBUF ioctl has been done before.
78 WARN_ON(atomic_long_read(&buf
->active_readers
) != 1);
79 consumed_old
= atomic_long_read(&buf
->consumed
);
80 consumed_old
+= *ppos
;
81 consumed_idx
= SUBBUF_INDEX(consumed_old
, chan
);
84 * Adjust read len, if longer than what is available.
85 * Max read size is 1 subbuffer due to get_subbuf/put_subbuf for
88 bytes_avail
= chan
->a
.sb_size
;
89 WARN_ON(bytes_avail
> chan
->a
.buf_size
);
90 len
= min_t(size_t, len
, bytes_avail
);
91 subbuf_pages
= bytes_avail
>> PAGE_SHIFT
;
92 nr_pages
= min_t(unsigned int, subbuf_pages
, PIPE_DEF_BUFFERS
);
93 roffset
= consumed_old
& PAGE_MASK
;
94 poff
= consumed_old
& ~PAGE_MASK
;
95 printk_dbg(KERN_DEBUG
"SPLICE actor len %zu pos %zd write_pos %ld\n",
96 len
, (ssize_t
)*ppos
, local_read(&buf
->offset
));
98 for (; spd
.nr_pages
< nr_pages
; spd
.nr_pages
++) {
99 unsigned int this_len
;
104 printk_dbg(KERN_DEBUG
"SPLICE actor loop len %zu roffset %ld\n",
107 this_len
= PAGE_SIZE
- poff
;
108 page
= ltt_relay_read_get_page(&buf
->a
, roffset
);
109 spd
.pages
[spd
.nr_pages
] = page
;
110 spd
.partial
[spd
.nr_pages
].offset
= poff
;
111 spd
.partial
[spd
.nr_pages
].len
= this_len
;
114 roffset
+= PAGE_SIZE
;
121 return splice_to_pipe(pipe
, &spd
);
124 ssize_t
ltt_relay_file_splice_read(struct file
*in
, loff_t
*ppos
,
125 struct pipe_inode_info
*pipe
, size_t len
,
134 printk_dbg(KERN_DEBUG
"SPLICE read len %zu pos %zd\n", len
,
136 while (len
&& !spliced
) {
137 ret
= subbuf_splice_actor(in
, ppos
, pipe
, len
, flags
);
138 printk_dbg(KERN_DEBUG
"SPLICE read loop ret %d\n", ret
);
142 if (flags
& SPLICE_F_NONBLOCK
)