aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c130
1 files changed, 68 insertions, 62 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index cbefe1f1f9fe..c4a8a0605125 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -107,7 +107,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
107 107
108 /* want handles we can use to read with first 108 /* want handles we can use to read with first
109 in the list so we do not have to walk the 109 in the list so we do not have to walk the
110 list to search for one in prepare_write */ 110 list to search for one in write_begin */
111 if ((file->f_flags & O_ACCMODE) == O_WRONLY) { 111 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
112 list_add_tail(&pCifsFile->flist, 112 list_add_tail(&pCifsFile->flist,
113 &pCifsInode->openFileList); 113 &pCifsInode->openFileList);
@@ -915,7 +915,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
915} 915}
916 916
917static ssize_t cifs_write(struct file *file, const char *write_data, 917static ssize_t cifs_write(struct file *file, const char *write_data,
918 size_t write_size, loff_t *poffset) 918 size_t write_size, loff_t *poffset)
919{ 919{
920 int rc = 0; 920 int rc = 0;
921 unsigned int bytes_written = 0; 921 unsigned int bytes_written = 0;
@@ -1065,6 +1065,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
1065struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) 1065struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
1066{ 1066{
1067 struct cifsFileInfo *open_file; 1067 struct cifsFileInfo *open_file;
1068 bool any_available = false;
1068 int rc; 1069 int rc;
1069 1070
1070 /* Having a null inode here (because mapping->host was set to zero by 1071 /* Having a null inode here (because mapping->host was set to zero by
@@ -1080,8 +1081,10 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
1080 read_lock(&GlobalSMBSeslock); 1081 read_lock(&GlobalSMBSeslock);
1081refind_writable: 1082refind_writable:
1082 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1083 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1083 if (open_file->closePend) 1084 if (open_file->closePend ||
1085 (!any_available && open_file->pid != current->tgid))
1084 continue; 1086 continue;
1087
1085 if (open_file->pfile && 1088 if (open_file->pfile &&
1086 ((open_file->pfile->f_flags & O_RDWR) || 1089 ((open_file->pfile->f_flags & O_RDWR) ||
1087 (open_file->pfile->f_flags & O_WRONLY))) { 1090 (open_file->pfile->f_flags & O_WRONLY))) {
@@ -1131,6 +1134,11 @@ refind_writable:
1131 of the loop here. */ 1134 of the loop here. */
1132 } 1135 }
1133 } 1136 }
1137 /* couldn't find useable FH with same pid, try any available */
1138 if (!any_available) {
1139 any_available = true;
1140 goto refind_writable;
1141 }
1134 read_unlock(&GlobalSMBSeslock); 1142 read_unlock(&GlobalSMBSeslock);
1135 return NULL; 1143 return NULL;
1136} 1144}
@@ -1447,49 +1455,52 @@ static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1447 return rc; 1455 return rc;
1448} 1456}
1449 1457
1450static int cifs_commit_write(struct file *file, struct page *page, 1458static int cifs_write_end(struct file *file, struct address_space *mapping,
1451 unsigned offset, unsigned to) 1459 loff_t pos, unsigned len, unsigned copied,
1460 struct page *page, void *fsdata)
1452{ 1461{
1453 int xid; 1462 int rc;
1454 int rc = 0; 1463 struct inode *inode = mapping->host;
1455 struct inode *inode = page->mapping->host;
1456 loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1457 char *page_data;
1458 1464
1459 xid = GetXid(); 1465 cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
1460 cFYI(1, ("commit write for page %p up to position %lld for %d", 1466 page, pos, copied));
1461 page, position, to)); 1467
1462 spin_lock(&inode->i_lock); 1468 if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
1463 if (position > inode->i_size) 1469 SetPageUptodate(page);
1464 i_size_write(inode, position);
1465 1470
1466 spin_unlock(&inode->i_lock);
1467 if (!PageUptodate(page)) { 1471 if (!PageUptodate(page)) {
1468 position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; 1472 char *page_data;
1469 /* can not rely on (or let) writepage write this data */ 1473 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
1470 if (to < offset) { 1474 int xid;
1471 cFYI(1, ("Illegal offsets, can not copy from %d to %d", 1475
1472 offset, to)); 1476 xid = GetXid();
1473 FreeXid(xid);
1474 return rc;
1475 }
1476 /* this is probably better than directly calling 1477 /* this is probably better than directly calling
1477 partialpage_write since in this function the file handle is 1478 partialpage_write since in this function the file handle is
1478 known which we might as well leverage */ 1479 known which we might as well leverage */
1479 /* BB check if anything else missing out of ppw 1480 /* BB check if anything else missing out of ppw
1480 such as updating last write time */ 1481 such as updating last write time */
1481 page_data = kmap(page); 1482 page_data = kmap(page);
1482 rc = cifs_write(file, page_data + offset, to-offset, 1483 rc = cifs_write(file, page_data + offset, copied, &pos);
1483 &position); 1484 /* if (rc < 0) should we set writebehind rc? */
1484 if (rc > 0)
1485 rc = 0;
1486 /* else if (rc < 0) should we set writebehind rc? */
1487 kunmap(page); 1485 kunmap(page);
1486
1487 FreeXid(xid);
1488 } else { 1488 } else {
1489 rc = copied;
1490 pos += copied;
1489 set_page_dirty(page); 1491 set_page_dirty(page);
1490 } 1492 }
1491 1493
1492 FreeXid(xid); 1494 if (rc > 0) {
1495 spin_lock(&inode->i_lock);
1496 if (pos > inode->i_size)
1497 i_size_write(inode, pos);
1498 spin_unlock(&inode->i_lock);
1499 }
1500
1501 unlock_page(page);
1502 page_cache_release(page);
1503
1493 return rc; 1504 return rc;
1494} 1505}
1495 1506
@@ -2035,49 +2046,44 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
2035 return true; 2046 return true;
2036} 2047}
2037 2048
2038static int cifs_prepare_write(struct file *file, struct page *page, 2049static int cifs_write_begin(struct file *file, struct address_space *mapping,
2039 unsigned from, unsigned to) 2050 loff_t pos, unsigned len, unsigned flags,
2051 struct page **pagep, void **fsdata)
2040{ 2052{
2041 int rc = 0; 2053 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2042 loff_t i_size; 2054 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
2043 loff_t offset;
2044 2055
2045 cFYI(1, ("prepare write for page %p from %d to %d", page, from, to)); 2056 cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
2046 if (PageUptodate(page)) 2057
2058 *pagep = __grab_cache_page(mapping, index);
2059 if (!*pagep)
2060 return -ENOMEM;
2061
2062 if (PageUptodate(*pagep))
2047 return 0; 2063 return 0;
2048 2064
2049 /* If we are writing a full page it will be up to date, 2065 /* If we are writing a full page it will be up to date,
2050 no need to read from the server */ 2066 no need to read from the server */
2051 if ((to == PAGE_CACHE_SIZE) && (from == 0)) { 2067 if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
2052 SetPageUptodate(page);
2053 return 0; 2068 return 0;
2054 }
2055 2069
2056 offset = (loff_t)page->index << PAGE_CACHE_SHIFT; 2070 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2057 i_size = i_size_read(page->mapping->host); 2071 int rc;
2058 2072
2059 if ((offset >= i_size) ||
2060 ((from == 0) && (offset + to) >= i_size)) {
2061 /*
2062 * We don't need to read data beyond the end of the file.
2063 * zero it, and set the page uptodate
2064 */
2065 simple_prepare_write(file, page, from, to);
2066 SetPageUptodate(page);
2067 } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2068 /* might as well read a page, it is fast enough */ 2073 /* might as well read a page, it is fast enough */
2069 rc = cifs_readpage_worker(file, page, &offset); 2074 rc = cifs_readpage_worker(file, *pagep, &offset);
2075
2076 /* we do not need to pass errors back
2077 e.g. if we do not have read access to the file
2078 because cifs_write_end will attempt synchronous writes
2079 -- shaggy */
2070 } else { 2080 } else {
2071 /* we could try using another file handle if there is one - 2081 /* we could try using another file handle if there is one -
2072 but how would we lock it to prevent close of that handle 2082 but how would we lock it to prevent close of that handle
2073 racing with this read? In any case 2083 racing with this read? In any case
2074 this will be written out by commit_write so is fine */ 2084 this will be written out by write_end so is fine */
2075 } 2085 }
2076 2086
2077 /* we do not need to pass errors back
2078 e.g. if we do not have read access to the file
2079 because cifs_commit_write will do the right thing. -- shaggy */
2080
2081 return 0; 2087 return 0;
2082} 2088}
2083 2089
@@ -2086,8 +2092,8 @@ const struct address_space_operations cifs_addr_ops = {
2086 .readpages = cifs_readpages, 2092 .readpages = cifs_readpages,
2087 .writepage = cifs_writepage, 2093 .writepage = cifs_writepage,
2088 .writepages = cifs_writepages, 2094 .writepages = cifs_writepages,
2089 .prepare_write = cifs_prepare_write, 2095 .write_begin = cifs_write_begin,
2090 .commit_write = cifs_commit_write, 2096 .write_end = cifs_write_end,
2091 .set_page_dirty = __set_page_dirty_nobuffers, 2097 .set_page_dirty = __set_page_dirty_nobuffers,
2092 /* .sync_page = cifs_sync_page, */ 2098 /* .sync_page = cifs_sync_page, */
2093 /* .direct_IO = */ 2099 /* .direct_IO = */
@@ -2102,8 +2108,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
2102 .readpage = cifs_readpage, 2108 .readpage = cifs_readpage,
2103 .writepage = cifs_writepage, 2109 .writepage = cifs_writepage,
2104 .writepages = cifs_writepages, 2110 .writepages = cifs_writepages,
2105 .prepare_write = cifs_prepare_write, 2111 .write_begin = cifs_write_begin,
2106 .commit_write = cifs_commit_write, 2112 .write_end = cifs_write_end,
2107 .set_page_dirty = __set_page_dirty_nobuffers, 2113 .set_page_dirty = __set_page_dirty_nobuffers,
2108 /* .sync_page = cifs_sync_page, */ 2114 /* .sync_page = cifs_sync_page, */
2109 /* .direct_IO = */ 2115 /* .direct_IO = */