Skip to content

Commit

Permalink
ceph: eliminate ceph_async_iput()
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Ilya Dryomov <[email protected]>
  • Loading branch information
jtlayton authored and idryomov committed Jun 28, 2021
1 parent 7732fe1 commit 23c2c76
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 69 deletions.
9 changes: 3 additions & 6 deletions fs/ceph/caps.c
Original file line number Diff line number Diff line change
Expand Up @@ -3142,8 +3142,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
if (complete_capsnap)
wake_up_all(&ci->i_cap_wq);
while (put-- > 0) {
/* avoid calling iput_final() in osd dispatch threads */
ceph_async_iput(inode);
iput(inode);
}
}

Expand Down Expand Up @@ -4131,8 +4130,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
mutex_unlock(&session->s_mutex);
done_unlocked:
ceph_put_string(extra_info.pool_ns);
/* avoid calling iput_final() in mds dispatch threads */
ceph_async_iput(inode);
iput(inode);
return;

flush_cap_releases:
Expand Down Expand Up @@ -4174,8 +4172,7 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
spin_unlock(&mdsc->cap_delay_lock);
dout("check_delayed_caps on %p\n", inode);
ceph_check_caps(ci, 0, NULL);
/* avoid calling iput_final() in tick thread */
ceph_async_iput(inode);
iput(inode);
spin_lock(&mdsc->cap_delay_lock);
}
}
Expand Down
28 changes: 3 additions & 25 deletions fs/ceph/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1566,8 +1566,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
unlock_new_inode(in);
}

/* avoid calling iput_final() in mds dispatch threads */
ceph_async_iput(in);
iput(in);
}

return err;
Expand Down Expand Up @@ -1764,13 +1763,11 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
if (ret < 0) {
pr_err("ceph_fill_inode badness on %p\n", in);
if (d_really_is_negative(dn)) {
/* avoid calling iput_final() in mds
* dispatch threads */
if (in->i_state & I_NEW) {
ihold(in);
discard_new_inode(in);
}
ceph_async_iput(in);
iput(in);
}
d_drop(dn);
err = ret;
Expand All @@ -1783,7 +1780,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
if (ceph_security_xattr_deadlock(in)) {
dout(" skip splicing dn %p to inode %p"
" (security xattr deadlock)\n", dn, in);
ceph_async_iput(in);
iput(in);
skipped++;
goto next_item;
}
Expand Down Expand Up @@ -1834,25 +1831,6 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)
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)
{
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
Expand Down
30 changes: 11 additions & 19 deletions fs/ceph/mds_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,14 +824,13 @@ void ceph_mdsc_release_request(struct kref *kref)
ceph_msg_put(req->r_reply);
if (req->r_inode) {
ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
/* avoid calling iput_final() in mds dispatch threads */
ceph_async_iput(req->r_inode);
iput(req->r_inode);
}
if (req->r_parent) {
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)
dput(req->r_dentry);
if (req->r_old_dentry)
Expand All @@ -845,7 +844,7 @@ void ceph_mdsc_release_request(struct kref *kref)
*/
ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir),
CEPH_CAP_PIN);
ceph_async_iput(req->r_old_dentry_dir);
iput(req->r_old_dentry_dir);
}
kfree(req->r_path1);
kfree(req->r_path2);
Expand Down Expand Up @@ -960,8 +959,7 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
}

if (req->r_unsafe_dir) {
/* avoid calling iput_final() in mds dispatch threads */
ceph_async_iput(req->r_unsafe_dir);
iput(req->r_unsafe_dir);
req->r_unsafe_dir = NULL;
}

Expand Down Expand Up @@ -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);
if (!cap) {
spin_unlock(&ci->i_ceph_lock);
ceph_async_iput(inode);
iput(inode);
goto random;
}
mds = cap->session->s_mds;
Expand All @@ -1141,9 +1139,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
cap == ci->i_auth_cap ? "auth " : "", cap);
spin_unlock(&ci->i_ceph_lock);
out:
/* avoid calling iput_final() while holding mdsc->mutex or
* in mds dispatch threads */
ceph_async_iput(inode);
iput(inode);
return mds;

