diff options
author | Steve French <sfrench@us.ibm.com> | 2007-03-05 19:31:00 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2007-03-05 19:31:00 -0500 |
commit | 8a236264f7d6db3f52881d37a86c5a5f704072b0 (patch) | |
tree | 2caf0cb67d6986b8e3544405b89135f24c05c137 /fs/cifs/file.c | |
parent | c7af1857ef74873bf5a9c8fcab0cfd79883492ac (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.c | 62 |
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 | ||