forked from luck/tmp_suning_uos_patched
ceph: fix snap realm splits
The snap realm split was checking i_snap_realm, not the list_head, to determine if an inode belonged in the new realm. The check always failed, which meant we always moved the inode, corrupting the old realm's list and causing various crashes. Also wait to release old realm reference to avoid possibility of use after free. Signed-off-by: Sage Weil <sage@newdream.net>
This commit is contained in:
parent
c10f5e12ba
commit
91dee39eeb
|
@ -869,16 +869,20 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
|
|||
continue;
|
||||
ci = ceph_inode(inode);
|
||||
spin_lock(&inode->i_lock);
|
||||
if (!ci->i_snap_realm)
|
||||
goto split_skip_inode;
|
||||
ceph_put_snap_realm(mdsc, ci->i_snap_realm);
|
||||
spin_lock(&realm->inodes_with_caps_lock);
|
||||
list_add(&ci->i_snap_realm_item,
|
||||
&realm->inodes_with_caps);
|
||||
ci->i_snap_realm = realm;
|
||||
spin_unlock(&realm->inodes_with_caps_lock);
|
||||
ceph_get_snap_realm(mdsc, realm);
|
||||
split_skip_inode:
|
||||
if (list_empty(&ci->i_snap_realm_item)) {
|
||||
struct ceph_snap_realm *oldrealm =
|
||||
ci->i_snap_realm;
|
||||
|
||||
dout(" moving %p to split realm %llx %p\n",
|
||||
inode, realm->ino, realm);
|
||||
spin_lock(&realm->inodes_with_caps_lock);
|
||||
list_add(&ci->i_snap_realm_item,
|
||||
&realm->inodes_with_caps);
|
||||
ci->i_snap_realm = realm;
|
||||
spin_unlock(&realm->inodes_with_caps_lock);
|
||||
ceph_get_snap_realm(mdsc, realm);
|
||||
ceph_put_snap_realm(mdsc, oldrealm);
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
iput(inode);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user