aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2013-09-13 09:11:57 -0400
committerSteve French <smfrench@gmail.com>2013-09-13 17:24:49 -0400
commit466bd31bbda9e1dd2ace1d72c8de5045bf6f3bf6 (patch)
treea9f0d34082a17ed39a237dfb843441766c550a08
parenta9e9b7bc15a32ec5b0679704e70f3ffeecfaadd8 (diff)
cifs: Avoid calling unlock_page() twice in cifs_readpage() when using fscache
When reading a single page with cifs_readpage(), we make a call to fscache_read_or_alloc_page() which once done, asynchronously calls the completion function cifs_readpage_from_fscache_complete(). This completion function unlocks the page once it has been populated from cache. The module then attempts to unlock the page a second time in cifs_readpage() which leads to warning messages. In case of a successful call to fscache_read_or_alloc_page() we should skip the second unlock_page() since this will be called by the cifs_readpage_from_fscache_complete() once the page has been populated by fscache. With the modifications to cifs_readpage_worker(), we will need to re-grab the page lock in cifs_write_begin(). The problem was first noticed when testing new fscache patches for cifs. https://bugzilla.redhat.com/show_bug.cgi?id=1005737 Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/file.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5f99ee551662..eb955b525e55 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3419,6 +3419,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
3419 3419
3420io_error: 3420io_error:
3421 kunmap(page); 3421 kunmap(page);
3422 unlock_page(page);
3422 3423
3423read_complete: 3424read_complete:
3424 return rc; 3425 return rc;
@@ -3443,8 +3444,6 @@ static int cifs_readpage(struct file *file, struct page *page)
3443 3444
3444 rc = cifs_readpage_worker(file, page, &offset); 3445 rc = cifs_readpage_worker(file, page, &offset);
3445 3446
3446 unlock_page(page);
3447
3448 free_xid(xid); 3447 free_xid(xid);
3449 return rc; 3448 return rc;
3450} 3449}
@@ -3498,6 +3497,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
3498 loff_t pos, unsigned len, unsigned flags, 3497 loff_t pos, unsigned len, unsigned flags,
3499 struct page **pagep, void **fsdata) 3498 struct page **pagep, void **fsdata)
3500{ 3499{
3500 int oncethru = 0;
3501 pgoff_t index = pos >> PAGE_CACHE_SHIFT; 3501 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
3502 loff_t offset = pos & (PAGE_CACHE_SIZE - 1); 3502 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
3503 loff_t page_start = pos & PAGE_MASK; 3503 loff_t page_start = pos & PAGE_MASK;
@@ -3507,6 +3507,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
3507 3507
3508 cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len); 3508 cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len);
3509 3509
3510start:
3510 page = grab_cache_page_write_begin(mapping, index, flags); 3511 page = grab_cache_page_write_begin(mapping, index, flags);
3511 if (!page) { 3512 if (!page) {
3512 rc = -ENOMEM; 3513 rc = -ENOMEM;
@@ -3548,13 +3549,16 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
3548 } 3549 }
3549 } 3550 }
3550 3551
3551 if ((file->f_flags & O_ACCMODE) != O_WRONLY) { 3552 if ((file->f_flags & O_ACCMODE) != O_WRONLY && !oncethru) {
3552 /* 3553 /*
3553 * might as well read a page, it is fast enough. If we get 3554 * might as well read a page, it is fast enough. If we get
3554 * an error, we don't need to return it. cifs_write_end will 3555 * an error, we don't need to return it. cifs_write_end will
3555 * do a sync write instead since PG_uptodate isn't set. 3556 * do a sync write instead since PG_uptodate isn't set.
3556 */ 3557 */
3557 cifs_readpage_worker(file, page, &page_start); 3558 cifs_readpage_worker(file, page, &page_start);
3559 page_cache_release(page);
3560 oncethru = 1;
3561 goto start;
3558 } else { 3562 } else {
3559 /* we could try using another file handle if there is one - 3563 /* we could try using another file handle if there is one -
3560 but how would we lock it to prevent close of that handle 3564 but how would we lock it to prevent close of that handle