summaryrefslogtreecommitdiffstats
path: root/fs/ceph/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r--fs/ceph/inode.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 3acdd3cc6039..761451f36e2d 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1476,7 +1476,8 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
1476 pr_err("fill_inode badness on %p got %d\n", in, rc); 1476 pr_err("fill_inode badness on %p got %d\n", in, rc);
1477 err = rc; 1477 err = rc;
1478 } 1478 }
1479 iput(in); 1479 /* avoid calling iput_final() in mds dispatch threads */
1480 ceph_async_iput(in);
1480 } 1481 }
1481 1482
1482 return err; 1483 return err;
@@ -1674,8 +1675,11 @@ retry_lookup:
1674 &req->r_caps_reservation); 1675 &req->r_caps_reservation);
1675 if (ret < 0) { 1676 if (ret < 0) {
1676 pr_err("fill_inode badness on %p\n", in); 1677 pr_err("fill_inode badness on %p\n", in);
1677 if (d_really_is_negative(dn)) 1678 if (d_really_is_negative(dn)) {
1678 iput(in); 1679 /* avoid calling iput_final() in mds
1680 * dispatch threads */
1681 ceph_async_iput(in);
1682 }
1679 d_drop(dn); 1683 d_drop(dn);
1680 err = ret; 1684 err = ret;
1681 goto next_item; 1685 goto next_item;
@@ -1685,7 +1689,7 @@ retry_lookup:
1685 if (ceph_security_xattr_deadlock(in)) { 1689 if (ceph_security_xattr_deadlock(in)) {
1686 dout(" skip splicing dn %p to inode %p" 1690 dout(" skip splicing dn %p to inode %p"
1687 " (security xattr deadlock)\n", dn, in); 1691 " (security xattr deadlock)\n", dn, in);
1688 iput(in); 1692 ceph_async_iput(in);
1689 skipped++; 1693 skipped++;
1690 goto next_item; 1694 goto next_item;
1691 } 1695 }
@@ -1737,6 +1741,25 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)
1737} 1741}
1738 1742
1739/* 1743/*
1744 * Put reference to inode, but avoid calling iput_final() in current thread.
1745 * iput_final() may wait for reahahead pages. The wait can cause deadlock in
1746 * some contexts.
1747 */
1748void ceph_async_iput(struct inode *inode)
1749{
1750 if (!inode)
1751 return;
1752 for (;;) {
1753 if (atomic_add_unless(&inode->i_count, -1, 1))
1754 break;
1755 if (queue_work(ceph_inode_to_client(inode)->inode_wq,
1756 &ceph_inode(inode)->i_work))
1757 break;
1758 /* queue work failed, i_count must be at least 2 */
1759 }
1760}
1761
1762/*
1740 * Write back inode data in a worker thread. (This can't be done 1763 * Write back inode data in a worker thread. (This can't be done
1741 * in the message handler context.) 1764 * in the message handler context.)
1742 */ 1765 */