Compare commits
252 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4a4c905b32 | ||
|
dd06b35ed8 | ||
|
b059b49bdf | ||
|
f8a33650d2 | ||
|
fafb7d4741 | ||
|
6a0d4e5ed8 | ||
|
820e7c59bf | ||
|
516639cf37 | ||
|
8d2e6b6711 | ||
|
5cf6cd5f1b | ||
|
3fefff7218 | ||
|
7ad55b80fa | ||
|
3616be85f2 | ||
|
366aabdf69 | ||
|
be79373a97 | ||
|
9c274912d0 | ||
|
559a97aa7c | ||
|
681a5aa459 | ||
|
49d3a5e47c | ||
|
0ba9ba5c40 | ||
|
6b79f76769 | ||
|
e236311e39 | ||
|
72e058bba3 | ||
|
6828ed1807 | ||
|
08650f8629 | ||
|
aee609e17c | ||
|
8b05f7bea6 | ||
|
f7cc6174ef | ||
|
fdeb57c0a1 | ||
|
04bc3962ad | ||
|
d11222e239 | ||
|
479ad83ebe | ||
|
af92c28b9c | ||
|
2dcaa3851f | ||
|
0c1df53e7a | ||
|
bf8f5afa44 | ||
|
1ce7786f42 | ||
|
cec70a601f | ||
|
5bced73616 | ||
|
c9f3613fcd | ||
|
3d9395c69e | ||
|
adc2ca50e9 | ||
|
531258aa51 | ||
|
268078c128 | ||
|
b4d441fd22 | ||
|
10db58ef77 | ||
|
ff12a5ed6a | ||
|
54db60cdb3 | ||
|
a347d3e747 | ||
|
d7b2f5b96e | ||
|
599aee6003 | ||
|
28bcf6a760 | ||
|
7952ef88e0 | ||
|
6ed8bdf7d7 | ||
|
7cb6475ab1 | ||
|
7c528fdbe1 | ||
|
d704e6a025 | ||
|
168bc2673e | ||
|
252aea5fad | ||
|
f6339ffdb7 | ||
|
13b801bf37 | ||
|
f20fbfe65b | ||
|
72a6fff8bb | ||
|
eb8f9bbc99 | ||
|
62c399ffaf | ||
|
2e56512236 | ||
|
4c7b504620 | ||
|
7c30df4ece | ||
|
4045068a32 | ||
|
86bc8a5f13 | ||
|
76f4b77726 | ||
|
54d4e7a631 | ||
|
ca0c4dcde8 | ||
|
831773b220 | ||
|
abf212ea6a | ||
|
18dfb63389 | ||
|
258b7fbff2 | ||
|
29ba5b1b43 | ||
|
8b8a7a80f6 | ||
|
e9d44aa39b | ||
|
fa3f818b4e | ||
|
c976353be8 | ||
|
df4600f4c9 | ||
|
cb97b86081 | ||
|
c441e27023 | ||
|
3a5ebfb06d | ||
|
665e3805f8 | ||
|
3edc534216 | ||
|
50e3b7bf31 | ||
|
4fafd3fe65 | ||
|
baf250e5e4 | ||
|
c0ea96cf5e | ||
|
5b250c0836 | ||
|
5e79e84e78 | ||
|
d453aaa360 | ||
|
a045d8d2fc | ||
|
f3c14b8dee | ||
|
a67e0eb37e | ||
|
3f52d2659e | ||
|
9b8f2ef354 | ||
|
54b4f4dd4b | ||
|
0c31b86a6f | ||
|
0cea6b57f6 | ||
|
b7d84562cb | ||
|
30399f312c | ||
|
712f9aa452 | ||
|
f2dbb50516 | ||
|
87666f5286 | ||
|
8b3dcd6191 | ||
|
09bf2b2092 | ||
|
1db33a8f74 | ||
|
e3babb2be1 | ||
|
55d6cc0eae | ||
|
d7b29fb9d5 | ||
|
7c621ff206 | ||
|
0de931dc6b | ||
|
9a377ecb22 | ||
|
2b1ad70c4c | ||
|
b0c93eb3fb | ||
|
bade2d8db5 | ||
|
e407385e03 | ||
|
aadd13f444 | ||
|
64c27c8dcc | ||
|
b16a4c22c4 | ||
|
4870695014 | ||
|
953b74b9b0 | ||
|
e351b19055 | ||
|
1922700ea7 | ||
|
fb37b8d941 | ||
|
737667e155 | ||
|
26b9be752b | ||
|
f0a2538c04 | ||
|
d33d418742 | ||
|
0ca5304550 | ||
|
982ae8f46c | ||
|
672710c8fc | ||
|
46cfc0484f | ||
|
73293d73eb | ||
|
962671f711 | ||
|
9ab5c8b67a | ||
|
324e3261e6 | ||
|
c5efdd55c2 | ||
|
3e0e077939 | ||
|
5d2d59be8d | ||
|
3824f6e39b | ||
|
31bfcb45b7 | ||
|
97ce07c261 | ||
|
9276019077 | ||
|
06fd87e4e9 | ||
|
ad154aaef2 | ||
|
560164d8da | ||
|
7ce4205ab0 | ||
|
5d25e3fcc8 | ||
|
d8f63f392a | ||
|
63524340a3 | ||
|
6060669e1a | ||
|
fc0214d539 | ||
|
6732946d0a | ||
|
162bf435cb | ||
|
0fa85da9c4 | ||
|
72672d4982 | ||
|
1a526000d0 | ||
|
ee06693c3d | ||
|
f2459a2f26 | ||
|
f135f5ff7f | ||
|
f61e421b05 | ||
|
688f7fb810 | ||
|
4f19ab4d4b | ||
|
0945b976df | ||
|
8ad609857f | ||
|
095f40630e | ||
|
6a4b678402 | ||
|
535543d4f1 | ||
|
54a78f41d2 | ||
|
8ad5671fbb | ||
|
544e2a273b | ||
|
89188e84f1 | ||
|
42567ba294 | ||
|
79e1c3f298 | ||
|
0de1c21570 | ||
|
d478b20ddf | ||
|
0496a2af3b | ||
|
bcd0ea8c1c | ||
|
6693862f9e | ||
|
6b7cca1542 | ||
|
56eced4280 | ||
|
7cc7d52830 | ||
|
1fa3b4f72d | ||
|
4f7ab50650 | ||
|
6b6101c1e7 | ||
|
ed1b4c926c | ||
|
1db41324f7 | ||
|
91ea8102b6 | ||
|
11dc297c1b | ||
|
0cd5af7143 | ||
|
c019eb4d67 | ||
|
943806efab | ||
|
de2609a241 | ||
|
13a2c5589c | ||
|
9754119ac9 | ||
|
22fa84f77a | ||
|
7d5f0ade61 | ||
|
6d7b690584 | ||
|
982a1bb7ed | ||
|
47c2ee6435 | ||
|
98d98ecb57 | ||
|
905c4dcf6f | ||
|
ce6550a935 | ||
|
c1d2bdfeb3 | ||
|
7c764edf85 | ||
|
f8a085a2d5 | ||
|
78df9be449 | ||
|
8247bd4041 | ||
|
b3a5763436 | ||
|
cc54140080 | ||
|
b1a2319686 | ||
|
aaba5d9c9e | ||
|
4bf72c9921 | ||
|
9c636a02f9 | ||
|
8f4d98bb40 | ||
|
a6545ae311 | ||
|
db6297b501 | ||
|
c2e288a625 | ||
|
712ab983df | ||
|
6a55d0dbfa | ||
|
53c5691fdf | ||
|
64aa7a5c16 | ||
|
e951b7689e | ||
|
ed1571eece | ||
|
5b03ae4ec0 | ||
|
66e0ed8e8d | ||
|
94e395631e | ||
|
edfd7ff2d0 | ||
|
b17e84e51e | ||
|
f46d3a2476 | ||
|
53f57b5dff | ||
|
bb9cd3b467 | ||
|
099bdaf3b5 | ||
|
a66276d9b7 | ||
|
75bfce75c2 | ||
|
ae3ae309db | ||
|
86ad46db55 | ||
|
92141ccf21 | ||
|
ce3ffc233b | ||
|
cb9e0db853 | ||
|
30f52282f4 | ||
|
4c0b2d1684 | ||
|
4bb9dcdb7d | ||
|
9bc7d6b34f | ||
|
a9bcb7f261 | ||
|
297182a083 | ||
|
4282294b8a |
@ -67,11 +67,6 @@ New API `spdk_bdev_part_construct_ext` is added and allows the bdev's UUID to be
|
||||
the existing worker and namespace association logic to access every namespace from each worker.
|
||||
This replicates behavior of bdevperf application when `-C` option is provided.
|
||||
|
||||
### util
|
||||
|
||||
New APIs `spdk_uuid_is_null` and `spdk_uuid_set_null` were added to compare and
|
||||
set UUID to NULL value.
|
||||
|
||||
## v23.01
|
||||
|
||||
### accel
|
||||
|
@ -536,11 +536,10 @@ Example commands
|
||||
## RAID {#bdev_ug_raid}
|
||||
|
||||
RAID virtual bdev module provides functionality to combine any SPDK bdevs into
|
||||
one RAID bdev. Currently SPDK supports only RAID 0. RAID metadata may be stored
|
||||
on member disks if enabled when creating the RAID bdev, so user does not have to
|
||||
recreate the RAID volume when restarting application. It is not enabled by
|
||||
default for backward compatibility. User may specify member disks to create
|
||||
RAID volume even if they do not exist yet - as the member disks are registered at
|
||||
one RAID bdev. Currently SPDK supports only RAID 0. RAID functionality does not
|
||||
store on-disk metadata on the member disks, so user must recreate the RAID
|
||||
volume when restarting application. User may specify member disks to create RAID
|
||||
volume event if they do not exists yet - as the member disks are registered at
|
||||
a later time, the RAID module will claim them and will surface the RAID volume
|
||||
after all of the member disks are available. It is allowed to use disks of
|
||||
different sizes - the smallest disk size will be the amount of space used on
|
||||
|
267
doc/jsonrpc.md
267
doc/jsonrpc.md
@ -495,10 +495,6 @@ Example response:
|
||||
"bdev_lvol_delete_lvstore",
|
||||
"bdev_lvol_rename_lvstore",
|
||||
"bdev_lvol_create_lvstore",
|
||||
"bdev_lvol_shallow_copy",
|
||||
"bdev_lvol_set_xattr",
|
||||
"bdev_lvol_get_xattr",
|
||||
"bdev_lvol_get_fragmap",
|
||||
"bdev_daos_delete",
|
||||
"bdev_daos_create",
|
||||
"bdev_daos_resize"
|
||||
@ -5986,7 +5982,6 @@ Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | Bdev name
|
||||
base_bdev_name | Required | string | Base bdev name
|
||||
uuid | Optional | string | UUID of new bdev
|
||||
|
||||
#### Result
|
||||
|
||||
@ -10002,160 +9997,6 @@ Example response:
|
||||
]
|
||||
~~~
|
||||
|
||||
### bdev_lvol_shallow_copy {#rpc_bdev_lvol_shallow_copy}
|
||||
|
||||
Make a shallow copy of lvol over a given bdev. Only cluster allocated to the lvol will be written on the bdev.
|
||||
Must have:
|
||||
|
||||
* lvol read only
|
||||
* lvol size smaller than bdev size
|
||||
* lvstore block size a multiple of bdev size
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
src_lvol_name | Required | string | UUID or alias of lvol to create a copy from
|
||||
dst_bdev_name | Required | string | Name of the bdev that acts as destination for the copy
|
||||
|
||||
### bdev_lvol_set_xattr {#rpc_bdev_lvol_set_xattr}
|
||||
|
||||
Set xattr for lvol bdev
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | UUID or alias of lvol
|
||||
xattr_name | Required | string | Name of the xattr
|
||||
xattr_value | Required | string | Value of the xattr
|
||||
|
||||
### bdev_lvol_get_xattr {#rpc_bdev_lvol_get_xattr}
|
||||
|
||||
Get xattr for lvol bdev
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | UUID or alias of lvol
|
||||
xattr_name | Required | string | Name of the xattr
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_lvol_shallow_copy",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"src_lvol_name": "8a47421a-20cf-444f-845c-d97ad0b0bd8e",
|
||||
"dst_bdev_name": "Nvme1n1"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
### bdev_lvol_shallow_copy_status {#rpc_bdev_lvol_shallow_copy_status}
|
||||
|
||||
Get shallow copy status
|
||||
|
||||
#### Result
|
||||
|
||||
This RPC reports the state of a shallow copy operation, in case of error a description, and
|
||||
operation's advance state in the format _number_of_copied_clusters/total_clusters_to_copy_.
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
src_lvol_name | Required | string | UUID or alias of source lvol
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_lvol_shallow_copy_status",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"src_lvol_name": "8a47421a-20cf-444f-845c-d97ad0b0bd8e"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": {
|
||||
"state": "in progress",
|
||||
"progress": "2/4"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
### bdev_lvol_get_fragmap {#bdev_lvol_get_fragmap}
|
||||
|
||||
Get a fragmap for a specific segment of a logical volume using the provided offset and size.
|
||||
A fragmap is a bitmap that records the allocation status of clusters. A value of "1" indicates
|
||||
that a cluster is allocated, whereas "0" signifies that a cluster is unallocated.
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | UUID or alias of the logical volume
|
||||
offset | Optional | number | Offset in bytes of the specific segment of the logical volume (Default: 0)
|
||||
size | Optional | number | Size in bytes of the specific segment of the logical volume (Default: 0 for representing the entire file)
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_lvol_get_fragmap",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"name": "8a47421a-20cf-444f-845c-d97ad0b0bd8e",
|
||||
"offset": 0,
|
||||
"size": 41943040
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": {
|
||||
"cluster_size": 4194304,
|
||||
"num_clusters": 10,
|
||||
"num_allocated_clusters": 0,
|
||||
"fragmap": "AAA="
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
## RAID
|
||||
|
||||
### bdev_raid_get_bdevs {#rpc_bdev_raid_get_bdevs}
|
||||
@ -10197,54 +10038,26 @@ Example response:
|
||||
"result": [
|
||||
{
|
||||
"name": "RaidBdev0",
|
||||
"uuid": "a0bf80ba-96c1-4a81-a008-ad2d1b4b814c",
|
||||
"strip_size_kb": 128,
|
||||
"state": "online",
|
||||
"raid_level": "raid0",
|
||||
"num_base_bdevs": 2,
|
||||
"num_base_bdevs_discovered": 2,
|
||||
"num_base_bdevs_operational": 2,
|
||||
"base_bdevs_list": [
|
||||
{
|
||||
"name": "malloc0",
|
||||
"uuid": "d2788884-5b3e-4fd7-87ff-6c78177e14ab",
|
||||
"is_configured": true,
|
||||
"data_offset": 256,
|
||||
"data_size": 261888
|
||||
},
|
||||
{
|
||||
"name": "malloc1",
|
||||
"uuid": "a81bb1f8-5865-488a-8758-10152017e7d1",
|
||||
"is_configured": true,
|
||||
"data_offset": 256,
|
||||
"data_size": 261888
|
||||
}
|
||||
"malloc0",
|
||||
"malloc1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "RaidBdev1",
|
||||
"uuid": "f7cb71ed-2d0e-4240-979e-27b0b7735f36",
|
||||
"strip_size_kb": 128,
|
||||
"state": "configuring",
|
||||
"raid_level": "raid0",
|
||||
"num_base_bdevs": 2,
|
||||
"num_base_bdevs_discovered": 1,
|
||||
"num_base_bdevs_operational": 2,
|
||||
"base_bdevs_list": [
|
||||
{
|
||||
"name": "malloc2",
|
||||
"uuid": "f60c20e1-3439-4f89-ae55-965a70333f86",
|
||||
"is_configured": true,
|
||||
"data_offset": 256,
|
||||
"data_size": 261888
|
||||
}
|
||||
{
|
||||
"name": "malloc3",
|
||||
"uuid": "00000000-0000-0000-0000-000000000000",
|
||||
"is_configured": false,
|
||||
"data_offset": 0,
|
||||
"data_size": 0
|
||||
}
|
||||
"malloc2",
|
||||
null
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -10332,78 +10145,6 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
### bdev_raid_remove_base_bdev {#rpc_bdev_raid_remove_base_bdev}
|
||||
|
||||
Remove base bdev from existing raid bdev.
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
name | Required | string | Base bdev name in RAID
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_raid_remove_base_bdev",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"name": "Raid0"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
### bdev_raid_grow_base_bdev {#rpc_bdev_raid_grow_base_bdev}
|
||||
|
||||
Add a base bdev to a raid bdev, growing the raid's size if needed
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
raid_name | Required | string | Raid bdev name
|
||||
base_name | Required | string | Base bdev name
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "bdev_raid_grow_base_bdev",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"raid_name": "Raid1",
|
||||
"base_name": "Nvme1n1",
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
## SPLIT
|
||||
|
||||
### bdev_split_create {#rpc_bdev_split_create}
|
||||
|
@ -197,12 +197,4 @@ bdev_lvol_decouple_parent [-h] name
|
||||
Decouple parent of a logical volume
|
||||
optional arguments:
|
||||
-h, --help show help
|
||||
bdev_lvol_set_xattr [-h] name xattr_name xattr_value
|
||||
Set xattr for lvol bdev
|
||||
optional arguments:
|
||||
-h, --help show help
|
||||
bdev_lvol_get_xattr [-h] name xattr_name
|
||||
Get xattr for lvol bdev
|
||||
optional arguments:
|
||||
-h, --help show help
|
||||
```
|
||||
|
@ -497,14 +497,6 @@ const char *spdk_bdev_get_name(const struct spdk_bdev *bdev);
|
||||
*/
|
||||
const char *spdk_bdev_get_product_name(const struct spdk_bdev *bdev);
|
||||
|
||||
/**
|
||||
* Get block device creation time.
|
||||
*
|
||||
* \param bdev Block device to query.
|
||||
* \return Creation time of bdev as a null-terminated string, or NULL if not present.
|
||||
*/
|
||||
const char *spdk_bdev_get_creation_time(const struct spdk_bdev *bdev);
|
||||
|
||||
/**
|
||||
* Get block device logical block size.
|
||||
*
|
||||
|
@ -513,13 +513,6 @@ struct spdk_bdev {
|
||||
*/
|
||||
struct spdk_uuid uuid;
|
||||
|
||||
/**
|
||||
* Creation time for this bdev.
|
||||
*
|
||||
* If not provided, it will be NULL.
|
||||
*/
|
||||
const char *creation_time;
|
||||
|
||||
/** Size in bytes of a metadata for the backend */
|
||||
uint32_t md_len;
|
||||
|
||||
|
@ -168,14 +168,6 @@ void spdk_bit_array_load_mask(struct spdk_bit_array *ba, const void *mask);
|
||||
*/
|
||||
void spdk_bit_array_clear_mask(struct spdk_bit_array *ba);
|
||||
|
||||
/**
|
||||
* Encode a bit array into a base64 string.
|
||||
*
|
||||
* @param array Bit array to encode.
|
||||
* @return base64 string.
|
||||
*/
|
||||
char *spdk_bit_array_to_base64_string(const struct spdk_bit_array *array);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -515,42 +515,6 @@ uint64_t spdk_blob_get_next_allocated_io_unit(struct spdk_blob *blob, uint64_t o
|
||||
*/
|
||||
uint64_t spdk_blob_get_next_unallocated_io_unit(struct spdk_blob *blob, uint64_t offset);
|
||||
|
||||
/**
|
||||
* Get the number of copied clusters of a shallow copy operation
|
||||
|
||||
* If a shallow copy of the blob is in progress or it is ended, this function returns
|
||||
* the number of copied clusters.
|
||||
*
|
||||
* \param blob Blob struct to query.
|
||||
*
|
||||
* \return number of copied clusters.
|
||||
*/
|
||||
uint64_t spdk_blob_get_shallow_copy_copied_clusters(struct spdk_blob *blob);
|
||||
|
||||
/**
|
||||
* Get the total number of clusters to be copied in a shallow copy operation
|
||||
|
||||
* If a shallow copy of the blob is in progress or it is ended, this function returns
|
||||
* the total number of clusters to be copied.
|
||||
*
|
||||
* \param blob Blob struct to query.
|
||||
*
|
||||
* \return total number of clusters.
|
||||
*/
|
||||
uint64_t spdk_blob_get_shallow_copy_total_clusters(struct spdk_blob *blob);
|
||||
|
||||
/**
|
||||
* Get the result of last shallow copy operation
|
||||
|
||||
* If a shallow copy of the blob is in progress or it is ended, this function returns
|
||||
* the result of the operation.
|
||||
*
|
||||
* \param blob Blob struct to query.
|
||||
*
|
||||
* \return 0 on success, negative errno on failure.
|
||||
*/
|
||||
int spdk_blob_get_shallow_copy_result(struct spdk_blob *blob);
|
||||
|
||||
struct spdk_blob_xattr_opts {
|
||||
/* Number of attributes */
|
||||
size_t count;
|
||||
@ -797,26 +761,6 @@ void spdk_bs_inflate_blob(struct spdk_blob_store *bs, struct spdk_io_channel *ch
|
||||
void spdk_bs_blob_decouple_parent(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
|
||||
spdk_blob_id blobid, spdk_blob_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Perform a shallow copy over a device
|
||||
*
|
||||
* This call make a shallow copy of a blob over an external blobstore block device.
|
||||
* Only cluster allocated to the blob will be written on the device.
|
||||
* Blob size must be smaller than device size.
|
||||
* Blobstore block size must be a multiple of device block size.
|
||||
|
||||
* \param bs Blobstore
|
||||
* \param channel IO channel used to copy the blob.
|
||||
* \param blobid The id of the blob.
|
||||
* \param ext_dev The device to copy on
|
||||
* \param cb_fn Called when the operation is complete.
|
||||
* \param cb_arg Argument passed to function cb_fn.
|
||||
*/
|
||||
void spdk_bs_blob_shallow_copy(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
|
||||
spdk_blob_id blobid, struct spdk_bs_dev *ext_dev,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
|
||||
struct spdk_blob_open_opts {
|
||||
enum blob_clear_method clear_method;
|
||||
|
||||
|
@ -22,7 +22,6 @@ extern "C" {
|
||||
struct spdk_bs_dev;
|
||||
struct spdk_lvol_store;
|
||||
struct spdk_lvol;
|
||||
struct spdk_fragmap;
|
||||
|
||||
enum lvol_clear_method {
|
||||
LVOL_CLEAR_WITH_DEFAULT = BLOB_CLEAR_WITH_DEFAULT,
|
||||
@ -38,8 +37,8 @@ enum lvs_clear_method {
|
||||
};
|
||||
|
||||
/* Must include null terminator. */
|
||||
#define SPDK_LVS_NAME_MAX 256
|
||||
#define SPDK_LVOL_NAME_MAX 256
|
||||
#define SPDK_LVS_NAME_MAX 64
|
||||
#define SPDK_LVOL_NAME_MAX 64
|
||||
|
||||
/**
|
||||
* Parameters for lvolstore initialization.
|
||||
@ -71,7 +70,7 @@ struct spdk_lvs_opts {
|
||||
*/
|
||||
spdk_bs_esnap_dev_create esnap_bs_dev_create;
|
||||
} __attribute__((packed));
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_lvs_opts) == 280, "Incorrect size");
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_lvs_opts) == 88, "Incorrect size");
|
||||
|
||||
/**
|
||||
* Initialize an spdk_lvs_opts structure to the defaults.
|
||||
@ -117,16 +116,6 @@ typedef void (*spdk_lvol_op_with_handle_complete)(void *cb_arg, struct spdk_lvol
|
||||
*/
|
||||
typedef void (*spdk_lvol_op_complete)(void *cb_arg, int lvolerrno);
|
||||
|
||||
/**
|
||||
* Callback definition for lvol operations with handle to fragmap
|
||||
*
|
||||
* @param cb_arg Custom arguments
|
||||
* @param fragmap Handle to fragmap or NULL when lvolerrno is set
|
||||
* @param lvolerrno Error
|
||||
*/
|
||||
typedef void (*spdk_lvol_op_with_fragmap_handle_complete)(void *cb_arg,
|
||||
struct spdk_fragmap *fragmap, int lvolerrno);
|
||||
|
||||
/**
|
||||
* Callback definition for spdk_lvol_iter_clones.
|
||||
*
|
||||
@ -261,31 +250,6 @@ void
|
||||
spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Set lvol's xattr.
|
||||
*
|
||||
* \param lvol Handle to lvol.
|
||||
* \param name xattr name.
|
||||
* \param value xattr value.
|
||||
* \param cb_fn Completion callback.
|
||||
* \param cb_arg Completion callback custom arguments.
|
||||
*/
|
||||
void
|
||||
spdk_lvol_set_xattr(struct spdk_lvol *lvol, const char *name, const char *value,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Get lvol's xattr.
|
||||
*
|
||||
* \param lvol Handle to lvol.
|
||||
* \param name Xattr name.
|
||||
* \param value Xattr value.
|
||||
* \param value_len Xattr value length.
|
||||
*/
|
||||
int
|
||||
spdk_lvol_get_xattr(struct spdk_lvol *lvol, const char *name,
|
||||
const void **value, size_t *value_len);
|
||||
|
||||
/**
|
||||
* \brief Returns if it is possible to delete an lvol (i.e. lvol is not a snapshot that have at least one clone).
|
||||
* \param lvol Handle to lvol
|
||||
@ -417,20 +381,6 @@ void spdk_lvol_decouple_parent(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_
|
||||
*/
|
||||
bool spdk_lvol_is_degraded(const struct spdk_lvol *lvol);
|
||||
|
||||
/**
|
||||
* Make a shallow copy of lvol on given bs_dev.
|
||||
*
|
||||
* lvol must be read only and lvol size must be smaller than bs_dev size.
|
||||
*
|
||||
* \param lvol Handle to lvol
|
||||
* \param ext_dev The bs_dev to copy on. This is created on the given bdev by using
|
||||
* spdk_bdev_create_bs_dev_ext() beforehand
|
||||
* \param cb_fn Completion callback
|
||||
* \param cb_arg Completion callback custom arguments
|
||||
*/
|
||||
void spdk_lvol_shallow_copy(struct spdk_lvol *lvol, struct spdk_bs_dev *ext_dev,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -308,40 +308,6 @@ spdk_memset_s(void *data, size_t data_size, int ch, size_t count)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if \b dividend is divisible by \b divisor
|
||||
*
|
||||
* @param dividend Dividend
|
||||
* @param divisor Divisor which is a power of 2
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
static inline bool
|
||||
spdk_is_divisible_by(uint64_t dividend, uint64_t divisor)
|
||||
{
|
||||
return (dividend & (divisor - 1)) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the UTC time string in RFC3339 format.
|
||||
*
|
||||
* \param buf Buffer to store the UTC time string.
|
||||
* \param buf_size Size of the buffer.
|
||||
*
|
||||
* \return void
|
||||
*/
|
||||
static inline void
|
||||
spdk_current_utc_time_rfc3339(char *buf, size_t buf_size)
|
||||
{
|
||||
struct tm *utc;
|
||||
time_t rawtime;
|
||||
|
||||
time(&rawtime);
|
||||
utc = gmtime(&rawtime);
|
||||
|
||||
strftime(buf, buf_size, "%Y-%m-%dT%H:%M:%SZ", utc);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -86,22 +86,6 @@ int spdk_uuid_generate_sha1(struct spdk_uuid *uuid, struct spdk_uuid *ns_uuid, c
|
||||
*/
|
||||
void spdk_uuid_copy(struct spdk_uuid *dst, const struct spdk_uuid *src);
|
||||
|
||||
/**
|
||||
* Compare the UUID to the NULL value (all bits equal to zero).
|
||||
*
|
||||
* \param uuid The UUID to test.
|
||||
*
|
||||
* \return true if uuid is equal to the NULL value, false if not.
|
||||
*/
|
||||
bool spdk_uuid_is_null(const struct spdk_uuid *uuid);
|
||||
|
||||
/**
|
||||
* Set the value of UUID to the NULL value.
|
||||
*
|
||||
* \param uuid The UUID to set.
|
||||
*/
|
||||
void spdk_uuid_set_null(struct spdk_uuid *uuid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -16,9 +16,6 @@
|
||||
/* Default size of blobstore cluster */
|
||||
#define SPDK_LVS_OPTS_CLUSTER_SZ (4 * 1024 * 1024)
|
||||
|
||||
/* Creation time format in RFC 3339 format */
|
||||
#define SPDK_CREATION_TIME_MAX 21 /* 20 characters + null terminator */
|
||||
|
||||
/* UUID + '_' + blobid (20 characters for uint64_t).
|
||||
* Null terminator is already included in SPDK_UUID_STRING_LEN. */
|
||||
#define SPDK_LVOL_UNIQUE_ID_MAX (SPDK_UUID_STRING_LEN + 1 + 20)
|
||||
@ -49,13 +46,6 @@ struct spdk_lvol_req {
|
||||
char name[SPDK_LVOL_NAME_MAX];
|
||||
};
|
||||
|
||||
struct spdk_lvol_copy_req {
|
||||
spdk_lvol_op_complete cb_fn;
|
||||
void *cb_arg;
|
||||
struct spdk_lvol *lvol;
|
||||
struct spdk_bs_dev *ext_dev;
|
||||
};
|
||||
|
||||
struct spdk_lvs_with_handle_req {
|
||||
spdk_lvs_op_with_handle_complete cb_fn;
|
||||
void *cb_arg;
|
||||
@ -109,7 +99,6 @@ struct spdk_lvol {
|
||||
char name[SPDK_LVOL_NAME_MAX];
|
||||
struct spdk_uuid uuid;
|
||||
char uuid_str[SPDK_UUID_STRING_LEN];
|
||||
char creation_time[SPDK_CREATION_TIME_MAX];
|
||||
struct spdk_bdev *bdev;
|
||||
int ref_count;
|
||||
bool action_in_progress;
|
||||
@ -119,30 +108,6 @@ struct spdk_lvol {
|
||||
TAILQ_ENTRY(spdk_lvol) degraded_link;
|
||||
};
|
||||
|
||||
struct spdk_fragmap {
|
||||
struct spdk_bit_array *map;
|
||||
|
||||
uint64_t cluster_size;
|
||||
uint64_t block_size;
|
||||
uint64_t num_clusters;
|
||||
uint64_t num_allocated_clusters;
|
||||
};
|
||||
|
||||
struct spdk_fragmap_req {
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_bdev_desc *bdev_desc;
|
||||
struct spdk_io_channel *bdev_io_channel;
|
||||
|
||||
struct spdk_fragmap fragmap;
|
||||
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
uint64_t current_offset;
|
||||
|
||||
spdk_lvol_op_with_fragmap_handle_complete cb_fn;
|
||||
void *cb_arg;
|
||||
};
|
||||
|
||||
struct lvol_store_bdev *vbdev_lvol_store_first(void);
|
||||
struct lvol_store_bdev *vbdev_lvol_store_next(struct lvol_store_bdev *prev);
|
||||
|
||||
|
@ -4569,12 +4569,6 @@ spdk_bdev_get_aliases(const struct spdk_bdev *bdev)
|
||||
return &bdev->aliases;
|
||||
}
|
||||
|
||||
const char *
|
||||
spdk_bdev_get_creation_time(const struct spdk_bdev *bdev)
|
||||
{
|
||||
return bdev->creation_time;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
spdk_bdev_get_block_size(const struct spdk_bdev *bdev)
|
||||
{
|
||||
@ -7433,7 +7427,7 @@ bdev_register(struct spdk_bdev *bdev)
|
||||
|
||||
/* UUID may be specified by the user or defined by bdev itself.
|
||||
* Otherwise it will be generated here, so this field will never be empty. */
|
||||
if (spdk_uuid_is_null(&bdev->uuid)) {
|
||||
if (spdk_mem_all_zero(&bdev->uuid, sizeof(bdev->uuid))) {
|
||||
spdk_uuid_generate(&bdev->uuid);
|
||||
}
|
||||
|
||||
|
@ -664,7 +664,6 @@ rpc_dump_bdev_info(void *ctx, struct spdk_bdev *bdev)
|
||||
uint64_t qos_limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES];
|
||||
struct spdk_memory_domain **domains;
|
||||
char uuid_str[SPDK_UUID_STRING_LEN];
|
||||
const char *creation_time_str;
|
||||
int i, rc;
|
||||
|
||||
spdk_json_write_object_begin(w);
|
||||
@ -688,12 +687,6 @@ rpc_dump_bdev_info(void *ctx, struct spdk_bdev *bdev)
|
||||
spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid);
|
||||
spdk_json_write_named_string(w, "uuid", uuid_str);
|
||||
|
||||
creation_time_str = spdk_bdev_get_creation_time(bdev);
|
||||
if (creation_time_str == NULL) {
|
||||
creation_time_str = "";
|
||||
}
|
||||
spdk_json_write_named_string(w, "creation_time", creation_time_str);
|
||||
|
||||
if (spdk_bdev_get_md_size(bdev) != 0) {
|
||||
spdk_json_write_named_uint32(w, "md_size", spdk_bdev_get_md_size(bdev));
|
||||
spdk_json_write_named_bool(w, "md_interleave", spdk_bdev_is_md_interleaved(bdev));
|
||||
|
@ -40,8 +40,6 @@ static int blob_remove_xattr(struct spdk_blob *blob, const char *name, bool inte
|
||||
static void blob_write_extent_page(struct spdk_blob *blob, uint32_t extent, uint64_t cluster_num,
|
||||
struct spdk_blob_md_page *page, spdk_blob_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
static void bs_shallow_copy_cluster_find_next(void *cb_arg, int bserrno);
|
||||
|
||||
/*
|
||||
* External snapshots require a channel per thread per esnap bdev. The tree
|
||||
* is populated lazily as blob IOs are handled by the back_bs_dev. When this
|
||||
@ -304,7 +302,6 @@ blob_alloc(struct spdk_blob_store *bs, spdk_blob_id id)
|
||||
blob->parent_id = SPDK_BLOBID_INVALID;
|
||||
|
||||
blob->state = SPDK_BLOB_STATE_DIRTY;
|
||||
blob->u.shallow_copy.bserrno = 1;
|
||||
blob->extent_rle_found = false;
|
||||
blob->extent_table_found = false;
|
||||
blob->active.num_pages = 1;
|
||||
@ -5882,30 +5879,6 @@ spdk_blob_get_next_unallocated_io_unit(struct spdk_blob *blob, uint64_t offset)
|
||||
return blob_find_io_unit(blob, offset, false);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spdk_blob_get_shallow_copy_copied_clusters(struct spdk_blob *blob)
|
||||
{
|
||||
assert(blob != NULL);
|
||||
|
||||
return blob->u.shallow_copy.copied_clusters_number;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spdk_blob_get_shallow_copy_total_clusters(struct spdk_blob *blob)
|
||||
{
|
||||
assert(blob != NULL);
|
||||
|
||||
return blob->u.shallow_copy.num_clusters_to_copy;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_blob_get_shallow_copy_result(struct spdk_blob *blob)
|
||||
{
|
||||
assert(blob != NULL);
|
||||
|
||||
return blob->u.shallow_copy.bserrno;
|
||||
}
|
||||
|
||||
/* START spdk_bs_create_blob */
|
||||
|
||||
static void
|
||||
@ -6946,234 +6919,6 @@ spdk_bs_blob_decouple_parent(struct spdk_blob_store *bs, struct spdk_io_channel
|
||||
}
|
||||
/* END spdk_bs_inflate_blob */
|
||||
|
||||
/* START spdk_bs_blob_shallow_copy */
|
||||
|
||||
struct shallow_copy_ctx {
|
||||
struct spdk_bs_cpl cpl;
|
||||
int bserrno;
|
||||
|
||||
/* Blob source for copy */
|
||||
struct spdk_blob *blob;
|
||||
struct spdk_io_channel *blob_channel;
|
||||
|
||||
/* Destination device for copy */
|
||||
struct spdk_bs_dev *ext_dev;
|
||||
struct spdk_io_channel *ext_channel;
|
||||
|
||||
/* Current cluster for copy operation */
|
||||
uint64_t cluster;
|
||||
|
||||
/* Buffer for blob reading */
|
||||
uint8_t *read_buff;
|
||||
|
||||
/* Struct for external device writing */
|
||||
struct spdk_bs_dev_cb_args ext_args;
|
||||
};
|
||||
|
||||
static void
|
||||
bs_shallow_copy_cleanup_finish(void *cb_arg, int bserrno)
|
||||
{
|
||||
struct shallow_copy_ctx *ctx = cb_arg;
|
||||
struct spdk_blob *_blob = ctx->blob;
|
||||
struct spdk_bs_cpl *cpl = &ctx->cpl;
|
||||
|
||||
if (bserrno != 0) {
|
||||
if (ctx->bserrno == 0) {
|
||||
SPDK_ERRLOG("Shallow copy cleanup error %d\n", bserrno);
|
||||
ctx->bserrno = bserrno;
|
||||
}
|
||||
}
|
||||
|
||||
_blob->u.shallow_copy.bserrno = ctx->bserrno;
|
||||
|
||||
ctx->ext_dev->destroy_channel(ctx->ext_dev, ctx->ext_channel);
|
||||
spdk_free(ctx->read_buff);
|
||||
|
||||
cpl->u.blob_basic.cb_fn(cpl->u.blob_basic.cb_arg, ctx->bserrno);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
bs_shallow_copy_bdev_write_cpl(struct spdk_io_channel *channel, void *cb_arg, int bserrno)
|
||||
{
|
||||
struct shallow_copy_ctx *ctx = (struct shallow_copy_ctx *)cb_arg;
|
||||
struct spdk_blob *_blob = ctx->blob;
|
||||
|
||||
if (bserrno != 0) {
|
||||
SPDK_ERRLOG("Shallow copy ext dev write error %d\n", bserrno);
|
||||
ctx->bserrno = bserrno;
|
||||
_blob->u.shallow_copy.bserrno = bserrno;
|
||||
_blob->locked_operation_in_progress = false;
|
||||
spdk_blob_close(_blob, bs_shallow_copy_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->cluster++;
|
||||
_blob->u.shallow_copy.copied_clusters_number++;
|
||||
|
||||
bs_shallow_copy_cluster_find_next(ctx, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
bs_shallow_copy_blob_read_cpl(void *cb_arg, int bserrno)
|
||||
{
|
||||
struct shallow_copy_ctx *ctx = (struct shallow_copy_ctx *)cb_arg;
|
||||
struct spdk_bs_dev *ext_dev = ctx->ext_dev;
|
||||
struct spdk_blob *_blob = ctx->blob;
|
||||
|
||||
if (bserrno != 0) {
|
||||
SPDK_ERRLOG("Shallow copy blob read error %d\n", bserrno);
|
||||
ctx->bserrno = bserrno;
|
||||
_blob->u.shallow_copy.bserrno = bserrno;
|
||||
_blob->locked_operation_in_progress = false;
|
||||
spdk_blob_close(_blob, bs_shallow_copy_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->ext_args.channel = ctx->ext_channel;
|
||||
ctx->ext_args.cb_fn = bs_shallow_copy_bdev_write_cpl;
|
||||
ctx->ext_args.cb_arg = ctx;
|
||||
|
||||
ext_dev->write(ext_dev, ctx->ext_channel, ctx->read_buff,
|
||||
bs_cluster_to_lba(_blob->bs, ctx->cluster),
|
||||
bs_dev_byte_to_lba(_blob->bs->dev, _blob->bs->cluster_sz),
|
||||
&ctx->ext_args);
|
||||
}
|
||||
|
||||
static void
|
||||
bs_shallow_copy_cluster_find_next(void *cb_arg, int bserrno)
|
||||
{
|
||||
struct shallow_copy_ctx *ctx = (struct shallow_copy_ctx *)cb_arg;
|
||||
struct spdk_blob *_blob = ctx->blob;
|
||||
|
||||
if (bserrno != 0) {
|
||||
SPDK_ERRLOG("Shallow copy bdev write error %d\n", bserrno);
|
||||
ctx->bserrno = bserrno;
|
||||
_blob->u.shallow_copy.bserrno = bserrno;
|
||||
_blob->locked_operation_in_progress = false;
|
||||
spdk_blob_close(_blob, bs_shallow_copy_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
while (ctx->cluster < _blob->active.num_clusters) {
|
||||
if (_blob->active.clusters[ctx->cluster] != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->cluster++;
|
||||
}
|
||||
|
||||
if (ctx->cluster < _blob->active.num_clusters) {
|
||||
blob_request_submit_op_single(ctx->blob_channel, _blob, ctx->read_buff,
|
||||
bs_cluster_to_lba(_blob->bs, ctx->cluster),
|
||||
bs_dev_byte_to_lba(_blob->bs->dev, _blob->bs->cluster_sz),
|
||||
bs_shallow_copy_blob_read_cpl, ctx, SPDK_BLOB_READ);
|
||||
} else {
|
||||
_blob->locked_operation_in_progress = false;
|
||||
spdk_blob_close(_blob, bs_shallow_copy_cleanup_finish, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bs_shallow_copy_blob_open_cpl(void *cb_arg, struct spdk_blob *_blob, int bserrno)
|
||||
{
|
||||
struct shallow_copy_ctx *ctx = (struct shallow_copy_ctx *)cb_arg;
|
||||
struct spdk_bs_dev *ext_dev = ctx->ext_dev;
|
||||
uint32_t blob_block_size;
|
||||
uint64_t blob_total_size;
|
||||
uint64_t i;
|
||||
|
||||
if (bserrno != 0) {
|
||||
SPDK_ERRLOG("Shallow copy blob open error %d\n", bserrno);
|
||||
ctx->bserrno = bserrno;
|
||||
bs_shallow_copy_cleanup_finish(ctx, bserrno);
|
||||
return;
|
||||
}
|
||||
|
||||
blob_block_size = _blob->bs->dev->blocklen;
|
||||
blob_total_size = spdk_blob_get_num_clusters(_blob) * spdk_bs_get_cluster_size(_blob->bs);
|
||||
|
||||
if (blob_total_size > ext_dev->blockcnt * ext_dev->blocklen) {
|
||||
SPDK_ERRLOG("external device must have at least blob size\n");
|
||||
ctx->bserrno = -EINVAL;
|
||||
spdk_blob_close(_blob, bs_shallow_copy_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blob_block_size % ext_dev->blocklen != 0) {
|
||||
SPDK_ERRLOG("external device block size is not compatible with blobstore block size\n");
|
||||
ctx->bserrno = -EINVAL;
|
||||
spdk_blob_close(_blob, bs_shallow_copy_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->blob = _blob;
|
||||
|
||||
if (_blob->locked_operation_in_progress) {
|
||||
SPDK_DEBUGLOG(blob, "Cannot make a shallow copy of blob - another operation in progress\n");
|
||||
ctx->bserrno = -EBUSY;
|
||||
spdk_blob_close(_blob, bs_shallow_copy_cleanup_finish, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
_blob->locked_operation_in_progress = true;
|
||||
|
||||
_blob->u.shallow_copy.copied_clusters_number = 0;
|
||||
_blob->u.shallow_copy.num_clusters_to_copy = 0;
|
||||
_blob->u.shallow_copy.bserrno = 0;
|
||||
|
||||
for (i = 0; i < _blob->active.num_clusters; i++) {
|
||||
if (_blob->active.clusters[i] != 0) {
|
||||
_blob->u.shallow_copy.num_clusters_to_copy++;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->cluster = 0;
|
||||
bs_shallow_copy_cluster_find_next(ctx, 0);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_blob_shallow_copy(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
|
||||
spdk_blob_id blobid, struct spdk_bs_dev *ext_dev,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct shallow_copy_ctx *ctx;
|
||||
struct spdk_io_channel *ext_channel;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->cpl.type = SPDK_BS_CPL_TYPE_BLOB_BASIC;
|
||||
ctx->cpl.u.bs_basic.cb_fn = cb_fn;
|
||||
ctx->cpl.u.bs_basic.cb_arg = cb_arg;
|
||||
ctx->bserrno = 0;
|
||||
ctx->blob_channel = channel;
|
||||
ctx->read_buff = spdk_malloc(bs->cluster_sz, bs->dev->blocklen, NULL,
|
||||
SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
|
||||
if (!ctx->read_buff) {
|
||||
free(ctx);
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
ext_channel = ext_dev->create_channel(ext_dev);
|
||||
if (!ext_channel) {
|
||||
spdk_free(ctx->read_buff);
|
||||
free(ctx);
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
ctx->ext_dev = ext_dev;
|
||||
ctx->ext_channel = ext_channel;
|
||||
|
||||
spdk_bs_open_blob(bs, blobid, bs_shallow_copy_blob_open_cpl, ctx);
|
||||
}
|
||||
/* END spdk_bs_blob_shallow_copy */
|
||||
|
||||
/* START spdk_blob_resize */
|
||||
struct spdk_bs_resize_ctx {
|
||||
spdk_blob_op_complete cb_fn;
|
||||
|
@ -148,14 +148,6 @@ struct spdk_blob {
|
||||
/* Number of data clusters retrieved from extent table,
|
||||
* that many have to be read from extent pages. */
|
||||
uint64_t remaining_clusters_in_et;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint64_t num_clusters_to_copy;
|
||||
uint64_t copied_clusters_number;
|
||||
int bserrno;
|
||||
} shallow_copy;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct spdk_blob_store {
|
||||
|
@ -22,9 +22,6 @@
|
||||
spdk_blob_get_num_clusters;
|
||||
spdk_blob_get_next_allocated_io_unit;
|
||||
spdk_blob_get_next_unallocated_io_unit;
|
||||
spdk_blob_get_shallow_copy_copied_clusters;
|
||||
spdk_blob_get_shallow_copy_total_clusters;
|
||||
spdk_blob_get_shallow_copy_result;
|
||||
spdk_blob_opts_init;
|
||||
spdk_bs_create_blob_ext;
|
||||
spdk_bs_create_blob;
|
||||
@ -41,7 +38,6 @@
|
||||
spdk_bs_delete_blob;
|
||||
spdk_bs_inflate_blob;
|
||||
spdk_bs_blob_decouple_parent;
|
||||
spdk_bs_blob_shallow_copy;
|
||||
spdk_blob_open_opts_init;
|
||||
spdk_bs_open_blob;
|
||||
spdk_bs_open_blob_ext;
|
||||
|
@ -393,9 +393,6 @@ write_string_or_name(struct spdk_json_write_ctx *w, const char *val, size_t len)
|
||||
{
|
||||
const uint8_t *p = val;
|
||||
const uint8_t *end = val + len;
|
||||
bool failed = false;
|
||||
int retval;
|
||||
|
||||
|
||||
if (emit(w, "\"", 1)) { return fail(w); }
|
||||
|
||||
@ -418,25 +415,14 @@ write_string_or_name(struct spdk_json_write_ctx *w, const char *val, size_t len)
|
||||
codepoint = utf8_decode_unsafe_4(p);
|
||||
break;
|
||||
default:
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
break;
|
||||
return fail(w);
|
||||
}
|
||||
|
||||
if (write_codepoint(w, codepoint)) { return fail(w); }
|
||||
p += codepoint_len;
|
||||
}
|
||||
|
||||
/* Always append "\"" in the end of string */
|
||||
retval = emit(w, "\"", 1);
|
||||
|
||||
if (failed) {
|
||||
return fail(w);
|
||||
}
|
||||
return retval;
|
||||
return emit(w, "\"", 1);
|
||||
}
|
||||
|
||||
static int
|
||||
|
147
lib/lvol/lvol.c
147
lib/lvol/lvol.c
@ -16,7 +16,6 @@
|
||||
#define SPDK_LVOL_BLOB_OPTS_CHANNEL_OPS 512
|
||||
|
||||
#define LVOL_NAME "name"
|
||||
#define LVOL_CREATION_TIME "creation_time"
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(lvol)
|
||||
|
||||
@ -115,7 +114,6 @@ lvol_alloc(struct spdk_lvol_store *lvs, const char *name, bool thin_provision,
|
||||
spdk_uuid_generate(&lvol->uuid);
|
||||
spdk_uuid_fmt_lower(lvol->uuid_str, sizeof(lvol->uuid_str), &lvol->uuid);
|
||||
spdk_uuid_fmt_lower(lvol->unique_id, sizeof(lvol->uuid_str), &lvol->uuid);
|
||||
spdk_current_utc_time_rfc3339(lvol->creation_time, sizeof(lvol->creation_time));
|
||||
|
||||
TAILQ_INSERT_TAIL(&lvs->pending_lvols, lvol, link);
|
||||
|
||||
@ -257,11 +255,11 @@ load_next_lvol(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
|
||||
if (rc != 0 || value_len != SPDK_UUID_STRING_LEN || attr[SPDK_UUID_STRING_LEN - 1] != '\0' ||
|
||||
spdk_uuid_parse(&lvol->uuid, attr) != 0) {
|
||||
SPDK_INFOLOG(lvol, "Missing or corrupt lvol uuid\n");
|
||||
spdk_uuid_set_null(&lvol->uuid);
|
||||
memset(&lvol->uuid, 0, sizeof(lvol->uuid));
|
||||
}
|
||||
spdk_uuid_fmt_lower(lvol->uuid_str, sizeof(lvol->uuid_str), &lvol->uuid);
|
||||
|
||||
if (!spdk_uuid_is_null(&lvol->uuid)) {
|
||||
if (!spdk_mem_all_zero(&lvol->uuid, sizeof(lvol->uuid))) {
|
||||
snprintf(lvol->unique_id, sizeof(lvol->unique_id), "%s", lvol->uuid_str);
|
||||
} else {
|
||||
spdk_uuid_fmt_lower(lvol->unique_id, sizeof(lvol->unique_id), &lvol->lvol_store->uuid);
|
||||
@ -280,11 +278,6 @@ load_next_lvol(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
|
||||
|
||||
snprintf(lvol->name, sizeof(lvol->name), "%s", attr);
|
||||
|
||||
rc = spdk_blob_get_xattr_value(blob, "creation_time", (const void **)&attr, &value_len);
|
||||
if (rc == 0 && value_len <= SPDK_CREATION_TIME_MAX) {
|
||||
snprintf(lvol->creation_time, sizeof(lvol->creation_time), "%s", attr);
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&lvs->lvols, lvol, link);
|
||||
|
||||
lvs->lvol_count++;
|
||||
@ -659,7 +652,7 @@ lvs_opts_copy(const struct spdk_lvs_opts *src, struct spdk_lvs_opts *dst)
|
||||
|
||||
/* You should not remove this statement, but need to update the assert statement
|
||||
* if you add a new field, and also add a corresponding SET_FIELD statement */
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_lvs_opts) == 280, "Incorrect size");
|
||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_lvs_opts) == 88, "Incorrect size");
|
||||
|
||||
#undef FIELD_OK
|
||||
#undef SET_FIELD
|
||||
@ -1146,12 +1139,6 @@ lvol_get_xattr_value(void *xattr_ctx, const char *name,
|
||||
*value_len = sizeof(lvol->uuid_str);
|
||||
return;
|
||||
}
|
||||
if (!strcmp(LVOL_CREATION_TIME, name)) {
|
||||
*value = lvol->creation_time;
|
||||
*value_len = sizeof(lvol->creation_time);
|
||||
return;
|
||||
}
|
||||
|
||||
*value = NULL;
|
||||
*value_len = 0;
|
||||
}
|
||||
@ -1197,7 +1184,7 @@ spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz,
|
||||
struct spdk_blob_store *bs;
|
||||
struct spdk_lvol *lvol;
|
||||
struct spdk_blob_opts opts;
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid", LVOL_CREATION_TIME};
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid"};
|
||||
int rc;
|
||||
|
||||
if (lvs == NULL) {
|
||||
@ -1252,7 +1239,7 @@ spdk_lvol_create_esnap_clone(const void *esnap_id, uint32_t id_len, uint64_t siz
|
||||
struct spdk_lvol *lvol;
|
||||
struct spdk_blob_opts opts;
|
||||
uint64_t cluster_sz;
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid", LVOL_CREATION_TIME};
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid"};
|
||||
int rc;
|
||||
|
||||
if (lvs == NULL) {
|
||||
@ -1316,7 +1303,7 @@ spdk_lvol_create_snapshot(struct spdk_lvol *origlvol, const char *snapshot_name,
|
||||
struct spdk_blob *origblob;
|
||||
struct spdk_lvol_with_handle_req *req;
|
||||
struct spdk_blob_xattr_opts snapshot_xattrs;
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid", LVOL_CREATION_TIME};
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid"};
|
||||
int rc;
|
||||
|
||||
if (origlvol == NULL) {
|
||||
@ -1377,7 +1364,7 @@ spdk_lvol_create_clone(struct spdk_lvol *origlvol, const char *clone_name,
|
||||
struct spdk_lvol_store *lvs;
|
||||
struct spdk_blob *origblob;
|
||||
struct spdk_blob_xattr_opts clone_xattrs;
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid", LVOL_CREATION_TIME};
|
||||
char *xattr_names[] = {LVOL_NAME, "uuid"};
|
||||
int rc;
|
||||
|
||||
if (origlvol == NULL) {
|
||||
@ -1562,51 +1549,6 @@ spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name,
|
||||
spdk_blob_sync_md(blob, lvol_rename_cb, req);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_set_xattr_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_req *req = cb_arg;
|
||||
|
||||
req->cb_fn(req->cb_arg, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_set_xattr(struct spdk_lvol *lvol, const char *name, const char *value,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_blob *blob = lvol->blob;
|
||||
struct spdk_lvol_req *req;
|
||||
int rc;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
|
||||
rc = spdk_blob_set_xattr(blob, name, value, strlen(value) + 1);
|
||||
if (rc < 0) {
|
||||
free(req);
|
||||
cb_fn(cb_arg, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_blob_sync_md(blob, lvol_set_xattr_cb, req);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_lvol_get_xattr(struct spdk_lvol *lvol, const char *name,
|
||||
const void **value, size_t *value_len)
|
||||
{
|
||||
struct spdk_blob *blob = lvol->blob;
|
||||
|
||||
return spdk_blob_get_xattr_value(blob, name, value, value_len);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
@ -2266,78 +2208,3 @@ spdk_lvol_is_degraded(const struct spdk_lvol *lvol)
|
||||
}
|
||||
return spdk_blob_is_degraded(blob);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_req *req = cb_arg;
|
||||
|
||||
spdk_bs_free_io_channel(req->channel);
|
||||
|
||||
if (lvolerrno < 0) {
|
||||
SPDK_ERRLOG("Could not make a shallow copy of lvol\n");
|
||||
}
|
||||
|
||||
req->cb_fn(req->cb_arg, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_shallow_copy(struct spdk_lvol *lvol, struct spdk_bs_dev *ext_dev,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_req *req;
|
||||
spdk_blob_id blob_id;
|
||||
uint64_t lvol_total_size;
|
||||
|
||||
assert(cb_fn != NULL);
|
||||
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
cb_fn(cb_arg, -ENODEV);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ext_dev == NULL) {
|
||||
SPDK_ERRLOG("External device does not exist\n");
|
||||
cb_fn(cb_arg, -ENODEV);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!spdk_blob_is_read_only(lvol->blob)) {
|
||||
SPDK_ERRLOG("lvol must be read only\n");
|
||||
cb_fn(cb_arg, -EPERM);
|
||||
return;
|
||||
}
|
||||
|
||||
lvol_total_size = spdk_blob_get_num_clusters(lvol->blob) *
|
||||
spdk_bs_get_cluster_size(lvol->lvol_store->blobstore);
|
||||
|
||||
if (lvol_total_size > ext_dev->blockcnt * ext_dev->blocklen) {
|
||||
SPDK_ERRLOG("bdev must have at least lvol size\n");
|
||||
cb_fn(cb_arg, -EFBIG);
|
||||
return;
|
||||
}
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
|
||||
if (req->channel == NULL) {
|
||||
SPDK_ERRLOG("Cannot alloc io channel for lvol shallow copy request\n");
|
||||
free(req);
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
blob_id = spdk_blob_get_id(lvol->blob);
|
||||
|
||||
spdk_bs_blob_shallow_copy(lvol->lvol_store->blobstore, req->channel, blob_id, ext_dev,
|
||||
lvol_shallow_copy_cb, req);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
spdk_lvol_get_by_uuid;
|
||||
spdk_lvol_get_by_names;
|
||||
spdk_lvol_is_degraded;
|
||||
spdk_lvol_shallow_copy;
|
||||
|
||||
# internal functions
|
||||
spdk_lvol_resize;
|
||||
|
@ -544,7 +544,7 @@ nvmf_write_subsystem_config_json(struct spdk_json_write_ctx *w,
|
||||
spdk_json_write_named_string_fmt(w, "eui64", "%016"PRIX64, from_be64(&ns_opts.eui64));
|
||||
}
|
||||
|
||||
if (!spdk_uuid_is_null(&ns_opts.uuid)) {
|
||||
if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) {
|
||||
spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid);
|
||||
spdk_json_write_named_string(w, "uuid", uuid_str);
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *s
|
||||
json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64));
|
||||
}
|
||||
|
||||
if (!spdk_uuid_is_null(&ns_opts.uuid)) {
|
||||
if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) {
|
||||
char uuid_str[SPDK_UUID_STRING_LEN];
|
||||
|
||||
spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid);
|
||||
@ -1221,7 +1221,7 @@ nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem,
|
||||
SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch");
|
||||
memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64));
|
||||
|
||||
if (!spdk_uuid_is_null(&ctx->ns_params.uuid)) {
|
||||
if (!spdk_mem_all_zero(&ctx->ns_params.uuid, sizeof(ctx->ns_params.uuid))) {
|
||||
ns_opts.uuid = ctx->ns_params.uuid;
|
||||
}
|
||||
|
||||
|
@ -1529,7 +1529,7 @@ spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size)
|
||||
memset(opts->eui64, 0, sizeof(opts->eui64));
|
||||
}
|
||||
if (FIELD_OK(uuid)) {
|
||||
spdk_uuid_set_null(&opts->uuid);
|
||||
memset(&opts->uuid, 0, sizeof(opts->uuid));
|
||||
}
|
||||
SET_FIELD(anagrpid, 0);
|
||||
|
||||
@ -1558,7 +1558,7 @@ nvmf_ns_opts_copy(struct spdk_nvmf_ns_opts *opts,
|
||||
memcpy(opts->eui64, user_opts->eui64, sizeof(opts->eui64));
|
||||
}
|
||||
if (FIELD_OK(uuid)) {
|
||||
spdk_uuid_copy(&opts->uuid, &user_opts->uuid);
|
||||
memcpy(&opts->uuid, &user_opts->uuid, sizeof(opts->uuid));
|
||||
}
|
||||
SET_FIELD(anagrpid);
|
||||
|
||||
@ -1686,7 +1686,7 @@ spdk_nvmf_subsystem_add_ns_ext(struct spdk_nvmf_subsystem *subsystem, const char
|
||||
/* Cache the zcopy capability of the bdev device */
|
||||
ns->zcopy = spdk_bdev_io_type_supported(ns->bdev, SPDK_BDEV_IO_TYPE_ZCOPY);
|
||||
|
||||
if (spdk_uuid_is_null(&opts.uuid)) {
|
||||
if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) {
|
||||
opts.uuid = *spdk_bdev_get_uuid(ns->bdev);
|
||||
}
|
||||
|
||||
|
@ -621,7 +621,7 @@ spdk_reduce_vol_init(struct spdk_reduce_vol_params *params,
|
||||
return;
|
||||
}
|
||||
|
||||
if (spdk_uuid_is_null(¶ms->uuid)) {
|
||||
if (spdk_mem_all_zero(¶ms->uuid, sizeof(params->uuid))) {
|
||||
spdk_uuid_generate(¶ms->uuid);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "spdk/likely.h"
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/base64.h"
|
||||
|
||||
typedef uint64_t spdk_bit_array_word;
|
||||
#define SPDK_BIT_ARRAY_WORD_TZCNT(x) (__builtin_ctzll(x))
|
||||
@ -492,51 +491,3 @@ spdk_bit_pool_free_all_bits(struct spdk_bit_pool *pool)
|
||||
pool->lowest_free_bit = 0;
|
||||
pool->free_count = spdk_bit_array_capacity(pool->array);
|
||||
}
|
||||
|
||||
static int
|
||||
bits_to_bytes(const int bits)
|
||||
{
|
||||
return ((bits + 7) >> 3);
|
||||
}
|
||||
|
||||
char *
|
||||
spdk_bit_array_to_base64_string(const struct spdk_bit_array *array)
|
||||
{
|
||||
uint32_t bit_count = spdk_bit_array_capacity(array);
|
||||
size_t byte_count = bits_to_bytes(bit_count);
|
||||
void *bytes;
|
||||
char *encoded;
|
||||
size_t total_size;
|
||||
int rc;
|
||||
|
||||
bytes = calloc(byte_count, sizeof(char));
|
||||
if (bytes == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < bit_count; i++) {
|
||||
if (spdk_bit_array_get(array, i)) {
|
||||
/*
|
||||
* Set the bit in bytes's correct position
|
||||
*/
|
||||
((uint8_t *)bytes)[i / 8] |= 1 << (i % 8);
|
||||
}
|
||||
}
|
||||
|
||||
total_size = spdk_base64_get_encoded_strlen(byte_count) + 1;
|
||||
encoded = calloc(total_size, sizeof(char));
|
||||
if (encoded == NULL) {
|
||||
free(bytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = spdk_base64_encode(encoded, bytes, byte_count);
|
||||
if (rc != 0) {
|
||||
free(bytes);
|
||||
free(encoded);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(bytes);
|
||||
return encoded;
|
||||
}
|
||||
|
@ -155,8 +155,6 @@
|
||||
spdk_uuid_generate;
|
||||
spdk_uuid_generate_sha1;
|
||||
spdk_uuid_copy;
|
||||
spdk_uuid_is_null;
|
||||
spdk_uuid_set_null;
|
||||
|
||||
# public functions in fd_group.h
|
||||
spdk_fd_group_create;
|
||||
|
@ -52,18 +52,6 @@ spdk_uuid_copy(struct spdk_uuid *dst, const struct spdk_uuid *src)
|
||||
uuid_copy((void *)dst, (void *)src);
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_uuid_is_null(const struct spdk_uuid *uuid)
|
||||
{
|
||||
return uuid_is_null((void *)uuid);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_uuid_set_null(struct spdk_uuid *uuid)
|
||||
{
|
||||
uuid_clear((void *)uuid);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <uuid.h>
|
||||
@ -120,18 +108,6 @@ spdk_uuid_copy(struct spdk_uuid *dst, const struct spdk_uuid *src)
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_uuid_is_null(const struct spdk_uuid *uuid)
|
||||
{
|
||||
return uuid_is_nil((const uuid_t *)uuid, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_uuid_set_null(struct spdk_uuid *uuid)
|
||||
{
|
||||
uuid_create_nil((uuid_t *)uuid, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -145,7 +145,7 @@ DEPDIRS-bdev_null := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_nvme = $(BDEV_DEPS_THREAD) accel nvme trace
|
||||
DEPDIRS-bdev_ocf := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_passthru := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_raid := $(BDEV_DEPS_THREAD) accel
|
||||
DEPDIRS-bdev_raid := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_rbd := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_uring := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_virtio := $(BDEV_DEPS_THREAD) virtio
|
||||
|
@ -93,7 +93,7 @@ rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (spdk_uuid_is_null(&conf.uuid)) {
|
||||
if (spdk_mem_all_zero(&conf.uuid, sizeof(conf.uuid))) {
|
||||
conf.mode |= SPDK_FTL_MODE_CREATE;
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/uuid.h"
|
||||
#include "spdk/blob.h"
|
||||
#include "spdk/bit_array.h"
|
||||
#include "spdk/base64.h"
|
||||
|
||||
#include "vbdev_lvol.h"
|
||||
|
||||
@ -1144,7 +1142,6 @@ _create_lvol_disk(struct spdk_lvol *lvol, bool destroy)
|
||||
assert((total_size % bdev->blocklen) == 0);
|
||||
bdev->blockcnt = total_size / bdev->blocklen;
|
||||
bdev->uuid = lvol->uuid;
|
||||
bdev->creation_time = lvol->creation_time;
|
||||
bdev->required_alignment = lvs_bdev->bdev->required_alignment;
|
||||
bdev->split_on_optimal_io_boundary = true;
|
||||
bdev->optimal_io_boundary = spdk_bs_get_cluster_size(lvol->lvol_store->blobstore) / bdev->blocklen;
|
||||
@ -1360,43 +1357,6 @@ vbdev_lvol_rename(struct spdk_lvol *lvol, const char *new_lvol_name,
|
||||
spdk_lvol_rename(lvol, new_lvol_name, _vbdev_lvol_rename_cb, req);
|
||||
}
|
||||
|
||||
static void
|
||||
_vbdev_lvol_set_xattr_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_req *req = cb_arg;
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
SPDK_ERRLOG("Setting xattr failed\n");
|
||||
}
|
||||
|
||||
req->cb_fn(req->cb_arg, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
void
|
||||
vbdev_lvol_set_xattr(struct spdk_lvol *lvol, const char *name,
|
||||
const char *value, spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_lvol_req *req;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (req == NULL) {
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
|
||||
spdk_lvol_set_xattr(lvol, name, value, _vbdev_lvol_set_xattr_cb, req);
|
||||
}
|
||||
|
||||
int
|
||||
vbdev_lvol_get_xattr(struct spdk_lvol *lvol, const char *name,
|
||||
const void **value, size_t *value_len)
|
||||
{
|
||||
return spdk_lvol_get_xattr(lvol, name, value, value_len);
|
||||
}
|
||||
|
||||
static void
|
||||
_vbdev_lvol_resize_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
@ -2060,256 +2020,4 @@ fail:
|
||||
|
||||
/* End external snapshot support */
|
||||
|
||||
static void
|
||||
_vbdev_lvol_shallow_copy_base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
|
||||
void *event_ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
_vbdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_lvol_copy_req *req = cb_arg;
|
||||
struct spdk_lvol *lvol = req->lvol;
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
SPDK_ERRLOG("Could not make a shallow copy of bdev lvol %s due to error: %d.\n", lvol->name,
|
||||
lvolerrno);
|
||||
}
|
||||
|
||||
req->ext_dev->destroy(req->ext_dev);
|
||||
req->cb_fn(req->cb_arg, lvolerrno);
|
||||
free(req);
|
||||
}
|
||||
|
||||
void
|
||||
vbdev_lvol_shallow_copy(struct spdk_lvol *lvol, const char *bdev_name,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_bs_dev *ext_dev;
|
||||
struct spdk_lvol_copy_req *req;
|
||||
int rc;
|
||||
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
cb_fn(cb_arg, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bdev_name == NULL) {
|
||||
SPDK_ERRLOG("bdev name does not exist\n");
|
||||
cb_fn(cb_arg, -ENODEV);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(lvol->bdev != NULL);
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (req == NULL) {
|
||||
SPDK_ERRLOG("Cannot alloc memory for vbdev lvol copy request pointer\n");
|
||||
cb_fn(cb_arg, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = spdk_bdev_create_bs_dev_ext(bdev_name, _vbdev_lvol_shallow_copy_base_bdev_event_cb,
|
||||
NULL, &ext_dev);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("Cannot create external bdev blob device\n");
|
||||
free(req);
|
||||
return;
|
||||
}
|
||||
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
req->lvol = lvol;
|
||||
req->ext_dev = ext_dev;
|
||||
|
||||
spdk_lvol_shallow_copy(lvol, ext_dev, _vbdev_lvol_shallow_copy_cb, req);
|
||||
}
|
||||
|
||||
static void seek_hole_done_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
|
||||
|
||||
static void
|
||||
get_fragmap_done(struct spdk_fragmap_req *req, int error_code, const char *error_msg)
|
||||
{
|
||||
req->cb_fn(req->cb_arg, &req->fragmap, error_code);
|
||||
|
||||
spdk_bit_array_free(&req->fragmap.map);
|
||||
spdk_put_io_channel(req->bdev_io_channel);
|
||||
spdk_bdev_close(req->bdev_desc);
|
||||
free(req);
|
||||
}
|
||||
|
||||
static void
|
||||
seek_data_done_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||
{
|
||||
struct spdk_fragmap_req *req = cb_arg;
|
||||
uint64_t next_data_offset_blocks;
|
||||
int rc;
|
||||
|
||||
next_data_offset_blocks = spdk_bdev_io_get_seek_offset(bdev_io);
|
||||
spdk_bdev_free_io(bdev_io);
|
||||
|
||||
req->current_offset = next_data_offset_blocks * req->fragmap.block_size;
|
||||
|
||||
if (next_data_offset_blocks == UINT64_MAX || req->current_offset >= req->offset + req->size) {
|
||||
get_fragmap_done(req, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = spdk_bdev_seek_hole(req->bdev_desc, req->bdev_io_channel,
|
||||
spdk_divide_round_up(req->current_offset, req->fragmap.block_size),
|
||||
seek_hole_done_cb, req);
|
||||
if (rc != 0) {
|
||||
get_fragmap_done(req, rc, "failed to seek hole");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
seek_hole_done_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||
{
|
||||
struct spdk_fragmap_req *req = cb_arg;
|
||||
uint64_t next_offset;
|
||||
uint64_t start_cluster;
|
||||
uint64_t num_clusters;
|
||||
int rc;
|
||||
|
||||
next_offset = spdk_bdev_io_get_seek_offset(bdev_io) * req->fragmap.block_size;
|
||||
spdk_bdev_free_io(bdev_io);
|
||||
|
||||
next_offset = spdk_min(next_offset, req->offset + req->size);
|
||||
|
||||
start_cluster = spdk_divide_round_up(req->current_offset - req->offset, req->fragmap.cluster_size);
|
||||
num_clusters = spdk_divide_round_up(next_offset - req->current_offset, req->fragmap.cluster_size);
|
||||
|
||||
for (uint64_t i = 0; i < num_clusters; i++) {
|
||||
spdk_bit_array_set(req->fragmap.map, start_cluster + i);
|
||||
}
|
||||
req->fragmap.num_allocated_clusters += num_clusters;
|
||||
|
||||
req->current_offset = next_offset;
|
||||
|
||||
if (req->current_offset == req->offset + req->size) {
|
||||
get_fragmap_done(req, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = spdk_bdev_seek_data(req->bdev_desc, req->bdev_io_channel,
|
||||
spdk_divide_round_up(req->current_offset, req->fragmap.block_size),
|
||||
seek_data_done_cb, req);
|
||||
if (rc != 0) {
|
||||
get_fragmap_done(req, rc, "failed to seek data");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
vbdev_lvol_get_fragmap(struct spdk_lvol *lvol, uint64_t offset, uint64_t size,
|
||||
spdk_lvol_op_with_fragmap_handle_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
struct spdk_bdev_desc *desc;
|
||||
struct spdk_io_channel *channel;
|
||||
struct spdk_bit_array *fragmap;
|
||||
struct spdk_fragmap_req *req;
|
||||
uint64_t cluster_size, num_clusters, block_size, num_blocks, lvol_size, segment_size;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Create a bitmap recording the allocated clusters
|
||||
*/
|
||||
cluster_size = spdk_bs_get_cluster_size(lvol->lvol_store->blobstore);
|
||||
block_size = spdk_bdev_get_block_size(lvol->bdev);
|
||||
num_blocks = spdk_bdev_get_num_blocks(lvol->bdev);
|
||||
lvol_size = num_blocks * block_size;
|
||||
|
||||
if (offset + size > lvol_size) {
|
||||
SPDK_ERRLOG("offset %lu and size %lu exceed lvol size %lu\n",
|
||||
offset, size, lvol_size);
|
||||
cb_fn(cb_arg, NULL, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
segment_size = size;
|
||||
if (size == 0) {
|
||||
segment_size = lvol_size;
|
||||
}
|
||||
|
||||
if (!spdk_is_divisible_by(offset, cluster_size) ||
|
||||
!spdk_is_divisible_by(segment_size, cluster_size)) {
|
||||
SPDK_ERRLOG("offset %lu and size %lu must be a multiple of cluster size %lu\n",
|
||||
offset, segment_size, cluster_size);
|
||||
cb_fn(cb_arg, NULL, -EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
num_clusters = spdk_divide_round_up(segment_size, cluster_size);
|
||||
fragmap = spdk_bit_array_create(num_clusters);
|
||||
if (fragmap == NULL) {
|
||||
SPDK_ERRLOG("failed to allocate fragmap with num_clusters %lu\n", num_clusters);
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a fragmap of the lvol
|
||||
*/
|
||||
rc = spdk_bdev_open_ext(lvol->bdev->name, false,
|
||||
dummy_bdev_event_cb, NULL, &desc);
|
||||
if (rc != 0) {
|
||||
spdk_bit_array_free(&fragmap);
|
||||
SPDK_ERRLOG("could not open bdev %s\n", lvol->bdev->name);
|
||||
cb_fn(cb_arg, NULL, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
channel = spdk_bdev_get_io_channel(desc);
|
||||
if (channel == NULL) {
|
||||
spdk_bit_array_free(&fragmap);
|
||||
spdk_bdev_close(desc);
|
||||
SPDK_ERRLOG("could not allocate I/O channel.\n");
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
req = calloc(1, sizeof(struct spdk_fragmap_req));
|
||||
if (req == NULL) {
|
||||
SPDK_ERRLOG("could not allocate fragmap_io\n");
|
||||
spdk_put_io_channel(channel);
|
||||
spdk_bdev_close(desc);
|
||||
spdk_bit_array_free(&fragmap);
|
||||
cb_fn(cb_arg, NULL, -ENOMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
req->bdev = lvol->bdev;
|
||||
req->bdev_desc = desc;
|
||||
req->bdev_io_channel = channel;
|
||||
req->offset = offset;
|
||||
req->size = segment_size;
|
||||
req->current_offset = offset;
|
||||
req->cb_fn = cb_fn;
|
||||
req->cb_arg = cb_arg;
|
||||
req->fragmap.map = fragmap;
|
||||
req->fragmap.num_clusters = num_clusters;
|
||||
req->fragmap.block_size = block_size;
|
||||
req->fragmap.cluster_size = cluster_size;
|
||||
req->fragmap.num_allocated_clusters = 0;
|
||||
|
||||
rc = spdk_bdev_seek_data(desc, channel,
|
||||
spdk_divide_round_up(offset, block_size),
|
||||
seek_data_done_cb, req);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("failed to seek data\n");
|
||||
spdk_put_io_channel(channel);
|
||||
spdk_bdev_close(desc);
|
||||
spdk_bit_array_free(&fragmap);
|
||||
free(req);
|
||||
cb_fn(cb_arg, NULL, rc);
|
||||
}
|
||||
}
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(vbdev_lvol)
|
||||
|
@ -69,27 +69,6 @@ void vbdev_lvol_set_read_only(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_f
|
||||
void vbdev_lvol_rename(struct spdk_lvol *lvol, const char *new_lvol_name,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* \brief Set lvol's xattr
|
||||
* \param lvol Handle to lvol
|
||||
* \param name xattr name
|
||||
* \param value xattr value
|
||||
* \param cb_fn Completion callback
|
||||
* \param cb_arg Completion callback custom arguments
|
||||
*/
|
||||
void vbdev_lvol_set_xattr(struct spdk_lvol *lvol, const char *name,
|
||||
const char *value, spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* \brief Get lvol's xattr
|
||||
* \param lvol Handle to lvol
|
||||
* \param name Xattr name
|
||||
* \param value Xattr value
|
||||
* \param value_len Xattr value length
|
||||
*/
|
||||
int vbdev_lvol_get_xattr(struct spdk_lvol *lvol, const char *name,
|
||||
const void **value, size_t *value_len);
|
||||
|
||||
/**
|
||||
* Destroy a logical volume
|
||||
* \param lvol Handle to lvol
|
||||
@ -146,27 +125,4 @@ int vbdev_lvol_esnap_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *
|
||||
const void *esnap_id, uint32_t id_len,
|
||||
struct spdk_bs_dev **_bs_dev);
|
||||
|
||||
/**
|
||||
* \brief Make a shallow copy of lvol over a bdev
|
||||
*
|
||||
* \param lvol Handle to lvol
|
||||
* \param bdev_name Name of the bdev to copy on
|
||||
* \param cb_fn Completion callback
|
||||
* \param cb_arg Completion callback custom arguments
|
||||
*/
|
||||
void vbdev_lvol_shallow_copy(struct spdk_lvol *lvol, const char *bdev_name,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* @brief Get a fragmap for a specific segment of a logical volume using the provided offset and size
|
||||
*
|
||||
* @param lvol Handle to lvol
|
||||
* @param offset Offset in bytes of the specific segment of the logical volume
|
||||
* @param size Size in bytes of the specific segment of the logical volume
|
||||
* @param cb_fn Completion callback
|
||||
* @param cb_arg Completion callback custom arguments
|
||||
*/
|
||||
void vbdev_lvol_get_fragmap(struct spdk_lvol *lvol, uint64_t offset, uint64_t size,
|
||||
spdk_lvol_op_with_fragmap_handle_complete cb_fn, void *cb_arg);
|
||||
|
||||
#endif /* SPDK_VBDEV_LVOL_H */
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include "vbdev_lvol.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/bdev_module.h"
|
||||
#include "spdk/bit_array.h"
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(lvol_rpc)
|
||||
|
||||
@ -701,154 +699,6 @@ cleanup:
|
||||
|
||||
SPDK_RPC_REGISTER("bdev_lvol_rename", rpc_bdev_lvol_rename, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_bdev_lvol_set_xattr {
|
||||
char *name;
|
||||
char *xattr_name;
|
||||
char *xattr_value;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_bdev_lvol_set_xattr(struct rpc_bdev_lvol_set_xattr *req)
|
||||
{
|
||||
free(req->name);
|
||||
free(req->xattr_name);
|
||||
free(req->xattr_value);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_bdev_lvol_set_xattr_decoders[] = {
|
||||
{"name", offsetof(struct rpc_bdev_lvol_set_xattr, name), spdk_json_decode_string},
|
||||
{"xattr_name", offsetof(struct rpc_bdev_lvol_set_xattr, xattr_name), spdk_json_decode_string},
|
||||
{"xattr_value", offsetof(struct rpc_bdev_lvol_set_xattr, xattr_value), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_set_xattr_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_jsonrpc_send_bool_response(request, true);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
spdk_strerror(-lvolerrno));
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_set_xattr(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_bdev_lvol_set_xattr req = {};
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_lvol *lvol;
|
||||
|
||||
SPDK_INFOLOG(lvol_rpc, "Setting lvol xattr\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_lvol_set_xattr_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_lvol_set_xattr_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(req.name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
lvol = vbdev_lvol_get_from_bdev(bdev);
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vbdev_lvol_set_xattr(lvol, req.xattr_name, req.xattr_value, rpc_bdev_lvol_set_xattr_cb, request);
|
||||
|
||||
cleanup:
|
||||
free_rpc_bdev_lvol_set_xattr(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("bdev_lvol_set_xattr", rpc_bdev_lvol_set_xattr, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_bdev_lvol_get_xattr {
|
||||
char *name;
|
||||
char *xattr_name;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_bdev_lvol_get_xattr(struct rpc_bdev_lvol_get_xattr *req)
|
||||
{
|
||||
free(req->name);
|
||||
free(req->xattr_name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_bdev_lvol_get_xattr_decoders[] = {
|
||||
{"name", offsetof(struct rpc_bdev_lvol_get_xattr, name), spdk_json_decode_string},
|
||||
{"xattr_name", offsetof(struct rpc_bdev_lvol_get_xattr, xattr_name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_get_xattr(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_bdev_lvol_get_xattr req = {};
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_lvol *lvol;
|
||||
const void *xattr_value;
|
||||
size_t xattr_value_len;
|
||||
int rc;
|
||||
|
||||
SPDK_INFOLOG(lvol_rpc, "Getting lvol xattr\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_lvol_get_xattr_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_lvol_get_xattr_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(req.name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
lvol = vbdev_lvol_get_from_bdev(bdev);
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = vbdev_lvol_get_xattr(lvol, req.xattr_name, &xattr_value, &xattr_value_len);
|
||||
if (rc != 0) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
spdk_strerror(-rc));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
spdk_json_write_string(w, (const char *)xattr_value);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
cleanup:
|
||||
free_rpc_bdev_lvol_get_xattr(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("bdev_lvol_get_xattr", rpc_bdev_lvol_get_xattr, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_bdev_lvol_inflate {
|
||||
char *name;
|
||||
};
|
||||
@ -1350,7 +1200,6 @@ rpc_dump_lvol(struct spdk_json_write_ctx *w, struct spdk_lvol *lvol)
|
||||
spdk_json_write_named_string_fmt(w, "alias", "%s/%s", lvs->name, lvol->name);
|
||||
spdk_json_write_named_string(w, "uuid", lvol->uuid_str);
|
||||
spdk_json_write_named_string(w, "name", lvol->name);
|
||||
spdk_json_write_named_string(w, "creation_time", lvol->creation_time);
|
||||
spdk_json_write_named_bool(w, "is_thin_provisioned", spdk_blob_is_thin_provisioned(lvol->blob));
|
||||
spdk_json_write_named_bool(w, "is_snapshot", spdk_blob_is_snapshot(lvol->blob));
|
||||
spdk_json_write_named_bool(w, "is_clone", spdk_blob_is_clone(lvol->blob));
|
||||
@ -1492,260 +1341,3 @@ cleanup:
|
||||
free_rpc_bdev_lvol_grow_lvstore(&req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_lvol_grow_lvstore", rpc_bdev_lvol_grow_lvstore, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_bdev_lvol_shallow_copy {
|
||||
char *src_lvol_name;
|
||||
char *dst_bdev_name;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_bdev_lvol_shallow_copy(struct rpc_bdev_lvol_shallow_copy *req)
|
||||
{
|
||||
free(req->src_lvol_name);
|
||||
free(req->dst_bdev_name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_decoders[] = {
|
||||
{"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy, src_lvol_name), spdk_json_decode_string},
|
||||
{"dst_bdev_name", offsetof(struct rpc_bdev_lvol_shallow_copy, dst_bdev_name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_shallow_copy_cb(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_jsonrpc_send_bool_response(request, true);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
spdk_strerror(-lvolerrno));
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_shallow_copy(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_bdev_lvol_shallow_copy req = {};
|
||||
struct spdk_lvol *src_lvol;
|
||||
struct spdk_bdev *src_lvol_bdev;
|
||||
struct spdk_bdev *dst_bdev;
|
||||
|
||||
SPDK_INFOLOG(lvol_rpc, "Shallow copying lvol\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
|
||||
if (src_lvol_bdev == NULL) {
|
||||
SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
|
||||
if (src_lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dst_bdev = spdk_bdev_get_by_name(req.dst_bdev_name);
|
||||
if (dst_bdev == NULL) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", req.dst_bdev_name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vbdev_lvol_shallow_copy(src_lvol, req.dst_bdev_name, rpc_bdev_lvol_shallow_copy_cb, request);
|
||||
|
||||
cleanup:
|
||||
free_rpc_bdev_lvol_shallow_copy(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("bdev_lvol_shallow_copy", rpc_bdev_lvol_shallow_copy, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_bdev_lvol_shallow_copy_status {
|
||||
char *src_lvol_name;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_bdev_lvol_shallow_copy_status(struct rpc_bdev_lvol_shallow_copy_status *req)
|
||||
{
|
||||
free(req->src_lvol_name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_bdev_lvol_shallow_copy_status_decoders[] = {
|
||||
{"src_lvol_name", offsetof(struct rpc_bdev_lvol_shallow_copy_status, src_lvol_name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_shallow_copy_status(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_bdev_lvol_shallow_copy_status req = {};
|
||||
struct spdk_bdev *src_lvol_bdev;
|
||||
struct spdk_lvol *src_lvol;
|
||||
struct spdk_json_write_ctx *w;
|
||||
uint64_t copied_clusters, total_clusters;
|
||||
int result;
|
||||
|
||||
SPDK_INFOLOG(lvol_rpc, "Shallow copy status\n");
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_lvol_shallow_copy_status_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_lvol_shallow_copy_status_decoders),
|
||||
&req)) {
|
||||
SPDK_INFOLOG(lvol_rpc, "spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
src_lvol_bdev = spdk_bdev_get_by_name(req.src_lvol_name);
|
||||
if (src_lvol_bdev == NULL) {
|
||||
SPDK_ERRLOG("lvol bdev '%s' does not exist\n", req.src_lvol_name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
src_lvol = vbdev_lvol_get_from_bdev(src_lvol_bdev);
|
||||
if (src_lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
copied_clusters = spdk_blob_get_shallow_copy_copied_clusters(src_lvol->blob);
|
||||
total_clusters = spdk_blob_get_shallow_copy_total_clusters(src_lvol->blob);
|
||||
result = spdk_blob_get_shallow_copy_result(src_lvol->blob);
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
|
||||
spdk_json_write_object_begin(w);
|
||||
|
||||
spdk_json_write_named_string_fmt(w, "progress", "%lu/%lu", copied_clusters, total_clusters);
|
||||
if (result > 0) {
|
||||
spdk_json_write_named_string(w, "state", "none");
|
||||
} else if (copied_clusters < total_clusters && result == 0) {
|
||||
spdk_json_write_named_string(w, "state", "in progress");
|
||||
} else if (copied_clusters == total_clusters && result == 0) {
|
||||
spdk_json_write_named_string(w, "state", "complete");
|
||||
} else {
|
||||
spdk_json_write_named_string(w, "state", "error");
|
||||
spdk_json_write_named_string(w, "error", spdk_strerror(-result));
|
||||
}
|
||||
|
||||
spdk_json_write_object_end(w);
|
||||
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
|
||||
cleanup:
|
||||
free_rpc_bdev_lvol_shallow_copy_status(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("bdev_lvol_shallow_copy_status", rpc_bdev_lvol_shallow_copy_status,
|
||||
SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_bdev_lvol_get_fragmap {
|
||||
char *name;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_bdev_lvol_get_fragmap(struct rpc_bdev_lvol_get_fragmap *r)
|
||||
{
|
||||
free(r->name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_bdev_lvol_get_fragmap_decoders[] = {
|
||||
{"name", offsetof(struct rpc_bdev_lvol_get_fragmap, name), spdk_json_decode_string, true},
|
||||
{"offset", offsetof(struct rpc_bdev_lvol_get_fragmap, offset), spdk_json_decode_uint64, true},
|
||||
{"size", offsetof(struct rpc_bdev_lvol_get_fragmap, size), spdk_json_decode_uint64, true},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_get_fragmap_cb(void *cb_arg, struct spdk_fragmap *fragmap, int lvolerrno)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
char *encoded;
|
||||
|
||||
if (lvolerrno != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
encoded = spdk_bit_array_to_base64_string(fragmap->map);
|
||||
if (encoded == NULL) {
|
||||
SPDK_ERRLOG("Failed to encode fragmap to base64 string\n");
|
||||
lvolerrno = -EINVAL;
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
spdk_json_write_object_begin(w);
|
||||
|
||||
spdk_json_write_named_uint64(w, "cluster_size", fragmap->cluster_size);
|
||||
spdk_json_write_named_uint64(w, "num_clusters", fragmap->num_clusters);
|
||||
spdk_json_write_named_uint64(w, "num_allocated_clusters", fragmap->num_allocated_clusters);
|
||||
spdk_json_write_named_string(w, "fragmap", encoded);
|
||||
|
||||
spdk_json_write_object_end(w);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
|
||||
free(encoded);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
spdk_strerror(-lvolerrno));
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_lvol_get_fragmap(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_bdev_lvol_get_fragmap req = {};
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_lvol *lvol;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_lvol_get_fragmap_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_lvol_get_fragmap_decoders),
|
||||
&req)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(req.name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
lvol = vbdev_lvol_get_from_bdev(bdev);
|
||||
if (lvol == NULL) {
|
||||
SPDK_ERRLOG("lvol does not exist\n");
|
||||
spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vbdev_lvol_get_fragmap(lvol, req.offset, req.size, rpc_bdev_lvol_get_fragmap_cb, request);
|
||||
|
||||
cleanup:
|
||||
free_rpc_bdev_lvol_get_fragmap(&req);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("bdev_lvol_get_fragmap", rpc_bdev_lvol_get_fragmap, SPDK_RPC_RUNTIME)
|
||||
|
@ -737,7 +737,7 @@ create_malloc_disk(struct spdk_bdev **bdev, const struct malloc_bdev_opts *opts)
|
||||
mdisk->disk.optimal_io_boundary = opts->optimal_io_boundary;
|
||||
mdisk->disk.split_on_optimal_io_boundary = true;
|
||||
}
|
||||
if (!spdk_uuid_is_null(&opts->uuid)) {
|
||||
if (!spdk_mem_all_zero(&opts->uuid, sizeof(opts->uuid))) {
|
||||
spdk_uuid_copy(&mdisk->disk.uuid, &opts->uuid);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@ SPDK_BDEV_MODULE_REGISTER(passthru, &passthru_if)
|
||||
struct bdev_names {
|
||||
char *vbdev_name;
|
||||
char *bdev_name;
|
||||
struct spdk_uuid uuid;
|
||||
TAILQ_ENTRY(bdev_names) link;
|
||||
};
|
||||
static TAILQ_HEAD(, bdev_names) g_bdev_names = TAILQ_HEAD_INITIALIZER(g_bdev_names);
|
||||
@ -405,19 +404,11 @@ vbdev_passthru_config_json(struct spdk_json_write_ctx *w)
|
||||
struct vbdev_passthru *pt_node;
|
||||
|
||||
TAILQ_FOREACH(pt_node, &g_pt_nodes, link) {
|
||||
const struct spdk_uuid *uuid = spdk_bdev_get_uuid(&pt_node->pt_bdev);
|
||||
|
||||
spdk_json_write_object_begin(w);
|
||||
spdk_json_write_named_string(w, "method", "bdev_passthru_create");
|
||||
spdk_json_write_named_object_begin(w, "params");
|
||||
spdk_json_write_named_string(w, "base_bdev_name", spdk_bdev_get_name(pt_node->base_bdev));
|
||||
spdk_json_write_named_string(w, "name", spdk_bdev_get_name(&pt_node->pt_bdev));
|
||||
if (!spdk_uuid_is_null(uuid)) {
|
||||
char uuid_str[SPDK_UUID_STRING_LEN];
|
||||
|
||||
spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), uuid);
|
||||
spdk_json_write_named_string(w, "uuid", uuid_str);
|
||||
}
|
||||
spdk_json_write_object_end(w);
|
||||
spdk_json_write_object_end(w);
|
||||
}
|
||||
@ -456,8 +447,7 @@ pt_bdev_ch_destroy_cb(void *io_device, void *ctx_buf)
|
||||
/* Create the passthru association from the bdev and vbdev name and insert
|
||||
* on the global list. */
|
||||
static int
|
||||
vbdev_passthru_insert_name(const char *bdev_name, const char *vbdev_name,
|
||||
const struct spdk_uuid *uuid)
|
||||
vbdev_passthru_insert_name(const char *bdev_name, const char *vbdev_name)
|
||||
{
|
||||
struct bdev_names *name;
|
||||
|
||||
@ -489,10 +479,6 @@ vbdev_passthru_insert_name(const char *bdev_name, const char *vbdev_name,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (uuid) {
|
||||
spdk_uuid_copy(&name->uuid, uuid);
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_bdev_names, name, link);
|
||||
|
||||
return 0;
|
||||
@ -621,7 +607,6 @@ vbdev_passthru_register(const char *bdev_name)
|
||||
break;
|
||||
}
|
||||
pt_node->pt_bdev.product_name = "passthru";
|
||||
spdk_uuid_copy(&pt_node->pt_bdev.uuid, &name->uuid);
|
||||
|
||||
/* The base bdev that we're attaching to. */
|
||||
rc = spdk_bdev_open_ext(bdev_name, true, vbdev_passthru_base_bdev_event_cb,
|
||||
@ -700,15 +685,14 @@ vbdev_passthru_register(const char *bdev_name)
|
||||
|
||||
/* Create the passthru disk from the given bdev and vbdev name. */
|
||||
int
|
||||
bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name,
|
||||
const struct spdk_uuid *uuid)
|
||||
bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Insert the bdev name into our global name list even if it doesn't exist yet,
|
||||
* it may show up soon...
|
||||
*/
|
||||
rc = vbdev_passthru_insert_name(bdev_name, vbdev_name, uuid);
|
||||
rc = vbdev_passthru_insert_name(bdev_name, vbdev_name);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -16,11 +16,9 @@
|
||||
*
|
||||
* \param bdev_name Bdev on which pass through vbdev will be created.
|
||||
* \param vbdev_name Name of the pass through bdev.
|
||||
* \param uuid Optional UUID to assign to the pass through bdev.
|
||||
* \return 0 on success, other on failure.
|
||||
*/
|
||||
int bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name,
|
||||
const struct spdk_uuid *uuid);
|
||||
int bdev_passthru_create_disk(const char *bdev_name, const char *vbdev_name);
|
||||
|
||||
/**
|
||||
* Delete passthru bdev.
|
||||
|
@ -14,7 +14,6 @@
|
||||
struct rpc_bdev_passthru_create {
|
||||
char *base_bdev_name;
|
||||
char *name;
|
||||
char *uuid;
|
||||
};
|
||||
|
||||
/* Free the allocated memory resource after the RPC handling. */
|
||||
@ -23,14 +22,12 @@ free_rpc_bdev_passthru_create(struct rpc_bdev_passthru_create *r)
|
||||
{
|
||||
free(r->base_bdev_name);
|
||||
free(r->name);
|
||||
free(r->uuid);
|
||||
}
|
||||
|
||||
/* Structure to decode the input parameters for this RPC method. */
|
||||
static const struct spdk_json_object_decoder rpc_bdev_passthru_create_decoders[] = {
|
||||
{"base_bdev_name", offsetof(struct rpc_bdev_passthru_create, base_bdev_name), spdk_json_decode_string},
|
||||
{"name", offsetof(struct rpc_bdev_passthru_create, name), spdk_json_decode_string},
|
||||
{"uuid", offsetof(struct rpc_bdev_passthru_create, uuid), spdk_json_decode_string, true},
|
||||
};
|
||||
|
||||
/* Decode the parameters for this RPC method and properly construct the passthru
|
||||
@ -42,8 +39,6 @@ rpc_bdev_passthru_create(struct spdk_jsonrpc_request *request,
|
||||
{
|
||||
struct rpc_bdev_passthru_create req = {NULL};
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_uuid *uuid = NULL;
|
||||
struct spdk_uuid decoded_uuid;
|
||||
int rc;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_passthru_create_decoders,
|
||||
@ -55,16 +50,7 @@ rpc_bdev_passthru_create(struct spdk_jsonrpc_request *request,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (req.uuid) {
|
||||
if (spdk_uuid_parse(&decoded_uuid, req.uuid)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Failed to parse bdev UUID");
|
||||
goto cleanup;
|
||||
}
|
||||
uuid = &decoded_uuid;
|
||||
}
|
||||
|
||||
rc = bdev_passthru_create_disk(req.base_bdev_name, req.name, uuid);
|
||||
rc = bdev_passthru_create_disk(req.base_bdev_name, req.name);
|
||||
if (rc != 0) {
|
||||
spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
|
||||
goto cleanup;
|
||||
|
@ -10,7 +10,7 @@ SO_VER := 5
|
||||
SO_MINOR := 0
|
||||
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/bdev/
|
||||
C_SRCS = bdev_raid.c bdev_raid_rpc.c bdev_raid_sb.c raid0.c raid1.c concat.c
|
||||
C_SRCS = bdev_raid.c bdev_raid_rpc.c raid0.c raid1.c concat.c
|
||||
|
||||
ifeq ($(CONFIG_RAID5F),y)
|
||||
C_SRCS += raid5f.c
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,13 +9,6 @@
|
||||
#include "spdk/bdev_module.h"
|
||||
#include "spdk/uuid.h"
|
||||
|
||||
#include "bdev_raid_sb.h"
|
||||
|
||||
#define RAID_BDEV_MIN_DATA_OFFSET_SIZE (1024*1024) /* 1 MiB */
|
||||
|
||||
SPDK_STATIC_ASSERT(RAID_BDEV_SB_MAX_LENGTH < RAID_BDEV_MIN_DATA_OFFSET_SIZE,
|
||||
"Incorrect min data offset");
|
||||
|
||||
enum raid_level {
|
||||
INVALID_RAID_LEVEL = -1,
|
||||
RAID0 = 0,
|
||||
@ -54,27 +47,15 @@ enum raid_bdev_state {
|
||||
* required per base device for raid bdev will be kept here
|
||||
*/
|
||||
struct raid_base_bdev_info {
|
||||
/* The raid bdev that this base bdev belongs to */
|
||||
struct raid_bdev *raid_bdev;
|
||||
|
||||
/* name of the bdev */
|
||||
char *name;
|
||||
|
||||
/* uuid of the bdev */
|
||||
struct spdk_uuid uuid;
|
||||
|
||||
/* pointer to base spdk bdev */
|
||||
struct spdk_bdev *bdev;
|
||||
|
||||
/* pointer to base bdev descriptor opened by raid bdev */
|
||||
struct spdk_bdev_desc *desc;
|
||||
|
||||
/* data offset for raid bdev [blocks] */
|
||||
uint64_t data_offset;
|
||||
|
||||
/* data size of for raid bdev [blocks] */
|
||||
uint64_t data_size;
|
||||
|
||||
/*
|
||||
* When underlying base device calls the hot plug function on drive removal,
|
||||
* this flag will be set and later after doing some processing, base device
|
||||
@ -84,12 +65,6 @@ struct raid_base_bdev_info {
|
||||
|
||||
/* Hold the number of blocks to know how large the base bdev is resized. */
|
||||
uint64_t blockcnt;
|
||||
|
||||
/* io channel for the app thread */
|
||||
struct spdk_io_channel *app_thread_ch;
|
||||
|
||||
/* Set to true when base bdev has completed the configuration process */
|
||||
bool is_configured;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -113,8 +88,6 @@ struct raid_bdev_io {
|
||||
|
||||
/* Private data for the raid module */
|
||||
void *module_private;
|
||||
|
||||
TAILQ_ENTRY(raid_bdev_io) link;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -153,9 +126,6 @@ struct raid_bdev {
|
||||
/* number of base bdevs discovered */
|
||||
uint8_t num_base_bdevs_discovered;
|
||||
|
||||
/* number of operational base bdevs */
|
||||
uint8_t num_base_bdevs_operational;
|
||||
|
||||
/* minimum number of viable base bdevs that are required by array to operate */
|
||||
uint8_t min_base_bdevs_operational;
|
||||
|
||||
@ -170,27 +140,6 @@ struct raid_bdev {
|
||||
|
||||
/* Private data for the raid module */
|
||||
void *module_private;
|
||||
|
||||
/* Counter of callers of raid_bdev_suspend() */
|
||||
uint32_t suspend_cnt;
|
||||
|
||||
/* Number of channels remaining to suspend */
|
||||
uint32_t suspend_num_channels;
|
||||
|
||||
/* List of suspend contexts */
|
||||
TAILQ_HEAD(, raid_bdev_suspend_ctx) suspend_ctx;
|
||||
|
||||
/* Device mutex */
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/* Superblock */
|
||||
struct raid_bdev_superblock *sb;
|
||||
|
||||
/* Superblock write context */
|
||||
void *sb_write_ctx;
|
||||
|
||||
/* A flag to indicate that an operation to add a base bdev is in progress */
|
||||
bool base_bdev_updating;
|
||||
};
|
||||
|
||||
#define RAID_FOR_EACH_BASE_BDEV(r, i) \
|
||||
@ -209,15 +158,6 @@ struct raid_bdev_io_channel {
|
||||
|
||||
/* Private raid module IO channel */
|
||||
struct spdk_io_channel *module_channel;
|
||||
|
||||
/* Number of raid IOs on this channel */
|
||||
uint32_t num_ios;
|
||||
|
||||
/* Is the channel currently suspended */
|
||||
bool is_suspended;
|
||||
|
||||
/* List of suspended IOs */
|
||||
TAILQ_HEAD(, raid_bdev_io) suspended_ios;
|
||||
};
|
||||
|
||||
/* TAIL head for raid bdev list */
|
||||
@ -228,8 +168,7 @@ extern struct raid_all_tailq g_raid_bdev_list;
|
||||
typedef void (*raid_bdev_destruct_cb)(void *cb_ctx, int rc);
|
||||
|
||||
int raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs,
|
||||
enum raid_level level, struct raid_bdev **raid_bdev_out,
|
||||
const struct spdk_uuid *uuid, bool superblock);
|
||||
enum raid_level level, struct raid_bdev **raid_bdev_out, const struct spdk_uuid *uuid);
|
||||
void raid_bdev_delete(struct raid_bdev *raid_bdev, raid_bdev_destruct_cb cb_fn, void *cb_ctx);
|
||||
int raid_bdev_add_base_device(struct raid_bdev *raid_bdev, const char *name, uint8_t slot);
|
||||
struct raid_bdev *raid_bdev_find_by_name(const char *name);
|
||||
@ -238,9 +177,6 @@ const char *raid_bdev_level_to_str(enum raid_level level);
|
||||
enum raid_bdev_state raid_bdev_str_to_state(const char *str);
|
||||
const char *raid_bdev_state_to_str(enum raid_bdev_state state);
|
||||
void raid_bdev_write_info_json(struct raid_bdev *raid_bdev, struct spdk_json_write_ctx *w);
|
||||
int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev);
|
||||
int raid_bdev_grow_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev_name,
|
||||
raid_bdev_destruct_cb cb_fn, void *cb_arg);
|
||||
|
||||
/*
|
||||
* RAID module descriptor
|
||||
@ -306,9 +242,6 @@ struct raid_bdev_module {
|
||||
void (*resize)(struct raid_bdev *raid_bdev);
|
||||
|
||||
TAILQ_ENTRY(raid_bdev_module) link;
|
||||
|
||||
bool (*channel_grow_base_bdev)(struct raid_bdev *raid_bdev,
|
||||
struct raid_bdev_io_channel *raid_ch);
|
||||
};
|
||||
|
||||
void raid_bdev_module_list_add(struct raid_bdev_module *raid_module);
|
||||
@ -330,62 +263,4 @@ void raid_bdev_queue_io_wait(struct raid_bdev_io *raid_io, struct spdk_bdev *bde
|
||||
void raid_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status);
|
||||
void raid_bdev_module_stop_done(struct raid_bdev *raid_bdev);
|
||||
|
||||
/**
|
||||
* Raid bdev I/O read/write wrapper for spdk_bdev_readv_blocks_ext function.
|
||||
*/
|
||||
static inline int
|
||||
raid_bdev_readv_blocks_ext(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch,
|
||||
struct iovec *iov, int iovcnt, uint64_t offset_blocks,
|
||||
uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg,
|
||||
struct spdk_bdev_ext_io_opts *opts)
|
||||
{
|
||||
struct spdk_bdev_desc *desc = base_info->desc;
|
||||
uint64_t offset = base_info->data_offset + offset_blocks;
|
||||
|
||||
return spdk_bdev_readv_blocks_ext(desc, ch, iov, iovcnt, offset, num_blocks, cb, cb_arg, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raid bdev I/O read/write wrapper for spdk_bdev_writev_blocks_ext function.
|
||||
*/
|
||||
static inline int
|
||||
raid_bdev_writev_blocks_ext(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch,
|
||||
struct iovec *iov, int iovcnt, uint64_t offset_blocks,
|
||||
uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg,
|
||||
struct spdk_bdev_ext_io_opts *opts)
|
||||
{
|
||||
struct spdk_bdev_desc *desc = base_info->desc;
|
||||
uint64_t offset = base_info->data_offset + offset_blocks;
|
||||
|
||||
return spdk_bdev_writev_blocks_ext(desc, ch, iov, iovcnt, offset, num_blocks, cb, cb_arg, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raid bdev I/O read/write wrapper for spdk_bdev_unmap_blocks function.
|
||||
*/
|
||||
static inline int
|
||||
raid_bdev_unmap_blocks(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch,
|
||||
uint64_t offset_blocks, uint64_t num_blocks,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
struct spdk_bdev_desc *desc = base_info->desc;
|
||||
uint64_t offset = base_info->data_offset + offset_blocks;
|
||||
|
||||
return spdk_bdev_unmap_blocks(desc, ch, offset, num_blocks, cb, cb_arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raid bdev I/O read/write wrapper for spdk_bdev_flush_blocks function.
|
||||
*/
|
||||
static inline int
|
||||
raid_bdev_flush_blocks(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch,
|
||||
uint64_t offset_blocks, uint64_t num_blocks,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
struct spdk_bdev_desc *desc = base_info->desc;
|
||||
uint64_t offset = base_info->data_offset + offset_blocks;
|
||||
|
||||
return spdk_bdev_flush_blocks(desc, ch, offset, num_blocks, cb, cb_arg);
|
||||
}
|
||||
|
||||
#endif /* SPDK_BDEV_RAID_INTERNAL_H */
|
||||
|
@ -87,12 +87,8 @@ rpc_bdev_raid_get_bdevs(struct spdk_jsonrpc_request *request,
|
||||
/* Get raid bdev list based on the category requested */
|
||||
TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
|
||||
if (raid_bdev->state == state || state == RAID_BDEV_STATE_MAX) {
|
||||
char uuid_str[SPDK_UUID_STRING_LEN];
|
||||
|
||||
spdk_json_write_object_begin(w);
|
||||
spdk_json_write_named_string(w, "name", raid_bdev->bdev.name);
|
||||
spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &raid_bdev->bdev.uuid);
|
||||
spdk_json_write_named_string(w, "uuid", uuid_str);
|
||||
raid_bdev_write_info_json(raid_bdev, w);
|
||||
spdk_json_write_object_end(w);
|
||||
}
|
||||
@ -134,9 +130,6 @@ struct rpc_bdev_raid_create {
|
||||
|
||||
/* UUID for this raid bdev */
|
||||
char *uuid;
|
||||
|
||||
/* superblock support */
|
||||
bool superblock;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -203,7 +196,6 @@ static const struct spdk_json_object_decoder rpc_bdev_raid_create_decoders[] = {
|
||||
{"raid_level", offsetof(struct rpc_bdev_raid_create, level), decode_raid_level},
|
||||
{"base_bdevs", offsetof(struct rpc_bdev_raid_create, base_bdevs), decode_base_bdevs},
|
||||
{"uuid", offsetof(struct rpc_bdev_raid_create, uuid), spdk_json_decode_string, true},
|
||||
{"superblock", offsetof(struct rpc_bdev_raid_create, superblock), spdk_json_decode_bool, true},
|
||||
};
|
||||
|
||||
/*
|
||||
@ -245,7 +237,7 @@ rpc_bdev_raid_create(struct spdk_jsonrpc_request *request,
|
||||
}
|
||||
|
||||
rc = raid_bdev_create(req.name, req.strip_size_kb, req.base_bdevs.num_base_bdevs,
|
||||
req.level, &raid_bdev, uuid, req.superblock);
|
||||
req.level, &raid_bdev, uuid);
|
||||
if (rc != 0) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, rc,
|
||||
"Failed to create RAID bdev %s: %s",
|
||||
@ -389,192 +381,3 @@ cleanup:
|
||||
free(ctx);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_raid_delete", rpc_bdev_raid_delete, SPDK_RPC_RUNTIME)
|
||||
|
||||
/*
|
||||
* Decoder object for RPC bdev_raid_remove_base_bdev
|
||||
*/
|
||||
static const struct spdk_json_object_decoder rpc_bdev_raid_remove_base_bdev_decoders[] = {
|
||||
{"name", 0, spdk_json_decode_string},
|
||||
};
|
||||
|
||||
/*
|
||||
* brief:
|
||||
* bdev_raid_remove_base_bdev function is the RPC for removing base bdev from a raid bdev.
|
||||
* It takes base bdev name as input.
|
||||
* params:
|
||||
* request - pointer to json rpc request
|
||||
* params - pointer to request parameters
|
||||
* returns:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
rpc_bdev_raid_remove_base_bdev(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct spdk_bdev *bdev;
|
||||
char *name = NULL;
|
||||
int rc;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_raid_remove_base_bdev_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_raid_remove_base_bdev_decoders),
|
||||
&name)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
return;
|
||||
}
|
||||
|
||||
bdev = spdk_bdev_get_by_name(name);
|
||||
if (bdev == NULL) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, "base bdev %s is not found in config", name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = raid_bdev_remove_base_bdev(bdev);
|
||||
if (rc != 0) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, rc, "Failed to remove base bdev %s from raid bdev",
|
||||
name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
spdk_jsonrpc_send_bool_response(request, true);
|
||||
|
||||
cleanup:
|
||||
free(name);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME)
|
||||
|
||||
/*
|
||||
* Input structure for RPC rpc_bdev_raid_grow_base_bdev
|
||||
*/
|
||||
struct rpc_bdev_raid_grow_base_bdev {
|
||||
/* Raid bdev name */
|
||||
char *raid_bdev_name;
|
||||
|
||||
/* Base bdev name */
|
||||
char *base_bdev_name;
|
||||
};
|
||||
|
||||
/*
|
||||
* brief:
|
||||
* free_rpc_bdev_raid_grow_base_bdev frees RPC bdev_raid_grow_base_bdev related parameters
|
||||
* params:
|
||||
* req - pointer to RPC request
|
||||
* returns:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
free_rpc_bdev_raid_grow_base_bdev(struct rpc_bdev_raid_grow_base_bdev *req)
|
||||
{
|
||||
free(req->raid_bdev_name);
|
||||
free(req->base_bdev_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decoder object for RPC bdev_raid_grow_base_bdev
|
||||
*/
|
||||
static const struct spdk_json_object_decoder rpc_bdev_raid_grow_base_bdev_decoders[] = {
|
||||
{"raid_name", offsetof(struct rpc_bdev_raid_grow_base_bdev, raid_bdev_name), spdk_json_decode_string},
|
||||
{"base_name", offsetof(struct rpc_bdev_raid_grow_base_bdev, base_bdev_name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
struct rpc_bdev_raid_grow_base_bdev_ctx {
|
||||
struct rpc_bdev_raid_grow_base_bdev req;
|
||||
struct spdk_jsonrpc_request *request;
|
||||
};
|
||||
|
||||
/*
|
||||
* brief:
|
||||
* params:
|
||||
* cb_arg - pointer to the callback context.
|
||||
* rc - return code of the adding a base bdev.
|
||||
* returns:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
bdev_raid_grow_base_bdev_done(void *cb_arg, int rc)
|
||||
{
|
||||
struct rpc_bdev_raid_grow_base_bdev_ctx *ctx = cb_arg;
|
||||
struct spdk_jsonrpc_request *request = ctx->request;
|
||||
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to grow raid %s adding base bdev %s (%d): %s\n",
|
||||
ctx->req.raid_bdev_name, ctx->req.base_bdev_name, rc, spdk_strerror(-rc));
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
spdk_strerror(-rc));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
spdk_jsonrpc_send_bool_response(request, true);
|
||||
exit:
|
||||
free_rpc_bdev_raid_grow_base_bdev(&ctx->req);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* brief:
|
||||
* bdev_raid_grow_base_bdev is the RPC add a base bdev to a raid bdev, growing the raid's size if needed
|
||||
* It takes raid bdev name and base bdev name as input.
|
||||
* params:
|
||||
* request - pointer to json rpc request
|
||||
* params - pointer to request parameters
|
||||
* returns:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
rpc_bdev_raid_grow_base_bdev(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_bdev_raid_grow_base_bdev_ctx *ctx;
|
||||
struct raid_bdev *raid_bdev;
|
||||
struct spdk_bdev *base_bdev;
|
||||
int rc;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
|
||||
return;
|
||||
}
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_bdev_raid_grow_base_bdev_decoders,
|
||||
SPDK_COUNTOF(rpc_bdev_raid_grow_base_bdev_decoders),
|
||||
&ctx->req)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
raid_bdev = raid_bdev_find_by_name(ctx->req.raid_bdev_name);
|
||||
if (raid_bdev == NULL) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, -ENODEV,
|
||||
"raid bdev %s not found",
|
||||
ctx->req.raid_bdev_name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
base_bdev = spdk_bdev_get_by_name(ctx->req.base_bdev_name);
|
||||
if (base_bdev == NULL) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, -ENODEV,
|
||||
"base bdev %s not found",
|
||||
ctx->req.base_bdev_name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ctx->request = request;
|
||||
|
||||
rc = raid_bdev_grow_base_bdev(raid_bdev, ctx->req.base_bdev_name, bdev_raid_grow_base_bdev_done,
|
||||
ctx);
|
||||
if (rc != 0) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, rc,
|
||||
"Failed to grow raid %s adding base bdev %s: %s",
|
||||
ctx->req.raid_bdev_name, ctx->req.base_bdev_name,
|
||||
spdk_strerror(-rc));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
free_rpc_bdev_raid_grow_base_bdev(&ctx->req);
|
||||
free(ctx);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_raid_grow_base_bdev", rpc_bdev_raid_grow_base_bdev, SPDK_RPC_RUNTIME)
|
||||
|
@ -1,229 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "spdk/bdev_module.h"
|
||||
#include "spdk/crc32.h"
|
||||
#include "spdk/env.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/util.h"
|
||||
|
||||
#include "bdev_raid_sb.h"
|
||||
|
||||
struct raid_bdev_read_sb_ctx {
|
||||
struct spdk_bdev_desc *desc;
|
||||
struct spdk_io_channel *ch;
|
||||
raid_bdev_load_sb_cb cb;
|
||||
void *cb_ctx;
|
||||
void *buf;
|
||||
uint32_t buf_size;
|
||||
};
|
||||
|
||||
struct raid_bdev_save_sb_ctx {
|
||||
raid_bdev_save_sb_cb cb;
|
||||
void *cb_ctx;
|
||||
};
|
||||
|
||||
static void raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
|
||||
|
||||
static int
|
||||
raid_bdev_parse_superblock(struct raid_bdev_read_sb_ctx *ctx)
|
||||
{
|
||||
struct raid_bdev_superblock *sb = ctx->buf;
|
||||
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
|
||||
uint32_t crc;
|
||||
|
||||
if (memcmp(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature))) {
|
||||
SPDK_DEBUGLOG(bdev_raid_sb, "invalid signature\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sb->length > ctx->buf_size) {
|
||||
if (sb->length > RAID_BDEV_SB_MAX_LENGTH) {
|
||||
SPDK_DEBUGLOG(bdev_raid_sb, "invalid length\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
crc = sb->crc;
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
if (sb->crc != crc) {
|
||||
SPDK_WARNLOG("Incorrect superblock crc on bdev %s\n", spdk_bdev_get_name(bdev));
|
||||
sb->crc = crc;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sb->version.major > RAID_BDEV_SB_VERSION_MAJOR) {
|
||||
SPDK_ERRLOG("Not supported superblock major version %d on bdev %s\n",
|
||||
sb->version.major, spdk_bdev_get_name(bdev));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sb->version.major == RAID_BDEV_SB_VERSION_MAJOR &&
|
||||
sb->version.minor > RAID_BDEV_SB_VERSION_MINOR) {
|
||||
SPDK_WARNLOG("Superblock minor version %d on bdev %s is higher than the currently supported: %d\n",
|
||||
sb->version.minor, spdk_bdev_get_name(bdev), RAID_BDEV_SB_VERSION_MINOR);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
raid_bdev_read_sb_ctx_free(struct raid_bdev_read_sb_ctx *ctx)
|
||||
{
|
||||
spdk_dma_free(ctx->buf);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static int
|
||||
raid_bdev_read_sb_remainder(struct raid_bdev_read_sb_ctx *ctx)
|
||||
{
|
||||
struct raid_bdev_superblock *sb = ctx->buf;
|
||||
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc);
|
||||
uint32_t buf_size_prev;
|
||||
void *buf;
|
||||
int rc;
|
||||
|
||||
buf_size_prev = ctx->buf_size;
|
||||
ctx->buf_size = SPDK_ALIGN_CEIL(sb->length, spdk_bdev_get_block_size(bdev));
|
||||
buf = spdk_dma_realloc(ctx->buf, ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
|
||||
if (buf == NULL) {
|
||||
SPDK_ERRLOG("Failed to reallocate buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ctx->buf = buf;
|
||||
|
||||
rc = spdk_bdev_read(ctx->desc, ctx->ch, ctx->buf + buf_size_prev, buf_size_prev,
|
||||
ctx->buf_size - buf_size_prev, raid_bdev_read_sb_cb, ctx);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to read bdev %s superblock remainder: %s\n",
|
||||
spdk_bdev_get_name(bdev), spdk_strerror(-rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||
{
|
||||
struct raid_bdev_read_sb_ctx *ctx = cb_arg;
|
||||
struct raid_bdev_superblock *sb = NULL;
|
||||
int status;
|
||||
|
||||
spdk_bdev_free_io(bdev_io);
|
||||
|
||||
if (success) {
|
||||
status = raid_bdev_parse_superblock(ctx);
|
||||
if (status == -EAGAIN) {
|
||||
status = raid_bdev_read_sb_remainder(ctx);
|
||||
if (status == 0) {
|
||||
return;
|
||||
}
|
||||
} else if (status != 0) {
|
||||
SPDK_DEBUGLOG(bdev_raid_sb, "failed to parse bdev %s superblock\n",
|
||||
spdk_bdev_get_name(spdk_bdev_desc_get_bdev(ctx->desc)));
|
||||
} else {
|
||||
sb = ctx->buf;
|
||||
}
|
||||
} else {
|
||||
status = -EIO;
|
||||
}
|
||||
|
||||
if (ctx->cb) {
|
||||
ctx->cb(sb, status, ctx->cb_ctx);
|
||||
}
|
||||
|
||||
raid_bdev_read_sb_ctx_free(ctx);
|
||||
}
|
||||
|
||||
int
|
||||
raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
raid_bdev_load_sb_cb cb, void *cb_ctx)
|
||||
{
|
||||
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
|
||||
struct raid_bdev_read_sb_ctx *ctx;
|
||||
int rc;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctx->desc = desc;
|
||||
ctx->ch = ch;
|
||||
ctx->cb = cb;
|
||||
ctx->cb_ctx = cb_ctx;
|
||||
ctx->buf_size = SPDK_ALIGN_CEIL(sizeof(struct raid_bdev_superblock),
|
||||
spdk_bdev_get_block_size(bdev));
|
||||
ctx->buf = spdk_dma_malloc(ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
|
||||
if (!ctx->buf) {
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = spdk_bdev_read(desc, ch, ctx->buf, 0, ctx->buf_size, raid_bdev_read_sb_cb, ctx);
|
||||
if (rc) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
raid_bdev_read_sb_ctx_free(ctx);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
raid_bdev_write_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||
{
|
||||
struct raid_bdev_save_sb_ctx *ctx = cb_arg;
|
||||
|
||||
spdk_bdev_free_io(bdev_io);
|
||||
|
||||
if (ctx->cb) {
|
||||
ctx->cb(success ? 0 : -EIO, ctx->cb_ctx);
|
||||
}
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int
|
||||
raid_bdev_save_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
const struct raid_bdev_superblock *sb,
|
||||
raid_bdev_save_sb_cb cb, void *cb_ctx)
|
||||
{
|
||||
struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
|
||||
uint64_t nbytes = SPDK_ALIGN_CEIL(sb->length, spdk_bdev_get_block_size(bdev));
|
||||
struct raid_bdev_save_sb_ctx *ctx;
|
||||
int rc;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctx->cb = cb;
|
||||
ctx->cb_ctx = cb_ctx;
|
||||
|
||||
rc = spdk_bdev_write(desc, ch, (void *)sb, 0, nbytes, raid_bdev_write_sb_cb, ctx);
|
||||
if (rc) {
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb)
|
||||
{
|
||||
sb->crc = 0;
|
||||
sb->crc = spdk_crc32c_update(sb, sb->length, 0);
|
||||
}
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(bdev_raid_sb)
|
@ -1,98 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef SPDK_BDEV_RAID_SB_H_
|
||||
#define SPDK_BDEV_RAID_SB_H_
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/uuid.h"
|
||||
|
||||
#define RAID_BDEV_SB_VERSION_MAJOR 1
|
||||
#define RAID_BDEV_SB_VERSION_MINOR 0
|
||||
|
||||
#define RAID_BDEV_SB_NAME_SIZE 64
|
||||
|
||||
#define RAID_BDEV_SB_MAX_LENGTH \
|
||||
SPDK_ALIGN_CEIL((sizeof(struct raid_bdev_superblock) + UINT8_MAX * sizeof(struct raid_bdev_sb_base_bdev)), 0x1000)
|
||||
|
||||
enum raid_bdev_sb_base_bdev_state {
|
||||
RAID_SB_BASE_BDEV_MISSING = 0,
|
||||
RAID_SB_BASE_BDEV_CONFIGURED = 1,
|
||||
RAID_SB_BASE_BDEV_FAILED = 2,
|
||||
RAID_SB_BASE_BDEV_REMOVED = 3,
|
||||
};
|
||||
|
||||
struct raid_bdev_sb_base_bdev {
|
||||
/* uuid of the base bdev */
|
||||
struct spdk_uuid uuid;
|
||||
/* offset in blocks from base device start to the start of raid data area */
|
||||
uint64_t data_offset;
|
||||
/* size in blocks of the base device raid data area */
|
||||
uint64_t data_size;
|
||||
/* state of the base bdev */
|
||||
uint32_t state;
|
||||
/* feature/status flags */
|
||||
uint32_t flags;
|
||||
/* slot number of this base bdev in the raid */
|
||||
uint8_t slot;
|
||||
|
||||
uint8_t reserved[23];
|
||||
};
|
||||
SPDK_STATIC_ASSERT(sizeof(struct raid_bdev_sb_base_bdev) == 64, "incorrect size");
|
||||
|
||||
struct raid_bdev_superblock {
|
||||
#define RAID_BDEV_SB_SIG "SPDKRAID"
|
||||
uint8_t signature[8];
|
||||
struct {
|
||||
/* incremented when a breaking change in the superblock structure is made */
|
||||
uint16_t major;
|
||||
/* incremented for changes in the superblock that are backward compatible */
|
||||
uint16_t minor;
|
||||
} version;
|
||||
/* length in bytes of the entire superblock */
|
||||
uint32_t length;
|
||||
/* crc32c checksum of the entire superblock */
|
||||
uint32_t crc;
|
||||
/* feature/status flags */
|
||||
uint32_t flags;
|
||||
/* unique id of the raid bdev */
|
||||
struct spdk_uuid uuid;
|
||||
/* name of the raid bdev */
|
||||
uint8_t name[RAID_BDEV_SB_NAME_SIZE];
|
||||
/* size of the raid bdev in blocks */
|
||||
uint64_t raid_size;
|
||||
/* the raid bdev block size - must be the same for all base bdevs */
|
||||
uint32_t block_size;
|
||||
/* the raid level */
|
||||
uint32_t level;
|
||||
/* strip (chunk) size in blocks */
|
||||
uint32_t strip_size;
|
||||
/* state of the raid */
|
||||
uint32_t state;
|
||||
/* sequence number, incremented on every superblock update */
|
||||
uint64_t seq_number;
|
||||
/* number of raid base devices */
|
||||
uint8_t num_base_bdevs;
|
||||
|
||||
uint8_t reserved[86];
|
||||
|
||||
/* size of the base bdevs array */
|
||||
uint8_t base_bdevs_size;
|
||||
/* array of base bdev descriptors */
|
||||
struct raid_bdev_sb_base_bdev base_bdevs[];
|
||||
};
|
||||
SPDK_STATIC_ASSERT(sizeof(struct raid_bdev_superblock) == 224, "incorrect size");
|
||||
|
||||
typedef void (*raid_bdev_load_sb_cb)(const struct raid_bdev_superblock *sb, int status, void *ctx);
|
||||
typedef void (*raid_bdev_save_sb_cb)(int status, void *ctx);
|
||||
|
||||
int raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
raid_bdev_load_sb_cb cb, void *cb_ctx);
|
||||
int raid_bdev_save_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
const struct raid_bdev_superblock *sb, raid_bdev_save_sb_cb cb, void *cb_ctx);
|
||||
void raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb);
|
||||
|
||||
#endif /* SPDK_BDEV_RAID_SB_H_ */
|
@ -110,12 +110,12 @@ concat_submit_rw_request(struct raid_bdev_io *raid_io)
|
||||
io_opts.metadata = bdev_io->u.bdev.md_buf;
|
||||
|
||||
if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
|
||||
ret = raid_bdev_readv_blocks_ext(base_info, base_ch,
|
||||
ret = spdk_bdev_readv_blocks_ext(base_info->desc, base_ch,
|
||||
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
||||
pd_lba, pd_blocks, concat_bdev_io_completion,
|
||||
raid_io, &io_opts);
|
||||
} else if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) {
|
||||
ret = raid_bdev_writev_blocks_ext(base_info, base_ch,
|
||||
ret = spdk_bdev_writev_blocks_ext(base_info->desc, base_ch,
|
||||
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
||||
pd_lba, pd_blocks, concat_bdev_io_completion,
|
||||
raid_io, &io_opts);
|
||||
@ -242,12 +242,12 @@ concat_submit_null_payload_request(struct raid_bdev_io *raid_io)
|
||||
base_ch = raid_io->raid_ch->base_channel[i];
|
||||
switch (bdev_io->type) {
|
||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||
ret = raid_bdev_unmap_blocks(base_info, base_ch,
|
||||
ret = spdk_bdev_unmap_blocks(base_info->desc, base_ch,
|
||||
pd_lba, pd_blocks,
|
||||
concat_base_io_complete, raid_io);
|
||||
break;
|
||||
case SPDK_BDEV_IO_TYPE_FLUSH:
|
||||
ret = raid_bdev_flush_blocks(base_info, base_ch,
|
||||
ret = spdk_bdev_flush_blocks(base_info->desc, base_ch,
|
||||
pd_lba, pd_blocks,
|
||||
concat_base_io_complete, raid_io);
|
||||
break;
|
||||
@ -287,11 +287,9 @@ concat_start(struct raid_bdev *raid_bdev)
|
||||
|
||||
int idx = 0;
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
uint64_t strip_cnt = base_info->data_size >> raid_bdev->strip_size_shift;
|
||||
uint64_t strip_cnt = base_info->bdev->blockcnt >> raid_bdev->strip_size_shift;
|
||||
uint64_t pd_block_cnt = strip_cnt << raid_bdev->strip_size_shift;
|
||||
|
||||
base_info->data_size = pd_block_cnt;
|
||||
|
||||
block_range[idx].start = total_blockcnt;
|
||||
block_range[idx].length = pd_block_cnt;
|
||||
total_blockcnt += pd_block_cnt;
|
||||
|
@ -111,12 +111,12 @@ raid0_submit_rw_request(struct raid_bdev_io *raid_io)
|
||||
io_opts.metadata = bdev_io->u.bdev.md_buf;
|
||||
|
||||
if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
|
||||
ret = raid_bdev_readv_blocks_ext(base_info, base_ch,
|
||||
ret = spdk_bdev_readv_blocks_ext(base_info->desc, base_ch,
|
||||
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
||||
pd_lba, pd_blocks, raid0_bdev_io_completion,
|
||||
raid_io, &io_opts);
|
||||
} else if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) {
|
||||
ret = raid_bdev_writev_blocks_ext(base_info, base_ch,
|
||||
ret = spdk_bdev_writev_blocks_ext(base_info->desc, base_ch,
|
||||
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
||||
pd_lba, pd_blocks, raid0_bdev_io_completion,
|
||||
raid_io, &io_opts);
|
||||
@ -303,13 +303,13 @@ raid0_submit_null_payload_request(struct raid_bdev_io *raid_io)
|
||||
|
||||
switch (bdev_io->type) {
|
||||
case SPDK_BDEV_IO_TYPE_UNMAP:
|
||||
ret = raid_bdev_unmap_blocks(base_info, base_ch,
|
||||
ret = spdk_bdev_unmap_blocks(base_info->desc, base_ch,
|
||||
offset_in_disk, nblocks_in_disk,
|
||||
raid0_base_io_complete, raid_io);
|
||||
break;
|
||||
|
||||
case SPDK_BDEV_IO_TYPE_FLUSH:
|
||||
ret = raid_bdev_flush_blocks(base_info, base_ch,
|
||||
ret = spdk_bdev_flush_blocks(base_info->desc, base_ch,
|
||||
offset_in_disk, nblocks_in_disk,
|
||||
raid0_base_io_complete, raid_io);
|
||||
break;
|
||||
@ -335,22 +335,15 @@ raid0_submit_null_payload_request(struct raid_bdev_io *raid_io)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
raid0_start(struct raid_bdev *raid_bdev)
|
||||
static uint64_t
|
||||
raid0_calculate_blockcnt(struct raid_bdev *raid_bdev)
|
||||
{
|
||||
uint64_t min_blockcnt = UINT64_MAX;
|
||||
uint64_t base_bdev_data_size;
|
||||
struct raid_base_bdev_info *base_info;
|
||||
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
/* Calculate minimum block count from all base bdevs */
|
||||
min_blockcnt = spdk_min(min_blockcnt, base_info->data_size);
|
||||
}
|
||||
|
||||
base_bdev_data_size = (min_blockcnt >> raid_bdev->strip_size_shift) << raid_bdev->strip_size_shift;
|
||||
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
base_info->data_size = base_bdev_data_size;
|
||||
min_blockcnt = spdk_min(min_blockcnt, base_info->bdev->blockcnt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -361,7 +354,14 @@ raid0_start(struct raid_bdev *raid_bdev)
|
||||
SPDK_DEBUGLOG(bdev_raid0, "min blockcount %" PRIu64 ", numbasedev %u, strip size shift %u\n",
|
||||
min_blockcnt, raid_bdev->num_base_bdevs, raid_bdev->strip_size_shift);
|
||||
|
||||
raid_bdev->bdev.blockcnt = base_bdev_data_size * raid_bdev->num_base_bdevs;
|
||||
return ((min_blockcnt >> raid_bdev->strip_size_shift) <<
|
||||
raid_bdev->strip_size_shift) * raid_bdev->num_base_bdevs;
|
||||
}
|
||||
|
||||
static int
|
||||
raid0_start(struct raid_bdev *raid_bdev)
|
||||
{
|
||||
raid_bdev->bdev.blockcnt = raid0_calculate_blockcnt(raid_bdev);
|
||||
|
||||
if (raid_bdev->num_base_bdevs > 1) {
|
||||
raid_bdev->bdev.optimal_io_boundary = raid_bdev->strip_size;
|
||||
@ -380,16 +380,8 @@ raid0_resize(struct raid_bdev *raid_bdev)
|
||||
{
|
||||
uint64_t blockcnt;
|
||||
int rc;
|
||||
uint64_t min_blockcnt = UINT64_MAX;
|
||||
struct raid_base_bdev_info *base_info;
|
||||
uint64_t base_bdev_data_size;
|
||||
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
min_blockcnt = spdk_min(min_blockcnt, base_info->bdev->blockcnt - base_info->data_offset);
|
||||
}
|
||||
|
||||
base_bdev_data_size = (min_blockcnt >> raid_bdev->strip_size_shift) << raid_bdev->strip_size_shift;
|
||||
blockcnt = base_bdev_data_size * raid_bdev->num_base_bdevs;
|
||||
blockcnt = raid0_calculate_blockcnt(raid_bdev);
|
||||
|
||||
if (blockcnt == raid_bdev->bdev.blockcnt) {
|
||||
return;
|
||||
@ -403,11 +395,6 @@ raid0_resize(struct raid_bdev *raid_bdev)
|
||||
rc = spdk_bdev_notify_blockcnt_change(&raid_bdev->bdev, blockcnt);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to notify blockcount change\n");
|
||||
return;
|
||||
}
|
||||
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
base_info->data_size = base_bdev_data_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,17 +13,6 @@ struct raid1_info {
|
||||
struct raid_bdev *raid_bdev;
|
||||
};
|
||||
|
||||
struct raid1_io_channel {
|
||||
/* Index of last base bdev used for reads */
|
||||
uint8_t base_bdev_read_idx;
|
||||
|
||||
/* Read bandwidths generated for base_bdevs */
|
||||
uint64_t *base_bdev_read_bw;
|
||||
|
||||
/* Maximum read bandwidth from all base_bdevs */
|
||||
uint64_t base_bdev_max_read_bw;
|
||||
};
|
||||
|
||||
static void
|
||||
raid1_bdev_io_completion(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||
{
|
||||
@ -56,81 +45,25 @@ raid1_init_ext_io_opts(struct spdk_bdev_io *bdev_io, struct spdk_bdev_ext_io_opt
|
||||
opts->metadata = bdev_io->u.bdev.md_buf;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
raid1_channel_next_read_base_bdev(struct raid_bdev_io_channel *raid_ch)
|
||||
{
|
||||
struct raid1_io_channel *raid1_ch = spdk_io_channel_get_ctx(raid_ch->module_channel);
|
||||
uint8_t idx = raid1_ch->base_bdev_read_idx;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < raid_ch->num_channels; i++) {
|
||||
if (++idx == raid_ch->num_channels) {
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
if (raid_ch->base_channel[idx]) {
|
||||
raid1_ch->base_bdev_read_idx = idx;
|
||||
|
||||
if (raid1_ch->base_bdev_read_bw[idx] < raid1_ch->base_bdev_max_read_bw) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return raid1_ch->base_bdev_read_idx;
|
||||
}
|
||||
|
||||
static void
|
||||
raid1_channel_update_read_bw_counters(struct raid_bdev_io_channel *raid_ch, uint64_t pd_blocks)
|
||||
{
|
||||
struct raid1_io_channel *raid1_ch = spdk_io_channel_get_ctx(raid_ch->module_channel);
|
||||
uint8_t idx = raid1_ch->base_bdev_read_idx;
|
||||
uint8_t i;
|
||||
|
||||
if (spdk_unlikely(raid1_ch->base_bdev_max_read_bw > UINT64_MAX - pd_blocks)) {
|
||||
for (i = 0; i < raid_ch->num_channels; i++) {
|
||||
raid1_ch->base_bdev_read_bw[i] = 0;
|
||||
}
|
||||
raid1_ch->base_bdev_max_read_bw = 0;
|
||||
}
|
||||
|
||||
raid1_ch->base_bdev_read_bw[idx] += pd_blocks;
|
||||
raid1_ch->base_bdev_max_read_bw = spdk_max(raid1_ch->base_bdev_max_read_bw,
|
||||
raid1_ch->base_bdev_read_bw[idx]);
|
||||
}
|
||||
|
||||
static int
|
||||
raid1_submit_read_request(struct raid_bdev_io *raid_io)
|
||||
{
|
||||
struct raid_bdev *raid_bdev = raid_io->raid_bdev;
|
||||
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(raid_io);
|
||||
struct spdk_bdev_ext_io_opts io_opts;
|
||||
struct raid_bdev_io_channel *raid_ch = raid_io->raid_ch;
|
||||
struct raid_base_bdev_info *base_info;
|
||||
struct spdk_io_channel *base_ch = NULL;
|
||||
uint8_t ch_idx = 0;
|
||||
struct raid_base_bdev_info *base_info = &raid_bdev->base_bdev_info[ch_idx];
|
||||
struct spdk_io_channel *base_ch = raid_io->raid_ch->base_channel[ch_idx];
|
||||
uint64_t pd_lba, pd_blocks;
|
||||
uint8_t idx;
|
||||
int ret;
|
||||
|
||||
pd_lba = bdev_io->u.bdev.offset_blocks;
|
||||
pd_blocks = bdev_io->u.bdev.num_blocks;
|
||||
|
||||
idx = raid1_channel_next_read_base_bdev(raid_ch);
|
||||
|
||||
if (spdk_unlikely(raid_ch->base_channel[idx] == NULL)) {
|
||||
raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
raid1_channel_update_read_bw_counters(raid_ch, pd_blocks);
|
||||
|
||||
base_info = &raid_bdev->base_bdev_info[idx];
|
||||
base_ch = raid_io->raid_ch->base_channel[idx];
|
||||
|
||||
raid_io->base_bdev_io_remaining = 1;
|
||||
|
||||
raid1_init_ext_io_opts(bdev_io, &io_opts);
|
||||
ret = raid_bdev_readv_blocks_ext(base_info, base_ch,
|
||||
ret = spdk_bdev_readv_blocks_ext(base_info->desc, base_ch,
|
||||
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
||||
pd_lba, pd_blocks, raid1_bdev_io_completion,
|
||||
raid_io, &io_opts);
|
||||
@ -155,7 +88,7 @@ raid1_submit_write_request(struct raid_bdev_io *raid_io)
|
||||
struct raid_base_bdev_info *base_info;
|
||||
struct spdk_io_channel *base_ch;
|
||||
uint64_t pd_lba, pd_blocks;
|
||||
uint8_t idx;
|
||||
uint16_t idx = raid_io->base_bdev_io_submitted;
|
||||
uint64_t base_bdev_io_not_submitted;
|
||||
int ret = 0;
|
||||
|
||||
@ -167,17 +100,11 @@ raid1_submit_write_request(struct raid_bdev_io *raid_io)
|
||||
}
|
||||
|
||||
raid1_init_ext_io_opts(bdev_io, &io_opts);
|
||||
for (idx = raid_io->base_bdev_io_submitted; idx < raid_bdev->num_base_bdevs; idx++) {
|
||||
for (; idx < raid_bdev->num_base_bdevs; idx++) {
|
||||
base_info = &raid_bdev->base_bdev_info[idx];
|
||||
base_ch = raid_io->raid_ch->base_channel[idx];
|
||||
|
||||
if (base_ch == NULL) {
|
||||
raid_io->base_bdev_io_submitted++;
|
||||
raid_bdev_io_complete_part(raid_io, 1, SPDK_BDEV_IO_STATUS_SUCCESS);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = raid_bdev_writev_blocks_ext(base_info, base_ch,
|
||||
ret = spdk_bdev_writev_blocks_ext(base_info->desc, base_ch,
|
||||
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
||||
pd_lba, pd_blocks, raid1_bdev_io_completion,
|
||||
raid_io, &io_opts);
|
||||
@ -198,10 +125,6 @@ raid1_submit_write_request(struct raid_bdev_io *raid_io)
|
||||
raid_io->base_bdev_io_submitted++;
|
||||
}
|
||||
|
||||
if (raid_io->base_bdev_io_submitted == 0) {
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -228,44 +151,6 @@ raid1_submit_rw_request(struct raid_bdev_io *raid_io)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
raid1_ioch_destroy(void *io_device, void *ctx_buf)
|
||||
{
|
||||
struct raid1_io_channel *r1ch = ctx_buf;
|
||||
|
||||
free(r1ch->base_bdev_read_bw);
|
||||
}
|
||||
|
||||
static int
|
||||
raid1_ioch_create(void *io_device, void *ctx_buf)
|
||||
{
|
||||
struct raid1_io_channel *r1ch = ctx_buf;
|
||||
struct raid1_info *r1info = io_device;
|
||||
struct raid_bdev *raid_bdev = r1info->raid_bdev;
|
||||
int status = 0;
|
||||
|
||||
r1ch->base_bdev_read_idx = 0;
|
||||
r1ch->base_bdev_max_read_bw = 0;
|
||||
r1ch->base_bdev_read_bw = calloc(raid_bdev->num_base_bdevs,
|
||||
sizeof(*r1ch->base_bdev_read_bw));
|
||||
if (!r1ch->base_bdev_read_bw) {
|
||||
SPDK_ERRLOG("Failed to initialize io channel\n");
|
||||
status = -ENOMEM;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
raid1_io_device_unregister_done(void *io_device)
|
||||
{
|
||||
struct raid1_info *r1info = io_device;
|
||||
|
||||
raid_bdev_module_stop_done(r1info->raid_bdev);
|
||||
|
||||
free(r1info);
|
||||
}
|
||||
|
||||
static int
|
||||
raid1_start(struct raid_bdev *raid_bdev)
|
||||
{
|
||||
@ -281,19 +166,12 @@ raid1_start(struct raid_bdev *raid_bdev)
|
||||
r1info->raid_bdev = raid_bdev;
|
||||
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
min_blockcnt = spdk_min(min_blockcnt, base_info->data_size);
|
||||
}
|
||||
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
base_info->data_size = min_blockcnt;
|
||||
min_blockcnt = spdk_min(min_blockcnt, base_info->bdev->blockcnt);
|
||||
}
|
||||
|
||||
raid_bdev->bdev.blockcnt = min_blockcnt;
|
||||
raid_bdev->module_private = r1info;
|
||||
|
||||
spdk_io_device_register(r1info, raid1_ioch_create, raid1_ioch_destroy,
|
||||
sizeof(struct raid1_io_channel), NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -302,49 +180,19 @@ raid1_stop(struct raid_bdev *raid_bdev)
|
||||
{
|
||||
struct raid1_info *r1info = raid_bdev->module_private;
|
||||
|
||||
spdk_io_device_unregister(r1info, raid1_io_device_unregister_done);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct spdk_io_channel *
|
||||
raid1_get_io_channel(struct raid_bdev *raid_bdev)
|
||||
{
|
||||
struct raid1_info *r1info = raid_bdev->module_private;
|
||||
|
||||
return spdk_get_io_channel(r1info);
|
||||
}
|
||||
|
||||
static bool
|
||||
channel_grow_base_bdev(struct raid_bdev *raid_bdev, struct raid_bdev_io_channel *raid_ch)
|
||||
{
|
||||
struct raid1_io_channel *raid1_ch = spdk_io_channel_get_ctx(raid_ch->module_channel);
|
||||
void *tmp;
|
||||
|
||||
tmp = realloc(raid1_ch->base_bdev_read_bw,
|
||||
raid_bdev->num_base_bdevs * sizeof(*raid1_ch->base_bdev_read_bw));
|
||||
if (!tmp) {
|
||||
SPDK_ERRLOG("Unable to reallocate raid1 channel base_bdev_modes_read_bw\n");
|
||||
return false;
|
||||
}
|
||||
memset(tmp + raid_ch->num_channels * sizeof(*raid1_ch->base_bdev_read_bw), 0,
|
||||
sizeof(*raid1_ch->base_bdev_read_bw));
|
||||
raid1_ch->base_bdev_read_bw = tmp;
|
||||
free(r1info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static struct raid_bdev_module g_raid1_module = {
|
||||
.level = RAID1,
|
||||
.base_bdevs_min = 1,
|
||||
.base_bdevs_min = 2,
|
||||
.base_bdevs_constraint = {CONSTRAINT_MIN_BASE_BDEVS_OPERATIONAL, 1},
|
||||
.memory_domains_supported = true,
|
||||
.start = raid1_start,
|
||||
.stop = raid1_stop,
|
||||
.submit_rw_request = raid1_submit_rw_request,
|
||||
.get_io_channel = raid1_get_io_channel,
|
||||
.channel_grow_base_bdev = channel_grow_base_bdev,
|
||||
};
|
||||
RAID_MODULE_REGISTER(&g_raid1_module)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -401,7 +401,7 @@ def bdev_raid_get_bdevs(client, category):
|
||||
return client.call('bdev_raid_get_bdevs', params)
|
||||
|
||||
|
||||
def bdev_raid_create(client, name, raid_level, base_bdevs, strip_size=None, strip_size_kb=None, uuid=None, superblock=False):
|
||||
def bdev_raid_create(client, name, raid_level, base_bdevs, strip_size=None, strip_size_kb=None, uuid=None):
|
||||
"""Create raid bdev. Either strip size arg will work but one is required.
|
||||
|
||||
Args:
|
||||
@ -411,13 +411,11 @@ def bdev_raid_create(client, name, raid_level, base_bdevs, strip_size=None, stri
|
||||
raid_level: raid level of raid bdev, supported values 0
|
||||
base_bdevs: Space separated names of Nvme bdevs in double quotes, like "Nvme0n1 Nvme1n1 Nvme2n1"
|
||||
uuid: UUID for this raid bdev (optional)
|
||||
superblock: information about raid bdev will be stored in superblock on each base bdev,
|
||||
disabled by default due to backward compatibility
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
params = {'name': name, 'raid_level': raid_level, 'base_bdevs': base_bdevs, 'superblock': superblock}
|
||||
params = {'name': name, 'raid_level': raid_level, 'base_bdevs': base_bdevs}
|
||||
|
||||
if strip_size:
|
||||
params['strip_size'] = strip_size
|
||||
@ -444,34 +442,6 @@ def bdev_raid_delete(client, name):
|
||||
return client.call('bdev_raid_delete', params)
|
||||
|
||||
|
||||
def bdev_raid_remove_base_bdev(client, name):
|
||||
"""Remove base bdev from existing raid bdev
|
||||
|
||||
Args:
|
||||
name: base bdev name
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
params = {'name': name}
|
||||
return client.call('bdev_raid_remove_base_bdev', params)
|
||||
|
||||
|
||||
def bdev_raid_grow_base_bdev(client, raid_name, base_name):
|
||||
"""Add a base bdev to a raid bdev, growing the raid's size if needed
|
||||
|
||||
Args:
|
||||
raid_name: raid bdev name
|
||||
base_name: base bdev name
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
params = {'raid_name': raid_name, 'base_name': base_name}
|
||||
|
||||
return client.call('bdev_raid_grow_base_bdev', params)
|
||||
|
||||
|
||||
def bdev_aio_create(client, filename, name, block_size=None, readonly=False):
|
||||
"""Construct a Linux AIO block device.
|
||||
|
||||
@ -1327,13 +1297,12 @@ def bdev_iscsi_delete(client, name):
|
||||
return client.call('bdev_iscsi_delete', params)
|
||||
|
||||
|
||||
def bdev_passthru_create(client, base_bdev_name, name, uuid=None):
|
||||
def bdev_passthru_create(client, base_bdev_name, name):
|
||||
"""Construct a pass-through block device.
|
||||
|
||||
Args:
|
||||
base_bdev_name: name of the existing bdev
|
||||
name: name of block device
|
||||
uuid: UUID of block device (optional)
|
||||
|
||||
Returns:
|
||||
Name of created block device.
|
||||
@ -1342,8 +1311,6 @@ def bdev_passthru_create(client, base_bdev_name, name, uuid=None):
|
||||
'base_bdev_name': base_bdev_name,
|
||||
'name': name,
|
||||
}
|
||||
if uuid:
|
||||
params['uuid'] = uuid
|
||||
return client.call('bdev_passthru_create', params)
|
||||
|
||||
|
||||
|
@ -161,36 +161,6 @@ def bdev_lvol_rename(client, old_name, new_name):
|
||||
return client.call('bdev_lvol_rename', params)
|
||||
|
||||
|
||||
def bdev_lvol_set_xattr(client, name, xattr_name, xattr_value):
|
||||
"""Set extended attribute on a logical volume.
|
||||
|
||||
Args:
|
||||
name: name of logical volume
|
||||
xattr_name: name of extended attribute
|
||||
xattr_value: value of extended attribute
|
||||
"""
|
||||
params = {
|
||||
'name': name,
|
||||
'xattr_name': xattr_name,
|
||||
'xattr_value': xattr_value,
|
||||
}
|
||||
return client.call('bdev_lvol_set_xattr', params)
|
||||
|
||||
|
||||
def bdev_lvol_get_xattr(client, name, xattr_name):
|
||||
"""Get extended attribute on a logical volume.
|
||||
|
||||
Args:
|
||||
name: name of logical volume
|
||||
xattr_name: name of extended attribute
|
||||
"""
|
||||
params = {
|
||||
'name': name,
|
||||
'xattr_name': xattr_name,
|
||||
}
|
||||
return client.call('bdev_lvol_get_xattr', params)
|
||||
|
||||
|
||||
def bdev_lvol_resize(client, name, size_in_mib):
|
||||
"""Resize a logical volume.
|
||||
|
||||
@ -253,51 +223,6 @@ def bdev_lvol_decouple_parent(client, name):
|
||||
return client.call('bdev_lvol_decouple_parent', params)
|
||||
|
||||
|
||||
def bdev_lvol_shallow_copy(client, src_lvol_name, dst_bdev_name):
|
||||
"""Make a shallow copy of lvol over a given bdev
|
||||
|
||||
Args:
|
||||
src_lvol_name: name of lvol to create a copy from
|
||||
bdev_name: name of the bdev that acts as destination for the copy
|
||||
"""
|
||||
params = {
|
||||
'src_lvol_name': src_lvol_name,
|
||||
'dst_bdev_name': dst_bdev_name
|
||||
}
|
||||
return client.call('bdev_lvol_shallow_copy', params)
|
||||
|
||||
|
||||
def bdev_lvol_shallow_copy_status(client, src_lvol_name):
|
||||
"""Get shallow copy status
|
||||
|
||||
Args:
|
||||
src_lvol_name: name of source lvol
|
||||
"""
|
||||
params = {
|
||||
'src_lvol_name': src_lvol_name
|
||||
}
|
||||
return client.call('bdev_lvol_shallow_copy_status', params)
|
||||
|
||||
|
||||
def bdev_lvol_get_fragmap(client, name, offset=0, size=0):
|
||||
"""Get a fragmap for a specific segment of a logical volume using the provided offset and size
|
||||
|
||||
Args:
|
||||
name: lvol bdev name
|
||||
offset: offset in bytes of the specific segment of the logical volume
|
||||
size: size in bytes of the specific segment of the logical volume
|
||||
"""
|
||||
params = {
|
||||
'name': name,
|
||||
}
|
||||
if offset:
|
||||
params['offset'] = offset
|
||||
if size:
|
||||
params['size'] = size
|
||||
|
||||
return client.call('bdev_lvol_get_fragmap', params)
|
||||
|
||||
|
||||
def bdev_lvol_delete_lvstore(client, uuid=None, lvs_name=None):
|
||||
"""Destroy a logical volume store.
|
||||
|
||||
|
@ -1129,13 +1129,11 @@ if __name__ == "__main__":
|
||||
def bdev_passthru_create(args):
|
||||
print_json(rpc.bdev.bdev_passthru_create(args.client,
|
||||
base_bdev_name=args.base_bdev_name,
|
||||
name=args.name,
|
||||
uuid=args.uuid))
|
||||
name=args.name))
|
||||
|
||||
p = subparsers.add_parser('bdev_passthru_create', help='Add a pass through bdev on existing bdev')
|
||||
p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True)
|
||||
p.add_argument('-p', '--name', help="Name of the pass through bdev", required=True)
|
||||
p.add_argument('-u', '--uuid', help="UUID of the bdev")
|
||||
p.set_defaults(func=bdev_passthru_create)
|
||||
|
||||
def bdev_passthru_delete(args):
|
||||
@ -1999,28 +1997,6 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument('new_name', help='new lvol name')
|
||||
p.set_defaults(func=bdev_lvol_rename)
|
||||
|
||||
def bdev_lvol_set_xattr(args):
|
||||
rpc.lvol.bdev_lvol_set_xattr(args.client,
|
||||
name=args.name,
|
||||
xattr_name=args.xattr_name,
|
||||
xattr_value=args.xattr_value)
|
||||
|
||||
p = subparsers.add_parser('bdev_lvol_set_xattr', help='Set xattr for lvol bdev')
|
||||
p.add_argument('name', help='lvol bdev name')
|
||||
p.add_argument('xattr_name', help='xattr name')
|
||||
p.add_argument('xattr_value', help='xattr value')
|
||||
p.set_defaults(func=bdev_lvol_set_xattr)
|
||||
|
||||
def bdev_lvol_get_xattr(args):
|
||||
print_dict(rpc.lvol.bdev_lvol_get_xattr(args.client,
|
||||
name=args.name,
|
||||
xattr_name=args.xattr_name))
|
||||
|
||||
p = subparsers.add_parser('bdev_lvol_get_xattr', help='Get xattr for lvol bdev')
|
||||
p.add_argument('name', help='lvol bdev name')
|
||||
p.add_argument('xattr_name', help='xattr name')
|
||||
p.set_defaults(func=bdev_lvol_get_xattr)
|
||||
|
||||
def bdev_lvol_inflate(args):
|
||||
rpc.lvol.bdev_lvol_inflate(args.client,
|
||||
name=args.name)
|
||||
@ -2063,36 +2039,6 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument('name', help='lvol bdev name')
|
||||
p.set_defaults(func=bdev_lvol_delete)
|
||||
|
||||
def bdev_lvol_shallow_copy(args):
|
||||
rpc.lvol.bdev_lvol_shallow_copy(args.client,
|
||||
src_lvol_name=args.src_lvol_name,
|
||||
dst_bdev_name=args.dst_bdev_name)
|
||||
|
||||
p = subparsers.add_parser('bdev_lvol_shallow_copy', help="""Make a shallow copy of lvol over a given bdev.
|
||||
lvol must be read only""")
|
||||
p.add_argument('src_lvol_name', help='source lvol name')
|
||||
p.add_argument('dst_bdev_name', help='destination bdev name')
|
||||
p.set_defaults(func=bdev_lvol_shallow_copy)
|
||||
|
||||
def bdev_lvol_shallow_copy_status(args):
|
||||
print_json(rpc.lvol.bdev_lvol_shallow_copy_status(args.client,
|
||||
src_lvol_name=args.src_lvol_name))
|
||||
p = subparsers.add_parser('bdev_lvol_shallow_copy_status', help='Get shallow copy status')
|
||||
p.add_argument('src_lvol_name', help='source lvol name')
|
||||
p.set_defaults(func=bdev_lvol_shallow_copy_status)
|
||||
|
||||
def bdev_lvol_get_fragmap(args):
|
||||
print_json(rpc.lvol.bdev_lvol_get_fragmap(args.client,
|
||||
name=args.name,
|
||||
offset=args.offset,
|
||||
size=args.size))
|
||||
p = subparsers.add_parser('bdev_lvol_get_fragmap',
|
||||
help='Get a fragmap for a specific segment of a logical volume using the provided offset and size.')
|
||||
p.add_argument('name', help='lvol bdev name')
|
||||
p.add_argument('--offset', help='offset in bytes of the specific segment of the logical volume', type=int, required=False)
|
||||
p.add_argument('--size', help='size in bytes of the specific segment of the logical volume', type=int, required=False)
|
||||
p.set_defaults(func=bdev_lvol_get_fragmap)
|
||||
|
||||
def bdev_lvol_delete_lvstore(args):
|
||||
rpc.lvol.bdev_lvol_delete_lvstore(args.client,
|
||||
uuid=args.uuid,
|
||||
@ -2146,16 +2092,13 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
strip_size_kb=args.strip_size_kb,
|
||||
raid_level=args.raid_level,
|
||||
base_bdevs=base_bdevs,
|
||||
uuid=args.uuid,
|
||||
superblock=args.superblock)
|
||||
uuid=args.uuid)
|
||||
p = subparsers.add_parser('bdev_raid_create', help='Create new raid bdev')
|
||||
p.add_argument('-n', '--name', help='raid bdev name', required=True)
|
||||
p.add_argument('-z', '--strip-size-kb', help='strip size in KB', type=int)
|
||||
p.add_argument('-r', '--raid-level', help='raid level, raid0, raid1 and a special level concat are supported', required=True)
|
||||
p.add_argument('-b', '--base-bdevs', help='base bdevs name, whitespace separated list in quotes', required=True)
|
||||
p.add_argument('--uuid', help='UUID for this raid bdev', required=False)
|
||||
p.add_argument('-s', '--superblock', help='information about raid bdev will be stored in superblock on each base bdev, '
|
||||
'disabled by default due to backward compatibility', action='store_true')
|
||||
p.set_defaults(func=bdev_raid_create)
|
||||
|
||||
def bdev_raid_delete(args):
|
||||
@ -2165,23 +2108,6 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument('name', help='raid bdev name')
|
||||
p.set_defaults(func=bdev_raid_delete)
|
||||
|
||||
def bdev_raid_remove_base_bdev(args):
|
||||
rpc.bdev.bdev_raid_remove_base_bdev(args.client,
|
||||
name=args.name)
|
||||
p = subparsers.add_parser('bdev_raid_remove_base_bdev', help='Remove base bdev from existing raid bdev')
|
||||
p.add_argument('name', help='base bdev name')
|
||||
p.set_defaults(func=bdev_raid_remove_base_bdev)
|
||||
|
||||
def bdev_raid_grow_base_bdev(args):
|
||||
rpc.bdev.bdev_raid_grow_base_bdev(args.client,
|
||||
raid_name=args.raid_name,
|
||||
base_name=args.base_name)
|
||||
p = subparsers.add_parser('bdev_raid_grow_base_bdev', help="""Add a base bdev to a raid bdev,
|
||||
growing the raid\'s size if needed""")
|
||||
p.add_argument('raid_name', help='raid bdev name')
|
||||
p.add_argument('base_name', help='base bdev name')
|
||||
p.set_defaults(func=bdev_raid_grow_base_bdev)
|
||||
|
||||
# split
|
||||
def bdev_split_create(args):
|
||||
print_array(rpc.bdev.bdev_split_create(args.client,
|
||||
|
@ -118,13 +118,11 @@ function raid_function_test() {
|
||||
return 0
|
||||
}
|
||||
|
||||
function verify_raid_bdev_state() (
|
||||
set +x
|
||||
function verify_raid_bdev_state() {
|
||||
local raid_bdev_name=$1
|
||||
local expected_state=$2
|
||||
local raid_level=$3
|
||||
local strip_size=$4
|
||||
local num_base_bdevs_operational=$5
|
||||
local raid_bdev
|
||||
local raid_bdev_info
|
||||
local num_base_bdevs
|
||||
@ -161,49 +159,28 @@ function verify_raid_bdev_state() (
|
||||
return 1
|
||||
fi
|
||||
|
||||
num_base_bdevs=$(echo $raid_bdev_info | jq -r '[.base_bdevs_list[]] | length')
|
||||
num_base_bdevs=$(echo $raid_bdev_info | jq -r '.base_bdevs_list | length')
|
||||
tmp=$(echo $raid_bdev_info | jq -r '.num_base_bdevs')
|
||||
if [ "$num_base_bdevs" != "$tmp" ]; then
|
||||
echo "incorrect num_base_bdevs: $tmp, expected: $num_base_bdevs"
|
||||
return 1
|
||||
fi
|
||||
|
||||
num_base_bdevs_discovered=$(echo $raid_bdev_info | jq -r '[.base_bdevs_list[] | select(.is_configured)] | length')
|
||||
num_base_bdevs_discovered=$(echo $raid_bdev_info | jq -r '[.base_bdevs_list[] | strings] | length')
|
||||
tmp=$(echo $raid_bdev_info | jq -r '.num_base_bdevs_discovered')
|
||||
if [ "$num_base_bdevs_discovered" != "$tmp" ]; then
|
||||
echo "incorrect num_base_bdevs_discovered: $tmp, expected: $num_base_bdevs_discovered"
|
||||
return 1
|
||||
fi
|
||||
|
||||
tmp=$(echo $raid_bdev_info | jq -r '.num_base_bdevs_operational')
|
||||
if [ "$num_base_bdevs_operational" != "$tmp" ]; then
|
||||
echo "incorrect num_base_bdevs_operational $tmp, expected: $num_base_bdevs_operational"
|
||||
return 1
|
||||
fi
|
||||
)
|
||||
|
||||
function has_redundancy() {
|
||||
case $1 in
|
||||
"raid1" | "raid5f") return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
function raid_state_function_test() {
|
||||
local raid_level=$1
|
||||
local num_base_bdevs=$2
|
||||
local raid_bdev
|
||||
local base_bdevs=($(for ((i = 1; i <= num_base_bdevs; i++)); do echo BaseBdev$i; done))
|
||||
local base_bdev1="Non_Existed_Base_1"
|
||||
local base_bdev2="Non_Existed_Base_2"
|
||||
local raid_bdev_name="Existed_Raid"
|
||||
local strip_size
|
||||
local strip_size_create_arg
|
||||
|
||||
if [ $raid_level != "raid1" ]; then
|
||||
strip_size=64
|
||||
strip_size_create_arg="-z $strip_size"
|
||||
else
|
||||
strip_size=0
|
||||
fi
|
||||
local strip_size=64
|
||||
|
||||
$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 -L bdev_raid &
|
||||
raid_pid=$!
|
||||
@ -212,61 +189,56 @@ function raid_state_function_test() {
|
||||
|
||||
# Step1: create a RAID bdev with no base bdevs
|
||||
# Expect state: CONFIGURING
|
||||
$rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs[*]}" -n $raid_bdev_name
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $num_base_bdevs; then
|
||||
$rpc_py bdev_raid_create -z $strip_size -r $raid_level -b "$base_bdev1 $base_bdev2" -n $raid_bdev_name
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size; then
|
||||
return 1
|
||||
else
|
||||
# Test: Delete the RAID bdev successfully
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
fi
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
|
||||
# Step2: create one base bdev and add to the RAID bdev
|
||||
# Expect state: CONFIGURING
|
||||
$rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs[*]}" -n $raid_bdev_name
|
||||
$rpc_py bdev_malloc_create 32 512 -b ${base_bdevs[0]}
|
||||
waitforbdev ${base_bdevs[0]}
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $num_base_bdevs; then
|
||||
$rpc_py bdev_raid_create -z $strip_size -r $raid_level -b "$base_bdev1 $base_bdev2" -n $raid_bdev_name
|
||||
$rpc_py bdev_malloc_create 32 512 -b $base_bdev1
|
||||
waitforbdev $base_bdev1
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size; then
|
||||
$rpc_py bdev_malloc_delete $base_bdev1
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
return 1
|
||||
else
|
||||
# Test: Delete the RAID bdev successfully
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
fi
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
|
||||
# Step3: create remaining base bdevs and add to the RAID bdev
|
||||
# Step3: create another base bdev and add to the RAID bdev
|
||||
# Expect state: ONLINE
|
||||
$rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs[*]}" -n $raid_bdev_name
|
||||
for ((i = 1; i < num_base_bdevs; i++)); do
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $num_base_bdevs; then
|
||||
return 1
|
||||
fi
|
||||
$rpc_py bdev_malloc_create 32 512 -b ${base_bdevs[$i]}
|
||||
waitforbdev ${base_bdevs[$i]}
|
||||
done
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "online" $raid_level $strip_size $num_base_bdevs; then
|
||||
$rpc_py bdev_raid_create -z $strip_size -r $raid_level -b "$base_bdev1 $base_bdev2" -n $raid_bdev_name
|
||||
$rpc_py bdev_malloc_create 32 512 -b $base_bdev2
|
||||
waitforbdev $base_bdev2
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "online" $raid_level $strip_size; then
|
||||
$rpc_py bdev_malloc_delete $base_bdev1
|
||||
$rpc_py bdev_malloc_delete $base_bdev2
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Step4: delete one base bdev from the RAID bdev
|
||||
$rpc_py bdev_malloc_delete ${base_bdevs[0]}
|
||||
local expected_state
|
||||
if ! has_redundancy $raid_level; then
|
||||
expected_state="offline"
|
||||
else
|
||||
expected_state="online"
|
||||
fi
|
||||
if ! verify_raid_bdev_state $raid_bdev_name $expected_state $raid_level $strip_size $((num_base_bdevs - 1)); then
|
||||
# Expect state: OFFLINE
|
||||
$rpc_py bdev_malloc_delete $base_bdev2
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "offline" $raid_level $strip_size; then
|
||||
$rpc_py bdev_malloc_delete $base_bdev1
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Step5: delete remaining base bdevs from the RAID bdev
|
||||
# Step5: delete last base bdev from the RAID bdev
|
||||
# Expect state: removed from system
|
||||
for ((i = 1; i < num_base_bdevs; i++)); do
|
||||
raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[0]["name"]')
|
||||
if [ "$raid_bdev" != $raid_bdev_name ]; then
|
||||
echo "$raid_bdev_name removed before all base bdevs were deleted"
|
||||
return 1
|
||||
fi
|
||||
$rpc_py bdev_malloc_delete ${base_bdevs[$i]}
|
||||
done
|
||||
$rpc_py bdev_malloc_delete $base_bdev1
|
||||
raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[0]["name"] | select(.)')
|
||||
if [ -n "$raid_bdev" ]; then
|
||||
echo "$raid_bdev_name is not removed"
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
return 1
|
||||
fi
|
||||
|
||||
@ -320,220 +292,12 @@ function raid0_resize_test() {
|
||||
return 0
|
||||
}
|
||||
|
||||
function raid_superblock_test() {
|
||||
local raid_level=$1
|
||||
local num_base_bdevs=$2
|
||||
local base_bdevs_malloc=()
|
||||
local base_bdevs_pt=()
|
||||
local base_bdevs_pt_uuid=()
|
||||
local raid_bdev_name="raid_bdev1"
|
||||
local raid_bdev_uuid
|
||||
local raid_bdev
|
||||
local strip_size
|
||||
local strip_size_create_arg
|
||||
|
||||
if [ $raid_level != "raid1" ]; then
|
||||
strip_size=64
|
||||
strip_size_create_arg="-z $strip_size"
|
||||
else
|
||||
strip_size=0
|
||||
fi
|
||||
|
||||
$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 -L bdev_raid &
|
||||
raid_pid=$!
|
||||
echo "Process raid pid: $raid_pid"
|
||||
waitforlisten $raid_pid $rpc_server
|
||||
|
||||
# Create base bdevs
|
||||
for ((i = 1; i <= num_base_bdevs; i++)); do
|
||||
local bdev_malloc="malloc$i"
|
||||
local bdev_pt="pt$i"
|
||||
local bdev_pt_uuid="00000000-0000-0000-0000-00000000000$i"
|
||||
|
||||
base_bdevs_malloc+=($bdev_malloc)
|
||||
base_bdevs_pt+=($bdev_pt)
|
||||
base_bdevs_pt_uuid+=($bdev_pt_uuid)
|
||||
|
||||
$rpc_py bdev_malloc_create 32 512 -b $bdev_malloc
|
||||
$rpc_py bdev_passthru_create -b $bdev_malloc -p $bdev_pt -u $bdev_pt_uuid
|
||||
done
|
||||
|
||||
# Create RAID bdev with superblock
|
||||
$rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs_pt[*]}" -n $raid_bdev_name -s
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "online" $raid_level $strip_size $num_base_bdevs; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get RAID bdev's UUID
|
||||
raid_bdev_uuid=$($rpc_py bdev_get_bdevs -b $raid_bdev_name | jq -r '.[] | .uuid | select(.)')
|
||||
if [ -z "$raid_bdev_uuid" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Stop the RAID bdev
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[]')
|
||||
if [ -n "$raid_bdev" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Delete the passthru bdevs
|
||||
for i in "${base_bdevs_pt[@]}"; do
|
||||
$rpc_py bdev_passthru_delete $i
|
||||
done
|
||||
if [ "$($rpc_py bdev_get_bdevs | jq -r '[.[] | select(.product_name == "passthru")] | any')" == "true" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Try to create new RAID bdev from malloc bdevs
|
||||
# Should not reach online state due to superblock still present on base bdevs
|
||||
$rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs_malloc[*]}" -n $raid_bdev_name
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $num_base_bdevs; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Stop the RAID bdev
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[]')
|
||||
if [ -n "$raid_bdev" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Re-add first base bdev
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[0]} -p ${base_bdevs_pt[0]} -u ${base_bdevs_pt_uuid[0]}
|
||||
|
||||
# Check if the RAID bdev was assembled from superblock
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $num_base_bdevs; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Re-add remaining base bdevs
|
||||
for ((i = 1; i < num_base_bdevs; i++)); do
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[$i]} -p ${base_bdevs_pt[$i]} -u ${base_bdevs_pt_uuid[$i]}
|
||||
done
|
||||
|
||||
# Check if the RAID bdev is in online state
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "online" $raid_level $strip_size $num_base_bdevs; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if the RAID bdev has the same UUID as when first created
|
||||
if [ "$($rpc_py bdev_get_bdevs -b $raid_bdev_name | jq -r '.[] | .uuid')" != "$raid_bdev_uuid" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if has_redundancy $raid_level; then
|
||||
# Delete one base bdev
|
||||
$rpc_py bdev_passthru_delete ${base_bdevs_pt[0]}
|
||||
|
||||
# Check if the RAID bdev is in online state (degraded)
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "online" $raid_level $strip_size $((num_base_bdevs - 1)); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Stop the RAID bdev
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[]')
|
||||
if [ -n "$raid_bdev" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Delete remaining base bdevs
|
||||
for ((i = 1; i < num_base_bdevs; i++)); do
|
||||
$rpc_py bdev_passthru_delete ${base_bdevs_pt[$i]}
|
||||
done
|
||||
|
||||
# Re-add base bdevs from the second up to (not including) the last one
|
||||
for ((i = 1; i < num_base_bdevs - 1; i++)); do
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[$i]} -p ${base_bdevs_pt[$i]} -u ${base_bdevs_pt_uuid[$i]}
|
||||
|
||||
# Check if the RAID bdev is in configuring state
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $((num_base_bdevs - 1)); then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Re-add the last base bdev
|
||||
i=$((num_base_bdevs - 1))
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[$i]} -p ${base_bdevs_pt[$i]} -u ${base_bdevs_pt_uuid[$i]}
|
||||
|
||||
# Check if the RAID bdev is in online state (degraded)
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "online" $raid_level $strip_size $((num_base_bdevs - 1)); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ $num_base_bdevs -gt 2 ]; then
|
||||
# Stop the RAID bdev
|
||||
$rpc_py bdev_raid_delete $raid_bdev_name
|
||||
raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[]')
|
||||
if [ -n "$raid_bdev" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Delete remaining base bdevs
|
||||
for ((i = 1; i < num_base_bdevs; i++)); do
|
||||
$rpc_py bdev_passthru_delete ${base_bdevs_pt[$i]}
|
||||
done
|
||||
|
||||
# Re-add first base bdev
|
||||
# This is the "failed" device and contains the "old" version of the superblock
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[0]} -p ${base_bdevs_pt[0]} -u ${base_bdevs_pt_uuid[0]}
|
||||
|
||||
# Check if the RAID bdev is in configuring state
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $num_base_bdevs; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Re-add the last base bdev
|
||||
i=$((num_base_bdevs - 1))
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[$i]} -p ${base_bdevs_pt[$i]} -u ${base_bdevs_pt_uuid[$i]}
|
||||
|
||||
# Check if the RAID bdev is in configuring state
|
||||
# This should use the newer superblock version and have n-1 online base bdevs
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $((num_base_bdevs - 1)); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Re-add remaining base bdevs
|
||||
for ((i = 1; i < num_base_bdevs - 1; i++)); do
|
||||
$rpc_py bdev_passthru_create -b ${base_bdevs_malloc[$i]} -p ${base_bdevs_pt[$i]} -u ${base_bdevs_pt_uuid[$i]}
|
||||
done
|
||||
|
||||
# Check if the RAID bdev is in online state (degraded)
|
||||
if ! verify_raid_bdev_state $raid_bdev_name "online" $raid_level $strip_size $((num_base_bdevs - 1)); then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if the RAID bdev has the same UUID as when first created
|
||||
if [ "$($rpc_py bdev_get_bdevs -b $raid_bdev_name | jq -r '.[] | .uuid')" != "$raid_bdev_uuid" ]; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
killprocess $raid_pid
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
trap 'on_error_exit;' ERR
|
||||
|
||||
raid_function_test raid0
|
||||
raid_function_test concat
|
||||
raid_state_function_test raid0
|
||||
raid_state_function_test concat
|
||||
raid0_resize_test
|
||||
|
||||
for n in {2..4}; do
|
||||
for level in raid0 concat raid1; do
|
||||
raid_state_function_test $level $n
|
||||
raid_superblock_test $level $n
|
||||
done
|
||||
done
|
||||
|
||||
if [ "$CONFIG_RAID5F" == y ]; then
|
||||
for n in {3..4}; do
|
||||
raid_state_function_test raid5f $n
|
||||
raid_superblock_test raid5f $n
|
||||
done
|
||||
fi
|
||||
|
||||
rm -f $tmp_file
|
||||
|
@ -55,8 +55,6 @@ function start_spdk_tgt() {
|
||||
|
||||
function setup_bdev_conf() {
|
||||
"$rpc_py" <<- RPC
|
||||
iobuf_set_options --small-pool-count 10000 --large-pool-count 1100
|
||||
framework_start_init
|
||||
bdev_split_create Malloc1 2
|
||||
bdev_split_create -s 4 Malloc2 8
|
||||
bdev_malloc_create -b Malloc0 32 512
|
||||
@ -67,12 +65,9 @@ function setup_bdev_conf() {
|
||||
bdev_malloc_create -b Malloc5 32 512
|
||||
bdev_malloc_create -b Malloc6 32 512
|
||||
bdev_malloc_create -b Malloc7 32 512
|
||||
bdev_malloc_create -b Malloc8 32 512
|
||||
bdev_malloc_create -b Malloc9 32 512
|
||||
bdev_passthru_create -p TestPT -b Malloc3
|
||||
bdev_raid_create -n raid0 -z 64 -r 0 -b "Malloc4 Malloc5"
|
||||
bdev_raid_create -n concat0 -z 64 -r concat -b "Malloc6 Malloc7"
|
||||
bdev_raid_create -n raid1 -r 1 -b "Malloc8 Malloc9"
|
||||
bdev_set_qos_limit --rw_mbytes_per_sec 100 Malloc3
|
||||
bdev_set_qos_limit --rw_ios_per_sec 20000 Malloc0
|
||||
RPC
|
||||
@ -673,7 +668,7 @@ if [ -n "$crypto_device" ] && [ -n "$wcs_file" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ $test_type == bdev || $test_type == crypto_* ]]; then
|
||||
if [[ $test_type == crypto_* ]]; then
|
||||
wait_for_rpc="--wait-for-rpc"
|
||||
fi
|
||||
start_spdk_tgt
|
||||
@ -726,8 +721,7 @@ esac
|
||||
cat <<- CONF > "$conf_file"
|
||||
{"subsystems":[
|
||||
$("$rpc_py" save_subsystem_config -n accel),
|
||||
$("$rpc_py" save_subsystem_config -n bdev),
|
||||
$("$rpc_py" save_subsystem_config -n iobuf)
|
||||
$("$rpc_py" save_subsystem_config -n bdev)
|
||||
]}
|
||||
CONF
|
||||
|
||||
|
@ -1,71 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2023 SUSE LLC.
|
||||
# All rights reserved.
|
||||
#
|
||||
testdir=$(readlink -f $(dirname $0))
|
||||
rootdir=$(readlink -f $testdir/../..)
|
||||
source $rootdir/test/common/autotest_common.sh
|
||||
source $rootdir/test/lvol/common.sh
|
||||
source $rootdir/test/bdev/nbd_common.sh
|
||||
|
||||
function test_shallow_copy_compare() {
|
||||
# Create lvs
|
||||
bs_malloc_name=$(rpc_cmd bdev_malloc_create 20 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$bs_malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 4 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * 4))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
# Fill second and fourth cluster of lvol
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" count=1 seek=1
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" count=1 seek=3
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
|
||||
# Create snapshots of lvol bdev
|
||||
snapshot_uuid=$(rpc_cmd bdev_lvol_snapshot lvs_test/lvol_test lvol_snapshot)
|
||||
|
||||
# Fill first and third cluster of lvol
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" count=1
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" count=1 seek=2
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
|
||||
# Set lvol as read only to perform the copy
|
||||
rpc_cmd bdev_lvol_set_read_only "$lvol_uuid"
|
||||
|
||||
# Create external bdev to make a shallow copy of lvol on
|
||||
ext_malloc_name=$(rpc_cmd bdev_malloc_create "$lvol_size" $MALLOC_BS)
|
||||
|
||||
# Make a shallow copy of lvol over external bdev
|
||||
rpc_cmd bdev_lvol_shallow_copy "$lvol_uuid" "$ext_malloc_name"
|
||||
|
||||
# Create nbd devices of lvol and external bdev for comparison
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$ext_malloc_name" /dev/nbd1
|
||||
|
||||
# Compare lvol and external bdev in first and third cluster
|
||||
cmp -n "$LVS_DEFAULT_CLUSTER_SIZE" /dev/nbd0 /dev/nbd1
|
||||
cmp -n "$LVS_DEFAULT_CLUSTER_SIZE" /dev/nbd0 /dev/nbd1 "$((LVS_DEFAULT_CLUSTER_SIZE * 2))" "$((LVS_DEFAULT_CLUSTER_SIZE * 2))"
|
||||
|
||||
# Check that second and fourth cluster of external bdev are zero filled
|
||||
cmp -n "$LVS_DEFAULT_CLUSTER_SIZE" /dev/nbd1 /dev/zero "$LVS_DEFAULT_CLUSTER_SIZE"
|
||||
cmp -n "$LVS_DEFAULT_CLUSTER_SIZE" /dev/nbd1 /dev/zero "$((LVS_DEFAULT_CLUSTER_SIZE * 3))"
|
||||
|
||||
# Stop nbd devices
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd1
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
}
|
||||
|
||||
$SPDK_BIN_DIR/spdk_tgt &
|
||||
spdk_pid=$!
|
||||
trap 'killprocess "$spdk_pid"; exit 1' SIGINT SIGTERM EXIT
|
||||
waitforlisten $spdk_pid
|
||||
modprobe nbd
|
||||
|
||||
run_test "test_shallow_copy_compare" test_shallow_copy_compare
|
||||
|
||||
trap - SIGINT SIGTERM EXIT
|
||||
killprocess $spdk_pid
|
@ -1,214 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2023 SUSE LLC.
|
||||
# All rights reserved.
|
||||
#
|
||||
testdir=$(readlink -f $(dirname $0))
|
||||
rootdir=$(readlink -f $testdir/../..)
|
||||
source $rootdir/test/common/autotest_common.sh
|
||||
source $rootdir/test/lvol/common.sh
|
||||
source $rootdir/test/bdev/nbd_common.sh
|
||||
|
||||
NUM_CLUSTERS=10
|
||||
LVS_DEFAULT_CLUSTER_SIZE_BTYE=$((LVS_DEFAULT_CLUSTER_SIZE_MB * 1024 * 1024))
|
||||
|
||||
function verify() {
|
||||
local fragmap="$1"
|
||||
local expected_cluster_size="$2"
|
||||
local expected_num_clusters="$3"
|
||||
local expected_num_allocated_clusters="$4"
|
||||
local expected_fragmap="$5"
|
||||
|
||||
[ "$(jq '.cluster_size' <<< "$fragmap")" == "$expected_cluster_size" ]
|
||||
[ "$(jq '.num_clusters' <<< "$fragmap")" == "$expected_num_clusters" ]
|
||||
[ "$(jq '.num_allocated_clusters' <<< "$fragmap")" == "$expected_num_allocated_clusters" ]
|
||||
[ "$(jq -r '.fragmap' <<< "$fragmap")" == "$expected_fragmap" ]
|
||||
}
|
||||
|
||||
function test_fragmap_empty_lvol() {
|
||||
# Create lvs
|
||||
malloc_name=$(rpc_cmd bdev_malloc_create 80 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 10 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * "$NUM_CLUSTERS"))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
|
||||
# Expected map: 00000000 00000000
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "$NUM_CLUSTERS" 0 "AAA="
|
||||
|
||||
# Stop nbd device
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
|
||||
rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid"
|
||||
rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false
|
||||
rpc_cmd bdev_malloc_delete "$malloc_name"
|
||||
check_leftover_devices
|
||||
}
|
||||
|
||||
function test_fragmap_data_hole() {
|
||||
# Create lvs
|
||||
malloc_name=$(rpc_cmd bdev_malloc_create 80 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 10 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * "$NUM_CLUSTERS"))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
|
||||
# Expected map: 00000001 00000000 (1st cluster is wriiten)
|
||||
|
||||
# Read entire fragmap
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs=4096 count=1
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "$NUM_CLUSTERS" "1" "AQA="
|
||||
|
||||
# Read fragmap [0, 5) clusters
|
||||
size=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset 0 --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "1" "AQ=="
|
||||
|
||||
# Read fragmap [5, 10) clusters
|
||||
offset=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset $offset --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "0" "AA=="
|
||||
|
||||
# Stop nbd device
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
|
||||
rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid"
|
||||
rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false
|
||||
rpc_cmd bdev_malloc_delete "$malloc_name"
|
||||
check_leftover_devices
|
||||
}
|
||||
|
||||
function test_fragmap_hole_data() {
|
||||
# Create lvs
|
||||
malloc_name=$(rpc_cmd bdev_malloc_create 80 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 10 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * "$NUM_CLUSTERS"))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
|
||||
# Expected map: 00000000 00000010 (10th cluster is wriiten)
|
||||
|
||||
# Read entire fragmap
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs=4096 count=1 seek=9216
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "$NUM_CLUSTERS" "1" "AAI="
|
||||
|
||||
# Read fragmap [0, 5) clusters
|
||||
size=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset 0 --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "0" "AA=="
|
||||
|
||||
# Read fragmap [5, 10) clusters
|
||||
offset=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset $offset --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "1" "EA=="
|
||||
|
||||
# Stop nbd device
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
|
||||
rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid"
|
||||
rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false
|
||||
rpc_cmd bdev_malloc_delete "$malloc_name"
|
||||
check_leftover_devices
|
||||
}
|
||||
|
||||
function test_fragmap_hole_data_hole() {
|
||||
# Create lvs
|
||||
malloc_name=$(rpc_cmd bdev_malloc_create 80 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 10 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * "$NUM_CLUSTERS"))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
|
||||
# Expected map: 01100000 00000000
|
||||
|
||||
# Read entire fragmap
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs=4096 count=2048 seek=5120
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "$NUM_CLUSTERS" "2" "YAA="
|
||||
|
||||
# Read fragmap [0, 5) clusters
|
||||
size=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset 0 --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "0" "AA=="
|
||||
|
||||
# Read fragmap [5, 10) clusters
|
||||
offset=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset $offset --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "2" "Aw=="
|
||||
|
||||
# Stop nbd device
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
|
||||
rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid"
|
||||
rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false
|
||||
rpc_cmd bdev_malloc_delete "$malloc_name"
|
||||
check_leftover_devices
|
||||
}
|
||||
|
||||
function test_fragmap_data_hole_data() {
|
||||
# Create lvs
|
||||
malloc_name=$(rpc_cmd bdev_malloc_create 80 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 10 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * "$NUM_CLUSTERS"))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0
|
||||
|
||||
# Expected map: 10000111 00000011
|
||||
|
||||
# Read entire fragmap
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs=4096 count=3072 seek=0
|
||||
dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs=4096 count=3072 seek=7168
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "$NUM_CLUSTERS" "6" "hwM="
|
||||
|
||||
# Read fragmap [0, 5) clusters
|
||||
size=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset 0 --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "3" "Bw=="
|
||||
|
||||
# Read fragmap [5, 10) clusters
|
||||
offset=$((LVS_DEFAULT_CLUSTER_SIZE_BTYE * 5))
|
||||
fragmap=$(rpc_cmd bdev_lvol_get_fragmap --offset $offset --size $size $lvol_uuid)
|
||||
verify "$fragmap" "$LVS_DEFAULT_CLUSTER_SIZE_BTYE" "5" "3" "HA=="
|
||||
|
||||
# Stop nbd device
|
||||
nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0
|
||||
|
||||
rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid"
|
||||
rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false
|
||||
rpc_cmd bdev_malloc_delete "$malloc_name"
|
||||
check_leftover_devices
|
||||
}
|
||||
|
||||
$SPDK_BIN_DIR/spdk_tgt &
|
||||
spdk_pid=$!
|
||||
trap 'killprocess "$spdk_pid"; exit 1' SIGINT SIGTERM EXIT
|
||||
waitforlisten $spdk_pid
|
||||
modprobe nbd
|
||||
|
||||
run_test "test_fragmap_empty_lvol" test_fragmap_empty_lvol
|
||||
run_test "test_fragmap_data_hole" test_fragmap_data_hole
|
||||
run_test "test_fragmap_hole_data" test_fragmap_hole_data
|
||||
run_test "test_fragmap_hole_data_hole" test_fragmap_hole_data_hole
|
||||
run_test "test_fragmap_data_hole_data" test_fragmap_data_hole_data
|
||||
|
||||
trap - SIGINT SIGTERM EXIT
|
||||
killprocess $spdk_pid
|
@ -20,9 +20,6 @@ run_test "lvol_rename" $rootdir/test/lvol/rename.sh
|
||||
run_test "lvol_provisioning" $rootdir/test/lvol/thin_provisioning.sh
|
||||
run_test "lvol_esnap" $rootdir/test/lvol/esnap/esnap
|
||||
run_test "lvol_external_snapshot" $rootdir/test/lvol/external_snapshot.sh
|
||||
run_test "lvol_external_copy" $rootdir/test/lvol/external_copy.sh
|
||||
run_test "lvol_fragmap" $rootdir/test/lvol/fragmap.sh
|
||||
run_test "lvol_xattr" $rootdir/test/lvol/xattr.sh
|
||||
timing_exit basic
|
||||
|
||||
timing_exit lvol
|
||||
|
@ -1,86 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2023 SUSE LLC.
|
||||
# All rights reserved.
|
||||
#
|
||||
testdir=$(readlink -f $(dirname $0))
|
||||
rootdir=$(readlink -f $testdir/../..)
|
||||
source $rootdir/test/common/autotest_common.sh
|
||||
source $rootdir/test/lvol/common.sh
|
||||
|
||||
function is_rfc3339_formatted() {
|
||||
# Define the RFC3339 regex pattern
|
||||
rfc3339_pattern="^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
|
||||
|
||||
# Check if the input string matches the pattern
|
||||
if [[ $1 =~ $rfc3339_pattern ]]; then
|
||||
echo "The time string '$1' is in RFC3339 format."
|
||||
return 0 # Success
|
||||
else
|
||||
echo "The time string '$1' is not in RFC3339 format."
|
||||
return 1 # Failure
|
||||
fi
|
||||
}
|
||||
|
||||
function test_set_xattr() {
|
||||
# Create lvs
|
||||
malloc_name=$(rpc_cmd bdev_malloc_create 20 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 4 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * 4))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
rpc_cmd bdev_lvol_set_xattr "$lvol_uuid" "foo" "bar"
|
||||
value=$(rpc_cmd bdev_lvol_get_xattr "$lvol_uuid" "foo")
|
||||
[ "\"bar\"" = "$value" ]
|
||||
|
||||
# Snapshot is read-only, so setting xattr should fail
|
||||
snapshot_uuid=$(rpc_cmd bdev_lvol_snapshot lvs_test/lvol_test lvol_snapshot)
|
||||
NOT rpc_cmd bdev_lvol_set_xattr "$snapshot_uuid" "foo" "bar"
|
||||
|
||||
rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid"
|
||||
rpc_cmd bdev_malloc_delete "$malloc_name"
|
||||
check_leftover_devices
|
||||
}
|
||||
|
||||
function test_creation_time_xattr() {
|
||||
# Create lvs
|
||||
malloc_name=$(rpc_cmd bdev_malloc_create 20 $MALLOC_BS)
|
||||
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test)
|
||||
|
||||
# Create lvol with 4 cluster
|
||||
lvol_size=$((LVS_DEFAULT_CLUSTER_SIZE_MB * 4))
|
||||
lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size" -t)
|
||||
|
||||
value=$(rpc_cmd bdev_lvol_get_xattr "$lvol_uuid" "creation_time")
|
||||
value="${value//\"/}"
|
||||
is_rfc3339_formatted ${value}
|
||||
|
||||
# Create snapshots of lvol bdev
|
||||
snapshot_uuid=$(rpc_cmd bdev_lvol_snapshot lvs_test/lvol_test lvol_snapshot)
|
||||
value=$(rpc_cmd bdev_lvol_get_xattr "$snapshot_uuid" "creation_time")
|
||||
value="${value//\"/}"
|
||||
is_rfc3339_formatted ${value}
|
||||
|
||||
clone_uuid=$(rpc_cmd bdev_lvol_clone "$snapshot_uuid" lvol_clone)
|
||||
value=$(rpc_cmd bdev_lvol_get_xattr "$snapshot_uuid" "creation_time")
|
||||
value="${value//\"/}"
|
||||
is_rfc3339_formatted ${value}
|
||||
|
||||
rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid"
|
||||
rpc_cmd bdev_malloc_delete "$malloc_name"
|
||||
check_leftover_devices
|
||||
}
|
||||
|
||||
$SPDK_BIN_DIR/spdk_tgt &
|
||||
spdk_pid=$!
|
||||
trap 'killprocess "$spdk_pid"; exit 1' SIGINT SIGTERM EXIT
|
||||
waitforlisten $spdk_pid
|
||||
modprobe nbd
|
||||
|
||||
run_test "test_set_xattr" test_set_xattr
|
||||
run_test "test_creation_time_xattr" test_creation_time_xattr
|
||||
|
||||
trap - SIGINT SIGTERM EXIT
|
||||
killprocess $spdk_pid
|
@ -5943,7 +5943,7 @@ bdev_register_uuid_alias(void)
|
||||
bdev = allocate_bdev("bdev0");
|
||||
|
||||
/* Make sure an UUID was generated */
|
||||
CU_ASSERT_FALSE(spdk_uuid_is_null(&bdev->uuid));
|
||||
CU_ASSERT_FALSE(spdk_mem_all_zero(&bdev->uuid, sizeof(bdev->uuid)));
|
||||
|
||||
/* Check that an UUID alias was registered */
|
||||
spdk_uuid_fmt_lower(uuid, sizeof(uuid), &bdev->uuid);
|
||||
|
@ -6,7 +6,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = bdev_raid.c bdev_raid_sb.c concat.c raid1.c
|
||||
DIRS-y = bdev_raid.c concat.c raid1.c
|
||||
|
||||
DIRS-$(CONFIG_RAID5F) += raid5f.c
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "bdev/raid/bdev_raid.c"
|
||||
#include "bdev/raid/bdev_raid_rpc.c"
|
||||
#include "bdev/raid/raid0.c"
|
||||
#include "bdev/raid/raid1.c"
|
||||
#include "common/lib/ut_multithread.c"
|
||||
|
||||
#define MAX_BASE_DRIVES 32
|
||||
@ -74,9 +73,6 @@ struct raid_io_ranges g_io_ranges[MAX_TEST_IO_RANGE];
|
||||
uint32_t g_io_range_idx;
|
||||
uint64_t g_lba_offset;
|
||||
struct spdk_io_channel g_io_channel;
|
||||
bool g_bdev_io_defer_completion;
|
||||
TAILQ_HEAD(, spdk_bdev_io) g_deferred_ios = TAILQ_HEAD_INITIALIZER(g_deferred_ios);
|
||||
struct spdk_io_channel *g_per_thread_base_bdev_channels;
|
||||
|
||||
DEFINE_STUB_V(spdk_bdev_module_examine_done, (struct spdk_bdev_module *module));
|
||||
DEFINE_STUB_V(spdk_bdev_module_list_add, (struct spdk_bdev_module *bdev_module));
|
||||
@ -101,7 +97,6 @@ DEFINE_STUB(spdk_json_decode_uint32, int, (const struct spdk_json_val *val, void
|
||||
DEFINE_STUB(spdk_json_decode_array, int, (const struct spdk_json_val *values,
|
||||
spdk_json_decode_fn decode_func,
|
||||
void *out, size_t max_size, size_t *out_size, size_t stride), 0);
|
||||
DEFINE_STUB(spdk_json_decode_bool, int, (const struct spdk_json_val *val, void *out), 0);
|
||||
DEFINE_STUB(spdk_json_write_name, int, (struct spdk_json_write_ctx *w, const char *name), 0);
|
||||
DEFINE_STUB(spdk_json_write_object_begin, int, (struct spdk_json_write_ctx *w), 0);
|
||||
DEFINE_STUB(spdk_json_write_named_object_begin, int, (struct spdk_json_write_ctx *w,
|
||||
@ -114,8 +109,6 @@ DEFINE_STUB(spdk_json_write_named_array_begin, int, (struct spdk_json_write_ctx
|
||||
const char *name), 0);
|
||||
DEFINE_STUB(spdk_json_write_bool, int, (struct spdk_json_write_ctx *w, bool val), 0);
|
||||
DEFINE_STUB(spdk_json_write_null, int, (struct spdk_json_write_ctx *w), 0);
|
||||
DEFINE_STUB(spdk_json_write_named_uint64, int, (struct spdk_json_write_ctx *w, const char *name,
|
||||
uint64_t val), 0);
|
||||
DEFINE_STUB(spdk_strerror, const char *, (int errnum), NULL);
|
||||
DEFINE_STUB(spdk_bdev_queue_io_wait, int, (struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
||||
struct spdk_bdev_io_wait_entry *entry), 0);
|
||||
@ -128,52 +121,13 @@ DEFINE_STUB(spdk_bdev_get_dif_type, enum spdk_dif_type, (const struct spdk_bdev
|
||||
SPDK_DIF_DISABLE);
|
||||
DEFINE_STUB(spdk_bdev_is_dif_head_of_md, bool, (const struct spdk_bdev *bdev), false);
|
||||
DEFINE_STUB(spdk_bdev_notify_blockcnt_change, int, (struct spdk_bdev *bdev, uint64_t size), 0);
|
||||
DEFINE_STUB(spdk_bdev_first, struct spdk_bdev *, (void), NULL);
|
||||
DEFINE_STUB(spdk_bdev_next, struct spdk_bdev *, (struct spdk_bdev *prev), NULL);
|
||||
DEFINE_STUB_V(raid_bdev_sb_update_crc, (struct raid_bdev_superblock *sb));
|
||||
|
||||
int
|
||||
raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
raid_bdev_load_sb_cb cb, void *cb_ctx)
|
||||
{
|
||||
if (cb) {
|
||||
cb(NULL, -EINVAL, cb_ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
raid_bdev_save_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
const struct raid_bdev_superblock *sb, raid_bdev_save_sb_cb cb, void *cb_ctx)
|
||||
{
|
||||
if (cb) {
|
||||
cb(0, cb_ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct spdk_uuid *
|
||||
spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
|
||||
{
|
||||
return &bdev->uuid;
|
||||
}
|
||||
|
||||
struct spdk_io_channel *
|
||||
spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc)
|
||||
{
|
||||
struct spdk_io_channel *ch;
|
||||
g_io_channel.thread = spdk_get_thread();
|
||||
|
||||
if (g_per_thread_base_bdev_channels) {
|
||||
ch = &g_per_thread_base_bdev_channels[g_ut_thread_id];
|
||||
} else {
|
||||
ch = &g_io_channel;
|
||||
}
|
||||
|
||||
ch->thread = spdk_get_thread();
|
||||
|
||||
return ch;
|
||||
return &g_io_channel;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -226,8 +180,6 @@ set_globals(void)
|
||||
g_json_decode_obj_err = 0;
|
||||
g_json_decode_obj_create = 0;
|
||||
g_lba_offset = 0;
|
||||
g_bdev_io_defer_completion = false;
|
||||
g_per_thread_base_bdev_channels = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -243,8 +195,6 @@ base_bdevs_cleanup(void)
|
||||
free(bdev);
|
||||
}
|
||||
}
|
||||
|
||||
free(g_per_thread_base_bdev_channels);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -257,7 +207,7 @@ check_and_remove_raid_bdev(struct raid_bdev *raid_bdev)
|
||||
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
||||
if (base_info->bdev) {
|
||||
raid_bdev_free_base_bdev_resource(base_info);
|
||||
raid_bdev_free_base_bdev_resource(raid_bdev, base_info);
|
||||
}
|
||||
}
|
||||
assert(raid_bdev->num_base_bdevs_discovered == 0);
|
||||
@ -274,7 +224,6 @@ reset_globals(void)
|
||||
}
|
||||
g_rpc_req = NULL;
|
||||
g_rpc_req_size = 0;
|
||||
g_per_thread_base_bdev_channels = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@ -307,29 +256,6 @@ set_io_output(struct io_output *output,
|
||||
output->iotype = iotype;
|
||||
}
|
||||
|
||||
static void
|
||||
child_io_complete(struct spdk_bdev_io *child_io, spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
if (g_bdev_io_defer_completion) {
|
||||
child_io->internal.cb = cb;
|
||||
child_io->internal.caller_ctx = cb_arg;
|
||||
TAILQ_INSERT_TAIL(&g_deferred_ios, child_io, internal.link);
|
||||
} else {
|
||||
cb(child_io, g_child_io_status_flag, cb_arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
complete_deferred_ios(void)
|
||||
{
|
||||
struct spdk_bdev_io *child_io;
|
||||
|
||||
while ((child_io = TAILQ_FIRST(&g_deferred_ios))) {
|
||||
TAILQ_REMOVE(&g_deferred_ios, child_io, internal.link);
|
||||
child_io->internal.cb(child_io, g_child_io_status_flag, child_io->internal.caller_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* It will cache the split IOs for verification */
|
||||
int
|
||||
spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
@ -356,7 +282,7 @@ spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
|
||||
child_io = calloc(1, sizeof(struct spdk_bdev_io));
|
||||
SPDK_CU_ASSERT_FATAL(child_io != NULL);
|
||||
child_io_complete(child_io, cb, cb_arg);
|
||||
cb(child_io, g_child_io_status_flag, cb_arg);
|
||||
}
|
||||
|
||||
return g_bdev_io_submit_status;
|
||||
@ -398,7 +324,7 @@ spdk_bdev_reset(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
|
||||
child_io = calloc(1, sizeof(struct spdk_bdev_io));
|
||||
SPDK_CU_ASSERT_FATAL(child_io != NULL);
|
||||
child_io_complete(child_io, cb, cb_arg);
|
||||
cb(child_io, g_child_io_status_flag, cb_arg);
|
||||
}
|
||||
|
||||
return g_bdev_io_submit_status;
|
||||
@ -423,7 +349,7 @@ spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
|
||||
child_io = calloc(1, sizeof(struct spdk_bdev_io));
|
||||
SPDK_CU_ASSERT_FATAL(child_io != NULL);
|
||||
child_io_complete(child_io, cb, cb_arg);
|
||||
cb(child_io, g_child_io_status_flag, cb_arg);
|
||||
}
|
||||
|
||||
return g_bdev_io_submit_status;
|
||||
@ -472,6 +398,12 @@ spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
|
||||
return (void *)desc;
|
||||
}
|
||||
|
||||
char *
|
||||
spdk_sprintf_alloc(const char *format, ...)
|
||||
{
|
||||
return strdup(format);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_json_write_named_uint32(struct spdk_json_write_ctx *w, const char *name, uint32_t val)
|
||||
{
|
||||
@ -512,18 +444,6 @@ spdk_json_write_named_string(struct spdk_json_write_ctx *w, const char *name, co
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_json_write_named_bool(struct spdk_json_write_ctx *w, const char *name, bool val)
|
||||
{
|
||||
if (!g_test_multi_raids) {
|
||||
struct rpc_bdev_raid_create *req = g_rpc_req;
|
||||
if (strcmp(name, "superblock") == 0) {
|
||||
CU_ASSERT(val == req->superblock);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
@ -554,7 +474,7 @@ spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
|
||||
child_io = calloc(1, sizeof(struct spdk_bdev_io));
|
||||
SPDK_CU_ASSERT_FATAL(child_io != NULL);
|
||||
child_io_complete(child_io, cb, cb_arg);
|
||||
cb(child_io, g_child_io_status_flag, cb_arg);
|
||||
}
|
||||
|
||||
return g_bdev_io_submit_status;
|
||||
@ -621,7 +541,6 @@ spdk_json_decode_object(const struct spdk_json_val *values,
|
||||
SPDK_CU_ASSERT_FATAL(_out->name != NULL);
|
||||
_out->strip_size_kb = req->strip_size_kb;
|
||||
_out->level = req->level;
|
||||
_out->superblock = req->superblock;
|
||||
_out->base_bdevs.num_base_bdevs = req->base_bdevs.num_base_bdevs;
|
||||
for (i = 0; i < req->base_bdevs.num_base_bdevs; i++) {
|
||||
_out->base_bdevs.base_bdevs[i] = strdup(req->base_bdevs.base_bdevs[i]);
|
||||
@ -947,23 +866,18 @@ verify_raid_bdev(struct rpc_bdev_raid_create *r, bool presence, uint32_t raid_st
|
||||
bdev = spdk_bdev_get_by_name(base_info->bdev->name);
|
||||
CU_ASSERT(bdev != NULL);
|
||||
CU_ASSERT(base_info->remove_scheduled == false);
|
||||
CU_ASSERT((pbdev->sb != NULL && base_info->data_offset != 0) ||
|
||||
(pbdev->sb == NULL && base_info->data_offset == 0));
|
||||
CU_ASSERT(base_info->data_offset + base_info->data_size == bdev->blockcnt);
|
||||
|
||||
if (bdev && base_info->data_size < min_blockcnt) {
|
||||
min_blockcnt = base_info->data_size;
|
||||
if (bdev && bdev->blockcnt < min_blockcnt) {
|
||||
min_blockcnt = bdev->blockcnt;
|
||||
}
|
||||
}
|
||||
if (r->strip_size_kb > 0) {
|
||||
CU_ASSERT((((min_blockcnt / (r->strip_size_kb * 1024 / g_block_len)) *
|
||||
(r->strip_size_kb * 1024 / g_block_len)) *
|
||||
r->base_bdevs.num_base_bdevs) == pbdev->bdev.blockcnt);
|
||||
}
|
||||
CU_ASSERT((((min_blockcnt / (r->strip_size_kb * 1024 / g_block_len)) *
|
||||
(r->strip_size_kb * 1024 / g_block_len)) *
|
||||
r->base_bdevs.num_base_bdevs) == pbdev->bdev.blockcnt);
|
||||
CU_ASSERT(strcmp(pbdev->bdev.product_name, "Raid Volume") == 0);
|
||||
CU_ASSERT(pbdev->bdev.write_cache == 0);
|
||||
CU_ASSERT(pbdev->bdev.blocklen == g_block_len);
|
||||
if (pbdev->num_base_bdevs > 1 && pbdev->level != RAID1) {
|
||||
if (pbdev->num_base_bdevs > 1) {
|
||||
CU_ASSERT(pbdev->bdev.optimal_io_boundary == pbdev->strip_size);
|
||||
CU_ASSERT(pbdev->bdev.split_on_optimal_io_boundary == true);
|
||||
} else {
|
||||
@ -1019,7 +933,6 @@ create_base_bdevs(uint32_t bbdev_start_idx)
|
||||
base_bdev = calloc(1, sizeof(struct spdk_bdev));
|
||||
SPDK_CU_ASSERT_FATAL(base_bdev != NULL);
|
||||
base_bdev->name = strdup(name);
|
||||
spdk_uuid_generate(&base_bdev->uuid);
|
||||
SPDK_CU_ASSERT_FATAL(base_bdev->name != NULL);
|
||||
base_bdev->blocklen = g_block_len;
|
||||
base_bdev->blockcnt = BLOCK_CNT;
|
||||
@ -1029,8 +942,7 @@ create_base_bdevs(uint32_t bbdev_start_idx)
|
||||
|
||||
static void
|
||||
create_test_req(struct rpc_bdev_raid_create *r, const char *raid_name,
|
||||
uint8_t bbdev_start_idx, bool create_base_bdev, bool superblock,
|
||||
uint8_t num_base_bdev_to_use)
|
||||
uint8_t bbdev_start_idx, bool create_base_bdev)
|
||||
{
|
||||
uint8_t i;
|
||||
char name[16];
|
||||
@ -1040,9 +952,8 @@ create_test_req(struct rpc_bdev_raid_create *r, const char *raid_name,
|
||||
SPDK_CU_ASSERT_FATAL(r->name != NULL);
|
||||
r->strip_size_kb = (g_strip_size * g_block_len) / 1024;
|
||||
r->level = RAID0;
|
||||
r->superblock = superblock;
|
||||
r->base_bdevs.num_base_bdevs = num_base_bdev_to_use;
|
||||
for (i = 0; i < num_base_bdev_to_use; i++, bbdev_idx++) {
|
||||
r->base_bdevs.num_base_bdevs = g_max_base_drives;
|
||||
for (i = 0; i < g_max_base_drives; i++, bbdev_idx++) {
|
||||
snprintf(name, 16, "%s%u%s", "Nvme", bbdev_idx, "n1");
|
||||
r->base_bdevs.base_bdevs[i] = strdup(name);
|
||||
SPDK_CU_ASSERT_FATAL(r->base_bdevs.base_bdevs[i] != NULL);
|
||||
@ -1055,13 +966,11 @@ create_test_req(struct rpc_bdev_raid_create *r, const char *raid_name,
|
||||
}
|
||||
|
||||
static void
|
||||
_create_raid_bdev_create_req(struct rpc_bdev_raid_create *r, const char *raid_name,
|
||||
uint8_t bbdev_start_idx, bool create_base_bdev,
|
||||
uint8_t json_decode_obj_err, bool superblock,
|
||||
uint8_t num_base_bdev_to_use)
|
||||
create_raid_bdev_create_req(struct rpc_bdev_raid_create *r, const char *raid_name,
|
||||
uint8_t bbdev_start_idx, bool create_base_bdev,
|
||||
uint8_t json_decode_obj_err)
|
||||
{
|
||||
create_test_req(r, raid_name, bbdev_start_idx, create_base_bdev, superblock,
|
||||
num_base_bdev_to_use);
|
||||
create_test_req(r, raid_name, bbdev_start_idx, create_base_bdev);
|
||||
|
||||
g_rpc_err = 0;
|
||||
g_json_decode_obj_create = 1;
|
||||
@ -1070,15 +979,6 @@ _create_raid_bdev_create_req(struct rpc_bdev_raid_create *r, const char *raid_na
|
||||
g_test_multi_raids = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
create_raid_bdev_create_req(struct rpc_bdev_raid_create *r, const char *raid_name,
|
||||
uint8_t bbdev_start_idx, bool create_base_bdev,
|
||||
uint8_t json_decode_obj_err, bool superblock)
|
||||
{
|
||||
_create_raid_bdev_create_req(r, raid_name, bbdev_start_idx, create_base_bdev,
|
||||
json_decode_obj_err, superblock, g_max_base_drives);
|
||||
}
|
||||
|
||||
static void
|
||||
free_test_req(struct rpc_bdev_raid_create *r)
|
||||
{
|
||||
@ -1133,7 +1033,7 @@ test_create_raid(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -1157,7 +1057,7 @@ test_delete_raid(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&construct_req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&construct_req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&construct_req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -1184,44 +1084,44 @@ test_create_raid_invalid_args(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
req.level = INVALID_RAID_LEVEL;
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 1);
|
||||
free_test_req(&req);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 1, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 1);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 1);
|
||||
free_test_req(&req);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 0);
|
||||
req.strip_size_kb = 1231;
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 1);
|
||||
free_test_req(&req);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
free_test_req(&req);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, false, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 1);
|
||||
free_test_req(&req);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid2", 0, false, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid2", 0, false, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 1);
|
||||
free_test_req(&req);
|
||||
verify_raid_bdev_present("raid2", false);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, true, 0);
|
||||
free(req.base_bdevs.base_bdevs[g_max_base_drives - 1]);
|
||||
req.base_bdevs.base_bdevs[g_max_base_drives - 1] = strdup("Nvme0n1");
|
||||
SPDK_CU_ASSERT_FATAL(req.base_bdevs.base_bdevs[g_max_base_drives - 1] != NULL);
|
||||
@ -1230,7 +1130,7 @@ test_create_raid_invalid_args(void)
|
||||
free_test_req(&req);
|
||||
verify_raid_bdev_present("raid2", false);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, true, 0);
|
||||
free(req.base_bdevs.base_bdevs[g_max_base_drives - 1]);
|
||||
req.base_bdevs.base_bdevs[g_max_base_drives - 1] = strdup("Nvme100000n1");
|
||||
SPDK_CU_ASSERT_FATAL(req.base_bdevs.base_bdevs[g_max_base_drives - 1] != NULL);
|
||||
@ -1242,7 +1142,7 @@ test_create_raid_invalid_args(void)
|
||||
SPDK_CU_ASSERT_FATAL(raid_bdev != NULL);
|
||||
check_and_remove_raid_bdev(raid_bdev);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, false, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, false, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
free_test_req(&req);
|
||||
@ -1268,7 +1168,7 @@ test_delete_raid_invalid_args(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&construct_req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&construct_req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&construct_req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -1306,7 +1206,7 @@ test_io_channel(void)
|
||||
set_globals();
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
@ -1358,7 +1258,7 @@ test_write_io(void)
|
||||
set_globals();
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
@ -1434,7 +1334,7 @@ test_read_io(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -1584,7 +1484,7 @@ test_unmap_io(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -1655,7 +1555,7 @@ test_io_failure(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -1737,7 +1637,7 @@ test_reset_io(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -1804,7 +1704,7 @@ test_multi_raid_no_io(void)
|
||||
for (i = 0; i < g_max_raids; i++) {
|
||||
snprintf(name, 16, "%s%u", "raid", i);
|
||||
verify_raid_bdev_present(name, false);
|
||||
create_raid_bdev_create_req(&construct_req[i], name, bbdev_idx, true, 0, false);
|
||||
create_raid_bdev_create_req(&construct_req[i], name, bbdev_idx, true, 0);
|
||||
bbdev_idx += g_max_base_drives;
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
@ -1907,7 +1807,7 @@ test_multi_raid_with_io(void)
|
||||
for (i = 0; i < g_max_raids; i++) {
|
||||
snprintf(name, 16, "%s%u", "raid", i);
|
||||
verify_raid_bdev_present(name, false);
|
||||
create_raid_bdev_create_req(&construct_req[i], name, bbdev_idx, true, 0, false);
|
||||
create_raid_bdev_create_req(&construct_req[i], name, bbdev_idx, true, 0);
|
||||
bbdev_idx += g_max_base_drives;
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
@ -1998,7 +1898,7 @@ test_raid_json_dump_info(void)
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
@ -2048,377 +1948,6 @@ test_raid_level_conversions(void)
|
||||
CU_ASSERT(raid_str != NULL && strcmp(raid_str, "raid0") == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_create_raid_superblock(void)
|
||||
{
|
||||
struct rpc_bdev_raid_create req;
|
||||
struct rpc_bdev_raid_delete delete_req;
|
||||
|
||||
set_globals();
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, true);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
free_test_req(&req);
|
||||
|
||||
create_raid_bdev_delete_req(&delete_req, "raid1", 0);
|
||||
rpc_bdev_raid_delete(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
raid_bdev_exit();
|
||||
base_bdevs_cleanup();
|
||||
reset_globals();
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
suspend_cb(struct raid_bdev *raid_bdev, void *ctx)
|
||||
{
|
||||
*(bool *)ctx = true;
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid_suspend_resume(void)
|
||||
{
|
||||
struct rpc_bdev_raid_create req;
|
||||
struct rpc_bdev_raid_delete destroy_req;
|
||||
struct raid_bdev *pbdev;
|
||||
struct spdk_io_channel *ch;
|
||||
struct raid_bdev_io_channel *raid_ch;
|
||||
struct spdk_bdev_io *bdev_io;
|
||||
bool suspend_cb_called, suspend_cb_called2;
|
||||
int rc;
|
||||
|
||||
set_globals();
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
|
||||
TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
|
||||
if (strcmp(pbdev->bdev.name, "raid1") == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CU_ASSERT(pbdev != NULL);
|
||||
|
||||
/* suspend/resume with no io channels */
|
||||
suspend_cb_called = false;
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
poll_threads();
|
||||
CU_ASSERT(suspend_cb_called == true);
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
poll_threads();
|
||||
|
||||
/* suspend/resume with one idle io channel */
|
||||
ch = spdk_get_io_channel(pbdev);
|
||||
SPDK_CU_ASSERT_FATAL(ch != NULL);
|
||||
raid_ch = spdk_io_channel_get_ctx(ch);
|
||||
|
||||
suspend_cb_called = false;
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
poll_threads();
|
||||
CU_ASSERT(suspend_cb_called == true);
|
||||
CU_ASSERT(raid_ch->is_suspended == true);
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch->is_suspended == false);
|
||||
|
||||
/* suspend/resume multiple */
|
||||
suspend_cb_called = false;
|
||||
suspend_cb_called2 = false;
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called2);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
poll_threads();
|
||||
CU_ASSERT(suspend_cb_called == true);
|
||||
CU_ASSERT(suspend_cb_called2 == true);
|
||||
CU_ASSERT(raid_ch->is_suspended == true);
|
||||
suspend_cb_called = false;
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
CU_ASSERT(suspend_cb_called == true);
|
||||
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch->is_suspended == true);
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch->is_suspended == true);
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch->is_suspended == false);
|
||||
|
||||
/* suspend/resume with io before and after suspend */
|
||||
bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
|
||||
SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
|
||||
bdev_io_initialize(bdev_io, ch, &pbdev->bdev, 0, 1, SPDK_BDEV_IO_TYPE_READ);
|
||||
memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
|
||||
g_io_output_index = 0;
|
||||
g_bdev_io_defer_completion = true;
|
||||
raid_bdev_submit_request(ch, bdev_io);
|
||||
CU_ASSERT(raid_ch->num_ios == 1);
|
||||
|
||||
suspend_cb_called = false;
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch->is_suspended == true);
|
||||
CU_ASSERT(suspend_cb_called == false);
|
||||
complete_deferred_ios();
|
||||
verify_io(bdev_io, req.base_bdevs.num_base_bdevs, raid_ch, pbdev, g_child_io_status_flag);
|
||||
poll_threads();
|
||||
CU_ASSERT(suspend_cb_called == true);
|
||||
g_io_output_index = 0;
|
||||
raid_bdev_submit_request(ch, bdev_io);
|
||||
CU_ASSERT(raid_ch->num_ios == 0);
|
||||
CU_ASSERT(TAILQ_FIRST(&raid_ch->suspended_ios) == (struct raid_bdev_io *)bdev_io->driver_ctx);
|
||||
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch->is_suspended == false);
|
||||
verify_io(bdev_io, req.base_bdevs.num_base_bdevs, raid_ch, pbdev, g_child_io_status_flag);
|
||||
|
||||
bdev_io_cleanup(bdev_io);
|
||||
spdk_put_io_channel(ch);
|
||||
|
||||
free_test_req(&req);
|
||||
|
||||
create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
|
||||
rpc_bdev_raid_delete(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
|
||||
raid_bdev_exit();
|
||||
base_bdevs_cleanup();
|
||||
reset_globals();
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid_suspend_resume_create_ch(void)
|
||||
{
|
||||
struct rpc_bdev_raid_create req;
|
||||
struct rpc_bdev_raid_delete destroy_req;
|
||||
struct raid_bdev *pbdev;
|
||||
struct spdk_io_channel *ch1, *ch2;
|
||||
struct raid_bdev_io_channel *raid_ch1, *raid_ch2;
|
||||
bool suspend_cb_called;
|
||||
int rc;
|
||||
|
||||
free_threads();
|
||||
allocate_threads(3);
|
||||
set_thread(0);
|
||||
|
||||
set_globals();
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
g_per_thread_base_bdev_channels = calloc(3, sizeof(struct spdk_io_channel));
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
|
||||
TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
|
||||
if (strcmp(pbdev->bdev.name, "raid1") == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CU_ASSERT(pbdev != NULL);
|
||||
|
||||
set_thread(1);
|
||||
ch1 = spdk_get_io_channel(pbdev);
|
||||
SPDK_CU_ASSERT_FATAL(ch1 != NULL);
|
||||
raid_ch1 = spdk_io_channel_get_ctx(ch1);
|
||||
|
||||
/* create a new io channel during suspend */
|
||||
set_thread(0);
|
||||
suspend_cb_called = false;
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
|
||||
poll_thread(1);
|
||||
CU_ASSERT(raid_ch1->is_suspended == true);
|
||||
CU_ASSERT(suspend_cb_called == false);
|
||||
|
||||
set_thread(2);
|
||||
ch2 = spdk_get_io_channel(pbdev);
|
||||
SPDK_CU_ASSERT_FATAL(ch2 != NULL);
|
||||
raid_ch2 = spdk_io_channel_get_ctx(ch2);
|
||||
|
||||
poll_threads();
|
||||
CU_ASSERT(suspend_cb_called == true);
|
||||
CU_ASSERT(raid_ch1->is_suspended == true);
|
||||
CU_ASSERT(raid_ch2->is_suspended == true);
|
||||
set_thread(0);
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch1->is_suspended == false);
|
||||
CU_ASSERT(raid_ch2->is_suspended == false);
|
||||
set_thread(2);
|
||||
spdk_put_io_channel(ch2);
|
||||
poll_threads();
|
||||
|
||||
/* create a new io channel during resume */
|
||||
set_thread(0);
|
||||
suspend_cb_called = false;
|
||||
rc = raid_bdev_suspend(pbdev, suspend_cb, &suspend_cb_called);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
poll_threads();
|
||||
CU_ASSERT(suspend_cb_called == true);
|
||||
CU_ASSERT(raid_ch1->is_suspended == true);
|
||||
raid_bdev_resume(pbdev, NULL, NULL);
|
||||
|
||||
set_thread(2);
|
||||
ch2 = spdk_get_io_channel(pbdev);
|
||||
SPDK_CU_ASSERT_FATAL(ch2 != NULL);
|
||||
raid_ch2 = spdk_io_channel_get_ctx(ch2);
|
||||
CU_ASSERT(raid_ch1->is_suspended == true);
|
||||
CU_ASSERT(raid_ch2->is_suspended == false);
|
||||
|
||||
poll_threads();
|
||||
CU_ASSERT(raid_ch1->is_suspended == false);
|
||||
CU_ASSERT(raid_ch2->is_suspended == false);
|
||||
set_thread(2);
|
||||
spdk_put_io_channel(ch2);
|
||||
poll_threads();
|
||||
|
||||
set_thread(1);
|
||||
spdk_put_io_channel(ch1);
|
||||
poll_threads();
|
||||
set_thread(0);
|
||||
|
||||
free_test_req(&req);
|
||||
|
||||
create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
|
||||
rpc_bdev_raid_delete(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
|
||||
raid_bdev_exit();
|
||||
base_bdevs_cleanup();
|
||||
reset_globals();
|
||||
|
||||
free_threads();
|
||||
allocate_threads(1);
|
||||
set_thread(0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid_grow_base_bdev_not_supported(void)
|
||||
{
|
||||
struct rpc_bdev_raid_create req;
|
||||
struct rpc_bdev_raid_delete destroy_req;
|
||||
struct raid_bdev *pbdev;
|
||||
int rc;
|
||||
|
||||
set_globals();
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
|
||||
req.level = RAID0;
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
|
||||
TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
|
||||
if (strcmp(pbdev->bdev.name, "raid1") == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CU_ASSERT(pbdev != NULL);
|
||||
|
||||
/* Only RAID1 level actually support grow base bdev operation */
|
||||
rc = raid_bdev_grow_base_bdev(pbdev, "", NULL, NULL);
|
||||
CU_ASSERT(rc == -EPERM);
|
||||
free_test_req(&req);
|
||||
|
||||
create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
|
||||
rpc_bdev_raid_delete(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
|
||||
raid_bdev_exit();
|
||||
base_bdevs_cleanup();
|
||||
reset_globals();
|
||||
}
|
||||
|
||||
static void
|
||||
grow_base_bdev_cb(void *cb_arg, int rc)
|
||||
{
|
||||
*(int *)cb_arg = rc;
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid_grow_base_bdev(void)
|
||||
{
|
||||
struct rpc_bdev_raid_create req;
|
||||
struct rpc_bdev_raid_delete destroy_req;
|
||||
struct raid_bdev *pbdev;
|
||||
char name[16];
|
||||
struct spdk_io_channel *ch;
|
||||
int grow_base_bdev_cb_output;
|
||||
int rc;
|
||||
|
||||
set_globals();
|
||||
CU_ASSERT(raid_bdev_init() == 0);
|
||||
|
||||
snprintf(name, 16, "%s%u%s", "Nvme", g_max_base_drives - 1, "n1");
|
||||
|
||||
/* Create a raid with RAID1 level */
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
_create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false,
|
||||
g_max_base_drives - 1);
|
||||
req.strip_size_kb = 0;
|
||||
req.level = RAID1;
|
||||
rpc_bdev_raid_create(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
|
||||
|
||||
TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
|
||||
if (strcmp(pbdev->bdev.name, "raid1") == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CU_ASSERT(pbdev != NULL);
|
||||
|
||||
/* Grow raid adding base bdev successfully */
|
||||
ch = spdk_get_io_channel(pbdev);
|
||||
SPDK_CU_ASSERT_FATAL(ch != NULL);
|
||||
grow_base_bdev_cb_output = 1;
|
||||
rc = raid_bdev_grow_base_bdev(pbdev, name, grow_base_bdev_cb,
|
||||
&grow_base_bdev_cb_output);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
/* Grow base bdev with another operation running */
|
||||
rc = raid_bdev_grow_base_bdev(pbdev, name, NULL, NULL);
|
||||
CU_ASSERT(rc == -EBUSY);
|
||||
|
||||
/* Check that new base bdev has been correctly added */
|
||||
poll_threads();
|
||||
CU_ASSERT(grow_base_bdev_cb_output == 0);
|
||||
spdk_put_io_channel(ch);
|
||||
free_test_req(&req);
|
||||
|
||||
create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
|
||||
rpc_bdev_raid_delete(NULL, NULL);
|
||||
CU_ASSERT(g_rpc_err == 0);
|
||||
verify_raid_bdev_present("raid1", false);
|
||||
|
||||
raid_bdev_exit();
|
||||
base_bdevs_cleanup();
|
||||
reset_globals();
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -2431,7 +1960,6 @@ main(int argc, char **argv)
|
||||
suite = CU_add_suite("raid", NULL, NULL);
|
||||
|
||||
CU_ADD_TEST(suite, test_create_raid);
|
||||
CU_ADD_TEST(suite, test_create_raid_superblock);
|
||||
CU_ADD_TEST(suite, test_delete_raid);
|
||||
CU_ADD_TEST(suite, test_create_raid_invalid_args);
|
||||
CU_ADD_TEST(suite, test_delete_raid_invalid_args);
|
||||
@ -2447,10 +1975,6 @@ main(int argc, char **argv)
|
||||
CU_ADD_TEST(suite, test_raid_json_dump_info);
|
||||
CU_ADD_TEST(suite, test_context_size);
|
||||
CU_ADD_TEST(suite, test_raid_level_conversions);
|
||||
CU_ADD_TEST(suite, test_raid_suspend_resume);
|
||||
CU_ADD_TEST(suite, test_raid_suspend_resume_create_ch);
|
||||
CU_ADD_TEST(suite, test_raid_grow_base_bdev_not_supported);
|
||||
CU_ADD_TEST(suite, test_raid_grow_base_bdev);
|
||||
|
||||
allocate_threads(1);
|
||||
set_thread(0);
|
||||
|
@ -1,10 +0,0 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2022 Intel Corporation.
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../../..)
|
||||
|
||||
TEST_FILE = bdev_raid_sb_ut.c
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk
|
@ -1,248 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk_cunit.h"
|
||||
#include "spdk/env.h"
|
||||
#include "spdk_internal/mock.h"
|
||||
|
||||
#include "common/lib/test_env.c"
|
||||
#include "bdev/raid/bdev_raid_sb.c"
|
||||
|
||||
#define TEST_BUF_ALIGN 64
|
||||
#define TEST_BLOCK_SIZE 512
|
||||
|
||||
DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *, (struct spdk_bdev_desc *desc), NULL);
|
||||
DEFINE_STUB(spdk_bdev_get_name, const char *, (const struct spdk_bdev *bdev), "test_bdev");
|
||||
DEFINE_STUB(spdk_bdev_get_buf_align, size_t, (const struct spdk_bdev *bdev), TEST_BUF_ALIGN);
|
||||
DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, (const struct spdk_bdev *bdev), TEST_BLOCK_SIZE);
|
||||
DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *g_bdev_io));
|
||||
|
||||
void *g_buf;
|
||||
int g_read_counter;
|
||||
|
||||
static int
|
||||
test_setup(void)
|
||||
{
|
||||
g_buf = spdk_dma_zmalloc(RAID_BDEV_SB_MAX_LENGTH, TEST_BUF_ALIGN, NULL);
|
||||
if (!g_buf) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_cleanup(void)
|
||||
{
|
||||
spdk_dma_free(g_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_read(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
void *buf, uint64_t offset, uint64_t nbytes,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
g_read_counter++;
|
||||
memcpy(buf, g_buf + offset, nbytes);
|
||||
cb(NULL, true, cb_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_write(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
void *buf, uint64_t offset, uint64_t nbytes,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
struct raid_bdev_superblock *sb = buf;
|
||||
|
||||
CU_ASSERT(offset == 0);
|
||||
CU_ASSERT(nbytes / TEST_BLOCK_SIZE == spdk_divide_round_up(sb->length, TEST_BLOCK_SIZE));
|
||||
|
||||
cb(NULL, true, cb_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_sb(struct raid_bdev_superblock *sb)
|
||||
{
|
||||
/* prepare a simplest valid sb */
|
||||
memset(sb, 0, RAID_BDEV_SB_MAX_LENGTH);
|
||||
memcpy(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature));
|
||||
sb->version.major = RAID_BDEV_SB_VERSION_MAJOR;
|
||||
sb->version.minor = RAID_BDEV_SB_VERSION_MINOR;
|
||||
sb->length = sizeof(*sb);
|
||||
sb->crc = spdk_crc32c_update(sb, sb->length, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
save_sb_cb(int status, void *ctx)
|
||||
{
|
||||
int *status_out = ctx;
|
||||
|
||||
*status_out = status;
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid_bdev_save_base_bdev_superblock(void)
|
||||
{
|
||||
struct raid_bdev_superblock *sb = g_buf;
|
||||
int rc;
|
||||
int status;
|
||||
|
||||
prepare_sb(sb);
|
||||
|
||||
status = INT_MAX;
|
||||
rc = raid_bdev_save_base_bdev_superblock(NULL, NULL, sb, save_sb_cb, &status);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(status == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
load_sb_cb(const struct raid_bdev_superblock *sb, int status, void *ctx)
|
||||
{
|
||||
int *status_out = ctx;
|
||||
|
||||
if (status == 0) {
|
||||
CU_ASSERT(memcmp(sb, g_buf, sb->length) == 0);
|
||||
}
|
||||
|
||||
*status_out = status;
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid_bdev_load_base_bdev_superblock(void)
|
||||
{
|
||||
struct raid_bdev_superblock *sb = g_buf;
|
||||
int rc;
|
||||
int status;
|
||||
|
||||
/* valid superblock */
|
||||
prepare_sb(sb);
|
||||
|
||||
g_read_counter = 0;
|
||||
status = INT_MAX;
|
||||
rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(status == 0);
|
||||
CU_ASSERT(g_read_counter == 1);
|
||||
|
||||
/* invalid signature */
|
||||
prepare_sb(sb);
|
||||
sb->signature[3] = 'Z';
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
|
||||
g_read_counter = 0;
|
||||
status = INT_MAX;
|
||||
rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(status == -EINVAL);
|
||||
CU_ASSERT(g_read_counter == 1);
|
||||
|
||||
/* make the sb longer than 1 bdev block - expect 2 reads */
|
||||
prepare_sb(sb);
|
||||
sb->length = TEST_BLOCK_SIZE * 3;
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
|
||||
g_read_counter = 0;
|
||||
status = INT_MAX;
|
||||
rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(status == 0);
|
||||
CU_ASSERT(g_read_counter == 2);
|
||||
|
||||
/* corrupted sb contents, length > 1 bdev block - expect 2 reads */
|
||||
prepare_sb(sb);
|
||||
sb->length = TEST_BLOCK_SIZE * 3;
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
sb->reserved[0] = 0xff;
|
||||
|
||||
g_read_counter = 0;
|
||||
status = INT_MAX;
|
||||
rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(status == -EINVAL);
|
||||
CU_ASSERT(g_read_counter == 2);
|
||||
|
||||
/* invalid signature, length > 1 bdev block - expect 1 read */
|
||||
prepare_sb(sb);
|
||||
sb->signature[3] = 'Z';
|
||||
sb->length = TEST_BLOCK_SIZE * 3;
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
|
||||
g_read_counter = 0;
|
||||
status = INT_MAX;
|
||||
rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(status == -EINVAL);
|
||||
CU_ASSERT(g_read_counter == 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid_bdev_parse_superblock(void)
|
||||
{
|
||||
struct raid_bdev_superblock *sb = g_buf;
|
||||
struct raid_bdev_read_sb_ctx ctx = {
|
||||
.buf = g_buf,
|
||||
.buf_size = TEST_BLOCK_SIZE,
|
||||
};
|
||||
|
||||
/* valid superblock */
|
||||
prepare_sb(sb);
|
||||
CU_ASSERT(raid_bdev_parse_superblock(&ctx) == 0);
|
||||
|
||||
/* invalid signature */
|
||||
prepare_sb(sb);
|
||||
sb->signature[3] = 'Z';
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
|
||||
|
||||
/* invalid crc */
|
||||
prepare_sb(sb);
|
||||
sb->crc = 0xdeadbeef;
|
||||
CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
|
||||
|
||||
/* corrupted sb contents */
|
||||
prepare_sb(sb);
|
||||
sb->reserved[0] = 0xff;
|
||||
CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
|
||||
|
||||
/* invalid major version */
|
||||
prepare_sb(sb);
|
||||
sb->version.major = 9999;
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
|
||||
|
||||
/* sb longer than 1 bdev block */
|
||||
prepare_sb(sb);
|
||||
sb->length = TEST_BLOCK_SIZE * 3;
|
||||
raid_bdev_sb_update_crc(sb);
|
||||
CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EAGAIN);
|
||||
ctx.buf_size = sb->length;
|
||||
CU_ASSERT(raid_bdev_parse_superblock(&ctx) == 0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
|
||||
CU_set_error_action(CUEA_ABORT);
|
||||
CU_initialize_registry();
|
||||
|
||||
suite = CU_add_suite("raid_sb", test_setup, test_cleanup);
|
||||
CU_ADD_TEST(suite, test_raid_bdev_save_base_bdev_superblock);
|
||||
CU_ADD_TEST(suite, test_raid_bdev_load_base_bdev_superblock);
|
||||
CU_ADD_TEST(suite, test_raid_bdev_parse_superblock);
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
num_failures = CU_get_number_of_failures();
|
||||
CU_cleanup_registry();
|
||||
return num_failures;
|
||||
}
|
@ -105,8 +105,6 @@ raid_test_create_raid_bdev(struct raid_params *params, struct raid_bdev_module *
|
||||
|
||||
base_info->bdev = bdev;
|
||||
base_info->desc = desc;
|
||||
base_info->data_offset = 0;
|
||||
base_info->data_size = bdev->blockcnt;
|
||||
}
|
||||
|
||||
raid_bdev->strip_size = params->strip_size;
|
||||
|
@ -6,16 +6,17 @@
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk_cunit.h"
|
||||
#include "spdk/env.h"
|
||||
|
||||
#include "common/lib/ut_multithread.c"
|
||||
#include "spdk_internal/mock.h"
|
||||
|
||||
#include "bdev/raid/raid1.c"
|
||||
#include "../common.c"
|
||||
|
||||
DEFINE_STUB_V(raid_bdev_module_list_add, (struct raid_bdev_module *raid_module));
|
||||
DEFINE_STUB_V(raid_bdev_module_stop_done, (struct raid_bdev *raid_bdev));
|
||||
DEFINE_STUB_V(raid_bdev_io_complete, (struct raid_bdev_io *raid_io,
|
||||
enum spdk_bdev_io_status status));
|
||||
DEFINE_STUB(raid_bdev_io_complete_part, bool, (struct raid_bdev_io *raid_io, uint64_t completed,
|
||||
enum spdk_bdev_io_status status), true);
|
||||
DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *bdev_io));
|
||||
DEFINE_STUB_V(raid_bdev_queue_io_wait, (struct raid_bdev_io *raid_io, struct spdk_bdev *bdev,
|
||||
struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn));
|
||||
DEFINE_STUB(spdk_bdev_readv_blocks_with_md, int, (struct spdk_bdev_desc *desc,
|
||||
@ -92,9 +93,9 @@ create_raid1(struct raid_params *params)
|
||||
}
|
||||
|
||||
static void
|
||||
delete_raid1(struct raid1_info *r1info)
|
||||
delete_raid1(struct raid1_info *r1_info)
|
||||
{
|
||||
struct raid_bdev *raid_bdev = r1info->raid_bdev;
|
||||
struct raid_bdev *raid_bdev = r1_info->raid_bdev;
|
||||
|
||||
raid1_stop(raid_bdev);
|
||||
|
||||
@ -107,171 +108,20 @@ test_raid1_start(void)
|
||||
struct raid_params *params;
|
||||
|
||||
RAID_PARAMS_FOR_EACH(params) {
|
||||
struct raid1_info *r1info;
|
||||
struct raid1_info *r1_info;
|
||||
|
||||
r1info = create_raid1(params);
|
||||
r1_info = create_raid1(params);
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(r1info != NULL);
|
||||
SPDK_CU_ASSERT_FATAL(r1_info != NULL);
|
||||
|
||||
CU_ASSERT_EQUAL(r1info->raid_bdev->level, RAID1);
|
||||
CU_ASSERT_EQUAL(r1info->raid_bdev->bdev.blockcnt, params->base_bdev_blockcnt);
|
||||
CU_ASSERT_PTR_EQUAL(r1info->raid_bdev->module, &g_raid1_module);
|
||||
CU_ASSERT_EQUAL(r1_info->raid_bdev->level, RAID1);
|
||||
CU_ASSERT_EQUAL(r1_info->raid_bdev->bdev.blockcnt, params->base_bdev_blockcnt);
|
||||
CU_ASSERT_PTR_EQUAL(r1_info->raid_bdev->module, &g_raid1_module);
|
||||
|
||||
delete_raid1(r1info);
|
||||
delete_raid1(r1_info);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
free(bdev_io);
|
||||
}
|
||||
|
||||
void
|
||||
raid_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status)
|
||||
{
|
||||
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(raid_io);
|
||||
|
||||
spdk_bdev_free_io(bdev_io);
|
||||
}
|
||||
|
||||
static struct raid_bdev_io *
|
||||
get_raid_io(struct raid1_info *r1info, struct raid_bdev_io_channel *raid_ch,
|
||||
enum spdk_bdev_io_type io_type, uint64_t num_blocks)
|
||||
{
|
||||
struct spdk_bdev_io *bdev_io;
|
||||
struct raid_bdev_io *raid_io;
|
||||
|
||||
bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
|
||||
SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
|
||||
|
||||
bdev_io->bdev = &r1info->raid_bdev->bdev;
|
||||
bdev_io->type = io_type;
|
||||
bdev_io->u.bdev.offset_blocks = 0;
|
||||
bdev_io->u.bdev.num_blocks = num_blocks;
|
||||
bdev_io->internal.cb = NULL;
|
||||
bdev_io->internal.caller_ctx = NULL;
|
||||
|
||||
raid_io = (void *)bdev_io->driver_ctx;
|
||||
raid_io->raid_bdev = r1info->raid_bdev;
|
||||
raid_io->raid_ch = raid_ch;
|
||||
|
||||
return raid_io;
|
||||
}
|
||||
|
||||
static void
|
||||
run_for_each_raid1_config(void (*test_fn)(struct raid_bdev *raid_bdev,
|
||||
struct raid_bdev_io_channel *raid_ch))
|
||||
{
|
||||
struct raid_params *params;
|
||||
|
||||
RAID_PARAMS_FOR_EACH(params) {
|
||||
struct raid1_info *r1info;
|
||||
struct raid_bdev_io_channel raid_ch = { 0 };
|
||||
int i;
|
||||
|
||||
r1info = create_raid1(params);
|
||||
|
||||
raid_ch.num_channels = params->num_base_bdevs;
|
||||
raid_ch.base_channel = calloc(params->num_base_bdevs, sizeof(struct spdk_io_channel *));
|
||||
SPDK_CU_ASSERT_FATAL(raid_ch.base_channel != NULL);
|
||||
for (i = 0; i < raid_ch.num_channels; i++) {
|
||||
raid_ch.base_channel[i] = calloc(1, sizeof(*raid_ch.base_channel));
|
||||
}
|
||||
|
||||
raid_ch.module_channel = raid1_get_io_channel(r1info->raid_bdev);
|
||||
SPDK_CU_ASSERT_FATAL(raid_ch.module_channel);
|
||||
|
||||
test_fn(r1info->raid_bdev, &raid_ch);
|
||||
|
||||
spdk_put_io_channel(raid_ch.module_channel);
|
||||
poll_threads();
|
||||
|
||||
for (i = 0; i < raid_ch.num_channels; i++) {
|
||||
free(raid_ch.base_channel[i]);
|
||||
}
|
||||
free(raid_ch.base_channel);
|
||||
|
||||
delete_raid1(r1info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
__test_raid1_read_balancing(struct raid_bdev *raid_bdev, struct raid_bdev_io_channel *raid_ch)
|
||||
{
|
||||
struct raid1_info *r1info = raid_bdev->module_private;
|
||||
struct raid_bdev_io *raid_io;
|
||||
struct raid1_io_channel *raid1_ch = spdk_io_channel_get_ctx(raid_ch->module_channel);
|
||||
uint8_t overloaded_ch_idx = 0;
|
||||
uint64_t big_io_blocks = 256;
|
||||
uint64_t small_io_blocks = 4;
|
||||
bool found_greater = false;
|
||||
|
||||
raid_io = get_raid_io(r1info, raid_ch, SPDK_BDEV_IO_TYPE_READ, big_io_blocks);
|
||||
raid1_submit_rw_request(raid_io);
|
||||
raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_SUCCESS);
|
||||
overloaded_ch_idx = raid1_ch->base_bdev_read_idx;
|
||||
|
||||
do {
|
||||
raid_io = get_raid_io(r1info, raid_ch, SPDK_BDEV_IO_TYPE_READ, small_io_blocks);
|
||||
raid1_submit_rw_request(raid_io);
|
||||
raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_SUCCESS);
|
||||
} while (raid1_ch->base_bdev_read_idx != overloaded_ch_idx);
|
||||
|
||||
for (uint8_t i = 0; i < raid_ch->num_channels; i++) {
|
||||
if (i == overloaded_ch_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (raid1_ch->base_bdev_read_bw[i] >= raid1_ch->base_bdev_read_bw[overloaded_ch_idx] -
|
||||
small_io_blocks) {
|
||||
found_greater = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CU_ASSERT_TRUE(found_greater);
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid1_read_balancing(void)
|
||||
{
|
||||
run_for_each_raid1_config(__test_raid1_read_balancing);
|
||||
}
|
||||
|
||||
static void
|
||||
__test_raid1_read_balancing_limit_reset(struct raid_bdev *raid_bdev,
|
||||
struct raid_bdev_io_channel *raid_ch)
|
||||
{
|
||||
struct raid1_info *r1info = raid_bdev->module_private;
|
||||
struct raid_bdev_io *raid_io;
|
||||
struct raid1_io_channel *raid1_ch = spdk_io_channel_get_ctx(raid_ch->module_channel);
|
||||
uint64_t read_io_blocks = 64;
|
||||
|
||||
raid1_ch->base_bdev_max_read_bw = UINT64_MAX - (read_io_blocks / 2);
|
||||
for (uint8_t i = 0; i < raid_ch->num_channels; i++) {
|
||||
raid1_ch->base_bdev_read_bw[i] = UINT64_MAX - (read_io_blocks / 2);
|
||||
}
|
||||
|
||||
raid_io = get_raid_io(r1info, raid_ch, SPDK_BDEV_IO_TYPE_READ, read_io_blocks);
|
||||
raid1_submit_rw_request(raid_io);
|
||||
raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_SUCCESS);
|
||||
|
||||
for (uint8_t i = 0; i < raid_ch->num_channels; i++) {
|
||||
if (i == raid1_ch->base_bdev_read_idx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(raid1_ch->base_bdev_read_bw[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid1_read_balancing_limit_reset(void)
|
||||
{
|
||||
run_for_each_raid1_config(__test_raid1_read_balancing_limit_reset);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -283,11 +133,6 @@ main(int argc, char **argv)
|
||||
|
||||
suite = CU_add_suite("raid1", test_setup, test_cleanup);
|
||||
CU_ADD_TEST(suite, test_raid1_start);
|
||||
CU_ADD_TEST(suite, test_raid1_read_balancing);
|
||||
CU_ADD_TEST(suite, test_raid1_read_balancing_limit_reset);
|
||||
|
||||
allocate_threads(1);
|
||||
set_thread(0);
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
|
@ -6,27 +6,15 @@
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk_cunit.h"
|
||||
#include "spdk/env.h"
|
||||
#include "spdk/xor.h"
|
||||
|
||||
#include "common/lib/ut_multithread.c"
|
||||
|
||||
#include "bdev/raid/raid5f.c"
|
||||
#include "../common.c"
|
||||
|
||||
static void *g_accel_p = (void *)0xdeadbeaf;
|
||||
static bool g_test_degraded;
|
||||
|
||||
DEFINE_STUB_V(raid_bdev_module_list_add, (struct raid_bdev_module *raid_module));
|
||||
DEFINE_STUB(spdk_bdev_get_buf_align, size_t, (const struct spdk_bdev *bdev), 0);
|
||||
DEFINE_STUB_V(raid_bdev_module_stop_done, (struct raid_bdev *raid_bdev));
|
||||
DEFINE_STUB(accel_channel_create, int, (void *io_device, void *ctx_buf), 0);
|
||||
DEFINE_STUB_V(accel_channel_destroy, (void *io_device, void *ctx_buf));
|
||||
|
||||
struct spdk_io_channel *
|
||||
spdk_accel_get_io_channel(void)
|
||||
{
|
||||
return spdk_get_io_channel(g_accel_p);
|
||||
}
|
||||
|
||||
void *
|
||||
spdk_bdev_io_get_md_buf(struct spdk_bdev_io *bdev_io)
|
||||
@ -40,38 +28,6 @@ spdk_bdev_get_md_size(const struct spdk_bdev *bdev)
|
||||
return bdev->md_len;
|
||||
}
|
||||
|
||||
struct xor_ctx {
|
||||
spdk_accel_completion_cb cb_fn;
|
||||
void *cb_arg;
|
||||
};
|
||||
|
||||
static void
|
||||
finish_xor(void *_ctx)
|
||||
{
|
||||
struct xor_ctx *ctx = _ctx;
|
||||
|
||||
ctx->cb_fn(ctx->cb_arg, 0);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_accel_submit_xor(struct spdk_io_channel *ch, void *dst, void **sources, uint32_t nsrcs,
|
||||
uint64_t nbytes, spdk_accel_completion_cb cb_fn, void *cb_arg)
|
||||
{
|
||||
struct xor_ctx *ctx;
|
||||
|
||||
ctx = malloc(sizeof(*ctx));
|
||||
SPDK_CU_ASSERT_FATAL(ctx != NULL);
|
||||
ctx->cb_fn = cb_fn;
|
||||
ctx->cb_arg = cb_arg;
|
||||
SPDK_CU_ASSERT_FATAL(spdk_xor_gen(dst, sources, nsrcs, nbytes) == 0);
|
||||
|
||||
spdk_thread_send_msg(spdk_get_thread(), finish_xor, ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
raid_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status)
|
||||
{
|
||||
@ -101,21 +57,8 @@ raid_bdev_io_complete_part(struct raid_bdev_io *raid_io, uint64_t completed,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_accel(void)
|
||||
{
|
||||
spdk_io_device_register(g_accel_p, accel_channel_create, accel_channel_destroy,
|
||||
sizeof(int), "accel_p");
|
||||
}
|
||||
|
||||
static void
|
||||
fini_accel(void)
|
||||
{
|
||||
spdk_io_device_unregister(g_accel_p, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
test_suite_init(void)
|
||||
test_setup(void)
|
||||
{
|
||||
uint8_t num_base_bdevs_values[] = { 3, 4, 5 };
|
||||
uint64_t base_bdev_blockcnt_values[] = { 1, 1024, 1024 * 1024 };
|
||||
@ -162,25 +105,16 @@ test_suite_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
init_accel();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_suite_cleanup(void)
|
||||
test_cleanup(void)
|
||||
{
|
||||
fini_accel();
|
||||
raid_test_params_free();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_setup(void)
|
||||
{
|
||||
g_test_degraded = false;
|
||||
}
|
||||
|
||||
static struct raid5f_info *
|
||||
create_raid5f(struct raid_params *params)
|
||||
{
|
||||
@ -237,9 +171,7 @@ struct raid_io_info {
|
||||
struct raid5f_info *r5f_info;
|
||||
struct raid_bdev_io_channel *raid_ch;
|
||||
enum spdk_bdev_io_type io_type;
|
||||
uint64_t stripe_index;
|
||||
uint64_t offset_blocks;
|
||||
uint64_t stripe_offset_blocks;
|
||||
uint64_t num_blocks;
|
||||
void *src_buf;
|
||||
void *dest_buf;
|
||||
@ -252,9 +184,9 @@ struct raid_io_info {
|
||||
void *parity_md_buf;
|
||||
void *reference_md_parity;
|
||||
size_t parity_md_buf_size;
|
||||
void *degraded_buf;
|
||||
void *degraded_md_buf;
|
||||
enum spdk_bdev_io_status status;
|
||||
bool failed;
|
||||
int remaining;
|
||||
TAILQ_HEAD(, spdk_bdev_io) bdev_io_queue;
|
||||
TAILQ_HEAD(, spdk_bdev_io_wait_entry) bdev_io_wait_queue;
|
||||
struct {
|
||||
@ -294,20 +226,31 @@ raid_bdev_io_completion_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_
|
||||
spdk_bdev_free_io(bdev_io);
|
||||
|
||||
if (!success) {
|
||||
io_info->status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||
} else {
|
||||
io_info->status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||
io_info->failed = true;
|
||||
}
|
||||
|
||||
if (--io_info->remaining == 0) {
|
||||
if (io_info->failed) {
|
||||
io_info->status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||
} else {
|
||||
io_info->status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct raid_bdev_io *
|
||||
get_raid_io(struct raid_io_info *io_info)
|
||||
get_raid_io(struct raid_io_info *io_info, uint64_t offset_blocks_split, uint64_t num_blocks)
|
||||
{
|
||||
struct spdk_bdev_io *bdev_io;
|
||||
struct raid_bdev_io *raid_io;
|
||||
struct raid_bdev *raid_bdev = io_info->r5f_info->raid_bdev;
|
||||
uint32_t blocklen = raid_bdev->bdev.blocklen;
|
||||
struct test_raid_bdev_io *test_raid_bdev_io;
|
||||
void *src_buf = io_info->src_buf + offset_blocks_split * blocklen;
|
||||
void *dest_buf = io_info->dest_buf + offset_blocks_split * blocklen;
|
||||
|
||||
void *src_md_buf = io_info->src_md_buf + offset_blocks_split * raid_bdev->bdev.md_len;
|
||||
void *dest_md_buf = io_info->dest_md_buf + offset_blocks_split * raid_bdev->bdev.md_len;
|
||||
|
||||
test_raid_bdev_io = calloc(1, sizeof(*test_raid_bdev_io));
|
||||
SPDK_CU_ASSERT_FATAL(test_raid_bdev_io != NULL);
|
||||
@ -316,8 +259,8 @@ get_raid_io(struct raid_io_info *io_info)
|
||||
bdev_io = (struct spdk_bdev_io *)test_raid_bdev_io->bdev_io_buf;
|
||||
bdev_io->bdev = &raid_bdev->bdev;
|
||||
bdev_io->type = io_info->io_type;
|
||||
bdev_io->u.bdev.offset_blocks = io_info->offset_blocks;
|
||||
bdev_io->u.bdev.num_blocks = io_info->num_blocks;
|
||||
bdev_io->u.bdev.offset_blocks = io_info->offset_blocks + offset_blocks_split;
|
||||
bdev_io->u.bdev.num_blocks = num_blocks;
|
||||
bdev_io->internal.cb = raid_bdev_io_completion_cb;
|
||||
bdev_io->internal.caller_ctx = io_info;
|
||||
|
||||
@ -329,20 +272,22 @@ get_raid_io(struct raid_io_info *io_info)
|
||||
test_raid_bdev_io->io_info = io_info;
|
||||
|
||||
if (io_info->io_type == SPDK_BDEV_IO_TYPE_READ) {
|
||||
test_raid_bdev_io->buf = io_info->src_buf;
|
||||
test_raid_bdev_io->buf_md = io_info->src_md_buf;
|
||||
bdev_io->iov.iov_base = io_info->dest_buf;
|
||||
bdev_io->u.bdev.md_buf = io_info->dest_md_buf;
|
||||
test_raid_bdev_io->buf = src_buf;
|
||||
test_raid_bdev_io->buf_md = src_md_buf;
|
||||
bdev_io->u.bdev.md_buf = dest_md_buf;
|
||||
bdev_io->iov.iov_base = dest_buf;
|
||||
} else {
|
||||
test_raid_bdev_io->buf = io_info->dest_buf;
|
||||
test_raid_bdev_io->buf_md = io_info->dest_md_buf;
|
||||
bdev_io->iov.iov_base = io_info->src_buf;
|
||||
bdev_io->u.bdev.md_buf = io_info->src_md_buf;
|
||||
test_raid_bdev_io->buf = dest_buf;
|
||||
test_raid_bdev_io->buf_md = dest_md_buf;
|
||||
bdev_io->u.bdev.md_buf = src_md_buf;
|
||||
bdev_io->iov.iov_base = src_buf;
|
||||
}
|
||||
|
||||
bdev_io->u.bdev.iovs = &bdev_io->iov;
|
||||
bdev_io->u.bdev.iovcnt = 1;
|
||||
bdev_io->iov.iov_len = io_info->num_blocks * blocklen;
|
||||
bdev_io->iov.iov_len = num_blocks * blocklen;
|
||||
|
||||
io_info->remaining++;
|
||||
|
||||
return raid_io;
|
||||
}
|
||||
@ -398,8 +343,6 @@ process_io_completions(struct raid_io_info *io_info)
|
||||
bdev_io->internal.cb(bdev_io, success, bdev_io->internal.caller_ctx);
|
||||
}
|
||||
|
||||
poll_threads();
|
||||
|
||||
if (io_info->error.type == TEST_BDEV_ERROR_NOMEM) {
|
||||
struct spdk_bdev_io_wait_entry *waitq_entry, *tmp;
|
||||
struct spdk_bdev *enomem_bdev = io_info->error.bdev;
|
||||
@ -435,30 +378,41 @@ spdk_bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_chan
|
||||
struct test_raid_bdev_io *test_raid_bdev_io;
|
||||
struct raid_io_info *io_info;
|
||||
struct raid_bdev *raid_bdev;
|
||||
uint64_t stripe_idx_off;
|
||||
uint8_t data_chunk_idx;
|
||||
uint64_t data_offset;
|
||||
void *dest_buf, *dest_md_buf;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(cb == raid5f_chunk_complete_bdev_io);
|
||||
SPDK_CU_ASSERT_FATAL(cb == raid5f_chunk_write_complete_bdev_io);
|
||||
SPDK_CU_ASSERT_FATAL(iovcnt == 1);
|
||||
|
||||
stripe_req = raid5f_chunk_stripe_req(chunk);
|
||||
test_raid_bdev_io = (struct test_raid_bdev_io *)spdk_bdev_io_from_ctx(stripe_req->raid_io);
|
||||
io_info = test_raid_bdev_io->io_info;
|
||||
|
||||
raid_bdev = io_info->r5f_info->raid_bdev;
|
||||
|
||||
stripe_idx_off = offset_blocks / raid_bdev->strip_size -
|
||||
io_info->offset_blocks / io_info->r5f_info->stripe_blocks;
|
||||
|
||||
if (chunk == stripe_req->parity_chunk) {
|
||||
if (io_info->parity_buf == NULL) {
|
||||
goto submit;
|
||||
}
|
||||
dest_buf = io_info->parity_buf;
|
||||
data_offset = stripe_idx_off * raid_bdev->strip_size_kb * 1024;
|
||||
dest_buf = io_info->parity_buf + data_offset;
|
||||
|
||||
if (md_buf != NULL) {
|
||||
dest_md_buf = io_info->parity_md_buf;
|
||||
data_offset = DATA_OFFSET_TO_MD_OFFSET(raid_bdev, data_offset);
|
||||
dest_md_buf = io_info->parity_md_buf + data_offset;
|
||||
}
|
||||
} else {
|
||||
data_chunk_idx = chunk < stripe_req->parity_chunk ? chunk->index : chunk->index - 1;
|
||||
data_offset = data_chunk_idx * raid_bdev->strip_size * raid_bdev->bdev.blocklen;
|
||||
data_offset = (stripe_idx_off * io_info->r5f_info->stripe_blocks +
|
||||
data_chunk_idx * raid_bdev->strip_size) *
|
||||
raid_bdev->bdev.blocklen;
|
||||
dest_buf = test_raid_bdev_io->buf + data_offset;
|
||||
|
||||
if (md_buf != NULL) {
|
||||
data_offset = DATA_OFFSET_TO_MD_OFFSET(raid_bdev, data_offset);
|
||||
dest_md_buf = test_raid_bdev_io->buf_md + data_offset;
|
||||
@ -474,44 +428,6 @@ submit:
|
||||
return submit_io(io_info, desc, cb, cb_arg);
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_bdev_readv_blocks_degraded(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
struct iovec *iov, int iovcnt,
|
||||
uint64_t offset_blocks, uint64_t num_blocks,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
struct chunk *chunk = cb_arg;
|
||||
struct stripe_request *stripe_req;
|
||||
struct test_raid_bdev_io *test_raid_bdev_io;
|
||||
struct raid_io_info *io_info;
|
||||
struct raid_bdev *raid_bdev;
|
||||
uint8_t data_chunk_idx;
|
||||
void *buf;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(cb == raid5f_chunk_complete_bdev_io);
|
||||
SPDK_CU_ASSERT_FATAL(iovcnt == 1);
|
||||
|
||||
stripe_req = raid5f_chunk_stripe_req(chunk);
|
||||
test_raid_bdev_io = (struct test_raid_bdev_io *)spdk_bdev_io_from_ctx(stripe_req->raid_io);
|
||||
io_info = test_raid_bdev_io->io_info;
|
||||
raid_bdev = io_info->r5f_info->raid_bdev;
|
||||
|
||||
if (chunk == stripe_req->parity_chunk) {
|
||||
buf = io_info->reference_parity;
|
||||
} else {
|
||||
data_chunk_idx = chunk < stripe_req->parity_chunk ? chunk->index : chunk->index - 1;
|
||||
buf = io_info->degraded_buf +
|
||||
data_chunk_idx * raid_bdev->strip_size * raid_bdev->bdev.blocklen;
|
||||
}
|
||||
|
||||
buf += (offset_blocks % raid_bdev->strip_size) * raid_bdev->bdev.blocklen;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(num_blocks * raid_bdev->bdev.blocklen <= iov->iov_len);
|
||||
memcpy(iov->iov_base, buf, num_blocks * raid_bdev->bdev.blocklen);
|
||||
|
||||
return submit_io(io_info, desc, cb, cb_arg);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||
struct iovec *iov, int iovcnt,
|
||||
@ -544,16 +460,11 @@ spdk_bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_chann
|
||||
struct raid_bdev_io *raid_io = cb_arg;
|
||||
struct test_raid_bdev_io *test_raid_bdev_io;
|
||||
|
||||
if (cb == raid5f_chunk_complete_bdev_io) {
|
||||
return spdk_bdev_readv_blocks_degraded(desc, ch, iov, iovcnt, offset_blocks, num_blocks, cb,
|
||||
cb_arg);
|
||||
}
|
||||
|
||||
test_raid_bdev_io = (struct test_raid_bdev_io *)spdk_bdev_io_from_ctx(raid_io);
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(cb == raid5f_chunk_read_complete);
|
||||
SPDK_CU_ASSERT_FATAL(iovcnt == 1);
|
||||
|
||||
test_raid_bdev_io = (struct test_raid_bdev_io *)spdk_bdev_io_from_ctx(raid_io);
|
||||
|
||||
memcpy(iov->iov_base, test_raid_bdev_io->buf, iov->iov_len);
|
||||
if (md_buf != NULL) {
|
||||
memcpy(md_buf, test_raid_bdev_io->buf_md, DATA_OFFSET_TO_MD_OFFSET(raid_io->raid_bdev,
|
||||
@ -601,45 +512,12 @@ test_raid5f_write_request(struct raid_io_info *io_info)
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(io_info->num_blocks / io_info->r5f_info->stripe_blocks == 1);
|
||||
|
||||
raid_io = get_raid_io(io_info);
|
||||
raid_io = get_raid_io(io_info, 0, io_info->num_blocks);
|
||||
|
||||
raid5f_submit_rw_request(raid_io);
|
||||
|
||||
poll_threads();
|
||||
|
||||
process_io_completions(io_info);
|
||||
|
||||
if (g_test_degraded) {
|
||||
struct raid_bdev *raid_bdev = io_info->r5f_info->raid_bdev;
|
||||
uint8_t p_idx;
|
||||
uint8_t i;
|
||||
off_t offset;
|
||||
uint32_t strip_len;
|
||||
|
||||
for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
|
||||
if (io_info->raid_ch->base_channel[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(i != raid_bdev->num_base_bdevs);
|
||||
|
||||
p_idx = raid5f_stripe_parity_chunk_index(raid_bdev, io_info->stripe_index);
|
||||
|
||||
if (i == p_idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (i >= p_idx) {
|
||||
i--;
|
||||
}
|
||||
|
||||
strip_len = raid_bdev->strip_size_kb * 1024;
|
||||
offset = i * strip_len;
|
||||
|
||||
memcpy(io_info->dest_buf + offset, io_info->src_buf + offset, strip_len);
|
||||
}
|
||||
|
||||
if (io_info->status == SPDK_BDEV_IO_STATUS_SUCCESS) {
|
||||
if (io_info->parity_buf) {
|
||||
CU_ASSERT(memcmp(io_info->parity_buf, io_info->reference_parity,
|
||||
@ -655,13 +533,22 @@ test_raid5f_write_request(struct raid_io_info *io_info)
|
||||
static void
|
||||
test_raid5f_read_request(struct raid_io_info *io_info)
|
||||
{
|
||||
struct raid_bdev_io *raid_io;
|
||||
uint32_t strip_size = io_info->r5f_info->raid_bdev->strip_size;
|
||||
uint64_t num_blocks = io_info->num_blocks;
|
||||
uint64_t offset_blocks_split = 0;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(io_info->num_blocks <= io_info->r5f_info->raid_bdev->strip_size);
|
||||
while (num_blocks) {
|
||||
uint64_t chunk_offset = offset_blocks_split % strip_size;
|
||||
uint64_t num_blocks_split = spdk_min(num_blocks, strip_size - chunk_offset);
|
||||
struct raid_bdev_io *raid_io;
|
||||
|
||||
raid_io = get_raid_io(io_info);
|
||||
raid_io = get_raid_io(io_info, offset_blocks_split, num_blocks_split);
|
||||
|
||||
raid5f_submit_rw_request(raid_io);
|
||||
raid5f_submit_rw_request(raid_io);
|
||||
|
||||
num_blocks -= num_blocks_split;
|
||||
offset_blocks_split += num_blocks_split;
|
||||
}
|
||||
|
||||
process_io_completions(io_info);
|
||||
}
|
||||
@ -677,14 +564,12 @@ deinit_io_info(struct raid_io_info *io_info)
|
||||
free(io_info->reference_parity);
|
||||
free(io_info->parity_md_buf);
|
||||
free(io_info->reference_md_parity);
|
||||
free(io_info->degraded_buf);
|
||||
free(io_info->degraded_md_buf);
|
||||
}
|
||||
|
||||
static void
|
||||
init_io_info(struct raid_io_info *io_info, struct raid5f_info *r5f_info,
|
||||
struct raid_bdev_io_channel *raid_ch, enum spdk_bdev_io_type io_type,
|
||||
uint64_t stripe_index, uint64_t stripe_offset_blocks, uint64_t num_blocks)
|
||||
uint64_t offset_blocks, uint64_t num_blocks)
|
||||
{
|
||||
struct raid_bdev *raid_bdev = r5f_info->raid_bdev;
|
||||
uint32_t blocklen = raid_bdev->bdev.blocklen;
|
||||
@ -695,8 +580,6 @@ init_io_info(struct raid_io_info *io_info, struct raid5f_info *r5f_info,
|
||||
uint64_t block;
|
||||
uint64_t i;
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(stripe_offset_blocks < r5f_info->stripe_blocks);
|
||||
|
||||
memset(io_info, 0, sizeof(*io_info));
|
||||
|
||||
if (buf_size) {
|
||||
@ -734,9 +617,7 @@ init_io_info(struct raid_io_info *io_info, struct raid5f_info *r5f_info,
|
||||
io_info->r5f_info = r5f_info;
|
||||
io_info->raid_ch = raid_ch;
|
||||
io_info->io_type = io_type;
|
||||
io_info->stripe_index = stripe_index;
|
||||
io_info->offset_blocks = stripe_index * r5f_info->stripe_blocks + stripe_offset_blocks;
|
||||
io_info->stripe_offset_blocks = stripe_offset_blocks;
|
||||
io_info->offset_blocks = offset_blocks;
|
||||
io_info->num_blocks = num_blocks;
|
||||
io_info->src_buf = src_buf;
|
||||
io_info->dest_buf = dest_buf;
|
||||
@ -750,79 +631,49 @@ init_io_info(struct raid_io_info *io_info, struct raid5f_info *r5f_info,
|
||||
}
|
||||
|
||||
static void
|
||||
io_info_setup_parity(struct raid_io_info *io_info, void *src, void *src_md)
|
||||
io_info_setup_parity(struct raid_io_info *io_info)
|
||||
{
|
||||
struct raid5f_info *r5f_info = io_info->r5f_info;
|
||||
struct raid_bdev *raid_bdev = r5f_info->raid_bdev;
|
||||
uint32_t blocklen = raid_bdev->bdev.blocklen;
|
||||
uint64_t num_stripes = io_info->num_blocks / r5f_info->stripe_blocks;
|
||||
size_t strip_len = raid_bdev->strip_size * blocklen;
|
||||
unsigned i;
|
||||
size_t strip_md_len = raid_bdev->strip_size * raid_bdev->bdev.md_len;
|
||||
void *src = io_info->src_buf;
|
||||
void *dest;
|
||||
unsigned i, j;
|
||||
|
||||
io_info->parity_buf_size = strip_len;
|
||||
io_info->parity_buf_size = num_stripes * strip_len;
|
||||
io_info->parity_buf = calloc(1, io_info->parity_buf_size);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->parity_buf != NULL);
|
||||
|
||||
io_info->reference_parity = calloc(1, io_info->parity_buf_size);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->reference_parity != NULL);
|
||||
|
||||
for (i = 0; i < raid5f_stripe_data_chunks_num(raid_bdev); i++) {
|
||||
xor_block(io_info->reference_parity, src, strip_len);
|
||||
src += strip_len;
|
||||
}
|
||||
|
||||
if (src_md) {
|
||||
size_t strip_md_len = raid_bdev->strip_size * raid_bdev->bdev.md_len;
|
||||
|
||||
io_info->parity_md_buf_size = strip_md_len;
|
||||
io_info->parity_md_buf = calloc(1, io_info->parity_md_buf_size);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->parity_md_buf != NULL);
|
||||
|
||||
io_info->reference_md_parity = calloc(1, io_info->parity_md_buf_size);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->reference_md_parity != NULL);
|
||||
|
||||
for (i = 0; i < raid5f_stripe_data_chunks_num(raid_bdev); i++) {
|
||||
xor_block(io_info->reference_md_parity, src_md, strip_md_len);
|
||||
src_md += strip_md_len;
|
||||
dest = io_info->reference_parity;
|
||||
for (i = 0; i < num_stripes; i++) {
|
||||
for (j = 0; j < raid5f_stripe_data_chunks_num(raid_bdev); j++) {
|
||||
xor_block(dest, src, strip_len);
|
||||
src += strip_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
io_info_setup_degraded(struct raid_io_info *io_info)
|
||||
{
|
||||
struct raid5f_info *r5f_info = io_info->r5f_info;
|
||||
struct raid_bdev *raid_bdev = r5f_info->raid_bdev;
|
||||
uint32_t blocklen = raid_bdev->bdev.blocklen;
|
||||
uint32_t md_len = raid_bdev->bdev.md_len;
|
||||
size_t stripe_len = r5f_info->stripe_blocks * blocklen;
|
||||
size_t stripe_md_len = r5f_info->stripe_blocks * md_len;
|
||||
|
||||
io_info->degraded_buf = malloc(stripe_len);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->degraded_buf != NULL);
|
||||
|
||||
memset(io_info->degraded_buf, 0xab, stripe_len);
|
||||
|
||||
memcpy(io_info->degraded_buf + io_info->stripe_offset_blocks * blocklen,
|
||||
io_info->src_buf, io_info->num_blocks * blocklen);
|
||||
|
||||
if (stripe_md_len != 0) {
|
||||
io_info->degraded_md_buf = malloc(stripe_md_len);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->degraded_md_buf != NULL);
|
||||
|
||||
memset(io_info->degraded_md_buf, 0xab, stripe_md_len);
|
||||
|
||||
memcpy(io_info->degraded_md_buf + io_info->stripe_offset_blocks * md_len,
|
||||
io_info->src_md_buf, io_info->num_blocks * md_len);
|
||||
dest += strip_len;
|
||||
}
|
||||
|
||||
io_info_setup_parity(io_info, io_info->degraded_buf, io_info->degraded_md_buf);
|
||||
io_info->parity_md_buf_size = num_stripes * strip_md_len;
|
||||
io_info->parity_md_buf = calloc(1, io_info->parity_md_buf_size);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->parity_md_buf != NULL);
|
||||
|
||||
memset(io_info->degraded_buf + io_info->stripe_offset_blocks * blocklen,
|
||||
0xcd, io_info->num_blocks * blocklen);
|
||||
io_info->reference_md_parity = calloc(1, io_info->parity_md_buf_size);
|
||||
SPDK_CU_ASSERT_FATAL(io_info->reference_md_parity != NULL);
|
||||
|
||||
if (stripe_md_len != 0) {
|
||||
memset(io_info->degraded_md_buf + io_info->stripe_offset_blocks * md_len,
|
||||
0xcd, io_info->num_blocks * md_len);
|
||||
src = io_info->src_md_buf;
|
||||
dest = io_info->reference_md_parity;
|
||||
for (i = 0; i < num_stripes; i++) {
|
||||
for (j = 0; j < raid5f_stripe_data_chunks_num(raid_bdev); j++) {
|
||||
xor_block(dest, src, strip_md_len);
|
||||
src += strip_md_len;
|
||||
}
|
||||
dest += strip_md_len;
|
||||
}
|
||||
}
|
||||
|
||||
@ -831,19 +682,17 @@ test_raid5f_submit_rw_request(struct raid5f_info *r5f_info, struct raid_bdev_io_
|
||||
enum spdk_bdev_io_type io_type, uint64_t stripe_index, uint64_t stripe_offset_blocks,
|
||||
uint64_t num_blocks)
|
||||
{
|
||||
uint64_t offset_blocks = stripe_index * r5f_info->stripe_blocks + stripe_offset_blocks;
|
||||
struct raid_io_info io_info;
|
||||
|
||||
init_io_info(&io_info, r5f_info, raid_ch, io_type, stripe_index, stripe_offset_blocks, num_blocks);
|
||||
init_io_info(&io_info, r5f_info, raid_ch, io_type, offset_blocks, num_blocks);
|
||||
|
||||
switch (io_type) {
|
||||
case SPDK_BDEV_IO_TYPE_READ:
|
||||
if (g_test_degraded) {
|
||||
io_info_setup_degraded(&io_info);
|
||||
}
|
||||
test_raid5f_read_request(&io_info);
|
||||
break;
|
||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||
io_info_setup_parity(&io_info, io_info.src_buf, io_info.src_md_buf);
|
||||
io_info_setup_parity(&io_info);
|
||||
test_raid5f_write_request(&io_info);
|
||||
break;
|
||||
default:
|
||||
@ -868,7 +717,6 @@ run_for_each_raid5f_config(void (*test_fn)(struct raid_bdev *raid_bdev,
|
||||
RAID_PARAMS_FOR_EACH(params) {
|
||||
struct raid5f_info *r5f_info;
|
||||
struct raid_bdev_io_channel raid_ch = { 0 };
|
||||
int i;
|
||||
|
||||
r5f_info = create_raid5f(params);
|
||||
|
||||
@ -876,13 +724,6 @@ run_for_each_raid5f_config(void (*test_fn)(struct raid_bdev *raid_bdev,
|
||||
raid_ch.base_channel = calloc(params->num_base_bdevs, sizeof(struct spdk_io_channel *));
|
||||
SPDK_CU_ASSERT_FATAL(raid_ch.base_channel != NULL);
|
||||
|
||||
for (i = 0; i < params->num_base_bdevs; i++) {
|
||||
if (g_test_degraded && i == 0) {
|
||||
continue;
|
||||
}
|
||||
raid_ch.base_channel[i] = (void *)1;
|
||||
}
|
||||
|
||||
raid_ch.module_channel = raid5f_get_io_channel(r5f_info->raid_bdev);
|
||||
SPDK_CU_ASSERT_FATAL(raid_ch.module_channel);
|
||||
|
||||
@ -900,31 +741,41 @@ run_for_each_raid5f_config(void (*test_fn)(struct raid_bdev *raid_bdev,
|
||||
#define RAID5F_TEST_FOR_EACH_STRIPE(raid_bdev, i) \
|
||||
for (i = 0; i < spdk_min(raid_bdev->num_base_bdevs, ((struct raid5f_info *)raid_bdev->module_private)->total_stripes); i++)
|
||||
|
||||
struct test_request_conf {
|
||||
uint64_t stripe_offset_blocks;
|
||||
uint64_t num_blocks;
|
||||
};
|
||||
|
||||
static void
|
||||
__test_raid5f_submit_read_request(struct raid_bdev *raid_bdev, struct raid_bdev_io_channel *raid_ch)
|
||||
{
|
||||
struct raid5f_info *r5f_info = raid_bdev->module_private;
|
||||
uint32_t strip_size = raid_bdev->strip_size;
|
||||
uint64_t stripe_index;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < raid5f_stripe_data_chunks_num(raid_bdev); i++) {
|
||||
uint64_t stripe_offset = i * strip_size;
|
||||
struct test_request_conf test_requests[] = {
|
||||
{ 0, 1 },
|
||||
{ 0, strip_size },
|
||||
{ 0, strip_size + 1 },
|
||||
{ 0, r5f_info->stripe_blocks },
|
||||
{ 1, 1 },
|
||||
{ 1, strip_size },
|
||||
{ 1, strip_size + 1 },
|
||||
{ strip_size, 1 },
|
||||
{ strip_size, strip_size },
|
||||
{ strip_size, strip_size + 1 },
|
||||
{ strip_size - 1, 1 },
|
||||
{ strip_size - 1, strip_size },
|
||||
{ strip_size - 1, strip_size + 1 },
|
||||
{ strip_size - 1, 2 },
|
||||
};
|
||||
for (i = 0; i < SPDK_COUNTOF(test_requests); i++) {
|
||||
struct test_request_conf *t = &test_requests[i];
|
||||
uint64_t stripe_index;
|
||||
|
||||
RAID5F_TEST_FOR_EACH_STRIPE(raid_bdev, stripe_index) {
|
||||
test_raid5f_submit_rw_request(r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_READ,
|
||||
stripe_index, stripe_offset, 1);
|
||||
|
||||
test_raid5f_submit_rw_request(r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_READ,
|
||||
stripe_index, stripe_offset, strip_size);
|
||||
|
||||
test_raid5f_submit_rw_request(r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_READ,
|
||||
stripe_index, stripe_offset + strip_size - 1, 1);
|
||||
if (strip_size <= 2) {
|
||||
continue;
|
||||
}
|
||||
test_raid5f_submit_rw_request(r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_READ,
|
||||
stripe_index, stripe_offset + 1, strip_size - 2);
|
||||
stripe_index, t->stripe_offset_blocks, t->num_blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -955,14 +806,14 @@ __test_raid5f_stripe_request_map_iovecs(struct raid_bdev *raid_bdev,
|
||||
size_t iovcnt = SPDK_COUNTOF(iovs);
|
||||
int ret;
|
||||
|
||||
init_io_info(&io_info, r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_WRITE, 0, 0, 0);
|
||||
init_io_info(&io_info, r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_WRITE, 0, 0);
|
||||
|
||||
raid_io = get_raid_io(&io_info);
|
||||
raid_io = get_raid_io(&io_info, 0, 0);
|
||||
bdev_io = spdk_bdev_io_from_ctx(raid_io);
|
||||
bdev_io->u.bdev.iovs = iovs;
|
||||
bdev_io->u.bdev.iovcnt = iovcnt;
|
||||
|
||||
stripe_req = raid5f_stripe_request_alloc(r5ch, STRIPE_REQ_WRITE);
|
||||
stripe_req = raid5f_stripe_request_alloc(r5ch);
|
||||
SPDK_CU_ASSERT_FATAL(stripe_req != NULL);
|
||||
|
||||
stripe_req->parity_chunk = &stripe_req->chunks[raid5f_stripe_data_chunks_num(raid_bdev)];
|
||||
@ -1039,7 +890,7 @@ __test_raid5f_chunk_write_error(struct raid_bdev *raid_bdev, struct raid_bdev_io
|
||||
RAID5F_TEST_FOR_EACH_STRIPE(raid_bdev, stripe_index) {
|
||||
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_bdev_info) {
|
||||
init_io_info(&io_info, r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_WRITE,
|
||||
stripe_index, 0, r5f_info->stripe_blocks);
|
||||
stripe_index * r5f_info->stripe_blocks, r5f_info->stripe_blocks);
|
||||
|
||||
io_info.error.type = error_type;
|
||||
io_info.error.bdev = base_bdev_info->bdev;
|
||||
@ -1099,7 +950,7 @@ __test_raid5f_chunk_write_error_with_enomem(struct raid_bdev *raid_bdev,
|
||||
}
|
||||
|
||||
init_io_info(&io_info, r5f_info, raid_ch, SPDK_BDEV_IO_TYPE_WRITE,
|
||||
stripe_index, 0, r5f_info->stripe_blocks);
|
||||
stripe_index * r5f_info->stripe_blocks, r5f_info->stripe_blocks);
|
||||
|
||||
io_info.error.type = TEST_BDEV_ERROR_NOMEM;
|
||||
io_info.error.bdev = base_bdev_info->bdev;
|
||||
@ -1123,20 +974,6 @@ test_raid5f_chunk_write_error_with_enomem(void)
|
||||
run_for_each_raid5f_config(__test_raid5f_chunk_write_error_with_enomem);
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid5f_submit_full_stripe_write_request_degraded(void)
|
||||
{
|
||||
g_test_degraded = true;
|
||||
run_for_each_raid5f_config(__test_raid5f_submit_full_stripe_write_request);
|
||||
}
|
||||
|
||||
static void
|
||||
test_raid5f_submit_read_request_degraded(void)
|
||||
{
|
||||
g_test_degraded = true;
|
||||
run_for_each_raid5f_config(__test_raid5f_submit_read_request);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -1146,16 +983,13 @@ main(int argc, char **argv)
|
||||
CU_set_error_action(CUEA_ABORT);
|
||||
CU_initialize_registry();
|
||||
|
||||
suite = CU_add_suite_with_setup_and_teardown("raid5f", test_suite_init, test_suite_cleanup,
|
||||
test_setup, NULL);
|
||||
suite = CU_add_suite("raid5f", test_setup, test_cleanup);
|
||||
CU_ADD_TEST(suite, test_raid5f_start);
|
||||
CU_ADD_TEST(suite, test_raid5f_submit_read_request);
|
||||
CU_ADD_TEST(suite, test_raid5f_stripe_request_map_iovecs);
|
||||
CU_ADD_TEST(suite, test_raid5f_submit_full_stripe_write_request);
|
||||
CU_ADD_TEST(suite, test_raid5f_chunk_write_error);
|
||||
CU_ADD_TEST(suite, test_raid5f_chunk_write_error_with_enomem);
|
||||
CU_ADD_TEST(suite, test_raid5f_submit_full_stripe_write_request_degraded);
|
||||
CU_ADD_TEST(suite, test_raid5f_submit_read_request_degraded);
|
||||
|
||||
allocate_threads(1);
|
||||
set_thread(0);
|
||||
|
@ -893,23 +893,6 @@ spdk_lvs_notify_hotplug(const void *esnap_id, uint32_t id_len,
|
||||
return g_bdev_is_missing;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lvol_shallow_copy(struct spdk_lvol *lvol, struct spdk_bs_dev *ext_dev,
|
||||
spdk_lvol_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
if (lvol == NULL) {
|
||||
cb_fn(cb_arg, -ENODEV);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ext_dev == NULL) {
|
||||
cb_fn(cb_arg, -ENODEV);
|
||||
return;
|
||||
}
|
||||
|
||||
cb_fn(cb_arg, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_store_op_complete(void *cb_arg, int lvserrno)
|
||||
{
|
||||
@ -950,12 +933,6 @@ vbdev_lvol_rename_complete(void *cb_arg, int lvolerrno)
|
||||
g_lvolerrno = lvolerrno;
|
||||
}
|
||||
|
||||
static void
|
||||
vbdev_lvol_shallow_copy_complete(void *cb_arg, int lvolerrno)
|
||||
{
|
||||
g_lvolerrno = lvolerrno;
|
||||
}
|
||||
|
||||
static void
|
||||
ut_lvs_destroy(void)
|
||||
{
|
||||
@ -1950,54 +1927,6 @@ ut_lvol_esnap_clone_bad_args(void)
|
||||
g_base_bdev = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ut_lvol_shallow_copy(void)
|
||||
{
|
||||
struct spdk_lvol_store *lvs;
|
||||
int sz = 10;
|
||||
int rc;
|
||||
struct spdk_lvol *lvol = NULL;
|
||||
|
||||
/* Lvol store is successfully created */
|
||||
rc = vbdev_lvs_create("bdev", "lvs", 0, LVS_CLEAR_WITH_UNMAP, 0,
|
||||
lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
||||
CU_ASSERT(g_lvol_store->bs_dev != NULL);
|
||||
lvs = g_lvol_store;
|
||||
|
||||
/* Successful lvol create */
|
||||
g_lvolerrno = -1;
|
||||
rc = vbdev_lvol_create(lvs, "lvol_sc", sz, false, LVOL_CLEAR_WITH_DEFAULT,
|
||||
vbdev_lvol_create_complete,
|
||||
NULL);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
|
||||
lvol = g_lvol;
|
||||
|
||||
/* Successful shallow copy */
|
||||
g_lvolerrno = -1;
|
||||
lvol_already_opened = false;
|
||||
vbdev_lvol_shallow_copy(lvol, "bdev_sc", vbdev_lvol_shallow_copy_complete, NULL);
|
||||
CU_ASSERT(g_lvolerrno == 0);
|
||||
|
||||
/* Shallow copy error with NULL lvol */
|
||||
vbdev_lvol_shallow_copy(NULL, "", vbdev_lvol_shallow_copy_complete, NULL);
|
||||
CU_ASSERT(g_lvolerrno != 0);
|
||||
|
||||
/* Successful lvol destroy */
|
||||
vbdev_lvol_destroy(g_lvol, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(g_lvol == NULL);
|
||||
|
||||
/* Destroy lvol store */
|
||||
vbdev_lvs_destruct(lvs, lvol_store_op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
CU_ASSERT(g_lvol_store == NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -2030,7 +1959,6 @@ main(int argc, char **argv)
|
||||
CU_ADD_TEST(suite, ut_lvol_seek);
|
||||
CU_ADD_TEST(suite, ut_esnap_dev_create);
|
||||
CU_ADD_TEST(suite, ut_lvol_esnap_clone_bad_args);
|
||||
CU_ADD_TEST(suite, ut_lvol_shallow_copy);
|
||||
|
||||
allocate_threads(1);
|
||||
set_thread(0);
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "common/lib/ut_multithread.c"
|
||||
#include "../bs_dev_common.c"
|
||||
#include "thread/thread.c"
|
||||
#include "ext_dev.c"
|
||||
#include "blob/blobstore.c"
|
||||
#include "blob/request.c"
|
||||
#include "blob/zeroes.c"
|
||||
@ -8578,129 +8577,6 @@ blob_is_degraded(void)
|
||||
g_blob->back_bs_dev = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bs_dev_io_complete_cb(struct spdk_io_channel *channel, void *cb_arg, int bserrno)
|
||||
{
|
||||
g_bserrno = bserrno;
|
||||
}
|
||||
|
||||
static void
|
||||
blob_shallow_copy(void)
|
||||
{
|
||||
struct spdk_blob_store *bs = g_bs;
|
||||
struct spdk_blob_opts blob_opts;
|
||||
struct spdk_blob *blob;
|
||||
spdk_blob_id blobid;
|
||||
uint64_t num_clusters = 4;
|
||||
struct spdk_bs_dev *ext_dev;
|
||||
struct spdk_bs_dev_cb_args ext_args;
|
||||
struct spdk_io_channel *bdev_ch, *blob_ch;
|
||||
uint8_t buf1[DEV_BUFFER_BLOCKLEN];
|
||||
uint8_t buf2[DEV_BUFFER_BLOCKLEN];
|
||||
uint64_t io_units_per_cluster;
|
||||
uint64_t offset;
|
||||
|
||||
blob_ch = spdk_bs_alloc_io_channel(bs);
|
||||
SPDK_CU_ASSERT_FATAL(blob_ch != NULL);
|
||||
|
||||
/* Set blob dimension and as thin provisioned */
|
||||
ut_spdk_blob_opts_init(&blob_opts);
|
||||
blob_opts.thin_provision = true;
|
||||
blob_opts.num_clusters = num_clusters;
|
||||
|
||||
/* Create a blob */
|
||||
blob = ut_blob_create_and_open(bs, &blob_opts);
|
||||
SPDK_CU_ASSERT_FATAL(blob != NULL);
|
||||
blobid = spdk_blob_get_id(blob);
|
||||
io_units_per_cluster = bs_io_units_per_cluster(blob);
|
||||
|
||||
/* Write on cluster 2 and 4 of blob */
|
||||
for (offset = io_units_per_cluster; offset < 2 * io_units_per_cluster; offset++) {
|
||||
memset(buf1, offset, DEV_BUFFER_BLOCKLEN);
|
||||
spdk_blob_io_write(blob, blob_ch, buf1, offset, 1, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
}
|
||||
for (offset = 3 * io_units_per_cluster; offset < 4 * io_units_per_cluster; offset++) {
|
||||
memset(buf1, offset, DEV_BUFFER_BLOCKLEN);
|
||||
spdk_blob_io_write(blob, blob_ch, buf1, offset, 1, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
}
|
||||
|
||||
/* Make a snapshot over blob */
|
||||
spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
/* Write on cluster 1 and 3 of blob */
|
||||
for (offset = 0; offset < io_units_per_cluster; offset++) {
|
||||
memset(buf1, offset, DEV_BUFFER_BLOCKLEN);
|
||||
spdk_blob_io_write(blob, blob_ch, buf1, offset, 1, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
}
|
||||
for (offset = 2 * io_units_per_cluster; offset < 3 * io_units_per_cluster; offset++) {
|
||||
memset(buf1, offset, DEV_BUFFER_BLOCKLEN);
|
||||
spdk_blob_io_write(blob, blob_ch, buf1, offset, 1, blob_op_complete, NULL);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
}
|
||||
|
||||
/* Create a spdk_bs_dev */
|
||||
ext_dev = init_ext_dev(num_clusters * 1024 * 1024, DEV_BUFFER_BLOCKLEN);
|
||||
|
||||
/* Make a shallow copy of blob over bdev */
|
||||
spdk_bs_blob_shallow_copy(bs, blob_ch, blobid, ext_dev, blob_op_complete, NULL);
|
||||
CU_ASSERT(spdk_blob_get_shallow_copy_total_clusters(blob) == 2);
|
||||
CU_ASSERT(spdk_blob_get_shallow_copy_copied_clusters(blob) == 0);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
|
||||
/* Read from bdev */
|
||||
/* Only cluster 1 and 3 must be filled */
|
||||
bdev_ch = ext_dev->create_channel(ext_dev);
|
||||
SPDK_CU_ASSERT_FATAL(bdev_ch != NULL);
|
||||
|
||||
ext_args.cb_fn = bs_dev_io_complete_cb;
|
||||
|
||||
for (offset = 0; offset < io_units_per_cluster; offset++) {
|
||||
memset(buf1, offset, DEV_BUFFER_BLOCKLEN);
|
||||
ext_dev->read(ext_dev, bdev_ch, buf2, offset, 1, &ext_args);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(memcmp(buf1, buf2, DEV_BUFFER_BLOCKLEN) == 0);
|
||||
}
|
||||
for (offset = io_units_per_cluster; offset < 2 * io_units_per_cluster; offset++) {
|
||||
memset(buf1, 0, DEV_BUFFER_BLOCKLEN);
|
||||
ext_dev->read(ext_dev, bdev_ch, buf2, offset, 1, &ext_args);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(memcmp(buf1, buf2, DEV_BUFFER_BLOCKLEN) == 0);
|
||||
}
|
||||
for (offset = 2 * io_units_per_cluster; offset < 3 * io_units_per_cluster; offset++) {
|
||||
memset(buf1, offset, DEV_BUFFER_BLOCKLEN);
|
||||
ext_dev->read(ext_dev, bdev_ch, buf2, offset, 1, &ext_args);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(memcmp(buf1, buf2, DEV_BUFFER_BLOCKLEN) == 0);
|
||||
}
|
||||
for (offset = 3 * io_units_per_cluster; offset < 4 * io_units_per_cluster; offset++) {
|
||||
memset(buf1, 0, DEV_BUFFER_BLOCKLEN);
|
||||
ext_dev->read(ext_dev, bdev_ch, buf2, offset, 1, &ext_args);
|
||||
poll_threads();
|
||||
CU_ASSERT(g_bserrno == 0);
|
||||
CU_ASSERT(memcmp(buf1, buf2, DEV_BUFFER_BLOCKLEN) == 0);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
ext_dev->destroy_channel(ext_dev, bdev_ch);
|
||||
ext_dev->destroy(ext_dev);
|
||||
spdk_bs_free_io_channel(blob_ch);
|
||||
ut_blob_close_and_delete(bs, blob);
|
||||
poll_threads();
|
||||
}
|
||||
|
||||
static void
|
||||
suite_bs_setup(void)
|
||||
{
|
||||
@ -8913,7 +8789,6 @@ main(int argc, char **argv)
|
||||
CU_ADD_TEST(suite_esnap_bs, blob_esnap_clone_reload);
|
||||
CU_ADD_TEST(suite_esnap_bs, blob_esnap_hotplug);
|
||||
CU_ADD_TEST(suite_blob, blob_is_degraded);
|
||||
CU_ADD_TEST(suite_bs, blob_shallow_copy);
|
||||
|
||||
allocate_threads(2);
|
||||
set_thread(0);
|
||||
|
@ -1,81 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (C) 2023 SUSE LLC.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "thread/thread_internal.h"
|
||||
#include "spdk/blob.h"
|
||||
|
||||
|
||||
#define EXT_DEV_BUFFER_SIZE (4 * 1024 * 1024)
|
||||
uint8_t g_ext_dev_buffer[EXT_DEV_BUFFER_SIZE];
|
||||
struct spdk_io_channel g_ext_io_channel;
|
||||
|
||||
static struct spdk_io_channel *
|
||||
ext_dev_create_channel(struct spdk_bs_dev *dev)
|
||||
{
|
||||
return &g_ext_io_channel;
|
||||
}
|
||||
|
||||
static void
|
||||
ext_dev_destroy_channel(struct spdk_bs_dev *dev, struct spdk_io_channel *channel)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ext_dev_destroy(struct spdk_bs_dev *dev)
|
||||
{
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
ext_dev_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
|
||||
uint64_t lba, uint32_t lba_count,
|
||||
struct spdk_bs_dev_cb_args *cb_args)
|
||||
{
|
||||
uint64_t offset, length;
|
||||
|
||||
offset = lba * dev->blocklen;
|
||||
length = lba_count * dev->blocklen;
|
||||
SPDK_CU_ASSERT_FATAL(offset + length <= EXT_DEV_BUFFER_SIZE);
|
||||
|
||||
if (length > 0) {
|
||||
memcpy(payload, &g_ext_dev_buffer[offset], length);
|
||||
}
|
||||
|
||||
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ext_dev_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
|
||||
uint64_t lba, uint32_t lba_count,
|
||||
struct spdk_bs_dev_cb_args *cb_args)
|
||||
{
|
||||
uint64_t offset, length;
|
||||
|
||||
offset = lba * dev->blocklen;
|
||||
length = lba_count * dev->blocklen;
|
||||
SPDK_CU_ASSERT_FATAL(offset + length <= EXT_DEV_BUFFER_SIZE);
|
||||
|
||||
memcpy(&g_ext_dev_buffer[offset], payload, length);
|
||||
|
||||
cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0);
|
||||
}
|
||||
|
||||
static struct spdk_bs_dev *
|
||||
init_ext_dev(uint64_t blockcnt, uint32_t blocklen)
|
||||
{
|
||||
struct spdk_bs_dev *dev = calloc(1, sizeof(*dev));
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(dev != NULL);
|
||||
|
||||
dev->create_channel = ext_dev_create_channel;
|
||||
dev->destroy_channel = ext_dev_destroy_channel;
|
||||
dev->destroy = ext_dev_destroy;
|
||||
dev->read = ext_dev_read;
|
||||
dev->write = ext_dev_write;
|
||||
dev->blockcnt = blockcnt;
|
||||
dev->blocklen = blocklen;
|
||||
|
||||
return dev;
|
||||
}
|
@ -59,7 +59,6 @@ int g_resize_rc;
|
||||
int g_inflate_rc;
|
||||
int g_remove_rc;
|
||||
bool g_lvs_rename_blob_open_error = false;
|
||||
bool g_blob_read_only = false;
|
||||
struct spdk_lvol_store *g_lvol_store;
|
||||
struct spdk_lvol *g_lvol;
|
||||
spdk_blob_id g_blobid = 1;
|
||||
@ -137,7 +136,7 @@ spdk_bs_iter_first(struct spdk_blob_store *bs,
|
||||
uint64_t
|
||||
spdk_blob_get_num_clusters(struct spdk_blob *blob)
|
||||
{
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
@ -248,14 +247,6 @@ spdk_blob_is_thin_provisioned(struct spdk_blob *blob)
|
||||
return blob->thin_provisioned;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_blob_shallow_copy(struct spdk_blob_store *bs, struct spdk_io_channel *channel,
|
||||
spdk_blob_id blobid, struct spdk_bs_dev *ext_dev,
|
||||
spdk_blob_op_complete cb_fn, void *cb_arg)
|
||||
{
|
||||
cb_fn(cb_arg, 0);
|
||||
}
|
||||
|
||||
DEFINE_STUB(spdk_bs_get_page_size, uint64_t, (struct spdk_blob_store *bs), BS_PAGE_SIZE);
|
||||
|
||||
int
|
||||
@ -466,12 +457,6 @@ spdk_blob_open_opts_init(struct spdk_blob_open_opts *opts, size_t opts_size)
|
||||
opts->clear_method = BLOB_CLEAR_WITH_DEFAULT;
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_blob_is_read_only(struct spdk_blob *blob)
|
||||
{
|
||||
return g_blob_read_only;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_bs_create_blob(struct spdk_blob_store *bs,
|
||||
spdk_blob_op_with_id_complete cb_fn, void *cb_arg)
|
||||
@ -3313,75 +3298,6 @@ lvol_get_by(void)
|
||||
free_dev(&dev2);
|
||||
}
|
||||
|
||||
static void
|
||||
lvol_shallow_copy(void)
|
||||
{
|
||||
struct lvol_ut_bs_dev bs_dev;
|
||||
struct spdk_lvs_opts opts;
|
||||
struct spdk_bs_dev ext_dev;
|
||||
int rc = 0;
|
||||
|
||||
init_dev(&bs_dev);
|
||||
|
||||
ext_dev.blocklen = DEV_BUFFER_BLOCKLEN;
|
||||
ext_dev.blockcnt = BS_CLUSTER_SIZE / DEV_BUFFER_BLOCKLEN;
|
||||
|
||||
spdk_lvs_opts_init(&opts);
|
||||
snprintf(opts.name, sizeof(opts.name), "lvs");
|
||||
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_init(&bs_dev.bs_dev, &opts, lvol_store_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol_store != NULL);
|
||||
|
||||
spdk_lvol_create(g_lvol_store, "lvol", BS_CLUSTER_SIZE, false, LVOL_CLEAR_WITH_DEFAULT,
|
||||
lvol_op_with_handle_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
SPDK_CU_ASSERT_FATAL(g_lvol != NULL);
|
||||
|
||||
/* Successful shallow copy */
|
||||
g_blob_read_only = true;
|
||||
spdk_lvol_shallow_copy(g_lvol, &ext_dev, op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
|
||||
/* Shallow copy with null lvol */
|
||||
spdk_lvol_shallow_copy(NULL, &ext_dev, op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno != 0);
|
||||
|
||||
/* Shallow copy with null ext_dev */
|
||||
spdk_lvol_shallow_copy(g_lvol, NULL, op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno != 0);
|
||||
|
||||
/* Shallow copy with invalid ext_dev size */
|
||||
ext_dev.blockcnt = 1;
|
||||
spdk_lvol_shallow_copy(g_lvol, &ext_dev, op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno != 0);
|
||||
|
||||
/* Shallow copy with writable lvol */
|
||||
g_blob_read_only = false;
|
||||
spdk_lvol_shallow_copy(g_lvol, &ext_dev, op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno != 0);
|
||||
|
||||
spdk_lvol_close(g_lvol, op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
spdk_lvol_destroy(g_lvol, op_complete, NULL);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
|
||||
g_lvserrno = -1;
|
||||
rc = spdk_lvs_unload(g_lvol_store, op_complete, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(g_lvserrno == 0);
|
||||
g_lvol_store = NULL;
|
||||
|
||||
free_dev(&bs_dev);
|
||||
|
||||
/* Make sure that all references to the io_channel was closed after
|
||||
* shallow copy call
|
||||
*/
|
||||
CU_ASSERT(g_io_channel == NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -3428,7 +3344,6 @@ main(int argc, char **argv)
|
||||
CU_ADD_TEST(suite, lvol_esnap_missing);
|
||||
CU_ADD_TEST(suite, lvol_esnap_hotplug);
|
||||
CU_ADD_TEST(suite, lvol_get_by);
|
||||
CU_ADD_TEST(suite, lvol_shallow_copy);
|
||||
|
||||
allocate_threads(1);
|
||||
set_thread(0);
|
||||
|
@ -1361,7 +1361,7 @@ test_reservation_write_exclusive(void)
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
|
||||
/* Unregister Host C */
|
||||
spdk_uuid_set_null(&g_ns_info.reg_hostid[2]);
|
||||
memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid));
|
||||
|
||||
/* Test Case: Read and Write commands from non-registrant Host C */
|
||||
cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE;
|
||||
@ -1430,7 +1430,7 @@ _test_reservation_write_exclusive_regs_only_and_all_regs(enum spdk_nvme_reservat
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
|
||||
/* Unregister Host C */
|
||||
spdk_uuid_set_null(&g_ns_info.reg_hostid[2]);
|
||||
memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid));
|
||||
|
||||
/* Test Case: Read and Write commands from non-registrant Host C */
|
||||
cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ;
|
||||
@ -1472,7 +1472,7 @@ _test_reservation_exclusive_access_regs_only_and_all_regs(enum spdk_nvme_reserva
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
|
||||
/* Unregister Host B */
|
||||
spdk_uuid_set_null(&g_ns_info.reg_hostid[1]);
|
||||
memset(&g_ns_info.reg_hostid[1], 0, sizeof(struct spdk_uuid));
|
||||
|
||||
/* Test Case: Issue a Read command from Host B */
|
||||
cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ;
|
||||
|
@ -20,7 +20,6 @@ function unittest_bdev() {
|
||||
$valgrind $testdir/lib/bdev/bdev.c/bdev_ut
|
||||
$valgrind $testdir/lib/bdev/nvme/bdev_nvme.c/bdev_nvme_ut
|
||||
$valgrind $testdir/lib/bdev/raid/bdev_raid.c/bdev_raid_ut
|
||||
$valgrind $testdir/lib/bdev/raid/bdev_raid_sb.c/bdev_raid_sb_ut
|
||||
$valgrind $testdir/lib/bdev/raid/concat.c/concat_ut
|
||||
$valgrind $testdir/lib/bdev/raid/raid1.c/raid1_ut
|
||||
$valgrind $testdir/lib/bdev/bdev_zone.c/bdev_zone_ut
|
||||
|
Loading…
Reference in New Issue
Block a user