18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/ceph/ceph_debug.h> 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/types.h> 58c2ecf20Sopenharmony_ci#include <linux/slab.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/ceph/cls_lock_client.h> 88c2ecf20Sopenharmony_ci#include <linux/ceph/decode.h> 98c2ecf20Sopenharmony_ci#include <linux/ceph/libceph.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/** 128c2ecf20Sopenharmony_ci * ceph_cls_lock - grab rados lock for object 138c2ecf20Sopenharmony_ci * @oid, @oloc: object to lock 148c2ecf20Sopenharmony_ci * @lock_name: the name of the lock 158c2ecf20Sopenharmony_ci * @type: lock type (CEPH_CLS_LOCK_EXCLUSIVE or CEPH_CLS_LOCK_SHARED) 168c2ecf20Sopenharmony_ci * @cookie: user-defined identifier for this instance of the lock 178c2ecf20Sopenharmony_ci * @tag: user-defined tag 188c2ecf20Sopenharmony_ci * @desc: user-defined lock description 198c2ecf20Sopenharmony_ci * @flags: lock flags 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * All operations on the same lock should use the same tag. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ciint ceph_cls_lock(struct ceph_osd_client *osdc, 248c2ecf20Sopenharmony_ci struct ceph_object_id *oid, 258c2ecf20Sopenharmony_ci struct ceph_object_locator *oloc, 268c2ecf20Sopenharmony_ci char *lock_name, u8 type, char *cookie, 278c2ecf20Sopenharmony_ci char *tag, char *desc, u8 flags) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci int lock_op_buf_size; 308c2ecf20Sopenharmony_ci int name_len = strlen(lock_name); 318c2ecf20Sopenharmony_ci int cookie_len = strlen(cookie); 328c2ecf20Sopenharmony_ci int tag_len = strlen(tag); 338c2ecf20Sopenharmony_ci int desc_len = strlen(desc); 348c2ecf20Sopenharmony_ci void *p, *end; 358c2ecf20Sopenharmony_ci struct page *lock_op_page; 368c2ecf20Sopenharmony_ci struct timespec64 mtime; 378c2ecf20Sopenharmony_ci int ret; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci lock_op_buf_size = name_len + sizeof(__le32) + 408c2ecf20Sopenharmony_ci cookie_len + sizeof(__le32) + 418c2ecf20Sopenharmony_ci tag_len + sizeof(__le32) + 428c2ecf20Sopenharmony_ci desc_len + sizeof(__le32) + 438c2ecf20Sopenharmony_ci sizeof(struct ceph_timespec) + 448c2ecf20Sopenharmony_ci /* flag and type */ 458c2ecf20Sopenharmony_ci sizeof(u8) + sizeof(u8) + 468c2ecf20Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 478c2ecf20Sopenharmony_ci if (lock_op_buf_size > PAGE_SIZE) 488c2ecf20Sopenharmony_ci return -E2BIG; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci lock_op_page = alloc_page(GFP_NOIO); 518c2ecf20Sopenharmony_ci if (!lock_op_page) 528c2ecf20Sopenharmony_ci return -ENOMEM; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci p = page_address(lock_op_page); 558c2ecf20Sopenharmony_ci end = p + lock_op_buf_size; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* encode cls_lock_lock_op struct */ 588c2ecf20Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 598c2ecf20Sopenharmony_ci lock_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 608c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 618c2ecf20Sopenharmony_ci ceph_encode_8(&p, type); 628c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 638c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, tag, tag_len); 648c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, desc, desc_len); 658c2ecf20Sopenharmony_ci /* only support infinite duration */ 668c2ecf20Sopenharmony_ci memset(&mtime, 0, sizeof(mtime)); 678c2ecf20Sopenharmony_ci ceph_encode_timespec64(p, &mtime); 688c2ecf20Sopenharmony_ci p += sizeof(struct ceph_timespec); 698c2ecf20Sopenharmony_ci ceph_encode_8(&p, flags); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci dout("%s lock_name %s type %d cookie %s tag %s desc %s flags 0x%x\n", 728c2ecf20Sopenharmony_ci __func__, lock_name, type, cookie, tag, desc, flags); 738c2ecf20Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "lock", 748c2ecf20Sopenharmony_ci CEPH_OSD_FLAG_WRITE, lock_op_page, 758c2ecf20Sopenharmony_ci lock_op_buf_size, NULL, NULL); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 788c2ecf20Sopenharmony_ci __free_page(lock_op_page); 798c2ecf20Sopenharmony_ci return ret; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_lock); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/** 848c2ecf20Sopenharmony_ci * ceph_cls_unlock - release rados lock for object 858c2ecf20Sopenharmony_ci * @oid, @oloc: object to lock 868c2ecf20Sopenharmony_ci * @lock_name: the name of the lock 878c2ecf20Sopenharmony_ci * @cookie: user-defined identifier for this instance of the lock 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ciint ceph_cls_unlock(struct ceph_osd_client *osdc, 908c2ecf20Sopenharmony_ci struct ceph_object_id *oid, 918c2ecf20Sopenharmony_ci struct ceph_object_locator *oloc, 928c2ecf20Sopenharmony_ci char *lock_name, char *cookie) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci int unlock_op_buf_size; 958c2ecf20Sopenharmony_ci int name_len = strlen(lock_name); 968c2ecf20Sopenharmony_ci int cookie_len = strlen(cookie); 978c2ecf20Sopenharmony_ci void *p, *end; 988c2ecf20Sopenharmony_ci struct page *unlock_op_page; 998c2ecf20Sopenharmony_ci int ret; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci unlock_op_buf_size = name_len + sizeof(__le32) + 1028c2ecf20Sopenharmony_ci cookie_len + sizeof(__le32) + 1038c2ecf20Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 1048c2ecf20Sopenharmony_ci if (unlock_op_buf_size > PAGE_SIZE) 1058c2ecf20Sopenharmony_ci return -E2BIG; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci unlock_op_page = alloc_page(GFP_NOIO); 1088c2ecf20Sopenharmony_ci if (!unlock_op_page) 1098c2ecf20Sopenharmony_ci return -ENOMEM; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci p = page_address(unlock_op_page); 1128c2ecf20Sopenharmony_ci end = p + unlock_op_buf_size; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* encode cls_lock_unlock_op struct */ 1158c2ecf20Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 1168c2ecf20Sopenharmony_ci unlock_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 1178c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 1188c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci dout("%s lock_name %s cookie %s\n", __func__, lock_name, cookie); 1218c2ecf20Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "unlock", 1228c2ecf20Sopenharmony_ci CEPH_OSD_FLAG_WRITE, unlock_op_page, 1238c2ecf20Sopenharmony_ci unlock_op_buf_size, NULL, NULL); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 1268c2ecf20Sopenharmony_ci __free_page(unlock_op_page); 1278c2ecf20Sopenharmony_ci return ret; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_unlock); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/** 1328c2ecf20Sopenharmony_ci * ceph_cls_break_lock - release rados lock for object for specified client 1338c2ecf20Sopenharmony_ci * @oid, @oloc: object to lock 1348c2ecf20Sopenharmony_ci * @lock_name: the name of the lock 1358c2ecf20Sopenharmony_ci * @cookie: user-defined identifier for this instance of the lock 1368c2ecf20Sopenharmony_ci * @locker: current lock owner 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ciint ceph_cls_break_lock(struct ceph_osd_client *osdc, 1398c2ecf20Sopenharmony_ci struct ceph_object_id *oid, 1408c2ecf20Sopenharmony_ci struct ceph_object_locator *oloc, 1418c2ecf20Sopenharmony_ci char *lock_name, char *cookie, 1428c2ecf20Sopenharmony_ci struct ceph_entity_name *locker) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci int break_op_buf_size; 1458c2ecf20Sopenharmony_ci int name_len = strlen(lock_name); 1468c2ecf20Sopenharmony_ci int cookie_len = strlen(cookie); 1478c2ecf20Sopenharmony_ci struct page *break_op_page; 1488c2ecf20Sopenharmony_ci void *p, *end; 1498c2ecf20Sopenharmony_ci int ret; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci break_op_buf_size = name_len + sizeof(__le32) + 1528c2ecf20Sopenharmony_ci cookie_len + sizeof(__le32) + 1538c2ecf20Sopenharmony_ci sizeof(u8) + sizeof(__le64) + 1548c2ecf20Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 1558c2ecf20Sopenharmony_ci if (break_op_buf_size > PAGE_SIZE) 1568c2ecf20Sopenharmony_ci return -E2BIG; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci break_op_page = alloc_page(GFP_NOIO); 1598c2ecf20Sopenharmony_ci if (!break_op_page) 1608c2ecf20Sopenharmony_ci return -ENOMEM; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci p = page_address(break_op_page); 1638c2ecf20Sopenharmony_ci end = p + break_op_buf_size; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* encode cls_lock_break_op struct */ 1668c2ecf20Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 1678c2ecf20Sopenharmony_ci break_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 1688c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 1698c2ecf20Sopenharmony_ci ceph_encode_copy(&p, locker, sizeof(*locker)); 1708c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci dout("%s lock_name %s cookie %s locker %s%llu\n", __func__, lock_name, 1738c2ecf20Sopenharmony_ci cookie, ENTITY_NAME(*locker)); 1748c2ecf20Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "break_lock", 1758c2ecf20Sopenharmony_ci CEPH_OSD_FLAG_WRITE, break_op_page, 1768c2ecf20Sopenharmony_ci break_op_buf_size, NULL, NULL); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 1798c2ecf20Sopenharmony_ci __free_page(break_op_page); 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_break_lock); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ciint ceph_cls_set_cookie(struct ceph_osd_client *osdc, 1858c2ecf20Sopenharmony_ci struct ceph_object_id *oid, 1868c2ecf20Sopenharmony_ci struct ceph_object_locator *oloc, 1878c2ecf20Sopenharmony_ci char *lock_name, u8 type, char *old_cookie, 1888c2ecf20Sopenharmony_ci char *tag, char *new_cookie) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci int cookie_op_buf_size; 1918c2ecf20Sopenharmony_ci int name_len = strlen(lock_name); 1928c2ecf20Sopenharmony_ci int old_cookie_len = strlen(old_cookie); 1938c2ecf20Sopenharmony_ci int tag_len = strlen(tag); 1948c2ecf20Sopenharmony_ci int new_cookie_len = strlen(new_cookie); 1958c2ecf20Sopenharmony_ci void *p, *end; 1968c2ecf20Sopenharmony_ci struct page *cookie_op_page; 1978c2ecf20Sopenharmony_ci int ret; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci cookie_op_buf_size = name_len + sizeof(__le32) + 2008c2ecf20Sopenharmony_ci old_cookie_len + sizeof(__le32) + 2018c2ecf20Sopenharmony_ci tag_len + sizeof(__le32) + 2028c2ecf20Sopenharmony_ci new_cookie_len + sizeof(__le32) + 2038c2ecf20Sopenharmony_ci sizeof(u8) + CEPH_ENCODING_START_BLK_LEN; 2048c2ecf20Sopenharmony_ci if (cookie_op_buf_size > PAGE_SIZE) 2058c2ecf20Sopenharmony_ci return -E2BIG; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci cookie_op_page = alloc_page(GFP_NOIO); 2088c2ecf20Sopenharmony_ci if (!cookie_op_page) 2098c2ecf20Sopenharmony_ci return -ENOMEM; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci p = page_address(cookie_op_page); 2128c2ecf20Sopenharmony_ci end = p + cookie_op_buf_size; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* encode cls_lock_set_cookie_op struct */ 2158c2ecf20Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 2168c2ecf20Sopenharmony_ci cookie_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 2178c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 2188c2ecf20Sopenharmony_ci ceph_encode_8(&p, type); 2198c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, old_cookie, old_cookie_len); 2208c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, tag, tag_len); 2218c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, new_cookie, new_cookie_len); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci dout("%s lock_name %s type %d old_cookie %s tag %s new_cookie %s\n", 2248c2ecf20Sopenharmony_ci __func__, lock_name, type, old_cookie, tag, new_cookie); 2258c2ecf20Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "set_cookie", 2268c2ecf20Sopenharmony_ci CEPH_OSD_FLAG_WRITE, cookie_op_page, 2278c2ecf20Sopenharmony_ci cookie_op_buf_size, NULL, NULL); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 2308c2ecf20Sopenharmony_ci __free_page(cookie_op_page); 2318c2ecf20Sopenharmony_ci return ret; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_set_cookie); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_civoid ceph_free_lockers(struct ceph_locker *lockers, u32 num_lockers) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci int i; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci for (i = 0; i < num_lockers; i++) 2408c2ecf20Sopenharmony_ci kfree(lockers[i].id.cookie); 2418c2ecf20Sopenharmony_ci kfree(lockers); 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_free_lockers); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic int decode_locker(void **p, void *end, struct ceph_locker *locker) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci u8 struct_v; 2488c2ecf20Sopenharmony_ci u32 len; 2498c2ecf20Sopenharmony_ci char *s; 2508c2ecf20Sopenharmony_ci int ret; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci ret = ceph_start_decoding(p, end, 1, "locker_id_t", &struct_v, &len); 2538c2ecf20Sopenharmony_ci if (ret) 2548c2ecf20Sopenharmony_ci return ret; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci ceph_decode_copy(p, &locker->id.name, sizeof(locker->id.name)); 2578c2ecf20Sopenharmony_ci s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO); 2588c2ecf20Sopenharmony_ci if (IS_ERR(s)) 2598c2ecf20Sopenharmony_ci return PTR_ERR(s); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci locker->id.cookie = s; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci ret = ceph_start_decoding(p, end, 1, "locker_info_t", &struct_v, &len); 2648c2ecf20Sopenharmony_ci if (ret) 2658c2ecf20Sopenharmony_ci return ret; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci *p += sizeof(struct ceph_timespec); /* skip expiration */ 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci ret = ceph_decode_entity_addr(p, end, &locker->info.addr); 2708c2ecf20Sopenharmony_ci if (ret) 2718c2ecf20Sopenharmony_ci return ret; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci len = ceph_decode_32(p); 2748c2ecf20Sopenharmony_ci *p += len; /* skip description */ 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci dout("%s %s%llu cookie %s addr %s\n", __func__, 2778c2ecf20Sopenharmony_ci ENTITY_NAME(locker->id.name), locker->id.cookie, 2788c2ecf20Sopenharmony_ci ceph_pr_addr(&locker->info.addr)); 2798c2ecf20Sopenharmony_ci return 0; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic int decode_lockers(void **p, void *end, u8 *type, char **tag, 2838c2ecf20Sopenharmony_ci struct ceph_locker **lockers, u32 *num_lockers) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci u8 struct_v; 2868c2ecf20Sopenharmony_ci u32 struct_len; 2878c2ecf20Sopenharmony_ci char *s; 2888c2ecf20Sopenharmony_ci int i; 2898c2ecf20Sopenharmony_ci int ret; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci ret = ceph_start_decoding(p, end, 1, "cls_lock_get_info_reply", 2928c2ecf20Sopenharmony_ci &struct_v, &struct_len); 2938c2ecf20Sopenharmony_ci if (ret) 2948c2ecf20Sopenharmony_ci return ret; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci *num_lockers = ceph_decode_32(p); 2978c2ecf20Sopenharmony_ci *lockers = kcalloc(*num_lockers, sizeof(**lockers), GFP_NOIO); 2988c2ecf20Sopenharmony_ci if (!*lockers) 2998c2ecf20Sopenharmony_ci return -ENOMEM; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci for (i = 0; i < *num_lockers; i++) { 3028c2ecf20Sopenharmony_ci ret = decode_locker(p, end, *lockers + i); 3038c2ecf20Sopenharmony_ci if (ret) 3048c2ecf20Sopenharmony_ci goto err_free_lockers; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci *type = ceph_decode_8(p); 3088c2ecf20Sopenharmony_ci s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO); 3098c2ecf20Sopenharmony_ci if (IS_ERR(s)) { 3108c2ecf20Sopenharmony_ci ret = PTR_ERR(s); 3118c2ecf20Sopenharmony_ci goto err_free_lockers; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci *tag = s; 3158c2ecf20Sopenharmony_ci return 0; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cierr_free_lockers: 3188c2ecf20Sopenharmony_ci ceph_free_lockers(*lockers, *num_lockers); 3198c2ecf20Sopenharmony_ci return ret; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci/* 3238c2ecf20Sopenharmony_ci * On success, the caller is responsible for: 3248c2ecf20Sopenharmony_ci * 3258c2ecf20Sopenharmony_ci * kfree(tag); 3268c2ecf20Sopenharmony_ci * ceph_free_lockers(lockers, num_lockers); 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ciint ceph_cls_lock_info(struct ceph_osd_client *osdc, 3298c2ecf20Sopenharmony_ci struct ceph_object_id *oid, 3308c2ecf20Sopenharmony_ci struct ceph_object_locator *oloc, 3318c2ecf20Sopenharmony_ci char *lock_name, u8 *type, char **tag, 3328c2ecf20Sopenharmony_ci struct ceph_locker **lockers, u32 *num_lockers) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci int get_info_op_buf_size; 3358c2ecf20Sopenharmony_ci int name_len = strlen(lock_name); 3368c2ecf20Sopenharmony_ci struct page *get_info_op_page, *reply_page; 3378c2ecf20Sopenharmony_ci size_t reply_len = PAGE_SIZE; 3388c2ecf20Sopenharmony_ci void *p, *end; 3398c2ecf20Sopenharmony_ci int ret; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci get_info_op_buf_size = name_len + sizeof(__le32) + 3428c2ecf20Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 3438c2ecf20Sopenharmony_ci if (get_info_op_buf_size > PAGE_SIZE) 3448c2ecf20Sopenharmony_ci return -E2BIG; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci get_info_op_page = alloc_page(GFP_NOIO); 3478c2ecf20Sopenharmony_ci if (!get_info_op_page) 3488c2ecf20Sopenharmony_ci return -ENOMEM; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci reply_page = alloc_page(GFP_NOIO); 3518c2ecf20Sopenharmony_ci if (!reply_page) { 3528c2ecf20Sopenharmony_ci __free_page(get_info_op_page); 3538c2ecf20Sopenharmony_ci return -ENOMEM; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci p = page_address(get_info_op_page); 3578c2ecf20Sopenharmony_ci end = p + get_info_op_buf_size; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci /* encode cls_lock_get_info_op struct */ 3608c2ecf20Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 3618c2ecf20Sopenharmony_ci get_info_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 3628c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci dout("%s lock_name %s\n", __func__, lock_name); 3658c2ecf20Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "get_info", 3668c2ecf20Sopenharmony_ci CEPH_OSD_FLAG_READ, get_info_op_page, 3678c2ecf20Sopenharmony_ci get_info_op_buf_size, &reply_page, &reply_len); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 3708c2ecf20Sopenharmony_ci if (ret >= 0) { 3718c2ecf20Sopenharmony_ci p = page_address(reply_page); 3728c2ecf20Sopenharmony_ci end = p + reply_len; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci ret = decode_lockers(&p, end, type, tag, lockers, num_lockers); 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci __free_page(get_info_op_page); 3788c2ecf20Sopenharmony_ci __free_page(reply_page); 3798c2ecf20Sopenharmony_ci return ret; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_lock_info); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ciint ceph_cls_assert_locked(struct ceph_osd_request *req, int which, 3848c2ecf20Sopenharmony_ci char *lock_name, u8 type, char *cookie, char *tag) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci int assert_op_buf_size; 3878c2ecf20Sopenharmony_ci int name_len = strlen(lock_name); 3888c2ecf20Sopenharmony_ci int cookie_len = strlen(cookie); 3898c2ecf20Sopenharmony_ci int tag_len = strlen(tag); 3908c2ecf20Sopenharmony_ci struct page **pages; 3918c2ecf20Sopenharmony_ci void *p, *end; 3928c2ecf20Sopenharmony_ci int ret; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci assert_op_buf_size = name_len + sizeof(__le32) + 3958c2ecf20Sopenharmony_ci cookie_len + sizeof(__le32) + 3968c2ecf20Sopenharmony_ci tag_len + sizeof(__le32) + 3978c2ecf20Sopenharmony_ci sizeof(u8) + CEPH_ENCODING_START_BLK_LEN; 3988c2ecf20Sopenharmony_ci if (assert_op_buf_size > PAGE_SIZE) 3998c2ecf20Sopenharmony_ci return -E2BIG; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci ret = osd_req_op_cls_init(req, which, "lock", "assert_locked"); 4028c2ecf20Sopenharmony_ci if (ret) 4038c2ecf20Sopenharmony_ci return ret; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci pages = ceph_alloc_page_vector(1, GFP_NOIO); 4068c2ecf20Sopenharmony_ci if (IS_ERR(pages)) 4078c2ecf20Sopenharmony_ci return PTR_ERR(pages); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci p = page_address(pages[0]); 4108c2ecf20Sopenharmony_ci end = p + assert_op_buf_size; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* encode cls_lock_assert_op struct */ 4138c2ecf20Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 4148c2ecf20Sopenharmony_ci assert_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 4158c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 4168c2ecf20Sopenharmony_ci ceph_encode_8(&p, type); 4178c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 4188c2ecf20Sopenharmony_ci ceph_encode_string(&p, end, tag, tag_len); 4198c2ecf20Sopenharmony_ci WARN_ON(p != end); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci osd_req_op_cls_request_data_pages(req, which, pages, assert_op_buf_size, 4228c2ecf20Sopenharmony_ci 0, false, true); 4238c2ecf20Sopenharmony_ci return 0; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_assert_locked); 426