diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 269 |
1 files changed, 185 insertions, 84 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 659ce1b92c44..4c144c1f50eb 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1842,24 +1842,30 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | |||
1842 | return NULL; | 1842 | return NULL; |
1843 | } | 1843 | } |
1844 | 1844 | ||
1845 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, | 1845 | /* Return -EBADF if no handle is found and general rc otherwise */ |
1846 | bool fsuid_only) | 1846 | int |
1847 | cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, | ||
1848 | struct cifsFileInfo **ret_file) | ||
1847 | { | 1849 | { |
1848 | struct cifsFileInfo *open_file, *inv_file = NULL; | 1850 | struct cifsFileInfo *open_file, *inv_file = NULL; |
1849 | struct cifs_sb_info *cifs_sb; | 1851 | struct cifs_sb_info *cifs_sb; |
1850 | struct cifs_tcon *tcon; | 1852 | struct cifs_tcon *tcon; |
1851 | bool any_available = false; | 1853 | bool any_available = false; |
1852 | int rc; | 1854 | int rc = -EBADF; |
1853 | unsigned int refind = 0; | 1855 | unsigned int refind = 0; |
1854 | 1856 | ||
1855 | /* Having a null inode here (because mapping->host was set to zero by | 1857 | *ret_file = NULL; |
1856 | the VFS or MM) should not happen but we had reports of on oops (due to | 1858 | |
1857 | it being zero) during stress testcases so we need to check for it */ | 1859 | /* |
1860 | * Having a null inode here (because mapping->host was set to zero by | ||
1861 | * the VFS or MM) should not happen but we had reports of on oops (due | ||
1862 | * to it being zero) during stress testcases so we need to check for it | ||
1863 | */ | ||
1858 | 1864 | ||
1859 | if (cifs_inode == NULL) { | 1865 | if (cifs_inode == NULL) { |
1860 | cifs_dbg(VFS, "Null inode passed to cifs_writeable_file\n"); | 1866 | cifs_dbg(VFS, "Null inode passed to cifs_writeable_file\n"); |
1861 | dump_stack(); | 1867 | dump_stack(); |
1862 | return NULL; | 1868 | return rc; |
1863 | } | 1869 | } |
1864 | 1870 | ||
1865 | cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); | 1871 | cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); |
@@ -1873,7 +1879,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, | |||
1873 | refind_writable: | 1879 | refind_writable: |
1874 | if (refind > MAX_REOPEN_ATT) { | 1880 | if (refind > MAX_REOPEN_ATT) { |
1875 | spin_unlock(&tcon->open_file_lock); | 1881 | spin_unlock(&tcon->open_file_lock); |
1876 | return NULL; | 1882 | return rc; |
1877 | } | 1883 | } |
1878 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 1884 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
1879 | if (!any_available && open_file->pid != current->tgid) | 1885 | if (!any_available && open_file->pid != current->tgid) |
@@ -1885,7 +1891,8 @@ refind_writable: | |||
1885 | /* found a good writable file */ | 1891 | /* found a good writable file */ |
1886 | cifsFileInfo_get(open_file); | 1892 | cifsFileInfo_get(open_file); |
1887 | spin_unlock(&tcon->open_file_lock); | 1893 | spin_unlock(&tcon->open_file_lock); |
1888 | return open_file; | 1894 | *ret_file = open_file; |
1895 | return 0; | ||
1889 | } else { | 1896 | } else { |
1890 | if (!inv_file) | 1897 | if (!inv_file) |
1891 | inv_file = open_file; | 1898 | inv_file = open_file; |
@@ -1907,22 +1914,35 @@ refind_writable: | |||
1907 | 1914 | ||
1908 | if (inv_file) { | 1915 | if (inv_file) { |
1909 | rc = cifs_reopen_file(inv_file, false); | 1916 | rc = cifs_reopen_file(inv_file, false); |
1910 | if (!rc) | 1917 | if (!rc) { |
1911 | return inv_file; | 1918 | *ret_file = inv_file; |
1912 | else { | 1919 | return 0; |
1913 | spin_lock(&tcon->open_file_lock); | ||
1914 | list_move_tail(&inv_file->flist, | ||
1915 | &cifs_inode->openFileList); | ||
1916 | spin_unlock(&tcon->open_file_lock); | ||
1917 | cifsFileInfo_put(inv_file); | ||
1918 | ++refind; | ||
1919 | inv_file = NULL; | ||
1920 | spin_lock(&tcon->open_file_lock); | ||
1921 | goto refind_writable; | ||
1922 | } | 1920 | } |
1921 | |||
1922 | spin_lock(&tcon->open_file_lock); | ||
1923 | list_move_tail(&inv_file->flist, &cifs_inode->openFileList); | ||
1924 | spin_unlock(&tcon->open_file_lock); | ||
1925 | cifsFileInfo_put(inv_file); | ||
1926 | ++refind; | ||
1927 | inv_file = NULL; | ||
1928 | spin_lock(&tcon->open_file_lock); | ||
1929 | goto refind_writable; | ||
1923 | } | 1930 | } |
1924 | 1931 | ||
1925 | return NULL; | 1932 | return rc; |
1933 | } | ||
1934 | |||
1935 | struct cifsFileInfo * | ||
1936 | find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) | ||
1937 | { | ||
1938 | struct cifsFileInfo *cfile; | ||
1939 | int rc; | ||
1940 | |||
1941 | rc = cifs_get_writable_file(cifs_inode, fsuid_only, &cfile); | ||
1942 | if (rc) | ||
1943 | cifs_dbg(FYI, "couldn't find writable handle rc=%d", rc); | ||
1944 | |||
1945 | return cfile; | ||
1926 | } | 1946 | } |
1927 | 1947 | ||
1928 | static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | 1948 | static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) |
@@ -1959,8 +1979,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1959 | if (mapping->host->i_size - offset < (loff_t)to) | 1979 | if (mapping->host->i_size - offset < (loff_t)to) |
1960 | to = (unsigned)(mapping->host->i_size - offset); | 1980 | to = (unsigned)(mapping->host->i_size - offset); |
1961 | 1981 | ||
1962 | open_file = find_writable_file(CIFS_I(mapping->host), false); | 1982 | rc = cifs_get_writable_file(CIFS_I(mapping->host), false, &open_file); |
1963 | if (open_file) { | 1983 | if (!rc) { |
1964 | bytes_written = cifs_write(open_file, open_file->pid, | 1984 | bytes_written = cifs_write(open_file, open_file->pid, |
1965 | write_data, to - from, &offset); | 1985 | write_data, to - from, &offset); |
1966 | cifsFileInfo_put(open_file); | 1986 | cifsFileInfo_put(open_file); |
@@ -1970,9 +1990,12 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1970 | rc = 0; | 1990 | rc = 0; |
1971 | else if (bytes_written < 0) | 1991 | else if (bytes_written < 0) |
1972 | rc = bytes_written; | 1992 | rc = bytes_written; |
1993 | else | ||
1994 | rc = -EFAULT; | ||
1973 | } else { | 1995 | } else { |
1974 | cifs_dbg(FYI, "No writeable filehandles for inode\n"); | 1996 | cifs_dbg(FYI, "No writable handle for write page rc=%d\n", rc); |
1975 | rc = -EIO; | 1997 | if (!is_retryable_error(rc)) |
1998 | rc = -EIO; | ||
1976 | } | 1999 | } |
1977 | 2000 | ||
1978 | kunmap(page); | 2001 | kunmap(page); |
@@ -2079,9 +2102,9 @@ static int | |||
2079 | wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, | 2102 | wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, |
2080 | struct address_space *mapping, struct writeback_control *wbc) | 2103 | struct address_space *mapping, struct writeback_control *wbc) |
2081 | { | 2104 | { |
2082 | int rc = 0; | 2105 | int rc; |
2083 | struct TCP_Server_Info *server; | 2106 | struct TCP_Server_Info *server = |
2084 | unsigned int i; | 2107 | tlink_tcon(wdata->cfile->tlink)->ses->server; |
2085 | 2108 | ||
2086 | wdata->sync_mode = wbc->sync_mode; | 2109 | wdata->sync_mode = wbc->sync_mode; |
2087 | wdata->nr_pages = nr_pages; | 2110 | wdata->nr_pages = nr_pages; |
@@ -2091,21 +2114,16 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, | |||
2091 | page_offset(wdata->pages[nr_pages - 1]), | 2114 | page_offset(wdata->pages[nr_pages - 1]), |
2092 | (loff_t)PAGE_SIZE); | 2115 | (loff_t)PAGE_SIZE); |
2093 | wdata->bytes = ((nr_pages - 1) * PAGE_SIZE) + wdata->tailsz; | 2116 | wdata->bytes = ((nr_pages - 1) * PAGE_SIZE) + wdata->tailsz; |
2117 | wdata->pid = wdata->cfile->pid; | ||
2094 | 2118 | ||
2095 | if (wdata->cfile != NULL) | 2119 | rc = adjust_credits(server, &wdata->credits, wdata->bytes); |
2096 | cifsFileInfo_put(wdata->cfile); | 2120 | if (rc) |
2097 | wdata->cfile = find_writable_file(CIFS_I(mapping->host), false); | 2121 | return rc; |
2098 | if (!wdata->cfile) { | ||
2099 | cifs_dbg(VFS, "No writable handles for inode\n"); | ||
2100 | rc = -EBADF; | ||
2101 | } else { | ||
2102 | wdata->pid = wdata->cfile->pid; | ||
2103 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; | ||
2104 | rc = server->ops->async_writev(wdata, cifs_writedata_release); | ||
2105 | } | ||
2106 | 2122 | ||
2107 | for (i = 0; i < nr_pages; ++i) | 2123 | if (wdata->cfile->invalidHandle) |
2108 | unlock_page(wdata->pages[i]); | 2124 | rc = -EAGAIN; |
2125 | else | ||
2126 | rc = server->ops->async_writev(wdata, cifs_writedata_release); | ||
2109 | 2127 | ||
2110 | return rc; | 2128 | return rc; |
2111 | } | 2129 | } |
@@ -2113,11 +2131,13 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages, | |||
2113 | static int cifs_writepages(struct address_space *mapping, | 2131 | static int cifs_writepages(struct address_space *mapping, |
2114 | struct writeback_control *wbc) | 2132 | struct writeback_control *wbc) |
2115 | { | 2133 | { |
2116 | struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb); | 2134 | struct inode *inode = mapping->host; |
2135 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
2117 | struct TCP_Server_Info *server; | 2136 | struct TCP_Server_Info *server; |
2118 | bool done = false, scanned = false, range_whole = false; | 2137 | bool done = false, scanned = false, range_whole = false; |
2119 | pgoff_t end, index; | 2138 | pgoff_t end, index; |
2120 | struct cifs_writedata *wdata; | 2139 | struct cifs_writedata *wdata; |
2140 | struct cifsFileInfo *cfile = NULL; | ||
2121 | int rc = 0; | 2141 | int rc = 0; |
2122 | int saved_rc = 0; | 2142 | int saved_rc = 0; |
2123 | unsigned int xid; | 2143 | unsigned int xid; |
@@ -2143,11 +2163,23 @@ static int cifs_writepages(struct address_space *mapping, | |||
2143 | server = cifs_sb_master_tcon(cifs_sb)->ses->server; | 2163 | server = cifs_sb_master_tcon(cifs_sb)->ses->server; |
2144 | retry: | 2164 | retry: |
2145 | while (!done && index <= end) { | 2165 | while (!done && index <= end) { |
2146 | unsigned int i, nr_pages, found_pages, wsize, credits; | 2166 | unsigned int i, nr_pages, found_pages, wsize; |
2147 | pgoff_t next = 0, tofind, saved_index = index; | 2167 | pgoff_t next = 0, tofind, saved_index = index; |
2168 | struct cifs_credits credits_on_stack; | ||
2169 | struct cifs_credits *credits = &credits_on_stack; | ||
2170 | int get_file_rc = 0; | ||
2171 | |||
2172 | if (cfile) | ||
2173 | cifsFileInfo_put(cfile); | ||
2174 | |||
2175 | rc = cifs_get_writable_file(CIFS_I(inode), false, &cfile); | ||
2176 | |||
2177 | /* in case of an error store it to return later */ | ||
2178 | if (rc) | ||
2179 | get_file_rc = rc; | ||
2148 | 2180 | ||
2149 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, | 2181 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, |
2150 | &wsize, &credits); | 2182 | &wsize, credits); |
2151 | if (rc != 0) { | 2183 | if (rc != 0) { |
2152 | done = true; | 2184 | done = true; |
2153 | break; | 2185 | break; |
@@ -2180,13 +2212,26 @@ retry: | |||
2180 | continue; | 2212 | continue; |
2181 | } | 2213 | } |
2182 | 2214 | ||
2183 | wdata->credits = credits; | 2215 | wdata->credits = credits_on_stack; |
2216 | wdata->cfile = cfile; | ||
2217 | cfile = NULL; | ||
2184 | 2218 | ||
2185 | rc = wdata_send_pages(wdata, nr_pages, mapping, wbc); | 2219 | if (!wdata->cfile) { |
2220 | cifs_dbg(VFS, "No writable handle in writepages rc=%d\n", | ||
2221 | get_file_rc); | ||
2222 | if (is_retryable_error(get_file_rc)) | ||
2223 | rc = get_file_rc; | ||
2224 | else | ||
2225 | rc = -EBADF; | ||
2226 | } else | ||
2227 | rc = wdata_send_pages(wdata, nr_pages, mapping, wbc); | ||
2228 | |||
2229 | for (i = 0; i < nr_pages; ++i) | ||
2230 | unlock_page(wdata->pages[i]); | ||
2186 | 2231 | ||
2187 | /* send failure -- clean up the mess */ | 2232 | /* send failure -- clean up the mess */ |
2188 | if (rc != 0) { | 2233 | if (rc != 0) { |
2189 | add_credits_and_wake_if(server, wdata->credits, 0); | 2234 | add_credits_and_wake_if(server, &wdata->credits, 0); |
2190 | for (i = 0; i < nr_pages; ++i) { | 2235 | for (i = 0; i < nr_pages; ++i) { |
2191 | if (is_retryable_error(rc)) | 2236 | if (is_retryable_error(rc)) |
2192 | redirty_page_for_writepage(wbc, | 2237 | redirty_page_for_writepage(wbc, |
@@ -2238,6 +2283,8 @@ retry: | |||
2238 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) | 2283 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) |
2239 | mapping->writeback_index = index; | 2284 | mapping->writeback_index = index; |
2240 | 2285 | ||
2286 | if (cfile) | ||
2287 | cifsFileInfo_put(cfile); | ||
2241 | free_xid(xid); | 2288 | free_xid(xid); |
2242 | return rc; | 2289 | return rc; |
2243 | } | 2290 | } |
@@ -2567,7 +2614,8 @@ static int | |||
2567 | cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, | 2614 | cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, |
2568 | struct cifs_aio_ctx *ctx) | 2615 | struct cifs_aio_ctx *ctx) |
2569 | { | 2616 | { |
2570 | unsigned int wsize, credits; | 2617 | unsigned int wsize; |
2618 | struct cifs_credits credits; | ||
2571 | int rc; | 2619 | int rc; |
2572 | struct TCP_Server_Info *server = | 2620 | struct TCP_Server_Info *server = |
2573 | tlink_tcon(wdata->cfile->tlink)->ses->server; | 2621 | tlink_tcon(wdata->cfile->tlink)->ses->server; |
@@ -2577,18 +2625,19 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, | |||
2577 | * Note: we are attempting to resend the whole wdata not in segments | 2625 | * Note: we are attempting to resend the whole wdata not in segments |
2578 | */ | 2626 | */ |
2579 | do { | 2627 | do { |
2580 | rc = server->ops->wait_mtu_credits( | 2628 | rc = server->ops->wait_mtu_credits(server, wdata->bytes, &wsize, |
2581 | server, wdata->bytes, &wsize, &credits); | 2629 | &credits); |
2582 | 2630 | ||
2583 | if (rc) | 2631 | if (rc) |
2584 | goto out; | 2632 | goto out; |
2585 | 2633 | ||
2586 | if (wsize < wdata->bytes) { | 2634 | if (wsize < wdata->bytes) { |
2587 | add_credits_and_wake_if(server, credits, 0); | 2635 | add_credits_and_wake_if(server, &credits, 0); |
2588 | msleep(1000); | 2636 | msleep(1000); |
2589 | } | 2637 | } |
2590 | } while (wsize < wdata->bytes); | 2638 | } while (wsize < wdata->bytes); |
2591 | 2639 | ||
2640 | wdata->credits = credits; | ||
2592 | rc = -EAGAIN; | 2641 | rc = -EAGAIN; |
2593 | while (rc == -EAGAIN) { | 2642 | while (rc == -EAGAIN) { |
2594 | rc = 0; | 2643 | rc = 0; |
@@ -2604,7 +2653,7 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, | |||
2604 | return 0; | 2653 | return 0; |
2605 | } | 2654 | } |
2606 | 2655 | ||
2607 | add_credits_and_wake_if(server, wdata->credits, 0); | 2656 | add_credits_and_wake_if(server, &wdata->credits, 0); |
2608 | out: | 2657 | out: |
2609 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); | 2658 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
2610 | 2659 | ||
@@ -2627,6 +2676,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
2627 | struct TCP_Server_Info *server; | 2676 | struct TCP_Server_Info *server; |
2628 | struct page **pagevec; | 2677 | struct page **pagevec; |
2629 | size_t start; | 2678 | size_t start; |
2679 | unsigned int xid; | ||
2630 | 2680 | ||
2631 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2681 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
2632 | pid = open_file->pid; | 2682 | pid = open_file->pid; |
@@ -2634,12 +2684,23 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
2634 | pid = current->tgid; | 2684 | pid = current->tgid; |
2635 | 2685 | ||
2636 | server = tlink_tcon(open_file->tlink)->ses->server; | 2686 | server = tlink_tcon(open_file->tlink)->ses->server; |
2687 | xid = get_xid(); | ||
2637 | 2688 | ||
2638 | do { | 2689 | do { |
2639 | unsigned int wsize, credits; | 2690 | unsigned int wsize; |
2691 | struct cifs_credits credits_on_stack; | ||
2692 | struct cifs_credits *credits = &credits_on_stack; | ||
2693 | |||
2694 | if (open_file->invalidHandle) { | ||
2695 | rc = cifs_reopen_file(open_file, false); | ||
2696 | if (rc == -EAGAIN) | ||
2697 | continue; | ||
2698 | else if (rc) | ||
2699 | break; | ||
2700 | } | ||
2640 | 2701 | ||
2641 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, | 2702 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, |
2642 | &wsize, &credits); | 2703 | &wsize, credits); |
2643 | if (rc) | 2704 | if (rc) |
2644 | break; | 2705 | break; |
2645 | 2706 | ||
@@ -2731,16 +2792,22 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
2731 | wdata->pid = pid; | 2792 | wdata->pid = pid; |
2732 | wdata->bytes = cur_len; | 2793 | wdata->bytes = cur_len; |
2733 | wdata->pagesz = PAGE_SIZE; | 2794 | wdata->pagesz = PAGE_SIZE; |
2734 | wdata->credits = credits; | 2795 | wdata->credits = credits_on_stack; |
2735 | wdata->ctx = ctx; | 2796 | wdata->ctx = ctx; |
2736 | kref_get(&ctx->refcount); | 2797 | kref_get(&ctx->refcount); |
2737 | 2798 | ||
2738 | if (!wdata->cfile->invalidHandle || | 2799 | rc = adjust_credits(server, &wdata->credits, wdata->bytes); |
2739 | !(rc = cifs_reopen_file(wdata->cfile, false))) | 2800 | |
2740 | rc = server->ops->async_writev(wdata, | 2801 | if (!rc) { |
2802 | if (wdata->cfile->invalidHandle) | ||
2803 | rc = -EAGAIN; | ||
2804 | else | ||
2805 | rc = server->ops->async_writev(wdata, | ||
2741 | cifs_uncached_writedata_release); | 2806 | cifs_uncached_writedata_release); |
2807 | } | ||
2808 | |||
2742 | if (rc) { | 2809 | if (rc) { |
2743 | add_credits_and_wake_if(server, wdata->credits, 0); | 2810 | add_credits_and_wake_if(server, &wdata->credits, 0); |
2744 | kref_put(&wdata->refcount, | 2811 | kref_put(&wdata->refcount, |
2745 | cifs_uncached_writedata_release); | 2812 | cifs_uncached_writedata_release); |
2746 | if (rc == -EAGAIN) { | 2813 | if (rc == -EAGAIN) { |
@@ -2756,6 +2823,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
2756 | len -= cur_len; | 2823 | len -= cur_len; |
2757 | } while (len > 0); | 2824 | } while (len > 0); |
2758 | 2825 | ||
2826 | free_xid(xid); | ||
2759 | return rc; | 2827 | return rc; |
2760 | } | 2828 | } |
2761 | 2829 | ||
@@ -3028,14 +3096,16 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) | |||
3028 | * these pages but not on the region from pos to ppos+len-1. | 3096 | * these pages but not on the region from pos to ppos+len-1. |
3029 | */ | 3097 | */ |
3030 | written = cifs_user_writev(iocb, from); | 3098 | written = cifs_user_writev(iocb, from); |
3031 | if (written > 0 && CIFS_CACHE_READ(cinode)) { | 3099 | if (CIFS_CACHE_READ(cinode)) { |
3032 | /* | 3100 | /* |
3033 | * Windows 7 server can delay breaking level2 oplock if a write | 3101 | * We have read level caching and we have just sent a write |
3034 | * request comes - break it on the client to prevent reading | 3102 | * request to the server thus making data in the cache stale. |
3035 | * an old data. | 3103 | * Zap the cache and set oplock/lease level to NONE to avoid |
3104 | * reading stale data from the cache. All subsequent read | ||
3105 | * operations will read new data from the server. | ||
3036 | */ | 3106 | */ |
3037 | cifs_zap_mapping(inode); | 3107 | cifs_zap_mapping(inode); |
3038 | cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n", | 3108 | cifs_dbg(FYI, "Set Oplock/Lease to NONE for inode=%p after write\n", |
3039 | inode); | 3109 | inode); |
3040 | cinode->oplock = 0; | 3110 | cinode->oplock = 0; |
3041 | } | 3111 | } |
@@ -3260,7 +3330,8 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, | |||
3260 | struct list_head *rdata_list, | 3330 | struct list_head *rdata_list, |
3261 | struct cifs_aio_ctx *ctx) | 3331 | struct cifs_aio_ctx *ctx) |
3262 | { | 3332 | { |
3263 | unsigned int rsize, credits; | 3333 | unsigned int rsize; |
3334 | struct cifs_credits credits; | ||
3264 | int rc; | 3335 | int rc; |
3265 | struct TCP_Server_Info *server = | 3336 | struct TCP_Server_Info *server = |
3266 | tlink_tcon(rdata->cfile->tlink)->ses->server; | 3337 | tlink_tcon(rdata->cfile->tlink)->ses->server; |
@@ -3277,11 +3348,12 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, | |||
3277 | goto out; | 3348 | goto out; |
3278 | 3349 | ||
3279 | if (rsize < rdata->bytes) { | 3350 | if (rsize < rdata->bytes) { |
3280 | add_credits_and_wake_if(server, credits, 0); | 3351 | add_credits_and_wake_if(server, &credits, 0); |
3281 | msleep(1000); | 3352 | msleep(1000); |
3282 | } | 3353 | } |
3283 | } while (rsize < rdata->bytes); | 3354 | } while (rsize < rdata->bytes); |
3284 | 3355 | ||
3356 | rdata->credits = credits; | ||
3285 | rc = -EAGAIN; | 3357 | rc = -EAGAIN; |
3286 | while (rc == -EAGAIN) { | 3358 | while (rc == -EAGAIN) { |
3287 | rc = 0; | 3359 | rc = 0; |
@@ -3297,7 +3369,7 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, | |||
3297 | return 0; | 3369 | return 0; |
3298 | } | 3370 | } |
3299 | 3371 | ||
3300 | add_credits_and_wake_if(server, rdata->credits, 0); | 3372 | add_credits_and_wake_if(server, &rdata->credits, 0); |
3301 | out: | 3373 | out: |
3302 | kref_put(&rdata->refcount, | 3374 | kref_put(&rdata->refcount, |
3303 | cifs_uncached_readdata_release); | 3375 | cifs_uncached_readdata_release); |
@@ -3311,7 +3383,9 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
3311 | struct cifs_aio_ctx *ctx) | 3383 | struct cifs_aio_ctx *ctx) |
3312 | { | 3384 | { |
3313 | struct cifs_readdata *rdata; | 3385 | struct cifs_readdata *rdata; |
3314 | unsigned int npages, rsize, credits; | 3386 | unsigned int npages, rsize; |
3387 | struct cifs_credits credits_on_stack; | ||
3388 | struct cifs_credits *credits = &credits_on_stack; | ||
3315 | size_t cur_len; | 3389 | size_t cur_len; |
3316 | int rc; | 3390 | int rc; |
3317 | pid_t pid; | 3391 | pid_t pid; |
@@ -3331,8 +3405,16 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
3331 | iov_iter_advance(&direct_iov, offset - ctx->pos); | 3405 | iov_iter_advance(&direct_iov, offset - ctx->pos); |
3332 | 3406 | ||
3333 | do { | 3407 | do { |
3408 | if (open_file->invalidHandle) { | ||
3409 | rc = cifs_reopen_file(open_file, true); | ||
3410 | if (rc == -EAGAIN) | ||
3411 | continue; | ||
3412 | else if (rc) | ||
3413 | break; | ||
3414 | } | ||
3415 | |||
3334 | rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize, | 3416 | rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize, |
3335 | &rsize, &credits); | 3417 | &rsize, credits); |
3336 | if (rc) | 3418 | if (rc) |
3337 | break; | 3419 | break; |
3338 | 3420 | ||
@@ -3406,15 +3488,21 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
3406 | rdata->pagesz = PAGE_SIZE; | 3488 | rdata->pagesz = PAGE_SIZE; |
3407 | rdata->read_into_pages = cifs_uncached_read_into_pages; | 3489 | rdata->read_into_pages = cifs_uncached_read_into_pages; |
3408 | rdata->copy_into_pages = cifs_uncached_copy_into_pages; | 3490 | rdata->copy_into_pages = cifs_uncached_copy_into_pages; |
3409 | rdata->credits = credits; | 3491 | rdata->credits = credits_on_stack; |
3410 | rdata->ctx = ctx; | 3492 | rdata->ctx = ctx; |
3411 | kref_get(&ctx->refcount); | 3493 | kref_get(&ctx->refcount); |
3412 | 3494 | ||
3413 | if (!rdata->cfile->invalidHandle || | 3495 | rc = adjust_credits(server, &rdata->credits, rdata->bytes); |
3414 | !(rc = cifs_reopen_file(rdata->cfile, true))) | 3496 | |
3415 | rc = server->ops->async_readv(rdata); | 3497 | if (!rc) { |
3498 | if (rdata->cfile->invalidHandle) | ||
3499 | rc = -EAGAIN; | ||
3500 | else | ||
3501 | rc = server->ops->async_readv(rdata); | ||
3502 | } | ||
3503 | |||
3416 | if (rc) { | 3504 | if (rc) { |
3417 | add_credits_and_wake_if(server, rdata->credits, 0); | 3505 | add_credits_and_wake_if(server, &rdata->credits, 0); |
3418 | kref_put(&rdata->refcount, | 3506 | kref_put(&rdata->refcount, |
3419 | cifs_uncached_readdata_release); | 3507 | cifs_uncached_readdata_release); |
3420 | if (rc == -EAGAIN) { | 3508 | if (rc == -EAGAIN) { |
@@ -3533,8 +3621,6 @@ again: | |||
3533 | ctx->total_len = ctx->len - iov_iter_count(to); | 3621 | ctx->total_len = ctx->len - iov_iter_count(to); |
3534 | } | 3622 | } |
3535 | 3623 | ||
3536 | cifs_stats_bytes_read(tcon, ctx->total_len); | ||
3537 | |||
3538 | /* mask nodata case */ | 3624 | /* mask nodata case */ |
3539 | if (rc == -ENODATA) | 3625 | if (rc == -ENODATA) |
3540 | rc = 0; | 3626 | rc = 0; |
@@ -4095,10 +4181,19 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
4095 | loff_t offset; | 4181 | loff_t offset; |
4096 | struct page *page, *tpage; | 4182 | struct page *page, *tpage; |
4097 | struct cifs_readdata *rdata; | 4183 | struct cifs_readdata *rdata; |
4098 | unsigned credits; | 4184 | struct cifs_credits credits_on_stack; |
4185 | struct cifs_credits *credits = &credits_on_stack; | ||
4186 | |||
4187 | if (open_file->invalidHandle) { | ||
4188 | rc = cifs_reopen_file(open_file, true); | ||
4189 | if (rc == -EAGAIN) | ||
4190 | continue; | ||
4191 | else if (rc) | ||
4192 | break; | ||
4193 | } | ||
4099 | 4194 | ||
4100 | rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize, | 4195 | rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize, |
4101 | &rsize, &credits); | 4196 | &rsize, credits); |
4102 | if (rc) | 4197 | if (rc) |
4103 | break; | 4198 | break; |
4104 | 4199 | ||
@@ -4144,18 +4239,24 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
4144 | rdata->tailsz = PAGE_SIZE; | 4239 | rdata->tailsz = PAGE_SIZE; |
4145 | rdata->read_into_pages = cifs_readpages_read_into_pages; | 4240 | rdata->read_into_pages = cifs_readpages_read_into_pages; |
4146 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; | 4241 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; |
4147 | rdata->credits = credits; | 4242 | rdata->credits = credits_on_stack; |
4148 | 4243 | ||
4149 | list_for_each_entry_safe(page, tpage, &tmplist, lru) { | 4244 | list_for_each_entry_safe(page, tpage, &tmplist, lru) { |
4150 | list_del(&page->lru); | 4245 | list_del(&page->lru); |
4151 | rdata->pages[rdata->nr_pages++] = page; | 4246 | rdata->pages[rdata->nr_pages++] = page; |
4152 | } | 4247 | } |
4153 | 4248 | ||
4154 | if (!rdata->cfile->invalidHandle || | 4249 | rc = adjust_credits(server, &rdata->credits, rdata->bytes); |
4155 | !(rc = cifs_reopen_file(rdata->cfile, true))) | 4250 | |
4156 | rc = server->ops->async_readv(rdata); | 4251 | if (!rc) { |
4252 | if (rdata->cfile->invalidHandle) | ||
4253 | rc = -EAGAIN; | ||
4254 | else | ||
4255 | rc = server->ops->async_readv(rdata); | ||
4256 | } | ||
4257 | |||
4157 | if (rc) { | 4258 | if (rc) { |
4158 | add_credits_and_wake_if(server, rdata->credits, 0); | 4259 | add_credits_and_wake_if(server, &rdata->credits, 0); |
4159 | for (i = 0; i < rdata->nr_pages; i++) { | 4260 | for (i = 0; i < rdata->nr_pages; i++) { |
4160 | page = rdata->pages[i]; | 4261 | page = rdata->pages[i]; |
4161 | lru_cache_add_file(page); | 4262 | lru_cache_add_file(page); |