Merge tag 'nfs-for-4.16-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:
"Hightlights include the following stable fixes:

- NFS: Fix an incorrect type in struct nfs_direct_req

- pNFS: Prevent the layout header refcount going to zero in
pnfs_roc()

- NFS: Fix unstable write completion"

* tag 'nfs-for-4.16-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
NFS: Fix unstable write completion
pNFS: Prevent the layout header refcount going to zero in pnfs_roc()
NFS: Fix an incorrect type in struct nfs_direct_req

+54 -44
+1 -1
fs/nfs/direct.c
··· 86 86 struct nfs_direct_mirror mirrors[NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX]; 87 87 int mirror_count; 88 88 89 + loff_t io_start; /* Start offset for I/O */ 89 90 ssize_t count, /* bytes actually processed */ 90 91 max_count, /* max expected count */ 91 92 bytes_left, /* bytes left to be sent */ 92 - io_start, /* start of IO */ 93 93 error; /* any reported error */ 94 94 struct completion completion; /* wait for i/o completion */ 95 95
+10 -3
fs/nfs/pnfs.c
··· 292 292 void 293 293 pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) 294 294 { 295 - struct inode *inode = lo->plh_inode; 295 + struct inode *inode; 296 296 297 + if (!lo) 298 + return; 299 + inode = lo->plh_inode; 297 300 pnfs_layoutreturn_before_put_layout_hdr(lo); 298 301 299 302 if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) { ··· 1244 1241 spin_lock(&ino->i_lock); 1245 1242 lo = nfsi->layout; 1246 1243 if (!lo || !pnfs_layout_is_valid(lo) || 1247 - test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) 1244 + test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) { 1245 + lo = NULL; 1248 1246 goto out_noroc; 1247 + } 1248 + pnfs_get_layout_hdr(lo); 1249 1249 if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) { 1250 - pnfs_get_layout_hdr(lo); 1251 1250 spin_unlock(&ino->i_lock); 1252 1251 wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN, 1253 1252 TASK_UNINTERRUPTIBLE); ··· 1317 1312 struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld; 1318 1313 if (ld->prepare_layoutreturn) 1319 1314 ld->prepare_layoutreturn(args); 1315 + pnfs_put_layout_hdr(lo); 1320 1316 return true; 1321 1317 } 1322 1318 if (layoutreturn) 1323 1319 pnfs_send_layoutreturn(lo, &stateid, iomode, true); 1320 + pnfs_put_layout_hdr(lo); 1324 1321 return false; 1325 1322 } 1326 1323
+43 -40
fs/nfs/write.c
··· 1876 1876 return status; 1877 1877 } 1878 1878 1879 - int nfs_commit_inode(struct inode *inode, int how) 1879 + static int __nfs_commit_inode(struct inode *inode, int how, 1880 + struct writeback_control *wbc) 1880 1881 { 1881 1882 LIST_HEAD(head); 1882 1883 struct nfs_commit_info cinfo; 1883 1884 int may_wait = how & FLUSH_SYNC; 1884 - int error = 0; 1885 - int res; 1885 + int ret, nscan; 1886 1886 1887 1887 nfs_init_cinfo_from_inode(&cinfo, inode); 1888 1888 nfs_commit_begin(cinfo.mds); 1889 - res = nfs_scan_commit(inode, &head, &cinfo); 1890 - if (res) 1891 - error = nfs_generic_commit_list(inode, &head, how, &cinfo); 1889 + for (;;) { 1890 + ret = nscan = nfs_scan_commit(inode, &head, &cinfo); 1891 + if (ret <= 0) 1892 + break; 1893 + ret = nfs_generic_commit_list(inode, &head, how, &cinfo); 1894 + if (ret < 0) 1895 + break; 1896 + ret = 0; 1897 + if (wbc && wbc->sync_mode == WB_SYNC_NONE) { 1898 + if (nscan < wbc->nr_to_write) 1899 + wbc->nr_to_write -= nscan; 1900 + else 1901 + wbc->nr_to_write = 0; 1902 + } 1903 + if (nscan < INT_MAX) 1904 + break; 1905 + cond_resched(); 1906 + } 1892 1907 nfs_commit_end(cinfo.mds); 1893 - if (res == 0) 1894 - return res; 1895 - if (error < 0) 1896 - goto out_error; 1897 - if (!may_wait) 1898 - goto out_mark_dirty; 1899 - error = wait_on_commit(cinfo.mds); 1900 - if (error < 0) 1901 - return error; 1902 - return res; 1903 - out_error: 1904 - res = error; 1905 - /* Note: If we exit without ensuring that the commit is complete, 1906 - * we must mark the inode as dirty. Otherwise, future calls to 1907 - * sync_inode() with the WB_SYNC_ALL flag set will fail to ensure 1908 - * that the data is on the disk. 1909 - */ 1910 - out_mark_dirty: 1911 - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 1912 - return res; 1908 + if (ret || !may_wait) 1909 + return ret; 1910 + return wait_on_commit(cinfo.mds); 1911 + } 1912 + 1913 + int nfs_commit_inode(struct inode *inode, int how) 1914 + { 1915 + return __nfs_commit_inode(inode, how, NULL); 1913 1916 } 1914 1917 EXPORT_SYMBOL_GPL(nfs_commit_inode); 1915 1918 ··· 1922 1919 int flags = FLUSH_SYNC; 1923 1920 int ret = 0; 1924 1921 1925 - /* no commits means nothing needs to be done */ 1926 - if (!atomic_long_read(&nfsi->commit_info.ncommit)) 1927 - return ret; 1928 - 1929 1922 if (wbc->sync_mode == WB_SYNC_NONE) { 1923 + /* no commits means nothing needs to be done */ 1924 + if (!atomic_long_read(&nfsi->commit_info.ncommit)) 1925 + goto check_requests_outstanding; 1926 + 1930 1927 /* Don't commit yet if this is a non-blocking flush and there 1931 1928 * are a lot of outstanding writes for this mapping. 1932 1929 */ ··· 1937 1934 flags = 0; 1938 1935 } 1939 1936 1940 - ret = nfs_commit_inode(inode, flags); 1941 - if (ret >= 0) { 1942 - if (wbc->sync_mode == WB_SYNC_NONE) { 1943 - if (ret < wbc->nr_to_write) 1944 - wbc->nr_to_write -= ret; 1945 - else 1946 - wbc->nr_to_write = 0; 1947 - } 1948 - return 0; 1949 - } 1937 + ret = __nfs_commit_inode(inode, flags, wbc); 1938 + if (!ret) { 1939 + if (flags & FLUSH_SYNC) 1940 + return 0; 1941 + } else if (atomic_long_read(&nfsi->commit_info.ncommit)) 1942 + goto out_mark_dirty; 1943 + 1944 + check_requests_outstanding: 1945 + if (!atomic_read(&nfsi->commit_info.rpcs_out)) 1946 + return ret; 1950 1947 out_mark_dirty: 1951 1948 __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 1952 1949 return ret;