diff options
author | Anand Avati <avati@redhat.com> | 2013-03-05 14:48:28 -0800 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2013-09-03 11:26:26 -0700 |
commit | 53e98f11d1f3df30cc013af021464a257949a62d (patch) | |
tree | 2841ea3d822918685c85f46cad09e03a3d648490 /xlators/features/qemu-block/src/coroutine-synctask.c | |
parent | 0d60175bd684cf6a14f750579d82dbd1ba97fcbc (diff) |
features/qemu-block: support for QCOW2 and QED formats
This patch adds support for internals snapshots using QCOW2 and
general framework for external snapshots (next patch) with
QCOW2 and QED.
For internal snapshots, the file must be "initialized" or
"formatted" into QCOW2 format, and specify a file size.
Snapshots can be created, deleted, and applied ("goto").
e.g:
// Format and Initialize
sh# setfattr -n trusted.glusterfs.block-format -v qcow2:10GB /mnt/imgfile
sh# ls -l /mnt/imgfile
-rw-r--r-- 1 root root 10G Jul 18 21:20 imgfile
// Create a snapshot
sh# setfattr -n trusted.glusterfs.block-snapshot-create -v name1 imgfile
// Apply a snapshot
sh# setfattr -n trusted.gluterfs.block-snapshot-goto -v name1 imgfile
Change-Id: If993e057a9455967ba3fa9dcabb7f74b8b2cf4c3
BUG: 986775
Signed-off-by: Anand Avati <avati@redhat.com>
Reviewed-on: http://review.gluster.org/5367
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Diffstat (limited to 'xlators/features/qemu-block/src/coroutine-synctask.c')
-rw-r--r-- | xlators/features/qemu-block/src/coroutine-synctask.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/xlators/features/qemu-block/src/coroutine-synctask.c b/xlators/features/qemu-block/src/coroutine-synctask.c new file mode 100644 index 00000000..c3538f60 --- /dev/null +++ b/xlators/features/qemu-block/src/coroutine-synctask.c @@ -0,0 +1,213 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "glusterfs.h" +#include "logging.h" +#include "dict.h" +#include "xlator.h" +#include "syncop.h" +#include "qemu-block-memory-types.h" + +#include "qemu-block.h" +#include "coroutine-synctask.h" + +void +qemu_coroutine_delete (Coroutine *co_) +{ + struct synctask *synctask = NULL; + CoroutineSynctask *cs = NULL; + + cs = DO_UPCAST(CoroutineSynctask, base, co_); + synctask = cs->synctask; + + cs->die = 1; + synctask_wake (synctask); + + /* Do not free either @cs or @synctask here. + @synctask is naturally destroyed when + cs_proc() returns (after "break"ing out of + the loop because of setting cs->die=1 above. + + We free @cs too just before returning from + cs_proc() + */ + return; +} + + +CoroutineAction +qemu_coroutine_switch (Coroutine *from_, Coroutine *to_, CoroutineAction action) +{ + struct synctask *to = NULL; + struct synctask *from = NULL; + CoroutineSynctask *csto = NULL; + CoroutineSynctask *csfrom = NULL; + + csto = DO_UPCAST(CoroutineSynctask, base, to_); + csfrom = DO_UPCAST(CoroutineSynctask, base, from_); + to = csto->synctask; + from = csfrom->synctask; + + /* TODO: need mutex/cond guarding when making syncenv + multithreaded + */ + csfrom->run = false; + csto->run = true; + + /* the next three lines must be in this specific order only */ + csfrom->action = action; + + synctask_wake (to); + + synctask_yield (from); + + /* the yielder set @action value in @csfrom, but for the + resumer it is @csto + */ + return csto->action; +} + + +int +cs_fin (int ret, call_frame_t *frame, void *opaque) +{ + /* nop */ + return 0; +} + + +static int +cs_proc (void *opaque) +{ + CoroutineSynctask *cs = opaque; + struct synctask *synctask = NULL; + + synctask = synctask_get (); /* == cs->synctask */ + + for (;;) { + while (!cs->run && !cs->die) + /* entry function (i.e cs->base.entry) will + not be set just yet first time. Wait for + caller to set it and call switch() + */ + synctask_yield (synctask); + + if (cs->die) + break; + + cs->base.entry (cs->base.entry_arg); + qemu_coroutine_switch (&cs->base, cs->base.caller, + COROUTINE_TERMINATE); + } + + GF_FREE (cs); + + return 0; +} + + +Coroutine * +qemu_coroutine_new() +{ + qb_conf_t *conf = NULL; + CoroutineSynctask *cs = NULL; + struct synctask *task = NULL; + + conf = THIS->private; + + cs = GF_CALLOC (1, sizeof (*cs), gf_qb_mt_coroutinesynctask_t); + if (!cs) + return NULL; + + task = synctask_get (); + /* Inherit the frame from the parent synctask, as this will + carry forward things like uid, gid, pid, lkowner etc. of the + caller properly. + */ + cs->synctask = synctask_create (conf->env, cs_proc, cs_fin, + task ? task->frame : NULL, cs); + if (!cs->synctask) + return NULL; + + return &cs->base; +} + + +Coroutine * +qemu_coroutine_self() +{ + struct synctask *synctask = NULL; + CoroutineSynctask *cs = NULL; + + synctask = synctask_get(); + + cs = synctask->opaque; + + return &cs->base; +} + + +bool +qemu_in_coroutine () +{ + Coroutine *co = NULL; + + co = qemu_coroutine_self (); + + return co && co->caller; +} + + +/* These are calls for the "top" xlator to invoke/submit + coroutines +*/ + +static int +synctask_nop_cbk (int ret, call_frame_t *frame, void *opaque) +{ + return 0; +} + + +int +qb_synctask_wrap (void *opaque) +{ + struct synctask *task = NULL; + CoroutineSynctask *cs = NULL; + qb_local_t *qb_local = NULL; + + task = synctask_get (); + cs = opaque; + cs->synctask = task; + qb_local = DO_UPCAST (qb_local_t, cs, cs); + + return qb_local->synctask_fn (opaque); +} + + +int +qb_coroutine (call_frame_t *frame, synctask_fn_t fn) +{ + qb_local_t *qb_local = NULL; + qb_conf_t *qb_conf = NULL; + + qb_local = frame->local; + qb_local->synctask_fn = fn; + qb_conf = frame->this->private; + + return synctask_new (qb_conf->env, qb_synctask_wrap, synctask_nop_cbk, + frame, &qb_local->cs); +} |