|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] Revert "tools: remove blktap2 source code"
commit d383c07e8bc6df81afb5fb250cc55c507d75ac75
Author: Wei Liu <wei.liu2@xxxxxxxxxx>
AuthorDate: Thu Sep 8 16:15:47 2016 +0100
Commit: Wei Liu <wei.liu2@xxxxxxxxxx>
CommitDate: Thu Sep 8 16:15:47 2016 +0100
Revert "tools: remove blktap2 source code"
This reverts commit 44b2829a8b97a8b04e063a93303dbe3a468642e3.
---
tools/blktap2/Makefile | 20 +
tools/blktap2/README | 321 +++
tools/blktap2/control/Makefile | 80 +
tools/blktap2/control/tap-ctl-allocate.c | 242 ++
tools/blktap2/control/tap-ctl-attach.c | 61 +
tools/blktap2/control/tap-ctl-check.c | 79 +
tools/blktap2/control/tap-ctl-close.c | 87 +
tools/blktap2/control/tap-ctl-create.c | 67 +
tools/blktap2/control/tap-ctl-destroy.c | 56 +
tools/blktap2/control/tap-ctl-detach.c | 61 +
tools/blktap2/control/tap-ctl-free.c | 54 +
tools/blktap2/control/tap-ctl-ipc.c | 249 +++
tools/blktap2/control/tap-ctl-list.c | 536 +++++
tools/blktap2/control/tap-ctl-major.c | 69 +
tools/blktap2/control/tap-ctl-open.c | 75 +
tools/blktap2/control/tap-ctl-pause.c | 59 +
tools/blktap2/control/tap-ctl-spawn.c | 174 ++
tools/blktap2/control/tap-ctl-unpause.c | 64 +
tools/blktap2/control/tap-ctl.c | 815 +++++++
tools/blktap2/control/tap-ctl.h | 101 +
tools/blktap2/drivers/Makefile | 113 +
tools/blktap2/drivers/aes.c | 1319 +++++++++++
tools/blktap2/drivers/aes.h | 28 +
tools/blktap2/drivers/atomicio.c | 61 +
tools/blktap2/drivers/blk.h | 36 +
tools/blktap2/drivers/blk_linux.c | 43 +
tools/blktap2/drivers/blk_netbsd.c | 41 +
tools/blktap2/drivers/block-aio.c | 258 +++
tools/blktap2/drivers/block-cache.c | 787 +++++++
tools/blktap2/drivers/block-log.c | 665 ++++++
tools/blktap2/drivers/block-qcow.c | 1501 +++++++++++++
tools/blktap2/drivers/block-ram.c | 256 +++
tools/blktap2/drivers/block-remus.c | 1733 ++++++++++++++
tools/blktap2/drivers/block-vhd.c | 2322 +++++++++++++++++++
tools/blktap2/drivers/bswap.h | 179 ++
tools/blktap2/drivers/check_gcrypt | 18 +
tools/blktap2/drivers/hashtable.c | 279 +++
tools/blktap2/drivers/hashtable.h | 204 ++
tools/blktap2/drivers/hashtable_itr.c | 195 ++
tools/blktap2/drivers/hashtable_itr.h | 96 +
tools/blktap2/drivers/hashtable_private.h | 90 +
tools/blktap2/drivers/hashtable_utility.c | 71 +
tools/blktap2/drivers/hashtable_utility.h | 55 +
tools/blktap2/drivers/img2qcow.c | 316 +++
tools/blktap2/drivers/io-optimize.c | 671 ++++++
tools/blktap2/drivers/io-optimize.h | 68 +
tools/blktap2/drivers/libaio-compat.h | 102 +
tools/blktap2/drivers/lock.c | 1000 +++++++++
tools/blktap2/drivers/lock.h | 51 +
tools/blktap2/drivers/log.h | 123 +
tools/blktap2/drivers/md5.c | 278 +++
tools/blktap2/drivers/md5.h | 15 +
tools/blktap2/drivers/profile.h | 191 ++
tools/blktap2/drivers/qcow-create.c | 121 +
tools/blktap2/drivers/qcow.h | 131 ++
tools/blktap2/drivers/qcow2raw.c | 443 ++++
tools/blktap2/drivers/scheduler.c | 265 +++
tools/blktap2/drivers/scheduler.h | 65 +
tools/blktap2/drivers/tapdisk-client.c | 496 +++++
tools/blktap2/drivers/tapdisk-control.c | 837 +++++++
tools/blktap2/drivers/tapdisk-control.h | 35 +
tools/blktap2/drivers/tapdisk-diff.c | 802 +++++++
tools/blktap2/drivers/tapdisk-disktype.c | 200 ++
tools/blktap2/drivers/tapdisk-disktype.h | 62 +
tools/blktap2/drivers/tapdisk-driver.c | 101 +
tools/blktap2/drivers/tapdisk-driver.h | 62 +
tools/blktap2/drivers/tapdisk-filter.c | 272 +++
tools/blktap2/drivers/tapdisk-filter.h | 67 +
tools/blktap2/drivers/tapdisk-image.c | 169 ++
tools/blktap2/drivers/tapdisk-image.h | 56 +
tools/blktap2/drivers/tapdisk-interface.c | 259 +++
tools/blktap2/drivers/tapdisk-interface.h | 54 +
tools/blktap2/drivers/tapdisk-log.c | 257 +++
tools/blktap2/drivers/tapdisk-log.h | 51 +
tools/blktap2/drivers/tapdisk-queue.c | 743 ++++++
tools/blktap2/drivers/tapdisk-queue.h | 125 ++
tools/blktap2/drivers/tapdisk-ring.c | 439 ++++
tools/blktap2/drivers/tapdisk-ring.h | 87 +
tools/blktap2/drivers/tapdisk-server.c | 345 +++
tools/blktap2/drivers/tapdisk-server.h | 67 +
tools/blktap2/drivers/tapdisk-stream.c | 605 +++++
tools/blktap2/drivers/tapdisk-utils.c | 214 ++
tools/blktap2/drivers/tapdisk-utils.h | 45 +
tools/blktap2/drivers/tapdisk-vbd.c | 1723 ++++++++++++++
tools/blktap2/drivers/tapdisk-vbd.h | 207 ++
tools/blktap2/drivers/tapdisk.h | 169 ++
tools/blktap2/drivers/tapdisk2.c | 138 ++
tools/blktap2/drivers/td.c | 691 ++++++
tools/blktap2/drivers/xmsnap | 78 +
tools/blktap2/include/Makefile | 17 +
tools/blktap2/include/atomicio.h | 33 +
tools/blktap2/include/blktap2.h | 67 +
tools/blktap2/include/blktaplib.h | 242 ++
tools/blktap2/include/libvhd-journal.h | 68 +
tools/blktap2/include/libvhd.h | 326 +++
tools/blktap2/include/list.h | 125 ++
tools/blktap2/include/lvm-util.h | 71 +
tools/blktap2/include/relative-path.h | 43 +
tools/blktap2/include/tapdisk-message.h | 203 ++
tools/blktap2/include/vhd-util.h | 44 +
tools/blktap2/include/vhd-uuid.h | 63 +
tools/blktap2/include/vhd.h | 219 ++
tools/blktap2/lvm/Makefile | 36 +
tools/blktap2/lvm/lvm-util.c | 349 +++
tools/blktap2/vhd/Makefile | 51 +
tools/blktap2/vhd/lib/Makefile | 82 +
tools/blktap2/vhd/lib/atomicio.c | 61 +
tools/blktap2/vhd/lib/libvhd-journal.c | 1534 +++++++++++++
tools/blktap2/vhd/lib/libvhd.c | 3348 ++++++++++++++++++++++++++++
tools/blktap2/vhd/lib/relative-path.c | 299 +++
tools/blktap2/vhd/lib/vhd-util-check.c | 980 ++++++++
tools/blktap2/vhd/lib/vhd-util-coalesce.c | 218 ++
tools/blktap2/vhd/lib/vhd-util-create.c | 80 +
tools/blktap2/vhd/lib/vhd-util-fill.c | 105 +
tools/blktap2/vhd/lib/vhd-util-modify.c | 132 ++
tools/blktap2/vhd/lib/vhd-util-query.c | 159 ++
tools/blktap2/vhd/lib/vhd-util-read.c | 742 ++++++
tools/blktap2/vhd/lib/vhd-util-repair.c | 84 +
tools/blktap2/vhd/lib/vhd-util-resize.c | 1131 ++++++++++
tools/blktap2/vhd/lib/vhd-util-revert.c | 106 +
tools/blktap2/vhd/lib/vhd-util-scan.c | 1317 +++++++++++
tools/blktap2/vhd/lib/vhd-util-set-field.c | 106 +
tools/blktap2/vhd/lib/vhd-util-snapshot.c | 216 ++
tools/blktap2/vhd/lib/vhd-util-uuid.c | 128 ++
tools/blktap2/vhd/vhd-update.c | 259 +++
tools/blktap2/vhd/vhd-util.c | 163 ++
126 files changed, 40123 insertions(+)
diff --git a/tools/blktap2/Makefile b/tools/blktap2/Makefile
new file mode 100644
index 0000000..94200dc
--- /dev/null
+++ b/tools/blktap2/Makefile
@@ -0,0 +1,20 @@
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+CFLAGS += $(CFLAGS_libxenctrl)
+LDLIBS += $(LDLIBS_libxenctrl)
+
+SUBDIRS-y :=
+SUBDIRS-y += include
+SUBDIRS-y += lvm
+SUBDIRS-y += vhd
+SUBDIRS-$(CONFIG_Linux) += drivers
+SUBDIRS-$(CONFIG_Linux) += control
+
+clean:
+ rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) TAGS
+
+distclean: clean
+
+.PHONY: all clean install distclean
+all clean install distclean: %: subdirs-%
diff --git a/tools/blktap2/README b/tools/blktap2/README
new file mode 100644
index 0000000..75fc614
--- /dev/null
+++ b/tools/blktap2/README
@@ -0,0 +1,321 @@
+Blktap2 Userspace Tools + Library
+================================
+
+Dutch Meyer
+4th June 2009
+
+Andrew Warfield and Julian Chesterfield
+16th June 2006
+
+
+The blktap2 userspace toolkit provides a user-level disk I/O
+interface. The blktap2 mechanism involves a kernel driver that acts
+similarly to the existing Xen/Linux blkback driver, and a set of
+associated user-level libraries. Using these tools, blktap2 allows
+virtual block devices presented to VMs to be implemented in userspace
+and to be backed by raw partitions, files, network, etc.
+
+The key benefit of blktap2 is that it makes it easy and fast to write
+arbitrary block backends, and that these user-level backends actually
+perform very well. Specifically:
+
+- Metadata disk formats such as Copy-on-Write, encrypted disks, sparse
+ formats and other compression features can be easily implemented.
+
+- Accessing file-based images from userspace avoids problems related
+ to flushing dirty pages which are present in the Linux loopback
+ driver. (Specifically, doing a large number of writes to an
+ NFS-backed image don't result in the OOM killer going berserk.)
+
+- Per-disk handler processes enable easier userspace policing of block
+ resources, and process-granularity QoS techniques (disk scheduling
+ and related tools) may be trivially applied to block devices.
+
+- It's very easy to take advantage of userspace facilities such as
+ networking libraries, compression utilities, peer-to-peer
+ file-sharing systems and so on to build more complex block backends.
+
+- Crashes are contained -- incremental development/debugging is very
+ fast.
+
+How it works (in one paragraph):
+
+Working in conjunction with the kernel blktap2 driver, all disk I/O
+requests from VMs are passed to the userspace deamon (using a shared
+memory interface) through a character device. Each active disk is
+mapped to an individual device node, allowing per-disk processes to
+implement individual block devices where desired. The userspace
+drivers are implemented using asynchronous (Linux libaio),
+O_DIRECT-based calls to preserve the unbuffered, batched and
+asynchronous request dispatch achieved with the existing blkback
+code. We provide a simple, asynchronous virtual disk interface that
+makes it quite easy to add new disk implementations.
+
+As of June 2009 the current supported disk formats are:
+
+ - Raw Images (both on partitions and in image files)
+ - Fast sharable RAM disk between VMs (requires some form of
+ cluster-based filesystem support e.g. OCFS2 in the guest kernel)
+ - VHD, including snapshots and sparse images
+ - Qcow, including snapshots and sparse images
+
+
+Build and Installation Instructions
+===================================
+
+Make to configure the blktap2 backend driver in your dom0 kernel. It
+will inter-operate with the existing backend and frontend drivers. It
+will also cohabitate with the original blktap driver. However, some
+formats (currently aio and qcow) will default to their blktap2
+versions when specified in a vm configuration file.
+
+To build the tools separately, "make && make install" in
+tools/blktap2.
+
+
+Using the Tools
+===============
+
+Preparing an image for boot:
+
+The userspace disk agent is configured to start automatically via xend
+
+Customize the VM config file to use the 'tap:tapdisk' handler,
+followed by the driver type. e.g. for a raw image such as a file or
+partition:
+
+disk = ['tap:tapdisk:aio:<FILENAME>,sda1,w']
+
+Alternatively, the vhd-util tool (installed with make install, or in
+/blktap2/vhd) can be used to build sparse copy-on-write vhd images.
+
+For example, to build a sparse image -
+ vhd-util create -n MyVHDFile -s 1024
+
+This creates a sparse 1GB file named "MyVHDFile" that can be mounted
+and populated with data.
+
+One can also base the image on a raw file -
+ vhd-util snapshot -n MyVHDFile -p SomeRawFile -m
+
+This creates a sparse VHD file named "MyVHDFile" using "SomeRawFile"
+as a parent image. Copy-on-write semantics ensure that writes will be
+stored in "MyVHDFile" while reads will be directed to the most
+recently written version of the data, either in "MyVHDFile" or
+"SomeRawFile" as is appropriate. Other options exist as well, consult
+the vhd-util application for the complete set of VHD tools.
+
+VHD files can be mounted automatically in a guest similarly to the
+above AIO example simply by specifying the vhd driver.
+
+disk = ['tap:tapdisk:vhd:<VHD FILENAME>,sda1,w']
+
+
+Snapshots:
+
+Pausing a guest will also plug the corresponding IO queue for blktap2
+devices and stop blktap2 drivers. This can be used to implement a
+safe live snapshot of qcow and vhd disks. An example script "xmsnap"
+is shown in the tools/blktap2/drivers directory. This script will
+perform a live snapshot of a qcow disk. VHD files can use the
+"vhd-util snapshot" tool discussed above. If this snapshot command is
+applied to a raw file mounted with tap:tapdisk:AIO, include the -m
+flag and the driver will be reloaded as VHD. If applied to an already
+mounted VHD file, omit the -m flag.
+
+
+Mounting images in Dom0 using the blktap2 driver
+===============================================
+Tap (and blkback) disks are also mountable in Dom0 without requiring an
+active VM to attach.
+
+The syntax is -
+ tapdisk2 -n <type>:<full path to file>
+
+For example -
+ tapdisk2 -n aio:/home/images/rawFile.img
+
+When successful the location of the new device will be provided by
+tapdisk2 to stdout and tapdisk2 will terminate. From that point
+forward control of the device is provided through sysfs in the
+directory-
+
+ /sys/class/blktap2/blktap#/
+
+Where # is a blktap2 device number present in the path that tapdisk2
+printed before terminating. The sysfs interface is largely intuitive,
+for example, to remove tap device 0 one would-
+
+ echo 1 > /sys/class/blktap2/blktap0/remove
+
+Similarly, a pause control is available, which is can be used to plug
+the request queue of a live running guest.
+
+Previous versions of blktap mounted devices in dom0 by using blkfront
+in dom0 and the xm block-attach command. This approach is still
+available, though slightly more cumbersome.
+
+
+Tapdisk Development
+===============================================
+
+People regularly ask how to develop their own tapdisk drivers, and
+while it has not yet been well documented, the process is relatively
+easy. Here I will provide a brief overview. The best reference, of
+course, comes from the existing drivers. Specifically,
+blktap2/drivers/block-ram.c and blktap2/drivers/block-aio.c provide
+the clearest examples of simple drivers.
+
+
+Setup:
+
+First you need to register your new driver with blktap. This is done
+in disktypes.h. There are five things that you must do. To
+demonstrate, I will create a disk called "mynewdisk", you can name
+yours freely.
+
+1) Forward declare an instance of struct tap_disk.
+
+e.g. -
+ extern struct tap_disk tapdisk_mynewdisk;
+
+2) Claim one of the unused disk type numbers, take care to observe the
+MAX_DISK_TYPES macro, increasing the number if necessary.
+
+e.g. -
+ #define DISK_TYPE_MYNEWDISK 10
+
+3) Create an instance of disk_info_t. The bulk of this file contains examples
of these.
+
+e.g. -
+ static disk_info_t mynewdisk_disk = {
+ DISK_TYPE_MYNEWDISK,
+ "My New Disk (mynewdisk)",
+ "mynewdisk",
+ 0,
+ #ifdef TAPDISK
+ &tapdisk_mynewdisk,
+ #endif
+ };
+
+A few words about what these mean. The first field must be the disk
+type number you claimed in step (2). The second field is a string
+describing your disk, and may contain any relevant info. The third
+field is the name of your disk as will be used by the tapdisk2 utility
+and xend (for example tapdisk2 -n mynewdisk:/path/to/disk.image, or in
+your xm create config file). The forth is binary and determines
+whether you will have one instance of your driver, or many. Here, a 1
+means that your driver is a singleton and will coordinate access to
+any number of tap devices. 0 is more common, meaning that you will
+have one driver for each device that is created. The final field
+should contain a reference to the struct tap_disk you created in step
+(1).
+
+4) Add a reference to your disk info structure (from step (3)) to the
+dtypes array. Take care here - you need to place it in the position
+corresponding to the device type number you claimed in step (2). So
+we would place &mynewdisk_disk in dtypes[10]. Look at the other
+devices in this array and pad with "&null_disk," as necessary.
+
+5) Modify the xend python scripts. You need to add your disk name to
+the list of disks that xend recognizes.
+
+edit:
+ tools/python/xen/xend/server/BlktapController.py
+
+And add your disk to the "blktap_disk_types" array near the top of
+your file. Use the same name you specified in the third field of step
+(3). The order of this list is not important.
+
+
+Now your driver is ready to be written. Create a block-mynewdisk.c in
+tools/blktap2/drivers and add it to the Makefile.
+
+
+Development:
+
+Copying block-aio.c and block-ram.c would be a good place to start.
+Read those files as you go through this, I will be assisting by
+commenting on a few useful functions and structures.
+
+struct tap_disk:
+
+Remember the forward declaration in step (1) of the setup phase above?
+Now is the time to make that structure a reality. This structure
+contains a list of function pointers for all the routines that will be
+asked of your driver. Currently the required functions are open,
+close, read, write, get_parent_id, validate_parent, and debug.
+
+e.g. -
+ struct tap_disk tapdisk_mynewdisk = {
+ .disk_type = "tapdisk_mynewdisk",
+ .flags = 0,
+ .private_data_size = sizeof(struct tdmynewdisk_state),
+ .td_open = tdmynewdisk_open,
+ ....
+
+The private_data_size field is used to provide a structure to store
+the state of your device. It is very likely that you will want
+something here, but you are free to design whatever structure you
+want. Blktap will allocate this space for you, you just need to tell
+it how much space you want.
+
+
+tdmynewdisk_open:
+
+This is the open routine. The first argument is a structure
+representing your driver. Two fields in this array are
+interesting.
+
+driver->data will contain a block of memory of the size your requested
+in in the .private_data_size field of your struct tap_disk (above).
+
+driver->info contains a structure that details information about your
+disk. You need to fill this out. By convention this is done with a
+_get_image_info() function. Assign a size (the total number of
+sectors), sector_size (the size of each sector in bytes, and set
+driver->info->info to 0.
+
+The second parameter contains the name that was specified in the
+creation of your device, either through xend, or on the command line
+with tapdisk2. Usually this specifies a file that you will open in
+this routine. The final parameter, flags, contains one of a number of
+flags specified in tapdisk.h that may change the way you treat the
+disk.
+
+
+_queue_read/write:
+
+These are your read and write operations. What you do here will
+depend on your disk, but you should do exactly one of-
+
+1) call td_complete_request with either error or success code.
+
+2) Call td_forward_request, which will forward the request to the next
+driver in the stack.
+
+3) Queue the request for asynchronous processing with
+td_prep_read/write. In doing so, you will also register a callback
+for request completion. When the request completes you must do one of
+options (1) or (2) above. Finally, call td_queue_tiocb to submit the
+request to a wait queue.
+
+The above functions are defined in tapdisk-interface.c. If you don't
+use them as specified you will run into problems as your driver will
+fail to inform blktap of the state of requests that have been
+submitted. Blktap keeps track of all requests and does not like losing track.
+
+
+_close, _get_parent_id, _validate_parent:
+
+These last few tend to be very routine. _close is called when the
+device is closed, and also when it is paused (in this case, open will
+also be called later). The other functions are used in stacking
+drivers. Most often drivers will return TD_NO_PARENT and -EINVAL,
+respectively.
+
+
+
+
+
+
diff --git a/tools/blktap2/control/Makefile b/tools/blktap2/control/Makefile
new file mode 100644
index 0000000..767f52a
--- /dev/null
+++ b/tools/blktap2/control/Makefile
@@ -0,0 +1,80 @@
+XEN_ROOT := $(CURDIR)/../../../
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR = 1.0
+MINOR = 0
+LIBNAME = libblktapctl
+LIBSONAME = $(LIBNAME).so.$(MAJOR)
+
+IBIN = tap-ctl
+
+CFLAGS += -Werror
+CFLAGS += -Wno-unused
+CFLAGS += -I../include -I../drivers
+CFLAGS += $(CFLAGS_xeninclude)
+CFLAGS += $(CFLAGS_libxenctrl)
+CFLAGS += -D_GNU_SOURCE
+CFLAGS += -DTAPCTL
+
+CTL_OBJS := tap-ctl-ipc.o
+CTL_OBJS += tap-ctl-list.o
+CTL_OBJS += tap-ctl-allocate.o
+CTL_OBJS += tap-ctl-free.o
+CTL_OBJS += tap-ctl-create.o
+CTL_OBJS += tap-ctl-destroy.o
+CTL_OBJS += tap-ctl-spawn.o
+CTL_OBJS += tap-ctl-attach.o
+CTL_OBJS += tap-ctl-detach.o
+CTL_OBJS += tap-ctl-open.o
+CTL_OBJS += tap-ctl-close.o
+CTL_OBJS += tap-ctl-pause.o
+CTL_OBJS += tap-ctl-unpause.o
+CTL_OBJS += tap-ctl-major.o
+CTL_OBJS += tap-ctl-check.o
+
+CTL_PICS = $(patsubst %.o,%.opic,$(CTL_OBJS))
+
+OBJS = $(CTL_OBJS) tap-ctl.o
+PICS = $(CTL_PICS)
+
+LIB_STATIC = $(LIBNAME).a
+LIB_SHARED = $(LIBSONAME).$(MINOR)
+IBIN = tap-ctl
+
+all: build
+
+build: $(IBIN) $(LIB_STATIC) $(LIB_SHARED)
+
+$(LIBNAME).so: $(LIBSONAME)
+ ln -sf $< $@
+
+$(LIBSONAME): $(LIB_SHARED)
+ ln -sf $< $@
+
+tap-ctl: tap-ctl.o $(LIBNAME).so
+ $(CC) $(LDFLAGS) -o $@ $^ $(APPEND_LDFLAGS)
+
+$(LIB_STATIC): $(CTL_OBJS)
+ $(AR) r $@ $^
+
+$(LIB_SHARED): $(CTL_PICS)
+ $(CC) $(LDFLAGS) -fPIC -Wl,$(SONAME_LDFLAG) -Wl,$(LIBSONAME)
$(SHLIB_LDFLAGS) -rdynamic $^ -o $@ $(APPEND_LDFLAGS)
+
+install: $(IBIN) $(LIB_STATIC) $(LIB_SHARED)
+ $(INSTALL_DIR) -p $(DESTDIR)$(sbindir)
+ $(INSTALL_PROG) $(IBIN) $(DESTDIR)$(sbindir)
+ $(INSTALL_DATA) $(LIB_STATIC) $(DESTDIR)$(libdir)
+ $(INSTALL_PROG) $(LIB_SHARED) $(DESTDIR)$(libdir)
+ ln -sf $(LIBSONAME) $(DESTDIR)$(libdir)/$(LIBNAME).so
+ ln -sf $(LIB_SHARED) $(DESTDIR)$(libdir)/$(LIBSONAME)
+
+clean:
+ rm -f $(OBJS) $(PICS) $(DEPS) $(IBIN) $(LIB_STATIC) $(LIB_SHARED)
+ rm -f $(LIBNAME).so $(LIBSONAME)
+ rm -f *~
+
+distclean: clean
+
+.PHONY: all build clean distclean install
+
+-include $(DEPS)
diff --git a/tools/blktap2/control/tap-ctl-allocate.c
b/tools/blktap2/control/tap-ctl-allocate.c
new file mode 100644
index 0000000..8a6471e
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-allocate.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/major.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+static int
+tap_ctl_prepare_directory(const char *dir)
+{
+ int err;
+ char *ptr, *name, *start;
+
+ err = access(dir, W_OK | R_OK);
+ if (!err)
+ return 0;
+
+ name = strdup(dir);
+ if (!name)
+ return ENOMEM;
+
+ start = name;
+
+ for (;;) {
+ ptr = strchr(start + 1, '/');
+ if (ptr)
+ *ptr = '\0';
+
+ err = mkdir(name, 0755);
+ if (err && errno != EEXIST) {
+ PERROR("mkdir %s", name);
+ err = errno;
+ break;
+ }
+
+ if (!ptr)
+ break;
+ else {
+ *ptr = '/';
+ start = ptr + 1;
+ }
+ }
+
+ free(name);
+ return err;
+}
+
+static int
+tap_ctl_make_device(const char *devname, const int major,
+ const int minor, const int perm)
+{
+ int err;
+ char *copy, *dir;
+
+ copy = strdup(devname);
+ if (!copy)
+ return ENOMEM;
+
+ dir = dirname(copy);
+
+ err = tap_ctl_prepare_directory(dir);
+ free(copy);
+
+ if (err)
+ return err;
+
+ if (!access(devname, F_OK))
+ if (unlink(devname)) {
+ PERROR("unlink %s", devname);
+ return errno;
+ }
+
+ err = mknod(devname, perm, makedev(major, minor));
+ if (err) {
+ PERROR("mknod %s", devname);
+ return errno;
+ }
+
+ return 0;
+}
+
+static int
+tap_ctl_check_environment(void)
+{
+ FILE *f;
+ int err, minor;
+ char name[256];
+
+ err = tap_ctl_prepare_directory(BLKTAP2_CONTROL_DIR);
+ if (err)
+ return err;
+
+ if (!access(BLKTAP2_CONTROL_DEVICE, R_OK | W_OK))
+ return 0;
+
+ memset(name, 0, sizeof(name));
+
+ f = fopen("/proc/misc", "r");
+ if (!f) {
+ EPRINTF("failed to open /proc/misc: %d\n", errno);
+ return errno;
+ }
+
+ while (fscanf(f, "%d %256s", &minor, name) == 2)
+ if (!strcmp(name, BLKTAP2_CONTROL_NAME)) {
+ err = tap_ctl_make_device(BLKTAP2_CONTROL_DEVICE,
+ MISC_MAJOR,
+ minor, S_IFCHR | 0600);
+ goto out;
+ }
+
+ err = ENOSYS;
+ EPRINTF("didn't find %s in /proc/misc\n", BLKTAP2_CONTROL_NAME);
+
+out:
+ fclose(f);
+ return err;
+}
+
+static int
+tap_ctl_allocate_device(int *minor, char **devname)
+{
+ char *name;
+ int fd, err;
+ struct blktap2_handle handle;
+
+ *minor = -1;
+ if (!devname)
+ return EINVAL;
+
+ fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
+ if (fd == -1) {
+ EPRINTF("failed to open control device: %d\n", errno);
+ return errno;
+ }
+
+ err = ioctl(fd, BLKTAP2_IOCTL_ALLOC_TAP, &handle);
+ close(fd);
+ if (err == -1) {
+ EPRINTF("failed to allocate new device: %d\n", errno);
+ return errno;
+ }
+
+ err = asprintf(&name, "%s%d", BLKTAP2_RING_DEVICE, handle.minor);
+ if (err == -1) {
+ err = ENOMEM;
+ goto fail;
+ }
+
+ err = tap_ctl_make_device(name, handle.ring,
+ handle.minor, S_IFCHR | 0600);
+ free(name);
+ if (err) {
+ EPRINTF("creating ring device for %d failed: %d\n",
+ handle.minor, err);
+ goto fail;
+ }
+
+ if (*devname)
+ name = *devname;
+ else {
+ err = asprintf(&name, "%s%d",
+ BLKTAP2_IO_DEVICE, handle.minor);
+ if (err == -1) {
+ err = ENOMEM;
+ goto fail;
+ }
+ *devname = name;
+ }
+
+ err = tap_ctl_make_device(name, handle.device,
+ handle.minor, S_IFBLK | 0600);
+ if (err) {
+ EPRINTF("creating IO device for %d failed: %d\n",
+ handle.minor, err);
+ goto fail;
+ }
+
+ DBG("new interface: ring: %u, device: %u, minor: %u\n",
+ handle.ring, handle.device, handle.minor);
+
+ *minor = handle.minor;
+ return 0;
+
+fail:
+ tap_ctl_free(handle.minor);
+ return err;
+}
+
+int
+tap_ctl_allocate(int *minor, char **devname)
+{
+ int err;
+
+ *minor = -1;
+
+ err = tap_ctl_check_environment();
+ if (err)
+ return err;
+
+ err = tap_ctl_allocate_device(minor, devname);
+ if (err)
+ return err;
+
+ return 0;
+}
diff --git a/tools/blktap2/control/tap-ctl-attach.c
b/tools/blktap2/control/tap-ctl-attach.c
new file mode 100644
index 0000000..3cb933c
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-attach.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_attach(const int id, const int minor)
+{
+ int err;
+ tapdisk_message_t message;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_ATTACH;
+ message.cookie = minor;
+
+ err = tap_ctl_connect_send_and_receive(id, &message, 5);
+ if (err)
+ return err;
+
+ if (message.type == TAPDISK_MESSAGE_ATTACH_RSP) {
+ err = message.u.response.error;
+ if (err)
+ EPRINTF("attach failed: %d\n", err);
+ } else {
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
+ err = EINVAL;
+ }
+
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-check.c
b/tools/blktap2/control/tap-ctl-check.c
new file mode 100644
index 0000000..e98583a
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-check.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_check_blktap(const char **msg)
+{
+ FILE *f;
+ int err = 0, minor;
+ char name[32];
+
+ memset(name, 0, sizeof(name));
+
+ f = fopen("/proc/misc", "r");
+ if (!f) {
+ *msg = "failed to open /proc/misc";
+ return -errno;
+ }
+
+ while (fscanf(f, "%d %32s", &minor, name) == 2) {
+ if (!strcmp(name, BLKTAP2_CONTROL_NAME))
+ goto out;
+ }
+
+ err = -ENOSYS;
+ *msg = "blktap kernel module not installed";
+
+out:
+ fclose(f);
+ return err;
+}
+
+int
+tap_ctl_check(const char **msg)
+{
+ int err;
+ uid_t uid;
+
+ err = tap_ctl_check_blktap(msg);
+ if (err)
+ goto out;
+
+ err = 0;
+ *msg = "ok";
+
+out:
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-close.c
b/tools/blktap2/control/tap-ctl-close.c
new file mode 100644
index 0000000..2e5f80b
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-close.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+static int
+__tap_ctl_close(const int id, const int minor, const int force)
+{
+ int err;
+ tapdisk_message_t message;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_CLOSE;
+ if (force)
+ message.type = TAPDISK_MESSAGE_FORCE_SHUTDOWN;
+ message.cookie = minor;
+
+ err = tap_ctl_connect_send_and_receive(id, &message, 5);
+ if (err)
+ return err;
+
+ if (message.type == TAPDISK_MESSAGE_CLOSE_RSP) {
+ err = message.u.response.error;
+ if (err)
+ EPRINTF("close failed: %d\n", err);
+ } else {
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
+ err = EINVAL;
+ }
+
+ return err;
+}
+
+int
+tap_ctl_close(const int id, const int minor, const int force)
+{
+ int i, err;
+
+ for (i = 0; i < 20; i++) {
+ err = __tap_ctl_close(id, minor, force);
+ if (!err)
+ return 0;
+
+ err = (err < 0 ? -err : err);
+ if (err != EAGAIN) {
+ EPRINTF("close failed: %d\n", err);
+ return err;
+ }
+
+ usleep(1000);
+ }
+
+ EPRINTF("close timed out\n");
+ return EIO;
+}
diff --git a/tools/blktap2/control/tap-ctl-create.c
b/tools/blktap2/control/tap-ctl-create.c
new file mode 100644
index 0000000..f4c47f1
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-create.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_create(const char *params, char **devname)
+{
+ int err, id, minor;
+
+ err = tap_ctl_allocate(&minor, devname);
+ if (err)
+ return err;
+
+ id = tap_ctl_spawn();
+ if (id < 0) {
+ err = id;
+ goto destroy;
+ }
+
+ err = tap_ctl_attach(id, minor);
+ if (err)
+ goto destroy;
+
+ err = tap_ctl_open(id, minor, params);
+ if (err)
+ goto detach;
+
+ return 0;
+
+detach:
+ tap_ctl_detach(id, minor);
+destroy:
+ tap_ctl_free(minor);
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-destroy.c
b/tools/blktap2/control/tap-ctl-destroy.c
new file mode 100644
index 0000000..dc5dbaa
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-destroy.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_destroy(const int id, const int minor)
+{
+ int err;
+
+ err = tap_ctl_close(id, minor, 0);
+ if (err)
+ return err;
+
+ err = tap_ctl_detach(id, minor);
+ if (err)
+ return err;
+
+ err = tap_ctl_free(minor);
+ if (err)
+ return err;
+
+ return 0;
+}
diff --git a/tools/blktap2/control/tap-ctl-detach.c
b/tools/blktap2/control/tap-ctl-detach.c
new file mode 100644
index 0000000..7d7bbf3
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-detach.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_detach(const int id, const int minor)
+{
+ int err;
+ tapdisk_message_t message;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_DETACH;
+ message.cookie = minor;
+
+ err = tap_ctl_connect_send_and_receive(id, &message, 5);
+ if (err)
+ return err;
+
+ if (message.type == TAPDISK_MESSAGE_DETACH_RSP) {
+ err = message.u.response.error;
+ if (err < 0)
+ printf("detach failed: %d\n", err);
+ } else {
+ printf("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
+ err = EINVAL;
+ }
+
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-free.c
b/tools/blktap2/control/tap-ctl-free.c
new file mode 100644
index 0000000..9ae7295
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-free.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_free(const int minor)
+{
+ int fd, err;
+
+ fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
+ if (fd == -1) {
+ EPRINTF("failed to open control device: %d\n", errno);
+ return errno;
+ }
+
+ err = ioctl(fd, BLKTAP2_IOCTL_FREE_TAP, minor);
+ close(fd);
+
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-ipc.c
b/tools/blktap2/control/tap-ctl-ipc.c
new file mode 100644
index 0000000..c7e42d9
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-ipc.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int tap_ctl_debug = 0;
+
+int
+tap_ctl_read_message(int fd, tapdisk_message_t *message, int timeout)
+{
+ fd_set readfds;
+ int ret, len, offset;
+ struct timeval tv, *t;
+
+ t = NULL;
+ offset = 0;
+ len = sizeof(tapdisk_message_t);
+
+ if (timeout) {
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ t = &tv;
+ }
+
+ memset(message, 0, sizeof(tapdisk_message_t));
+
+ while (offset < len) {
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ ret = select(fd + 1, &readfds, NULL, NULL, t);
+ if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ else if (FD_ISSET(fd, &readfds)) {
+ ret = read(fd, message + offset, len - offset);
+ if (ret <= 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ offset += ret;
+ } else
+ break;
+ }
+
+ if (offset != len) {
+ EPRINTF("failure reading message\n");
+ return -EIO;
+ }
+
+ DBG("received '%s' message (uuid = %u)\n",
+ tapdisk_message_name(message->type), message->cookie);
+
+ return 0;
+}
+
+int
+tap_ctl_write_message(int fd, tapdisk_message_t *message, int timeout)
+{
+ fd_set writefds;
+ int ret, len, offset;
+ struct timeval tv, *t;
+
+ t = NULL;
+ offset = 0;
+ len = sizeof(tapdisk_message_t);
+
+ if (timeout) {
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ t = &tv;
+ }
+
+ DBG("sending '%s' message (uuid = %u)\n",
+ tapdisk_message_name(message->type), message->cookie);
+
+ while (offset < len) {
+ FD_ZERO(&writefds);
+ FD_SET(fd, &writefds);
+
+ /* we don't bother reinitializing tv. at worst, it will wait a
+ * bit more time than expected. */
+
+ ret = select(fd + 1, NULL, &writefds, NULL, t);
+ if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ else if (FD_ISSET(fd, &writefds)) {
+ ret = write(fd, message + offset, len - offset);
+ if (ret <= 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ offset += ret;
+ } else
+ break;
+ }
+
+ if (offset != len) {
+ EPRINTF("failure writing message\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+tap_ctl_send_and_receive(int sfd, tapdisk_message_t *message, int timeout)
+{
+ int err;
+
+ err = tap_ctl_write_message(sfd, message, timeout);
+ if (err) {
+ EPRINTF("failed to send '%s' message\n",
+ tapdisk_message_name(message->type));
+ return err;
+ }
+
+ err = tap_ctl_read_message(sfd, message, timeout);
+ if (err) {
+ EPRINTF("failed to receive '%s' message\n",
+ tapdisk_message_name(message->type));
+ return err;
+ }
+
+ return 0;
+}
+
+char *
+tap_ctl_socket_name(int id)
+{
+ char *name;
+
+ if (asprintf(&name, "%s/%s%d",
+ BLKTAP2_CONTROL_DIR, BLKTAP2_CONTROL_SOCKET, id) == -1)
+ return NULL;
+
+ return name;
+}
+
+int
+tap_ctl_connect(const char *name, int *sfd)
+{
+ int fd, err;
+ struct sockaddr_un saddr;
+
+ *sfd = -1;
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1) {
+ EPRINTF("couldn't create socket for %s: %d\n", name, errno);
+ return -errno;
+ }
+
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sun_family = AF_UNIX;
+ strcpy(saddr.sun_path, name);
+
+ err = connect(fd, (const struct sockaddr *)&saddr, sizeof(saddr));
+ if (err) {
+ EPRINTF("couldn't connect to %s: %d\n", name, errno);
+ close(fd);
+ return -errno;
+ }
+
+ *sfd = fd;
+ return 0;
+}
+
+int
+tap_ctl_connect_id(int id, int *sfd)
+{
+ int err;
+ char *name;
+
+ *sfd = -1;
+
+ if (id < 0) {
+ EPRINTF("invalid id %d\n", id);
+ return -EINVAL;
+ }
+
+ name = tap_ctl_socket_name(id);
+ if (!name) {
+ EPRINTF("couldn't name socket for %d\n", id);
+ return -ENOMEM;
+ }
+
+ err = tap_ctl_connect(name, sfd);
+ free(name);
+
+ return err;
+}
+
+int
+tap_ctl_connect_send_and_receive(int id, tapdisk_message_t *message, int
timeout)
+{
+ int err, sfd;
+
+ err = tap_ctl_connect_id(id, &sfd);
+ if (err)
+ return err;
+
+ err = tap_ctl_send_and_receive(sfd, message, timeout);
+
+ close(sfd);
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-list.c
b/tools/blktap2/control/tap-ctl-list.c
new file mode 100644
index 0000000..f8d49c3
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-list.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <glob.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+#include "list.h"
+
+static void
+free_list(tap_list_t *entry)
+{
+ if (entry->type) {
+ free(entry->type);
+ entry->type = NULL;
+ }
+
+ if (entry->path) {
+ free(entry->path);
+ entry->path = NULL;
+ }
+
+ free(entry);
+}
+
+int
+_parse_params(const char *params, char **type, char **path)
+{
+ char *ptr;
+ size_t len;
+
+ ptr = strchr(params, ':');
+ if (!ptr)
+ return -EINVAL;
+
+ len = ptr - params;
+
+ *type = strndup(params, len);
+ *path = strdup(params + len + 1);
+
+ if (!*type || !*path) {
+ free(*type);
+ *type = NULL;
+
+ free(*path);
+ *path = NULL;
+
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int
+init_list(tap_list_t *entry,
+ int tap_id, pid_t tap_pid, int vbd_minor, int vbd_state,
+ const char *params)
+{
+ int err = 0;
+
+ entry->id = tap_id;
+ entry->pid = tap_pid;
+ entry->minor = vbd_minor;
+ entry->state = vbd_state;
+
+ if (params)
+ err = _parse_params(params, &entry->type, &entry->path);
+
+ return err;
+}
+
+void
+tap_ctl_free_list(tap_list_t **list)
+{
+ tap_list_t **_entry;
+
+ for (_entry = list; *_entry != NULL; ++_entry)
+ free_list(*_entry);
+
+ free(list);
+}
+
+static tap_list_t**
+tap_ctl_alloc_list(int n)
+{
+ tap_list_t **list, *entry;
+ size_t size;
+ int i;
+
+ size = sizeof(tap_list_t*) * (n+1);
+ list = malloc(size);
+ if (!list)
+ goto fail;
+
+ memset(list, 0, size);
+
+ for (i = 0; i < n; ++i) {
+ tap_list_t *entry;
+
+ entry = malloc(sizeof(tap_list_t));
+ if (!entry)
+ goto fail;
+
+ memset(entry, 0, sizeof(tap_list_t));
+
+ list[i] = entry;
+ }
+
+ return list;
+
+fail:
+ if (list)
+ tap_ctl_free_list(list);
+
+ return NULL;
+}
+
+static int
+tap_ctl_list_length(const tap_list_t **list)
+{
+ const tap_list_t **_entry;
+ int n;
+
+ n = 0;
+ for (_entry = list; *_entry != NULL; ++_entry)
+ n++;
+
+ return n;
+}
+
+static int
+_tap_minor_cmp(const void *a, const void *b)
+{
+ return *(int*)a - *(int*)b;
+}
+
+int
+_tap_ctl_find_minors(int **_minorv)
+{
+ glob_t glbuf = { 0 };
+ const char *pattern, *format;
+ int *minorv = NULL, n_minors = 0;
+ int err, i;
+
+ pattern = BLKTAP2_SYSFS_DIR"/blktap*";
+ format = BLKTAP2_SYSFS_DIR"/blktap%d";
+
+ n_minors = 0;
+ minorv = NULL;
+
+ err = glob(pattern, 0, NULL, &glbuf);
+ switch (err) {
+ case GLOB_NOMATCH:
+ goto done;
+
+ case GLOB_ABORTED:
+ case GLOB_NOSPACE:
+ err = -errno;
+ EPRINTF("%s: glob failed, err %d", pattern, err);
+ goto fail;
+ }
+
+ minorv = malloc(sizeof(int) * glbuf.gl_pathc);
+ if (!minorv) {
+ err = -errno;
+ goto fail;
+ }
+
+ for (i = 0; i < glbuf.gl_pathc; ++i) {
+ int n;
+
+ n = sscanf(glbuf.gl_pathv[i], format, &minorv[n_minors]);
+ if (n != 1)
+ continue;
+
+ n_minors++;
+ }
+
+ qsort(minorv, n_minors, sizeof(int), _tap_minor_cmp);
+
+done:
+ *_minorv = minorv;
+ err = 0;
+
+out:
+ if (glbuf.gl_pathv)
+ globfree(&glbuf);
+
+ return err ? : n_minors;
+
+fail:
+ if (minorv)
+ free(minorv);
+
+ goto out;
+}
+
+struct tapdisk {
+ int id;
+ pid_t pid;
+ struct list_head list;
+};
+
+static int
+_tap_tapdisk_cmp(const void *a, const void *b)
+{
+ return ((struct tapdisk*)a)->id - ((struct tapdisk*)b)->id;
+}
+
+int
+_tap_ctl_find_tapdisks(struct tapdisk **_tapv)
+{
+ glob_t glbuf = { 0 };
+ const char *pattern, *format;
+ struct tapdisk *tapv = NULL;
+ int err, i, n_taps = 0;
+
+ pattern = BLKTAP2_CONTROL_DIR"/"BLKTAP2_CONTROL_SOCKET"*";
+ format = BLKTAP2_CONTROL_DIR"/"BLKTAP2_CONTROL_SOCKET"%d";
+
+ n_taps = 0;
+ tapv = NULL;
+
+ err = glob(pattern, 0, NULL, &glbuf);
+ switch (err) {
+ case GLOB_NOMATCH:
+ goto done;
+
+ case GLOB_ABORTED:
+ case GLOB_NOSPACE:
+ err = -errno;
+ EPRINTF("%s: glob failed, err %d", pattern, err);
+ goto fail;
+ }
+
+ tapv = malloc(sizeof(struct tapdisk) * glbuf.gl_pathc);
+ if (!tapv) {
+ err = -errno;
+ goto fail;
+ }
+
+ for (i = 0; i < glbuf.gl_pathc; ++i) {
+ struct tapdisk *tap;
+ int n;
+
+ tap = &tapv[n_taps];
+
+ err = sscanf(glbuf.gl_pathv[i], format, &tap->id);
+ if (err != 1)
+ continue;
+
+ tap->pid = tap_ctl_get_pid(tap->id);
+ if (tap->pid < 0)
+ continue;
+
+ n_taps++;
+ }
+
+ qsort(tapv, n_taps, sizeof(struct tapdisk), _tap_tapdisk_cmp);
+
+ for (i = 0; i < n_taps; ++i)
+ INIT_LIST_HEAD(&tapv[i].list);
+
+done:
+ *_tapv = tapv;
+ err = 0;
+
+out:
+ if (glbuf.gl_pathv)
+ globfree(&glbuf);
+
+ return err ? : n_taps;
+
+fail:
+ if (tapv)
+ free(tapv);
+
+ goto out;
+}
+
+struct tapdisk_list {
+ int minor;
+ int state;
+ char *params;
+ struct list_head entry;
+};
+
+int
+_tap_ctl_list_tapdisk(int id, struct list_head *_list)
+{
+ tapdisk_message_t message;
+ struct list_head list;
+ struct tapdisk_list *tl, *next;
+ int err, sfd;
+
+ err = tap_ctl_connect_id(id, &sfd);
+ if (err)
+ return err;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_LIST;
+ message.cookie = -1;
+
+ err = tap_ctl_write_message(sfd, &message, 2);
+ if (err)
+ return err;
+
+ INIT_LIST_HEAD(&list);
+ do {
+ err = tap_ctl_read_message(sfd, &message, 2);
+ if (err) {
+ err = -EPROTO;
+ break;
+ }
+
+ if (message.u.list.count == 0)
+ break;
+
+ tl = malloc(sizeof(struct tapdisk_list));
+ if (!tl) {
+ err = -ENOMEM;
+ break;
+ }
+
+ tl->minor = message.u.list.minor;
+ tl->state = message.u.list.state;
+ if (message.u.list.path[0] != 0) {
+ tl->params = strndup(message.u.list.path,
+ sizeof(message.u.list.path));
+ if (!tl->params) {
+ err = -errno;
+ break;
+ }
+ } else
+ tl->params = NULL;
+
+ list_add(&tl->entry, &list);
+ } while (1);
+
+ if (err)
+ list_for_each_entry_safe(tl, next, &list, entry) {
+ list_del(&tl->entry);
+ free(tl->params);
+ free(tl);
+ }
+
+ close(sfd);
+ list_splice(&list, _list);
+ return err;
+}
+
+void
+_tap_ctl_free_tapdisks(struct tapdisk *tapv, int n_taps)
+{
+ struct tapdisk *tap;
+
+ for (tap = tapv; tap < &tapv[n_taps]; ++tap) {
+ struct tapdisk_list *tl, *next;
+
+ list_for_each_entry_safe(tl, next, &tap->list, entry) {
+ free(tl->params);
+ free(tl);
+ }
+ }
+
+ free(tapv);
+}
+
+int
+_tap_list_join3(int n_minors, int *minorv, int n_taps, struct tapdisk *tapv,
+ tap_list_t ***_list)
+{
+ tap_list_t **list, **_entry;
+ int i, _m, err;
+
+ list = tap_ctl_alloc_list(n_minors + n_taps);
+ if (!list) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ _entry = list;
+
+ for (i = 0; i < n_taps; ++i) {
+ struct tapdisk *tap = &tapv[i];
+ struct tapdisk_list *tl;
+
+ /* orphaned tapdisk */
+ if (list_empty(&tap->list)) {
+ err = init_list(*_entry++, tap->id, tap->pid, -1, -1,
NULL);
+ if (err)
+ goto fail;
+ continue;
+ }
+
+ list_for_each_entry(tl, &tap->list, entry) {
+
+ err = init_list(*_entry++,
+ tap->id, tap->pid,
+ tl->minor, tl->state, tl->params);
+ if (err)
+ goto fail;
+
+ if (tl->minor >= 0) {
+ /* clear minor */
+ for (_m = 0; _m < n_minors; ++_m) {
+ if (minorv[_m] == tl->minor) {
+ minorv[_m] = -1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* orphaned minors */
+ for (_m = 0; _m < n_minors; ++_m) {
+ int minor = minorv[_m];
+ if (minor >= 0) {
+ err = init_list(*_entry++, -1, -1, minor, -1, NULL);
+ if (err)
+ goto fail;
+ }
+ }
+
+ /* free extraneous list entries */
+ for (; *_entry != NULL; ++_entry) {
+ free_list(*_entry);
+ *_entry = NULL;
+ }
+
+ *_list = list;
+
+ return 0;
+
+fail:
+ if (list)
+ tap_ctl_free_list(list);
+
+ return err;
+}
+
+int
+tap_ctl_list(tap_list_t ***list)
+{
+ int n_taps, n_minors, err, *minorv;
+ struct tapdisk *tapv, *tap;
+
+ n_taps = -1;
+ n_minors = -1;
+
+ err = n_minors = _tap_ctl_find_minors(&minorv);
+ if (err < 0)
+ goto out;
+
+ err = n_taps = _tap_ctl_find_tapdisks(&tapv);
+ if (err < 0)
+ goto out;
+
+ for (tap = tapv; tap < &tapv[n_taps]; ++tap) {
+ err = _tap_ctl_list_tapdisk(tap->id, &tap->list);
+ if (err)
+ goto out;
+ }
+
+ err = _tap_list_join3(n_minors, minorv, n_taps, tapv, list);
+
+out:
+ if (n_taps > 0)
+ _tap_ctl_free_tapdisks(tapv, n_taps);
+
+ if (n_minors > 0)
+ free(minorv);
+
+ return err;
+}
+
+int
+tap_ctl_find(const char *type, const char *path, tap_list_t *tap)
+{
+ tap_list_t **list, **_entry;
+ int ret = -ENOENT, err;
+
+ err = tap_ctl_list(&list);
+ if (err)
+ return err;
+
+ for (_entry = list; *_entry != NULL; ++_entry) {
+ tap_list_t *entry = *_entry;
+
+ if (type && (!entry->type || strcmp(entry->type, type)))
+ continue;
+
+ if (path && (!entry->path || strcmp(entry->path, path)))
+ continue;
+
+ *tap = *entry;
+ tap->type = tap->path = NULL;
+ ret = 0;
+ break;
+ }
+
+ tap_ctl_free_list(list);
+
+ return ret;
+}
diff --git a/tools/blktap2/control/tap-ctl-major.c
b/tools/blktap2/control/tap-ctl-major.c
new file mode 100644
index 0000000..847af28
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-major.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_blk_major(void)
+{
+ FILE *devices;
+ int rv, major;
+
+ devices = fopen("/proc/devices", "r");
+ if (!devices) {
+ rv = -errno;
+ goto out;
+ }
+
+ do {
+ char buf[32], *s;
+ int n, offset;
+
+ s = fgets(buf, sizeof(buf), devices);
+ if (!s)
+ break;
+
+ major = -ENODEV;
+ offset = 0;
+
+ n = sscanf(buf, "%d tapdev%n", &major, &offset);
+ if (n == 1 && offset)
+ break;
+ } while (1);
+
+ rv = major;
+
+out:
+ if (devices)
+ fclose(devices);
+
+ return rv;
+}
diff --git a/tools/blktap2/control/tap-ctl-open.c
b/tools/blktap2/control/tap-ctl-open.c
new file mode 100644
index 0000000..5961c99
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-open.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+#include "blktaplib.h"
+
+int
+tap_ctl_open(const int id, const int minor, const char *params)
+{
+ int err;
+ tapdisk_message_t message;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_OPEN;
+ message.cookie = minor;
+ message.u.params.storage = TAPDISK_STORAGE_TYPE_DEFAULT;
+ message.u.params.devnum = minor;
+
+ err = snprintf(message.u.params.path,
+ sizeof(message.u.params.path) - 1, "%s", params);
+ if (err >= sizeof(message.u.params.path)) {
+ EPRINTF("name too long\n");
+ return ENAMETOOLONG;
+ }
+
+ err = tap_ctl_connect_send_and_receive(id, &message, 5);
+ if (err)
+ return err;
+
+ switch (message.type) {
+ case TAPDISK_MESSAGE_OPEN_RSP:
+ break;
+ case TAPDISK_MESSAGE_ERROR:
+ err = -message.u.response.error;
+ EPRINTF("open failed, err %d\n", err);
+ break;
+ default:
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
+ err = EINVAL;
+ }
+
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-pause.c
b/tools/blktap2/control/tap-ctl-pause.c
new file mode 100644
index 0000000..5e31a58
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-pause.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_pause(const int id, const int minor)
+{
+ int err;
+ tapdisk_message_t message;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_PAUSE;
+ message.cookie = minor;
+
+ err = tap_ctl_connect_send_and_receive(id, &message, 5);
+ if (err)
+ return err;
+
+ if (message.type == TAPDISK_MESSAGE_PAUSE_RSP)
+ err = message.u.response.error;
+ else {
+ err = EINVAL;
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
+ }
+
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl-spawn.c
b/tools/blktap2/control/tap-ctl-spawn.c
new file mode 100644
index 0000000..31a651e
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-spawn.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+static pid_t
+__tap_ctl_spawn(int *readfd)
+{
+ int err, child, channel[2];
+ char *tapdisk;
+
+ if (pipe(channel)) {
+ EPRINTF("pipe failed: %d\n", errno);
+ return -errno;
+ }
+
+ if ((child = fork()) == -1) {
+ EPRINTF("fork failed: %d\n", errno);
+ return -errno;
+ }
+
+ if (child) {
+ close(channel[1]);
+ *readfd = channel[0];
+ return child;
+ }
+
+ if (dup2(channel[1], STDOUT_FILENO) == -1) {
+ EPRINTF("dup2 failed: %d\n", errno);
+ exit(errno);
+ }
+
+ if (dup2(channel[1], STDERR_FILENO) == -1) {
+ EPRINTF("dup2 failed: %d\n", errno);
+ exit(errno);
+ }
+
+ close(channel[0]);
+ close(channel[1]);
+
+ tapdisk = getenv("TAPDISK2");
+ if (!tapdisk)
+ tapdisk = "tapdisk2";
+
+ execlp(tapdisk, tapdisk, NULL);
+
+ EPRINTF("exec failed\n");
+ exit(1);
+}
+
+pid_t
+tap_ctl_get_pid(const int id)
+{
+ int err;
+ tapdisk_message_t message;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_PID;
+
+ err = tap_ctl_connect_send_and_receive(id, &message, 2);
+ if (err)
+ return err;
+
+ return message.u.tapdisk_pid;
+}
+
+static int
+tap_ctl_wait(pid_t child)
+{
+ pid_t pid;
+ int status;
+
+ pid = waitpid(child, &status, 0);
+ if (pid < 0) {
+ EPRINTF("wait(%d) failed, err %d\n", child, errno);
+ return -errno;
+ }
+
+ if (WIFEXITED(status)) {
+ int code = WEXITSTATUS(status);
+ if (code)
+ EPRINTF("tapdisk2[%d] failed, status %d\n", child,
code);
+ return -code;
+ }
+
+ if (WIFSIGNALED(status)) {
+ int signo = WTERMSIG(status);
+ EPRINTF("tapdisk2[%d] killed by signal %d\n", child, signo);
+ return -EINTR;
+ }
+
+ EPRINTF("tapdisk2[%d]: unexpected status %#x\n", child, status);
+ return -EAGAIN;
+}
+
+static int
+tap_ctl_get_child_id(int readfd)
+{
+ int id;
+ FILE *f;
+
+ f = fdopen(readfd, "r");
+ if (!f) {
+ EPRINTF("fdopen failed: %d\n", errno);
+ return -1;
+ }
+
+ errno = 0;
+ if (fscanf(f, BLKTAP2_CONTROL_DIR"/"
+ BLKTAP2_CONTROL_SOCKET"%d", &id) != 1) {
+ errno = (errno ? : EINVAL);
+ EPRINTF("parsing id failed: %d\n", errno);
+ id = -1;
+ }
+
+ fclose(f);
+ return id;
+}
+
+int
+tap_ctl_spawn(void)
+{
+ pid_t child;
+ int err, id, readfd;
+
+ readfd = -1;
+
+ child = __tap_ctl_spawn(&readfd);
+ if (child < 0)
+ return child;
+
+ err = tap_ctl_wait(child);
+ if (err)
+ return err;
+
+ id = tap_ctl_get_child_id(readfd);
+ if (id < 0)
+ EPRINTF("get_id failed, child %d err %d\n", child, errno);
+
+ return id;
+}
diff --git a/tools/blktap2/control/tap-ctl-unpause.c
b/tools/blktap2/control/tap-ctl-unpause.c
new file mode 100644
index 0000000..dfb7450
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl-unpause.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+int
+tap_ctl_unpause(const int id, const int minor, const char *params)
+{
+ int err;
+ tapdisk_message_t message;
+
+ memset(&message, 0, sizeof(message));
+ message.type = TAPDISK_MESSAGE_RESUME;
+ message.cookie = minor;
+
+ if (params)
+ strncpy(message.u.params.path, params,
+ sizeof(message.u.params.path) - 1);
+
+ err = tap_ctl_connect_send_and_receive(id, &message, 15);
+ if (err)
+ return err;
+
+ if (message.type == TAPDISK_MESSAGE_RESUME_RSP)
+ err = message.u.response.error;
+ else {
+ err = EINVAL;
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
+ }
+
+ return err;
+}
diff --git a/tools/blktap2/control/tap-ctl.c b/tools/blktap2/control/tap-ctl.c
new file mode 100644
index 0000000..e254f07
--- /dev/null
+++ b/tools/blktap2/control/tap-ctl.c
@@ -0,0 +1,815 @@
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "tap-ctl.h"
+
+typedef int (*tap_ctl_func_t) (int, char **);
+
+struct command {
+ char *name;
+ tap_ctl_func_t func;
+};
+
+static void
+tap_cli_list_usage(FILE *stream)
+{
+ fprintf(stream,
+ "usage: list [-h] [-p pid] [-m minor] [-t type] [-f file]\n");
+}
+
+static void
+tap_ctl_list_row(tap_list_t *entry)
+{
+ char minor_str[10] = "-";
+ char state_str[10] = "-";
+ char pid_str[10] = "-";
+
+ if (entry->pid != -1)
+ sprintf(pid_str, "%d", entry->pid);
+
+ if (entry->minor != -1)
+ sprintf(minor_str, "%d", entry->minor);
+
+ if (entry->state != -1)
+ sprintf(state_str, "%x", entry->state);
+
+ printf("%8s %2s %4s %10s %s\n",
+ pid_str, minor_str, state_str,
+ entry->type ? : "-", entry->path ? : "-");
+}
+
+static void
+tap_ctl_list_dict(tap_list_t *entry)
+{
+ int d = 0;
+
+ if (entry->pid != -1) {
+ if (d) putc(' ', stdout);
+ d = printf("pid=%d", entry->pid);
+ }
+
+ if (entry->minor != -1) {
+ if (d) putc(' ', stdout);
+ d = printf("minor=%d", entry->minor);
+ }
+
+ if (entry->state != -1) {
+ if (d) putc(' ', stdout);
+ d = printf("state=%d", entry->state);
+ }
+
+ if (entry->type && entry->path) {
+ if (d) putc(' ', stdout);
+ d = printf("args=%s:%s", entry->type, entry->path);
+ }
+
+ putc('\n', stdout);
+}
+
+int
+tap_cli_list(int argc, char **argv)
+{
+ tap_list_t **list, **_entry;
+ int c, minor, tty, err;
+ const char *type, *file;
+ pid_t pid;
+
+ err = tap_ctl_list(&list);
+ if (err)
+ return -err;
+
+ pid = -1;
+ minor = -1;
+ type = NULL;
+ file = NULL;
+
+ while ((c = getopt(argc, argv, "m:p:t:f:h")) != -1) {
+ switch (c) {
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case 'p':
+ pid = atoi(optarg);
+ break;
+ case 't':
+ type = optarg;
+ break;
+ case 'f':
+ file = optarg;
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_list_usage(stdout);
+ return 0;
+ }
+ }
+
+ tty = isatty(STDOUT_FILENO);
+
+ for (_entry = list; *_entry != NULL; ++_entry) {
+ tap_list_t *entry = *_entry;
+
+ if (minor >= 0 && entry->minor != minor)
+ continue;
+
+ if (pid >= 0 && entry->pid != pid)
+ continue;
+
+ if (type && (!entry->type || strcmp(entry->type, type)))
+ continue;
+
+ if (file && (!entry->path || strcmp(entry->path, file)))
+ continue;
+
+ if (tty)
+ tap_ctl_list_row(entry);
+ else
+ tap_ctl_list_dict(entry);
+ }
+
+ tap_ctl_free_list(list);
+
+ return 0;
+
+usage:
+ tap_cli_list_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_allocate_usage(FILE *stream)
+{
+ fprintf(stream, "usage: allocate [-d device name]>\n");
+}
+
+static int
+tap_cli_allocate(int argc, char **argv)
+{
+ char *devname;
+ int c, minor, err;
+
+ devname = NULL;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "d:h")) != -1) {
+ switch (c) {
+ case 'd':
+ devname = optarg;
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_allocate_usage(stdout);
+ return 0;
+ }
+ }
+
+ err = tap_ctl_allocate(&minor, &devname);
+ if (!err)
+ printf("%s\n", devname);
+
+ return err;
+
+usage:
+ tap_cli_allocate_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_free_usage(FILE *stream)
+{
+ fprintf(stream, "usage: free <-m minor>\n");
+}
+
+static int
+tap_cli_free(int argc, char **argv)
+{
+ int c, minor;
+
+ minor = -1;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "m:h")) != -1) {
+ switch (c) {
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_free_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (minor == -1)
+ goto usage;
+
+ return tap_ctl_free(minor);
+
+usage:
+ tap_cli_free_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_create_usage(FILE *stream)
+{
+ fprintf(stream, "usage: create <-a args> [-d device name]\n");
+}
+
+static int
+tap_cli_create(int argc, char **argv)
+{
+ int c, err;
+ char *args, *devname;
+
+ args = NULL;
+ devname = NULL;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "a:d:h")) != -1) {
+ switch (c) {
+ case 'a':
+ args = optarg;
+ break;
+ case 'd':
+ devname = optarg;
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_create_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (!args)
+ goto usage;
+
+ err = tap_ctl_create(args, &devname);
+ if (!err)
+ printf("%s\n", devname);
+
+ return err;
+
+usage:
+ tap_cli_create_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_destroy_usage(FILE *stream)
+{
+ fprintf(stream, "usage: destroy <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_destroy(int argc, char **argv)
+{
+ int c, pid, minor;
+
+ pid = -1;
+ minor = -1;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+ switch (c) {
+ case 'p':
+ pid = atoi(optarg);
+ break;
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_destroy_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (pid == -1 || minor == -1)
+ goto usage;
+
+ return tap_ctl_destroy(pid, minor);
+
+usage:
+ tap_cli_destroy_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_spawn_usage(FILE *stream)
+{
+ fprintf(stream, "usage: spawn\n");
+}
+
+static int
+tap_cli_spawn(int argc, char **argv)
+{
+ int c;
+ pid_t task;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "h")) != -1) {
+ switch (c) {
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_spawn_usage(stdout);
+ return 0;
+ }
+ }
+
+ task = tap_ctl_spawn();
+ if (task < 0) {
+ printf("spawn failed: %d\n", errno);
+ return task;
+ }
+
+ printf("tapdisk spawned with pid %d\n", task);
+ return 0;
+
+usage:
+ tap_cli_spawn_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_attach_usage(FILE *stream)
+{
+ fprintf(stream, "usage: attach <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_attach(int argc, char **argv)
+{
+ int c, pid, minor;
+
+ pid = -1;
+ minor = -1;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+ switch (c) {
+ case 'p':
+ pid = atoi(optarg);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |