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

Commit 7fd21be7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'btrfs-3.0' of git://github.com/chrismason/linux

* 'btrfs-3.0' of git://github.com/chrismason/linux:
  Btrfs: force a page fault if we have a shorty copy on a page boundary
parents 9b137769 b6316429
Loading
Loading
Loading
Loading
+16 −8
Original line number Original line Diff line number Diff line
@@ -1036,11 +1036,13 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
 * on error we return an unlocked page and the error value
 * on error we return an unlocked page and the error value
 * on success we return a locked page and 0
 * on success we return a locked page and 0
 */
 */
static int prepare_uptodate_page(struct page *page, u64 pos)
static int prepare_uptodate_page(struct page *page, u64 pos,
				 bool force_uptodate)
{
{
	int ret = 0;
	int ret = 0;


	if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) {
	if (((pos & (PAGE_CACHE_SIZE - 1)) || force_uptodate) &&
	    !PageUptodate(page)) {
		ret = btrfs_readpage(NULL, page);
		ret = btrfs_readpage(NULL, page);
		if (ret)
		if (ret)
			return ret;
			return ret;
@@ -1061,7 +1063,7 @@ static int prepare_uptodate_page(struct page *page, u64 pos)
static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
			 struct page **pages, size_t num_pages,
			 struct page **pages, size_t num_pages,
			 loff_t pos, unsigned long first_index,
			 loff_t pos, unsigned long first_index,
			 size_t write_bytes)
			 size_t write_bytes, bool force_uptodate)
{
{
	struct extent_state *cached_state = NULL;
	struct extent_state *cached_state = NULL;
	int i;
	int i;
@@ -1086,10 +1088,11 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
		}
		}


		if (i == 0)
		if (i == 0)
			err = prepare_uptodate_page(pages[i], pos);
			err = prepare_uptodate_page(pages[i], pos,
						    force_uptodate);
		if (i == num_pages - 1)
		if (i == num_pages - 1)
			err = prepare_uptodate_page(pages[i],
			err = prepare_uptodate_page(pages[i],
						    pos + write_bytes);
						    pos + write_bytes, false);
		if (err) {
		if (err) {
			page_cache_release(pages[i]);
			page_cache_release(pages[i]);
			faili = i - 1;
			faili = i - 1;
@@ -1158,6 +1161,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
	size_t num_written = 0;
	size_t num_written = 0;
	int nrptrs;
	int nrptrs;
	int ret = 0;
	int ret = 0;
	bool force_page_uptodate = false;


	nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) /
	nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) /
		     PAGE_CACHE_SIZE, PAGE_CACHE_SIZE /
		     PAGE_CACHE_SIZE, PAGE_CACHE_SIZE /
@@ -1200,7 +1204,8 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
		 * contents of pages from loop to loop
		 * contents of pages from loop to loop
		 */
		 */
		ret = prepare_pages(root, file, pages, num_pages,
		ret = prepare_pages(root, file, pages, num_pages,
				    pos, first_index, write_bytes);
				    pos, first_index, write_bytes,
				    force_page_uptodate);
		if (ret) {
		if (ret) {
			btrfs_delalloc_release_space(inode,
			btrfs_delalloc_release_space(inode,
					num_pages << PAGE_CACHE_SHIFT);
					num_pages << PAGE_CACHE_SHIFT);
@@ -1217,12 +1222,15 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
		if (copied < write_bytes)
		if (copied < write_bytes)
			nrptrs = 1;
			nrptrs = 1;


		if (copied == 0)
		if (copied == 0) {
			force_page_uptodate = true;
			dirty_pages = 0;
			dirty_pages = 0;
		else
		} else {
			force_page_uptodate = false;
			dirty_pages = (copied + offset +
			dirty_pages = (copied + offset +
				       PAGE_CACHE_SIZE - 1) >>
				       PAGE_CACHE_SIZE - 1) >>
				       PAGE_CACHE_SHIFT;
				       PAGE_CACHE_SHIFT;
		}


		/*
		/*
		 * If we had a short copy we need to release the excess delaloc
		 * If we had a short copy we need to release the excess delaloc