diff options
Diffstat (limited to 'fs/cifs/file.c')
| -rw-r--r-- | fs/cifs/file.c | 105 |
1 files changed, 75 insertions, 30 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ead1a3bb0256..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->tidStatus != CifsNeedReconnect) { | 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")); |
| @@ -1404,7 +1411,10 @@ retry: | |||
| 1404 | if ((wbc->nr_to_write -= n_iov) <= 0) | 1411 | if ((wbc->nr_to_write -= n_iov) <= 0) |
| 1405 | done = 1; | 1412 | done = 1; |
| 1406 | index = next; | 1413 | index = next; |
| 1407 | } | 1414 | } else |
| 1415 | /* Need to re-find the pages we skipped */ | ||
| 1416 | index = pvec.pages[0]->index + 1; | ||
| 1417 | |||
| 1408 | pagevec_release(&pvec); | 1418 | pagevec_release(&pvec); |
| 1409 | } | 1419 | } |
| 1410 | if (!scanned && !done) { | 1420 | if (!scanned && !done) { |
| @@ -1465,7 +1475,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
| 1465 | 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", |
| 1466 | page, pos, copied)); | 1476 | page, pos, copied)); |
| 1467 | 1477 | ||
| 1468 | 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) | ||
| 1469 | SetPageUptodate(page); | 1483 | SetPageUptodate(page); |
| 1470 | 1484 | ||
| 1471 | if (!PageUptodate(page)) { | 1485 | if (!PageUptodate(page)) { |
| @@ -2052,39 +2066,70 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping, | |||
| 2052 | { | 2066 | { |
| 2053 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | 2067 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
| 2054 | 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; | ||
| 2055 | 2073 | ||
| 2056 | 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)); |
| 2057 | 2075 | ||
| 2058 | *pagep = __grab_cache_page(mapping, index); | 2076 | page = __grab_cache_page(mapping, index); |
| 2059 | if (!*pagep) | 2077 | if (!page) { |
| 2060 | return -ENOMEM; | 2078 | rc = -ENOMEM; |
| 2061 | 2079 | goto out; | |
| 2062 | if (PageUptodate(*pagep)) | 2080 | } |
| 2063 | return 0; | ||
| 2064 | 2081 | ||
| 2065 | /* If we are writing a full page it will be up to date, | 2082 | if (PageUptodate(page)) |
| 2066 | no need to read from the server */ | 2083 | goto out; |
| 2067 | if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE) | ||
| 2068 | return 0; | ||
| 2069 | 2084 | ||
| 2070 | if ((file->f_flags & O_ACCMODE) != O_WRONLY) { | 2085 | /* |
| 2071 | 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; | ||
| 2072 | 2092 | ||
| 2073 | /* might as well read a page, it is fast enough */ | 2093 | /* |
| 2074 | 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 | } | ||
| 2075 | 2116 | ||
| 2076 | /* we do not need to pass errors back | 2117 | if ((file->f_flags & O_ACCMODE) != O_WRONLY) { |
| 2077 | e.g. if we do not have read access to the file | 2118 | /* |
| 2078 | because cifs_write_end will attempt synchronous writes | 2119 | * might as well read a page, it is fast enough. If we get |
| 2079 | -- 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); | ||
| 2080 | } else { | 2124 | } else { |
| 2081 | /* we could try using another file handle if there is one - | 2125 | /* we could try using another file handle if there is one - |
| 2082 | 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 |
| 2083 | racing with this read? In any case | 2127 | racing with this read? In any case |
| 2084 | this will be written out by write_end so is fine */ | 2128 | this will be written out by write_end so is fine */ |
| 2085 | } | 2129 | } |
| 2086 | 2130 | out: | |
| 2087 | return 0; | 2131 | *pagep = page; |
| 2132 | return rc; | ||
| 2088 | } | 2133 | } |
| 2089 | 2134 | ||
| 2090 | const struct address_space_operations cifs_addr_ops = { | 2135 | const struct address_space_operations cifs_addr_ops = { |
