aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2007-03-05 19:31:00 -0500
committerSteve French <sfrench@us.ibm.com>2007-03-05 19:31:00 -0500
commit8a236264f7d6db3f52881d37a86c5a5f704072b0 (patch)
tree2caf0cb67d6986b8e3544405b89135f24c05c137 /fs/cifs/file.c
parentc7af1857ef74873bf5a9c8fcab0cfd79883492ac (diff)
[CIFS] cifs_prepare_write was incorrectly rereading page in some cases
Noticed by Shaggy. Signed-off-by: Shaggy <shaggy@us.ibm.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c62
1 files changed, 40 insertions, 22 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index c07ff8317a8b..2d3275bedb55 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1992,34 +1992,52 @@ static int cifs_prepare_write(struct file *file, struct page *page,
1992 unsigned from, unsigned to) 1992 unsigned from, unsigned to)
1993{ 1993{
1994 int rc = 0; 1994 int rc = 0;
1995 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; 1995 loff_t i_size;
1996 loff_t offset;
1997
1996 cFYI(1, ("prepare write for page %p from %d to %d",page,from,to)); 1998 cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1997 if (!PageUptodate(page)) { 1999 if (PageUptodate(page))
1998 /* if (to - from != PAGE_CACHE_SIZE) { 2000 return 0;
1999 void *kaddr = kmap_atomic(page, KM_USER0); 2001
2002 /* If we are writing a full page it will be up to date,
2003 no need to read from the server */
2004 if ((to == PAGE_CACHE_SIZE) && (from == 0)) {
2005 SetPageUptodate(page);
2006 return 0;
2007 }
2008
2009 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2010 i_size = i_size_read(page->mapping->host);
2011
2012 if ((offset >= i_size) ||
2013 ((from == 0) && (offset + to) >= i_size)) {
2014 /*
2015 * We don't need to read data beyond the end of the file.
2016 * zero it, and set the page uptodate
2017 */
2018 void *kaddr = kmap_atomic(page, KM_USER0);
2019
2020 if (from)
2000 memset(kaddr, 0, from); 2021 memset(kaddr, 0, from);
2022 if (to < PAGE_CACHE_SIZE)
2001 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); 2023 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
2002 flush_dcache_page(page); 2024 flush_dcache_page(page);
2003 kunmap_atomic(kaddr, KM_USER0); 2025 kunmap_atomic(kaddr, KM_USER0);
2004 } */ 2026 SetPageUptodate(page);
2005 /* If we are writing a full page it will be up to date, 2027 } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2006 no need to read from the server */
2007 if ((to == PAGE_CACHE_SIZE) && (from == 0))
2008 SetPageUptodate(page);
2009
2010 /* might as well read a page, it is fast enough */ 2028 /* might as well read a page, it is fast enough */
2011 if ((file->f_flags & O_ACCMODE) != O_WRONLY) { 2029 rc = cifs_readpage_worker(file, page, &offset);
2012 rc = cifs_readpage_worker(file, page, &offset); 2030 } else {
2013 } else { 2031 /* we could try using another file handle if there is one -
2014 /* should we try using another file handle if there is one - 2032 but how would we lock it to prevent close of that handle
2015 how would we lock it to prevent close of that handle 2033 racing with this read? In any case
2016 racing with this read? 2034 this will be written out by commit_write so is fine */
2017 In any case this will be written out by commit_write */
2018 }
2019 } 2035 }
2020 2036
2021 /* BB should we pass any errors back? 2037 /* we do not need to pass errors back
2022 e.g. if we do not have read access to the file */ 2038 e.g. if we do not have read access to the file
2039 because cifs_commit_write will do the right thing. -- shaggy */
2040
2023 return 0; 2041 return 0;
2024} 2042}
2025 2043