Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c6376eb authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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



Ensure that we hold a reference to the layout header when processing
the pNFS return-on-close so that the refcount value does not inadvertently
go to zero.

Reported-by: default avatarTigran Mkrtchyan <tigran.mkrtchyan@desy.de>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Cc: stable@vger.kernel.org # v4.10+
Tested-by: default avatarTigran Mkrtchyan <tigran.mkrtchyan@desy.de>
parent d9ee6553
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -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;
	if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
	}
	pnfs_get_layout_hdr(lo);
	if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
		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;
}