On Thu, Jun 04, 2015 at 05:46:07PM -0400, John Snow wrote: > The goal here is to add a new method to transactions that allows > developers to specify a callback that will get invoked only once > all jobs spawned by a transaction are completed, allowing developers > the chance to perform actions conditionally pending complete success, > partial failure, or complete failure. > > In order to register the new callback to be invoked, a user must request > a callback pointer and closure by calling new_action_cb_wrapper, which > creates a wrapper around an opaque pointer and callback that would have > originally been passed to e.g. backup_start(). > > The function will return a function pointer and a new opaque pointer to > be passed instead. The transaction system will effectively intercept the > original callbacks and perform book-keeping on the transaction after it > has delivered the original enveloped callback. > > This means that Transaction Action callback methods will be called after > all callbacks triggered by all Actions in the Transactional group have > been received. > > This feature has no knowledge of any jobs spawned by Actions that do not > inform the system via new_action_cb_wrapper(). > > For an example of how to use the feature, please skip ahead to: > 'block: drive_backup transaction callback support' which serves as an example > for how to hook up a post-transaction callback to the Drive Backup action. > > > Note 1: Defining a callback method alone is not sufficient to have the new > method invoked. You must call new_action_cb_wrapper() AND ensure the > callback it returns is the one used as the callback for the job > launched by the action. > > Note 2: You can use this feature for any system that registers completions of > an asynchronous task via a callback of the form > (void *opaque, int ret), not just block job callbacks. > > Signed-off-by: John Snow <js...@redhat.com> > --- > blockdev.c | 183 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 179 insertions(+), 4 deletions(-) > > diff --git a/blockdev.c b/blockdev.c > index dea57b4..9db8202 100644 > --- a/blockdev.c > +++ b/blockdev.c > @@ -1240,6 +1240,8 @@ typedef struct BlkActionState BlkActionState; > * @abort: Abort the changes on fail, can be NULL. > * @clean: Clean up resources after all transaction actions have called > * commit() or abort(). Can be NULL. > + * @cb: Executed after all jobs launched by actions in the transaction > finish, > + * but only if requested by new_action_cb_wrapper() prior to clean(). > * > * Only prepare() may fail. In a single transaction, only one of commit() or > * abort() will be called. clean() will always be called if it is present. > @@ -1250,6 +1252,7 @@ typedef struct BlkActionOps { > void (*commit)(BlkActionState *common); > void (*abort)(BlkActionState *common); > void (*clean)(BlkActionState *common); > + void (*cb)(BlkActionState *common); > } BlkActionOps; > > /** > @@ -1258,19 +1261,46 @@ typedef struct BlkActionOps { > * by a transaction group. > * > * @refcnt: A reference count for this object. > + * @status: A cumulative return code for all actions that have reported > + * a return code via callback in the transaction. > * @actions: A list of all Actions in the Transaction. > + * However, once the transaction has completed, it will be only a > list > + * of transactions that have registered a post-transaction > callback. > */ > typedef struct BlkTransactionState { > int refcnt; > + int status; > QTAILQ_HEAD(actions, BlkActionState) actions; > } BlkTransactionState; > > +typedef void (CallbackFn)(void *opaque, int ret);
Please use BlockCompletionFunc from aio.h: typedef void BlockCompletionFunc(void *opaque, int ret);
pgptUJU19QpH7.pgp
Description: PGP signature