summary refs log tree commit diff
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-16 15:39:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-16 15:39:21 -0400
commit3369d116934b70bd2755cdd8b2af9741d18a4047 (patch)
tree12c5444ae63bb9d6b00829b26668009d4c87a1c8 /fs
parentf1da3458e9d915d72b0dd30a7c41c3aff8f03589 (diff)
parent81b66220a9ebea7dd1547388279ee1898d7fe0f9 (diff)
downloadlinux-3369d116934b70bd2755cdd8b2af9741d18a4047.tar.gz
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French:
 "Two minor cifs fixes and a minor documentation cleanup for cifs.txt"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update cifs.txt and remove some outdated infos
  cifs: Avoid calling unlock_page() twice in cifs_readpage() when using fscache
  cifs: Do not take a reference to the page in cifs_readpage_worker()
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/file.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d044b35ce228..eb955b525e55 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3379,6 +3379,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 	return rc;
 }
 
+/*
+ * cifs_readpage_worker must be called with the page pinned
+ */
 static int cifs_readpage_worker(struct file *file, struct page *page,
 	loff_t *poffset)
 {
@@ -3390,7 +3393,6 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 	if (rc == 0)
 		goto read_complete;
 
-	page_cache_get(page);
 	read_data = kmap(page);
 	/* for reads over a certain size could initiate async read ahead */
 
@@ -3417,7 +3419,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 
 io_error:
 	kunmap(page);
-	page_cache_release(page);
+	unlock_page(page);
 
 read_complete:
 	return rc;
@@ -3442,8 +3444,6 @@ static int cifs_readpage(struct file *file, struct page *page)
 
 	rc = cifs_readpage_worker(file, page, &offset);
 
-	unlock_page(page);
-
 	free_xid(xid);
 	return rc;
 }
@@ -3497,6 +3497,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned flags,
 			struct page **pagep, void **fsdata)
 {
+	int oncethru = 0;
 	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
 	loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
 	loff_t page_start = pos & PAGE_MASK;
@@ -3506,6 +3507,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
 
 	cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len);
 
+start:
 	page = grab_cache_page_write_begin(mapping, index, flags);
 	if (!page) {
 		rc = -ENOMEM;
@@ -3547,13 +3549,16 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
 		}
 	}
 
-	if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+	if ((file->f_flags & O_ACCMODE) != O_WRONLY && !oncethru) {
 		/*
 		 * might as well read a page, it is fast enough. If we get
 		 * an error, we don't need to return it. cifs_write_end will
 		 * do a sync write instead since PG_uptodate isn't set.
 		 */
 		cifs_readpage_worker(file, page, &page_start);
+		page_cache_release(page);
+		oncethru = 1;
+		goto start;
 	} else {
 		/* we could try using another file handle if there is one -
 		   but how would we lock it to prevent close of that handle