diff options
author | Douglas Fuller <dfuller@redhat.com> | 2015-06-29 19:55:42 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2016-08-24 17:49:15 -0400 |
commit | d4ed4a530562881cc5225050e42d96034f405aae (patch) | |
tree | 0c7f7326e1d3d14cf58f20ca02f56db3d8fafef2 | |
parent | f66241cb99dac861aa2cedb9f05ffa98d70cbc6e (diff) |
libceph: support for lock.lock_info
Add an interface for the Ceph OSD lock.lock_info method and associated
data structures.
Based heavily on code by Mike Christie <michaelc@cs.wisc.edu>.
Signed-off-by: Douglas Fuller <dfuller@redhat.com>
[idryomov@gmail.com: refactor, misc fixes throughout]
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Mike Christie <mchristi@redhat.com>
Reviewed-by: Alex Elder <elder@linaro.org>
-rw-r--r-- | include/linux/ceph/cls_lock_client.h | 22 | ||||
-rw-r--r-- | net/ceph/cls_lock_client.c | 145 |
2 files changed, 167 insertions, 0 deletions
diff --git a/include/linux/ceph/cls_lock_client.h b/include/linux/ceph/cls_lock_client.h index 4e4dffef22bb..84884d8d4710 100644 --- a/include/linux/ceph/cls_lock_client.h +++ b/include/linux/ceph/cls_lock_client.h | |||
@@ -9,6 +9,20 @@ enum ceph_cls_lock_type { | |||
9 | CEPH_CLS_LOCK_SHARED = 2, | 9 | CEPH_CLS_LOCK_SHARED = 2, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | struct ceph_locker_id { | ||
13 | struct ceph_entity_name name; /* locker's client name */ | ||
14 | char *cookie; /* locker's cookie */ | ||
15 | }; | ||
16 | |||
17 | struct ceph_locker_info { | ||
18 | struct ceph_entity_addr addr; /* locker's address */ | ||
19 | }; | ||
20 | |||
21 | struct ceph_locker { | ||
22 | struct ceph_locker_id id; | ||
23 | struct ceph_locker_info info; | ||
24 | }; | ||
25 | |||
12 | int ceph_cls_lock(struct ceph_osd_client *osdc, | 26 | int ceph_cls_lock(struct ceph_osd_client *osdc, |
13 | struct ceph_object_id *oid, | 27 | struct ceph_object_id *oid, |
14 | struct ceph_object_locator *oloc, | 28 | struct ceph_object_locator *oloc, |
@@ -24,4 +38,12 @@ int ceph_cls_break_lock(struct ceph_osd_client *osdc, | |||
24 | char *lock_name, char *cookie, | 38 | char *lock_name, char *cookie, |
25 | struct ceph_entity_name *locker); | 39 | struct ceph_entity_name *locker); |
26 | 40 | ||
41 | void ceph_free_lockers(struct ceph_locker *lockers, u32 num_lockers); | ||
42 | |||
43 | int ceph_cls_lock_info(struct ceph_osd_client *osdc, | ||
44 | struct ceph_object_id *oid, | ||
45 | struct ceph_object_locator *oloc, | ||
46 | char *lock_name, u8 *type, char **tag, | ||
47 | struct ceph_locker **lockers, u32 *num_lockers); | ||
48 | |||
27 | #endif | 49 | #endif |
diff --git a/net/ceph/cls_lock_client.c b/net/ceph/cls_lock_client.c index 2a314537f958..50f040fdb2a9 100644 --- a/net/ceph/cls_lock_client.c +++ b/net/ceph/cls_lock_client.c | |||
@@ -178,3 +178,148 @@ int ceph_cls_break_lock(struct ceph_osd_client *osdc, | |||
178 | return ret; | 178 | return ret; |
179 | } | 179 | } |
180 | EXPORT_SYMBOL(ceph_cls_break_lock); | 180 | EXPORT_SYMBOL(ceph_cls_break_lock); |
181 | |||
182 | void ceph_free_lockers(struct ceph_locker *lockers, u32 num_lockers) | ||
183 | { | ||
184 | int i; | ||
185 | |||
186 | for (i = 0; i < num_lockers; i++) | ||
187 | kfree(lockers[i].id.cookie); | ||
188 | kfree(lockers); | ||
189 | } | ||
190 | EXPORT_SYMBOL(ceph_free_lockers); | ||
191 | |||
192 | static int decode_locker(void **p, void *end, struct ceph_locker *locker) | ||
193 | { | ||
194 | u8 struct_v; | ||
195 | u32 len; | ||
196 | char *s; | ||
197 | int ret; | ||
198 | |||
199 | ret = ceph_start_decoding(p, end, 1, "locker_id_t", &struct_v, &len); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
203 | ceph_decode_copy(p, &locker->id.name, sizeof(locker->id.name)); | ||
204 | s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO); | ||
205 | if (IS_ERR(s)) | ||
206 | return PTR_ERR(s); | ||
207 | |||
208 | locker->id.cookie = s; | ||
209 | |||
210 | ret = ceph_start_decoding(p, end, 1, "locker_info_t", &struct_v, &len); | ||
211 | if (ret) | ||
212 | return ret; | ||
213 | |||
214 | *p += sizeof(struct ceph_timespec); /* skip expiration */ | ||
215 | ceph_decode_copy(p, &locker->info.addr, sizeof(locker->info.addr)); | ||
216 | ceph_decode_addr(&locker->info.addr); | ||
217 | len = ceph_decode_32(p); | ||
218 | *p += len; /* skip description */ | ||
219 | |||
220 | dout("%s %s%llu cookie %s addr %s\n", __func__, | ||
221 | ENTITY_NAME(locker->id.name), locker->id.cookie, | ||
222 | ceph_pr_addr(&locker->info.addr.in_addr)); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int decode_lockers(void **p, void *end, u8 *type, char **tag, | ||
227 | struct ceph_locker **lockers, u32 *num_lockers) | ||
228 | { | ||
229 | u8 struct_v; | ||
230 | u32 struct_len; | ||
231 | char *s; | ||
232 | int i; | ||
233 | int ret; | ||
234 | |||
235 | ret = ceph_start_decoding(p, end, 1, "cls_lock_get_info_reply", | ||
236 | &struct_v, &struct_len); | ||
237 | if (ret) | ||
238 | return ret; | ||
239 | |||
240 | *num_lockers = ceph_decode_32(p); | ||
241 | *lockers = kcalloc(*num_lockers, sizeof(**lockers), GFP_NOIO); | ||
242 | if (!*lockers) | ||
243 | return -ENOMEM; | ||
244 | |||
245 | for (i = 0; i < *num_lockers; i++) { | ||
246 | ret = decode_locker(p, end, *lockers + i); | ||
247 | if (ret) | ||
248 | goto err_free_lockers; | ||
249 | } | ||
250 | |||
251 | *type = ceph_decode_8(p); | ||
252 | s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO); | ||
253 | if (IS_ERR(s)) { | ||
254 | ret = PTR_ERR(s); | ||
255 | goto err_free_lockers; | ||
256 | } | ||
257 | |||
258 | *tag = s; | ||
259 | return 0; | ||
260 | |||
261 | err_free_lockers: | ||
262 | ceph_free_lockers(*lockers, *num_lockers); | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * On success, the caller is responsible for: | ||
268 | * | ||
269 | * kfree(tag); | ||
270 | * ceph_free_lockers(lockers, num_lockers); | ||
271 | */ | ||
272 | int ceph_cls_lock_info(struct ceph_osd_client *osdc, | ||
273 | struct ceph_object_id *oid, | ||
274 | struct ceph_object_locator *oloc, | ||
275 | char *lock_name, u8 *type, char **tag, | ||
276 | struct ceph_locker **lockers, u32 *num_lockers) | ||
277 | { | ||
278 | int get_info_op_buf_size; | ||
279 | int name_len = strlen(lock_name); | ||
280 | struct page *get_info_op_page, *reply_page; | ||
281 | size_t reply_len; | ||
282 | void *p, *end; | ||
283 | int ret; | ||
284 | |||
285 | get_info_op_buf_size = name_len + sizeof(__le32) + | ||
286 | CEPH_ENCODING_START_BLK_LEN; | ||
287 | if (get_info_op_buf_size > PAGE_SIZE) | ||
288 | return -E2BIG; | ||
289 | |||
290 | get_info_op_page = alloc_page(GFP_NOIO); | ||
291 | if (!get_info_op_page) | ||
292 | return -ENOMEM; | ||
293 | |||
294 | reply_page = alloc_page(GFP_NOIO); | ||
295 | if (!reply_page) { | ||
296 | __free_page(get_info_op_page); | ||
297 | return -ENOMEM; | ||
298 | } | ||
299 | |||
300 | p = page_address(get_info_op_page); | ||
301 | end = p + get_info_op_buf_size; | ||
302 | |||
303 | /* encode cls_lock_get_info_op struct */ | ||
304 | ceph_start_encoding(&p, 1, 1, | ||
305 | get_info_op_buf_size - CEPH_ENCODING_START_BLK_LEN); | ||
306 | ceph_encode_string(&p, end, lock_name, name_len); | ||
307 | |||
308 | dout("%s lock_name %s\n", __func__, lock_name); | ||
309 | ret = ceph_osdc_call(osdc, oid, oloc, "lock", "get_info", | ||
310 | CEPH_OSD_FLAG_READ, get_info_op_page, | ||
311 | get_info_op_buf_size, reply_page, &reply_len); | ||
312 | |||
313 | dout("%s: status %d\n", __func__, ret); | ||
314 | if (ret >= 0) { | ||
315 | p = page_address(reply_page); | ||
316 | end = p + reply_len; | ||
317 | |||
318 | ret = decode_lockers(&p, end, type, tag, lockers, num_lockers); | ||
319 | } | ||
320 | |||
321 | __free_page(get_info_op_page); | ||
322 | __free_page(reply_page); | ||
323 | return ret; | ||
324 | } | ||
325 | EXPORT_SYMBOL(ceph_cls_lock_info); | ||