|
@@ -909,6 +909,7 @@ pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, nfs4_stateid stateid,
|
|
|
status = -ENOMEM;
|
|
|
spin_lock(&ino->i_lock);
|
|
|
lo->plh_block_lgets--;
|
|
|
+ rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq);
|
|
|
spin_unlock(&ino->i_lock);
|
|
|
pnfs_put_layout_hdr(lo);
|
|
|
goto out;
|
|
@@ -926,11 +927,6 @@ pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, nfs4_stateid stateid,
|
|
|
|
|
|
status = nfs4_proc_layoutreturn(lrp, sync);
|
|
|
out:
|
|
|
- if (status) {
|
|
|
- spin_lock(&ino->i_lock);
|
|
|
- clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
|
|
|
- spin_unlock(&ino->i_lock);
|
|
|
- }
|
|
|
dprintk("<-- %s status: %d\n", __func__, status);
|
|
|
return status;
|
|
|
}
|
|
@@ -1028,8 +1024,9 @@ bool pnfs_roc(struct inode *ino)
|
|
|
{
|
|
|
struct pnfs_layout_hdr *lo;
|
|
|
struct pnfs_layout_segment *lseg, *tmp;
|
|
|
+ nfs4_stateid stateid;
|
|
|
LIST_HEAD(tmp_list);
|
|
|
- bool found = false;
|
|
|
+ bool found = false, layoutreturn = false;
|
|
|
|
|
|
spin_lock(&ino->i_lock);
|
|
|
lo = NFS_I(ino)->layout;
|
|
@@ -1050,7 +1047,20 @@ bool pnfs_roc(struct inode *ino)
|
|
|
return true;
|
|
|
|
|
|
out_nolayout:
|
|
|
+ if (lo) {
|
|
|
+ stateid = lo->plh_stateid;
|
|
|
+ layoutreturn =
|
|
|
+ test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
|
|
+ &lo->plh_flags);
|
|
|
+ if (layoutreturn) {
|
|
|
+ lo->plh_block_lgets++;
|
|
|
+ pnfs_get_layout_hdr(lo);
|
|
|
+ }
|
|
|
+ }
|
|
|
spin_unlock(&ino->i_lock);
|
|
|
+ if (layoutreturn)
|
|
|
+ pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, 0,
|
|
|
+ NFS4_MAX_UINT64, true);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -1085,8 +1095,9 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
|
|
|
struct nfs_inode *nfsi = NFS_I(ino);
|
|
|
struct pnfs_layout_hdr *lo;
|
|
|
struct pnfs_layout_segment *lseg;
|
|
|
+ nfs4_stateid stateid;
|
|
|
u32 current_seqid;
|
|
|
- bool found = false;
|
|
|
+ bool found = false, layoutreturn = false;
|
|
|
|
|
|
spin_lock(&ino->i_lock);
|
|
|
list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list)
|
|
@@ -1103,7 +1114,22 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
|
|
|
*/
|
|
|
*barrier = current_seqid + atomic_read(&lo->plh_outstanding);
|
|
|
out:
|
|
|
+ if (!found) {
|
|
|
+ stateid = lo->plh_stateid;
|
|
|
+ layoutreturn =
|
|
|
+ test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
|
|
+ &lo->plh_flags);
|
|
|
+ if (layoutreturn) {
|
|
|
+ lo->plh_block_lgets++;
|
|
|
+ pnfs_get_layout_hdr(lo);
|
|
|
+ }
|
|
|
+ }
|
|
|
spin_unlock(&ino->i_lock);
|
|
|
+ if (layoutreturn) {
|
|
|
+ rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
|
|
|
+ pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, 0,
|
|
|
+ NFS4_MAX_UINT64, false);
|
|
|
+ }
|
|
|
return found;
|
|
|
}
|
|
|
|