Skip to content

Commit fc6eabb

Browse files
committed
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
2 parents 0c8efd6 + c4f24df commit fc6eabb

File tree

3 files changed

+54
-44
lines changed

3 files changed

+54
-44
lines changed

fs/nfs/direct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ struct nfs_direct_req {
8686
struct nfs_direct_mirror mirrors[NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX];
8787
int mirror_count;
8888

89+
loff_t io_start; /* Start offset for I/O */
8990
ssize_t count, /* bytes actually processed */
9091
max_count, /* max expected count */
9192
bytes_left, /* bytes left to be sent */
92-
io_start, /* start of IO */
9393
error; /* any reported error */
9494
struct completion completion; /* wait for i/o completion */
9595

fs/nfs/pnfs.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,11 @@ pnfs_detach_layout_hdr(struct pnfs_layout_hdr *lo)
292292
void
293293
pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
294294
{
295-
struct inode *inode = lo->plh_inode;
295+
struct inode *inode;
296296

297+
if (!lo)
298+
return;
299+
inode = lo->plh_inode;
297300
pnfs_layoutreturn_before_put_layout_hdr(lo);
298301

299302
if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
@@ -1241,10 +1244,12 @@ bool pnfs_roc(struct inode *ino,
12411244
spin_lock(&ino->i_lock);
12421245
lo = nfsi->layout;
12431246
if (!lo || !pnfs_layout_is_valid(lo) ||
1244-
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags))
1247+
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
1248+
lo = NULL;
12451249
goto out_noroc;
1250+
}
1251+
pnfs_get_layout_hdr(lo);
12461252
if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
1247-
pnfs_get_layout_hdr(lo);
12481253
spin_unlock(&ino->i_lock);
12491254
wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
12501255
TASK_UNINTERRUPTIBLE);
@@ -1312,10 +1317,12 @@ bool pnfs_roc(struct inode *ino,
13121317
struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
13131318
if (ld->prepare_layoutreturn)
13141319
ld->prepare_layoutreturn(args);
1320+
pnfs_put_layout_hdr(lo);
13151321
return true;
13161322
}
13171323
if (layoutreturn)
13181324
pnfs_send_layoutreturn(lo, &stateid, iomode, true);
1325+
pnfs_put_layout_hdr(lo);
13191326
return false;
13201327
}
13211328

fs/nfs/write.c

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,40 +1876,43 @@ int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
18761876
return status;
18771877
}
18781878

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)
18801881
{
18811882
LIST_HEAD(head);
18821883
struct nfs_commit_info cinfo;
18831884
int may_wait = how & FLUSH_SYNC;
1884-
int error = 0;
1885-
int res;
1885+
int ret, nscan;
18861886

18871887
nfs_init_cinfo_from_inode(&cinfo, inode);
18881888
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+
}
18921907
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);
19131916
}
19141917
EXPORT_SYMBOL_GPL(nfs_commit_inode);
19151918

@@ -1919,11 +1922,11 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
19191922
int flags = FLUSH_SYNC;
19201923
int ret = 0;
19211924

1922-
/* no commits means nothing needs to be done */
1923-
if (!atomic_long_read(&nfsi->commit_info.ncommit))
1924-
return ret;
1925-
19261925
if (wbc->sync_mode == WB_SYNC_NONE) {
1926+
/* no commits means nothing needs to be done */
1927+
if (!atomic_long_read(&nfsi->commit_info.ncommit))
1928+
goto check_requests_outstanding;
1929+
19271930
/* Don't commit yet if this is a non-blocking flush and there
19281931
* are a lot of outstanding writes for this mapping.
19291932
*/
@@ -1934,16 +1937,16 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
19341937
flags = 0;
19351938
}
19361939

1937-
ret = nfs_commit_inode(inode, flags);
1938-
if (ret >= 0) {
1939-
if (wbc->sync_mode == WB_SYNC_NONE) {
1940-
if (ret < wbc->nr_to_write)
1941-
wbc->nr_to_write -= ret;
1942-
else
1943-
wbc->nr_to_write = 0;
1944-
}
1945-
return 0;
1946-
}
1940+
ret = __nfs_commit_inode(inode, flags, wbc);
1941+
if (!ret) {
1942+
if (flags & FLUSH_SYNC)
1943+
return 0;
1944+
} else if (atomic_long_read(&nfsi->commit_info.ncommit))
1945+
goto out_mark_dirty;
1946+
1947+
check_requests_outstanding:
1948+
if (!atomic_read(&nfsi->commit_info.rpcs_out))
1949+
return ret;
19471950
out_mark_dirty:
19481951
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
19491952
return ret;

0 commit comments

Comments
 (0)