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.c98
1 files changed, 70 insertions, 28 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 6449e1aae621..f0a81e631ae6 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -488,12 +488,13 @@ int cifs_close(struct inode *inode, struct file *file)
488 pTcon = cifs_sb->tcon; 488 pTcon = cifs_sb->tcon;
489 if (pSMBFile) { 489 if (pSMBFile) {
490 struct cifsLockInfo *li, *tmp; 490 struct cifsLockInfo *li, *tmp;
491 491 write_lock(&GlobalSMBSeslock);
492 pSMBFile->closePend = true; 492 pSMBFile->closePend = true;
493 if (pTcon) { 493 if (pTcon) {
494 /* no sense reconnecting to close a file that is 494 /* no sense reconnecting to close a file that is
495 already closed */ 495 already closed */
496 if (!pTcon->need_reconnect) { 496 if (!pTcon->need_reconnect) {
497 write_unlock(&GlobalSMBSeslock);
497 timeout = 2; 498 timeout = 2;
498 while ((atomic_read(&pSMBFile->wrtPending) != 0) 499 while ((atomic_read(&pSMBFile->wrtPending) != 0)
499 && (timeout <= 2048)) { 500 && (timeout <= 2048)) {
@@ -510,12 +511,15 @@ int cifs_close(struct inode *inode, struct file *file)
510 timeout *= 4; 511 timeout *= 4;
511 } 512 }
512 if (atomic_read(&pSMBFile->wrtPending)) 513 if (atomic_read(&pSMBFile->wrtPending))
513 cERROR(1, 514 cERROR(1, ("close with pending write"));
514 ("close with pending writes")); 515 if (!pTcon->need_reconnect &&
515 rc = CIFSSMBClose(xid, pTcon, 516 !pSMBFile->invalidHandle)
517 rc = CIFSSMBClose(xid, pTcon,
516 pSMBFile->netfid); 518 pSMBFile->netfid);
517 } 519 } else
518 } 520 write_unlock(&GlobalSMBSeslock);
521 } else
522 write_unlock(&GlobalSMBSeslock);
519 523
520 /* Delete any outstanding lock records. 524 /* Delete any outstanding lock records.
521 We'll lose them when the file is closed anyway. */ 525 We'll lose them when the file is closed anyway. */
@@ -587,15 +591,18 @@ int cifs_closedir(struct inode *inode, struct file *file)
587 pTcon = cifs_sb->tcon; 591 pTcon = cifs_sb->tcon;
588 592
589 cFYI(1, ("Freeing private data in close dir")); 593 cFYI(1, ("Freeing private data in close dir"));
594 write_lock(&GlobalSMBSeslock);
590 if (!pCFileStruct->srch_inf.endOfSearch && 595 if (!pCFileStruct->srch_inf.endOfSearch &&
591 !pCFileStruct->invalidHandle) { 596 !pCFileStruct->invalidHandle) {
592 pCFileStruct->invalidHandle = true; 597 pCFileStruct->invalidHandle = true;
598 write_unlock(&GlobalSMBSeslock);
593 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); 599 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
594 cFYI(1, ("Closing uncompleted readdir with rc %d", 600 cFYI(1, ("Closing uncompleted readdir with rc %d",
595 rc)); 601 rc));
596 /* not much we can do if it fails anyway, ignore rc */ 602 /* not much we can do if it fails anyway, ignore rc */
597 rc = 0; 603 rc = 0;
598 } 604 } else
605 write_unlock(&GlobalSMBSeslock);
599 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; 606 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
600 if (ptmp) { 607 if (ptmp) {
601 cFYI(1, ("closedir free smb buf in srch struct")); 608 cFYI(1, ("closedir free smb buf in srch struct"));
@@ -1468,7 +1475,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
1468 cFYI(1, ("write_end for page %p from pos %lld with %d bytes", 1475 cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
1469 page, pos, copied)); 1476 page, pos, copied));
1470 1477
1471 if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE) 1478 if (PageChecked(page)) {
1479 if (copied == len)
1480 SetPageUptodate(page);
1481 ClearPageChecked(page);
1482 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
1472 SetPageUptodate(page); 1483 SetPageUptodate(page);
1473 1484
1474 if (!PageUptodate(page)) { 1485 if (!PageUptodate(page)) {
@@ -2055,39 +2066,70 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
2055{ 2066{
2056 pgoff_t index = pos >> PAGE_CACHE_SHIFT; 2067 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2057 loff_t offset = pos & (PAGE_CACHE_SIZE - 1); 2068 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
2069 loff_t page_start = pos & PAGE_MASK;
2070 loff_t i_size;
2071 struct page *page;
2072 int rc = 0;
2058 2073
2059 cFYI(1, ("write_begin from %lld len %d", (long long)pos, len)); 2074 cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
2060 2075
2061 *pagep = __grab_cache_page(mapping, index); 2076 page = __grab_cache_page(mapping, index);
2062 if (!*pagep) 2077 if (!page) {
2063 return -ENOMEM; 2078 rc = -ENOMEM;
2064 2079 goto out;
2065 if (PageUptodate(*pagep)) 2080 }
2066 return 0;
2067 2081
2068 /* If we are writing a full page it will be up to date, 2082 if (PageUptodate(page))
2069 no need to read from the server */ 2083 goto out;
2070 if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
2071 return 0;
2072 2084
2073 if ((file->f_flags & O_ACCMODE) != O_WRONLY) { 2085 /*
2074 int rc; 2086 * If we write a full page it will be up to date, no need to read from
2087 * the server. If the write is short, we'll end up doing a sync write
2088 * instead.
2089 */
2090 if (len == PAGE_CACHE_SIZE)
2091 goto out;
2075 2092
2076 /* might as well read a page, it is fast enough */ 2093 /*
2077 rc = cifs_readpage_worker(file, *pagep, &offset); 2094 * optimize away the read when we have an oplock, and we're not
2095 * expecting to use any of the data we'd be reading in. That
2096 * is, when the page lies beyond the EOF, or straddles the EOF
2097 * and the write will cover all of the existing data.
2098 */
2099 if (CIFS_I(mapping->host)->clientCanCacheRead) {
2100 i_size = i_size_read(mapping->host);
2101 if (page_start >= i_size ||
2102 (offset == 0 && (pos + len) >= i_size)) {
2103 zero_user_segments(page, 0, offset,
2104 offset + len,
2105 PAGE_CACHE_SIZE);
2106 /*
2107 * PageChecked means that the parts of the page
2108 * to which we're not writing are considered up
2109 * to date. Once the data is copied to the
2110 * page, it can be set uptodate.
2111 */
2112 SetPageChecked(page);
2113 goto out;
2114 }
2115 }
2078 2116
2079 /* we do not need to pass errors back 2117 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2080 e.g. if we do not have read access to the file 2118 /*
2081 because cifs_write_end will attempt synchronous writes 2119 * might as well read a page, it is fast enough. If we get
2082 -- shaggy */ 2120 * an error, we don't need to return it. cifs_write_end will
2121 * do a sync write instead since PG_uptodate isn't set.
2122 */
2123 cifs_readpage_worker(file, page, &page_start);
2083 } else { 2124 } else {
2084 /* we could try using another file handle if there is one - 2125 /* we could try using another file handle if there is one -
2085 but how would we lock it to prevent close of that handle 2126 but how would we lock it to prevent close of that handle
2086 racing with this read? In any case 2127 racing with this read? In any case
2087 this will be written out by write_end so is fine */ 2128 this will be written out by write_end so is fine */
2088 } 2129 }
2089 2130out:
2090 return 0; 2131 *pagep = page;
2132 return rc;
2091} 2133}
2092 2134
2093const struct address_space_operations cifs_addr_ops = { 2135const struct address_space_operations cifs_addr_ops = {