1325 lines · 29.2 KB · C
RawDownload
/* *  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/log2.h>#include <linux/mount.h>#include <linux/magic.h>#include <linux/pipe_fs_i.h>#include <linux/uio.h>#include <linux/highmem.h>#include <linux/pagemap.h>#include <linux/audit.h>#include <linux/syscalls.h>#include <linux/fcntl.h>#include <linux/aio.h> #include <asm/uaccess.h>#include <asm/ioctls.h> #include "internal.h" /* * The max size that a non-root user is allowed to grow the pipe. Can * be set by root in /proc/sys/fs/pipe-max-size */unsigned int pipe_max_size = 1048576; /* * Minimum pipe size, as required by POSIX */unsigned int pipe_min_size = PAGE_SIZE; /* * 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 */ static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass){	if (pipe->files)		mutex_lock_nested(&pipe->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->files)		mutex_unlock(&pipe->mutex);}EXPORT_SYMBOL(pipe_unlock); 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);} 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_PARENT);		pipe_lock_nested(pipe1, I_MUTEX_CHILD);	}} /* Drop the inode semaphore and wait for a pipe event, atomically */void pipe_wait(struct pipe_inode_info *pipe){	DEFINE_WAIT(wait); 	/*	 * Pipes are system-local resources, so sleeping on them	 * is considered a noninteractive wait:	 */	prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE);	pipe_unlock(pipe);	schedule();	finish_wait(&pipe->wait, &wait);	pipe_lock(pipe);} static intpipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len,			int atomic){	unsigned long copy; 	while (len > 0) {		while (!iov->iov_len)			iov++;		copy = min_t(unsigned long, len, iov->iov_len); 		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;		}		to += copy;		len -= copy;		iov->iov_base += copy;		iov->iov_len -= copy;	}	return 0;} static intpipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len,		      int atomic){	unsigned long copy; 	while (len > 0) {		while (!iov->iov_len)			iov++;		copy = min_t(unsigned long, len, iov->iov_len); 		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;		}		from += copy;		len -= copy;		iov->iov_base += copy;		iov->iov_len -= copy;	}	return 0;} /* * 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++;	}} static void anon_pipe_buf_release(struct pipe_inode_info *pipe,				  struct pipe_buffer *buf){	struct page *page = buf->page; 	/*	 * 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	 * allocation cache. (Otherwise just release our reference to it)	 */	if (page_count(page) == 1 && !pipe->tmp_page)		pipe->tmp_page = page;	else		page_cache_release(page);} /** * 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 *	pipe_buffer passed in @buf. If @atomic is set, an atomic map is provided *	and the caller has to be careful not to fault before calling *	the unmap function. * *	Note that this function calls kmap_atomic() if @atomic != 0. */void *generic_pipe_buf_map(struct pipe_inode_info *pipe,			   struct pipe_buffer *buf, int atomic){	if (atomic) {		buf->flags |= PIPE_BUF_FLAG_ATOMIC;		return kmap_atomic(buf->page);	} 	return kmap(buf->page);}EXPORT_SYMBOL(generic_pipe_buf_map); /** * 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. */void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,			    struct pipe_buffer *buf, void *map_data){	if (buf->flags & PIPE_BUF_FLAG_ATOMIC) {		buf->flags &= ~PIPE_BUF_FLAG_ATOMIC;		kunmap_atomic(map_data);	} else		kunmap(buf->page);}EXPORT_SYMBOL(generic_pipe_buf_unmap); /** * generic_pipe_buf_steal - attempt to take ownership of a &pipe_buffer * @pipe:	the pipe that the buffer belongs to * @buf:	the buffer to attempt to steal * * Description: *	This function attempts to steal the &struct page attached to *	@buf. If successful, this function returns 0 and returns with *	the page locked. The caller may then reuse the page for whatever *	he wishes; the typical use is insertion into a different file *	page cache. */int generic_pipe_buf_steal(struct pipe_inode_info *pipe,			   struct pipe_buffer *buf){	struct page *page = buf->page; 	/*	 * 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.	 */	if (page_count(page) == 1) {		lock_page(page);		return 0;	} 	return 1;}EXPORT_SYMBOL(generic_pipe_buf_steal); /** * generic_pipe_buf_get - get a reference to a &struct pipe_buffer * @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){	page_cache_get(buf->page);}EXPORT_SYMBOL(generic_pipe_buf_get); /** * generic_pipe_buf_confirm - verify contents of the pipe buffer * @info:	the pipe that the buffer belongs to * @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. */int generic_pipe_buf_confirm(struct pipe_inode_info *info,			     struct pipe_buffer *buf){	return 0;}EXPORT_SYMBOL(generic_pipe_buf_confirm); /** * 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){	page_cache_release(buf->page);}EXPORT_SYMBOL(generic_pipe_buf_release); static const struct pipe_buf_operations anon_pipe_buf_ops = {	.can_merge = 1,	.map = generic_pipe_buf_map,	.unmap = generic_pipe_buf_unmap,	.confirm = generic_pipe_buf_confirm,	.release = anon_pipe_buf_release,	.steal = generic_pipe_buf_steal,	.get = generic_pipe_buf_get,}; static const struct pipe_buf_operations packet_pipe_buf_ops = {	.can_merge = 0,	.map = generic_pipe_buf_map,	.unmap = generic_pipe_buf_unmap,	.confirm = generic_pipe_buf_confirm,	.release = anon_pipe_buf_release,	.steal = generic_pipe_buf_steal,	.get = generic_pipe_buf_get,}; static ssize_tpipe_read(struct kiocb *iocb, const struct iovec *_iov,	   unsigned long nr_segs, loff_t pos){	struct file *filp = iocb->ki_filp;	struct pipe_inode_info *pipe = filp->private_data;	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;	__pipe_lock(pipe);	for (;;) {		int bufs = pipe->nrbufs;		if (bufs) {			int curbuf = pipe->curbuf;			struct pipe_buffer *buf = pipe->bufs + curbuf;			const struct pipe_buf_operations *ops = buf->ops;			void *addr;			size_t chars = buf->len;			int error, atomic; 			if (chars > total_len)				chars = total_len; 			error = ops->confirm(pipe, buf);			if (error) {				if (!ret)					ret = error;				break;			} 			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);			if (unlikely(error)) {				/*				 * Just retry with the slow path if we failed.				 */				if (atomic) {					atomic = 0;					goto redo;				}				if (!ret)					ret = error;				break;			}			ret += chars;			buf->offset += chars;			buf->len -= chars; 			/* Was it a packet buffer? Clean up and exit */			if (buf->flags & PIPE_BUF_FLAG_PACKET) {				total_len = chars;				buf->len = 0;			} 			if (!buf->len) {				buf->ops = NULL;				ops->release(pipe, buf);				curbuf = (curbuf + 1) & (pipe->buffers - 1);				pipe->curbuf = curbuf;				pipe->nrbufs = --bufs;				do_wakeup = 1;			}			total_len -= chars;			if (!total_len)				break;	/* common path: read succeeded */		}		if (bufs)	/* More to do? */			continue;		if (!pipe->writers)			break;		if (!pipe->waiting_writers) {			/* 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)) {			if (!ret)				ret = -ERESTARTSYS;			break;		}		if (do_wakeup) {			wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT | POLLWRNORM); 			kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);		}		pipe_wait(pipe);	}	__pipe_unlock(pipe); 	/* Signal writers asynchronously that there is more room. */	if (do_wakeup) {		wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT | POLLWRNORM);		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);	}	if (ret > 0)		file_accessed(filp);	return ret;} static inline int is_packetized(struct file *file){	return (file->f_flags & O_DIRECT) != 0;} static ssize_tpipe_write(struct kiocb *iocb, const struct iovec *_iov,	    unsigned long nr_segs, loff_t ppos){	struct file *filp = iocb->ki_filp;	struct pipe_inode_info *pipe = filp->private_data;

Lines 1–500 of 1325.