ceph: fix iterate_caps removal race
authorSage Weil <sage@newdream.net>
Tue, 16 Feb 2010 19:39:45 +0000 (11:39 -0800)
committerSage Weil <sage@newdream.net>
Wed, 17 Feb 2010 18:02:47 +0000 (10:02 -0800)
commit7c1332b8cb5b27656cf6ab1f5fe808a8eb8bb2c0
treef990ab6b339a88896f41a6b3541d0676684c935d
parent85ccce43a3fc15a40ded6ae1603e3f68a17f4d24
ceph: fix iterate_caps removal race

We need to be able to iterate over all caps on a session with a
possibly slow callback on each cap.  To allow this, we used to
prevent cap reordering while we were iterating.  However, we were
not safe from races with removal: removing the 'next' cap would
make the next pointer from list_for_each_entry_safe be invalid,
and cause a lock up or similar badness.

Instead, we keep an iterator pointer in the session pointing to
the current cap.  As before, we avoid reordering.  For removal,
if the cap isn't the current cap we are iterating over, we are
fine.  If it is, we clear cap->ci (to mark the cap as pending
removal) but leave it in the session list.  In iterate_caps, we
can safely finish removal and get the next cap pointer.

While we're at it, clean up put_cap to not take a cap reservation
context, as it was never used.

Signed-off-by: Sage Weil <sage@newdream.net>
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h