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:
@@ -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);
|
||||
|
مرجع در شماره جدید
Block a user