diff options
| -rw-r--r-- | drivers/block/rbd.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index b673a8dc161d..b51f1c997c1d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -2319,6 +2319,83 @@ out: | |||
| 2319 | return 0; | 2319 | return 0; |
| 2320 | } | 2320 | } |
| 2321 | 2321 | ||
| 2322 | static char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, u32 which) | ||
| 2323 | { | ||
| 2324 | size_t size; | ||
| 2325 | void *reply_buf; | ||
| 2326 | __le64 snap_id; | ||
| 2327 | int ret; | ||
| 2328 | void *p; | ||
| 2329 | void *end; | ||
| 2330 | size_t snap_name_len; | ||
| 2331 | char *snap_name; | ||
| 2332 | |||
| 2333 | size = sizeof (__le32) + RBD_MAX_SNAP_NAME_LEN; | ||
| 2334 | reply_buf = kmalloc(size, GFP_KERNEL); | ||
| 2335 | if (!reply_buf) | ||
| 2336 | return ERR_PTR(-ENOMEM); | ||
| 2337 | |||
| 2338 | snap_id = cpu_to_le64(rbd_dev->header.snapc->snaps[which]); | ||
| 2339 | ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name, | ||
| 2340 | "rbd", "get_snapshot_name", | ||
| 2341 | (char *) &snap_id, sizeof (snap_id), | ||
| 2342 | reply_buf, size, | ||
| 2343 | CEPH_OSD_FLAG_READ, NULL); | ||
| 2344 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); | ||
| 2345 | if (ret < 0) | ||
| 2346 | goto out; | ||
| 2347 | |||
| 2348 | p = reply_buf; | ||
| 2349 | end = (char *) reply_buf + size; | ||
| 2350 | snap_name_len = 0; | ||
| 2351 | snap_name = ceph_extract_encoded_string(&p, end, &snap_name_len, | ||
| 2352 | GFP_KERNEL); | ||
| 2353 | if (IS_ERR(snap_name)) { | ||
| 2354 | ret = PTR_ERR(snap_name); | ||
| 2355 | goto out; | ||
| 2356 | } else { | ||
| 2357 | dout(" snap_id 0x%016llx snap_name = %s\n", | ||
| 2358 | (unsigned long long) le64_to_cpu(snap_id), snap_name); | ||
| 2359 | } | ||
| 2360 | kfree(reply_buf); | ||
| 2361 | |||
| 2362 | return snap_name; | ||
| 2363 | out: | ||
| 2364 | kfree(reply_buf); | ||
| 2365 | |||
| 2366 | return ERR_PTR(ret); | ||
| 2367 | } | ||
| 2368 | |||
| 2369 | static char *rbd_dev_v2_snap_info(struct rbd_device *rbd_dev, u32 which, | ||
| 2370 | u64 *snap_size, u64 *snap_features) | ||
| 2371 | { | ||
| 2372 | __le64 snap_id; | ||
| 2373 | u8 order; | ||
| 2374 | int ret; | ||
| 2375 | |||
| 2376 | snap_id = rbd_dev->header.snapc->snaps[which]; | ||
| 2377 | ret = _rbd_dev_v2_snap_size(rbd_dev, snap_id, &order, snap_size); | ||
| 2378 | if (ret) | ||
| 2379 | return ERR_PTR(ret); | ||
| 2380 | ret = _rbd_dev_v2_snap_features(rbd_dev, snap_id, snap_features); | ||
| 2381 | if (ret) | ||
| 2382 | return ERR_PTR(ret); | ||
| 2383 | |||
| 2384 | return rbd_dev_v2_snap_name(rbd_dev, which); | ||
| 2385 | } | ||
| 2386 | |||
| 2387 | static char *rbd_dev_snap_info(struct rbd_device *rbd_dev, u32 which, | ||
| 2388 | u64 *snap_size, u64 *snap_features) | ||
| 2389 | { | ||
| 2390 | if (rbd_dev->image_format == 1) | ||
| 2391 | return rbd_dev_v1_snap_info(rbd_dev, which, | ||
| 2392 | snap_size, snap_features); | ||
| 2393 | if (rbd_dev->image_format == 2) | ||
| 2394 | return rbd_dev_v2_snap_info(rbd_dev, which, | ||
| 2395 | snap_size, snap_features); | ||
| 2396 | return ERR_PTR(-EINVAL); | ||
| 2397 | } | ||
| 2398 | |||
| 2322 | /* | 2399 | /* |
| 2323 | * Scan the rbd device's current snapshot list and compare it to the | 2400 | * Scan the rbd device's current snapshot list and compare it to the |
| 2324 | * newly-received snapshot context. Remove any existing snapshots | 2401 | * newly-received snapshot context. Remove any existing snapshots |
| @@ -2372,8 +2449,8 @@ static int rbd_dev_snaps_update(struct rbd_device *rbd_dev) | |||
| 2372 | continue; | 2449 | continue; |
| 2373 | } | 2450 | } |
| 2374 | 2451 | ||
| 2375 | snap_name = rbd_dev_v1_snap_info(rbd_dev, index, | 2452 | snap_name = rbd_dev_snap_info(rbd_dev, index, |
| 2376 | &snap_size, &snap_features); | 2453 | &snap_size, &snap_features); |
| 2377 | if (IS_ERR(snap_name)) | 2454 | if (IS_ERR(snap_name)) |
| 2378 | return PTR_ERR(snap_name); | 2455 | return PTR_ERR(snap_name); |
| 2379 | 2456 | ||
