Blame view
fs/pipe.c
24.8 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * linux/fs/pipe.c * * Copyright (C) 1991, 1992, 1999 Linus Torvalds */ #include <linux/mm.h> #include <linux/file.h> #include <linux/poll.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/mount.h> #include <linux/pipe_fs_i.h> #include <linux/uio.h> #include <linux/highmem.h> |
5274f052e [PATCH] Introduce... |
18 |
#include <linux/pagemap.h> |
db3495099 [PATCH] AUDIT_FD_... |
19 |
#include <linux/audit.h> |
ba719baea sys_pipe(): fix f... |
20 |
#include <linux/syscalls.h> |
1da177e4c Linux-2.6.12-rc2 |
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <asm/uaccess.h> #include <asm/ioctls.h> /* * We use a start+len construction, which provides full use of the * allocated memory. * -- Florian Coosmann (FGC) * * Reads with count = 0 should always return 0. * -- Julian Bradfield 1999-06-07. * * FIFOs and Pipes now generate SIGIO for both readers and writers. * -- Jeremy Elson <jelson@circlemud.org> 2001-08-16 * * pipe_read & write cleanup * -- Manfred Spraul <manfred@colorfullife.com> 2002-05-09 */ |
61e0d47c3 splice: add helpe... |
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass) { if (pipe->inode) mutex_lock_nested(&pipe->inode->i_mutex, subclass); } void pipe_lock(struct pipe_inode_info *pipe) { /* * pipe_lock() nests non-pipe inode locks (for writing to a file) */ pipe_lock_nested(pipe, I_MUTEX_PARENT); } EXPORT_SYMBOL(pipe_lock); void pipe_unlock(struct pipe_inode_info *pipe) { if (pipe->inode) mutex_unlock(&pipe->inode->i_mutex); } EXPORT_SYMBOL(pipe_unlock); void pipe_double_lock(struct pipe_inode_info *pipe1, struct pipe_inode_info *pipe2) { BUG_ON(pipe1 == pipe2); if (pipe1 < pipe2) { pipe_lock_nested(pipe1, I_MUTEX_PARENT); pipe_lock_nested(pipe2, I_MUTEX_CHILD); } else { pipe_lock_nested(pipe2, I_MUTEX_CHILD); pipe_lock_nested(pipe1, I_MUTEX_PARENT); } } |
1da177e4c Linux-2.6.12-rc2 |
74 |
/* Drop the inode semaphore and wait for a pipe event, atomically */ |
3a326a2ce [PATCH] introduce... |
75 |
void pipe_wait(struct pipe_inode_info *pipe) |
1da177e4c Linux-2.6.12-rc2 |
76 77 |
{ DEFINE_WAIT(wait); |
d79fc0fc6 [PATCH] sched: TA... |
78 79 80 81 |
/* * Pipes are system-local resources, so sleeping on them * is considered a noninteractive wait: */ |
af9272326 sched: cleanup, r... |
82 |
prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE); |
61e0d47c3 splice: add helpe... |
83 |
pipe_unlock(pipe); |
1da177e4c Linux-2.6.12-rc2 |
84 |
schedule(); |
3a326a2ce [PATCH] introduce... |
85 |
finish_wait(&pipe->wait, &wait); |
61e0d47c3 splice: add helpe... |
86 |
pipe_lock(pipe); |
1da177e4c Linux-2.6.12-rc2 |
87 |
} |
858119e15 [PATCH] Unlinline... |
88 |
static int |
f6762b7ad [PATCH] pipe: ena... |
89 90 |
pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, int atomic) |
1da177e4c Linux-2.6.12-rc2 |
91 92 93 94 95 96 97 |
{ unsigned long copy; while (len > 0) { while (!iov->iov_len) iov++; copy = min_t(unsigned long, len, iov->iov_len); |
f6762b7ad [PATCH] pipe: ena... |
98 99 100 101 102 103 104 |
if (atomic) { if (__copy_from_user_inatomic(to, iov->iov_base, copy)) return -EFAULT; } else { if (copy_from_user(to, iov->iov_base, copy)) return -EFAULT; } |
1da177e4c Linux-2.6.12-rc2 |
105 106 107 108 109 110 111 |
to += copy; len -= copy; iov->iov_base += copy; iov->iov_len -= copy; } return 0; } |
858119e15 [PATCH] Unlinline... |
112 |
static int |
f6762b7ad [PATCH] pipe: ena... |
113 114 |
pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, int atomic) |
1da177e4c Linux-2.6.12-rc2 |
115 116 117 118 119 120 121 |
{ unsigned long copy; while (len > 0) { while (!iov->iov_len) iov++; copy = min_t(unsigned long, len, iov->iov_len); |
f6762b7ad [PATCH] pipe: ena... |
122 123 124 125 126 127 128 |
if (atomic) { if (__copy_to_user_inatomic(iov->iov_base, from, copy)) return -EFAULT; } else { if (copy_to_user(iov->iov_base, from, copy)) return -EFAULT; } |
1da177e4c Linux-2.6.12-rc2 |
129 130 131 132 133 134 135 |
from += copy; len -= copy; iov->iov_base += copy; iov->iov_len -= copy; } return 0; } |
f6762b7ad [PATCH] pipe: ena... |
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
/* * Attempt to pre-fault in the user memory, so we can use atomic copies. * Returns the number of bytes not faulted in. */ static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len) { while (!iov->iov_len) iov++; while (len > 0) { unsigned long this_len; this_len = min_t(unsigned long, len, iov->iov_len); if (fault_in_pages_writeable(iov->iov_base, this_len)) break; len -= this_len; iov++; } return len; } /* * Pre-fault in the user memory, so we can use atomic copies. */ static void iov_fault_in_pages_read(struct iovec *iov, unsigned long len) { while (!iov->iov_len) iov++; while (len > 0) { unsigned long this_len; this_len = min_t(unsigned long, len, iov->iov_len); fault_in_pages_readable(iov->iov_base, this_len); len -= this_len; iov++; } } |
341b446bc [PATCH] another r... |
176 177 |
static void anon_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf) |
1da177e4c Linux-2.6.12-rc2 |
178 179 |
{ struct page *page = buf->page; |
5274f052e [PATCH] Introduce... |
180 181 182 |
/* * If nobody else uses this page, and we don't already have a * temporary page, let's keep track of it as a one-deep |
341b446bc [PATCH] another r... |
183 |
* allocation cache. (Otherwise just release our reference to it) |
5274f052e [PATCH] Introduce... |
184 |
*/ |
341b446bc [PATCH] another r... |
185 |
if (page_count(page) == 1 && !pipe->tmp_page) |
923f4f239 [PATCH] pipe.c/fi... |
186 |
pipe->tmp_page = page; |
341b446bc [PATCH] another r... |
187 188 |
else page_cache_release(page); |
1da177e4c Linux-2.6.12-rc2 |
189 |
} |
0845718da pipe: add documen... |
190 191 192 193 194 195 196 197 |
/** * generic_pipe_buf_map - virtually map a pipe buffer * @pipe: the pipe that the buffer belongs to * @buf: the buffer that should be mapped * @atomic: whether to use an atomic map * * Description: * This function returns a kernel virtual address mapping for the |
b51d63c6d kernel-doc: fix f... |
198 |
* pipe_buffer passed in @buf. If @atomic is set, an atomic map is provided |
0845718da pipe: add documen... |
199 200 201 202 203 |
* and the caller has to be careful not to fault before calling * the unmap function. * * Note that this function occupies KM_USER0 if @atomic != 0. */ |
f84d75199 [PATCH] pipe: int... |
204 |
void *generic_pipe_buf_map(struct pipe_inode_info *pipe, |
f6762b7ad [PATCH] pipe: ena... |
205 |
struct pipe_buffer *buf, int atomic) |
1da177e4c Linux-2.6.12-rc2 |
206 |
{ |
f6762b7ad [PATCH] pipe: ena... |
207 208 209 210 |
if (atomic) { buf->flags |= PIPE_BUF_FLAG_ATOMIC; return kmap_atomic(buf->page, KM_USER0); } |
1da177e4c Linux-2.6.12-rc2 |
211 212 |
return kmap(buf->page); } |
0845718da pipe: add documen... |
213 214 215 216 217 218 219 220 221 |
/** * generic_pipe_buf_unmap - unmap a previously mapped pipe buffer * @pipe: the pipe that the buffer belongs to * @buf: the buffer that should be unmapped * @map_data: the data that the mapping function returned * * Description: * This function undoes the mapping that ->map() provided. */ |
f84d75199 [PATCH] pipe: int... |
222 |
void generic_pipe_buf_unmap(struct pipe_inode_info *pipe, |
f6762b7ad [PATCH] pipe: ena... |
223 |
struct pipe_buffer *buf, void *map_data) |
1da177e4c Linux-2.6.12-rc2 |
224 |
{ |
f6762b7ad [PATCH] pipe: ena... |
225 226 227 228 229 |
if (buf->flags & PIPE_BUF_FLAG_ATOMIC) { buf->flags &= ~PIPE_BUF_FLAG_ATOMIC; kunmap_atomic(map_data, KM_USER0); } else kunmap(buf->page); |
1da177e4c Linux-2.6.12-rc2 |
230 |
} |
0845718da pipe: add documen... |
231 |
/** |
b51d63c6d kernel-doc: fix f... |
232 |
* generic_pipe_buf_steal - attempt to take ownership of a &pipe_buffer |
0845718da pipe: add documen... |
233 234 235 236 |
* @pipe: the pipe that the buffer belongs to * @buf: the buffer to attempt to steal * * Description: |
b51d63c6d kernel-doc: fix f... |
237 |
* This function attempts to steal the &struct page attached to |
0845718da pipe: add documen... |
238 239 |
* @buf. If successful, this function returns 0 and returns with * the page locked. The caller may then reuse the page for whatever |
b51d63c6d kernel-doc: fix f... |
240 |
* he wishes; the typical use is insertion into a different file |
0845718da pipe: add documen... |
241 242 |
* page cache. */ |
330ab7161 [PATCH] vmsplice:... |
243 244 |
int generic_pipe_buf_steal(struct pipe_inode_info *pipe, struct pipe_buffer *buf) |
5abc97aa2 [PATCH] splice: a... |
245 |
{ |
46e678c96 [PATCH] splice: f... |
246 |
struct page *page = buf->page; |
0845718da pipe: add documen... |
247 248 249 250 251 |
/* * A reference of one is golden, that means that the owner of this * page is the only one holding a reference to it. lock the page * and return OK. */ |
46e678c96 [PATCH] splice: f... |
252 |
if (page_count(page) == 1) { |
46e678c96 [PATCH] splice: f... |
253 254 255 256 257 |
lock_page(page); return 0; } return 1; |
5abc97aa2 [PATCH] splice: a... |
258 |
} |
0845718da pipe: add documen... |
259 |
/** |
b51d63c6d kernel-doc: fix f... |
260 |
* generic_pipe_buf_get - get a reference to a &struct pipe_buffer |
0845718da pipe: add documen... |
261 262 263 264 265 266 267 268 269 |
* @pipe: the pipe that the buffer belongs to * @buf: the buffer to get a reference to * * Description: * This function grabs an extra reference to @buf. It's used in * in the tee() system call, when we duplicate the buffers in one * pipe into another. */ void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) |
70524490e [PATCH] splice: a... |
270 271 272 |
{ page_cache_get(buf->page); } |
0845718da pipe: add documen... |
273 274 |
/** * generic_pipe_buf_confirm - verify contents of the pipe buffer |
79685b8de docbook: add pipe... |
275 |
* @info: the pipe that the buffer belongs to |
0845718da pipe: add documen... |
276 277 278 279 280 281 |
* @buf: the buffer to confirm * * Description: * This function does nothing, because the generic pipe code uses * pages that are always good when inserted into the pipe. */ |
cac36bb06 pipe: change the ... |
282 283 |
int generic_pipe_buf_confirm(struct pipe_inode_info *info, struct pipe_buffer *buf) |
f84d75199 [PATCH] pipe: int... |
284 285 286 |
{ return 0; } |
d4c3cca94 [PATCH] constify ... |
287 |
static const struct pipe_buf_operations anon_pipe_buf_ops = { |
1da177e4c Linux-2.6.12-rc2 |
288 |
.can_merge = 1, |
f84d75199 [PATCH] pipe: int... |
289 290 |
.map = generic_pipe_buf_map, .unmap = generic_pipe_buf_unmap, |
cac36bb06 pipe: change the ... |
291 |
.confirm = generic_pipe_buf_confirm, |
1da177e4c Linux-2.6.12-rc2 |
292 |
.release = anon_pipe_buf_release, |
330ab7161 [PATCH] vmsplice:... |
293 |
.steal = generic_pipe_buf_steal, |
f84d75199 [PATCH] pipe: int... |
294 |
.get = generic_pipe_buf_get, |
1da177e4c Linux-2.6.12-rc2 |
295 296 297 |
}; static ssize_t |
ee0b3e671 [PATCH] Remove re... |
298 299 |
pipe_read(struct kiocb *iocb, const struct iovec *_iov, unsigned long nr_segs, loff_t pos) |
1da177e4c Linux-2.6.12-rc2 |
300 |
{ |
ee0b3e671 [PATCH] Remove re... |
301 |
struct file *filp = iocb->ki_filp; |
0f7fc9e4d [PATCH] VFS: chan... |
302 |
struct inode *inode = filp->f_path.dentry->d_inode; |
923f4f239 [PATCH] pipe.c/fi... |
303 |
struct pipe_inode_info *pipe; |
1da177e4c Linux-2.6.12-rc2 |
304 305 306 307 308 309 310 311 312 313 314 315 |
int do_wakeup; ssize_t ret; struct iovec *iov = (struct iovec *)_iov; size_t total_len; total_len = iov_length(iov, nr_segs); /* Null read succeeds. */ if (unlikely(total_len == 0)) return 0; do_wakeup = 0; ret = 0; |
9aeedfc47 [PATCH] get rid o... |
316 |
mutex_lock(&inode->i_mutex); |
923f4f239 [PATCH] pipe.c/fi... |
317 |
pipe = inode->i_pipe; |
1da177e4c Linux-2.6.12-rc2 |
318 |
for (;;) { |
923f4f239 [PATCH] pipe.c/fi... |
319 |
int bufs = pipe->nrbufs; |
1da177e4c Linux-2.6.12-rc2 |
320 |
if (bufs) { |
923f4f239 [PATCH] pipe.c/fi... |
321 322 |
int curbuf = pipe->curbuf; struct pipe_buffer *buf = pipe->bufs + curbuf; |
d4c3cca94 [PATCH] constify ... |
323 |
const struct pipe_buf_operations *ops = buf->ops; |
1da177e4c Linux-2.6.12-rc2 |
324 325 |
void *addr; size_t chars = buf->len; |
f6762b7ad [PATCH] pipe: ena... |
326 |
int error, atomic; |
1da177e4c Linux-2.6.12-rc2 |
327 328 329 |
if (chars > total_len) chars = total_len; |
cac36bb06 pipe: change the ... |
330 |
error = ops->confirm(pipe, buf); |
f84d75199 [PATCH] pipe: int... |
331 |
if (error) { |
5274f052e [PATCH] Introduce... |
332 |
if (!ret) |
f84d75199 [PATCH] pipe: int... |
333 |
error = ret; |
5274f052e [PATCH] Introduce... |
334 335 |
break; } |
f84d75199 [PATCH] pipe: int... |
336 |
|
f6762b7ad [PATCH] pipe: ena... |
337 338 339 340 341 |
atomic = !iov_fault_in_pages_write(iov, chars); redo: addr = ops->map(pipe, buf, atomic); error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); ops->unmap(pipe, buf, addr); |
1da177e4c Linux-2.6.12-rc2 |
342 |
if (unlikely(error)) { |
f6762b7ad [PATCH] pipe: ena... |
343 344 345 346 347 348 349 |
/* * Just retry with the slow path if we failed. */ if (atomic) { atomic = 0; goto redo; } |
341b446bc [PATCH] another r... |
350 |
if (!ret) |
f6762b7ad [PATCH] pipe: ena... |
351 |
ret = error; |
1da177e4c Linux-2.6.12-rc2 |
352 353 354 355 356 357 358 |
break; } ret += chars; buf->offset += chars; buf->len -= chars; if (!buf->len) { buf->ops = NULL; |
923f4f239 [PATCH] pipe.c/fi... |
359 |
ops->release(pipe, buf); |
1da177e4c Linux-2.6.12-rc2 |
360 |
curbuf = (curbuf + 1) & (PIPE_BUFFERS-1); |
923f4f239 [PATCH] pipe.c/fi... |
361 362 |
pipe->curbuf = curbuf; pipe->nrbufs = --bufs; |
1da177e4c Linux-2.6.12-rc2 |
363 364 365 366 367 368 369 370 |
do_wakeup = 1; } total_len -= chars; if (!total_len) break; /* common path: read succeeded */ } if (bufs) /* More to do? */ continue; |
923f4f239 [PATCH] pipe.c/fi... |
371 |
if (!pipe->writers) |
1da177e4c Linux-2.6.12-rc2 |
372 |
break; |
923f4f239 [PATCH] pipe.c/fi... |
373 |
if (!pipe->waiting_writers) { |
1da177e4c Linux-2.6.12-rc2 |
374 375 376 377 378 379 380 381 382 383 384 385 386 |
/* syscall merging: Usually we must not sleep * if O_NONBLOCK is set, or if we got some data. * But if a writer sleeps in kernel space, then * we can wait for that data without violating POSIX. */ if (ret) break; if (filp->f_flags & O_NONBLOCK) { ret = -EAGAIN; break; } } if (signal_pending(current)) { |
341b446bc [PATCH] another r... |
387 388 |
if (!ret) ret = -ERESTARTSYS; |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 |
break; } if (do_wakeup) { |
923f4f239 [PATCH] pipe.c/fi... |
392 393 |
wake_up_interruptible_sync(&pipe->wait); kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); |
1da177e4c Linux-2.6.12-rc2 |
394 |
} |
923f4f239 [PATCH] pipe.c/fi... |
395 |
pipe_wait(pipe); |
1da177e4c Linux-2.6.12-rc2 |
396 |
} |
9aeedfc47 [PATCH] get rid o... |
397 |
mutex_unlock(&inode->i_mutex); |
341b446bc [PATCH] another r... |
398 399 |
/* Signal writers asynchronously that there is more room. */ |
1da177e4c Linux-2.6.12-rc2 |
400 |
if (do_wakeup) { |
71e20f187 sched: affine syn... |
401 |
wake_up_interruptible_sync(&pipe->wait); |
923f4f239 [PATCH] pipe.c/fi... |
402 |
kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); |
1da177e4c Linux-2.6.12-rc2 |
403 404 405 406 407 408 409 |
} if (ret > 0) file_accessed(filp); return ret; } static ssize_t |
ee0b3e671 [PATCH] Remove re... |
410 411 |
pipe_write(struct kiocb *iocb, const struct iovec *_iov, unsigned long nr_segs, loff_t ppos) |
1da177e4c Linux-2.6.12-rc2 |
412 |
{ |
ee0b3e671 [PATCH] Remove re... |
413 |
struct file *filp = iocb->ki_filp; |
0f7fc9e4d [PATCH] VFS: chan... |
414 |
struct inode *inode = filp->f_path.dentry->d_inode; |
923f4f239 [PATCH] pipe.c/fi... |
415 |
struct pipe_inode_info *pipe; |
1da177e4c Linux-2.6.12-rc2 |
416 417 418 419 420 421 422 423 424 425 426 427 428 |
ssize_t ret; int do_wakeup; struct iovec *iov = (struct iovec *)_iov; size_t total_len; ssize_t chars; total_len = iov_length(iov, nr_segs); /* Null write succeeds. */ if (unlikely(total_len == 0)) return 0; do_wakeup = 0; ret = 0; |
9aeedfc47 [PATCH] get rid o... |
429 |
mutex_lock(&inode->i_mutex); |
923f4f239 [PATCH] pipe.c/fi... |
430 |
pipe = inode->i_pipe; |
1da177e4c Linux-2.6.12-rc2 |
431 |
|
923f4f239 [PATCH] pipe.c/fi... |
432 |
if (!pipe->readers) { |
1da177e4c Linux-2.6.12-rc2 |
433 434 435 436 437 438 439 |
send_sig(SIGPIPE, current, 0); ret = -EPIPE; goto out; } /* We try to merge small writes */ chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */ |
923f4f239 [PATCH] pipe.c/fi... |
440 |
if (pipe->nrbufs && chars != 0) { |
341b446bc [PATCH] another r... |
441 442 |
int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) & (PIPE_BUFFERS-1); |
923f4f239 [PATCH] pipe.c/fi... |
443 |
struct pipe_buffer *buf = pipe->bufs + lastbuf; |
d4c3cca94 [PATCH] constify ... |
444 |
const struct pipe_buf_operations *ops = buf->ops; |
1da177e4c Linux-2.6.12-rc2 |
445 |
int offset = buf->offset + buf->len; |
341b446bc [PATCH] another r... |
446 |
|
1da177e4c Linux-2.6.12-rc2 |
447 |
if (ops->can_merge && offset + chars <= PAGE_SIZE) { |
f6762b7ad [PATCH] pipe: ena... |
448 |
int error, atomic = 1; |
5274f052e [PATCH] Introduce... |
449 |
void *addr; |
5274f052e [PATCH] Introduce... |
450 |
|
cac36bb06 pipe: change the ... |
451 |
error = ops->confirm(pipe, buf); |
f84d75199 [PATCH] pipe: int... |
452 |
if (error) |
5274f052e [PATCH] Introduce... |
453 |
goto out; |
f84d75199 [PATCH] pipe: int... |
454 |
|
f6762b7ad [PATCH] pipe: ena... |
455 456 457 |
iov_fault_in_pages_read(iov, chars); redo1: addr = ops->map(pipe, buf, atomic); |
5274f052e [PATCH] Introduce... |
458 |
error = pipe_iov_copy_from_user(offset + addr, iov, |
f6762b7ad [PATCH] pipe: ena... |
459 460 |
chars, atomic); ops->unmap(pipe, buf, addr); |
1da177e4c Linux-2.6.12-rc2 |
461 462 |
ret = error; do_wakeup = 1; |
f6762b7ad [PATCH] pipe: ena... |
463 464 465 466 467 |
if (error) { if (atomic) { atomic = 0; goto redo1; } |
1da177e4c Linux-2.6.12-rc2 |
468 |
goto out; |
f6762b7ad [PATCH] pipe: ena... |
469 |
} |
1da177e4c Linux-2.6.12-rc2 |
470 471 472 473 474 475 476 477 478 479 |
buf->len += chars; total_len -= chars; ret = chars; if (!total_len) goto out; } } for (;;) { int bufs; |
341b446bc [PATCH] another r... |
480 |
|
923f4f239 [PATCH] pipe.c/fi... |
481 |
if (!pipe->readers) { |
1da177e4c Linux-2.6.12-rc2 |
482 |
send_sig(SIGPIPE, current, 0); |
341b446bc [PATCH] another r... |
483 484 |
if (!ret) ret = -EPIPE; |
1da177e4c Linux-2.6.12-rc2 |
485 486 |
break; } |
923f4f239 [PATCH] pipe.c/fi... |
487 |
bufs = pipe->nrbufs; |
1da177e4c Linux-2.6.12-rc2 |
488 |
if (bufs < PIPE_BUFFERS) { |
923f4f239 [PATCH] pipe.c/fi... |
489 490 491 |
int newbuf = (pipe->curbuf + bufs) & (PIPE_BUFFERS-1); struct pipe_buffer *buf = pipe->bufs + newbuf; struct page *page = pipe->tmp_page; |
f6762b7ad [PATCH] pipe: ena... |
492 493 |
char *src; int error, atomic = 1; |
1da177e4c Linux-2.6.12-rc2 |
494 495 496 497 498 499 500 |
if (!page) { page = alloc_page(GFP_HIGHUSER); if (unlikely(!page)) { ret = ret ? : -ENOMEM; break; } |
923f4f239 [PATCH] pipe.c/fi... |
501 |
pipe->tmp_page = page; |
1da177e4c Linux-2.6.12-rc2 |
502 |
} |
341b446bc [PATCH] another r... |
503 |
/* Always wake up, even if the copy fails. Otherwise |
1da177e4c Linux-2.6.12-rc2 |
504 505 506 507 508 509 510 511 |
* we lock up (O_NONBLOCK-)readers that sleep due to * syscall merging. * FIXME! Is this really true? */ do_wakeup = 1; chars = PAGE_SIZE; if (chars > total_len) chars = total_len; |
f6762b7ad [PATCH] pipe: ena... |
512 513 514 515 516 517 518 519 520 521 522 523 524 |
iov_fault_in_pages_read(iov, chars); redo2: if (atomic) src = kmap_atomic(page, KM_USER0); else src = kmap(page); error = pipe_iov_copy_from_user(src, iov, chars, atomic); if (atomic) kunmap_atomic(src, KM_USER0); else kunmap(page); |
1da177e4c Linux-2.6.12-rc2 |
525 |
if (unlikely(error)) { |
f6762b7ad [PATCH] pipe: ena... |
526 527 528 529 |
if (atomic) { atomic = 0; goto redo2; } |
341b446bc [PATCH] another r... |
530 |
if (!ret) |
f6762b7ad [PATCH] pipe: ena... |
531 |
ret = error; |
1da177e4c Linux-2.6.12-rc2 |
532 533 534 535 536 537 538 539 540 |
break; } ret += chars; /* Insert it into the buffer array */ buf->page = page; buf->ops = &anon_pipe_buf_ops; buf->offset = 0; buf->len = chars; |
923f4f239 [PATCH] pipe.c/fi... |
541 542 |
pipe->nrbufs = ++bufs; pipe->tmp_page = NULL; |
1da177e4c Linux-2.6.12-rc2 |
543 544 545 546 547 548 549 550 |
total_len -= chars; if (!total_len) break; } if (bufs < PIPE_BUFFERS) continue; if (filp->f_flags & O_NONBLOCK) { |
341b446bc [PATCH] another r... |
551 552 |
if (!ret) ret = -EAGAIN; |
1da177e4c Linux-2.6.12-rc2 |
553 554 555 |
break; } if (signal_pending(current)) { |
341b446bc [PATCH] another r... |
556 557 |
if (!ret) ret = -ERESTARTSYS; |
1da177e4c Linux-2.6.12-rc2 |
558 559 560 |
break; } if (do_wakeup) { |
923f4f239 [PATCH] pipe.c/fi... |
561 562 |
wake_up_interruptible_sync(&pipe->wait); kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
1da177e4c Linux-2.6.12-rc2 |
563 564 |
do_wakeup = 0; } |
923f4f239 [PATCH] pipe.c/fi... |
565 566 567 |
pipe->waiting_writers++; pipe_wait(pipe); pipe->waiting_writers--; |
1da177e4c Linux-2.6.12-rc2 |
568 569 |
} out: |
9aeedfc47 [PATCH] get rid o... |
570 |
mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
571 |
if (do_wakeup) { |
71e20f187 sched: affine syn... |
572 |
wake_up_interruptible_sync(&pipe->wait); |
923f4f239 [PATCH] pipe.c/fi... |
573 |
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
1da177e4c Linux-2.6.12-rc2 |
574 575 |
} if (ret > 0) |
870f48179 [PATCH] replace i... |
576 |
file_update_time(filp); |
1da177e4c Linux-2.6.12-rc2 |
577 578 579 580 |
return ret; } static ssize_t |
1da177e4c Linux-2.6.12-rc2 |
581 582 583 584 585 586 |
bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { return -EBADF; } static ssize_t |
341b446bc [PATCH] another r... |
587 588 |
bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) |
1da177e4c Linux-2.6.12-rc2 |
589 590 591 |
{ return -EBADF; } |
d59d0b1b8 BKL-Removal: conv... |
592 |
static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
593 |
{ |
0f7fc9e4d [PATCH] VFS: chan... |
594 |
struct inode *inode = filp->f_path.dentry->d_inode; |
923f4f239 [PATCH] pipe.c/fi... |
595 |
struct pipe_inode_info *pipe; |
1da177e4c Linux-2.6.12-rc2 |
596 597 598 599 |
int count, buf, nrbufs; switch (cmd) { case FIONREAD: |
9aeedfc47 [PATCH] get rid o... |
600 |
mutex_lock(&inode->i_mutex); |
923f4f239 [PATCH] pipe.c/fi... |
601 |
pipe = inode->i_pipe; |
1da177e4c Linux-2.6.12-rc2 |
602 |
count = 0; |
923f4f239 [PATCH] pipe.c/fi... |
603 604 |
buf = pipe->curbuf; nrbufs = pipe->nrbufs; |
1da177e4c Linux-2.6.12-rc2 |
605 |
while (--nrbufs >= 0) { |
923f4f239 [PATCH] pipe.c/fi... |
606 |
count += pipe->bufs[buf].len; |
1da177e4c Linux-2.6.12-rc2 |
607 608 |
buf = (buf+1) & (PIPE_BUFFERS-1); } |
9aeedfc47 [PATCH] get rid o... |
609 |
mutex_unlock(&inode->i_mutex); |
923f4f239 [PATCH] pipe.c/fi... |
610 |
|
1da177e4c Linux-2.6.12-rc2 |
611 612 613 614 615 616 617 618 619 620 621 |
return put_user(count, (int __user *)arg); default: return -EINVAL; } } /* No kernel lock held - fine */ static unsigned int pipe_poll(struct file *filp, poll_table *wait) { unsigned int mask; |
0f7fc9e4d [PATCH] VFS: chan... |
622 |
struct inode *inode = filp->f_path.dentry->d_inode; |
923f4f239 [PATCH] pipe.c/fi... |
623 |
struct pipe_inode_info *pipe = inode->i_pipe; |
1da177e4c Linux-2.6.12-rc2 |
624 |
int nrbufs; |
923f4f239 [PATCH] pipe.c/fi... |
625 |
poll_wait(filp, &pipe->wait, wait); |
1da177e4c Linux-2.6.12-rc2 |
626 627 |
/* Reading only -- no need for acquiring the semaphore. */ |
923f4f239 [PATCH] pipe.c/fi... |
628 |
nrbufs = pipe->nrbufs; |
1da177e4c Linux-2.6.12-rc2 |
629 630 631 |
mask = 0; if (filp->f_mode & FMODE_READ) { mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0; |
923f4f239 [PATCH] pipe.c/fi... |
632 |
if (!pipe->writers && filp->f_version != pipe->w_counter) |
1da177e4c Linux-2.6.12-rc2 |
633 634 635 636 637 |
mask |= POLLHUP; } if (filp->f_mode & FMODE_WRITE) { mask |= (nrbufs < PIPE_BUFFERS) ? POLLOUT | POLLWRNORM : 0; |
5e5d7a222 [PATCH] pipe: rem... |
638 639 640 641 |
/* * Most Unices do not set POLLERR for FIFOs but on Linux they * behave exactly like pipes for poll(). */ |
923f4f239 [PATCH] pipe.c/fi... |
642 |
if (!pipe->readers) |
1da177e4c Linux-2.6.12-rc2 |
643 644 645 646 647 |
mask |= POLLERR; } return mask; } |
1da177e4c Linux-2.6.12-rc2 |
648 649 650 |
static int pipe_release(struct inode *inode, int decr, int decw) { |
923f4f239 [PATCH] pipe.c/fi... |
651 |
struct pipe_inode_info *pipe; |
9aeedfc47 [PATCH] get rid o... |
652 |
mutex_lock(&inode->i_mutex); |
923f4f239 [PATCH] pipe.c/fi... |
653 654 655 |
pipe = inode->i_pipe; pipe->readers -= decr; pipe->writers -= decw; |
341b446bc [PATCH] another r... |
656 |
|
923f4f239 [PATCH] pipe.c/fi... |
657 |
if (!pipe->readers && !pipe->writers) { |
1da177e4c Linux-2.6.12-rc2 |
658 659 |
free_pipe_info(inode); } else { |
71e20f187 sched: affine syn... |
660 |
wake_up_interruptible_sync(&pipe->wait); |
923f4f239 [PATCH] pipe.c/fi... |
661 662 |
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); |
1da177e4c Linux-2.6.12-rc2 |
663 |
} |
9aeedfc47 [PATCH] get rid o... |
664 |
mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
665 666 667 668 669 670 671 |
return 0; } static int pipe_read_fasync(int fd, struct file *filp, int on) { |
0f7fc9e4d [PATCH] VFS: chan... |
672 |
struct inode *inode = filp->f_path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
673 |
int retval; |
9aeedfc47 [PATCH] get rid o... |
674 675 676 |
mutex_lock(&inode->i_mutex); retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers); mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
677 |
|
60aa49243 Rationalize fasyn... |
678 |
return retval; |
1da177e4c Linux-2.6.12-rc2 |
679 680 681 682 683 684 |
} static int pipe_write_fasync(int fd, struct file *filp, int on) { |
0f7fc9e4d [PATCH] VFS: chan... |
685 |
struct inode *inode = filp->f_path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
686 |
int retval; |
9aeedfc47 [PATCH] get rid o... |
687 688 689 |
mutex_lock(&inode->i_mutex); retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers); mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
690 |
|
60aa49243 Rationalize fasyn... |
691 |
return retval; |
1da177e4c Linux-2.6.12-rc2 |
692 693 694 695 696 697 |
} static int pipe_rdwr_fasync(int fd, struct file *filp, int on) { |
0f7fc9e4d [PATCH] VFS: chan... |
698 |
struct inode *inode = filp->f_path.dentry->d_inode; |
341b446bc [PATCH] another r... |
699 |
struct pipe_inode_info *pipe = inode->i_pipe; |
1da177e4c Linux-2.6.12-rc2 |
700 |
int retval; |
9aeedfc47 [PATCH] get rid o... |
701 |
mutex_lock(&inode->i_mutex); |
341b446bc [PATCH] another r... |
702 |
retval = fasync_helper(fd, filp, on, &pipe->fasync_readers); |
e5bc49ba7 pipe_rdwr_fasync:... |
703 |
if (retval >= 0) { |
341b446bc [PATCH] another r... |
704 |
retval = fasync_helper(fd, filp, on, &pipe->fasync_writers); |
e5bc49ba7 pipe_rdwr_fasync:... |
705 706 707 |
if (retval < 0) /* this can happen only if on == T */ fasync_helper(-1, filp, 0, &pipe->fasync_readers); } |
9aeedfc47 [PATCH] get rid o... |
708 |
mutex_unlock(&inode->i_mutex); |
60aa49243 Rationalize fasyn... |
709 |
return retval; |
1da177e4c Linux-2.6.12-rc2 |
710 711 712 713 714 715 |
} static int pipe_read_release(struct inode *inode, struct file *filp) { |
1da177e4c Linux-2.6.12-rc2 |
716 717 718 719 720 721 |
return pipe_release(inode, 1, 0); } static int pipe_write_release(struct inode *inode, struct file *filp) { |
1da177e4c Linux-2.6.12-rc2 |
722 723 724 725 726 727 728 |
return pipe_release(inode, 0, 1); } static int pipe_rdwr_release(struct inode *inode, struct file *filp) { int decr, decw; |
1da177e4c Linux-2.6.12-rc2 |
729 730 731 732 733 734 735 736 737 738 |
decr = (filp->f_mode & FMODE_READ) != 0; decw = (filp->f_mode & FMODE_WRITE) != 0; return pipe_release(inode, decr, decw); } static int pipe_read_open(struct inode *inode, struct file *filp) { /* We could have perhaps used atomic_t, but this and friends below are the only places. So it doesn't seem worthwhile. */ |
9aeedfc47 [PATCH] get rid o... |
739 740 741 |
mutex_lock(&inode->i_mutex); inode->i_pipe->readers++; mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
742 743 744 745 746 747 748 |
return 0; } static int pipe_write_open(struct inode *inode, struct file *filp) { |
9aeedfc47 [PATCH] get rid o... |
749 750 751 |
mutex_lock(&inode->i_mutex); inode->i_pipe->writers++; mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
752 753 754 755 756 757 758 |
return 0; } static int pipe_rdwr_open(struct inode *inode, struct file *filp) { |
9aeedfc47 [PATCH] get rid o... |
759 |
mutex_lock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
760 |
if (filp->f_mode & FMODE_READ) |
9aeedfc47 [PATCH] get rid o... |
761 |
inode->i_pipe->readers++; |
1da177e4c Linux-2.6.12-rc2 |
762 |
if (filp->f_mode & FMODE_WRITE) |
9aeedfc47 [PATCH] get rid o... |
763 764 |
inode->i_pipe->writers++; mutex_unlock(&inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
765 766 767 768 769 770 771 |
return 0; } /* * The file_operations structs are not static because they * are also used in linux/fs/fifo.c to do operations on FIFOs. |
d2d9648ec [PATCH] reuse xxx... |
772 773 |
* * Pipes reuse fifos' file_operations structs. |
1da177e4c Linux-2.6.12-rc2 |
774 |
*/ |
d2d9648ec [PATCH] reuse xxx... |
775 |
const struct file_operations read_pipefifo_fops = { |
1da177e4c Linux-2.6.12-rc2 |
776 |
.llseek = no_llseek, |
ee0b3e671 [PATCH] Remove re... |
777 778 |
.read = do_sync_read, .aio_read = pipe_read, |
1da177e4c Linux-2.6.12-rc2 |
779 780 |
.write = bad_pipe_w, .poll = pipe_poll, |
d59d0b1b8 BKL-Removal: conv... |
781 |
.unlocked_ioctl = pipe_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
782 783 784 785 |
.open = pipe_read_open, .release = pipe_read_release, .fasync = pipe_read_fasync, }; |
d2d9648ec [PATCH] reuse xxx... |
786 |
const struct file_operations write_pipefifo_fops = { |
1da177e4c Linux-2.6.12-rc2 |
787 788 |
.llseek = no_llseek, .read = bad_pipe_r, |
ee0b3e671 [PATCH] Remove re... |
789 790 |
.write = do_sync_write, .aio_write = pipe_write, |
1da177e4c Linux-2.6.12-rc2 |
791 |
.poll = pipe_poll, |
d59d0b1b8 BKL-Removal: conv... |
792 |
.unlocked_ioctl = pipe_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
793 794 795 796 |
.open = pipe_write_open, .release = pipe_write_release, .fasync = pipe_write_fasync, }; |
d2d9648ec [PATCH] reuse xxx... |
797 |
const struct file_operations rdwr_pipefifo_fops = { |
1da177e4c Linux-2.6.12-rc2 |
798 |
.llseek = no_llseek, |
ee0b3e671 [PATCH] Remove re... |
799 800 801 802 |
.read = do_sync_read, .aio_read = pipe_read, .write = do_sync_write, .aio_write = pipe_write, |
1da177e4c Linux-2.6.12-rc2 |
803 |
.poll = pipe_poll, |
d59d0b1b8 BKL-Removal: conv... |
804 |
.unlocked_ioctl = pipe_ioctl, |
1da177e4c Linux-2.6.12-rc2 |
805 806 807 808 |
.open = pipe_rdwr_open, .release = pipe_rdwr_release, .fasync = pipe_rdwr_fasync, }; |
3a326a2ce [PATCH] introduce... |
809 810 |
struct pipe_inode_info * alloc_pipe_info(struct inode *inode) { |
923f4f239 [PATCH] pipe.c/fi... |
811 |
struct pipe_inode_info *pipe; |
3a326a2ce [PATCH] introduce... |
812 |
|
923f4f239 [PATCH] pipe.c/fi... |
813 814 815 816 817 |
pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); if (pipe) { init_waitqueue_head(&pipe->wait); pipe->r_counter = pipe->w_counter = 1; pipe->inode = inode; |
3a326a2ce [PATCH] introduce... |
818 |
} |
923f4f239 [PATCH] pipe.c/fi... |
819 |
return pipe; |
3a326a2ce [PATCH] introduce... |
820 |
} |
923f4f239 [PATCH] pipe.c/fi... |
821 |
void __free_pipe_info(struct pipe_inode_info *pipe) |
1da177e4c Linux-2.6.12-rc2 |
822 823 |
{ int i; |
1da177e4c Linux-2.6.12-rc2 |
824 |
|
1da177e4c Linux-2.6.12-rc2 |
825 |
for (i = 0; i < PIPE_BUFFERS; i++) { |
923f4f239 [PATCH] pipe.c/fi... |
826 |
struct pipe_buffer *buf = pipe->bufs + i; |
1da177e4c Linux-2.6.12-rc2 |
827 |
if (buf->ops) |
923f4f239 [PATCH] pipe.c/fi... |
828 |
buf->ops->release(pipe, buf); |
1da177e4c Linux-2.6.12-rc2 |
829 |
} |
923f4f239 [PATCH] pipe.c/fi... |
830 831 832 |
if (pipe->tmp_page) __free_page(pipe->tmp_page); kfree(pipe); |
1da177e4c Linux-2.6.12-rc2 |
833 |
} |
b92ce5589 [PATCH] splice: a... |
834 835 836 837 838 |
void free_pipe_info(struct inode *inode) { __free_pipe_info(inode->i_pipe); inode->i_pipe = NULL; } |
fa3536cc1 [PATCH] Use __rea... |
839 |
static struct vfsmount *pipe_mnt __read_mostly; |
1da177e4c Linux-2.6.12-rc2 |
840 841 |
static int pipefs_delete_dentry(struct dentry *dentry) { |
d18de5a27 [PATCH] don't ins... |
842 843 844 845 846 847 848 849 |
/* * At creation time, we pretended this dentry was hashed * (by clearing DCACHE_UNHASHED bit in d_flags) * At delete time, we restore the truth : not hashed. * (so that dput() can proceed correctly) */ dentry->d_flags |= DCACHE_UNHASHED; return 0; |
1da177e4c Linux-2.6.12-rc2 |
850 |
} |
341b446bc [PATCH] another r... |
851 |
|
c23fbb6bc VFS: delay the de... |
852 853 854 855 856 857 858 859 |
/* * pipefs_dname() is called from d_path(). */ static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen) { return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]", dentry->d_inode->i_ino); } |
3ba13d179 constify dentry_o... |
860 |
static const struct dentry_operations pipefs_dentry_operations = { |
1da177e4c Linux-2.6.12-rc2 |
861 |
.d_delete = pipefs_delete_dentry, |
c23fbb6bc VFS: delay the de... |
862 |
.d_dname = pipefs_dname, |
1da177e4c Linux-2.6.12-rc2 |
863 864 865 866 867 |
}; static struct inode * get_pipe_inode(void) { struct inode *inode = new_inode(pipe_mnt->mnt_sb); |
923f4f239 [PATCH] pipe.c/fi... |
868 |
struct pipe_inode_info *pipe; |
1da177e4c Linux-2.6.12-rc2 |
869 870 871 |
if (!inode) goto fail_inode; |
923f4f239 [PATCH] pipe.c/fi... |
872 873 |
pipe = alloc_pipe_info(inode); if (!pipe) |
1da177e4c Linux-2.6.12-rc2 |
874 |
goto fail_iput; |
923f4f239 [PATCH] pipe.c/fi... |
875 |
inode->i_pipe = pipe; |
3a326a2ce [PATCH] introduce... |
876 |
|
923f4f239 [PATCH] pipe.c/fi... |
877 |
pipe->readers = pipe->writers = 1; |
d2d9648ec [PATCH] reuse xxx... |
878 |
inode->i_fop = &rdwr_pipefifo_fops; |
1da177e4c Linux-2.6.12-rc2 |
879 880 881 882 883 884 885 886 887 |
/* * Mark the inode dirty from the very beginning, * that way it will never be moved to the dirty * list because "mark_inode_dirty()" will think * that it already _is_ on the dirty list. */ inode->i_state = I_DIRTY; inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR; |
da9592ede CRED: Wrap task c... |
888 889 |
inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); |
1da177e4c Linux-2.6.12-rc2 |
890 |
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
923f4f239 [PATCH] pipe.c/fi... |
891 |
|
1da177e4c Linux-2.6.12-rc2 |
892 893 894 895 |
return inode; fail_iput: iput(inode); |
341b446bc [PATCH] another r... |
896 |
|
1da177e4c Linux-2.6.12-rc2 |
897 898 899 |
fail_inode: return NULL; } |
be61a86d7 flag parameters: ... |
900 |
struct file *create_write_pipe(int flags) |
1da177e4c Linux-2.6.12-rc2 |
901 |
{ |
d6cbd281d [PATCH] Some clea... |
902 903 904 |
int err; struct inode *inode; struct file *f; |
1da177e4c Linux-2.6.12-rc2 |
905 |
struct dentry *dentry; |
c23fbb6bc VFS: delay the de... |
906 |
struct qstr name = { .name = "" }; |
1da177e4c Linux-2.6.12-rc2 |
907 |
|
d6cbd281d [PATCH] Some clea... |
908 |
err = -ENFILE; |
1da177e4c Linux-2.6.12-rc2 |
909 910 |
inode = get_pipe_inode(); if (!inode) |
430e285e0 [PATCH] fix up ne... |
911 |
goto err; |
1da177e4c Linux-2.6.12-rc2 |
912 |
|
d6cbd281d [PATCH] Some clea... |
913 |
err = -ENOMEM; |
c23fbb6bc VFS: delay the de... |
914 |
dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); |
1da177e4c Linux-2.6.12-rc2 |
915 |
if (!dentry) |
d6cbd281d [PATCH] Some clea... |
916 |
goto err_inode; |
341b446bc [PATCH] another r... |
917 |
|
1da177e4c Linux-2.6.12-rc2 |
918 |
dentry->d_op = &pipefs_dentry_operations; |
d18de5a27 [PATCH] don't ins... |
919 920 921 922 923 924 925 |
/* * We dont want to publish this dentry into global dentry hash table. * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED * This permits a working /proc/$pid/fd/XXX on pipes */ dentry->d_flags &= ~DCACHE_UNHASHED; d_instantiate(dentry, inode); |
430e285e0 [PATCH] fix up ne... |
926 927 |
err = -ENFILE; |
d2d9648ec [PATCH] reuse xxx... |
928 |
f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops); |
430e285e0 [PATCH] fix up ne... |
929 930 |
if (!f) goto err_dentry; |
d6cbd281d [PATCH] Some clea... |
931 |
f->f_mapping = inode->i_mapping; |
341b446bc [PATCH] another r... |
932 |
|
be61a86d7 flag parameters: ... |
933 |
f->f_flags = O_WRONLY | (flags & O_NONBLOCK); |
d6cbd281d [PATCH] Some clea... |
934 935 936 |
f->f_version = 0; return f; |
1da177e4c Linux-2.6.12-rc2 |
937 |
|
430e285e0 [PATCH] fix up ne... |
938 |
err_dentry: |
ed1524371 [PATCH] double-fr... |
939 |
free_pipe_info(inode); |
430e285e0 [PATCH] fix up ne... |
940 |
dput(dentry); |
ed1524371 [PATCH] double-fr... |
941 |
return ERR_PTR(err); |
d6cbd281d [PATCH] Some clea... |
942 |
err_inode: |
1da177e4c Linux-2.6.12-rc2 |
943 944 |
free_pipe_info(inode); iput(inode); |
430e285e0 [PATCH] fix up ne... |
945 |
err: |
d6cbd281d [PATCH] Some clea... |
946 947 948 949 950 |
return ERR_PTR(err); } void free_write_pipe(struct file *f) { |
5ccac88ee [PATCH] fix leaks... |
951 |
free_pipe_info(f->f_dentry->d_inode); |
c8e7f449b [patch 1/4] vfs: ... |
952 |
path_put(&f->f_path); |
d6cbd281d [PATCH] Some clea... |
953 954 |
put_filp(f); } |
be61a86d7 flag parameters: ... |
955 |
struct file *create_read_pipe(struct file *wrf, int flags) |
d6cbd281d [PATCH] Some clea... |
956 957 958 959 960 961 |
{ struct file *f = get_empty_filp(); if (!f) return ERR_PTR(-ENFILE); /* Grab pipe from the writer */ |
c8e7f449b [patch 1/4] vfs: ... |
962 963 |
f->f_path = wrf->f_path; path_get(&wrf->f_path); |
0f7fc9e4d [PATCH] VFS: chan... |
964 |
f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping; |
d6cbd281d [PATCH] Some clea... |
965 966 |
f->f_pos = 0; |
be61a86d7 flag parameters: ... |
967 |
f->f_flags = O_RDONLY | (flags & O_NONBLOCK); |
d2d9648ec [PATCH] reuse xxx... |
968 |
f->f_op = &read_pipefifo_fops; |
d6cbd281d [PATCH] Some clea... |
969 970 971 972 973 |
f->f_mode = FMODE_READ; f->f_version = 0; return f; } |
ed8cae8ba flag parameters: ... |
974 |
int do_pipe_flags(int *fd, int flags) |
d6cbd281d [PATCH] Some clea... |
975 976 977 978 |
{ struct file *fw, *fr; int error; int fdw, fdr; |
be61a86d7 flag parameters: ... |
979 |
if (flags & ~(O_CLOEXEC | O_NONBLOCK)) |
ed8cae8ba flag parameters: ... |
980 |
return -EINVAL; |
be61a86d7 flag parameters: ... |
981 |
fw = create_write_pipe(flags); |
d6cbd281d [PATCH] Some clea... |
982 983 |
if (IS_ERR(fw)) return PTR_ERR(fw); |
be61a86d7 flag parameters: ... |
984 |
fr = create_read_pipe(fw, flags); |
d6cbd281d [PATCH] Some clea... |
985 986 987 |
error = PTR_ERR(fr); if (IS_ERR(fr)) goto err_write_pipe; |
ed8cae8ba flag parameters: ... |
988 |
error = get_unused_fd_flags(flags); |
d6cbd281d [PATCH] Some clea... |
989 990 991 |
if (error < 0) goto err_read_pipe; fdr = error; |
ed8cae8ba flag parameters: ... |
992 |
error = get_unused_fd_flags(flags); |
d6cbd281d [PATCH] Some clea... |
993 994 995 |
if (error < 0) goto err_fdr; fdw = error; |
157cf649a sanitize audit_fd... |
996 |
audit_fd_pair(fdr, fdw); |
d6cbd281d [PATCH] Some clea... |
997 998 999 1000 1001 1002 1003 1004 1005 1006 |
fd_install(fdr, fr); fd_install(fdw, fw); fd[0] = fdr; fd[1] = fdw; return 0; err_fdr: put_unused_fd(fdr); err_read_pipe: |
c8e7f449b [patch 1/4] vfs: ... |
1007 |
path_put(&fr->f_path); |
d6cbd281d [PATCH] Some clea... |
1008 1009 1010 1011 |
put_filp(fr); err_write_pipe: free_write_pipe(fw); return error; |
1da177e4c Linux-2.6.12-rc2 |
1012 1013 1014 |
} /* |
d35c7b0e5 unified (weak) sy... |
1015 1016 1017 |
* sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way Unix traditionally does this, though. */ |
d4e82042c [CVE-2009-0029] S... |
1018 |
SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags) |
d35c7b0e5 unified (weak) sy... |
1019 1020 1021 |
{ int fd[2]; int error; |
ed8cae8ba flag parameters: ... |
1022 |
error = do_pipe_flags(fd, flags); |
d35c7b0e5 unified (weak) sy... |
1023 |
if (!error) { |
ba719baea sys_pipe(): fix f... |
1024 1025 1026 |
if (copy_to_user(fildes, fd, sizeof(fd))) { sys_close(fd[0]); sys_close(fd[1]); |
d35c7b0e5 unified (weak) sy... |
1027 |
error = -EFAULT; |
ba719baea sys_pipe(): fix f... |
1028 |
} |
d35c7b0e5 unified (weak) sy... |
1029 1030 1031 |
} return error; } |
2b6642199 [CVE-2009-0029] S... |
1032 |
SYSCALL_DEFINE1(pipe, int __user *, fildes) |
ed8cae8ba flag parameters: ... |
1033 1034 1035 |
{ return sys_pipe2(fildes, 0); } |
d35c7b0e5 unified (weak) sy... |
1036 |
/* |
1da177e4c Linux-2.6.12-rc2 |
1037 1038 1039 1040 1041 |
* pipefs should _never_ be mounted by userland - too much of security hassle, * no real gain from having the whole whorehouse mounted. So we don't need * any operations on the root directory. However, we need a non-trivial * d_name - pipe: will go nicely and kill the special-casing in procfs. */ |
454e2398b [PATCH] VFS: Perm... |
1042 1043 1044 |
static int pipefs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1da177e4c Linux-2.6.12-rc2 |
1045 |
{ |
454e2398b [PATCH] VFS: Perm... |
1046 |
return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt); |
1da177e4c Linux-2.6.12-rc2 |
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 |
} static struct file_system_type pipe_fs_type = { .name = "pipefs", .get_sb = pipefs_get_sb, .kill_sb = kill_anon_super, }; static int __init init_pipe_fs(void) { int err = register_filesystem(&pipe_fs_type); |
341b446bc [PATCH] another r... |
1058 |
|
1da177e4c Linux-2.6.12-rc2 |
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 |
if (!err) { pipe_mnt = kern_mount(&pipe_fs_type); if (IS_ERR(pipe_mnt)) { err = PTR_ERR(pipe_mnt); unregister_filesystem(&pipe_fs_type); } } return err; } static void __exit exit_pipe_fs(void) { unregister_filesystem(&pipe_fs_type); mntput(pipe_mnt); } fs_initcall(init_pipe_fs); module_exit(exit_pipe_fs); |