Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5212c555 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block

* 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block:
  splice: __generic_file_splice_read: fix read/truncate race
  splice: __generic_file_splice_read: fix i_size_read() length checks
  splice: move balance_dirty_pages_ratelimited() outside of splice actor
  pipe: move pipe_inode_info structure decleration up before it's used
  splice: remove do_splice_direct() symbol export
  splice: move inode size check into generic_file_splice_read()
parents 845a2fdc 620a324b
Loading
Loading
Loading
Loading
+35 −35
Original line number Diff line number Diff line
@@ -272,7 +272,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
	struct page *page;
	pgoff_t index, end_index;
	loff_t isize;
	size_t total_len;
	int error, page_nr;
	struct splice_pipe_desc spd = {
		.pages = pages,
@@ -298,7 +297,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
	 * Now fill in the holes:
	 */
	error = 0;
	total_len = 0;

	/*
	 * Lookup the (hopefully) full range of pages we need.
@@ -415,9 +413,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,

				break;
			}

		}
fill_it:
		/*
			 * i_size must be checked after ->readpage().
		 * i_size must be checked after PageUptodate.
		 */
		isize = i_size_read(mapping->host);
		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
@@ -429,29 +428,32 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
		 * the length and stop
		 */
		if (end_index == index) {
				loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
				if (total_len + loff > isize)
			unsigned int plen;

			/*
			 * max good bytes in this page
			 */
			plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
			if (plen <= loff)
				break;

			/*
			 * force quit after adding this page
			 */
			this_len = min(this_len, plen - loff);
			len = this_len;
				this_len = min(this_len, loff);
				loff = 0;
			}
		}
fill_it:

		partial[page_nr].offset = loff;
		partial[page_nr].len = this_len;
		len -= this_len;
		total_len += this_len;
		loff = 0;
		spd.nr_pages++;
		index++;
	}

	/*
	 * Release any pages at the end, if we quit early. 'i' is how far
	 * Release any pages at the end, if we quit early. 'page_nr' is how far
	 * we got, 'nr_pages' is how many pages are in the map.
	 */
	while (page_nr < nr_pages)
@@ -478,10 +480,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
{
	ssize_t spliced;
	int ret;
	loff_t isize, left;

	isize = i_size_read(in->f_mapping->host);
	if (unlikely(*ppos >= isize))
		return 0;

	left = isize - *ppos;
	if (unlikely(left < len))
		len = left;

	ret = 0;
	spliced = 0;

	while (len) {
		ret = __generic_file_splice_read(in, ppos, pipe, len, flags);

@@ -644,7 +654,6 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
	 * accessed, we are now done!
	 */
	mark_page_accessed(page);
	balance_dirty_pages_ratelimited(mapping);
out:
	page_cache_release(page);
	unlock_page(page);
@@ -815,6 +824,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
			if (err)
				ret = err;
		}
		balance_dirty_pages_ratelimited(mapping);
	}

	return ret;
@@ -868,6 +878,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
			if (err)
				ret = err;
		}
		balance_dirty_pages_ratelimited(mapping);
	}

	return ret;
@@ -922,7 +933,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
			 struct pipe_inode_info *pipe, size_t len,
			 unsigned int flags)
{
	loff_t isize, left;
	int ret;

	if (unlikely(!in->f_op || !in->f_op->splice_read))
@@ -935,14 +945,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
	if (unlikely(ret < 0))
		return ret;

	isize = i_size_read(in->f_mapping->host);
	if (unlikely(*ppos >= isize))
		return 0;
	
	left = isize - *ppos;
	if (unlikely(left < len))
		len = left;

	return in->f_op->splice_read(in, ppos, pipe, len, flags);
}

@@ -1058,8 +1060,6 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
	return ret;
}

EXPORT_SYMBOL(do_splice_direct);

/*
 * 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
+15 −15
Original line number Diff line number Diff line
@@ -16,6 +16,21 @@ struct pipe_buffer {
	unsigned int flags;
};

struct pipe_inode_info {
	wait_queue_head_t wait;
	unsigned int nrbufs, curbuf;
	struct page *tmp_page;
	unsigned int readers;
	unsigned int writers;
	unsigned int waiting_writers;
	unsigned int r_counter;
	unsigned int w_counter;
	struct fasync_struct *fasync_readers;
	struct fasync_struct *fasync_writers;
	struct inode *inode;
	struct pipe_buffer bufs[PIPE_BUFFERS];
};

/*
 * Note on the nesting of these functions:
 *
@@ -38,21 +53,6 @@ struct pipe_buf_operations {
	void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};

struct pipe_inode_info {
	wait_queue_head_t wait;
	unsigned int nrbufs, curbuf;
	struct page *tmp_page;
	unsigned int readers;
	unsigned int writers;
	unsigned int waiting_writers;
	unsigned int r_counter;
	unsigned int w_counter;
	struct fasync_struct *fasync_readers;
	struct fasync_struct *fasync_writers;
	struct inode *inode;
	struct pipe_buffer bufs[PIPE_BUFFERS];
};

/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
   memory allocation, whereas PIPE_BUF makes atomicity guarantees.  */
#define PIPE_SIZE		PAGE_SIZE