ceph: eliminate ceph_async_iput()
Now that we don't need to hold session->s_mutex or the snap_rwsem when calling ceph_check_caps, we can eliminate ceph_async_iput and just use normal iput calls. Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
7732fe168e
commit
23c2c76ead
@ -3142,8 +3142,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
|
|||||||
if (complete_capsnap)
|
if (complete_capsnap)
|
||||||
wake_up_all(&ci->i_cap_wq);
|
wake_up_all(&ci->i_cap_wq);
|
||||||
while (put-- > 0) {
|
while (put-- > 0) {
|
||||||
/* avoid calling iput_final() in osd dispatch threads */
|
iput(inode);
|
||||||
ceph_async_iput(inode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4131,8 +4130,7 @@ done:
|
|||||||
mutex_unlock(&session->s_mutex);
|
mutex_unlock(&session->s_mutex);
|
||||||
done_unlocked:
|
done_unlocked:
|
||||||
ceph_put_string(extra_info.pool_ns);
|
ceph_put_string(extra_info.pool_ns);
|
||||||
/* avoid calling iput_final() in mds dispatch threads */
|
iput(inode);
|
||||||
ceph_async_iput(inode);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flush_cap_releases:
|
flush_cap_releases:
|
||||||
@ -4174,8 +4172,7 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
|
|||||||
spin_unlock(&mdsc->cap_delay_lock);
|
spin_unlock(&mdsc->cap_delay_lock);
|
||||||
dout("check_delayed_caps on %p\n", inode);
|
dout("check_delayed_caps on %p\n", inode);
|
||||||
ceph_check_caps(ci, 0, NULL);
|
ceph_check_caps(ci, 0, NULL);
|
||||||
/* avoid calling iput_final() in tick thread */
|
iput(inode);
|
||||||
ceph_async_iput(inode);
|
|
||||||
spin_lock(&mdsc->cap_delay_lock);
|
spin_lock(&mdsc->cap_delay_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1566,8 +1566,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
|
|||||||
unlock_new_inode(in);
|
unlock_new_inode(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* avoid calling iput_final() in mds dispatch threads */
|
iput(in);
|
||||||
ceph_async_iput(in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -1764,13 +1763,11 @@ retry_lookup:
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("ceph_fill_inode badness on %p\n", in);
|
pr_err("ceph_fill_inode badness on %p\n", in);
|
||||||
if (d_really_is_negative(dn)) {
|
if (d_really_is_negative(dn)) {
|
||||||
/* avoid calling iput_final() in mds
|
|
||||||
* dispatch threads */
|
|
||||||
if (in->i_state & I_NEW) {
|
if (in->i_state & I_NEW) {
|
||||||
ihold(in);
|
ihold(in);
|
||||||
discard_new_inode(in);
|
discard_new_inode(in);
|
||||||
}
|
}
|
||||||
ceph_async_iput(in);
|
iput(in);
|
||||||
}
|
}
|
||||||
d_drop(dn);
|
d_drop(dn);
|
||||||
err = ret;
|
err = ret;
|
||||||
@ -1783,7 +1780,7 @@ retry_lookup:
|
|||||||
if (ceph_security_xattr_deadlock(in)) {
|
if (ceph_security_xattr_deadlock(in)) {
|
||||||
dout(" skip splicing dn %p to inode %p"
|
dout(" skip splicing dn %p to inode %p"
|
||||||
" (security xattr deadlock)\n", dn, in);
|
" (security xattr deadlock)\n", dn, in);
|
||||||
ceph_async_iput(in);
|
iput(in);
|
||||||
skipped++;
|
skipped++;
|
||||||
goto next_item;
|
goto next_item;
|
||||||
}
|
}
|
||||||
@ -1834,25 +1831,6 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Put reference to inode, but avoid calling iput_final() in current thread.
|
|
||||||
* iput_final() may wait for reahahead pages. The wait can cause deadlock in
|
|
||||||
* some contexts.
|
|
||||||
*/
|
|
||||||
void ceph_async_iput(struct inode *inode)
|
|
||||||
{
|
|
||||||
if (!inode)
|
|
||||||
return;
|
|
||||||
for (;;) {
|
|
||||||
if (atomic_add_unless(&inode->i_count, -1, 1))
|
|
||||||
break;
|
|
||||||
if (queue_work(ceph_inode_to_client(inode)->inode_wq,
|
|
||||||
&ceph_inode(inode)->i_work))
|
|
||||||
break;
|
|
||||||
/* queue work failed, i_count must be at least 2 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ceph_queue_inode_work(struct inode *inode, int work_bit)
|
void ceph_queue_inode_work(struct inode *inode, int work_bit)
|
||||||
{
|
{
|
||||||
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
|
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
|
||||||
|
@ -824,14 +824,13 @@ void ceph_mdsc_release_request(struct kref *kref)
|
|||||||
ceph_msg_put(req->r_reply);
|
ceph_msg_put(req->r_reply);
|
||||||
if (req->r_inode) {
|
if (req->r_inode) {
|
||||||
ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
|
ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
|
||||||
/* avoid calling iput_final() in mds dispatch threads */
|
iput(req->r_inode);
|
||||||
ceph_async_iput(req->r_inode);
|
|
||||||
}
|
}
|
||||||
if (req->r_parent) {
|
if (req->r_parent) {
|
||||||
ceph_put_cap_refs(ceph_inode(req->r_parent), CEPH_CAP_PIN);
|
ceph_put_cap_refs(ceph_inode(req->r_parent), CEPH_CAP_PIN);
|
||||||
ceph_async_iput(req->r_parent);
|
iput(req->r_parent);
|
||||||
}
|
}
|
||||||
ceph_async_iput(req->r_target_inode);
|
iput(req->r_target_inode);
|
||||||
if (req->r_dentry)
|
if (req->r_dentry)
|
||||||
dput(req->r_dentry);
|
dput(req->r_dentry);
|
||||||
if (req->r_old_dentry)
|
if (req->r_old_dentry)
|
||||||
@ -845,7 +844,7 @@ void ceph_mdsc_release_request(struct kref *kref)
|
|||||||
*/
|
*/
|
||||||
ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir),
|
ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir),
|
||||||
CEPH_CAP_PIN);
|
CEPH_CAP_PIN);
|
||||||
ceph_async_iput(req->r_old_dentry_dir);
|
iput(req->r_old_dentry_dir);
|
||||||
}
|
}
|
||||||
kfree(req->r_path1);
|
kfree(req->r_path1);
|
||||||
kfree(req->r_path2);
|
kfree(req->r_path2);
|
||||||
@ -960,8 +959,7 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req->r_unsafe_dir) {
|
if (req->r_unsafe_dir) {
|
||||||
/* avoid calling iput_final() in mds dispatch threads */
|
iput(req->r_unsafe_dir);
|
||||||
ceph_async_iput(req->r_unsafe_dir);
|
|
||||||
req->r_unsafe_dir = NULL;
|
req->r_unsafe_dir = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1132,7 +1130,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
|
|||||||
cap = rb_entry(rb_first(&ci->i_caps), struct ceph_cap, ci_node);
|
cap = rb_entry(rb_first(&ci->i_caps), struct ceph_cap, ci_node);
|
||||||
if (!cap) {
|
if (!cap) {
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
ceph_async_iput(inode);
|
iput(inode);
|
||||||
goto random;
|
goto random;
|
||||||
}
|
}
|
||||||
mds = cap->session->s_mds;
|
mds = cap->session->s_mds;
|
||||||
@ -1141,9 +1139,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
|
|||||||
cap == ci->i_auth_cap ? "auth " : "", cap);
|
cap == ci->i_auth_cap ? "auth " : "", cap);
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
out:
|
out:
|
||||||
/* avoid calling iput_final() while holding mdsc->mutex or
|
iput(inode);
|
||||||
* in mds dispatch threads */
|
|
||||||
ceph_async_iput(inode);
|
|
||||||
return mds;
|
return mds;
|
||||||
|
|
||||||
random:
|
random:
|
||||||
@ -1546,9 +1542,7 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session,
|
|||||||
spin_unlock(&session->s_cap_lock);
|
spin_unlock(&session->s_cap_lock);
|
||||||
|
|
||||||
if (last_inode) {
|
if (last_inode) {
|
||||||
/* avoid calling iput_final() while holding
|
iput(last_inode);
|
||||||
* s_mutex or in mds dispatch threads */
|
|
||||||
ceph_async_iput(last_inode);
|
|
||||||
last_inode = NULL;
|
last_inode = NULL;
|
||||||
}
|
}
|
||||||
if (old_cap) {
|
if (old_cap) {
|
||||||
@ -1582,7 +1576,7 @@ out:
|
|||||||
session->s_cap_iterator = NULL;
|
session->s_cap_iterator = NULL;
|
||||||
spin_unlock(&session->s_cap_lock);
|
spin_unlock(&session->s_cap_lock);
|
||||||
|
|
||||||
ceph_async_iput(last_inode);
|
iput(last_inode);
|
||||||
if (old_cap)
|
if (old_cap)
|
||||||
ceph_put_cap(session->s_mdsc, old_cap);
|
ceph_put_cap(session->s_mdsc, old_cap);
|
||||||
|
|
||||||
@ -1722,8 +1716,7 @@ static void remove_session_caps(struct ceph_mds_session *session)
|
|||||||
spin_unlock(&session->s_cap_lock);
|
spin_unlock(&session->s_cap_lock);
|
||||||
|
|
||||||
inode = ceph_find_inode(sb, vino);
|
inode = ceph_find_inode(sb, vino);
|
||||||
/* avoid calling iput_final() while holding s_mutex */
|
iput(inode);
|
||||||
ceph_async_iput(inode);
|
|
||||||
|
|
||||||
spin_lock(&session->s_cap_lock);
|
spin_lock(&session->s_cap_lock);
|
||||||
}
|
}
|
||||||
@ -4369,8 +4362,7 @@ release:
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&session->s_mutex);
|
mutex_unlock(&session->s_mutex);
|
||||||
/* avoid calling iput_final() in mds dispatch threads */
|
iput(inode);
|
||||||
ceph_async_iput(inode);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
|
@ -74,8 +74,7 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
|
|||||||
le64_to_cpu(h->max_files));
|
le64_to_cpu(h->max_files));
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
/* avoid calling iput_final() in dispatch thread */
|
iput(inode);
|
||||||
ceph_async_iput(inode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ceph_quotarealm_inode *
|
static struct ceph_quotarealm_inode *
|
||||||
@ -247,8 +246,7 @@ restart:
|
|||||||
|
|
||||||
ci = ceph_inode(in);
|
ci = ceph_inode(in);
|
||||||
has_quota = __ceph_has_any_quota(ci);
|
has_quota = __ceph_has_any_quota(ci);
|
||||||
/* avoid calling iput_final() while holding mdsc->snap_rwsem */
|
iput(in);
|
||||||
ceph_async_iput(in);
|
|
||||||
|
|
||||||
next = realm->parent;
|
next = realm->parent;
|
||||||
if (has_quota || !next)
|
if (has_quota || !next)
|
||||||
@ -383,8 +381,7 @@ restart:
|
|||||||
pr_warn("Invalid quota check op (%d)\n", op);
|
pr_warn("Invalid quota check op (%d)\n", op);
|
||||||
exceeded = true; /* Just break the loop */
|
exceeded = true; /* Just break the loop */
|
||||||
}
|
}
|
||||||
/* avoid calling iput_final() while holding mdsc->snap_rwsem */
|
iput(in);
|
||||||
ceph_async_iput(in);
|
|
||||||
|
|
||||||
next = realm->parent;
|
next = realm->parent;
|
||||||
if (exceeded || !next)
|
if (exceeded || !next)
|
||||||
|
@ -677,15 +677,13 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
|
|||||||
if (!inode)
|
if (!inode)
|
||||||
continue;
|
continue;
|
||||||
spin_unlock(&realm->inodes_with_caps_lock);
|
spin_unlock(&realm->inodes_with_caps_lock);
|
||||||
/* avoid calling iput_final() while holding
|
iput(lastinode);
|
||||||
* mdsc->snap_rwsem or in mds dispatch threads */
|
|
||||||
ceph_async_iput(lastinode);
|
|
||||||
lastinode = inode;
|
lastinode = inode;
|
||||||
ceph_queue_cap_snap(ci);
|
ceph_queue_cap_snap(ci);
|
||||||
spin_lock(&realm->inodes_with_caps_lock);
|
spin_lock(&realm->inodes_with_caps_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&realm->inodes_with_caps_lock);
|
spin_unlock(&realm->inodes_with_caps_lock);
|
||||||
ceph_async_iput(lastinode);
|
iput(lastinode);
|
||||||
|
|
||||||
dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
|
dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
|
||||||
}
|
}
|
||||||
@ -839,9 +837,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
|
|||||||
ihold(inode);
|
ihold(inode);
|
||||||
spin_unlock(&mdsc->snap_flush_lock);
|
spin_unlock(&mdsc->snap_flush_lock);
|
||||||
ceph_flush_snaps(ci, &session);
|
ceph_flush_snaps(ci, &session);
|
||||||
/* avoid calling iput_final() while holding
|
iput(inode);
|
||||||
* session->s_mutex or in mds dispatch threads */
|
|
||||||
ceph_async_iput(inode);
|
|
||||||
spin_lock(&mdsc->snap_flush_lock);
|
spin_lock(&mdsc->snap_flush_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&mdsc->snap_flush_lock);
|
spin_unlock(&mdsc->snap_flush_lock);
|
||||||
@ -982,14 +978,12 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
|
|||||||
ceph_get_snap_realm(mdsc, realm);
|
ceph_get_snap_realm(mdsc, realm);
|
||||||
ceph_put_snap_realm(mdsc, oldrealm);
|
ceph_put_snap_realm(mdsc, oldrealm);
|
||||||
|
|
||||||
/* avoid calling iput_final() while holding
|
iput(inode);
|
||||||
* mdsc->snap_rwsem or mds in dispatch threads */
|
|
||||||
ceph_async_iput(inode);
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
skip_inode:
|
skip_inode:
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
ceph_async_iput(inode);
|
iput(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we may have taken some of the old realm's children. */
|
/* we may have taken some of the old realm's children. */
|
||||||
|
@ -988,8 +988,6 @@ extern int ceph_inode_holds_cap(struct inode *inode, int mask);
|
|||||||
extern bool ceph_inode_set_size(struct inode *inode, loff_t size);
|
extern bool ceph_inode_set_size(struct inode *inode, loff_t size);
|
||||||
extern void __ceph_do_pending_vmtruncate(struct inode *inode);
|
extern void __ceph_do_pending_vmtruncate(struct inode *inode);
|
||||||
|
|
||||||
extern void ceph_async_iput(struct inode *inode);
|
|
||||||
|
|
||||||
void ceph_queue_inode_work(struct inode *inode, int work_bit);
|
void ceph_queue_inode_work(struct inode *inode, int work_bit);
|
||||||
|
|
||||||
static inline void ceph_queue_vmtruncate(struct inode *inode)
|
static inline void ceph_queue_vmtruncate(struct inode *inode)
|
||||||
|
Loading…
Reference in New Issue
Block a user