Skip to content

Commit

Permalink
ceph: fix snap realm splits
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sage Weil committed May 3, 2010
1 parent c10f5e1 commit 91dee39
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions fs/ceph/snap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit 91dee39

Please sign in to comment.