Blame view

fs/pipe.c 27.7 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   *  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>
35f3d14db   Jens Axboe   pipe: add support...
15
  #include <linux/log2.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/mount.h>
4fa7ec5db   David Howells   vfs: Convert pipe...
17
  #include <linux/pseudo_fs.h>
b502bd115   Muthu Kumar   magic.h: move som...
18
  #include <linux/magic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
  #include <linux/pipe_fs_i.h>
  #include <linux/uio.h>
  #include <linux/highmem.h>
5274f052e   Jens Axboe   [PATCH] Introduce...
22
  #include <linux/pagemap.h>
db3495099   Al Viro   [PATCH] AUDIT_FD_...
23
  #include <linux/audit.h>
ba719baea   Ulrich Drepper   sys_pipe(): fix f...
24
  #include <linux/syscalls.h>
b492e95be   Jens Axboe   pipe: set lower a...
25
  #include <linux/fcntl.h>
d86133bd3   Vladimir Davydov   pipe: account to ...
26
  #include <linux/memcontrol.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
28
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <asm/ioctls.h>
599a0ac14   Al Viro   pipe: fold file_o...
30
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  /*
b492e95be   Jens Axboe   pipe: set lower a...
32
   * The max size that a non-root user is allowed to grow the pipe. Can
ff9da691c   Jens Axboe   pipe: change /pro...
33
   * be set by root in /proc/sys/fs/pipe-max-size
b492e95be   Jens Axboe   pipe: set lower a...
34
   */
ff9da691c   Jens Axboe   pipe: change /pro...
35
  unsigned int pipe_max_size = 1048576;
759c01142   Willy Tarreau   pipe: limit the p...
36
37
38
39
40
  /* Maximum allocatable pages per user. Hard limit is unset by default, soft
   * matches default values.
   */
  unsigned long pipe_user_pages_hard;
  unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
b492e95be   Jens Axboe   pipe: set lower a...
41
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
48
49
50
51
52
53
54
   * 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   Miklos Szeredi   splice: add helpe...
55
56
  static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass)
  {
6447a3cf1   Al Viro   get rid of pipe->...
57
  	if (pipe->files)
72b0d9aac   Al Viro   pipe: don't use -...
58
  		mutex_lock_nested(&pipe->mutex, subclass);
61e0d47c3   Miklos Szeredi   splice: add helpe...
59
60
61
62
63
64
65
66
67
68
69
70
71
  }
  
  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)
  {
6447a3cf1   Al Viro   get rid of pipe->...
72
  	if (pipe->files)
72b0d9aac   Al Viro   pipe: don't use -...
73
  		mutex_unlock(&pipe->mutex);
61e0d47c3   Miklos Szeredi   splice: add helpe...
74
75
  }
  EXPORT_SYMBOL(pipe_unlock);
ebec73f47   Al Viro   introduce variant...
76
77
78
79
80
81
82
83
84
  static inline void __pipe_lock(struct pipe_inode_info *pipe)
  {
  	mutex_lock_nested(&pipe->mutex, I_MUTEX_PARENT);
  }
  
  static inline void __pipe_unlock(struct pipe_inode_info *pipe)
  {
  	mutex_unlock(&pipe->mutex);
  }
