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: Xiaodong Liu <xiaodong.liu@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468777 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
parent
4c10e0bbca
commit
9c6e742679
@ -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
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -93,8 +93,22 @@ function blobfs_fuse_test() {
|
||||
# check mount status
|
||||
mount || grep $mount_dir
|
||||
|
||||
# basic file operations in mount dir
|
||||
# create a rand file in mount dir
|
||||
dd if=/dev/urandom of=${mount_dir}/rand_file bs=4k count=32
|
||||
|
||||
umount ${mount_dir}
|
||||
killprocess $blobfs_pid
|
||||
|
||||
# Verify there is no file in mount dir now
|
||||
if [ -f ${mount_dir}/rand_file ]; then
|
||||
false
|
||||
fi
|
||||
|
||||
# use blobfs mount RPC
|
||||
blobfs_start_app
|
||||
$rpc_py blobfs_mount ${bdevname} $mount_dir
|
||||
|
||||
# read and delete the rand file
|
||||
md5sum ${mount_dir}/rand_file
|
||||
rm ${mount_dir}/rand_file
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user