Skip to content

Commit c35cac6

Browse files
jtlaytonidryomov
authored andcommitted
ceph: drop private list from remove_session_caps_cb
This function does a lot of list-shuffling with cap flushes, all to avoid possibly freeing a slab allocation under spinlock (which is totally ok). Simplify the code by just detaching and freeing the cap flushes in place. Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent 8006daf commit c35cac6

File tree

1 file changed

+10
-16
lines changed

1 file changed

+10
-16
lines changed

fs/ceph/mds_client.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,6 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
16191619
struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg;
16201620
struct ceph_mds_client *mdsc = fsc->mdsc;
16211621
struct ceph_inode_info *ci = ceph_inode(inode);
1622-
LIST_HEAD(to_remove);
16231622
bool dirty_dropped = false;
16241623
bool invalidate = false;
16251624
int capsnap_release = 0;
@@ -1638,16 +1637,17 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
16381637
mapping_set_error(&inode->i_data, -EIO);
16391638
}
16401639

1640+
spin_lock(&mdsc->cap_dirty_lock);
1641+
1642+
/* trash all of the cap flushes for this inode */
16411643
while (!list_empty(&ci->i_cap_flush_list)) {
16421644
cf = list_first_entry(&ci->i_cap_flush_list,
16431645
struct ceph_cap_flush, i_list);
1644-
list_move(&cf->i_list, &to_remove);
1645-
}
1646-
1647-
spin_lock(&mdsc->cap_dirty_lock);
1648-
1649-
list_for_each_entry(cf, &to_remove, i_list)
16501646
list_del_init(&cf->g_list);
1647+
list_del_init(&cf->i_list);
1648+
if (!cf->is_capsnap)
1649+
ceph_free_cap_flush(cf);
1650+
}
16511651

16521652
if (!list_empty(&ci->i_dirty_item)) {
16531653
pr_warn_ratelimited(
@@ -1690,22 +1690,16 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
16901690
}
16911691

16921692
if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
1693-
list_add(&ci->i_prealloc_cap_flush->i_list, &to_remove);
1693+
cf = ci->i_prealloc_cap_flush;
16941694
ci->i_prealloc_cap_flush = NULL;
1695+
if (!cf->is_capsnap)
1696+
ceph_free_cap_flush(cf);
16951697
}
16961698

16971699
if (!list_empty(&ci->i_cap_snaps))
16981700
capsnap_release = remove_capsnaps(mdsc, inode);
16991701
}
17001702
spin_unlock(&ci->i_ceph_lock);
1701-
while (!list_empty(&to_remove)) {
1702-
struct ceph_cap_flush *cf;
1703-
cf = list_first_entry(&to_remove,
1704-
struct ceph_cap_flush, i_list);
1705-
list_del_init(&cf->i_list);
1706-
if (!cf->is_capsnap)
1707-
ceph_free_cap_flush(cf);
1708-
}
17091703

17101704
wake_up_all(&ci->i_cap_wq);
17111705
if (invalidate)

0 commit comments

Comments
 (0)