61e0d47c3   Miklos Szeredi   splice: add helpe...
85
86
87
88
89
90
91
92
93
  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 {
023d43c7b   Peter Zijlstra   lockdep: Fix lock...
94
95
  		pipe_lock_nested(pipe2, I_MUTEX_PARENT);
  		pipe_lock_nested(pipe1, I_MUTEX_CHILD);
61e0d47c3   Miklos Szeredi   splice: add helpe...
96
97
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  /* Drop the inode semaphore and wait for a pipe event, atomically */
3a326a2ce   Ingo Molnar   [PATCH] introduce...
99
  void pipe_wait(struct pipe_inode_info *pipe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
  {
  	DEFINE_WAIT(wait);
d79fc0fc6   Ingo Molnar   [PATCH] sched: TA...
102
103
104
105
  	/*
  	 * Pipes are system-local resources, so sleeping on them
  	 * is considered a noninteractive wait:
  	 */
af9272326   Mike Galbraith   sched: cleanup, r...
106
  	prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE);
61e0d47c3   Miklos Szeredi   splice: add helpe...
107
  	pipe_unlock(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  	schedule();
3a326a2ce   Ingo Molnar   [PATCH] introduce...
109
  	finish_wait(&pipe->wait, &wait);
61e0d47c3   Miklos Szeredi   splice: add helpe...
110
  	pipe_lock(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
341b446bc   Ingo Molnar   [PATCH] another r...
112
113
  static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
  				  struct pipe_buffer *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
  {
  	struct page *page = buf->page;
5274f052e   Jens Axboe   [PATCH] Introduce...
116
117
118
  	/*
  	 * 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   Ingo Molnar   [PATCH] another r...
119
  	 * allocation cache. (Otherwise just release our reference to it)
5274f052e   Jens Axboe   [PATCH] Introduce...
120
  	 */
341b446bc   Ingo Molnar   [PATCH] another r...
121
  	if (page_count(page) == 1 && !pipe->tmp_page)
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
122
  		pipe->tmp_page = page;
341b446bc   Ingo Molnar   [PATCH] another r...
123
  	else
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
124
  		put_page(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  }
d86133bd3   Vladimir Davydov   pipe: account to ...
126
127
128
129
130
131
  static int anon_pipe_buf_steal(struct pipe_inode_info *pipe,
  			       struct pipe_buffer *buf)
  {
  	struct page *page = buf->page;
  
  	if (page_count(page) == 1) {
60cd4bcd6   Shakeel Butt   memcg: localize m...
132
  		memcg_kmem_uncharge(page, 0);
d86133bd3   Vladimir Davydov   pipe: account to ...
133
134
135
136
137
  		__SetPageLocked(page);
  		return 0;
  	}
  	return 1;
  }
0845718da   Jens Axboe   pipe: add documen...
138
  /**
b51d63c6d   Randy Dunlap   kernel-doc: fix f...
139
   * generic_pipe_buf_steal - attempt to take ownership of a &pipe_buffer
0845718da   Jens Axboe   pipe: add documen...
140
141
142
143
   * @pipe:	the pipe that the buffer belongs to
   * @buf:	the buffer to attempt to steal
   *
   * Description:
b51d63c6d   Randy Dunlap   kernel-doc: fix f...
144
   *	This function attempts to steal the &struct page attached to
0845718da   Jens Axboe   pipe: add documen...
145
146
   *	@buf. If successful, this function returns 0 and returns with
   *	the page locked. The caller may then reuse the page for whatever
b51d63c6d   Randy Dunlap   kernel-doc: fix f...
147
   *	he wishes; the typical use is insertion into a different file
0845718da   Jens Axboe   pipe: add documen...
148
149
   *	page cache.
   */
330ab7161   Jens Axboe   [PATCH] vmsplice:...
150
151
  int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
  			   struct pipe_buffer *buf)
5abc97aa2   Jens Axboe   [PATCH] splice: a...
152
  {
46e678c96   Jens Axboe   [PATCH] splice: f...
153
  	struct page *page = buf->page;
0845718da   Jens Axboe   pipe: add documen...
154
155
156
157
158
  	/*
  	 * 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   Jens Axboe   [PATCH] splice: f...
159
  	if (page_count(page) == 1) {
46e678c96   Jens Axboe   [PATCH] splice: f...
160
161
162
163
164
  		lock_page(page);
  		return 0;
  	}
  
  	return 1;
5abc97aa2   Jens Axboe   [PATCH] splice: a...
165
  }
51921cb74   Miklos Szeredi   mm: export generi...
166
  EXPORT_SYMBOL(generic_pipe_buf_steal);
5abc97aa2   Jens Axboe   [PATCH] splice: a...
167

0845718da   Jens Axboe   pipe: add documen...
168
  /**
b51d63c6d   Randy Dunlap   kernel-doc: fix f...
169
   * generic_pipe_buf_get - get a reference to a &struct pipe_buffer
0845718da   Jens Axboe   pipe: add documen...
170
171
172
173
174
175
176
177
   * @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.
   */
15fab63e1   Matthew Wilcox   fs: prevent page ...
178
  bool generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
70524490e   Jens Axboe   [PATCH] splice: a...
179
  {
15fab63e1   Matthew Wilcox   fs: prevent page ...
180
  	return try_get_page(buf->page);
70524490e   Jens Axboe   [PATCH] splice: a...
181
  }
51921cb74   Miklos Szeredi   mm: export generi...
182
  EXPORT_SYMBOL(generic_pipe_buf_get);
70524490e   Jens Axboe   [PATCH] splice: a...
183

0845718da   Jens Axboe   pipe: add documen...
184
185
  /**
   * generic_pipe_buf_confirm - verify contents of the pipe buffer
79685b8de   Randy Dunlap   docbook: add pipe...
186
   * @info:	the pipe that the buffer belongs to
0845718da   Jens Axboe   pipe: add documen...
187
188
189
190
191
192
   * @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   Jens Axboe   pipe: change the ...
193
194
  int generic_pipe_buf_confirm(struct pipe_inode_info *info,
  			     struct pipe_buffer *buf)
f84d75199   Jens Axboe   [PATCH] pipe: int...
195
196
197
  {
  	return 0;
  }
51921cb74   Miklos Szeredi   mm: export generi...
198
  EXPORT_SYMBOL(generic_pipe_buf_confirm);
f84d75199   Jens Axboe   [PATCH] pipe: int...
199

6818173bd   Miklos Szeredi   splice: implement...
200
201
202
203
204
205
206
207
208
209
210
  /**
   * generic_pipe_buf_release - put a reference to a &struct pipe_buffer
   * @pipe:	the pipe that the buffer belongs to
   * @buf:	the buffer to put a reference to
   *
   * Description:
   *	This function releases a reference to @buf.
   */
  void generic_pipe_buf_release(struct pipe_inode_info *pipe,
  			      struct pipe_buffer *buf)
  {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
211
  	put_page(buf->page);
6818173bd   Miklos Szeredi   splice: implement...
212
  }
51921cb74   Miklos Szeredi   mm: export generi...
213
  EXPORT_SYMBOL(generic_pipe_buf_release);
6818173bd   Miklos Szeredi   splice: implement...
214

01e7187b4   Jann Horn   pipe: stop using ...
215
  /* New data written to a pipe may be appended to a buffer with this type. */
d4c3cca94   Eric Dumazet   [PATCH] constify ...
216
  static const struct pipe_buf_operations anon_pipe_buf_ops = {
cac36bb06   Jens Axboe   pipe: change the ...
217
  	.confirm = generic_pipe_buf_confirm,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  	.release = anon_pipe_buf_release,
d86133bd3   Vladimir Davydov   pipe: account to ...
219
  	.steal = anon_pipe_buf_steal,
f84d75199   Jens Axboe   [PATCH] pipe: int...
220
  	.get = generic_pipe_buf_get,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  };
a0ce2f0aa   Jann Horn   splice: don't mer...
222
  static const struct pipe_buf_operations anon_pipe_buf_nomerge_ops = {
cac36bb06   Jens Axboe   pipe: change the ...
223
  	.confirm = generic_pipe_buf_confirm,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  	.release = anon_pipe_buf_release,
d86133bd3   Vladimir Davydov   pipe: account to ...
225
  	.steal = anon_pipe_buf_steal,
f84d75199   Jens Axboe   [PATCH] pipe: int...
226
  	.get = generic_pipe_buf_get,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  };
9883035ae   Linus Torvalds   pipes: add a "pac...
228
  static const struct pipe_buf_operations packet_pipe_buf_ops = {
9883035ae   Linus Torvalds   pipes: add a "pac...
229
230
  	.confirm = generic_pipe_buf_confirm,
  	.release = anon_pipe_buf_release,
d86133bd3   Vladimir Davydov   pipe: account to ...
231
  	.steal = anon_pipe_buf_steal,
9883035ae   Linus Torvalds   pipes: add a "pac...
232
233
  	.get = generic_pipe_buf_get,
  };
01e7187b4   Jann Horn   pipe: stop using ...
234
235
236
237
238
239
240
241
242
  /**
   * pipe_buf_mark_unmergeable - mark a &struct pipe_buffer as unmergeable
   * @buf:	the buffer to mark
   *
   * Description:
   *	This function ensures that no future writes will be merged into the
   *	given &struct pipe_buffer. This is necessary when multiple pipe buffers
   *	share the same backing page.
   */
a0ce2f0aa   Jann Horn   splice: don't mer...
243
244
245
246
247
  void pipe_buf_mark_unmergeable(struct pipe_buffer *buf)
  {
  	if (buf->ops == &anon_pipe_buf_ops)
  		buf->ops = &anon_pipe_buf_nomerge_ops;
  }
01e7187b4   Jann Horn   pipe: stop using ...
248
249
250
251
  static bool pipe_buf_can_merge(struct pipe_buffer *buf)
  {
  	return buf->ops == &anon_pipe_buf_ops;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  static ssize_t
fb9096a34   Al Viro   pipe: switch to -...
253
  pipe_read(struct kiocb *iocb, struct iov_iter *to)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  {
fb9096a34   Al Viro   pipe: switch to -...
255
  	size_t total_len = iov_iter_count(to);
ee0b3e671   Badari Pulavarty   [PATCH] Remove re...
256
  	struct file *filp = iocb->ki_filp;
de32ec4cf   Al Viro   pipe: set file->p...
257
  	struct pipe_inode_info *pipe = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
  	int do_wakeup;
  	ssize_t ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
  	/* Null read succeeds. */
  	if (unlikely(total_len == 0))
  		return 0;
  
  	do_wakeup = 0;
  	ret = 0;
ebec73f47   Al Viro   introduce variant...
267
  	__pipe_lock(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  	for (;;) {
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
269
  		int bufs = pipe->nrbufs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  		if (bufs) {
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
271
272
  			int curbuf = pipe->curbuf;
  			struct pipe_buffer *buf = pipe->bufs + curbuf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  			size_t chars = buf->len;
637b58c28   Al Viro   switch pipe_read(...
274
275
  			size_t written;
  			int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
  
  			if (chars > total_len)
  				chars = total_len;
fba597db4   Miklos Szeredi   pipe: add pipe_bu...
279
  			error = pipe_buf_confirm(pipe, buf);
f84d75199   Jens Axboe   [PATCH] pipe: int...
280
  			if (error) {
5274f052e   Jens Axboe   [PATCH] Introduce...
281
  				if (!ret)
e5953cbdf   Nicolas Kaiser   pipe: fix failure...
282
  					ret = error;
5274f052e   Jens Axboe   [PATCH] Introduce...
283
284
  				break;
  			}
f84d75199   Jens Axboe   [PATCH] pipe: int...
285

fb9096a34   Al Viro   pipe: switch to -...
286
  			written = copy_page_to_iter(buf->page, buf->offset, chars, to);
637b58c28   Al Viro   switch pipe_read(...
287
  			if (unlikely(written < chars)) {
341b446bc   Ingo Molnar   [PATCH] another r...
288
  				if (!ret)
637b58c28   Al Viro   switch pipe_read(...
289
  					ret = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
292
293
294
  				break;
  			}
  			ret += chars;
  			buf->offset += chars;
  			buf->len -= chars;
9883035ae   Linus Torvalds   pipes: add a "pac...
295
296
297
298
299
300
  
  			/* Was it a packet buffer? Clean up and exit */
  			if (buf->flags & PIPE_BUF_FLAG_PACKET) {
  				total_len = chars;
  				buf->len = 0;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  			if (!buf->len) {
a779638cf   Miklos Szeredi   pipe: add pipe_bu...
302
  				pipe_buf_release(pipe, buf);
35f3d14db   Jens Axboe   pipe: add support...
303
  				curbuf = (curbuf + 1) & (pipe->buffers - 1);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
304
305
  				pipe->curbuf = curbuf;
  				pipe->nrbufs = --bufs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
308
309
310
311
312
313
  				do_wakeup = 1;
  			}
  			total_len -= chars;
  			if (!total_len)
  				break;	/* common path: read succeeded */
  		}
  		if (bufs)	/* More to do? */
  			continue;
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
314
  		if (!pipe->writers)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  			break;
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
316
  		if (!pipe->waiting_writers) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
320
321
322
323
324
325
326
327
328
329
  			/* 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   Ingo Molnar   [PATCH] another r...
330
331
  			if (!ret)
  				ret = -ERESTARTSYS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
334
  			break;
  		}
  		if (do_wakeup) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
335
  			wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
336
   			kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  		}
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
338
  		pipe_wait(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  	}
ebec73f47   Al Viro   introduce variant...
340
  	__pipe_unlock(pipe);
341b446bc   Ingo Molnar   [PATCH] another r...
341
342
  
  	/* Signal writers asynchronously that there is more room. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  	if (do_wakeup) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
344
  		wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
345
  		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
  	}
  	if (ret > 0)
  		file_accessed(filp);
  	return ret;
  }
9883035ae   Linus Torvalds   pipes: add a "pac...
351
352
353
354
  static inline int is_packetized(struct file *file)
  {
  	return (file->f_flags & O_DIRECT) != 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
  static ssize_t
f0d1bec9d   Al Viro   new helper: copy_...
356
  pipe_write(struct kiocb *iocb, struct iov_iter *from)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  {
ee0b3e671   Badari Pulavarty   [PATCH] Remove re...
358
  	struct file *filp = iocb->ki_filp;
de32ec4cf   Al Viro   pipe: set file->p...
359
  	struct pipe_inode_info *pipe = filp->private_data;
f0d1bec9d   Al Viro   new helper: copy_...
360
361
362
  	ssize_t ret = 0;
  	int do_wakeup = 0;
  	size_t total_len = iov_iter_count(from);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  	ssize_t chars;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
  	/* Null write succeeds. */
  	if (unlikely(total_len == 0))
  		return 0;
ebec73f47   Al Viro   introduce variant...
367
  	__pipe_lock(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368

923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
369
  	if (!pipe->readers) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
374
375
376
  		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   Ingo Molnar   [PATCH] pipe.c/fi...
377
  	if (pipe->nrbufs && chars != 0) {
341b446bc   Ingo Molnar   [PATCH] another r...
378
  		int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
35f3d14db   Jens Axboe   pipe: add support...
379
  							(pipe->buffers - 1);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
380
  		struct pipe_buffer *buf = pipe->bufs + lastbuf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  		int offset = buf->offset + buf->len;
341b446bc   Ingo Molnar   [PATCH] another r...
382

01e7187b4   Jann Horn   pipe: stop using ...
383
  		if (pipe_buf_can_merge(buf) && offset + chars <= PAGE_SIZE) {
fba597db4   Miklos Szeredi   pipe: add pipe_bu...
384
  			ret = pipe_buf_confirm(pipe, buf);
6ae080699   Eric Biggers   fs/pipe.c: return...
385
  			if (ret)
5274f052e   Jens Axboe   [PATCH] Introduce...
386
  				goto out;
f84d75199   Jens Axboe   [PATCH] pipe: int...
387

f0d1bec9d   Al Viro   new helper: copy_...
388
389
  			ret = copy_page_from_iter(buf->page, offset, chars, from);
  			if (unlikely(ret < chars)) {
6ae080699   Eric Biggers   fs/pipe.c: return...
390
  				ret = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  				goto out;
f6762b7ad   Jens Axboe   [PATCH] pipe: ena...
392
  			}
f0d1bec9d   Al Viro   new helper: copy_...
393
  			do_wakeup = 1;
6ae080699   Eric Biggers   fs/pipe.c: return...
394
  			buf->len += ret;
f0d1bec9d   Al Viro   new helper: copy_...
395
  			if (!iov_iter_count(from))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
401
  				goto out;
  		}
  	}
  
  	for (;;) {
  		int bufs;
341b446bc   Ingo Molnar   [PATCH] another r...
402

923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
403
  		if (!pipe->readers) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  			send_sig(SIGPIPE, current, 0);
341b446bc   Ingo Molnar   [PATCH] another r...
405
406
  			if (!ret)
  				ret = -EPIPE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
  			break;
  		}
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
409
  		bufs = pipe->nrbufs;
35f3d14db   Jens Axboe   pipe: add support...
410
411
  		if (bufs < pipe->buffers) {
  			int newbuf = (pipe->curbuf + bufs) & (pipe->buffers-1);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
412
413
  			struct pipe_buffer *buf = pipe->bufs + newbuf;
  			struct page *page = pipe->tmp_page;
f0d1bec9d   Al Viro   new helper: copy_...
414
  			int copied;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
  
  			if (!page) {
d86133bd3   Vladimir Davydov   pipe: account to ...
417
  				page = alloc_page(GFP_HIGHUSER | __GFP_ACCOUNT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
420
421
  				if (unlikely(!page)) {
  					ret = ret ? : -ENOMEM;
  					break;
  				}
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
422
  				pipe->tmp_page = page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  			}
341b446bc   Ingo Molnar   [PATCH] another r...
424
  			/* Always wake up, even if the copy fails. Otherwise
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
427
428
429
  			 * we lock up (O_NONBLOCK-)readers that sleep due to
  			 * syscall merging.
  			 * FIXME! Is this really true?
  			 */
  			do_wakeup = 1;
f0d1bec9d   Al Viro   new helper: copy_...
430
431
  			copied = copy_page_from_iter(page, 0, PAGE_SIZE, from);
  			if (unlikely(copied < PAGE_SIZE && iov_iter_count(from))) {
341b446bc   Ingo Molnar   [PATCH] another r...
432
  				if (!ret)
f0d1bec9d   Al Viro   new helper: copy_...
433
  					ret = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
  				break;
  			}
f0d1bec9d   Al Viro   new helper: copy_...
436
  			ret += copied;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
439
440
441
  
  			/* Insert it into the buffer array */
  			buf->page = page;
  			buf->ops = &anon_pipe_buf_ops;
  			buf->offset = 0;
f0d1bec9d   Al Viro   new helper: copy_...
442
  			buf->len = copied;
9883035ae   Linus Torvalds   pipes: add a "pac...
443
444
445
446
447
  			buf->flags = 0;
  			if (is_packetized(filp)) {
  				buf->ops = &packet_pipe_buf_ops;
  				buf->flags = PIPE_BUF_FLAG_PACKET;
  			}
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
448
449
  			pipe->nrbufs = ++bufs;
  			pipe->tmp_page = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450

f0d1bec9d   Al Viro   new helper: copy_...
451
  			if (!iov_iter_count(from))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
  				break;
  		}
35f3d14db   Jens Axboe   pipe: add support...
454
  		if (bufs < pipe->buffers)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
  			continue;
  		if (filp->f_flags & O_NONBLOCK) {
341b446bc   Ingo Molnar   [PATCH] another r...
457
458
  			if (!ret)
  				ret = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
  			break;
  		}
  		if (signal_pending(current)) {
341b446bc   Ingo Molnar   [PATCH] another r...
462
463
  			if (!ret)
  				ret = -ERESTARTSYS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
  			break;
  		}
  		if (do_wakeup) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
467
  			wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
468
  			kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
  			do_wakeup = 0;
  		}
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
471
472
473
  		pipe->waiting_writers++;
  		pipe_wait(pipe);
  		pipe->waiting_writers--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  	}
  out:
ebec73f47   Al Viro   introduce variant...
476
  	__pipe_unlock(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  	if (do_wakeup) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
478
  		wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
479
  		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  	}
7e775f46a   Dmitry Monakhov   fs/pipe.c: skip f...
481
  	if (ret > 0 && sb_start_write_trylock(file_inode(filp)->i_sb)) {
c3b2da314   Josef Bacik   fs: introduce ino...
482
483
484
  		int err = file_update_time(filp);
  		if (err)
  			ret = err;
7e775f46a   Dmitry Monakhov   fs/pipe.c: skip f...
485
  		sb_end_write(file_inode(filp)->i_sb);
c3b2da314   Josef Bacik   fs: introduce ino...
486
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
  	return ret;
  }
d59d0b1b8   Andi Kleen   BKL-Removal: conv...
489
  static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  {
de32ec4cf   Al Viro   pipe: set file->p...
491
  	struct pipe_inode_info *pipe = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
495
  	int count, buf, nrbufs;
  
  	switch (cmd) {
  		case FIONREAD:
ebec73f47   Al Viro   introduce variant...
496
  			__pipe_lock(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
  			count = 0;
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
498
499
  			buf = pipe->curbuf;
  			nrbufs = pipe->nrbufs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  			while (--nrbufs >= 0) {
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
501
  				count += pipe->bufs[buf].len;
35f3d14db   Jens Axboe   pipe: add support...
502
  				buf = (buf+1) & (pipe->buffers - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
  			}
ebec73f47   Al Viro   introduce variant...
504
  			__pipe_unlock(pipe);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
505

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
  			return put_user(count, (int __user *)arg);
  		default:
46ce341b2   Will Deacon   pipe: return -ENO...
508
  			return -ENOIOCTLCMD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
  	}
  }
dd67081b3   Christoph Hellwig   pipe: convert to ...
511
  /* No kernel lock held - fine */
a11e1d432   Linus Torvalds   Revert changes to...
512
513
  static __poll_t
  pipe_poll(struct file *filp, poll_table *wait)
dd67081b3   Christoph Hellwig   pipe: convert to ...
514
  {
a11e1d432   Linus Torvalds   Revert changes to...
515
  	__poll_t mask;
dd67081b3   Christoph Hellwig   pipe: convert to ...
516
  	struct pipe_inode_info *pipe = filp->private_data;
a11e1d432   Linus Torvalds   Revert changes to...
517
518
519
  	int nrbufs;
  
  	poll_wait(filp, &pipe->wait, wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
  
  	/* Reading only -- no need for acquiring the semaphore.  */
a11e1d432   Linus Torvalds   Revert changes to...
522
523
  	nrbufs = pipe->nrbufs;
  	mask = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
  	if (filp->f_mode & FMODE_READ) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
525
  		mask = (nrbufs > 0) ? EPOLLIN | EPOLLRDNORM : 0;
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
526
  		if (!pipe->writers && filp->f_version != pipe->w_counter)
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
527
  			mask |= EPOLLHUP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
529
530
  	}
  
  	if (filp->f_mode & FMODE_WRITE) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
531
  		mask |= (nrbufs < pipe->buffers) ? EPOLLOUT | EPOLLWRNORM : 0;
5e5d7a222   Pekka Enberg   [PATCH] pipe: rem...
532
  		/*
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
533
  		 * Most Unices do not set EPOLLERR for FIFOs but on Linux they
5e5d7a222   Pekka Enberg   [PATCH] pipe: rem...
534
535
  		 * behave exactly like pipes for poll().
  		 */
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
536
  		if (!pipe->readers)
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
537
  			mask |= EPOLLERR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
540
541
  	}
  
  	return mask;
  }
b0d8d2292   Linus Torvalds   vfs: fix subtle u...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
  static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
  {
  	int kill = 0;
  
  	spin_lock(&inode->i_lock);
  	if (!--pipe->files) {
  		inode->i_pipe = NULL;
  		kill = 1;
  	}
  	spin_unlock(&inode->i_lock);
  
  	if (kill)
  		free_pipe_info(pipe);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
  static int
599a0ac14   Al Viro   pipe: fold file_o...
557
  pipe_release(struct inode *inode, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
  {
b0d8d2292   Linus Torvalds   vfs: fix subtle u...
559
  	struct pipe_inode_info *pipe = file->private_data;
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
560

ebec73f47   Al Viro   introduce variant...
561
  	__pipe_lock(pipe);
599a0ac14   Al Viro   pipe: fold file_o...
562
563
564
565
  	if (file->f_mode & FMODE_READ)
  		pipe->readers--;
  	if (file->f_mode & FMODE_WRITE)
  		pipe->writers--;
341b446bc   Ingo Molnar   [PATCH] another r...
566

ba5bb1473   Al Viro   pipe: take alloca...
567
  	if (pipe->readers || pipe->writers) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
568
  		wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM | EPOLLERR | EPOLLHUP);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
569
570
  		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
  		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  	}
ebec73f47   Al Viro   introduce variant...
572
  	__pipe_unlock(pipe);
ba5bb1473   Al Viro   pipe: take alloca...
573

b0d8d2292   Linus Torvalds   vfs: fix subtle u...
574
  	put_pipe_info(inode, pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
577
578
  	return 0;
  }
  
  static int
599a0ac14   Al Viro   pipe: fold file_o...
579
  pipe_fasync(int fd, struct file *filp, int on)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  {
de32ec4cf   Al Viro   pipe: set file->p...
581
  	struct pipe_inode_info *pipe = filp->private_data;
599a0ac14   Al Viro   pipe: fold file_o...
582
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583

ebec73f47   Al Viro   introduce variant...
584
  	__pipe_lock(pipe);
599a0ac14   Al Viro   pipe: fold file_o...
585
586
587
  	if (filp->f_mode & FMODE_READ)
  		retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
  	if ((filp->f_mode & FMODE_WRITE) && retval >= 0) {
341b446bc   Ingo Molnar   [PATCH] another r...
588
  		retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
599a0ac14   Al Viro   pipe: fold file_o...
589
590
  		if (retval < 0 && (filp->f_mode & FMODE_READ))
  			/* this can happen only if on == T */
e5bc49ba7   Oleg Nesterov   pipe_rdwr_fasync:...
591
592
  			fasync_helper(-1, filp, 0, &pipe->fasync_readers);
  	}
ebec73f47   Al Viro   introduce variant...
593
  	__pipe_unlock(pipe);
60aa49243   Jonathan Corbet   Rationalize fasyn...
594
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  }
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
596
  static unsigned long account_pipe_buffers(struct user_struct *user,
759c01142   Willy Tarreau   pipe: limit the p...
597
598
                                   unsigned long old, unsigned long new)
  {
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
599
  	return atomic_long_add_return(new - old, &user->pipe_bufs);
759c01142   Willy Tarreau   pipe: limit the p...
600
  }
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
601
  static bool too_many_pipe_buffers_soft(unsigned long user_bufs)
759c01142   Willy Tarreau   pipe: limit the p...
602
  {
f73407618   Eric Biggers   pipe: read buffer...
603
604
605
  	unsigned long soft_limit = READ_ONCE(pipe_user_pages_soft);
  
  	return soft_limit && user_bufs > soft_limit;
759c01142   Willy Tarreau   pipe: limit the p...
606
  }
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
607
  static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
759c01142   Willy Tarreau   pipe: limit the p...
608
  {
f73407618   Eric Biggers   pipe: read buffer...
609
610
611
  	unsigned long hard_limit = READ_ONCE(pipe_user_pages_hard);
  
  	return hard_limit && user_bufs > hard_limit;
759c01142   Willy Tarreau   pipe: limit the p...
612
  }
85c2dd547   Eric Biggers   pipe: actually al...
613
614
615
616
  static bool is_unprivileged_user(void)
  {
  	return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
  }
7bee130e2   Al Viro   get rid of alloc_...
617
  struct pipe_inode_info *alloc_pipe_info(void)
3a326a2ce   Ingo Molnar   [PATCH] introduce...
618
  {
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
619
  	struct pipe_inode_info *pipe;
09b4d1990   Michael Kerrisk (man-pages)   pipe: simplify lo...
620
621
  	unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
  	struct user_struct *user = get_current_user();
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
622
  	unsigned long user_bufs;
f73407618   Eric Biggers   pipe: read buffer...
623
  	unsigned int max_size = READ_ONCE(pipe_max_size);
3a326a2ce   Ingo Molnar   [PATCH] introduce...
624

d86133bd3   Vladimir Davydov   pipe: account to ...
625
  	pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT);
09b4d1990   Michael Kerrisk (man-pages)   pipe: simplify lo...
626
627
  	if (pipe == NULL)
  		goto out_free_uid;
f73407618   Eric Biggers   pipe: read buffer...
628
629
  	if (pipe_bufs * PAGE_SIZE > max_size && !capable(CAP_SYS_RESOURCE))
  		pipe_bufs = max_size >> PAGE_SHIFT;
086e774a5   Michael Kerrisk (man-pages)   pipe: cap initial...
630

9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
631
  	user_bufs = account_pipe_buffers(user, 0, pipe_bufs);
a005ca0e6   Michael Kerrisk (man-pages)   pipe: fix limit c...
632

85c2dd547   Eric Biggers   pipe: actually al...
633
  	if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) {
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
634
  		user_bufs = account_pipe_buffers(user, pipe_bufs, 1);
a005ca0e6   Michael Kerrisk (man-pages)   pipe: fix limit c...
635
  		pipe_bufs = 1;
09b4d1990   Michael Kerrisk (man-pages)   pipe: simplify lo...
636
  	}
759c01142   Willy Tarreau   pipe: limit the p...
637

85c2dd547   Eric Biggers   pipe: actually al...
638
  	if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user())
a005ca0e6   Michael Kerrisk (man-pages)   pipe: fix limit c...
639
640
641
642
  		goto out_revert_acct;
  
  	pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer),
  			     GFP_KERNEL_ACCOUNT);
09b4d1990   Michael Kerrisk (man-pages)   pipe: simplify lo...
643
644
645
646
647
  	if (pipe->bufs) {
  		init_waitqueue_head(&pipe->wait);
  		pipe->r_counter = pipe->w_counter = 1;
  		pipe->buffers = pipe_bufs;
  		pipe->user = user;
09b4d1990   Michael Kerrisk (man-pages)   pipe: simplify lo...
648
649
  		mutex_init(&pipe->mutex);
  		return pipe;
3a326a2ce   Ingo Molnar   [PATCH] introduce...
650
  	}
a005ca0e6   Michael Kerrisk (man-pages)   pipe: fix limit c...
651
  out_revert_acct:
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
652
  	(void) account_pipe_buffers(user, pipe_bufs, 0);
09b4d1990   Michael Kerrisk (man-pages)   pipe: simplify lo...
653
654
655
  	kfree(pipe);
  out_free_uid:
  	free_uid(user);
35f3d14db   Jens Axboe   pipe: add support...
656
  	return NULL;
3a326a2ce   Ingo Molnar   [PATCH] introduce...
657
  }
4b8a8f1e4   Al Viro   get rid of the la...
658
  void free_pipe_info(struct pipe_inode_info *pipe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661

9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
662
  	(void) account_pipe_buffers(pipe->user, pipe->buffers, 0);
759c01142   Willy Tarreau   pipe: limit the p...
663
  	free_uid(pipe->user);
35f3d14db   Jens Axboe   pipe: add support...
664
  	for (i = 0; i < pipe->buffers; i++) {
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
665
  		struct pipe_buffer *buf = pipe->bufs + i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  		if (buf->ops)
a779638cf   Miklos Szeredi   pipe: add pipe_bu...
667
  			pipe_buf_release(pipe, buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
  	}
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
669
670
  	if (pipe->tmp_page)
  		__free_page(pipe->tmp_page);
35f3d14db   Jens Axboe   pipe: add support...
671
  	kfree(pipe->bufs);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
672
  	kfree(pipe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
  }
fa3536cc1   Eric Dumazet   [PATCH] Use __rea...
674
  static struct vfsmount *pipe_mnt __read_mostly;
341b446bc   Ingo Molnar   [PATCH] another r...
675

c23fbb6bc   Eric Dumazet   VFS: delay the de...
676
677
678
679
680
681
  /*
   * 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]",
75c3cfa85   David Howells   VFS: assorted wei...
682
  				d_inode(dentry)->i_ino);
c23fbb6bc   Eric Dumazet   VFS: delay the de...
683
  }
3ba13d179   Al Viro   constify dentry_o...
684
  static const struct dentry_operations pipefs_dentry_operations = {
c23fbb6bc   Eric Dumazet   VFS: delay the de...
685
  	.d_dname	= pipefs_dname,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
  };
  
  static struct inode * get_pipe_inode(void)
  {
a209dfc7b   Eric Dumazet   vfs: dont chain p...
690
  	struct inode *inode = new_inode_pseudo(pipe_mnt->mnt_sb);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
691
  	struct pipe_inode_info *pipe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
  
  	if (!inode)
  		goto fail_inode;
85fe4025c   Christoph Hellwig   fs: do not assign...
695
  	inode->i_ino = get_next_ino();
7bee130e2   Al Viro   get rid of alloc_...
696
  	pipe = alloc_pipe_info();
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
697
  	if (!pipe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  		goto fail_iput;
3a326a2ce   Ingo Molnar   [PATCH] introduce...
699

ba5bb1473   Al Viro   pipe: take alloca...
700
701
  	inode->i_pipe = pipe;
  	pipe->files = 2;
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
702
  	pipe->readers = pipe->writers = 1;
599a0ac14   Al Viro   pipe: fold file_o...
703
  	inode->i_fop = &pipefifo_fops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
706
707
708
709
710
711
712
  
  	/*
  	 * 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   David Howells   CRED: Wrap task c...
713
714
  	inode->i_uid = current_fsuid();
  	inode->i_gid = current_fsgid();
078cd8279   Deepa Dinamani   fs: Replace CURRE...
715
  	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
923f4f239   Ingo Molnar   [PATCH] pipe.c/fi...
716

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
719
720
  	return inode;
  
  fail_iput:
  	iput(inode);
341b446bc   Ingo Molnar   [PATCH] another r...
721

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
724
  fail_inode:
  	return NULL;
  }
e4fad8e5d   Al Viro   consolidate pipe ...
725
  int create_pipe_files(struct file **res, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  {
e4fad8e5d   Al Viro   consolidate pipe ...
727
  	struct inode *inode = get_pipe_inode();
d6cbd281d   Andi Kleen   [PATCH] Some clea...
728
  	struct file *f;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
  	if (!inode)
e4fad8e5d   Al Viro   consolidate pipe ...
731
  		return -ENFILE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732

152b6372c   Al Viro   create_pipe_files...
733
734
735
  	f = alloc_file_pseudo(inode, pipe_mnt, "",
  				O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)),
  				&pipefifo_fops);
e9bb1f9b1   Eric Biggers   fs/pipe.c: preser...
736
  	if (IS_ERR(f)) {
152b6372c   Al Viro   create_pipe_files...
737
738
739
  		free_pipe_info(inode->i_pipe);
  		iput(inode);
  		return PTR_ERR(f);
e9bb1f9b1   Eric Biggers   fs/pipe.c: preser...
740
  	}
341b446bc   Ingo Molnar   [PATCH] another r...
741

de32ec4cf   Al Viro   pipe: set file->p...
742
  	f->private_data = inode->i_pipe;
d6cbd281d   Andi Kleen   [PATCH] Some clea...
743

183266f26   Al Viro   new helper: alloc...
744
745
  	res[0] = alloc_file_clone(f, O_RDONLY | (flags & O_NONBLOCK),
  				  &pipefifo_fops);
e9bb1f9b1   Eric Biggers   fs/pipe.c: preser...
746
  	if (IS_ERR(res[0])) {
b10a4a9f7   Al Viro   create_pipe_files...
747
748
749
  		put_pipe_info(inode, inode->i_pipe);
  		fput(f);
  		return PTR_ERR(res[0]);
e9bb1f9b1   Eric Biggers   fs/pipe.c: preser...
750
  	}
de32ec4cf   Al Viro   pipe: set file->p...
751
  	res[0]->private_data = inode->i_pipe;
e4fad8e5d   Al Viro   consolidate pipe ...
752
753
  	res[1] = f;
  	return 0;
d6cbd281d   Andi Kleen   [PATCH] Some clea...
754
  }
5b249b1b0   Al Viro   pipe(2) - race-fr...
755
  static int __do_pipe_flags(int *fd, struct file **files, int flags)
d6cbd281d   Andi Kleen   [PATCH] Some clea...
756
  {
d6cbd281d   Andi Kleen   [PATCH] Some clea...
757
758
  	int error;
  	int fdw, fdr;
9883035ae   Linus Torvalds   pipes: add a "pac...
759
  	if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT))
ed8cae8ba   Ulrich Drepper   flag parameters: ...
760
  		return -EINVAL;
e4fad8e5d   Al Viro   consolidate pipe ...
761
762
763
  	error = create_pipe_files(files, flags);
  	if (error)
  		return error;
d6cbd281d   Andi Kleen   [PATCH] Some clea...
764

ed8cae8ba   Ulrich Drepper   flag parameters: ...
765
  	error = get_unused_fd_flags(flags);
d6cbd281d   Andi Kleen   [PATCH] Some clea...
766
767
768
  	if (error < 0)
  		goto err_read_pipe;
  	fdr = error;
ed8cae8ba   Ulrich Drepper   flag parameters: ...
769
  	error = get_unused_fd_flags(flags);
d6cbd281d   Andi Kleen   [PATCH] Some clea...
770
771
772
  	if (error < 0)
  		goto err_fdr;
  	fdw = error;
157cf649a   Al Viro   sanitize audit_fd...
773
  	audit_fd_pair(fdr, fdw);
d6cbd281d   Andi Kleen   [PATCH] Some clea...
774
775
  	fd[0] = fdr;
  	fd[1] = fdw;
d6cbd281d   Andi Kleen   [PATCH] Some clea...
776
777
778
779
780
  	return 0;
  
   err_fdr:
  	put_unused_fd(fdr);
   err_read_pipe:
e4fad8e5d   Al Viro   consolidate pipe ...
781
782
  	fput(files[0]);
  	fput(files[1]);
d6cbd281d   Andi Kleen   [PATCH] Some clea...
783
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  }
5b249b1b0   Al Viro   pipe(2) - race-fr...
785
786
787
788
789
790
791
792
793
794
  int do_pipe_flags(int *fd, int flags)
  {
  	struct file *files[2];
  	int error = __do_pipe_flags(fd, files, flags);
  	if (!error) {
  		fd_install(fd[0], files[0]);
  		fd_install(fd[1], files[1]);
  	}
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
  /*
d35c7b0e5   Ulrich Drepper   unified (weak) sy...
796
797
798
   * sys_pipe() is the normal C calling standard for creating
   * a pipe. It's not the way Unix traditionally does this, though.
   */
0a216dd1c   Dominik Brodowski   fs: add do_pipe2(...
799
  static int do_pipe2(int __user *fildes, int flags)
d35c7b0e5   Ulrich Drepper   unified (weak) sy...
800
  {
5b249b1b0   Al Viro   pipe(2) - race-fr...
801
  	struct file *files[2];
d35c7b0e5   Ulrich Drepper   unified (weak) sy...
802
803
  	int fd[2];
  	int error;
5b249b1b0   Al Viro   pipe(2) - race-fr...
804
  	error = __do_pipe_flags(fd, files, flags);
d35c7b0e5   Ulrich Drepper   unified (weak) sy...
805
  	if (!error) {
5b249b1b0   Al Viro   pipe(2) - race-fr...
806
807
808
809
810
  		if (unlikely(copy_to_user(fildes, fd, sizeof(fd)))) {
  			fput(files[0]);
  			fput(files[1]);
  			put_unused_fd(fd[0]);
  			put_unused_fd(fd[1]);
d35c7b0e5   Ulrich Drepper   unified (weak) sy...
811
  			error = -EFAULT;
5b249b1b0   Al Viro   pipe(2) - race-fr...
812
813
814
  		} else {
  			fd_install(fd[0], files[0]);
  			fd_install(fd[1], files[1]);
ba719baea   Ulrich Drepper   sys_pipe(): fix f...
815
  		}
d35c7b0e5   Ulrich Drepper   unified (weak) sy...
816
817
818
  	}
  	return error;
  }
0a216dd1c   Dominik Brodowski   fs: add do_pipe2(...
819
820
821
822
  SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags)
  {
  	return do_pipe2(fildes, flags);
  }
2b6642199   Heiko Carstens   [CVE-2009-0029] S...
823
  SYSCALL_DEFINE1(pipe, int __user *, fildes)
ed8cae8ba   Ulrich Drepper   flag parameters: ...
824
  {
0a216dd1c   Dominik Brodowski   fs: add do_pipe2(...
825
  	return do_pipe2(fildes, 0);
ed8cae8ba   Ulrich Drepper   flag parameters: ...
826
  }
fc7478a2b   Al Viro   pipe: switch wait...
827
  static int wait_for_partner(struct pipe_inode_info *pipe, unsigned int *cnt)
f776c7388   Al Viro   fold fifo.c into ...
828
829
830
831
  {
  	int cur = *cnt;	
  
  	while (cur == *cnt) {
fc7478a2b   Al Viro   pipe: switch wait...
832
  		pipe_wait(pipe);
f776c7388   Al Viro   fold fifo.c into ...
833
834
835
836
837
  		if (signal_pending(current))
  			break;
  	}
  	return cur == *cnt ? -ERESTARTSYS : 0;
  }
fc7478a2b   Al Viro   pipe: switch wait...
838
  static void wake_up_partner(struct pipe_inode_info *pipe)
f776c7388   Al Viro   fold fifo.c into ...
839
  {
fc7478a2b   Al Viro   pipe: switch wait...
840
  	wake_up_interruptible(&pipe->wait);
f776c7388   Al Viro   fold fifo.c into ...
841
842
843
844
845
  }
  
  static int fifo_open(struct inode *inode, struct file *filp)
  {
  	struct pipe_inode_info *pipe;
599a0ac14   Al Viro   pipe: fold file_o...
846
  	bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
f776c7388   Al Viro   fold fifo.c into ...
847
  	int ret;
ba5bb1473   Al Viro   pipe: take alloca...
848
849
850
851
852
853
854
855
856
  	filp->f_version = 0;
  
  	spin_lock(&inode->i_lock);
  	if (inode->i_pipe) {
  		pipe = inode->i_pipe;
  		pipe->files++;
  		spin_unlock(&inode->i_lock);
  	} else {
  		spin_unlock(&inode->i_lock);
7bee130e2   Al Viro   get rid of alloc_...
857
  		pipe = alloc_pipe_info();
f776c7388   Al Viro   fold fifo.c into ...
858
  		if (!pipe)
ba5bb1473   Al Viro   pipe: take alloca...
859
860
861
862
863
864
  			return -ENOMEM;
  		pipe->files = 1;
  		spin_lock(&inode->i_lock);
  		if (unlikely(inode->i_pipe)) {
  			inode->i_pipe->files++;
  			spin_unlock(&inode->i_lock);
4b8a8f1e4   Al Viro   get rid of the la...
865
  			free_pipe_info(pipe);
ba5bb1473   Al Viro   pipe: take alloca...
866
867
868
869
870
  			pipe = inode->i_pipe;
  		} else {
  			inode->i_pipe = pipe;
  			spin_unlock(&inode->i_lock);
  		}
f776c7388   Al Viro   fold fifo.c into ...
871
  	}
de32ec4cf   Al Viro   pipe: set file->p...
872
  	filp->private_data = pipe;
ba5bb1473   Al Viro   pipe: take alloca...
873
  	/* OK, we have a pipe and it's pinned down */
ebec73f47   Al Viro   introduce variant...
874
  	__pipe_lock(pipe);
f776c7388   Al Viro   fold fifo.c into ...
875
876
877
878
879
880
881
882
883
884
885
  
  	/* We can only do regular read/write on fifos */
  	filp->f_mode &= (FMODE_READ | FMODE_WRITE);
  
  	switch (filp->f_mode) {
  	case FMODE_READ:
  	/*
  	 *  O_RDONLY
  	 *  POSIX.1 says that O_NONBLOCK means return with the FIFO
  	 *  opened, even when there is no process writing the FIFO.
  	 */
f776c7388   Al Viro   fold fifo.c into ...
886
887
  		pipe->r_counter++;
  		if (pipe->readers++ == 0)
fc7478a2b   Al Viro   pipe: switch wait...
888
  			wake_up_partner(pipe);
f776c7388   Al Viro   fold fifo.c into ...
889

599a0ac14   Al Viro   pipe: fold file_o...
890
  		if (!is_pipe && !pipe->writers) {
f776c7388   Al Viro   fold fifo.c into ...
891
  			if ((filp->f_flags & O_NONBLOCK)) {
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
892
  				/* suppress EPOLLHUP until we have
f776c7388   Al Viro   fold fifo.c into ...
893
894
895
  				 * seen a writer */
  				filp->f_version = pipe->w_counter;
  			} else {
fc7478a2b   Al Viro   pipe: switch wait...
896
  				if (wait_for_partner(pipe, &pipe->w_counter))
f776c7388   Al Viro   fold fifo.c into ...
897
898
899
900
901
902
903
904
905
906
907
908
  					goto err_rd;
  			}
  		}
  		break;
  	
  	case FMODE_WRITE:
  	/*
  	 *  O_WRONLY
  	 *  POSIX.1 says that O_NONBLOCK means return -1 with
  	 *  errno=ENXIO when there is no process reading the FIFO.
  	 */
  		ret = -ENXIO;
599a0ac14   Al Viro   pipe: fold file_o...
909
  		if (!is_pipe && (filp->f_flags & O_NONBLOCK) && !pipe->readers)
f776c7388   Al Viro   fold fifo.c into ...
910
  			goto err;
f776c7388   Al Viro   fold fifo.c into ...
911
912
  		pipe->w_counter++;
  		if (!pipe->writers++)
fc7478a2b   Al Viro   pipe: switch wait...
913
  			wake_up_partner(pipe);
f776c7388   Al Viro   fold fifo.c into ...
914

599a0ac14   Al Viro   pipe: fold file_o...
915
  		if (!is_pipe && !pipe->readers) {
fc7478a2b   Al Viro   pipe: switch wait...
916
  			if (wait_for_partner(pipe, &pipe->r_counter))
f776c7388   Al Viro   fold fifo.c into ...
917
918
919
920
921
922
923
924
925
926
927
  				goto err_wr;
  		}
  		break;
  	
  	case FMODE_READ | FMODE_WRITE:
  	/*
  	 *  O_RDWR
  	 *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
  	 *  This implementation will NEVER block on a O_RDWR open, since
  	 *  the process can at least talk to itself.
  	 */
f776c7388   Al Viro   fold fifo.c into ...
928
929
930
931
932
933
  
  		pipe->readers++;
  		pipe->writers++;
  		pipe->r_counter++;
  		pipe->w_counter++;
  		if (pipe->readers == 1 || pipe->writers == 1)
fc7478a2b   Al Viro   pipe: switch wait...
934
  			wake_up_partner(pipe);
f776c7388   Al Viro   fold fifo.c into ...
935
936
937
938
939
940
941
942
  		break;
  
  	default:
  		ret = -EINVAL;
  		goto err;
  	}
  
  	/* Ok! */
ebec73f47   Al Viro   introduce variant...
943
  	__pipe_unlock(pipe);
f776c7388   Al Viro   fold fifo.c into ...
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
  	return 0;
  
  err_rd:
  	if (!--pipe->readers)
  		wake_up_interruptible(&pipe->wait);
  	ret = -ERESTARTSYS;
  	goto err;
  
  err_wr:
  	if (!--pipe->writers)
  		wake_up_interruptible(&pipe->wait);
  	ret = -ERESTARTSYS;
  	goto err;
  
  err:
ebec73f47   Al Viro   introduce variant...
959
  	__pipe_unlock(pipe);
b0d8d2292   Linus Torvalds   vfs: fix subtle u...
960
961
  
  	put_pipe_info(inode, pipe);
f776c7388   Al Viro   fold fifo.c into ...
962
963
  	return ret;
  }
599a0ac14   Al Viro   pipe: fold file_o...
964
965
966
  const struct file_operations pipefifo_fops = {
  	.open		= fifo_open,
  	.llseek		= no_llseek,
fb9096a34   Al Viro   pipe: switch to -...
967
  	.read_iter	= pipe_read,
f0d1bec9d   Al Viro   new helper: copy_...
968
  	.write_iter	= pipe_write,
a11e1d432   Linus Torvalds   Revert changes to...
969
  	.poll		= pipe_poll,
599a0ac14   Al Viro   pipe: fold file_o...
970
971
972
  	.unlocked_ioctl	= pipe_ioctl,
  	.release	= pipe_release,
  	.fasync		= pipe_fasync,
f776c7388   Al Viro   fold fifo.c into ...
973
  };
d35c7b0e5   Ulrich Drepper   unified (weak) sy...
974
  /*
f491bd711   Michael Kerrisk (man-pages)   pipe: relocate ro...
975
   * Currently we rely on the pipe array holding a power-of-2 number
d3f14c485   Joe Lawrence   pipe: avoid round...
976
   * of pages. Returns 0 on error.
f491bd711   Michael Kerrisk (man-pages)   pipe: relocate ro...
977
   */
96e99be40   Eric Biggers   pipe: reject F_SE...
978
  unsigned int round_pipe_size(unsigned long size)
f491bd711   Michael Kerrisk (man-pages)   pipe: relocate ro...
979
  {
c4fed5a91   Eric Biggers   pipe: simplify ro...
980
  	if (size > (1U << 31))
96e99be40   Eric Biggers   pipe: reject F_SE...
981
  		return 0;
4c2e4befb   Eric Biggers   pipe, sysctl: dro...
982
983
  	/* Minimum pipe size, as required by POSIX */
  	if (size < PAGE_SIZE)
c4fed5a91   Eric Biggers   pipe: simplify ro...
984
  		return PAGE_SIZE;
d3f14c485   Joe Lawrence   pipe: avoid round...
985

c4fed5a91   Eric Biggers   pipe: simplify ro...
986
  	return roundup_pow_of_two(size);
f491bd711   Michael Kerrisk (man-pages)   pipe: relocate ro...
987
988
989
  }
  
  /*
35f3d14db   Jens Axboe   pipe: add support...
990
991
992
   * Allocate a new array of pipe buffers and copy the info over. Returns the
   * pipe size if successful, or return -ERROR on error.
   */
d37d41666   Michael Kerrisk (man-pages)   pipe: move limit ...
993
  static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
35f3d14db   Jens Axboe   pipe: add support...
994
995
  {
  	struct pipe_buffer *bufs;
d37d41666   Michael Kerrisk (man-pages)   pipe: move limit ...
996
  	unsigned int size, nr_pages;
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
997
  	unsigned long user_bufs;
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
998
  	long ret = 0;
d37d41666   Michael Kerrisk (man-pages)   pipe: move limit ...
999
1000
1001
1002
1003
1004
  
  	size = round_pipe_size(arg);
  	nr_pages = size >> PAGE_SHIFT;
  
  	if (!nr_pages)
  		return -EINVAL;
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
1005
1006
1007
1008
1009
1010
1011
1012
1013
  	/*
  	 * If trying to increase the pipe capacity, check that an
  	 * unprivileged user is not trying to exceed various limits
  	 * (soft limit check here, hard limit check just below).
  	 * Decreasing the pipe capacity is always permitted, even
  	 * if the user is currently over a limit.
  	 */
  	if (nr_pages > pipe->buffers &&
  			size > pipe_max_size && !capable(CAP_SYS_RESOURCE))
d37d41666   Michael Kerrisk (man-pages)   pipe: move limit ...
1014
  		return -EPERM;
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
1015
  	user_bufs = account_pipe_buffers(pipe->user, pipe->buffers, nr_pages);
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
1016
1017
  
  	if (nr_pages > pipe->buffers &&
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
1018
1019
  			(too_many_pipe_buffers_hard(user_bufs) ||
  			 too_many_pipe_buffers_soft(user_bufs)) &&
85c2dd547   Eric Biggers   pipe: actually al...
1020
  			is_unprivileged_user()) {
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
1021
1022
1023
  		ret = -EPERM;
  		goto out_revert_acct;
  	}
35f3d14db   Jens Axboe   pipe: add support...
1024
1025
  
  	/*
35f3d14db   Jens Axboe   pipe: add support...
1026
1027
1028
1029
1030
  	 * We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't
  	 * expect a lot of shrink+grow operations, just free and allocate
  	 * again like we would do for growing. If the pipe currently
  	 * contains more buffers than arg, then return busy.
  	 */
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
1031
1032
1033
1034
  	if (nr_pages < pipe->nrbufs) {
  		ret = -EBUSY;
  		goto out_revert_acct;
  	}
35f3d14db   Jens Axboe   pipe: add support...
1035

d86133bd3   Vladimir Davydov   pipe: account to ...
1036
1037
  	bufs = kcalloc(nr_pages, sizeof(*bufs),
  		       GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
1038
1039
1040
1041
  	if (unlikely(!bufs)) {
  		ret = -ENOMEM;
  		goto out_revert_acct;
  	}
35f3d14db   Jens Axboe   pipe: add support...
1042
1043
1044
1045
1046
1047
  
  	/*
  	 * The pipe array wraps around, so just start the new one at zero
  	 * and adjust the indexes.
  	 */
  	if (pipe->nrbufs) {
1d862f412   Miklos Szeredi   pipe: fix pipe bu...
1048
1049
  		unsigned int tail;
  		unsigned int head;
35f3d14db   Jens Axboe   pipe: add support...
1050

1d862f412   Miklos Szeredi   pipe: fix pipe bu...
1051
1052
1053
1054
1055
1056
1057
  		tail = pipe->curbuf + pipe->nrbufs;
  		if (tail < pipe->buffers)
  			tail = 0;
  		else
  			tail &= (pipe->buffers - 1);
  
  		head = pipe->nrbufs - tail;
35f3d14db   Jens Axboe   pipe: add support...
1058
1059
1060
  		if (head)
  			memcpy(bufs, pipe->bufs + pipe->curbuf, head * sizeof(struct pipe_buffer));
  		if (tail)
1d862f412   Miklos Szeredi   pipe: fix pipe bu...
1061
  			memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
35f3d14db   Jens Axboe   pipe: add support...
1062
1063
1064
1065
1066
  	}
  
  	pipe->curbuf = 0;
  	kfree(pipe->bufs);
  	pipe->bufs = bufs;
b9598db34   Jens Axboe   pipe: make F_{GET...
1067
1068
  	pipe->buffers = nr_pages;
  	return nr_pages * PAGE_SIZE;
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
1069
1070
  
  out_revert_acct:
9c87bcf0a   Michael Kerrisk (man-pages)   pipe: make accoun...
1071
  	(void) account_pipe_buffers(pipe->user, nr_pages, pipe->buffers);
b0b91d18e   Michael Kerrisk (man-pages)   pipe: fix limit c...
1072
  	return ret;
35f3d14db   Jens Axboe   pipe: add support...
1073
  }
ff9da691c   Jens Axboe   pipe: change /pro...
1074
  /*
720836465   Linus Torvalds   Un-inline get_pip...
1075
1076
1077
1078
1079
1080
   * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
   * location, so checking ->i_pipe is not enough to verify that this is a
   * pipe.
   */
  struct pipe_inode_info *get_pipe_info(struct file *file)
  {
de32ec4cf   Al Viro   pipe: set file->p...
1081
  	return file->f_op == &pipefifo_fops ? file->private_data : NULL;
720836465   Linus Torvalds   Un-inline get_pip...
1082
  }
35f3d14db   Jens Axboe   pipe: add support...
1083
1084
1085
1086
  long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
  {
  	struct pipe_inode_info *pipe;
  	long ret;
c66fb3479   Linus Torvalds   Export 'get_pipe_...
1087
  	pipe = get_pipe_info(file);
35f3d14db   Jens Axboe   pipe: add support...
1088
1089
  	if (!pipe)
  		return -EBADF;
ebec73f47   Al Viro   introduce variant...
1090
  	__pipe_lock(pipe);
35f3d14db   Jens Axboe   pipe: add support...
1091
1092
  
  	switch (cmd) {
d37d41666   Michael Kerrisk (man-pages)   pipe: move limit ...
1093
1094
  	case F_SETPIPE_SZ:
  		ret = pipe_set_size(pipe, arg);
35f3d14db   Jens Axboe   pipe: add support...
1095
1096
  		break;
  	case F_GETPIPE_SZ:
b9598db34   Jens Axboe   pipe: make F_{GET...
1097
  		ret = pipe->buffers * PAGE_SIZE;
35f3d14db   Jens Axboe   pipe: add support...
1098
1099
1100
1101
1102
  		break;
  	default:
  		ret = -EINVAL;
  		break;
  	}
ebec73f47   Al Viro   introduce variant...
1103
  	__pipe_unlock(pipe);
35f3d14db   Jens Axboe   pipe: add support...
1104
1105
  	return ret;
  }
ff0c7d15f   Nick Piggin   fs: avoid inode R...
1106
1107
  static const struct super_operations pipefs_ops = {
  	.destroy_inode = free_inode_nonrcu,
d70ef97ba   Pavel Emelyanov   fs/pipe.c: add ->...
1108
  	.statfs = simple_statfs,
ff0c7d15f   Nick Piggin   fs: avoid inode R...
1109
  };
35f3d14db   Jens Axboe   pipe: add support...
1110
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
1114
1115
   * 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.
   */
4fa7ec5db   David Howells   vfs: Convert pipe...
1116
1117
  
  static int pipefs_init_fs_context(struct fs_context *fc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1118
  {
4fa7ec5db   David Howells   vfs: Convert pipe...
1119
1120
1121
1122
1123
1124
  	struct pseudo_fs_context *ctx = init_pseudo(fc, PIPEFS_MAGIC);
  	if (!ctx)
  		return -ENOMEM;
  	ctx->ops = &pipefs_ops;
  	ctx->dops = &pipefs_dentry_operations;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
1126
1127
1128
  }
  
  static struct file_system_type pipe_fs_type = {
  	.name		= "pipefs",
4fa7ec5db   David Howells   vfs: Convert pipe...
1129
  	.init_fs_context = pipefs_init_fs_context,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
1131
1132
1133
1134
1135
  	.kill_sb	= kill_anon_super,
  };
  
  static int __init init_pipe_fs(void)
  {
  	int err = register_filesystem(&pipe_fs_type);
341b446bc   Ingo Molnar   [PATCH] another r...
1136

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
1138
1139
1140
1141
1142
1143
1144
1145
  	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;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
  fs_initcall(init_pipe_fs);