Skip to content

Commit 36e6da9

Browse files
jtlaytonidryomov
authored andcommitted
ceph: refactor remove_session_caps_cb
Move remove_capsnaps to caps.c. Move the part of remove_session_caps_cb under i_ceph_lock into a separate function that lives in caps.c. Have remove_session_caps_cb call the new helper after taking the lock. Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent 3c30502 commit 36e6da9

File tree

3 files changed

+120
-105
lines changed

3 files changed

+120
-105
lines changed

fs/ceph/caps.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4561,3 +4561,119 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
45614561
spin_unlock(&dentry->d_lock);
45624562
return ret;
45634563
}
4564+
4565+
static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
4566+
{
4567+
struct ceph_inode_info *ci = ceph_inode(inode);
4568+
struct ceph_cap_snap *capsnap;
4569+
int capsnap_release = 0;
4570+
4571+
lockdep_assert_held(&ci->i_ceph_lock);
4572+
4573+
dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
4574+
4575+
while (!list_empty(&ci->i_cap_snaps)) {
4576+
capsnap = list_first_entry(&ci->i_cap_snaps,
4577+
struct ceph_cap_snap, ci_item);
4578+
__ceph_remove_capsnap(inode, capsnap, NULL, NULL);
4579+
ceph_put_snap_context(capsnap->context);
4580+
ceph_put_cap_snap(capsnap);
4581+
capsnap_release++;
4582+
}
4583+
wake_up_all(&ci->i_cap_wq);
4584+
wake_up_all(&mdsc->cap_flushing_wq);
4585+
return capsnap_release;
4586+
}
4587+
4588+
int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate)
4589+
{
4590+
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
4591+
struct ceph_mds_client *mdsc = fsc->mdsc;
4592+
struct ceph_inode_info *ci = ceph_inode(inode);
4593+
bool is_auth;
4594+
bool dirty_dropped = false;
4595+
int iputs = 0;
4596+
4597+
lockdep_assert_held(&ci->i_ceph_lock);
4598+
4599+
dout("removing cap %p, ci is %p, inode is %p\n",
4600+
cap, ci, &ci->vfs_inode);
4601+
4602+
is_auth = (cap == ci->i_auth_cap);
4603+
__ceph_remove_cap(cap, false);
4604+
if (is_auth) {
4605+
struct ceph_cap_flush *cf;
4606+
4607+
if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {
4608+
if (inode->i_data.nrpages > 0)
4609+
*invalidate = true;
4610+
if (ci->i_wrbuffer_ref > 0)
4611+
mapping_set_error(&inode->i_data, -EIO);
4612+
}
4613+
4614+
spin_lock(&mdsc->cap_dirty_lock);
4615+
4616+
/* trash all of the cap flushes for this inode */
4617+
while (!list_empty(&ci->i_cap_flush_list)) {
4618+
cf = list_first_entry(&ci->i_cap_flush_list,
4619+
struct ceph_cap_flush, i_list);
4620+
list_del_init(&cf->g_list);
4621+
list_del_init(&cf->i_list);
4622+
if (!cf->is_capsnap)
4623+
ceph_free_cap_flush(cf);
4624+
}
4625+
4626+
if (!list_empty(&ci->i_dirty_item)) {
4627+
pr_warn_ratelimited(
4628+
" dropping dirty %s state for %p %lld\n",
4629+
ceph_cap_string(ci->i_dirty_caps),
4630+
inode, ceph_ino(inode));
4631+
ci->i_dirty_caps = 0;
4632+
list_del_init(&ci->i_dirty_item);
4633+
dirty_dropped = true;
4634+
}
4635+
if (!list_empty(&ci->i_flushing_item)) {
4636+
pr_warn_ratelimited(
4637+
" dropping dirty+flushing %s state for %p %lld\n",
4638+
ceph_cap_string(ci->i_flushing_caps),
4639+
inode, ceph_ino(inode));
4640+
ci->i_flushing_caps = 0;
4641+
list_del_init(&ci->i_flushing_item);
4642+
mdsc->num_cap_flushing--;
4643+
dirty_dropped = true;
4644+
}
4645+
spin_unlock(&mdsc->cap_dirty_lock);
4646+
4647+
if (dirty_dropped) {
4648+
mapping_set_error(inode->i_mapping, -EIO);
4649+
4650+
if (ci->i_wrbuffer_ref_head == 0 &&
4651+
ci->i_wr_ref == 0 &&
4652+
ci->i_dirty_caps == 0 &&
4653+
ci->i_flushing_caps == 0) {
4654+
ceph_put_snap_context(ci->i_head_snapc);
4655+
ci->i_head_snapc = NULL;
4656+
}
4657+
}
4658+
4659+
if (atomic_read(&ci->i_filelock_ref) > 0) {
4660+
/* make further file lock syscall return -EIO */
4661+
ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
4662+
pr_warn_ratelimited(" dropping file locks for %p %lld\n",
4663+
inode, ceph_ino(inode));
4664+
}
4665+
4666+
if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
4667+
cf = ci->i_prealloc_cap_flush;
4668+
ci->i_prealloc_cap_flush = NULL;
4669+
if (!cf->is_capsnap)
4670+
ceph_free_cap_flush(cf);
4671+
}
4672+
4673+
if (!list_empty(&ci->i_cap_snaps))
4674+
iputs = remove_capsnaps(mdsc, inode);
4675+
}
4676+
if (dirty_dropped)
4677+
++iputs;
4678+
return iputs;
4679+
}

fs/ceph/mds_client.c

Lines changed: 3 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,125 +1590,23 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session,
15901590
return ret;
15911591
}
15921592

