summaryrefslogtreecommitdiff
path: root/crypto/khazad.c
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2015-02-17 19:37:15 +0300
committerIlya Dryomov <idryomov@gmail.com>2015-02-19 14:27:50 +0300
commit7eb71e0351fbb1b242ae70abb7bb17107fe2f792 (patch)
treea5b06178c59e77df73f6c86dbf4b160f18dbf62c /crypto/khazad.c
parent7ad18afad02f9802f1eeade91cf880b97e7a9902 (diff)
libceph: fix double __remove_osd() problem
It turns out it's possible to get __remove_osd() called twice on the same OSD. That doesn't sit well with rb_erase() - depending on the shape of the tree we can get a NULL dereference, a soft lockup or a random crash at some point in the future as we end up touching freed memory. One scenario that I was able to reproduce is as follows: <osd3 is idle, on the osd lru list> <con reset - osd3> con_fault_finish() osd_reset() <osdmap - osd3 down> ceph_osdc_handle_map() <takes map_sem> kick_requests() <takes request_mutex> reset_changed_osds() __reset_osd() __remove_osd() <releases request_mutex> <releases map_sem> <takes map_sem> <takes request_mutex> __kick_osd_requests() __reset_osd() __remove_osd() <-- !!! A case can be made that osd refcounting is imperfect and reworking it would be a proper resolution, but for now Sage and I decided to fix this by adding a safe guard around __remove_osd(). Fixes: http://tracker.ceph.com/issues/8087 Cc: Sage Weil <sage@redhat.com> Cc: stable@vger.kernel.org # 3.9+: 7c6e6fc53e73: libceph: assert both regular and lingering lists in __remove_osd() Cc: stable@vger.kernel.org # 3.9+: cc9f1f518cec: libceph: change from BUG to WARN for __remove_osd() asserts Cc: stable@vger.kernel.org # 3.9+ Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Sage Weil <sage@redhat.com> Reviewed-by: Alex Elder <elder@linaro.org>
Diffstat (limited to 'crypto/khazad.c')
0 files changed, 0 insertions, 0 deletions