diff options
author | Pavel Shilovsky <pshilov@microsoft.com> | 2019-01-29 15:15:11 -0500 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-03-05 19:10:04 -0500 |
commit | fe768d51c832ebde70a83221b0633dc7bc9640a6 (patch) | |
tree | 06304ab7a40e0372eb79a3af3014e59c4eadc4d0 /fs/cifs/file.c | |
parent | c4b8f657d55b4ed60cb0a2187e940706de23f2b2 (diff) |
CIFS: Return error code when getting file handle for writeback
Now we just return NULL cifsFileInfo pointer in cases we didn't find
or couldn't reopen a file. This hides errors from cifs_reopen_file()
especially retryable errors which should be handled appropriately.
Create new cifs_get_writable_file() routine that returns error codes
from cifs_reopen_file() and use it in the writeback codepath.
Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 90 |
1 files changed, 61 insertions, 29 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8d5fec497792..9b53f33137b3 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); |
@@ -2144,11 +2167,16 @@ retry: | |||
2144 | pgoff_t next = 0, tofind, saved_index = index; | 2167 | pgoff_t next = 0, tofind, saved_index = index; |
2145 | struct cifs_credits credits_on_stack; | 2168 | struct cifs_credits credits_on_stack; |
2146 | struct cifs_credits *credits = &credits_on_stack; | 2169 | struct cifs_credits *credits = &credits_on_stack; |
2170 | int get_file_rc = 0; | ||
2147 | 2171 | ||
2148 | if (cfile) | 2172 | if (cfile) |
2149 | cifsFileInfo_put(cfile); | 2173 | cifsFileInfo_put(cfile); |
2150 | 2174 | ||
2151 | cfile = find_writable_file(CIFS_I(inode), false); | 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; | ||
2152 | 2180 | ||
2153 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, | 2181 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, |
2154 | &wsize, credits); | 2182 | &wsize, credits); |
@@ -2189,8 +2217,12 @@ retry: | |||
2189 | cfile = NULL; | 2217 | cfile = NULL; |
2190 | 2218 | ||
2191 | if (!wdata->cfile) { | 2219 | if (!wdata->cfile) { |
2192 | cifs_dbg(VFS, "No writable handle in writepages\n"); | 2220 | cifs_dbg(VFS, "No writable handle in writepages rc=%d\n", |
2193 | rc = -EBADF; | 2221 | get_file_rc); |
2222 | if (is_retryable_error(get_file_rc)) | ||
2223 | rc = get_file_rc; | ||
2224 | else | ||
2225 | rc = -EBADF; | ||
2194 | } else | 2226 | } else |
2195 | rc = wdata_send_pages(wdata, nr_pages, mapping, wbc); | 2227 | rc = wdata_send_pages(wdata, nr_pages, mapping, wbc); |
2196 | 2228 | ||