random:
Expand Down Expand Up @@ -1546,9 +1542,7 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session,
spin_unlock(&session->s_cap_lock);

if (last_inode) {
/* avoid calling iput_final() while holding
* s_mutex or in mds dispatch threads */
ceph_async_iput(last_inode);
iput(last_inode);
last_inode = NULL;
}
if (old_cap) {
Expand Down Expand Up @@ -1582,7 +1576,7 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session,
session->s_cap_iterator = NULL;
spin_unlock(&session->s_cap_lock);

ceph_async_iput(last_inode);
iput(last_inode);
if (old_cap)
ceph_put_cap(session->s_mdsc, old_cap);

Expand Down Expand Up @@ -1722,8 +1716,7 @@ static void remove_session_caps(struct ceph_mds_session *session)
spin_unlock(&session->s_cap_lock);

inode = ceph_find_inode(sb, vino);
/* avoid calling iput_final() while holding s_mutex */
ceph_async_iput(inode);
iput(inode);

spin_lock(&session->s_cap_lock);
}
Expand Down Expand Up @@ -4369,8 +4362,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,

out:
mutex_unlock(&session->s_mutex);
/* avoid calling iput_final() in mds dispatch threads */
ceph_async_iput(inode);
iput(inode);
return;

bad:
Expand Down
9 changes: 3 additions & 6 deletions fs/ceph/quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
le64_to_cpu(h->max_files));
spin_unlock(&ci->i_ceph_lock);

/* avoid calling iput_final() in dispatch thread */
ceph_async_iput(inode);
iput(inode);
}

static struct ceph_quotarealm_inode *
Expand Down Expand Up @@ -247,8 +246,7 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,

ci = ceph_inode(in);
has_quota = __ceph_has_any_quota(ci);
/* avoid calling iput_final() while holding mdsc->snap_rwsem */
ceph_async_iput(in);
iput(in);

next = realm->parent;
if (has_quota || !next)
Expand Down Expand Up @@ -383,8 +381,7 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
pr_warn("Invalid quota check op (%d)\n", op);
exceeded = true; /* Just break the loop */
}
/* avoid calling iput_final() while holding mdsc->snap_rwsem */
ceph_async_iput(in);
iput(in);

next = realm->parent;
if (exceeded || !next)
Expand Down
16 changes: 5 additions & 11 deletions fs/ceph/snap.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,15 +677,13 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
if (!inode)
continue;
spin_unlock(&realm->inodes_with_caps_lock);
/* avoid calling iput_final() while holding
* mdsc->snap_rwsem or in mds dispatch threads */
ceph_async_iput(lastinode);
iput(lastinode);
lastinode = inode;
ceph_queue_cap_snap(ci);
spin_lock(&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);
}
Expand Down Expand Up @@ -839,9 +837,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
ihold(inode);
spin_unlock(&mdsc->snap_flush_lock);
ceph_flush_snaps(ci, &session);
/* avoid calling iput_final() while holding
* session->s_mutex or in mds dispatch threads */
ceph_async_iput(inode);
iput(inode);
spin_lock(&mdsc->snap_flush_lock);
}
spin_unlock(&mdsc->snap_flush_lock);
Expand Down Expand Up @@ -982,14 +978,12 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
ceph_get_snap_realm(mdsc, realm);
ceph_put_snap_realm(mdsc, oldrealm);

/* avoid calling iput_final() while holding
* mdsc->snap_rwsem or mds in dispatch threads */
ceph_async_iput(inode);
iput(inode);
continue;

skip_inode:
spin_unlock(&ci->i_ceph_lock);
ceph_async_iput(inode);
iput(inode);
}

/* we may have taken some of the old realm's children. */
Expand Down
2 changes: 0 additions & 2 deletions fs/ceph/super.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 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);

static inline void ceph_queue_vmtruncate(struct inode *inode)
Expand Down

0 comments on commit 23c2c76

Please sign in to comment.