mirror of https://gitee.com/openkylin/linux.git
NFS client bugfixes for Linux 4.16
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 -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJaprb9AAoJEGcL54qWCgDysK0P/Rwyc7fhcs4CvxETQT0LhbbB P6XDAb5pBeU+ca8ZWzqlpe1uKc0z5ykuTLuxLt2QvSb9+6h+8T1gxOa5SibehnwY 6UizLDgHMuY2V4wqm4XLHiZX7J0Evdo4rgNCp7qq2/TinBPYKQsqIz34+s9BZDti 6LG6WiVhOtkhs6s/sRbAn+FfMbSiQn54iQIgFPeO+3zEzaaLzUZqlVHO5yjxVnxh 6oYGkEPVzP09URUO/HJ1VTUZJnso1/axEcH9qhuJzZ+pANCpuBjSMoFzzE6oI2mD dfD8UJZjwqLb7AsFhgSQUrDXzaI0Xg7ccrImtCp4QLlTjja3TlOYMYbK9kDRHC1/ kT93cSFSIeSGpqLVSdNyiz7pCh2Cps2U0JTbhwE0R1NEskWQPzSwY73jEwiA/bex JOZBxtjVZt8TgOKHxPO65rvQwaq3T31KrQSDLqv3JReI0epJeqng0h+pwiZluNAs TFjE1aP0l567A3qQnPrHrGZ4IIs8XYobZ+MBxf9x5PaRWnGoPUkhHXMP2j8JCnwa ofPBR4Mx5WhnsB7Z5vsYetHtmD99QbJ0+WH9ObilUFt6gUgXoXCrvexIUq+LD3DP HIIqfbSorAIlQxtCwEz7m85B7VEKByaCWj8OiFt5VVAreEhiazmsncsyh8R5fa88 wJDxRe3QmNu7BEJ9NJKi =IQGX -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
fc6eabbbf8
|
@ -86,10 +86,10 @@ struct nfs_direct_req {
|
|||
struct nfs_direct_mirror mirrors[NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX];
|
||||
int mirror_count;
|
||||
|
||||
loff_t io_start; /* Start offset for I/O */
|
||||
ssize_t count, /* bytes actually processed */
|
||||
max_count, /* max expected count */
|
||||
bytes_left, /* bytes left to be sent */
|
||||
io_start, /* start of IO */
|
||||
error; /* any reported error */
|
||||
struct completion completion; /* wait for i/o completion */
|
||||
|
||||
|
|
|
@ -292,8 +292,11 @@ pnfs_detach_layout_hdr(struct pnfs_layout_hdr *lo)
|
|||
void
|
||||
pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
|
||||
{
|
||||
struct inode *inode = lo->plh_inode;
|
||||
struct inode *inode;
|
||||
|
||||
if (!lo)
|
||||
return;
|
||||
inode = lo->plh_inode;
|
||||
pnfs_layoutreturn_before_put_layout_hdr(lo);
|
||||
|
||||
if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
|
||||
|
@ -1241,10 +1244,12 @@ bool pnfs_roc(struct inode *ino,
|
|||
spin_lock(&ino->i_lock);
|
||||
lo = nfsi->layout;
|
||||
if (!lo || !pnfs_layout_is_valid(lo) ||
|
||||
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags))
|
||||
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
|
||||
lo = NULL;
|
||||
goto out_noroc;
|
||||
}
|
||||
pnfs_get_layout_hdr(lo);
|
||||
if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
|
||||
pnfs_get_layout_hdr(lo);
|
||||
spin_unlock(&ino->i_lock);
|
||||
wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
|
@ -1312,10 +1317,12 @@ bool pnfs_roc(struct inode *ino,
|
|||
struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
|
||||
if (ld->prepare_layoutreturn)
|
||||
ld->prepare_layoutreturn(args);
|
||||
pnfs_put_layout_hdr(lo);
|
||||
return true;
|
||||
}
|
||||
if (layoutreturn)
|
||||
pnfs_send_layoutreturn(lo, &stateid, iomode, true);
|
||||
pnfs_put_layout_hdr(lo);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1876,40 +1876,43 @@ int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
|
|||
return status;
|
||||
}
|
||||
|
||||
int nfs_commit_inode(struct inode *inode, int how)
|
||||
static int __nfs_commit_inode(struct inode *inode, int how,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
LIST_HEAD(head);
|
||||
struct nfs_commit_info cinfo;
|
||||
int may_wait = how & FLUSH_SYNC;
|
||||
int error = 0;
|
||||
int res;
|
||||
int ret, nscan;
|
||||
|
||||
nfs_init_cinfo_from_inode(&cinfo, inode);
|
||||
nfs_commit_begin(cinfo.mds);
|
||||
res = nfs_scan_commit(inode, &head, &cinfo);
|
||||
if (res)
|
||||
error = nfs_generic_commit_list(inode, &head, how, &cinfo);
|
||||
for (;;) {
|
||||
ret = nscan = nfs_scan_commit(inode, &head, &cinfo);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = nfs_generic_commit_list(inode, &head, how, &cinfo);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret = 0;
|
||||
if (wbc && wbc->sync_mode == WB_SYNC_NONE) {
|
||||
if (nscan < wbc->nr_to_write)
|
||||
wbc->nr_to_write -= nscan;
|
||||
else
|
||||
wbc->nr_to_write = 0;
|
||||
}
|
||||
if (nscan < INT_MAX)
|
||||
break;
|
||||
cond_resched();
|
||||
}
|
||||
nfs_commit_end(cinfo.mds);
|
||||
if (res == 0)
|
||||
return res;
|
||||
if (error < 0)
|
||||
goto out_error;
|
||||
if (!may_wait)
|
||||
goto out_mark_dirty;
|
||||
error = wait_on_commit(cinfo.mds);
|
||||
if (error < 0)
|
||||
return error;
|
||||
return res;
|
||||
out_error:
|
||||
res = error;
|
||||
/* Note: If we exit without ensuring that the commit is complete,
|
||||
* we must mark the inode as dirty. Otherwise, future calls to
|
||||
* sync_inode() with the WB_SYNC_ALL flag set will fail to ensure
|
||||
* that the data is on the disk.
|
||||
*/
|
||||
out_mark_dirty:
|
||||
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
|
||||
return res;
|
||||
if (ret || !may_wait)
|
||||
return ret;
|
||||
return wait_on_commit(cinfo.mds);
|
||||
}
|
||||
|
||||
int nfs_commit_inode(struct inode *inode, int how)
|
||||
{
|
||||
return __nfs_commit_inode(inode, how, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_commit_inode);
|
||||
|
||||
|
@ -1919,11 +1922,11 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
|||
int flags = FLUSH_SYNC;
|
||||
int ret = 0;
|
||||
|
||||
/* no commits means nothing needs to be done */
|
||||
if (!atomic_long_read(&nfsi->commit_info.ncommit))
|
||||
return ret;
|
||||
|
||||
if (wbc->sync_mode == WB_SYNC_NONE) {
|
||||
/* no commits means nothing needs to be done */
|
||||
if (!atomic_long_read(&nfsi->commit_info.ncommit))
|
||||
goto check_requests_outstanding;
|
||||
|
||||
/* Don't commit yet if this is a non-blocking flush and there
|
||||
* are a lot of outstanding writes for this mapping.
|
||||
*/
|
||||
|
@ -1934,16 +1937,16 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
|||
flags = 0;
|
||||
}
|
||||
|
||||
ret = nfs_commit_inode(inode, flags);
|
||||
if (ret >= 0) {
|
||||
if (wbc->sync_mode == WB_SYNC_NONE) {
|
||||
if (ret < wbc->nr_to_write)
|
||||
wbc->nr_to_write -= ret;
|
||||
else
|
||||
wbc->nr_to_write = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ret = __nfs_commit_inode(inode, flags, wbc);
|
||||
if (!ret) {
|
||||
if (flags & FLUSH_SYNC)
|
||||
return 0;
|
||||
} else if (atomic_long_read(&nfsi->commit_info.ncommit))
|
||||
goto out_mark_dirty;
|
||||
|
||||
check_requests_outstanding:
|
||||
if (!atomic_read(&nfsi->commit_info.rpcs_out))
|
||||
return ret;
|
||||
out_mark_dirty:
|
||||
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue