.. | .. |
---|
632 | 632 | static void rbd_dev_remove_parent(struct rbd_device *rbd_dev); |
---|
633 | 633 | |
---|
634 | 634 | static int rbd_dev_refresh(struct rbd_device *rbd_dev); |
---|
635 | | -static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev); |
---|
636 | | -static int rbd_dev_header_info(struct rbd_device *rbd_dev); |
---|
637 | | -static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev); |
---|
| 635 | +static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev, |
---|
| 636 | + struct rbd_image_header *header); |
---|
638 | 637 | static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, |
---|
639 | 638 | u64 snap_id); |
---|
640 | 639 | static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id, |
---|
.. | .. |
---|
1047 | 1046 | RCU_INIT_POINTER(rbd_dev->layout.pool_ns, NULL); |
---|
1048 | 1047 | } |
---|
1049 | 1048 | |
---|
| 1049 | +static void rbd_image_header_cleanup(struct rbd_image_header *header) |
---|
| 1050 | +{ |
---|
| 1051 | + kfree(header->object_prefix); |
---|
| 1052 | + ceph_put_snap_context(header->snapc); |
---|
| 1053 | + kfree(header->snap_sizes); |
---|
| 1054 | + kfree(header->snap_names); |
---|
| 1055 | + |
---|
| 1056 | + memset(header, 0, sizeof(*header)); |
---|
| 1057 | +} |
---|
| 1058 | + |
---|
1050 | 1059 | /* |
---|
1051 | 1060 | * Fill an rbd image header with information from the given format 1 |
---|
1052 | 1061 | * on-disk header. |
---|
1053 | 1062 | */ |
---|
1054 | | -static int rbd_header_from_disk(struct rbd_device *rbd_dev, |
---|
1055 | | - struct rbd_image_header_ondisk *ondisk) |
---|
| 1063 | +static int rbd_header_from_disk(struct rbd_image_header *header, |
---|
| 1064 | + struct rbd_image_header_ondisk *ondisk, |
---|
| 1065 | + bool first_time) |
---|
1056 | 1066 | { |
---|
1057 | | - struct rbd_image_header *header = &rbd_dev->header; |
---|
1058 | | - bool first_time = header->object_prefix == NULL; |
---|
1059 | 1067 | struct ceph_snap_context *snapc; |
---|
1060 | 1068 | char *object_prefix = NULL; |
---|
1061 | 1069 | char *snap_names = NULL; |
---|
.. | .. |
---|
1122 | 1130 | if (first_time) { |
---|
1123 | 1131 | header->object_prefix = object_prefix; |
---|
1124 | 1132 | header->obj_order = ondisk->options.order; |
---|
1125 | | - rbd_init_layout(rbd_dev); |
---|
1126 | | - } else { |
---|
1127 | | - ceph_put_snap_context(header->snapc); |
---|
1128 | | - kfree(header->snap_names); |
---|
1129 | | - kfree(header->snap_sizes); |
---|
1130 | 1133 | } |
---|
1131 | 1134 | |
---|
1132 | 1135 | /* The remaining fields always get updated (when we refresh) */ |
---|
.. | .. |
---|
1397 | 1400 | /* |
---|
1398 | 1401 | * Must be called after rbd_obj_calc_img_extents(). |
---|
1399 | 1402 | */ |
---|
1400 | | -static bool rbd_obj_copyup_enabled(struct rbd_obj_request *obj_req) |
---|
| 1403 | +static void rbd_obj_set_copyup_enabled(struct rbd_obj_request *obj_req) |
---|
1401 | 1404 | { |
---|
1402 | | - if (!obj_req->num_img_extents || |
---|
1403 | | - (rbd_obj_is_entire(obj_req) && |
---|
1404 | | - !obj_req->img_request->snapc->num_snaps)) |
---|
1405 | | - return false; |
---|
| 1405 | + rbd_assert(obj_req->img_request->snapc); |
---|
1406 | 1406 | |
---|
1407 | | - return true; |
---|
| 1407 | + if (obj_req->img_request->op_type == OBJ_OP_DISCARD) { |
---|
| 1408 | + dout("%s %p objno %llu discard\n", __func__, obj_req, |
---|
| 1409 | + obj_req->ex.oe_objno); |
---|
| 1410 | + return; |
---|
| 1411 | + } |
---|
| 1412 | + |
---|
| 1413 | + if (!obj_req->num_img_extents) { |
---|
| 1414 | + dout("%s %p objno %llu not overlapping\n", __func__, obj_req, |
---|
| 1415 | + obj_req->ex.oe_objno); |
---|
| 1416 | + return; |
---|
| 1417 | + } |
---|
| 1418 | + |
---|
| 1419 | + if (rbd_obj_is_entire(obj_req) && |
---|
| 1420 | + !obj_req->img_request->snapc->num_snaps) { |
---|
| 1421 | + dout("%s %p objno %llu entire\n", __func__, obj_req, |
---|
| 1422 | + obj_req->ex.oe_objno); |
---|
| 1423 | + return; |
---|
| 1424 | + } |
---|
| 1425 | + |
---|
| 1426 | + obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED; |
---|
1408 | 1427 | } |
---|
1409 | 1428 | |
---|
1410 | 1429 | static u64 rbd_obj_img_extents_bytes(struct rbd_obj_request *obj_req) |
---|
.. | .. |
---|
1505 | 1524 | static struct ceph_osd_request * |
---|
1506 | 1525 | rbd_obj_add_osd_request(struct rbd_obj_request *obj_req, int num_ops) |
---|
1507 | 1526 | { |
---|
| 1527 | + rbd_assert(obj_req->img_request->snapc); |
---|
1508 | 1528 | return __rbd_obj_add_osd_request(obj_req, obj_req->img_request->snapc, |
---|
1509 | 1529 | num_ops); |
---|
1510 | 1530 | } |
---|
.. | .. |
---|
1641 | 1661 | mutex_init(&img_request->state_mutex); |
---|
1642 | 1662 | } |
---|
1643 | 1663 | |
---|
| 1664 | +/* |
---|
| 1665 | + * Only snap_id is captured here, for reads. For writes, snapshot |
---|
| 1666 | + * context is captured in rbd_img_object_requests() after exclusive |
---|
| 1667 | + * lock is ensured to be held. |
---|
| 1668 | + */ |
---|
1644 | 1669 | static void rbd_img_capture_header(struct rbd_img_request *img_req) |
---|
1645 | 1670 | { |
---|
1646 | 1671 | struct rbd_device *rbd_dev = img_req->rbd_dev; |
---|
1647 | 1672 | |
---|
1648 | 1673 | lockdep_assert_held(&rbd_dev->header_rwsem); |
---|
1649 | 1674 | |
---|
1650 | | - if (rbd_img_is_write(img_req)) |
---|
1651 | | - img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc); |
---|
1652 | | - else |
---|
| 1675 | + if (!rbd_img_is_write(img_req)) |
---|
1653 | 1676 | img_req->snap_id = rbd_dev->spec->snap_id; |
---|
1654 | 1677 | |
---|
1655 | 1678 | if (rbd_dev_parent_get(rbd_dev)) |
---|
.. | .. |
---|
2296 | 2319 | if (ret) |
---|
2297 | 2320 | return ret; |
---|
2298 | 2321 | |
---|
2299 | | - if (rbd_obj_copyup_enabled(obj_req)) |
---|
2300 | | - obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED; |
---|
2301 | | - |
---|
2302 | 2322 | obj_req->write_state = RBD_OBJ_WRITE_START; |
---|
2303 | 2323 | return 0; |
---|
2304 | 2324 | } |
---|
.. | .. |
---|
2404 | 2424 | if (ret) |
---|
2405 | 2425 | return ret; |
---|
2406 | 2426 | |
---|
2407 | | - if (rbd_obj_copyup_enabled(obj_req)) |
---|
2408 | | - obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED; |
---|
2409 | 2427 | if (!obj_req->num_img_extents) { |
---|
2410 | 2428 | obj_req->flags |= RBD_OBJ_FLAG_NOOP_FOR_NONEXISTENT; |
---|
2411 | 2429 | if (rbd_obj_is_entire(obj_req)) |
---|
.. | .. |
---|
3351 | 3369 | case RBD_OBJ_WRITE_START: |
---|
3352 | 3370 | rbd_assert(!*result); |
---|
3353 | 3371 | |
---|
| 3372 | + rbd_obj_set_copyup_enabled(obj_req); |
---|
3354 | 3373 | if (rbd_obj_write_is_noop(obj_req)) |
---|
3355 | 3374 | return true; |
---|
3356 | 3375 | |
---|
.. | .. |
---|
3537 | 3556 | |
---|
3538 | 3557 | static void rbd_img_object_requests(struct rbd_img_request *img_req) |
---|
3539 | 3558 | { |
---|
| 3559 | + struct rbd_device *rbd_dev = img_req->rbd_dev; |
---|
3540 | 3560 | struct rbd_obj_request *obj_req; |
---|
3541 | 3561 | |
---|
3542 | 3562 | rbd_assert(!img_req->pending.result && !img_req->pending.num_pending); |
---|
| 3563 | + rbd_assert(!need_exclusive_lock(img_req) || |
---|
| 3564 | + __rbd_is_lock_owner(rbd_dev)); |
---|
| 3565 | + |
---|
| 3566 | + if (rbd_img_is_write(img_req)) { |
---|
| 3567 | + rbd_assert(!img_req->snapc); |
---|
| 3568 | + down_read(&rbd_dev->header_rwsem); |
---|
| 3569 | + img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc); |
---|
| 3570 | + up_read(&rbd_dev->header_rwsem); |
---|
| 3571 | + } |
---|
3543 | 3572 | |
---|
3544 | 3573 | for_each_obj_request(img_req, obj_req) { |
---|
3545 | 3574 | int result = 0; |
---|
.. | .. |
---|
3557 | 3586 | |
---|
3558 | 3587 | static bool rbd_img_advance(struct rbd_img_request *img_req, int *result) |
---|
3559 | 3588 | { |
---|
3560 | | - struct rbd_device *rbd_dev = img_req->rbd_dev; |
---|
3561 | 3589 | int ret; |
---|
3562 | 3590 | |
---|
3563 | 3591 | again: |
---|
.. | .. |
---|
3577 | 3605 | case RBD_IMG_EXCLUSIVE_LOCK: |
---|
3578 | 3606 | if (*result) |
---|
3579 | 3607 | return true; |
---|
3580 | | - |
---|
3581 | | - rbd_assert(!need_exclusive_lock(img_req) || |
---|
3582 | | - __rbd_is_lock_owner(rbd_dev)); |
---|
3583 | 3608 | |
---|
3584 | 3609 | rbd_img_object_requests(img_req); |
---|
3585 | 3610 | if (!img_req->pending.num_pending) { |
---|
.. | .. |
---|
3718 | 3743 | ret = ceph_cls_lock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc, |
---|
3719 | 3744 | RBD_LOCK_NAME, CEPH_CLS_LOCK_EXCLUSIVE, cookie, |
---|
3720 | 3745 | RBD_LOCK_TAG, "", 0); |
---|
3721 | | - if (ret) |
---|
| 3746 | + if (ret && ret != -EEXIST) |
---|
3722 | 3747 | return ret; |
---|
3723 | 3748 | |
---|
3724 | 3749 | __rbd_lock(rbd_dev, cookie); |
---|
.. | .. |
---|
3892 | 3917 | list_splice_tail_init(&rbd_dev->acquiring_list, &rbd_dev->running_list); |
---|
3893 | 3918 | } |
---|
3894 | 3919 | |
---|
3895 | | -static int get_lock_owner_info(struct rbd_device *rbd_dev, |
---|
3896 | | - struct ceph_locker **lockers, u32 *num_lockers) |
---|
| 3920 | +static bool locker_equal(const struct ceph_locker *lhs, |
---|
| 3921 | + const struct ceph_locker *rhs) |
---|
| 3922 | +{ |
---|
| 3923 | + return lhs->id.name.type == rhs->id.name.type && |
---|
| 3924 | + lhs->id.name.num == rhs->id.name.num && |
---|
| 3925 | + !strcmp(lhs->id.cookie, rhs->id.cookie) && |
---|
| 3926 | + ceph_addr_equal_no_type(&lhs->info.addr, &rhs->info.addr); |
---|
| 3927 | +} |
---|
| 3928 | + |
---|
| 3929 | +static void free_locker(struct ceph_locker *locker) |
---|
| 3930 | +{ |
---|
| 3931 | + if (locker) |
---|
| 3932 | + ceph_free_lockers(locker, 1); |
---|
| 3933 | +} |
---|
| 3934 | + |
---|
| 3935 | +static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev) |
---|
3897 | 3936 | { |
---|
3898 | 3937 | struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; |
---|
| 3938 | + struct ceph_locker *lockers; |
---|
| 3939 | + u32 num_lockers; |
---|
3899 | 3940 | u8 lock_type; |
---|
3900 | 3941 | char *lock_tag; |
---|
3901 | 3942 | int ret; |
---|
.. | .. |
---|
3904 | 3945 | |
---|
3905 | 3946 | ret = ceph_cls_lock_info(osdc, &rbd_dev->header_oid, |
---|
3906 | 3947 | &rbd_dev->header_oloc, RBD_LOCK_NAME, |
---|
3907 | | - &lock_type, &lock_tag, lockers, num_lockers); |
---|
3908 | | - if (ret) |
---|
3909 | | - return ret; |
---|
| 3948 | + &lock_type, &lock_tag, &lockers, &num_lockers); |
---|
| 3949 | + if (ret) { |
---|
| 3950 | + rbd_warn(rbd_dev, "failed to get header lockers: %d", ret); |
---|
| 3951 | + return ERR_PTR(ret); |
---|
| 3952 | + } |
---|
3910 | 3953 | |
---|
3911 | | - if (*num_lockers == 0) { |
---|
| 3954 | + if (num_lockers == 0) { |
---|
3912 | 3955 | dout("%s rbd_dev %p no lockers detected\n", __func__, rbd_dev); |
---|
| 3956 | + lockers = NULL; |
---|
3913 | 3957 | goto out; |
---|
3914 | 3958 | } |
---|
3915 | 3959 | |
---|
3916 | 3960 | if (strcmp(lock_tag, RBD_LOCK_TAG)) { |
---|
3917 | 3961 | rbd_warn(rbd_dev, "locked by external mechanism, tag %s", |
---|
3918 | 3962 | lock_tag); |
---|
3919 | | - ret = -EBUSY; |
---|
3920 | | - goto out; |
---|
| 3963 | + goto err_busy; |
---|
3921 | 3964 | } |
---|
3922 | 3965 | |
---|
3923 | 3966 | if (lock_type == CEPH_CLS_LOCK_SHARED) { |
---|
3924 | 3967 | rbd_warn(rbd_dev, "shared lock type detected"); |
---|
3925 | | - ret = -EBUSY; |
---|
3926 | | - goto out; |
---|
| 3968 | + goto err_busy; |
---|
3927 | 3969 | } |
---|
3928 | 3970 | |
---|
3929 | | - if (strncmp((*lockers)[0].id.cookie, RBD_LOCK_COOKIE_PREFIX, |
---|
| 3971 | + WARN_ON(num_lockers != 1); |
---|
| 3972 | + if (strncmp(lockers[0].id.cookie, RBD_LOCK_COOKIE_PREFIX, |
---|
3930 | 3973 | strlen(RBD_LOCK_COOKIE_PREFIX))) { |
---|
3931 | 3974 | rbd_warn(rbd_dev, "locked by external mechanism, cookie %s", |
---|
3932 | | - (*lockers)[0].id.cookie); |
---|
3933 | | - ret = -EBUSY; |
---|
3934 | | - goto out; |
---|
| 3975 | + lockers[0].id.cookie); |
---|
| 3976 | + goto err_busy; |
---|
3935 | 3977 | } |
---|
3936 | 3978 | |
---|
3937 | 3979 | out: |
---|
3938 | 3980 | kfree(lock_tag); |
---|
3939 | | - return ret; |
---|
| 3981 | + return lockers; |
---|
| 3982 | + |
---|
| 3983 | +err_busy: |
---|
| 3984 | + kfree(lock_tag); |
---|
| 3985 | + ceph_free_lockers(lockers, num_lockers); |
---|
| 3986 | + return ERR_PTR(-EBUSY); |
---|
3940 | 3987 | } |
---|
3941 | 3988 | |
---|
3942 | 3989 | static int find_watcher(struct rbd_device *rbd_dev, |
---|
.. | .. |
---|
3952 | 3999 | ret = ceph_osdc_list_watchers(osdc, &rbd_dev->header_oid, |
---|
3953 | 4000 | &rbd_dev->header_oloc, &watchers, |
---|
3954 | 4001 | &num_watchers); |
---|
3955 | | - if (ret) |
---|
| 4002 | + if (ret) { |
---|
| 4003 | + rbd_warn(rbd_dev, "failed to get watchers: %d", ret); |
---|
3956 | 4004 | return ret; |
---|
| 4005 | + } |
---|
3957 | 4006 | |
---|
3958 | 4007 | sscanf(locker->id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu", &cookie); |
---|
3959 | 4008 | for (i = 0; i < num_watchers; i++) { |
---|
3960 | | - if (!memcmp(&watchers[i].addr, &locker->info.addr, |
---|
3961 | | - sizeof(locker->info.addr)) && |
---|
| 4009 | + /* |
---|
| 4010 | + * Ignore addr->type while comparing. This mimics |
---|
| 4011 | + * entity_addr_t::get_legacy_str() + strcmp(). |
---|
| 4012 | + */ |
---|
| 4013 | + if (ceph_addr_equal_no_type(&watchers[i].addr, |
---|
| 4014 | + &locker->info.addr) && |
---|
3962 | 4015 | watchers[i].cookie == cookie) { |
---|
3963 | 4016 | struct rbd_client_id cid = { |
---|
3964 | 4017 | .gid = le64_to_cpu(watchers[i].name.num), |
---|
.. | .. |
---|
3986 | 4039 | static int rbd_try_lock(struct rbd_device *rbd_dev) |
---|
3987 | 4040 | { |
---|
3988 | 4041 | struct ceph_client *client = rbd_dev->rbd_client->client; |
---|
3989 | | - struct ceph_locker *lockers; |
---|
3990 | | - u32 num_lockers; |
---|
| 4042 | + struct ceph_locker *locker, *refreshed_locker; |
---|
3991 | 4043 | int ret; |
---|
3992 | 4044 | |
---|
3993 | 4045 | for (;;) { |
---|
| 4046 | + locker = refreshed_locker = NULL; |
---|
| 4047 | + |
---|
3994 | 4048 | ret = rbd_lock(rbd_dev); |
---|
3995 | | - if (ret != -EBUSY) |
---|
3996 | | - return ret; |
---|
| 4049 | + if (!ret) |
---|
| 4050 | + goto out; |
---|
| 4051 | + if (ret != -EBUSY) { |
---|
| 4052 | + rbd_warn(rbd_dev, "failed to lock header: %d", ret); |
---|
| 4053 | + goto out; |
---|
| 4054 | + } |
---|
3997 | 4055 | |
---|
3998 | 4056 | /* determine if the current lock holder is still alive */ |
---|
3999 | | - ret = get_lock_owner_info(rbd_dev, &lockers, &num_lockers); |
---|
4000 | | - if (ret) |
---|
4001 | | - return ret; |
---|
4002 | | - |
---|
4003 | | - if (num_lockers == 0) |
---|
| 4057 | + locker = get_lock_owner_info(rbd_dev); |
---|
| 4058 | + if (IS_ERR(locker)) { |
---|
| 4059 | + ret = PTR_ERR(locker); |
---|
| 4060 | + locker = NULL; |
---|
| 4061 | + goto out; |
---|
| 4062 | + } |
---|
| 4063 | + if (!locker) |
---|
4004 | 4064 | goto again; |
---|
4005 | 4065 | |
---|
4006 | | - ret = find_watcher(rbd_dev, lockers); |
---|
| 4066 | + ret = find_watcher(rbd_dev, locker); |
---|
4007 | 4067 | if (ret) |
---|
4008 | 4068 | goto out; /* request lock or error */ |
---|
4009 | 4069 | |
---|
| 4070 | + refreshed_locker = get_lock_owner_info(rbd_dev); |
---|
| 4071 | + if (IS_ERR(refreshed_locker)) { |
---|
| 4072 | + ret = PTR_ERR(refreshed_locker); |
---|
| 4073 | + refreshed_locker = NULL; |
---|
| 4074 | + goto out; |
---|
| 4075 | + } |
---|
| 4076 | + if (!refreshed_locker || |
---|
| 4077 | + !locker_equal(locker, refreshed_locker)) |
---|
| 4078 | + goto again; |
---|
| 4079 | + |
---|
4010 | 4080 | rbd_warn(rbd_dev, "breaking header lock owned by %s%llu", |
---|
4011 | | - ENTITY_NAME(lockers[0].id.name)); |
---|
| 4081 | + ENTITY_NAME(locker->id.name)); |
---|
4012 | 4082 | |
---|
4013 | 4083 | ret = ceph_monc_blocklist_add(&client->monc, |
---|
4014 | | - &lockers[0].info.addr); |
---|
| 4084 | + &locker->info.addr); |
---|
4015 | 4085 | if (ret) { |
---|
4016 | | - rbd_warn(rbd_dev, "blocklist of %s%llu failed: %d", |
---|
4017 | | - ENTITY_NAME(lockers[0].id.name), ret); |
---|
| 4086 | + rbd_warn(rbd_dev, "failed to blocklist %s%llu: %d", |
---|
| 4087 | + ENTITY_NAME(locker->id.name), ret); |
---|
4018 | 4088 | goto out; |
---|
4019 | 4089 | } |
---|
4020 | 4090 | |
---|
4021 | 4091 | ret = ceph_cls_break_lock(&client->osdc, &rbd_dev->header_oid, |
---|
4022 | 4092 | &rbd_dev->header_oloc, RBD_LOCK_NAME, |
---|
4023 | | - lockers[0].id.cookie, |
---|
4024 | | - &lockers[0].id.name); |
---|
4025 | | - if (ret && ret != -ENOENT) |
---|
| 4093 | + locker->id.cookie, &locker->id.name); |
---|
| 4094 | + if (ret && ret != -ENOENT) { |
---|
| 4095 | + rbd_warn(rbd_dev, "failed to break header lock: %d", |
---|
| 4096 | + ret); |
---|
4026 | 4097 | goto out; |
---|
| 4098 | + } |
---|
4027 | 4099 | |
---|
4028 | 4100 | again: |
---|
4029 | | - ceph_free_lockers(lockers, num_lockers); |
---|
| 4101 | + free_locker(refreshed_locker); |
---|
| 4102 | + free_locker(locker); |
---|
4030 | 4103 | } |
---|
4031 | 4104 | |
---|
4032 | 4105 | out: |
---|
4033 | | - ceph_free_lockers(lockers, num_lockers); |
---|
| 4106 | + free_locker(refreshed_locker); |
---|
| 4107 | + free_locker(locker); |
---|
4034 | 4108 | return ret; |
---|
4035 | 4109 | } |
---|
4036 | 4110 | |
---|
4037 | 4111 | static int rbd_post_acquire_action(struct rbd_device *rbd_dev) |
---|
4038 | 4112 | { |
---|
4039 | 4113 | int ret; |
---|
| 4114 | + |
---|
| 4115 | + ret = rbd_dev_refresh(rbd_dev); |
---|
| 4116 | + if (ret) |
---|
| 4117 | + return ret; |
---|
4040 | 4118 | |
---|
4041 | 4119 | if (rbd_dev->header.features & RBD_FEATURE_OBJECT_MAP) { |
---|
4042 | 4120 | ret = rbd_object_map_open(rbd_dev); |
---|
.. | .. |
---|
4076 | 4154 | |
---|
4077 | 4155 | ret = rbd_try_lock(rbd_dev); |
---|
4078 | 4156 | if (ret < 0) { |
---|
4079 | | - rbd_warn(rbd_dev, "failed to lock header: %d", ret); |
---|
4080 | | - if (ret == -EBLOCKLISTED) |
---|
4081 | | - goto out; |
---|
4082 | | - |
---|
4083 | | - ret = 1; /* request lock anyway */ |
---|
| 4157 | + rbd_warn(rbd_dev, "failed to acquire lock: %d", ret); |
---|
| 4158 | + goto out; |
---|
4084 | 4159 | } |
---|
4085 | 4160 | if (ret > 0) { |
---|
4086 | 4161 | up_write(&rbd_dev->lock_rwsem); |
---|
.. | .. |
---|
4844 | 4919 | * return, the rbd_dev->header field will contain up-to-date |
---|
4845 | 4920 | * information about the image. |
---|
4846 | 4921 | */ |
---|
4847 | | -static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev) |
---|
| 4922 | +static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev, |
---|
| 4923 | + struct rbd_image_header *header, |
---|
| 4924 | + bool first_time) |
---|
4848 | 4925 | { |
---|
4849 | 4926 | struct rbd_image_header_ondisk *ondisk = NULL; |
---|
4850 | 4927 | u32 snap_count = 0; |
---|
.. | .. |
---|
4892 | 4969 | snap_count = le32_to_cpu(ondisk->snap_count); |
---|
4893 | 4970 | } while (snap_count != want_count); |
---|
4894 | 4971 | |
---|
4895 | | - ret = rbd_header_from_disk(rbd_dev, ondisk); |
---|
| 4972 | + ret = rbd_header_from_disk(header, ondisk, first_time); |
---|
4896 | 4973 | out: |
---|
4897 | 4974 | kfree(ondisk); |
---|
4898 | 4975 | |
---|
.. | .. |
---|
4915 | 4992 | set_capacity(rbd_dev->disk, size); |
---|
4916 | 4993 | revalidate_disk_size(rbd_dev->disk, true); |
---|
4917 | 4994 | } |
---|
4918 | | -} |
---|
4919 | | - |
---|
4920 | | -static int rbd_dev_refresh(struct rbd_device *rbd_dev) |
---|
4921 | | -{ |
---|
4922 | | - u64 mapping_size; |
---|
4923 | | - int ret; |
---|
4924 | | - |
---|
4925 | | - down_write(&rbd_dev->header_rwsem); |
---|
4926 | | - mapping_size = rbd_dev->mapping.size; |
---|
4927 | | - |
---|
4928 | | - ret = rbd_dev_header_info(rbd_dev); |
---|
4929 | | - if (ret) |
---|
4930 | | - goto out; |
---|
4931 | | - |
---|
4932 | | - /* |
---|
4933 | | - * If there is a parent, see if it has disappeared due to the |
---|
4934 | | - * mapped image getting flattened. |
---|
4935 | | - */ |
---|
4936 | | - if (rbd_dev->parent) { |
---|
4937 | | - ret = rbd_dev_v2_parent_info(rbd_dev); |
---|
4938 | | - if (ret) |
---|
4939 | | - goto out; |
---|
4940 | | - } |
---|
4941 | | - |
---|
4942 | | - rbd_assert(!rbd_is_snap(rbd_dev)); |
---|
4943 | | - rbd_dev->mapping.size = rbd_dev->header.image_size; |
---|
4944 | | - |
---|
4945 | | -out: |
---|
4946 | | - up_write(&rbd_dev->header_rwsem); |
---|
4947 | | - if (!ret && mapping_size != rbd_dev->mapping.size) |
---|
4948 | | - rbd_dev_update_size(rbd_dev); |
---|
4949 | | - |
---|
4950 | | - return ret; |
---|
4951 | 4995 | } |
---|
4952 | 4996 | |
---|
4953 | 4997 | static const struct blk_mq_ops rbd_mq_ops = { |
---|
.. | .. |
---|
5369 | 5413 | module_put(THIS_MODULE); |
---|
5370 | 5414 | } |
---|
5371 | 5415 | |
---|
5372 | | -static struct rbd_device *__rbd_dev_create(struct rbd_client *rbdc, |
---|
5373 | | - struct rbd_spec *spec) |
---|
| 5416 | +static struct rbd_device *__rbd_dev_create(struct rbd_spec *spec) |
---|
5374 | 5417 | { |
---|
5375 | 5418 | struct rbd_device *rbd_dev; |
---|
5376 | 5419 | |
---|
.. | .. |
---|
5415 | 5458 | rbd_dev->dev.parent = &rbd_root_dev; |
---|
5416 | 5459 | device_initialize(&rbd_dev->dev); |
---|
5417 | 5460 | |
---|
5418 | | - rbd_dev->rbd_client = rbdc; |
---|
5419 | | - rbd_dev->spec = spec; |
---|
5420 | | - |
---|
5421 | 5461 | return rbd_dev; |
---|
5422 | 5462 | } |
---|
5423 | 5463 | |
---|
.. | .. |
---|
5430 | 5470 | { |
---|
5431 | 5471 | struct rbd_device *rbd_dev; |
---|
5432 | 5472 | |
---|
5433 | | - rbd_dev = __rbd_dev_create(rbdc, spec); |
---|
| 5473 | + rbd_dev = __rbd_dev_create(spec); |
---|
5434 | 5474 | if (!rbd_dev) |
---|
5435 | 5475 | return NULL; |
---|
5436 | | - |
---|
5437 | | - rbd_dev->opts = opts; |
---|
5438 | 5476 | |
---|
5439 | 5477 | /* get an id and fill in device name */ |
---|
5440 | 5478 | rbd_dev->dev_id = ida_simple_get(&rbd_dev_id_ida, 0, |
---|
.. | .. |
---|
5451 | 5489 | |
---|
5452 | 5490 | /* we have a ref from do_rbd_add() */ |
---|
5453 | 5491 | __module_get(THIS_MODULE); |
---|
| 5492 | + |
---|
| 5493 | + rbd_dev->rbd_client = rbdc; |
---|
| 5494 | + rbd_dev->spec = spec; |
---|
| 5495 | + rbd_dev->opts = opts; |
---|
5454 | 5496 | |
---|
5455 | 5497 | dout("%s rbd_dev %p dev_id %d\n", __func__, rbd_dev, rbd_dev->dev_id); |
---|
5456 | 5498 | return rbd_dev; |
---|
.. | .. |
---|
5506 | 5548 | return 0; |
---|
5507 | 5549 | } |
---|
5508 | 5550 | |
---|
5509 | | -static int rbd_dev_v2_image_size(struct rbd_device *rbd_dev) |
---|
5510 | | -{ |
---|
5511 | | - return _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP, |
---|
5512 | | - &rbd_dev->header.obj_order, |
---|
5513 | | - &rbd_dev->header.image_size); |
---|
5514 | | -} |
---|
5515 | | - |
---|
5516 | | -static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev) |
---|
| 5551 | +static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev, |
---|
| 5552 | + char **pobject_prefix) |
---|
5517 | 5553 | { |
---|
5518 | 5554 | size_t size; |
---|
5519 | 5555 | void *reply_buf; |
---|
| 5556 | + char *object_prefix; |
---|
5520 | 5557 | int ret; |
---|
5521 | 5558 | void *p; |
---|
5522 | 5559 | |
---|
.. | .. |
---|
5534 | 5571 | goto out; |
---|
5535 | 5572 | |
---|
5536 | 5573 | p = reply_buf; |
---|
5537 | | - rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p, |
---|
5538 | | - p + ret, NULL, GFP_NOIO); |
---|
| 5574 | + object_prefix = ceph_extract_encoded_string(&p, p + ret, NULL, |
---|
| 5575 | + GFP_NOIO); |
---|
| 5576 | + if (IS_ERR(object_prefix)) { |
---|
| 5577 | + ret = PTR_ERR(object_prefix); |
---|
| 5578 | + goto out; |
---|
| 5579 | + } |
---|
5539 | 5580 | ret = 0; |
---|
5540 | 5581 | |
---|
5541 | | - if (IS_ERR(rbd_dev->header.object_prefix)) { |
---|
5542 | | - ret = PTR_ERR(rbd_dev->header.object_prefix); |
---|
5543 | | - rbd_dev->header.object_prefix = NULL; |
---|
5544 | | - } else { |
---|
5545 | | - dout(" object_prefix = %s\n", rbd_dev->header.object_prefix); |
---|
5546 | | - } |
---|
| 5582 | + *pobject_prefix = object_prefix; |
---|
| 5583 | + dout(" object_prefix = %s\n", object_prefix); |
---|
5547 | 5584 | out: |
---|
5548 | 5585 | kfree(reply_buf); |
---|
5549 | 5586 | |
---|
.. | .. |
---|
5594 | 5631 | return 0; |
---|
5595 | 5632 | } |
---|
5596 | 5633 | |
---|
5597 | | -static int rbd_dev_v2_features(struct rbd_device *rbd_dev) |
---|
5598 | | -{ |
---|
5599 | | - return _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP, |
---|
5600 | | - rbd_is_ro(rbd_dev), |
---|
5601 | | - &rbd_dev->header.features); |
---|
5602 | | -} |
---|
5603 | | - |
---|
5604 | 5634 | /* |
---|
5605 | 5635 | * These are generic image flags, but since they are used only for |
---|
5606 | 5636 | * object map, store them in rbd_dev->object_map_flags. |
---|
.. | .. |
---|
5636 | 5666 | bool has_overlap; |
---|
5637 | 5667 | u64 overlap; |
---|
5638 | 5668 | }; |
---|
| 5669 | + |
---|
| 5670 | +static void rbd_parent_info_cleanup(struct parent_image_info *pii) |
---|
| 5671 | +{ |
---|
| 5672 | + kfree(pii->pool_ns); |
---|
| 5673 | + kfree(pii->image_id); |
---|
| 5674 | + |
---|
| 5675 | + memset(pii, 0, sizeof(*pii)); |
---|
| 5676 | +} |
---|
5639 | 5677 | |
---|
5640 | 5678 | /* |
---|
5641 | 5679 | * The caller is responsible for @pii. |
---|
.. | .. |
---|
5706 | 5744 | if (pii->has_overlap) |
---|
5707 | 5745 | ceph_decode_64_safe(&p, end, pii->overlap, e_inval); |
---|
5708 | 5746 | |
---|
| 5747 | + dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n", |
---|
| 5748 | + __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id, |
---|
| 5749 | + pii->has_overlap, pii->overlap); |
---|
5709 | 5750 | return 0; |
---|
5710 | 5751 | |
---|
5711 | 5752 | e_inval: |
---|
.. | .. |
---|
5744 | 5785 | pii->has_overlap = true; |
---|
5745 | 5786 | ceph_decode_64_safe(&p, end, pii->overlap, e_inval); |
---|
5746 | 5787 | |
---|
| 5788 | + dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n", |
---|
| 5789 | + __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id, |
---|
| 5790 | + pii->has_overlap, pii->overlap); |
---|
5747 | 5791 | return 0; |
---|
5748 | 5792 | |
---|
5749 | 5793 | e_inval: |
---|
5750 | 5794 | return -EINVAL; |
---|
5751 | 5795 | } |
---|
5752 | 5796 | |
---|
5753 | | -static int get_parent_info(struct rbd_device *rbd_dev, |
---|
5754 | | - struct parent_image_info *pii) |
---|
| 5797 | +static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev, |
---|
| 5798 | + struct parent_image_info *pii) |
---|
5755 | 5799 | { |
---|
5756 | 5800 | struct page *req_page, *reply_page; |
---|
5757 | 5801 | void *p; |
---|
.. | .. |
---|
5779 | 5823 | return ret; |
---|
5780 | 5824 | } |
---|
5781 | 5825 | |
---|
5782 | | -static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) |
---|
| 5826 | +static int rbd_dev_setup_parent(struct rbd_device *rbd_dev) |
---|
5783 | 5827 | { |
---|
5784 | 5828 | struct rbd_spec *parent_spec; |
---|
5785 | 5829 | struct parent_image_info pii = { 0 }; |
---|
.. | .. |
---|
5789 | 5833 | if (!parent_spec) |
---|
5790 | 5834 | return -ENOMEM; |
---|
5791 | 5835 | |
---|
5792 | | - ret = get_parent_info(rbd_dev, &pii); |
---|
| 5836 | + ret = rbd_dev_v2_parent_info(rbd_dev, &pii); |
---|
5793 | 5837 | if (ret) |
---|
5794 | 5838 | goto out_err; |
---|
5795 | 5839 | |
---|
5796 | | - dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n", |
---|
5797 | | - __func__, pii.pool_id, pii.pool_ns, pii.image_id, pii.snap_id, |
---|
5798 | | - pii.has_overlap, pii.overlap); |
---|
5799 | | - |
---|
5800 | | - if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) { |
---|
5801 | | - /* |
---|
5802 | | - * Either the parent never existed, or we have |
---|
5803 | | - * record of it but the image got flattened so it no |
---|
5804 | | - * longer has a parent. When the parent of a |
---|
5805 | | - * layered image disappears we immediately set the |
---|
5806 | | - * overlap to 0. The effect of this is that all new |
---|
5807 | | - * requests will be treated as if the image had no |
---|
5808 | | - * parent. |
---|
5809 | | - * |
---|
5810 | | - * If !pii.has_overlap, the parent image spec is not |
---|
5811 | | - * applicable. It's there to avoid duplication in each |
---|
5812 | | - * snapshot record. |
---|
5813 | | - */ |
---|
5814 | | - if (rbd_dev->parent_overlap) { |
---|
5815 | | - rbd_dev->parent_overlap = 0; |
---|
5816 | | - rbd_dev_parent_put(rbd_dev); |
---|
5817 | | - pr_info("%s: clone image has been flattened\n", |
---|
5818 | | - rbd_dev->disk->disk_name); |
---|
5819 | | - } |
---|
5820 | | - |
---|
| 5840 | + if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) |
---|
5821 | 5841 | goto out; /* No parent? No problem. */ |
---|
5822 | | - } |
---|
5823 | 5842 | |
---|
5824 | 5843 | /* The ceph file layout needs to fit pool id in 32 bits */ |
---|
5825 | 5844 | |
---|
.. | .. |
---|
5831 | 5850 | } |
---|
5832 | 5851 | |
---|
5833 | 5852 | /* |
---|
5834 | | - * The parent won't change (except when the clone is |
---|
5835 | | - * flattened, already handled that). So we only need to |
---|
5836 | | - * record the parent spec we have not already done so. |
---|
| 5853 | + * The parent won't change except when the clone is flattened, |
---|
| 5854 | + * so we only need to record the parent image spec once. |
---|
5837 | 5855 | */ |
---|
5838 | | - if (!rbd_dev->parent_spec) { |
---|
5839 | | - parent_spec->pool_id = pii.pool_id; |
---|
5840 | | - if (pii.pool_ns && *pii.pool_ns) { |
---|
5841 | | - parent_spec->pool_ns = pii.pool_ns; |
---|
5842 | | - pii.pool_ns = NULL; |
---|
5843 | | - } |
---|
5844 | | - parent_spec->image_id = pii.image_id; |
---|
5845 | | - pii.image_id = NULL; |
---|
5846 | | - parent_spec->snap_id = pii.snap_id; |
---|
5847 | | - |
---|
5848 | | - rbd_dev->parent_spec = parent_spec; |
---|
5849 | | - parent_spec = NULL; /* rbd_dev now owns this */ |
---|
| 5856 | + parent_spec->pool_id = pii.pool_id; |
---|
| 5857 | + if (pii.pool_ns && *pii.pool_ns) { |
---|
| 5858 | + parent_spec->pool_ns = pii.pool_ns; |
---|
| 5859 | + pii.pool_ns = NULL; |
---|
5850 | 5860 | } |
---|
| 5861 | + parent_spec->image_id = pii.image_id; |
---|
| 5862 | + pii.image_id = NULL; |
---|
| 5863 | + parent_spec->snap_id = pii.snap_id; |
---|
| 5864 | + |
---|
| 5865 | + rbd_assert(!rbd_dev->parent_spec); |
---|
| 5866 | + rbd_dev->parent_spec = parent_spec; |
---|
| 5867 | + parent_spec = NULL; /* rbd_dev now owns this */ |
---|
5851 | 5868 | |
---|
5852 | 5869 | /* |
---|
5853 | | - * We always update the parent overlap. If it's zero we issue |
---|
5854 | | - * a warning, as we will proceed as if there was no parent. |
---|
| 5870 | + * Record the parent overlap. If it's zero, issue a warning as |
---|
| 5871 | + * we will proceed as if there is no parent. |
---|
5855 | 5872 | */ |
---|
5856 | | - if (!pii.overlap) { |
---|
5857 | | - if (parent_spec) { |
---|
5858 | | - /* refresh, careful to warn just once */ |
---|
5859 | | - if (rbd_dev->parent_overlap) |
---|
5860 | | - rbd_warn(rbd_dev, |
---|
5861 | | - "clone now standalone (overlap became 0)"); |
---|
5862 | | - } else { |
---|
5863 | | - /* initial probe */ |
---|
5864 | | - rbd_warn(rbd_dev, "clone is standalone (overlap 0)"); |
---|
5865 | | - } |
---|
5866 | | - } |
---|
| 5873 | + if (!pii.overlap) |
---|
| 5874 | + rbd_warn(rbd_dev, "clone is standalone (overlap 0)"); |
---|
5867 | 5875 | rbd_dev->parent_overlap = pii.overlap; |
---|
5868 | 5876 | |
---|
5869 | 5877 | out: |
---|
5870 | 5878 | ret = 0; |
---|
5871 | 5879 | out_err: |
---|
5872 | | - kfree(pii.pool_ns); |
---|
5873 | | - kfree(pii.image_id); |
---|
| 5880 | + rbd_parent_info_cleanup(&pii); |
---|
5874 | 5881 | rbd_spec_put(parent_spec); |
---|
5875 | 5882 | return ret; |
---|
5876 | 5883 | } |
---|
5877 | 5884 | |
---|
5878 | | -static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev) |
---|
| 5885 | +static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev, |
---|
| 5886 | + u64 *stripe_unit, u64 *stripe_count) |
---|
5879 | 5887 | { |
---|
5880 | 5888 | struct { |
---|
5881 | 5889 | __le64 stripe_unit; |
---|
5882 | 5890 | __le64 stripe_count; |
---|
5883 | 5891 | } __attribute__ ((packed)) striping_info_buf = { 0 }; |
---|
5884 | 5892 | size_t size = sizeof (striping_info_buf); |
---|
5885 | | - void *p; |
---|
5886 | 5893 | int ret; |
---|
5887 | 5894 | |
---|
5888 | 5895 | ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid, |
---|
.. | .. |
---|
5894 | 5901 | if (ret < size) |
---|
5895 | 5902 | return -ERANGE; |
---|
5896 | 5903 | |
---|
5897 | | - p = &striping_info_buf; |
---|
5898 | | - rbd_dev->header.stripe_unit = ceph_decode_64(&p); |
---|
5899 | | - rbd_dev->header.stripe_count = ceph_decode_64(&p); |
---|
| 5904 | + *stripe_unit = le64_to_cpu(striping_info_buf.stripe_unit); |
---|
| 5905 | + *stripe_count = le64_to_cpu(striping_info_buf.stripe_count); |
---|
| 5906 | + dout(" stripe_unit = %llu stripe_count = %llu\n", *stripe_unit, |
---|
| 5907 | + *stripe_count); |
---|
| 5908 | + |
---|
5900 | 5909 | return 0; |
---|
5901 | 5910 | } |
---|
5902 | 5911 | |
---|
5903 | | -static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev) |
---|
| 5912 | +static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev, s64 *data_pool_id) |
---|
5904 | 5913 | { |
---|
5905 | | - __le64 data_pool_id; |
---|
| 5914 | + __le64 data_pool_buf; |
---|
5906 | 5915 | int ret; |
---|
5907 | 5916 | |
---|
5908 | 5917 | ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid, |
---|
5909 | 5918 | &rbd_dev->header_oloc, "get_data_pool", |
---|
5910 | | - NULL, 0, &data_pool_id, sizeof(data_pool_id)); |
---|
| 5919 | + NULL, 0, &data_pool_buf, |
---|
| 5920 | + sizeof(data_pool_buf)); |
---|
| 5921 | + dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret); |
---|
5911 | 5922 | if (ret < 0) |
---|
5912 | 5923 | return ret; |
---|
5913 | | - if (ret < sizeof(data_pool_id)) |
---|
| 5924 | + if (ret < sizeof(data_pool_buf)) |
---|
5914 | 5925 | return -EBADMSG; |
---|
5915 | 5926 | |
---|
5916 | | - rbd_dev->header.data_pool_id = le64_to_cpu(data_pool_id); |
---|
5917 | | - WARN_ON(rbd_dev->header.data_pool_id == CEPH_NOPOOL); |
---|
| 5927 | + *data_pool_id = le64_to_cpu(data_pool_buf); |
---|
| 5928 | + dout(" data_pool_id = %lld\n", *data_pool_id); |
---|
| 5929 | + WARN_ON(*data_pool_id == CEPH_NOPOOL); |
---|
| 5930 | + |
---|
5918 | 5931 | return 0; |
---|
5919 | 5932 | } |
---|
5920 | 5933 | |
---|
.. | .. |
---|
6106 | 6119 | return ret; |
---|
6107 | 6120 | } |
---|
6108 | 6121 | |
---|
6109 | | -static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev) |
---|
| 6122 | +static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, |
---|
| 6123 | + struct ceph_snap_context **psnapc) |
---|
6110 | 6124 | { |
---|
6111 | 6125 | size_t size; |
---|
6112 | 6126 | int ret; |
---|
.. | .. |
---|
6167 | 6181 | for (i = 0; i < snap_count; i++) |
---|
6168 | 6182 | snapc->snaps[i] = ceph_decode_64(&p); |
---|
6169 | 6183 | |
---|
6170 | | - ceph_put_snap_context(rbd_dev->header.snapc); |
---|
6171 | | - rbd_dev->header.snapc = snapc; |
---|
6172 | | - |
---|
| 6184 | + *psnapc = snapc; |
---|
6173 | 6185 | dout(" snap context seq = %llu, snap_count = %u\n", |
---|
6174 | 6186 | (unsigned long long)seq, (unsigned int)snap_count); |
---|
6175 | 6187 | out: |
---|
.. | .. |
---|
6218 | 6230 | return snap_name; |
---|
6219 | 6231 | } |
---|
6220 | 6232 | |
---|
6221 | | -static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev) |
---|
| 6233 | +static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev, |
---|
| 6234 | + struct rbd_image_header *header, |
---|
| 6235 | + bool first_time) |
---|
6222 | 6236 | { |
---|
6223 | | - bool first_time = rbd_dev->header.object_prefix == NULL; |
---|
6224 | 6237 | int ret; |
---|
6225 | 6238 | |
---|
6226 | | - ret = rbd_dev_v2_image_size(rbd_dev); |
---|
| 6239 | + ret = _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP, |
---|
| 6240 | + first_time ? &header->obj_order : NULL, |
---|
| 6241 | + &header->image_size); |
---|
6227 | 6242 | if (ret) |
---|
6228 | 6243 | return ret; |
---|
6229 | 6244 | |
---|
6230 | 6245 | if (first_time) { |
---|
6231 | | - ret = rbd_dev_v2_header_onetime(rbd_dev); |
---|
| 6246 | + ret = rbd_dev_v2_header_onetime(rbd_dev, header); |
---|
6232 | 6247 | if (ret) |
---|
6233 | 6248 | return ret; |
---|
6234 | 6249 | } |
---|
6235 | 6250 | |
---|
6236 | | - ret = rbd_dev_v2_snap_context(rbd_dev); |
---|
6237 | | - if (ret && first_time) { |
---|
6238 | | - kfree(rbd_dev->header.object_prefix); |
---|
6239 | | - rbd_dev->header.object_prefix = NULL; |
---|
6240 | | - } |
---|
| 6251 | + ret = rbd_dev_v2_snap_context(rbd_dev, &header->snapc); |
---|
| 6252 | + if (ret) |
---|
| 6253 | + return ret; |
---|
6241 | 6254 | |
---|
6242 | | - return ret; |
---|
| 6255 | + return 0; |
---|
6243 | 6256 | } |
---|
6244 | 6257 | |
---|
6245 | | -static int rbd_dev_header_info(struct rbd_device *rbd_dev) |
---|
| 6258 | +static int rbd_dev_header_info(struct rbd_device *rbd_dev, |
---|
| 6259 | + struct rbd_image_header *header, |
---|
| 6260 | + bool first_time) |
---|
6246 | 6261 | { |
---|
6247 | 6262 | rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); |
---|
| 6263 | + rbd_assert(!header->object_prefix && !header->snapc); |
---|
6248 | 6264 | |
---|
6249 | 6265 | if (rbd_dev->image_format == 1) |
---|
6250 | | - return rbd_dev_v1_header_info(rbd_dev); |
---|
| 6266 | + return rbd_dev_v1_header_info(rbd_dev, header, first_time); |
---|
6251 | 6267 | |
---|
6252 | | - return rbd_dev_v2_header_info(rbd_dev); |
---|
| 6268 | + return rbd_dev_v2_header_info(rbd_dev, header, first_time); |
---|
6253 | 6269 | } |
---|
6254 | 6270 | |
---|
6255 | 6271 | /* |
---|
.. | .. |
---|
6632 | 6648 | cancel_delayed_work_sync(&rbd_dev->lock_dwork); |
---|
6633 | 6649 | if (!ret) |
---|
6634 | 6650 | ret = -ETIMEDOUT; |
---|
6635 | | - } |
---|
6636 | 6651 | |
---|
6637 | | - if (ret) { |
---|
6638 | | - rbd_warn(rbd_dev, "failed to acquire exclusive lock: %ld", ret); |
---|
6639 | | - return ret; |
---|
| 6652 | + rbd_warn(rbd_dev, "failed to acquire lock: %ld", ret); |
---|
6640 | 6653 | } |
---|
| 6654 | + if (ret) |
---|
| 6655 | + return ret; |
---|
6641 | 6656 | |
---|
6642 | 6657 | /* |
---|
6643 | 6658 | * The lock may have been released by now, unless automatic lock |
---|
.. | .. |
---|
6737 | 6752 | */ |
---|
6738 | 6753 | static void rbd_dev_unprobe(struct rbd_device *rbd_dev) |
---|
6739 | 6754 | { |
---|
6740 | | - struct rbd_image_header *header; |
---|
6741 | | - |
---|
6742 | 6755 | rbd_dev_parent_put(rbd_dev); |
---|
6743 | 6756 | rbd_object_map_free(rbd_dev); |
---|
6744 | 6757 | rbd_dev_mapping_clear(rbd_dev); |
---|
6745 | 6758 | |
---|
6746 | 6759 | /* Free dynamic fields from the header, then zero it out */ |
---|
6747 | 6760 | |
---|
6748 | | - header = &rbd_dev->header; |
---|
6749 | | - ceph_put_snap_context(header->snapc); |
---|
6750 | | - kfree(header->snap_sizes); |
---|
6751 | | - kfree(header->snap_names); |
---|
6752 | | - kfree(header->object_prefix); |
---|
6753 | | - memset(header, 0, sizeof (*header)); |
---|
| 6761 | + rbd_image_header_cleanup(&rbd_dev->header); |
---|
6754 | 6762 | } |
---|
6755 | 6763 | |
---|
6756 | | -static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev) |
---|
| 6764 | +static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev, |
---|
| 6765 | + struct rbd_image_header *header) |
---|
6757 | 6766 | { |
---|
6758 | 6767 | int ret; |
---|
6759 | 6768 | |
---|
6760 | | - ret = rbd_dev_v2_object_prefix(rbd_dev); |
---|
| 6769 | + ret = rbd_dev_v2_object_prefix(rbd_dev, &header->object_prefix); |
---|
6761 | 6770 | if (ret) |
---|
6762 | | - goto out_err; |
---|
| 6771 | + return ret; |
---|
6763 | 6772 | |
---|
6764 | 6773 | /* |
---|
6765 | 6774 | * Get the and check features for the image. Currently the |
---|
6766 | 6775 | * features are assumed to never change. |
---|
6767 | 6776 | */ |
---|
6768 | | - ret = rbd_dev_v2_features(rbd_dev); |
---|
| 6777 | + ret = _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP, |
---|
| 6778 | + rbd_is_ro(rbd_dev), &header->features); |
---|
6769 | 6779 | if (ret) |
---|
6770 | | - goto out_err; |
---|
| 6780 | + return ret; |
---|
6771 | 6781 | |
---|
6772 | 6782 | /* If the image supports fancy striping, get its parameters */ |
---|
6773 | 6783 | |
---|
6774 | | - if (rbd_dev->header.features & RBD_FEATURE_STRIPINGV2) { |
---|
6775 | | - ret = rbd_dev_v2_striping_info(rbd_dev); |
---|
6776 | | - if (ret < 0) |
---|
6777 | | - goto out_err; |
---|
6778 | | - } |
---|
6779 | | - |
---|
6780 | | - if (rbd_dev->header.features & RBD_FEATURE_DATA_POOL) { |
---|
6781 | | - ret = rbd_dev_v2_data_pool(rbd_dev); |
---|
| 6784 | + if (header->features & RBD_FEATURE_STRIPINGV2) { |
---|
| 6785 | + ret = rbd_dev_v2_striping_info(rbd_dev, &header->stripe_unit, |
---|
| 6786 | + &header->stripe_count); |
---|
6782 | 6787 | if (ret) |
---|
6783 | | - goto out_err; |
---|
| 6788 | + return ret; |
---|
6784 | 6789 | } |
---|
6785 | 6790 | |
---|
6786 | | - rbd_init_layout(rbd_dev); |
---|
6787 | | - return 0; |
---|
| 6791 | + if (header->features & RBD_FEATURE_DATA_POOL) { |
---|
| 6792 | + ret = rbd_dev_v2_data_pool(rbd_dev, &header->data_pool_id); |
---|
| 6793 | + if (ret) |
---|
| 6794 | + return ret; |
---|
| 6795 | + } |
---|
6788 | 6796 | |
---|
6789 | | -out_err: |
---|
6790 | | - rbd_dev->header.features = 0; |
---|
6791 | | - kfree(rbd_dev->header.object_prefix); |
---|
6792 | | - rbd_dev->header.object_prefix = NULL; |
---|
6793 | | - return ret; |
---|
| 6797 | + return 0; |
---|
6794 | 6798 | } |
---|
6795 | 6799 | |
---|
6796 | 6800 | /* |
---|
.. | .. |
---|
6812 | 6816 | goto out_err; |
---|
6813 | 6817 | } |
---|
6814 | 6818 | |
---|
6815 | | - parent = __rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec); |
---|
| 6819 | + parent = __rbd_dev_create(rbd_dev->parent_spec); |
---|
6816 | 6820 | if (!parent) { |
---|
6817 | 6821 | ret = -ENOMEM; |
---|
6818 | 6822 | goto out_err; |
---|
.. | .. |
---|
6822 | 6826 | * Images related by parent/child relationships always share |
---|
6823 | 6827 | * rbd_client and spec/parent_spec, so bump their refcounts. |
---|
6824 | 6828 | */ |
---|
6825 | | - __rbd_get_client(rbd_dev->rbd_client); |
---|
6826 | | - rbd_spec_get(rbd_dev->parent_spec); |
---|
| 6829 | + parent->rbd_client = __rbd_get_client(rbd_dev->rbd_client); |
---|
| 6830 | + parent->spec = rbd_spec_get(rbd_dev->parent_spec); |
---|
6827 | 6831 | |
---|
6828 | 6832 | __set_bit(RBD_DEV_FLAG_READONLY, &parent->flags); |
---|
6829 | 6833 | |
---|
.. | .. |
---|
6985 | 6989 | if (!depth) |
---|
6986 | 6990 | down_write(&rbd_dev->header_rwsem); |
---|
6987 | 6991 | |
---|
6988 | | - ret = rbd_dev_header_info(rbd_dev); |
---|
| 6992 | + ret = rbd_dev_header_info(rbd_dev, &rbd_dev->header, true); |
---|
6989 | 6993 | if (ret) { |
---|
6990 | 6994 | if (ret == -ENOENT && !need_watch) |
---|
6991 | 6995 | rbd_print_dne(rbd_dev, false); |
---|
6992 | 6996 | goto err_out_probe; |
---|
6993 | 6997 | } |
---|
| 6998 | + |
---|
| 6999 | + rbd_init_layout(rbd_dev); |
---|
6994 | 7000 | |
---|
6995 | 7001 | /* |
---|
6996 | 7002 | * If this image is the one being mapped, we have pool name and |
---|
.. | .. |
---|
7020 | 7026 | } |
---|
7021 | 7027 | |
---|
7022 | 7028 | if (rbd_dev->header.features & RBD_FEATURE_LAYERING) { |
---|
7023 | | - ret = rbd_dev_v2_parent_info(rbd_dev); |
---|
| 7029 | + ret = rbd_dev_setup_parent(rbd_dev); |
---|
7024 | 7030 | if (ret) |
---|
7025 | 7031 | goto err_out_probe; |
---|
7026 | 7032 | } |
---|
.. | .. |
---|
7046 | 7052 | return ret; |
---|
7047 | 7053 | } |
---|
7048 | 7054 | |
---|
| 7055 | +static void rbd_dev_update_header(struct rbd_device *rbd_dev, |
---|
| 7056 | + struct rbd_image_header *header) |
---|
| 7057 | +{ |
---|
| 7058 | + rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); |
---|
| 7059 | + rbd_assert(rbd_dev->header.object_prefix); /* !first_time */ |
---|
| 7060 | + |
---|
| 7061 | + if (rbd_dev->header.image_size != header->image_size) { |
---|
| 7062 | + rbd_dev->header.image_size = header->image_size; |
---|
| 7063 | + |
---|
| 7064 | + if (!rbd_is_snap(rbd_dev)) { |
---|
| 7065 | + rbd_dev->mapping.size = header->image_size; |
---|
| 7066 | + rbd_dev_update_size(rbd_dev); |
---|
| 7067 | + } |
---|
| 7068 | + } |
---|
| 7069 | + |
---|
| 7070 | + ceph_put_snap_context(rbd_dev->header.snapc); |
---|
| 7071 | + rbd_dev->header.snapc = header->snapc; |
---|
| 7072 | + header->snapc = NULL; |
---|
| 7073 | + |
---|
| 7074 | + if (rbd_dev->image_format == 1) { |
---|
| 7075 | + kfree(rbd_dev->header.snap_names); |
---|
| 7076 | + rbd_dev->header.snap_names = header->snap_names; |
---|
| 7077 | + header->snap_names = NULL; |
---|
| 7078 | + |
---|
| 7079 | + kfree(rbd_dev->header.snap_sizes); |
---|
| 7080 | + rbd_dev->header.snap_sizes = header->snap_sizes; |
---|
| 7081 | + header->snap_sizes = NULL; |
---|
| 7082 | + } |
---|
| 7083 | +} |
---|
| 7084 | + |
---|
| 7085 | +static void rbd_dev_update_parent(struct rbd_device *rbd_dev, |
---|
| 7086 | + struct parent_image_info *pii) |
---|
| 7087 | +{ |
---|
| 7088 | + if (pii->pool_id == CEPH_NOPOOL || !pii->has_overlap) { |
---|
| 7089 | + /* |
---|
| 7090 | + * Either the parent never existed, or we have |
---|
| 7091 | + * record of it but the image got flattened so it no |
---|
| 7092 | + * longer has a parent. When the parent of a |
---|
| 7093 | + * layered image disappears we immediately set the |
---|
| 7094 | + * overlap to 0. The effect of this is that all new |
---|
| 7095 | + * requests will be treated as if the image had no |
---|
| 7096 | + * parent. |
---|
| 7097 | + * |
---|
| 7098 | + * If !pii.has_overlap, the parent image spec is not |
---|
| 7099 | + * applicable. It's there to avoid duplication in each |
---|
| 7100 | + * snapshot record. |
---|
| 7101 | + */ |
---|
| 7102 | + if (rbd_dev->parent_overlap) { |
---|
| 7103 | + rbd_dev->parent_overlap = 0; |
---|
| 7104 | + rbd_dev_parent_put(rbd_dev); |
---|
| 7105 | + pr_info("%s: clone has been flattened\n", |
---|
| 7106 | + rbd_dev->disk->disk_name); |
---|
| 7107 | + } |
---|
| 7108 | + } else { |
---|
| 7109 | + rbd_assert(rbd_dev->parent_spec); |
---|
| 7110 | + |
---|
| 7111 | + /* |
---|
| 7112 | + * Update the parent overlap. If it became zero, issue |
---|
| 7113 | + * a warning as we will proceed as if there is no parent. |
---|
| 7114 | + */ |
---|
| 7115 | + if (!pii->overlap && rbd_dev->parent_overlap) |
---|
| 7116 | + rbd_warn(rbd_dev, |
---|
| 7117 | + "clone has become standalone (overlap 0)"); |
---|
| 7118 | + rbd_dev->parent_overlap = pii->overlap; |
---|
| 7119 | + } |
---|
| 7120 | +} |
---|
| 7121 | + |
---|
| 7122 | +static int rbd_dev_refresh(struct rbd_device *rbd_dev) |
---|
| 7123 | +{ |
---|
| 7124 | + struct rbd_image_header header = { 0 }; |
---|
| 7125 | + struct parent_image_info pii = { 0 }; |
---|
| 7126 | + int ret; |
---|
| 7127 | + |
---|
| 7128 | + dout("%s rbd_dev %p\n", __func__, rbd_dev); |
---|
| 7129 | + |
---|
| 7130 | + ret = rbd_dev_header_info(rbd_dev, &header, false); |
---|
| 7131 | + if (ret) |
---|
| 7132 | + goto out; |
---|
| 7133 | + |
---|
| 7134 | + /* |
---|
| 7135 | + * If there is a parent, see if it has disappeared due to the |
---|
| 7136 | + * mapped image getting flattened. |
---|
| 7137 | + */ |
---|
| 7138 | + if (rbd_dev->parent) { |
---|
| 7139 | + ret = rbd_dev_v2_parent_info(rbd_dev, &pii); |
---|
| 7140 | + if (ret) |
---|
| 7141 | + goto out; |
---|
| 7142 | + } |
---|
| 7143 | + |
---|
| 7144 | + down_write(&rbd_dev->header_rwsem); |
---|
| 7145 | + rbd_dev_update_header(rbd_dev, &header); |
---|
| 7146 | + if (rbd_dev->parent) |
---|
| 7147 | + rbd_dev_update_parent(rbd_dev, &pii); |
---|
| 7148 | + up_write(&rbd_dev->header_rwsem); |
---|
| 7149 | + |
---|
| 7150 | +out: |
---|
| 7151 | + rbd_parent_info_cleanup(&pii); |
---|
| 7152 | + rbd_image_header_cleanup(&header); |
---|
| 7153 | + return ret; |
---|
| 7154 | +} |
---|
| 7155 | + |
---|
7049 | 7156 | static ssize_t do_rbd_add(struct bus_type *bus, |
---|
7050 | 7157 | const char *buf, |
---|
7051 | 7158 | size_t count) |
---|