aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2008-09-24 11:32:59 -0400
committerSteve French <sfrench@us.ibm.com>2008-09-24 15:32:56 -0400
commitd9414774dc0c7b395036deeca000af42e2d13612 (patch)
tree4ddd38ff111978b597a802c111944ee2f9059449
parentd388908ec40ada0001dfe05134de31d0cc62907c (diff)
cifs: Convert cifs to new aops.
cifs: Convert cifs to new aops. This patch is based on the one originally posted by Nick Piggin. His patch was very close, but had a couple of small bugs. Nick's original comments follow: This is another relatively naive conversion. Always do the read upfront when the page is not uptodate (unless we're in the writethrough path). Fix an uninitialized data exposure where SetPageUptodate was called before the page was uptodate. SetPageUptodate and switch to writeback mode in the case that the full page was dirtied. Acked-by: Shaggy <shaggy@austin.ibm.com> Acked-by: Badari Pulavarty <pbadari@us.ibm.com> Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/file.c120
1 files changed, 59 insertions, 61 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d39e852a28a9..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;
@@ -1455,49 +1455,52 @@ static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1455 return rc; 1455 return rc;
1456} 1456}
1457 1457
1458static int cifs_commit_write(struct file *file, struct page *page, 1458static int cifs_write_end(struct file *file, struct address_space *mapping,
1459 unsigned offset, unsigned to) 1459 loff_t pos, unsigned len, unsigned copied,
1460 struct page *page, void *fsdata)
1460{ 1461{
1461 int xid; 1462 int rc;
1462 int rc = 0; 1463 struct inode *inode = mapping->host;
1463 struct inode *inode = page->mapping->host;
1464 loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1465 char *page_data;
1466 1464
1467 xid = GetXid(); 1465 cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
1468 cFYI(1, ("commit write for page %p up to position %lld for %d", 1466 page, pos, copied));
1469 page, position, to)); 1467
1470 spin_lock(&inode->i_lock); 1468 if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
1471 if (position > inode->i_size) 1469 SetPageUptodate(page);
1472 i_size_write(inode, position);
1473 1470
1474 spin_unlock(&inode->i_lock);
1475 if (!PageUptodate(page)) { 1471 if (!PageUptodate(page)) {
1476 position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; 1472 char *page_data;
1477 /* can not rely on (or let) writepage write this data */ 1473 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
1478 if (to < offset) { 1474 int xid;
1479 cFYI(1, ("Illegal offsets, can not copy from %d to %d", 1475
1480 offset, to)); 1476 xid = GetXid();
1481 FreeXid(xid);
1482 return rc;
1483 }
1484 /* this is probably better than directly calling 1477 /* this is probably better than directly calling
1485 partialpage_write since in this function the file handle is 1478 partialpage_write since in this function the file handle is
1486 known which we might as well leverage */ 1479 known which we might as well leverage */
1487 /* BB check if anything else missing out of ppw 1480 /* BB check if anything else missing out of ppw
1488 such as updating last write time */ 1481 such as updating last write time */
1489 page_data = kmap(page); 1482 page_data = kmap(page);
1490 rc = cifs_write(file, page_data + offset, to-offset, 1483 rc = cifs_write(file, page_data + offset, copied, &pos);
1491 &position); 1484 /* if (rc < 0) should we set writebehind rc? */
1492 if (rc > 0)
1493 rc = 0;
1494 /* else if (rc < 0) should we set writebehind rc? */
1495 kunmap(page); 1485 kunmap(page);
1486
1487 FreeXid(xid);
1496 } else { 1488 } else {
1489 rc = copied;
1490 pos += copied;
1497 set_page_dirty(page); 1491 set_page_dirty(page);
1498 } 1492 }
1499 1493
1500 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
1501 return rc; 1504 return rc;
1502} 1505}
1503 1506
@@ -2043,49 +2046,44 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
2043 return true; 2046 return true;
2044} 2047}
2045 2048
2046static int cifs_prepare_write(struct file *file, struct page *page, 2049static int cifs_write_begin(struct file *file, struct address_space *mapping,
2047 unsigned from, unsigned to) 2050 loff_t pos, unsigned len, unsigned flags,
2051 struct page **pagep, void **fsdata)
2048{ 2052{
2049 int rc = 0; 2053 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2050 loff_t i_size; 2054 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
2051 loff_t offset; 2055
2056 cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
2057
2058 *pagep = __grab_cache_page(mapping, index);
2059 if (!*pagep)
2060 return -ENOMEM;
2052 2061
2053 cFYI(1, ("prepare write for page %p from %d to %d", page, from, to)); 2062 if (PageUptodate(*pagep))
2054 if (PageUptodate(page))
2055 return 0; 2063 return 0;
2056 2064
2057 /* 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,
2058 no need to read from the server */ 2066 no need to read from the server */
2059 if ((to == PAGE_CACHE_SIZE) && (from == 0)) { 2067 if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
2060 SetPageUptodate(page);
2061 return 0; 2068 return 0;
2062 }
2063 2069
2064 offset = (loff_t)page->index << PAGE_CACHE_SHIFT; 2070 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2065 i_size = i_size_read(page->mapping->host); 2071 int rc;
2066 2072
2067 if ((offset >= i_size) ||
2068 ((from == 0) && (offset + to) >= i_size)) {
2069 /*
2070 * We don't need to read data beyond the end of the file.
2071 * zero it, and set the page uptodate
2072 */
2073 simple_prepare_write(file, page, from, to);
2074 SetPageUptodate(page);
2075 } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2076 /* might as well read a page, it is fast enough */ 2073 /* might as well read a page, it is fast enough */
2077 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 */
2078 } else { 2080 } else {
2079 /* we could try using another file handle if there is one - 2081 /* we could try using another file handle if there is one -
2080 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
2081 racing with this read? In any case 2083 racing with this read? In any case
2082 this will be written out by commit_write so is fine */ 2084 this will be written out by write_end so is fine */
2083 } 2085 }
2084 2086
2085 /* we do not need to pass errors back
2086 e.g. if we do not have read access to the file
2087 because cifs_commit_write will do the right thing. -- shaggy */
2088
2089 return 0; 2087 return 0;
2090} 2088}
2091 2089
@@ -2094,8 +2092,8 @@ const struct address_space_operations cifs_addr_ops = {
2094 .readpages = cifs_readpages, 2092 .readpages = cifs_readpages,
2095 .writepage = cifs_writepage, 2093 .writepage = cifs_writepage,
2096 .writepages = cifs_writepages, 2094 .writepages = cifs_writepages,
2097 .prepare_write = cifs_prepare_write, 2095 .write_begin = cifs_write_begin,
2098 .commit_write = cifs_commit_write, 2096 .write_end = cifs_write_end,
2099 .set_page_dirty = __set_page_dirty_nobuffers, 2097 .set_page_dirty = __set_page_dirty_nobuffers,
2100 /* .sync_page = cifs_sync_page, */ 2098 /* .sync_page = cifs_sync_page, */
2101 /* .direct_IO = */ 2099 /* .direct_IO = */
@@ -2110,8 +2108,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
2110 .readpage = cifs_readpage, 2108 .readpage = cifs_readpage,
2111 .writepage = cifs_writepage, 2109 .writepage = cifs_writepage,
2112 .writepages = cifs_writepages, 2110 .writepages = cifs_writepages,
2113 .prepare_write = cifs_prepare_write, 2111 .write_begin = cifs_write_begin,
2114 .commit_write = cifs_commit_write, 2112 .write_end = cifs_write_end,
2115 .set_page_dirty = __set_page_dirty_nobuffers, 2113 .set_page_dirty = __set_page_dirty_nobuffers,
2116 /* .sync_page = cifs_sync_page, */ 2114 /* .sync_page = cifs_sync_page, */
2117 /* .direct_IO = */ 2115 /* .direct_IO = */