ceph: use i_ceph_lock instead of i_lock

We have been using i_lock to protect all kinds of data structures in the
ceph_inode_info struct, including lists of inodes that we need to iterate
over while avoiding races with inode destruction.  That requires grabbing
a reference to the inode with the list lock protected, but igrab() now
takes i_lock to check the inode flags.

Changing the list lock ordering would be a painful process.

However, using a ceph-specific i_ceph_lock in the ceph inode instead of
i_lock is a simple mechanical change and avoids the ordering constraints
imposed by igrab().

Reported-by: Amon Ott <a.ott@m-privacy.de>
Signed-off-by: Sage Weil <sage@newdream.net>
This commit is contained in:
Sage Weil
2011-11-30 09:47:09 -08:00
والد 51703306b3
کامیت be655596b3
11فایلهای تغییر یافته به همراه212 افزوده شده و 207 حذف شده

مشاهده پرونده

@@ -220,7 +220,7 @@ struct ceph_dentry_info {
* The locking for D_COMPLETE is a bit odd:
* - we can clear it at almost any time (see ceph_d_prune)
* - it is only meaningful if:
* - we hold dir inode i_lock
* - we hold dir inode i_ceph_lock
* - we hold dir FILE_SHARED caps
* - the dentry D_COMPLETE is set
*/
@@ -250,6 +250,8 @@ struct ceph_inode_xattrs_info {
struct ceph_inode_info {
struct ceph_vino i_vino; /* ceph ino + snap */
spinlock_t i_ceph_lock;
u64 i_version;
u32 i_time_warp_seq;
@@ -271,7 +273,7 @@ struct ceph_inode_info {
struct ceph_inode_xattrs_info i_xattrs;
/* capabilities. protected _both_ by i_lock and cap->session's
/* capabilities. protected _both_ by i_ceph_lock and cap->session's
* s_mutex. */
struct rb_root i_caps; /* cap list */
struct ceph_cap *i_auth_cap; /* authoritative cap, if any */
@@ -437,18 +439,18 @@ static inline void ceph_i_clear(struct inode *inode, unsigned mask)
{
struct ceph_inode_info *ci = ceph_inode(inode);
spin_lock(&inode->i_lock);
spin_lock(&ci->i_ceph_lock);
ci->i_ceph_flags &= ~mask;
spin_unlock(&inode->i_lock);
spin_unlock(&ci->i_ceph_lock);
}
static inline void ceph_i_set(struct inode *inode, unsigned mask)
{
struct ceph_inode_info *ci = ceph_inode(inode);
spin_lock(&inode->i_lock);
spin_lock(&ci->i_ceph_lock);
ci->i_ceph_flags |= mask;
spin_unlock(&inode->i_lock);
spin_unlock(&ci->i_ceph_lock);
}
static inline bool ceph_i_test(struct inode *inode, unsigned mask)
@@ -456,9 +458,9 @@ static inline bool ceph_i_test(struct inode *inode, unsigned mask)
struct ceph_inode_info *ci = ceph_inode(inode);
bool r;
spin_lock(&inode->i_lock);
spin_lock(&ci->i_ceph_lock);
r = (ci->i_ceph_flags & mask) == mask;
spin_unlock(&inode->i_lock);
spin_unlock(&ci->i_ceph_lock);
return r;
}
@@ -508,9 +510,9 @@ extern int __ceph_caps_issued_other(struct ceph_inode_info *ci,
static inline int ceph_caps_issued(struct ceph_inode_info *ci)
{
int issued;
spin_lock(&ci->vfs_inode.i_lock);
spin_lock(&ci->i_ceph_lock);
issued = __ceph_caps_issued(ci, NULL);
spin_unlock(&ci->vfs_inode.i_lock);
spin_unlock(&ci->i_ceph_lock);
return issued;
}
@@ -518,9 +520,9 @@ static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask,
int touch)
{
int r;
spin_lock(&ci->vfs_inode.i_lock);
spin_lock(&ci->i_ceph_lock);
r = __ceph_caps_issued_mask(ci, mask, touch);
spin_unlock(&ci->vfs_inode.i_lock);
spin_unlock(&ci->i_ceph_lock);
return r;
}
@@ -743,10 +745,9 @@ extern int ceph_add_cap(struct inode *inode,
extern void __ceph_remove_cap(struct ceph_cap *cap);
static inline void ceph_remove_cap(struct ceph_cap *cap)
{
struct inode *inode = &cap->ci->vfs_inode;
spin_lock(&inode->i_lock);
spin_lock(&cap->ci->i_ceph_lock);
__ceph_remove_cap(cap);
spin_unlock(&inode->i_lock);
spin_unlock(&cap->ci->i_ceph_lock);
}
extern void ceph_put_cap(struct ceph_mds_client *mdsc,
struct ceph_cap *cap);