162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/ceph/ceph_debug.h> 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/types.h> 562306a36Sopenharmony_ci#include <linux/slab.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/ceph/cls_lock_client.h> 862306a36Sopenharmony_ci#include <linux/ceph/decode.h> 962306a36Sopenharmony_ci#include <linux/ceph/libceph.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/** 1262306a36Sopenharmony_ci * ceph_cls_lock - grab rados lock for object 1362306a36Sopenharmony_ci * @osdc: OSD client instance 1462306a36Sopenharmony_ci * @oid: object to lock 1562306a36Sopenharmony_ci * @oloc: object to lock 1662306a36Sopenharmony_ci * @lock_name: the name of the lock 1762306a36Sopenharmony_ci * @type: lock type (CEPH_CLS_LOCK_EXCLUSIVE or CEPH_CLS_LOCK_SHARED) 1862306a36Sopenharmony_ci * @cookie: user-defined identifier for this instance of the lock 1962306a36Sopenharmony_ci * @tag: user-defined tag 2062306a36Sopenharmony_ci * @desc: user-defined lock description 2162306a36Sopenharmony_ci * @flags: lock flags 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * All operations on the same lock should use the same tag. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ciint ceph_cls_lock(struct ceph_osd_client *osdc, 2662306a36Sopenharmony_ci struct ceph_object_id *oid, 2762306a36Sopenharmony_ci struct ceph_object_locator *oloc, 2862306a36Sopenharmony_ci char *lock_name, u8 type, char *cookie, 2962306a36Sopenharmony_ci char *tag, char *desc, u8 flags) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci int lock_op_buf_size; 3262306a36Sopenharmony_ci int name_len = strlen(lock_name); 3362306a36Sopenharmony_ci int cookie_len = strlen(cookie); 3462306a36Sopenharmony_ci int tag_len = strlen(tag); 3562306a36Sopenharmony_ci int desc_len = strlen(desc); 3662306a36Sopenharmony_ci void *p, *end; 3762306a36Sopenharmony_ci struct page *lock_op_page; 3862306a36Sopenharmony_ci struct timespec64 mtime; 3962306a36Sopenharmony_ci int ret; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci lock_op_buf_size = name_len + sizeof(__le32) + 4262306a36Sopenharmony_ci cookie_len + sizeof(__le32) + 4362306a36Sopenharmony_ci tag_len + sizeof(__le32) + 4462306a36Sopenharmony_ci desc_len + sizeof(__le32) + 4562306a36Sopenharmony_ci sizeof(struct ceph_timespec) + 4662306a36Sopenharmony_ci /* flag and type */ 4762306a36Sopenharmony_ci sizeof(u8) + sizeof(u8) + 4862306a36Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 4962306a36Sopenharmony_ci if (lock_op_buf_size > PAGE_SIZE) 5062306a36Sopenharmony_ci return -E2BIG; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci lock_op_page = alloc_page(GFP_NOIO); 5362306a36Sopenharmony_ci if (!lock_op_page) 5462306a36Sopenharmony_ci return -ENOMEM; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci p = page_address(lock_op_page); 5762306a36Sopenharmony_ci end = p + lock_op_buf_size; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* encode cls_lock_lock_op struct */ 6062306a36Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 6162306a36Sopenharmony_ci lock_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 6262306a36Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 6362306a36Sopenharmony_ci ceph_encode_8(&p, type); 6462306a36Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 6562306a36Sopenharmony_ci ceph_encode_string(&p, end, tag, tag_len); 6662306a36Sopenharmony_ci ceph_encode_string(&p, end, desc, desc_len); 6762306a36Sopenharmony_ci /* only support infinite duration */ 6862306a36Sopenharmony_ci memset(&mtime, 0, sizeof(mtime)); 6962306a36Sopenharmony_ci ceph_encode_timespec64(p, &mtime); 7062306a36Sopenharmony_ci p += sizeof(struct ceph_timespec); 7162306a36Sopenharmony_ci ceph_encode_8(&p, flags); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci dout("%s lock_name %s type %d cookie %s tag %s desc %s flags 0x%x\n", 7462306a36Sopenharmony_ci __func__, lock_name, type, cookie, tag, desc, flags); 7562306a36Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "lock", 7662306a36Sopenharmony_ci CEPH_OSD_FLAG_WRITE, lock_op_page, 7762306a36Sopenharmony_ci lock_op_buf_size, NULL, NULL); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 8062306a36Sopenharmony_ci __free_page(lock_op_page); 8162306a36Sopenharmony_ci return ret; 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_lock); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/** 8662306a36Sopenharmony_ci * ceph_cls_unlock - release rados lock for object 8762306a36Sopenharmony_ci * @osdc: OSD client instance 8862306a36Sopenharmony_ci * @oid: object to lock 8962306a36Sopenharmony_ci * @oloc: object to lock 9062306a36Sopenharmony_ci * @lock_name: the name of the lock 9162306a36Sopenharmony_ci * @cookie: user-defined identifier for this instance of the lock 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ciint ceph_cls_unlock(struct ceph_osd_client *osdc, 9462306a36Sopenharmony_ci struct ceph_object_id *oid, 9562306a36Sopenharmony_ci struct ceph_object_locator *oloc, 9662306a36Sopenharmony_ci char *lock_name, char *cookie) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci int unlock_op_buf_size; 9962306a36Sopenharmony_ci int name_len = strlen(lock_name); 10062306a36Sopenharmony_ci int cookie_len = strlen(cookie); 10162306a36Sopenharmony_ci void *p, *end; 10262306a36Sopenharmony_ci struct page *unlock_op_page; 10362306a36Sopenharmony_ci int ret; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci unlock_op_buf_size = name_len + sizeof(__le32) + 10662306a36Sopenharmony_ci cookie_len + sizeof(__le32) + 10762306a36Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 10862306a36Sopenharmony_ci if (unlock_op_buf_size > PAGE_SIZE) 10962306a36Sopenharmony_ci return -E2BIG; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci unlock_op_page = alloc_page(GFP_NOIO); 11262306a36Sopenharmony_ci if (!unlock_op_page) 11362306a36Sopenharmony_ci return -ENOMEM; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci p = page_address(unlock_op_page); 11662306a36Sopenharmony_ci end = p + unlock_op_buf_size; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* encode cls_lock_unlock_op struct */ 11962306a36Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 12062306a36Sopenharmony_ci unlock_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 12162306a36Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 12262306a36Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci dout("%s lock_name %s cookie %s\n", __func__, lock_name, cookie); 12562306a36Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "unlock", 12662306a36Sopenharmony_ci CEPH_OSD_FLAG_WRITE, unlock_op_page, 12762306a36Sopenharmony_ci unlock_op_buf_size, NULL, NULL); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 13062306a36Sopenharmony_ci __free_page(unlock_op_page); 13162306a36Sopenharmony_ci return ret; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_unlock); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci/** 13662306a36Sopenharmony_ci * ceph_cls_break_lock - release rados lock for object for specified client 13762306a36Sopenharmony_ci * @osdc: OSD client instance 13862306a36Sopenharmony_ci * @oid: object to lock 13962306a36Sopenharmony_ci * @oloc: object to lock 14062306a36Sopenharmony_ci * @lock_name: the name of the lock 14162306a36Sopenharmony_ci * @cookie: user-defined identifier for this instance of the lock 14262306a36Sopenharmony_ci * @locker: current lock owner 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ciint ceph_cls_break_lock(struct ceph_osd_client *osdc, 14562306a36Sopenharmony_ci struct ceph_object_id *oid, 14662306a36Sopenharmony_ci struct ceph_object_locator *oloc, 14762306a36Sopenharmony_ci char *lock_name, char *cookie, 14862306a36Sopenharmony_ci struct ceph_entity_name *locker) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci int break_op_buf_size; 15162306a36Sopenharmony_ci int name_len = strlen(lock_name); 15262306a36Sopenharmony_ci int cookie_len = strlen(cookie); 15362306a36Sopenharmony_ci struct page *break_op_page; 15462306a36Sopenharmony_ci void *p, *end; 15562306a36Sopenharmony_ci int ret; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci break_op_buf_size = name_len + sizeof(__le32) + 15862306a36Sopenharmony_ci cookie_len + sizeof(__le32) + 15962306a36Sopenharmony_ci sizeof(u8) + sizeof(__le64) + 16062306a36Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 16162306a36Sopenharmony_ci if (break_op_buf_size > PAGE_SIZE) 16262306a36Sopenharmony_ci return -E2BIG; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci break_op_page = alloc_page(GFP_NOIO); 16562306a36Sopenharmony_ci if (!break_op_page) 16662306a36Sopenharmony_ci return -ENOMEM; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci p = page_address(break_op_page); 16962306a36Sopenharmony_ci end = p + break_op_buf_size; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* encode cls_lock_break_op struct */ 17262306a36Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 17362306a36Sopenharmony_ci break_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 17462306a36Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 17562306a36Sopenharmony_ci ceph_encode_copy(&p, locker, sizeof(*locker)); 17662306a36Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci dout("%s lock_name %s cookie %s locker %s%llu\n", __func__, lock_name, 17962306a36Sopenharmony_ci cookie, ENTITY_NAME(*locker)); 18062306a36Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "break_lock", 18162306a36Sopenharmony_ci CEPH_OSD_FLAG_WRITE, break_op_page, 18262306a36Sopenharmony_ci break_op_buf_size, NULL, NULL); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 18562306a36Sopenharmony_ci __free_page(break_op_page); 18662306a36Sopenharmony_ci return ret; 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_break_lock); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ciint ceph_cls_set_cookie(struct ceph_osd_client *osdc, 19162306a36Sopenharmony_ci struct ceph_object_id *oid, 19262306a36Sopenharmony_ci struct ceph_object_locator *oloc, 19362306a36Sopenharmony_ci char *lock_name, u8 type, char *old_cookie, 19462306a36Sopenharmony_ci char *tag, char *new_cookie) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci int cookie_op_buf_size; 19762306a36Sopenharmony_ci int name_len = strlen(lock_name); 19862306a36Sopenharmony_ci int old_cookie_len = strlen(old_cookie); 19962306a36Sopenharmony_ci int tag_len = strlen(tag); 20062306a36Sopenharmony_ci int new_cookie_len = strlen(new_cookie); 20162306a36Sopenharmony_ci void *p, *end; 20262306a36Sopenharmony_ci struct page *cookie_op_page; 20362306a36Sopenharmony_ci int ret; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci cookie_op_buf_size = name_len + sizeof(__le32) + 20662306a36Sopenharmony_ci old_cookie_len + sizeof(__le32) + 20762306a36Sopenharmony_ci tag_len + sizeof(__le32) + 20862306a36Sopenharmony_ci new_cookie_len + sizeof(__le32) + 20962306a36Sopenharmony_ci sizeof(u8) + CEPH_ENCODING_START_BLK_LEN; 21062306a36Sopenharmony_ci if (cookie_op_buf_size > PAGE_SIZE) 21162306a36Sopenharmony_ci return -E2BIG; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci cookie_op_page = alloc_page(GFP_NOIO); 21462306a36Sopenharmony_ci if (!cookie_op_page) 21562306a36Sopenharmony_ci return -ENOMEM; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci p = page_address(cookie_op_page); 21862306a36Sopenharmony_ci end = p + cookie_op_buf_size; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* encode cls_lock_set_cookie_op struct */ 22162306a36Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 22262306a36Sopenharmony_ci cookie_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 22362306a36Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 22462306a36Sopenharmony_ci ceph_encode_8(&p, type); 22562306a36Sopenharmony_ci ceph_encode_string(&p, end, old_cookie, old_cookie_len); 22662306a36Sopenharmony_ci ceph_encode_string(&p, end, tag, tag_len); 22762306a36Sopenharmony_ci ceph_encode_string(&p, end, new_cookie, new_cookie_len); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci dout("%s lock_name %s type %d old_cookie %s tag %s new_cookie %s\n", 23062306a36Sopenharmony_ci __func__, lock_name, type, old_cookie, tag, new_cookie); 23162306a36Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "set_cookie", 23262306a36Sopenharmony_ci CEPH_OSD_FLAG_WRITE, cookie_op_page, 23362306a36Sopenharmony_ci cookie_op_buf_size, NULL, NULL); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 23662306a36Sopenharmony_ci __free_page(cookie_op_page); 23762306a36Sopenharmony_ci return ret; 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_set_cookie); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_civoid ceph_free_lockers(struct ceph_locker *lockers, u32 num_lockers) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci int i; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci for (i = 0; i < num_lockers; i++) 24662306a36Sopenharmony_ci kfree(lockers[i].id.cookie); 24762306a36Sopenharmony_ci kfree(lockers); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_free_lockers); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic int decode_locker(void **p, void *end, struct ceph_locker *locker) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci u8 struct_v; 25462306a36Sopenharmony_ci u32 len; 25562306a36Sopenharmony_ci char *s; 25662306a36Sopenharmony_ci int ret; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci ret = ceph_start_decoding(p, end, 1, "locker_id_t", &struct_v, &len); 25962306a36Sopenharmony_ci if (ret) 26062306a36Sopenharmony_ci return ret; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci ceph_decode_copy(p, &locker->id.name, sizeof(locker->id.name)); 26362306a36Sopenharmony_ci s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO); 26462306a36Sopenharmony_ci if (IS_ERR(s)) 26562306a36Sopenharmony_ci return PTR_ERR(s); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci locker->id.cookie = s; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci ret = ceph_start_decoding(p, end, 1, "locker_info_t", &struct_v, &len); 27062306a36Sopenharmony_ci if (ret) 27162306a36Sopenharmony_ci return ret; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci *p += sizeof(struct ceph_timespec); /* skip expiration */ 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci ret = ceph_decode_entity_addr(p, end, &locker->info.addr); 27662306a36Sopenharmony_ci if (ret) 27762306a36Sopenharmony_ci return ret; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci len = ceph_decode_32(p); 28062306a36Sopenharmony_ci *p += len; /* skip description */ 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci dout("%s %s%llu cookie %s addr %s\n", __func__, 28362306a36Sopenharmony_ci ENTITY_NAME(locker->id.name), locker->id.cookie, 28462306a36Sopenharmony_ci ceph_pr_addr(&locker->info.addr)); 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic int decode_lockers(void **p, void *end, u8 *type, char **tag, 28962306a36Sopenharmony_ci struct ceph_locker **lockers, u32 *num_lockers) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci u8 struct_v; 29262306a36Sopenharmony_ci u32 struct_len; 29362306a36Sopenharmony_ci char *s; 29462306a36Sopenharmony_ci int i; 29562306a36Sopenharmony_ci int ret; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci ret = ceph_start_decoding(p, end, 1, "cls_lock_get_info_reply", 29862306a36Sopenharmony_ci &struct_v, &struct_len); 29962306a36Sopenharmony_ci if (ret) 30062306a36Sopenharmony_ci return ret; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci *num_lockers = ceph_decode_32(p); 30362306a36Sopenharmony_ci *lockers = kcalloc(*num_lockers, sizeof(**lockers), GFP_NOIO); 30462306a36Sopenharmony_ci if (!*lockers) 30562306a36Sopenharmony_ci return -ENOMEM; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci for (i = 0; i < *num_lockers; i++) { 30862306a36Sopenharmony_ci ret = decode_locker(p, end, *lockers + i); 30962306a36Sopenharmony_ci if (ret) 31062306a36Sopenharmony_ci goto err_free_lockers; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci *type = ceph_decode_8(p); 31462306a36Sopenharmony_ci s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO); 31562306a36Sopenharmony_ci if (IS_ERR(s)) { 31662306a36Sopenharmony_ci ret = PTR_ERR(s); 31762306a36Sopenharmony_ci goto err_free_lockers; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci *tag = s; 32162306a36Sopenharmony_ci return 0; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cierr_free_lockers: 32462306a36Sopenharmony_ci ceph_free_lockers(*lockers, *num_lockers); 32562306a36Sopenharmony_ci return ret; 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/* 32962306a36Sopenharmony_ci * On success, the caller is responsible for: 33062306a36Sopenharmony_ci * 33162306a36Sopenharmony_ci * kfree(tag); 33262306a36Sopenharmony_ci * ceph_free_lockers(lockers, num_lockers); 33362306a36Sopenharmony_ci */ 33462306a36Sopenharmony_ciint ceph_cls_lock_info(struct ceph_osd_client *osdc, 33562306a36Sopenharmony_ci struct ceph_object_id *oid, 33662306a36Sopenharmony_ci struct ceph_object_locator *oloc, 33762306a36Sopenharmony_ci char *lock_name, u8 *type, char **tag, 33862306a36Sopenharmony_ci struct ceph_locker **lockers, u32 *num_lockers) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci int get_info_op_buf_size; 34162306a36Sopenharmony_ci int name_len = strlen(lock_name); 34262306a36Sopenharmony_ci struct page *get_info_op_page, *reply_page; 34362306a36Sopenharmony_ci size_t reply_len = PAGE_SIZE; 34462306a36Sopenharmony_ci void *p, *end; 34562306a36Sopenharmony_ci int ret; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci get_info_op_buf_size = name_len + sizeof(__le32) + 34862306a36Sopenharmony_ci CEPH_ENCODING_START_BLK_LEN; 34962306a36Sopenharmony_ci if (get_info_op_buf_size > PAGE_SIZE) 35062306a36Sopenharmony_ci return -E2BIG; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci get_info_op_page = alloc_page(GFP_NOIO); 35362306a36Sopenharmony_ci if (!get_info_op_page) 35462306a36Sopenharmony_ci return -ENOMEM; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci reply_page = alloc_page(GFP_NOIO); 35762306a36Sopenharmony_ci if (!reply_page) { 35862306a36Sopenharmony_ci __free_page(get_info_op_page); 35962306a36Sopenharmony_ci return -ENOMEM; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci p = page_address(get_info_op_page); 36362306a36Sopenharmony_ci end = p + get_info_op_buf_size; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci /* encode cls_lock_get_info_op struct */ 36662306a36Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 36762306a36Sopenharmony_ci get_info_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 36862306a36Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci dout("%s lock_name %s\n", __func__, lock_name); 37162306a36Sopenharmony_ci ret = ceph_osdc_call(osdc, oid, oloc, "lock", "get_info", 37262306a36Sopenharmony_ci CEPH_OSD_FLAG_READ, get_info_op_page, 37362306a36Sopenharmony_ci get_info_op_buf_size, &reply_page, &reply_len); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci dout("%s: status %d\n", __func__, ret); 37662306a36Sopenharmony_ci if (ret >= 0) { 37762306a36Sopenharmony_ci p = page_address(reply_page); 37862306a36Sopenharmony_ci end = p + reply_len; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci ret = decode_lockers(&p, end, type, tag, lockers, num_lockers); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci __free_page(get_info_op_page); 38462306a36Sopenharmony_ci __free_page(reply_page); 38562306a36Sopenharmony_ci return ret; 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_lock_info); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ciint ceph_cls_assert_locked(struct ceph_osd_request *req, int which, 39062306a36Sopenharmony_ci char *lock_name, u8 type, char *cookie, char *tag) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci int assert_op_buf_size; 39362306a36Sopenharmony_ci int name_len = strlen(lock_name); 39462306a36Sopenharmony_ci int cookie_len = strlen(cookie); 39562306a36Sopenharmony_ci int tag_len = strlen(tag); 39662306a36Sopenharmony_ci struct page **pages; 39762306a36Sopenharmony_ci void *p, *end; 39862306a36Sopenharmony_ci int ret; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci assert_op_buf_size = name_len + sizeof(__le32) + 40162306a36Sopenharmony_ci cookie_len + sizeof(__le32) + 40262306a36Sopenharmony_ci tag_len + sizeof(__le32) + 40362306a36Sopenharmony_ci sizeof(u8) + CEPH_ENCODING_START_BLK_LEN; 40462306a36Sopenharmony_ci if (assert_op_buf_size > PAGE_SIZE) 40562306a36Sopenharmony_ci return -E2BIG; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci ret = osd_req_op_cls_init(req, which, "lock", "assert_locked"); 40862306a36Sopenharmony_ci if (ret) 40962306a36Sopenharmony_ci return ret; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci pages = ceph_alloc_page_vector(1, GFP_NOIO); 41262306a36Sopenharmony_ci if (IS_ERR(pages)) 41362306a36Sopenharmony_ci return PTR_ERR(pages); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci p = page_address(pages[0]); 41662306a36Sopenharmony_ci end = p + assert_op_buf_size; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /* encode cls_lock_assert_op struct */ 41962306a36Sopenharmony_ci ceph_start_encoding(&p, 1, 1, 42062306a36Sopenharmony_ci assert_op_buf_size - CEPH_ENCODING_START_BLK_LEN); 42162306a36Sopenharmony_ci ceph_encode_string(&p, end, lock_name, name_len); 42262306a36Sopenharmony_ci ceph_encode_8(&p, type); 42362306a36Sopenharmony_ci ceph_encode_string(&p, end, cookie, cookie_len); 42462306a36Sopenharmony_ci ceph_encode_string(&p, end, tag, tag_len); 42562306a36Sopenharmony_ci WARN_ON(p != end); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci osd_req_op_cls_request_data_pages(req, which, pages, assert_op_buf_size, 42862306a36Sopenharmony_ci 0, false, true); 42962306a36Sopenharmony_ci return 0; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ciEXPORT_SYMBOL(ceph_cls_assert_locked); 432