]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osdc/ObjectCacher: only call flush callback if we transitions to clean
authorSage Weil <sage@inktank.com>
Sat, 10 Nov 2012 02:34:22 +0000 (18:34 -0800)
committerSage Weil <sage@inktank.com>
Sat, 10 Nov 2012 02:34:22 +0000 (18:34 -0800)
If we race with e.g. truncate and are in bh_write_commit but the oset
is already clean, we should not call the flush callback (again).

This is reproduced by:

 - kludging slow osd replies into the code (e.g., 2 second delay)
 - mount ceph-fuse with --client-oc-max-dirty-age 1
 - dd if=/dev/zero of=mnt/foo count=1
   sleep 1
   truncate --size 0 mnt/foo
 -> crash

Signed-off-by: Sage Weil <sage@inktank.com>
src/osdc/ObjectCacher.cc

index 610a0061dcd920a0c4bdbdd645e5c5c543ccdeaf..a700959613d2481aec3858615e033b5844200ce3 100644 (file)
@@ -720,6 +720,7 @@ void ObjectCacher::bh_write_commit(int64_t poolid, sobject_t oid, loff_t start,
     ldout(cct, 7) << "bh_write_commit no object cache" << dendl;
   } else {
     Object *ob = objects[poolid][oid];
+    int was_dirty_or_tx = ob->oset->dirty_or_tx;
     
     // apply to bh's!
     for (map<loff_t, BufferHead*>::iterator p = ob->data.lower_bound(start);
@@ -780,6 +781,7 @@ void ObjectCacher::bh_write_commit(int64_t poolid, sobject_t oid, loff_t start,
 
     // is the entire object set now clean?
     if (flush_set_callback &&
+       was_dirty_or_tx > 0 &&
        oset->dirty_or_tx == 0) {        // nothing dirty/tx
       flush_set_callback(flush_set_callback_arg, oset);      
     }