--- /dev/null
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <xseg/xseg.h>
+#include <xseg/protocol.h>
+
+#define MAX_ARG_LEN 255
+int safe_strlen(char *s)
+{
+ int i;
+ if (!s)
+ return -1;
+
+ for (i = 0; i < MAX_ARG_LEN; i++) {
+ if (!s)
+ break;
+ s++;
+ }
+ if (i == MAX_ARG_LEN)
+ return -1;
+
+ return i;
+}
+
+int validate_alphanumeric(char *s)
+{
+ int i;
+ int len = safe_strlen(s);
+ if (len < 0)
+ return -1;
+
+ for (i = 0; i < len; i++) {
+ if (!isalnum(s))
+ return -1;
+ s++;
+ }
+ return 0;
+}
+
+int validate_numeric(char *s)
+{
+ int i;
+ int len = safe_strlen(s);
+ if (len < 0)
+ return -1;
+
+ for (i = 0; i < len; i++) {
+ if (!isdigit(s))
+ return -1;
+ s++;
+ }
+ return 0;
+}
+
+char *spec = "segdev:xsegbd:16:1024:12";
+struct xseg *xseg;
+struct xseg_config cfg;
+xport srcport = NoPort;
+xport sport = NoPort;
+struct xseg_port *port;
+xport mportno;
+
+static void init_local_signal()
+{
+ if (xseg && sport != srcport){
+ xseg_init_local_signal(xseg, srcport);
+ sport = srcport;
+ }
+}
+
+int wait_reply(struct xseg_request *expected_req)
+{
+ struct xseg_request *rec;
+ xseg_prepare_wait(xseg, srcport);
+ while(1) {
+ rec = xseg_receive(xseg, srcport);
+ if (rec) {
+ if (rec != expected_req) {
+ fprintf(stderr, "Unknown received req. Putting req.\n");
+ xseg_put_request(xseg, rec, srcport);
+ } else if (!(rec->state & XS_SERVED)) {
+ fprintf(stderr, "Failed req\n");
+ return -1;
+ } else {
+ break;
+ }
+ }
+ xseg_wait_signal(xseg, 1000000UL);
+ }
+ xseg_cancel_wait(xseg, srcport);
+
+ return 0;
+}
+
+int vlmc_create(char *name, uint64_t size, char *snap)
+{
+ int targetlen = safe_strlen(name);
+ int snaplen = safe_strlen(snap);
+ if (targetlen <= 0) {
+ fprintf(stderr, "Invalid name\n");
+ return -1;
+ }
+ if (snaplen <= 0 && size == -1) {
+ fprintf(stderr, "Size or snap must be provided in create\n");
+ return -1;
+ }
+
+ struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
+ if (!req) {
+ fprintf(stderr, "Couldn't allocate xseg request\n");
+ return -1;
+ }
+ int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_clone));
+ if (r < 0){
+ fprintf(stderr, "Couldn't prep xseg request\n");
+ xseg_put_request(xseg, req, srcport);
+ return -1;
+ }
+ struct xseg_request_clone *xclone = (struct xseg_request_clone *) xseg_get_data(xseg, req);
+ if (snaplen < 0)
+ memset(xclone->target, 0, XSEG_MAX_TARGETLEN);
+ else {
+ strncpy(xclone->target, snap, snaplen);
+ xclone->target[snaplen] = 0;
+ }
+ xclone->size = size;
+ req->offset = 0;
+ req->size = req->datalen;
+ req->op = X_CLONE;
+
+ xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
+ if (p == NoPort){
+ fprintf(stderr, "couldn't submit req\n");
+ xseg_put_request(xseg, req, srcport);
+ return -1;
+ }
+ xseg_signal(xseg, p);
+
+ wait_reply(req);
+
+ xseg_put_request(xseg, req, srcport);
+
+ return 0;
+}
+
+int vlmc_snapshot(char *name)
+{
+ return -1;
+}
+
+int vlmc_remove(char *name)
+{
+ int targetlen = safe_strlen(name);
+ if (targetlen <= 0) {
+ fprintf(stderr, "Invalid name\n");
+ return -1;
+ }
+
+ struct xseg_request *req = xseg_get_request(xseg, srcport, mportno, X_ALLOC);
+ if (!req) {
+ fprintf(stderr, "Couldn't allocate xseg request\n");
+ return -1;
+ }
+ int r = xseg_prep_request(xseg, req, targetlen, 0);
+ if (r < 0){
+ fprintf(stderr, "Couldn't prep xseg request\n");
+ xseg_put_request(xseg, req, srcport);
+ return -1;
+ }
+ char *target = xseg_get_target(xseg, req);
+ strncpy(target, name, targetlen);
+ target[targetlen] = 0;
+ req->offset = 0;
+ req->size = req->datalen;
+ req->op = X_DELETE;
+
+ xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
+ if (p == NoPort){
+ fprintf(stderr, "couldn't submit req\n");
+ xseg_put_request(xseg, req, srcport);
+ return -1;
+ }
+ xseg_signal(xseg, p);
+
+ wait_reply(req);
+
+ xseg_put_request(xseg, req, srcport);
+
+ return 0;
+}
+
+int vlmc_resize(char *name, uint64_t size)
+{
+ return 0;
+}
+
+int vlmc_map(char *name)
+{
+ /*
+ char cmd[1024];
+ char buf[1024];
+ int fd;
+ xport p;
+
+
+ for (p = 2; p < cfg.nr_ports; p++) {
+ sprintf(buf, "%sdevices/%u/srcport", XSEGBD_SYSFS, p);
+ fd = open(buf, O_RDONLY);
+ if (fd < 0 && errno == ENOENT)
+ break;
+ }
+ if (p == cfg.nr_ports){
+ fprintf(stderr, "No available port\n");
+ return -1;
+ }
+
+ sprintf(cmd, "%s %u:%u:%u", name, p, VPORT, REQS);
+ sprintf(buf, "%sadd", XSEGBD_SYSFS);
+ fd = open(add, O_WRONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open sysfs add\n");
+ return -1;
+ }
+ r = write(fd, cmd, strlen(cmd));
+ if (r < 0){
+ fprintf(stderr, "write error\n");
+ return -1;
+ }
+ */
+
+ return 0;
+}
+
+int vlmc_unmap(char *name)
+{
+ return 0;
+}
+
+int vlmc_list()
+{
+ return 0;
+}
+
+#define err_in_arg(__i, __arg) do { \
+ fprintf(stderr, "Error in argument %d (%s)\n", __i, __arg); \
+ exit(-1); \
+ } while(0)
+
+int main(int argc, const char *argv[])
+{
+ int i;
+ if (argc < 6){
+ fprintf(stderr, "insufficient arguments\n");
+ return -1;
+ }
+
+ spec = argv[1];
+ if (xseg_parse_spec(spec, &cfg)) {
+ fprintf(stderr, "Cannot parse spec\n");
+ return -1;
+ }
+
+ if (xseg_initialize()) {
+ fprintf(stderr, "cannot initialize!\n");
+ return -1;
+ }
+
+ xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
+ if (!xseg) {
+ fprintf(stderr, "cannot join segment!\n");
+ return -1;
+ }
+ init_local_signal();
+
+ char *name = NULL;
+ char *snap = NULL;
+ uint64_t size = -1;
+ char *pool = NULL;
+ char *config = NULL;
+
+ for (i = 3; i < argc; i++) {
+ if ((!strcmp(argv[i], "-s") || !strcmp(argv[i], "--size")) && i+1 < argc){
+ if (!validate_numeric(argv[i+1])){
+ err_in_arg(i, argv[i]);
+ } else {
+ size = atol(argv[i+1]);
+ i++;
+ }
+ }else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && i+1 < argc){
+ if (!validate_alphanumeric(argv[i+1])){
+ err_in_arg(i, argv[i]);
+ } else {
+ config = argv[i+1];
+ i++;
+ }
+ } else if (!strcmp(argv[i], "--snap") && i+1 < argc){
+ if (!validate_alphanumeric(argv[i+1])){
+ err_in_arg(i, argv[i]);
+ } else {
+ snap = argv[i+1];
+ i++;
+ }
+ } else if (!strcmp(argv[i], "-mp") && i+1 < argc){
+ if (!validate_numeric(argv[i+1])){
+ err_in_arg(i, argv[i]);
+ } else {
+ mportno = atol(argv[i+1]);
+ i++;
+ }
+ } else if (!strcmp(argv[i], "-p") && i+1 < argc){
+ if (!validate_alphanumeric(argv[i+1])){
+ err_in_arg(i, argv[i]);
+ } else {
+ srcport = atol(argv[i+1]);
+ i++;
+ }
+ } else if (!strcmp(argv[i], "--name") && i+1 < argc){
+ if (!validate_alphanumeric(argv[i+1])){
+ err_in_arg(i, argv[i]);
+ } else {
+ name = argv[i+1];
+ }
+ } else {
+ err_in_arg(i, argv[i]);
+ }
+ }
+
+ if (srcport > cfg.nr_ports || mportno > cfg.nr_ports) {
+ fprintf(stderr, "Invalid port\n");
+ return -1;
+ }
+
+ port = xseg_bind_port(xseg, srcport);
+ if (!port) {
+ fprintf(stderr, "Error binding port %u\n", srcport);
+ exit(-1);
+ }
+
+ int ret = -1;
+
+ if (!strcmp(argv[2], "create"))
+ ret = vlmc_create(name, size, snap);
+ else if (!strcmp(argv[2], "remove"))
+ ret = vlmc_remove(name);
+/*
+ else if (!strcmp(argv[2], "map"))
+ ret = vlmc_map(name);
+ else if (!strcmp(argv[2], "unmap"))
+ ret = vlmc_unmap(name);
+ else if (!strcmp(argv[2], "showmapped"))
+ ret = vlmc_showmapped();
+ else if (!strcmp(argv[2], "list") || !(strcmp(argv[2], "ls"))
+ ret = vlmc_list();
+*/
+ else if (!strcmp(argv[2], "resize"))
+ ret = vlmc_resize(name, size);
+ else
+ fprintf(stderr, "Unknown action (%s)\n", argv[2]);
+
+ return ret;
+}
+
--- /dev/null
+#!/usr/bin/env python
+#
+# vlmc tool
+
+import os, sys, subprocess, argparse
+
+def vlmc_create(args):
+ name = args.name[0]
+ size = args.size << 20
+ snap = args.snap
+
+ if size == None and snap == None:
+ print >> sys.stderr, "At least one of the size/snap args must be provided"
+ sys.exit(-1)
+
+ cmd = ["/root/archip_rest/xseg/peers/user/vlmc-xseg", "%s" % SPEC, "create", "--name", "%s" % name]
+ if snap != None:
+ cmd.extend("--snap", "%s" % snap)
+ if size != None:
+ cmd.extend("--size", "%s" % size)
+ cmd.extend("-mp", "%s" % MPORT)
+ cmd.extend("-p", "%s" % VTOOL)
+
+ result = utils.RunCmd(cmd)
+ if result.failed:
+ sys.stderr.write("vlmc creation failed\n")
+ sys.exit(-1)
+
+
+def vlmc_snapshot(args):
+ # snapshot
+ return
+
+def vlmc_list(args):
+ # list
+ return
+
+def vlmc_remove(args):
+ name = args.name[0]
+ cmd = ["/root/archip_rest/xseg/peers/user/vlmc-xseg", "%s" % SPEC, "remove", "--name", "%s" % name]
+ cmd.extend("-mp", "%s" % MPORT)
+ cmd.extend("-p", "%s" % VTOOL)
+ result = utils.RunCmd(cmd)
+ if result.failed:
+ sys.stderr.write("vlmc creation failed\n")
+ sys.exit(-1)
+
+
+def xsegbd_loaded():
+ try:
+ os.stat("/sys/bus/xsegbd")
+ except Exception, reason:
+ print >> sys.stderr, reason
+ sys.exit(-1)
+
+def vlmc_map(args):
+ xsegbd_loaded()
+ name = args.name[0]
+ prev = 2
+ try:
+ result = [int(open(XSEGBD_SYSFS + "devices/" + f + "/srcport").read().strip()) for f in os.listdir(XSEGBD_SYSFS + "devices/")]
+ result.sort()
+
+ for p in result:
+ if p - prev > 1:
+ break
+ else:
+ prev = p
+
+ port = prev + 1
+ fd = os.open(XSEGBD_SYSFS + "add", os.O_WRONLY)
+ os.write(fd, "%s %d:%d:%d" % (name, port, VPORT, REQS))
+ os.close(fd)
+ except Exception, reason:
+ print >> sys.stderr, reason
+ sys.exit(-1)
+
+def vlmc_unmap(args):
+ xsegbd_loaded()
+ device = args.name[0]
+ try:
+ for f in os.listdir(XSEGBD_SYSFS + "devices/"):
+ d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
+ name = open(XSEGBD_SYSFS + "devices/"+ f + "/target").read().strip()
+ if device == DEVICE_PREFIX + d_id:
+ fd = os.open(XSEGBD_SYSFS + "remove", os.O_WRONLY)
+ os.write(fd, d_id)
+ os.close(fd)
+
+ sys.exit(0)
+ print >> sys.stderr, "Device %s doesn't exist" % device
+ sys.exit(-1)
+ except Exception, reason:
+ print >> sys.stderr, reason
+ sys.exit(-1)
+
+def vlmc_showmapped(args):
+ xsegbd_loaded()
+ print "id\tpool\timage\tsnap\tdevice"
+ try:
+ for f in os.listdir(XSEGBD_SYSFS + "devices/"):
+ d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
+ target = open(XSEGBD_SYSFS + "devices/"+ f + "/target").read().strip()
+
+ print "%s\t%s\t%s\t%s\t%s" % (d_id, '-', target, '-', DEVICE_PREFIX +
+ d_id)
+ except Exception, reason:
+ print >> sys.stderr, reason
+ sys.exit(-1)
+
+# FIXME:
+def vlmc_resize(args):
+ xsegbd_loaded()
+
+ name = args.name[0]
+ size = args.size[0]
+
+ try:
+
+ for f in os.listdir(XSEGBD_SYSFS + "devices/"):
+ d_id = open(XSEGBD_SYSFS + "devices/" + f + "/id").read().strip()
+ d_name = open(XSEGBD_SYSFS + "devices/"+ f + "/name").read().strip()
+ if name == d_name:
+ fd = os.open(XSEGBD_SYSFS + "devices/" + d_id +"/refresh", os.O_WRONLY)
+ os.write(fd, "1")
+ os.close(fd)
+
+ sys.exit(0)
+ except Exception, reason:
+ print >> sys.stderr, reason
+ sys.exit(-1)
+
+def loadrc(rc):
+ #FIXME
+ try:
+ if rc == None:
+ execfile(os.path.expanduser("~/.xsegrc"), globals())
+ else:
+ execfile(rc, globals())
+ except:
+ pass
+
+if __name__ == "__main__":
+ # parse arguments and discpatch to the correct func
+ parser = argparse.ArgumentParser(description='vlmc tool')
+ parser.add_argument('-c', '--config', type=str, nargs='?', help='config file')
+ subparsers = parser.add_subparsers()
+
+ create_parser = subparsers.add_parser('create', help='Create volume')
+ #group = create_parser.add_mutually_exclusive_group(required=True)
+ create_parser.add_argument('-s', '--size', type=int, nargs='?', help='requested size in MB for create')
+ create_parser.add_argument('--snap', type=str, nargs='?', help='create from snapshot')
+ create_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+ create_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
+ create_parser.set_defaults(func=vlmc_create)
+
+ remove_parser = subparsers.add_parser('remove', help='Delete volume')
+ remove_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
+ remove_parser.set_defaults(func=vlmc_remove)
+ remove_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ rm_parser = subparsers.add_parser('rm', help='Delete volume')
+ rm_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
+ rm_parser.set_defaults(func=vlmc_remove)
+ rm_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ map_parser = subparsers.add_parser('map', help='Map volume')
+ map_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
+ map_parser.set_defaults(func=vlmc_map)
+ map_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ unmap_parser = subparsers.add_parser('unmap', help='Unmap volume')
+ unmap_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
+ unmap_parser.set_defaults(func=vlmc_unmap)
+ unmap_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ showmapped_parser = subparsers.add_parser('showmapped', help='Show mapped volumes')
+ showmapped_parser.set_defaults(func=vlmc_showmapped)
+ showmapped_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ list_parser = subparsers.add_parser('list', help='List volumes')
+ list_parser.set_defaults(func=vlmc_list)
+ list_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ ls_parser = subparsers.add_parser('ls', help='List volumes')
+ ls_parser.set_defaults(func=vlmc_list)
+ ls_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ resize_parser = subparsers.add_parser('resize', help='Resize volume')
+ resize_parser.add_argument('-s', '--size', type=int, nargs=1, help='requested size in MB for resize')
+ resize_parser.add_argument('name', type=str, nargs=1, help='volume/device name')
+ resize_parser.set_defaults(func=vlmc_resize)
+ resize_parser.add_argument('-p', '--pool', type=str, nargs='?', help='for backwards compatiblity with rbd')
+
+ args = parser.parse_args()
+ loadrc(args.config)
+ args.func(args)