1593-
static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
1594-
{
1595-
struct ceph_inode_info *ci = ceph_inode(inode);
1596-
struct ceph_cap_snap *capsnap;
1597-
int capsnap_release = 0;
1598-
1599-
lockdep_assert_held(&ci->i_ceph_lock);
1600-
1601-
dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
1602-
1603-
while (!list_empty(&ci->i_cap_snaps)) {
1604-
capsnap = list_first_entry(&ci->i_cap_snaps,
1605-
struct ceph_cap_snap, ci_item);
1606-
__ceph_remove_capsnap(inode, capsnap, NULL, NULL);
1607-
ceph_put_snap_context(capsnap->context);
1608-
ceph_put_cap_snap(capsnap);
1609-
capsnap_release++;
1610-
}
1611-
wake_up_all(&ci->i_cap_wq);
1612-
wake_up_all(&mdsc->cap_flushing_wq);
1613-
return capsnap_release;
1614-
}
1615-
16161593
static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
16171594
void *arg)
16181595
{
1619-
struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg;
1620-
struct ceph_mds_client *mdsc = fsc->mdsc;
16211596
struct ceph_inode_info *ci = ceph_inode(inode);
1622-
bool is_auth;
1623-
bool dirty_dropped = false;
16241597
bool invalidate = false;
1625-
int capsnap_release = 0;
1598+
int iputs;
16261599

16271600
dout("removing cap %p, ci is %p, inode is %p\n",
16281601
cap, ci, &ci->vfs_inode);
16291602
spin_lock(&ci->i_ceph_lock);
1630-
is_auth = (cap == ci->i_auth_cap);
1631-
__ceph_remove_cap(cap, false);
1632-
if (is_auth) {
1633-
struct ceph_cap_flush *cf;
1634-
1635-
if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {
1636-
if (inode->i_data.nrpages > 0)
1637-
invalidate = true;
1638-
if (ci->i_wrbuffer_ref > 0)
1639-
mapping_set_error(&inode->i_data, -EIO);
1640-
}
1641-
1642-
spin_lock(&mdsc->cap_dirty_lock);
1643-
1644-
/* trash all of the cap flushes for this inode */
1645-
while (!list_empty(&ci->i_cap_flush_list)) {
1646-
cf = list_first_entry(&ci->i_cap_flush_list,
1647-
struct ceph_cap_flush, i_list);
1648-
list_del_init(&cf->g_list);
1649-
list_del_init(&cf->i_list);
1650-
if (!cf->is_capsnap)
1651-
ceph_free_cap_flush(cf);
1652-
}
1653-
1654-
if (!list_empty(&ci->i_dirty_item)) {
1655-
pr_warn_ratelimited(
1656-
" dropping dirty %s state for %p %lld\n",
1657-
ceph_cap_string(ci->i_dirty_caps),
1658-
inode, ceph_ino(inode));
1659-
ci->i_dirty_caps = 0;
1660-
list_del_init(&ci->i_dirty_item);
1661-
dirty_dropped = true;
1662-
}
1663-
if (!list_empty(&ci->i_flushing_item)) {
1664-
pr_warn_ratelimited(
1665-
" dropping dirty+flushing %s state for %p %lld\n",
1666-
ceph_cap_string(ci->i_flushing_caps),
1667-
inode, ceph_ino(inode));
1668-
ci->i_flushing_caps = 0;
1669-
list_del_init(&ci->i_flushing_item);
1670-
mdsc->num_cap_flushing--;
1671-
dirty_dropped = true;
1672-
}
1673-
spin_unlock(&mdsc->cap_dirty_lock);
1674-
1675-
if (dirty_dropped) {
1676-
mapping_set_error(inode->i_mapping, -EIO);
1677-
1678-
if (ci->i_wrbuffer_ref_head == 0 &&
1679-
ci->i_wr_ref == 0 &&
1680-
ci->i_dirty_caps == 0 &&
1681-
ci->i_flushing_caps == 0) {
1682-
ceph_put_snap_context(ci->i_head_snapc);
1683-
ci->i_head_snapc = NULL;
1684-
}
1685-
}
1686-
1687-
if (atomic_read(&ci->i_filelock_ref) > 0) {
1688-
/* make further file lock syscall return -EIO */
1689-
ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
1690-
pr_warn_ratelimited(" dropping file locks for %p %lld\n",
1691-
inode, ceph_ino(inode));
1692-
}
1693-
1694-
if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
1695-
cf = ci->i_prealloc_cap_flush;
1696-
ci->i_prealloc_cap_flush = NULL;
1697-
if (!cf->is_capsnap)
1698-
ceph_free_cap_flush(cf);
1699-
}
1700-
1701-
if (!list_empty(&ci->i_cap_snaps))
1702-
capsnap_release = remove_capsnaps(mdsc, inode);
1703-
}
1603+
iputs = ceph_purge_inode_cap(inode, cap, &invalidate);
17041604
spin_unlock(&ci->i_ceph_lock);
17051605

17061606
wake_up_all(&ci->i_cap_wq);
17071607
if (invalidate)
17081608
ceph_queue_invalidate(inode);
1709-
if (dirty_dropped)
1710-
iput(inode);
1711-
while (capsnap_release--)
1609+
while (iputs--)
17121610
iput(inode);
17131611
return 0;
17141612
}

fs/ceph/super.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,7 @@ extern int ceph_mmap(struct file *file, struct vm_area_struct *vma);
11991199
extern int ceph_uninline_data(struct file *filp, struct page *locked_page);
12001200
extern int ceph_pool_perm_check(struct inode *inode, int need);
12011201
extern void ceph_pool_perm_destroy(struct ceph_mds_client* mdsc);
1202+
int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate);
12021203

12031204
/* file.c */
12041205
extern const struct file_operations ceph_file_fops;

0 commit comments

Comments
 (0)