diff options
| author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2012-05-21 21:39:42 +0200 | 
|---|---|---|
| committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2012-05-21 21:39:42 +0200 | 
| commit | 0ad8c6a22d03a1598f7cc6585c65354dadca62ad (patch) | |
| tree | 1507deef3d55d5f3c71b2f76924fe1f6c6211905 /fs/pipe.c | |
| parent | 8527f8e2934683e53405fbe876a4e6f4a0c46eb8 (diff) | |
| parent | 76e10d158efb6d4516018846f60c2ab5501900bc (diff) | |
Merge tag 'v3.4' with SCSI updates, needed for subsequent firewire-sbp2 changes
Linux 3.4
Diffstat (limited to 'fs/pipe.c')
| -rw-r--r-- | fs/pipe.c | 31 | 
1 files changed, 29 insertions, 2 deletions
diff --git a/fs/pipe.c b/fs/pipe.c index 25feaa3faac0..fec5e4ad071a 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -346,6 +346,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {  	.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_t  pipe_read(struct kiocb *iocb, const struct iovec *_iov,  	   unsigned long nr_segs, loff_t pos) @@ -407,6 +417,13 @@ redo:  			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); @@ -459,6 +476,11 @@ redo:  	return ret;  } +static inline int is_packetized(struct file *file) +{ +	return (file->f_flags & O_DIRECT) != 0; +} +  static ssize_t  pipe_write(struct kiocb *iocb, const struct iovec *_iov,  	    unsigned long nr_segs, loff_t ppos) @@ -593,6 +615,11 @@ redo2:  			buf->ops = &anon_pipe_buf_ops;  			buf->offset = 0;  			buf->len = chars; +			buf->flags = 0; +			if (is_packetized(filp)) { +				buf->ops = &packet_pipe_buf_ops; +				buf->flags = PIPE_BUF_FLAG_PACKET; +			}  			pipe->nrbufs = ++bufs;  			pipe->tmp_page = NULL; @@ -1013,7 +1040,7 @@ struct file *create_write_pipe(int flags)  		goto err_dentry;  	f->f_mapping = inode->i_mapping; -	f->f_flags = O_WRONLY | (flags & O_NONBLOCK); +	f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));  	f->f_version = 0;  	return f; @@ -1057,7 +1084,7 @@ int do_pipe_flags(int *fd, int flags)  	int error;  	int fdw, fdr; -	if (flags & ~(O_CLOEXEC | O_NONBLOCK)) +	if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT))  		return -EINVAL;  	fw = create_write_pipe(flags);  | 
