Whamcloud - gitweb
fix issue with use-after-free if commit occurs while journal_stop()
authortappro <tappro>
Thu, 10 Aug 2006 12:08:23 +0000 (12:08 +0000)
committertappro <tappro>
Thu, 10 Aug 2006 12:08:23 +0000 (12:08 +0000)
the ot_ref count is added into osd_thandle and osd_thandle is freed only when
last reference is dropped.

lustre/osd/osd_handler.c

index 6cf9751..3639e18 100644 (file)
@@ -217,6 +217,7 @@ static struct dt_index_operations       osd_index_compat_ops;
 
 struct osd_thandle {
         struct thandle          ot_super;
+        int                     ot_ref;
         handle_t               *ot_handle;
         struct journal_callback ot_jcb;
 };
@@ -435,6 +436,27 @@ static int osd_param_is_sane(const struct osd_device *dev,
         return param->tp_credits <= osd_journal(dev)->j_max_transaction_buffers;
 }
 
+static inline void osd_thandle_get(struct osd_thandle *oh)
+{
+        LASSERT(oh->ot_ref > 0);
+        oh->ot_ref ++;
+}
+
+static inline void osd_thandle_put(struct osd_thandle *oh)
+{
+        LASSERT(oh->ot_ref > 0);
+        if (-- oh->ot_ref == 0) {
+                struct thandle *th = &oh->ot_super;
+
+                if (th->th_dev != NULL) {
+                        lu_device_put(&th->th_dev->dd_lu_dev);
+                        th->th_dev = NULL;
+                }
+                lu_context_fini(&th->th_ctx);
+                OBD_FREE_PTR(oh);
+        }
+}
+
 static void osd_trans_commit_cb(struct journal_callback *jcb, int error)
 {
         struct osd_thandle *oh = container_of0(jcb, struct osd_thandle, ot_jcb);
@@ -442,14 +464,7 @@ static void osd_trans_commit_cb(struct journal_callback *jcb, int error)
 
         /* there is no thread context available */
         dt_txn_hook_commit(&th->th_ctx, th->th_dev, th);
-
-        if (th->th_dev != NULL) {
-                lu_device_put(&th->th_dev->dd_lu_dev);
-                th->th_dev = NULL;
-        }
-
-        lu_context_fini(&th->th_ctx);
-        OBD_FREE_PTR(oh);
+        osd_thandle_put(oh);
 }
 
 static struct thandle *osd_trans_start(const struct lu_context *ctx,
@@ -479,9 +494,14 @@ static struct thandle *osd_trans_start(const struct lu_context *ctx,
                          * XXX temporary stuff. Some abstraction layer should
                          * be used.
                          */
+                        
                         jh = journal_start(osd_journal(dev), p->tp_credits);
                         if (!IS_ERR(jh)) {
                                 oh->ot_handle = jh;
+                                /* hmm, since oh init and start are done together
+                                 * the ref starts from 2
+                                 */
+                                oh->ot_ref = 2;
                                 th = &oh->ot_super;
                                 th->th_dev = d;
                                 lu_device_get(&d->dd_lu_dev);
@@ -527,17 +547,12 @@ static void osd_trans_stop(const struct lu_context *ctx, struct thandle *th)
                 if (result != 0)
                         CERROR("Failure to stop transaction: %d\n", result);
                 oh->ot_handle = NULL;
+                osd_thandle_put(oh);
                 LASSERT(oti->oti_txns == 1);
                 LASSERT(oti->oti_r_locks == 0);
                 LASSERT(oti->oti_w_locks == 0);
                 oti->oti_txns--;
         }
-/*
-        if (th->th_dev != NULL) {
-                lu_device_put(&th->th_dev->dd_lu_dev);
-                th->th_dev = NULL;
-        }
-*/
         EXIT;
 }