| 98 | } |
| 99 | |
| 100 | static int cls_2pc_queue_reserve(cls_method_context_t hctx, bufferlist *in, bufferlist *out) { |
| 101 | cls_2pc_queue_reserve_op res_op; |
| 102 | try { |
| 103 | auto in_iter = in->cbegin(); |
| 104 | decode(res_op, in_iter); |
| 105 | } catch (ceph::buffer::error& err) { |
| 106 | CLS_LOG(1, "ERROR: cls_2pc_queue_reserve: failed to decode entry: %s", err.what()); |
| 107 | return -EINVAL; |
| 108 | } |
| 109 | |
| 110 | if (res_op.size == 0) { |
| 111 | CLS_LOG(1, "ERROR: cls_2pc_queue_reserve: cannot reserve zero bytes"); |
| 112 | return -EINVAL; |
| 113 | } |
| 114 | if (res_op.entries == 0) { |
| 115 | CLS_LOG(1, "ERROR: cls_2pc_queue_reserve: cannot reserve zero entries"); |
| 116 | return -EINVAL; |
| 117 | } |
| 118 | |
| 119 | // get head |
| 120 | cls_queue_head head; |
| 121 | int ret = queue_read_head(hctx, head); |
| 122 | if (ret < 0) { |
| 123 | return ret; |
| 124 | } |
| 125 | |
| 126 | cls_2pc_urgent_data urgent_data; |
| 127 | try { |
| 128 | auto in_iter = head.bl_urgent_data.cbegin(); |
| 129 | decode(urgent_data, in_iter); |
| 130 | } catch (ceph::buffer::error& err) { |
| 131 | CLS_LOG(1, "ERROR: cls_2pc_queue_reserve: failed to decode entry: %s", err.what()); |
| 132 | return -EINVAL; |
| 133 | } |
| 134 | |
| 135 | // For old queues (v1/v2), recalculate reserved_size from actual reservations |
| 136 | // to fix any historical drift. Once written back, queue becomes v3. |
| 137 | if (urgent_data.decoded_struct_v < 3) { |
| 138 | urgent_data.reserved_size = |
| 139 | calc_reservations_size(urgent_data.reservations); |
| 140 | |
| 141 | // Also check xattrs if they exist |
| 142 | cls_2pc_reservations xattr_reservations; |
| 143 | bufferlist bl_xattrs; |
| 144 | if (urgent_data.has_xattrs) { |
| 145 | ret = |
| 146 | cls_cxx_getxattr(hctx, CLS_QUEUE_URGENT_DATA_XATTR_NAME, &bl_xattrs); |
| 147 | if (ret < 0 && (ret != -ENOENT && ret != -ENODATA)) { |
| 148 | CLS_LOG(1, |
| 149 | "ERROR: cls_2pc_queue_reserve: failed to read xattrs with: %d", |
| 150 | ret); |
| 151 | return ret; |
| 152 | } |
| 153 | if (ret >= 0) { |
| 154 | auto iter = bl_xattrs.cbegin(); |
| 155 | try { |
| 156 | decode(xattr_reservations, iter); |
| 157 | } catch (ceph::buffer::error& err) { |