Commit 9c6e7426 authored by Xiaodong Liu's avatar Xiaodong Liu Committed by Tomasz Zawadzki
Browse files

blobfs: add blobfs_mount RPC as FUSE



This RPC method will mount blobfs on bdev to one host
path through FUSE. Then on the host path, user can
directly do some file operations which will be mapped
to blobfs.

Note:
* The FUSE mount of blobfs can be umounted directly by
SHELL umount or fusermount command.

Change-Id: I7c322d978b39bbc7255fced345a749ad5bfa7077
Signed-off-by: default avatarXiaodong Liu <xiaodong.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468777


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
parent 4c10e0bb
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -151,6 +151,10 @@ Added `blobfs_detect` RPC method to detect whether a blobfs exists on given bdev

Added `blobfs_create` RPC method to build blobfs on given bdev.

Added `blobfs_mount` RPC method to mount blobfs on given bdev to a host path by FUSE.
Then on the host path, user can directly do some file operations which will be mapped
to blobfs.

## v19.07:

### ftl
+37 −0
Original line number Diff line number Diff line
@@ -5771,6 +5771,43 @@ Example response:
}
~~~

## blobfs_mount {#rpc_blobfs_mount}

Mount a blobfs on bdev to one host path through FUSE

### Parameters

Name                    | Optional | Type        | Description
----------------------- | -------- | ----------- | -----------
bdev_name               | Required | string      | Block device name where the blobfs is
mountpoint              | Required | string      | Mountpoint path in host to mount blobfs

### Example

Example request:

~~~
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": ""blobfs_mount"",
  "params": {
    "bdev_name": "Malloc0",
    "mountpoint": "/mnt/"
  }
}
~~~

Example response:

~~~
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "true"
}
~~~

# Miscellaneous RPC commands

## bdev_nvme_send_cmd {#rpc_bdev_nvme_send_cmd}
+81 −0
Original line number Diff line number Diff line
@@ -217,3 +217,84 @@ spdk_rpc_blobfs_create(struct spdk_jsonrpc_request *request,
}

SPDK_RPC_REGISTER("blobfs_create", spdk_rpc_blobfs_create, SPDK_RPC_RUNTIME)

#ifdef SPDK_CONFIG_FUSE

struct rpc_blobfs_mount {
	char *bdev_name;
	char *mountpoint;

	struct spdk_jsonrpc_request *request;
};

static void
free_rpc_blobfs_mount(struct rpc_blobfs_mount *req)
{
	free(req->bdev_name);
	free(req->mountpoint);
	free(req);
}

static const struct spdk_json_object_decoder rpc_blobfs_mount_decoders[] = {
	{"bdev_name", offsetof(struct rpc_blobfs_mount, bdev_name), spdk_json_decode_string},
	{"mountpoint", offsetof(struct rpc_blobfs_mount, mountpoint), spdk_json_decode_string},
};

static void
_rpc_blobfs_mount_done(void *cb_arg, int fserrno)
{
	struct rpc_blobfs_mount *req = cb_arg;
	struct spdk_json_write_ctx *w;

	if (fserrno == -EILSEQ) {
		/* There is no blobfs existing on bdev */
		spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
						 "No blobfs detected on given bdev");

		return;
	} else if (fserrno != 0) {
		spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 spdk_strerror(-fserrno));

		return;
	}

	w = spdk_jsonrpc_begin_result(req->request);
	spdk_json_write_bool(w, true);
	spdk_jsonrpc_end_result(req->request, w);

	free_rpc_blobfs_mount(req);
}

static void
spdk_rpc_blobfs_mount(struct spdk_jsonrpc_request *request,
		      const struct spdk_json_val *params)
{
	struct rpc_blobfs_mount *req;

	req = calloc(1, sizeof(*req));
	if (req == NULL) {
		SPDK_ERRLOG("could not allocate rpc_blobfs_mount request.\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
		return;
	}

	if (spdk_json_decode_object(params, rpc_blobfs_mount_decoders,
				    SPDK_COUNTOF(rpc_blobfs_mount_decoders),
				    req)) {
		SPDK_ERRLOG("spdk_json_decode_object failed\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
						 "spdk_json_decode_object failed");

		free_rpc_blobfs_mount(req);

		return;
	}

	req->request = request;
	spdk_blobfs_bdev_mount(req->bdev_name, req->mountpoint, _rpc_blobfs_mount_done, req);
}

SPDK_RPC_REGISTER("blobfs_mount", spdk_rpc_blobfs_mount, SPDK_RPC_RUNTIME)

#endif
+10 −0
Original line number Diff line number Diff line
@@ -2087,6 +2087,16 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
                   help="""Size of cluster in bytes (Optional). Must be multiple of 4KB page size. Default and minimal value is 1M.""")
    p.set_defaults(func=blobfs_create)

    def blobfs_mount(args):
        print(rpc.blobfs.blobfs_mount(args.client,
                                      bdev_name=args.bdev_name,
                                      mountpoint=args.mountpoint))

    p = subparsers.add_parser('blobfs_mount', help='Mount a blobfs on bdev to host path by FUSE')
    p.add_argument('bdev_name', help='Blockdev name where the blobfs is. Example: Malloc0.')
    p.add_argument('mountpoint', help='Mountpoint path in host to mount blobfs. Example: /mnt/.')
    p.set_defaults(func=blobfs_mount)

    def check_called_name(name):
        if name in deprecated_aliases:
            print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr)
+14 −0
Original line number Diff line number Diff line
@@ -26,3 +26,17 @@ def blobfs_create(client, bdev_name, cluster_sz=None):
    if cluster_sz:
        params['cluster_sz'] = cluster_sz
    return client.call('blobfs_create', params)


def blobfs_mount(client, bdev_name, mountpoint):
    """Mount blobfs on bdev by FUSE.

    Args:
        bdev_name: block device name where the blobfs is
        mountpoint: Mountpoint path in host to mount blobfs
    """
    params = {
        'bdev_name': bdev_name,
        'mountpoint': mountpoint
    }
    return client.call('blobfs_mount', params)
Loading