diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 105 |
1 files changed, 63 insertions, 42 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index a1265c9bfec0..2d3275bedb55 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -879,18 +879,19 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
879 | cifs_stats_bytes_written(pTcon, total_written); | 879 | cifs_stats_bytes_written(pTcon, total_written); |
880 | 880 | ||
881 | /* since the write may have blocked check these pointers again */ | 881 | /* since the write may have blocked check these pointers again */ |
882 | if (file->f_path.dentry) { | 882 | if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { |
883 | if (file->f_path.dentry->d_inode) { | 883 | struct inode *inode = file->f_path.dentry->d_inode; |
884 | struct inode *inode = file->f_path.dentry->d_inode; | 884 | /* Do not update local mtime - server will set its actual value on write |
885 | inode->i_ctime = inode->i_mtime = | 885 | * inode->i_ctime = inode->i_mtime = |
886 | current_fs_time(inode->i_sb); | 886 | * current_fs_time(inode->i_sb);*/ |
887 | if (total_written > 0) { | 887 | if (total_written > 0) { |
888 | if (*poffset > file->f_path.dentry->d_inode->i_size) | 888 | spin_lock(&inode->i_lock); |
889 | i_size_write(file->f_path.dentry->d_inode, | 889 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
890 | i_size_write(file->f_path.dentry->d_inode, | ||
890 | *poffset); | 891 | *poffset); |
891 | } | 892 | spin_unlock(&inode->i_lock); |
892 | mark_inode_dirty_sync(file->f_path.dentry->d_inode); | ||
893 | } | 893 | } |
894 | mark_inode_dirty_sync(file->f_path.dentry->d_inode); | ||
894 | } | 895 | } |
895 | FreeXid(xid); | 896 | FreeXid(xid); |
896 | return total_written; | 897 | return total_written; |
@@ -1012,18 +1013,18 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1012 | cifs_stats_bytes_written(pTcon, total_written); | 1013 | cifs_stats_bytes_written(pTcon, total_written); |
1013 | 1014 | ||
1014 | /* since the write may have blocked check these pointers again */ | 1015 | /* since the write may have blocked check these pointers again */ |
1015 | if (file->f_path.dentry) { | 1016 | if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { |
1016 | if (file->f_path.dentry->d_inode) { | ||
1017 | /*BB We could make this contingent on superblock ATIME flag too */ | 1017 | /*BB We could make this contingent on superblock ATIME flag too */ |
1018 | /* file->f_path.dentry->d_inode->i_ctime = | 1018 | /* file->f_path.dentry->d_inode->i_ctime = |
1019 | file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/ | 1019 | file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/ |
1020 | if (total_written > 0) { | 1020 | if (total_written > 0) { |
1021 | if (*poffset > file->f_path.dentry->d_inode->i_size) | 1021 | spin_lock(&file->f_path.dentry->d_inode->i_lock); |
1022 | i_size_write(file->f_path.dentry->d_inode, | 1022 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
1023 | *poffset); | 1023 | i_size_write(file->f_path.dentry->d_inode, |
1024 | } | 1024 | *poffset); |
1025 | mark_inode_dirty_sync(file->f_path.dentry->d_inode); | 1025 | spin_unlock(&file->f_path.dentry->d_inode->i_lock); |
1026 | } | 1026 | } |
1027 | mark_inode_dirty_sync(file->f_path.dentry->d_inode); | ||
1027 | } | 1028 | } |
1028 | FreeXid(xid); | 1029 | FreeXid(xid); |
1029 | return total_written; | 1030 | return total_written; |
@@ -1400,6 +1401,7 @@ static int cifs_commit_write(struct file *file, struct page *page, | |||
1400 | xid = GetXid(); | 1401 | xid = GetXid(); |
1401 | cFYI(1, ("commit write for page %p up to position %lld for %d", | 1402 | cFYI(1, ("commit write for page %p up to position %lld for %d", |
1402 | page, position, to)); | 1403 | page, position, to)); |
1404 | spin_lock(&inode->i_lock); | ||
1403 | if (position > inode->i_size) { | 1405 | if (position > inode->i_size) { |
1404 | i_size_write(inode, position); | 1406 | i_size_write(inode, position); |
1405 | /* if (file->private_data == NULL) { | 1407 | /* if (file->private_data == NULL) { |
@@ -1429,6 +1431,7 @@ static int cifs_commit_write(struct file *file, struct page *page, | |||
1429 | cFYI(1, (" SetEOF (commit write) rc = %d", rc)); | 1431 | cFYI(1, (" SetEOF (commit write) rc = %d", rc)); |
1430 | } */ | 1432 | } */ |
1431 | } | 1433 | } |
1434 | spin_unlock(&inode->i_lock); | ||
1432 | if (!PageUptodate(page)) { | 1435 | if (!PageUptodate(page)) { |
1433 | position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; | 1436 | position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; |
1434 | /* can not rely on (or let) writepage write this data */ | 1437 | /* can not rely on (or let) writepage write this data */ |
@@ -1989,34 +1992,52 @@ static int cifs_prepare_write(struct file *file, struct page *page, | |||
1989 | unsigned from, unsigned to) | 1992 | unsigned from, unsigned to) |
1990 | { | 1993 | { |
1991 | int rc = 0; | 1994 | int rc = 0; |
1992 | loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; | 1995 | loff_t i_size; |
1996 | loff_t offset; | ||
1997 | |||
1993 | 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)); |
1994 | if (!PageUptodate(page)) { | 1999 | if (PageUptodate(page)) |
1995 | /* if (to - from != PAGE_CACHE_SIZE) { | 2000 | return 0; |
1996 | 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) | ||
1997 | memset(kaddr, 0, from); | 2021 | memset(kaddr, 0, from); |
2022 | if (to < PAGE_CACHE_SIZE) | ||
1998 | memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); | 2023 | memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); |
1999 | flush_dcache_page(page); | 2024 | flush_dcache_page(page); |
2000 | kunmap_atomic(kaddr, KM_USER0); | 2025 | kunmap_atomic(kaddr, KM_USER0); |
2001 | } */ | 2026 | SetPageUptodate(page); |
2002 | /* If we are writing a full page it will be up to date, | 2027 | } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) { |
2003 | no need to read from the server */ | ||
2004 | if ((to == PAGE_CACHE_SIZE) && (from == 0)) | ||
2005 | SetPageUptodate(page); | ||
2006 | |||
2007 | /* might as well read a page, it is fast enough */ | 2028 | /* might as well read a page, it is fast enough */ |
2008 | if ((file->f_flags & O_ACCMODE) != O_WRONLY) { | 2029 | rc = cifs_readpage_worker(file, page, &offset); |
2009 | rc = cifs_readpage_worker(file, page, &offset); | 2030 | } else { |
2010 | } else { | 2031 | /* we could try using another file handle if there is one - |
2011 | /* should we try using another file handle if there is one - | 2032 | but how would we lock it to prevent close of that handle |
2012 | how would we lock it to prevent close of that handle | 2033 | racing with this read? In any case |
2013 | racing with this read? | 2034 | this will be written out by commit_write so is fine */ |
2014 | In any case this will be written out by commit_write */ | ||
2015 | } | ||
2016 | } | 2035 | } |
2017 | 2036 | ||
2018 | /* BB should we pass any errors back? | 2037 | /* we do not need to pass errors back |
2019 | 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 | |||
2020 | return 0; | 2041 | return 0; |
2021 | } | 2042 | } |
2022 | 2043 | ||