mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 01:04:08 +08:00
ceph: hold i_ceph_lock when removing caps for freeing inode
ceph_d_revalidate(, LOOKUP_RCU) may call __ceph_caps_issued_mask() on a freeing inode. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
8f2a98ef3c
commit
d6e4781972
@ -1263,20 +1263,22 @@ static int send_cap_msg(struct cap_msg_args *arg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue cap releases when an inode is dropped from our cache. Since
|
||||
* inode is about to be destroyed, there is no need for i_ceph_lock.
|
||||
* Queue cap releases when an inode is dropped from our cache.
|
||||
*/
|
||||
void __ceph_remove_caps(struct inode *inode)
|
||||
void __ceph_remove_caps(struct ceph_inode_info *ci)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
struct rb_node *p;
|
||||
|
||||
/* lock i_ceph_lock, because ceph_d_revalidate(..., LOOKUP_RCU)
|
||||
* may call __ceph_caps_issued_mask() on a freeing inode. */
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
p = rb_first(&ci->i_caps);
|
||||
while (p) {
|
||||
struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
|
||||
p = rb_next(p);
|
||||
__ceph_remove_cap(cap, true);
|
||||
}
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -533,7 +533,7 @@ void ceph_destroy_inode(struct inode *inode)
|
||||
|
||||
ceph_fscache_unregister_inode_cookie(ci);
|
||||
|
||||
__ceph_remove_caps(inode);
|
||||
__ceph_remove_caps(ci);
|
||||
|
||||
if (__ceph_has_any_quota(ci))
|
||||
ceph_adjust_quota_realms_count(inode, false);
|
||||
|
@ -1004,7 +1004,7 @@ extern void ceph_add_cap(struct inode *inode,
|
||||
unsigned cap, unsigned seq, u64 realmino, int flags,
|
||||
struct ceph_cap **new_cap);
|
||||
extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
|
||||
extern void __ceph_remove_caps(struct inode* inode);
|
||||
extern void __ceph_remove_caps(struct ceph_inode_info *ci);
|
||||
extern void ceph_put_cap(struct ceph_mds_client *mdsc,
|
||||
struct ceph_cap *cap);
|
||||
extern int ceph_is_any_caps(struct inode *inode);
|
||||
|
Loading…
Reference in New Issue
Block a user