diff --git a/helpers.c b/helpers.c
index cf619e960870eb270e48ad0779b9ca438d0a5e5e..5db3b4dab2824a3700f9a472f2e75f48e31b7e55 100644
--- a/helpers.c
+++ b/helpers.c
@@ -16,51 +16,6 @@
 #include <linux/zio-trigger.h>
 #include "zio-internal.h"
 
-/* The trigger is armed and the cset spin lock is taken */
-static void __zio_internal_data_done(struct zio_cset *cset)
-{
-	struct zio_buffer_type *zbuf;
-	struct zio_device *zdev;
-	struct zio_channel *chan;
-	struct zio_block *block;
-	struct zio_ti *ti;
-	struct zio_bi *bi;
-
-	pr_debug("%s:%d\n", __func__, __LINE__);
-
-	ti = cset->ti;
-	zdev = cset->zdev;
-	zbuf = cset->zbuf;
-
-	if (unlikely((ti->flags & ZIO_DIR) == ZIO_DIR_OUTPUT)) {
-		chan_for_each(chan, cset) {
-			bi = chan->bi;
-			block = chan->active_block;
-			if (block)
-				zbuf->b_op->free_block(chan->bi, block);
-			/* We may have a new block ready, or not */
-			chan->active_block = zbuf->b_op->retr_block(chan->bi);
-		}
-		return;
-	}
-	/* DIR_INPUT */
-	chan_for_each(chan, cset) {
-		bi = chan->bi;
-		block = chan->active_block;
-		if (!block)
-			continue;
-		/* Copy the stamp: it is cset-wide so it lives in the trigger */
-		chan->current_ctrl->tstamp.secs = ti->tstamp.tv_sec;
-		chan->current_ctrl->tstamp.ticks = ti->tstamp.tv_nsec;
-		chan->current_ctrl->tstamp.bins = ti->tstamp_extra;
-		memcpy(zio_get_ctrl(block), chan->current_ctrl,
-		       ZIO_CONTROL_SIZE);
-
-		if (zbuf->b_op->store_block(bi, block)) /* may fail, no prob */
-			zbuf->b_op->free_block(bi, block);
-	}
-}
-
 /*
  * zio_trigger_data_done
  * This is a ZIO helper to invoke the data_done trigger operation when a data
@@ -76,7 +31,7 @@ void zio_trigger_data_done(struct zio_cset *cset)
 	if (cset->ti->t_op->data_done)
 		cset->ti->t_op->data_done(cset);
 	else
-		__zio_internal_data_done(cset);
+		zio_generic_data_done(cset);
 
 	cset->ti->flags &= ~ZIO_TI_ARMED;
 	spin_unlock(&cset->lock);
diff --git a/include/linux/zio-trigger.h b/include/linux/zio-trigger.h
index 1aa389411631ca2c5dd561c184ee6af8dadfa8bb..9ccced7b48b508fe3014d564e4a660207d4e98e3 100644
--- a/include/linux/zio-trigger.h
+++ b/include/linux/zio-trigger.h
@@ -108,4 +108,54 @@ struct zio_trigger_operations {
 void zio_trigger_data_done(struct zio_cset *cset);
 int zio_trigger_abort_disable(struct zio_cset *cset, int disable);
 
+/*
+ * This generic_data_done can be used by triggers, as part of their own.
+ * If not trigger-specific function is specified, the core calls this one.
+ * When data_done is called, the trigger is armed and the cset lock is taken
+ */
+static inline void zio_generic_data_done(struct zio_cset *cset)
+{
+	struct zio_buffer_type *zbuf;
+	struct zio_device *zdev;
+	struct zio_channel *chan;
+	struct zio_block *block;
+	struct zio_ti *ti;
+	struct zio_bi *bi;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+
+	ti = cset->ti;
+	zdev = cset->zdev;
+	zbuf = cset->zbuf;
+
+	if (unlikely((ti->flags & ZIO_DIR) == ZIO_DIR_OUTPUT)) {
+		chan_for_each(chan, cset) {
+			bi = chan->bi;
+			block = chan->active_block;
+			if (block)
+				zbuf->b_op->free_block(chan->bi, block);
+			/* We may have a new block ready, or not */
+			chan->active_block = zbuf->b_op->retr_block(chan->bi);
+		}
+		return;
+	}
+	/* DIR_INPUT */
+	chan_for_each(chan, cset) {
+		bi = chan->bi;
+		block = chan->active_block;
+		if (!block)
+			continue;
+		/* Copy the stamp: it is cset-wide so it lives in the trigger */
+		chan->current_ctrl->tstamp.secs = ti->tstamp.tv_sec;
+		chan->current_ctrl->tstamp.ticks = ti->tstamp.tv_nsec;
+		chan->current_ctrl->tstamp.bins = ti->tstamp_extra;
+		memcpy(zio_get_ctrl(block), chan->current_ctrl,
+		       ZIO_CONTROL_SIZE);
+
+		if (zbuf->b_op->store_block(bi, block)) /* may fail, no prob */
+			zbuf->b_op->free_block(bi, block);
+		chan->active_block = NULL;
+	}
+}
+
 #endif /* __ZIO_TRIGGER_H__ */