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: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Cc: stable@vger.kernel.org # v4.10+ Tested-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
This commit is contained in:
parent
d9ee65539d
commit
9c6376ebdd
1 changed files with 10 additions and 3 deletions
|
@ -292,8 +292,11 @@ pnfs_detach_layout_hdr(struct pnfs_layout_hdr *lo)
|
||||||
void
|
void
|
||||||
pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
|
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);
|
pnfs_layoutreturn_before_put_layout_hdr(lo);
|
||||||
|
|
||||||
if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
|
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);
|
spin_lock(&ino->i_lock);
|
||||||
lo = nfsi->layout;
|
lo = nfsi->layout;
|
||||||
if (!lo || !pnfs_layout_is_valid(lo) ||
|
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;
|
goto out_noroc;
|
||||||
|
}
|
||||||
|
pnfs_get_layout_hdr(lo);
|
||||||
if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
|
if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
|
||||||
pnfs_get_layout_hdr(lo);
|
|
||||||
spin_unlock(&ino->i_lock);
|
spin_unlock(&ino->i_lock);
|
||||||
wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
|
wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
|
||||||
TASK_UNINTERRUPTIBLE);
|
TASK_UNINTERRUPTIBLE);
|
||||||
|
@ -1312,10 +1317,12 @@ bool pnfs_roc(struct inode *ino,
|
||||||
struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
|
struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
|
||||||
if (ld->prepare_layoutreturn)
|
if (ld->prepare_layoutreturn)
|
||||||
ld->prepare_layoutreturn(args);
|
ld->prepare_layoutreturn(args);
|
||||||
|
pnfs_put_layout_hdr(lo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (layoutreturn)
|
if (layoutreturn)
|
||||||
pnfs_send_layoutreturn(lo, &stateid, iomode, true);
|
pnfs_send_layoutreturn(lo, &stateid, iomode, true);
|
||||||
|
pnfs_put_layout_hdr(lo);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue