1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/ceph/ceph_debug.h>
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/types.h>
5*4882a593Smuzhiyun #include <linux/slab.h>
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/ceph/cls_lock_client.h>
8*4882a593Smuzhiyun #include <linux/ceph/decode.h>
9*4882a593Smuzhiyun #include <linux/ceph/libceph.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun /**
12*4882a593Smuzhiyun * ceph_cls_lock - grab rados lock for object
13*4882a593Smuzhiyun * @oid, @oloc: object to lock
14*4882a593Smuzhiyun * @lock_name: the name of the lock
15*4882a593Smuzhiyun * @type: lock type (CEPH_CLS_LOCK_EXCLUSIVE or CEPH_CLS_LOCK_SHARED)
16*4882a593Smuzhiyun * @cookie: user-defined identifier for this instance of the lock
17*4882a593Smuzhiyun * @tag: user-defined tag
18*4882a593Smuzhiyun * @desc: user-defined lock description
19*4882a593Smuzhiyun * @flags: lock flags
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * All operations on the same lock should use the same tag.
22*4882a593Smuzhiyun */
ceph_cls_lock(struct ceph_osd_client * osdc,struct ceph_object_id * oid,struct ceph_object_locator * oloc,char * lock_name,u8 type,char * cookie,char * tag,char * desc,u8 flags)23*4882a593Smuzhiyun int ceph_cls_lock(struct ceph_osd_client *osdc,
24*4882a593Smuzhiyun struct ceph_object_id *oid,
25*4882a593Smuzhiyun struct ceph_object_locator *oloc,
26*4882a593Smuzhiyun char *lock_name, u8 type, char *cookie,
27*4882a593Smuzhiyun char *tag, char *desc, u8 flags)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun int lock_op_buf_size;
30*4882a593Smuzhiyun int name_len = strlen(lock_name);
31*4882a593Smuzhiyun int cookie_len = strlen(cookie);
32*4882a593Smuzhiyun int tag_len = strlen(tag);
33*4882a593Smuzhiyun int desc_len = strlen(desc);
34*4882a593Smuzhiyun void *p, *end;
35*4882a593Smuzhiyun struct page *lock_op_page;
36*4882a593Smuzhiyun struct timespec64 mtime;
37*4882a593Smuzhiyun int ret;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun lock_op_buf_size = name_len + sizeof(__le32) +
40*4882a593Smuzhiyun cookie_len + sizeof(__le32) +
41*4882a593Smuzhiyun tag_len + sizeof(__le32) +
42*4882a593Smuzhiyun desc_len + sizeof(__le32) +
43*4882a593Smuzhiyun sizeof(struct ceph_timespec) +
44*4882a593Smuzhiyun /* flag and type */
45*4882a593Smuzhiyun sizeof(u8) + sizeof(u8) +
46*4882a593Smuzhiyun CEPH_ENCODING_START_BLK_LEN;
47*4882a593Smuzhiyun if (lock_op_buf_size > PAGE_SIZE)
48*4882a593Smuzhiyun return -E2BIG;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun lock_op_page = alloc_page(GFP_NOIO);
51*4882a593Smuzhiyun if (!lock_op_page)
52*4882a593Smuzhiyun return -ENOMEM;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun p = page_address(lock_op_page);
55*4882a593Smuzhiyun end = p + lock_op_buf_size;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* encode cls_lock_lock_op struct */
58*4882a593Smuzhiyun ceph_start_encoding(&p, 1, 1,
59*4882a593Smuzhiyun lock_op_buf_size - CEPH_ENCODING_START_BLK_LEN);
60*4882a593Smuzhiyun ceph_encode_string(&p, end, lock_name, name_len);
61*4882a593Smuzhiyun ceph_encode_8(&p, type);
62*4882a593Smuzhiyun ceph_encode_string(&p, end, cookie, cookie_len);
63*4882a593Smuzhiyun ceph_encode_string(&p, end, tag, tag_len);
64*4882a593Smuzhiyun ceph_encode_string(&p, end, desc, desc_len);
65*4882a593Smuzhiyun /* only support infinite duration */
66*4882a593Smuzhiyun memset(&mtime, 0, sizeof(mtime));
67*4882a593Smuzhiyun ceph_encode_timespec64(p, &mtime);
68*4882a593Smuzhiyun p += sizeof(struct ceph_timespec);
69*4882a593Smuzhiyun ceph_encode_8(&p, flags);
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun dout("%s lock_name %s type %d cookie %s tag %s desc %s flags 0x%x\n",
72*4882a593Smuzhiyun __func__, lock_name, type, cookie, tag, desc, flags);
73*4882a593Smuzhiyun ret = ceph_osdc_call(osdc, oid, oloc, "lock", "lock",
74*4882a593Smuzhiyun CEPH_OSD_FLAG_WRITE, lock_op_page,
75*4882a593Smuzhiyun lock_op_buf_size, NULL, NULL);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun dout("%s: status %d\n", __func__, ret);
78*4882a593Smuzhiyun __free_page(lock_op_page);
79*4882a593Smuzhiyun return ret;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_cls_lock);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /**
84*4882a593Smuzhiyun * ceph_cls_unlock - release rados lock for object
85*4882a593Smuzhiyun * @oid, @oloc: object to lock
86*4882a593Smuzhiyun * @lock_name: the name of the lock
87*4882a593Smuzhiyun * @cookie: user-defined identifier for this instance of the lock
88*4882a593Smuzhiyun */
ceph_cls_unlock(struct ceph_osd_client * osdc,struct ceph_object_id * oid,struct ceph_object_locator * oloc,char * lock_name,char * cookie)89*4882a593Smuzhiyun int ceph_cls_unlock(struct ceph_osd_client *osdc,
90*4882a593Smuzhiyun struct ceph_object_id *oid,
91*4882a593Smuzhiyun struct ceph_object_locator *oloc,
92*4882a593Smuzhiyun char *lock_name, char *cookie)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun int unlock_op_buf_size;
95*4882a593Smuzhiyun int name_len = strlen(lock_name);
96*4882a593Smuzhiyun int cookie_len = strlen(cookie);
97*4882a593Smuzhiyun void *p, *end;
98*4882a593Smuzhiyun struct page *unlock_op_page;
99*4882a593Smuzhiyun int ret;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun unlock_op_buf_size = name_len + sizeof(__le32) +
102*4882a593Smuzhiyun cookie_len + sizeof(__le32) +
103*4882a593Smuzhiyun CEPH_ENCODING_START_BLK_LEN;
104*4882a593Smuzhiyun if (unlock_op_buf_size > PAGE_SIZE)
105*4882a593Smuzhiyun return -E2BIG;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun unlock_op_page = alloc_page(GFP_NOIO);
108*4882a593Smuzhiyun if (!unlock_op_page)
109*4882a593Smuzhiyun return -ENOMEM;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun p = page_address(unlock_op_page);
112*4882a593Smuzhiyun end = p + unlock_op_buf_size;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /* encode cls_lock_unlock_op struct */
115*4882a593Smuzhiyun ceph_start_encoding(&p, 1, 1,
116*4882a593Smuzhiyun unlock_op_buf_size - CEPH_ENCODING_START_BLK_LEN);
117*4882a593Smuzhiyun ceph_encode_string(&p, end, lock_name, name_len);
118*4882a593Smuzhiyun ceph_encode_string(&p, end, cookie, cookie_len);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun dout("%s lock_name %s cookie %s\n", __func__, lock_name, cookie);
121*4882a593Smuzhiyun ret = ceph_osdc_call(osdc, oid, oloc, "lock", "unlock",
122*4882a593Smuzhiyun CEPH_OSD_FLAG_WRITE, unlock_op_page,
123*4882a593Smuzhiyun unlock_op_buf_size, NULL, NULL);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun dout("%s: status %d\n", __func__, ret);
126*4882a593Smuzhiyun __free_page(unlock_op_page);
127*4882a593Smuzhiyun return ret;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_cls_unlock);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /**
132*4882a593Smuzhiyun * ceph_cls_break_lock - release rados lock for object for specified client
133*4882a593Smuzhiyun * @oid, @oloc: object to lock
134*4882a593Smuzhiyun * @lock_name: the name of the lock
135*4882a593Smuzhiyun * @cookie: user-defined identifier for this instance of the lock
136*4882a593Smuzhiyun * @locker: current lock owner
137*4882a593Smuzhiyun */
ceph_cls_break_lock(struct ceph_osd_client * osdc,struct ceph_object_id * oid,struct ceph_object_locator * oloc,char * lock_name,char * cookie,struct ceph_entity_name * locker)138*4882a593Smuzhiyun int ceph_cls_break_lock(struct ceph_osd_client *osdc,
139*4882a593Smuzhiyun struct ceph_object_id *oid,
140*4882a593Smuzhiyun struct ceph_object_locator *oloc,
141*4882a593Smuzhiyun char *lock_name, char *cookie,
142*4882a593Smuzhiyun struct ceph_entity_name *locker)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun int break_op_buf_size;
145*4882a593Smuzhiyun int name_len = strlen(lock_name);
146*4882a593Smuzhiyun int cookie_len = strlen(cookie);
147*4882a593Smuzhiyun struct page *break_op_page;
148*4882a593Smuzhiyun void *p, *end;
149*4882a593Smuzhiyun int ret;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun break_op_buf_size = name_len + sizeof(__le32) +
152*4882a593Smuzhiyun cookie_len + sizeof(__le32) +
153*4882a593Smuzhiyun sizeof(u8) + sizeof(__le64) +
154*4882a593Smuzhiyun CEPH_ENCODING_START_BLK_LEN;
155*4882a593Smuzhiyun if (break_op_buf_size > PAGE_SIZE)
156*4882a593Smuzhiyun return -E2BIG;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun break_op_page = alloc_page(GFP_NOIO);
159*4882a593Smuzhiyun if (!break_op_page)
160*4882a593Smuzhiyun return -ENOMEM;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun p = page_address(break_op_page);
163*4882a593Smuzhiyun end = p + break_op_buf_size;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* encode cls_lock_break_op struct */
166*4882a593Smuzhiyun ceph_start_encoding(&p, 1, 1,
167*4882a593Smuzhiyun break_op_buf_size - CEPH_ENCODING_START_BLK_LEN);
168*4882a593Smuzhiyun ceph_encode_string(&p, end, lock_name, name_len);
169*4882a593Smuzhiyun ceph_encode_copy(&p, locker, sizeof(*locker));
170*4882a593Smuzhiyun ceph_encode_string(&p, end, cookie, cookie_len);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun dout("%s lock_name %s cookie %s locker %s%llu\n", __func__, lock_name,
173*4882a593Smuzhiyun cookie, ENTITY_NAME(*locker));
174*4882a593Smuzhiyun ret = ceph_osdc_call(osdc, oid, oloc, "lock", "break_lock",
175*4882a593Smuzhiyun CEPH_OSD_FLAG_WRITE, break_op_page,
176*4882a593Smuzhiyun break_op_buf_size, NULL, NULL);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun dout("%s: status %d\n", __func__, ret);
179*4882a593Smuzhiyun __free_page(break_op_page);
180*4882a593Smuzhiyun return ret;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_cls_break_lock);
183*4882a593Smuzhiyun
ceph_cls_set_cookie(struct ceph_osd_client * osdc,struct ceph_object_id * oid,struct ceph_object_locator * oloc,char * lock_name,u8 type,char * old_cookie,char * tag,char * new_cookie)184*4882a593Smuzhiyun int ceph_cls_set_cookie(struct ceph_osd_client *osdc,
185*4882a593Smuzhiyun struct ceph_object_id *oid,
186*4882a593Smuzhiyun struct ceph_object_locator *oloc,
187*4882a593Smuzhiyun char *lock_name, u8 type, char *old_cookie,
188*4882a593Smuzhiyun char *tag, char *new_cookie)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun int cookie_op_buf_size;
191*4882a593Smuzhiyun int name_len = strlen(lock_name);
192*4882a593Smuzhiyun int old_cookie_len = strlen(old_cookie);
193*4882a593Smuzhiyun int tag_len = strlen(tag);
194*4882a593Smuzhiyun int new_cookie_len = strlen(new_cookie);
195*4882a593Smuzhiyun void *p, *end;
196*4882a593Smuzhiyun struct page *cookie_op_page;
197*4882a593Smuzhiyun int ret;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun cookie_op_buf_size = name_len + sizeof(__le32) +
200*4882a593Smuzhiyun old_cookie_len + sizeof(__le32) +
201*4882a593Smuzhiyun tag_len + sizeof(__le32) +
202*4882a593Smuzhiyun new_cookie_len + sizeof(__le32) +
203*4882a593Smuzhiyun sizeof(u8) + CEPH_ENCODING_START_BLK_LEN;
204*4882a593Smuzhiyun if (cookie_op_buf_size > PAGE_SIZE)
205*4882a593Smuzhiyun return -E2BIG;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun cookie_op_page = alloc_page(GFP_NOIO);
208*4882a593Smuzhiyun if (!cookie_op_page)
209*4882a593Smuzhiyun return -ENOMEM;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun p = page_address(cookie_op_page);
212*4882a593Smuzhiyun end = p + cookie_op_buf_size;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* encode cls_lock_set_cookie_op struct */
215*4882a593Smuzhiyun ceph_start_encoding(&p, 1, 1,
216*4882a593Smuzhiyun cookie_op_buf_size - CEPH_ENCODING_START_BLK_LEN);
217*4882a593Smuzhiyun ceph_encode_string(&p, end, lock_name, name_len);
218*4882a593Smuzhiyun ceph_encode_8(&p, type);
219*4882a593Smuzhiyun ceph_encode_string(&p, end, old_cookie, old_cookie_len);
220*4882a593Smuzhiyun ceph_encode_string(&p, end, tag, tag_len);
221*4882a593Smuzhiyun ceph_encode_string(&p, end, new_cookie, new_cookie_len);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun dout("%s lock_name %s type %d old_cookie %s tag %s new_cookie %s\n",
224*4882a593Smuzhiyun __func__, lock_name, type, old_cookie, tag, new_cookie);
225*4882a593Smuzhiyun ret = ceph_osdc_call(osdc, oid, oloc, "lock", "set_cookie",
226*4882a593Smuzhiyun CEPH_OSD_FLAG_WRITE, cookie_op_page,
227*4882a593Smuzhiyun cookie_op_buf_size, NULL, NULL);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun dout("%s: status %d\n", __func__, ret);
230*4882a593Smuzhiyun __free_page(cookie_op_page);
231*4882a593Smuzhiyun return ret;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_cls_set_cookie);
234*4882a593Smuzhiyun
ceph_free_lockers(struct ceph_locker * lockers,u32 num_lockers)235*4882a593Smuzhiyun void ceph_free_lockers(struct ceph_locker *lockers, u32 num_lockers)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun int i;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun for (i = 0; i < num_lockers; i++)
240*4882a593Smuzhiyun kfree(lockers[i].id.cookie);
241*4882a593Smuzhiyun kfree(lockers);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_free_lockers);
244*4882a593Smuzhiyun
decode_locker(void ** p,void * end,struct ceph_locker * locker)245*4882a593Smuzhiyun static int decode_locker(void **p, void *end, struct ceph_locker *locker)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun u8 struct_v;
248*4882a593Smuzhiyun u32 len;
249*4882a593Smuzhiyun char *s;
250*4882a593Smuzhiyun int ret;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun ret = ceph_start_decoding(p, end, 1, "locker_id_t", &struct_v, &len);
253*4882a593Smuzhiyun if (ret)
254*4882a593Smuzhiyun return ret;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun ceph_decode_copy(p, &locker->id.name, sizeof(locker->id.name));
257*4882a593Smuzhiyun s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO);
258*4882a593Smuzhiyun if (IS_ERR(s))
259*4882a593Smuzhiyun return PTR_ERR(s);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun locker->id.cookie = s;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun ret = ceph_start_decoding(p, end, 1, "locker_info_t", &struct_v, &len);
264*4882a593Smuzhiyun if (ret)
265*4882a593Smuzhiyun return ret;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun *p += sizeof(struct ceph_timespec); /* skip expiration */
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun ret = ceph_decode_entity_addr(p, end, &locker->info.addr);
270*4882a593Smuzhiyun if (ret)
271*4882a593Smuzhiyun return ret;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun len = ceph_decode_32(p);
274*4882a593Smuzhiyun *p += len; /* skip description */
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun dout("%s %s%llu cookie %s addr %s\n", __func__,
277*4882a593Smuzhiyun ENTITY_NAME(locker->id.name), locker->id.cookie,
278*4882a593Smuzhiyun ceph_pr_addr(&locker->info.addr));
279*4882a593Smuzhiyun return 0;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
decode_lockers(void ** p,void * end,u8 * type,char ** tag,struct ceph_locker ** lockers,u32 * num_lockers)282*4882a593Smuzhiyun static int decode_lockers(void **p, void *end, u8 *type, char **tag,
283*4882a593Smuzhiyun struct ceph_locker **lockers, u32 *num_lockers)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun u8 struct_v;
286*4882a593Smuzhiyun u32 struct_len;
287*4882a593Smuzhiyun char *s;
288*4882a593Smuzhiyun int i;
289*4882a593Smuzhiyun int ret;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun ret = ceph_start_decoding(p, end, 1, "cls_lock_get_info_reply",
292*4882a593Smuzhiyun &struct_v, &struct_len);
293*4882a593Smuzhiyun if (ret)
294*4882a593Smuzhiyun return ret;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun *num_lockers = ceph_decode_32(p);
297*4882a593Smuzhiyun *lockers = kcalloc(*num_lockers, sizeof(**lockers), GFP_NOIO);
298*4882a593Smuzhiyun if (!*lockers)
299*4882a593Smuzhiyun return -ENOMEM;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun for (i = 0; i < *num_lockers; i++) {
302*4882a593Smuzhiyun ret = decode_locker(p, end, *lockers + i);
303*4882a593Smuzhiyun if (ret)
304*4882a593Smuzhiyun goto err_free_lockers;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun *type = ceph_decode_8(p);
308*4882a593Smuzhiyun s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO);
309*4882a593Smuzhiyun if (IS_ERR(s)) {
310*4882a593Smuzhiyun ret = PTR_ERR(s);
311*4882a593Smuzhiyun goto err_free_lockers;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun *tag = s;
315*4882a593Smuzhiyun return 0;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun err_free_lockers:
318*4882a593Smuzhiyun ceph_free_lockers(*lockers, *num_lockers);
319*4882a593Smuzhiyun return ret;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun /*
323*4882a593Smuzhiyun * On success, the caller is responsible for:
324*4882a593Smuzhiyun *
325*4882a593Smuzhiyun * kfree(tag);
326*4882a593Smuzhiyun * ceph_free_lockers(lockers, num_lockers);
327*4882a593Smuzhiyun */
ceph_cls_lock_info(struct ceph_osd_client * osdc,struct ceph_object_id * oid,struct ceph_object_locator * oloc,char * lock_name,u8 * type,char ** tag,struct ceph_locker ** lockers,u32 * num_lockers)328*4882a593Smuzhiyun int ceph_cls_lock_info(struct ceph_osd_client *osdc,
329*4882a593Smuzhiyun struct ceph_object_id *oid,
330*4882a593Smuzhiyun struct ceph_object_locator *oloc,
331*4882a593Smuzhiyun char *lock_name, u8 *type, char **tag,
332*4882a593Smuzhiyun struct ceph_locker **lockers, u32 *num_lockers)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun int get_info_op_buf_size;
335*4882a593Smuzhiyun int name_len = strlen(lock_name);
336*4882a593Smuzhiyun struct page *get_info_op_page, *reply_page;
337*4882a593Smuzhiyun size_t reply_len = PAGE_SIZE;
338*4882a593Smuzhiyun void *p, *end;
339*4882a593Smuzhiyun int ret;
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun get_info_op_buf_size = name_len + sizeof(__le32) +
342*4882a593Smuzhiyun CEPH_ENCODING_START_BLK_LEN;
343*4882a593Smuzhiyun if (get_info_op_buf_size > PAGE_SIZE)
344*4882a593Smuzhiyun return -E2BIG;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun get_info_op_page = alloc_page(GFP_NOIO);
347*4882a593Smuzhiyun if (!get_info_op_page)
348*4882a593Smuzhiyun return -ENOMEM;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun reply_page = alloc_page(GFP_NOIO);
351*4882a593Smuzhiyun if (!reply_page) {
352*4882a593Smuzhiyun __free_page(get_info_op_page);
353*4882a593Smuzhiyun return -ENOMEM;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun p = page_address(get_info_op_page);
357*4882a593Smuzhiyun end = p + get_info_op_buf_size;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /* encode cls_lock_get_info_op struct */
360*4882a593Smuzhiyun ceph_start_encoding(&p, 1, 1,
361*4882a593Smuzhiyun get_info_op_buf_size - CEPH_ENCODING_START_BLK_LEN);
362*4882a593Smuzhiyun ceph_encode_string(&p, end, lock_name, name_len);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun dout("%s lock_name %s\n", __func__, lock_name);
365*4882a593Smuzhiyun ret = ceph_osdc_call(osdc, oid, oloc, "lock", "get_info",
366*4882a593Smuzhiyun CEPH_OSD_FLAG_READ, get_info_op_page,
367*4882a593Smuzhiyun get_info_op_buf_size, &reply_page, &reply_len);
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun dout("%s: status %d\n", __func__, ret);
370*4882a593Smuzhiyun if (ret >= 0) {
371*4882a593Smuzhiyun p = page_address(reply_page);
372*4882a593Smuzhiyun end = p + reply_len;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun ret = decode_lockers(&p, end, type, tag, lockers, num_lockers);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun __free_page(get_info_op_page);
378*4882a593Smuzhiyun __free_page(reply_page);
379*4882a593Smuzhiyun return ret;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_cls_lock_info);
382*4882a593Smuzhiyun
ceph_cls_assert_locked(struct ceph_osd_request * req,int which,char * lock_name,u8 type,char * cookie,char * tag)383*4882a593Smuzhiyun int ceph_cls_assert_locked(struct ceph_osd_request *req, int which,
384*4882a593Smuzhiyun char *lock_name, u8 type, char *cookie, char *tag)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun int assert_op_buf_size;
387*4882a593Smuzhiyun int name_len = strlen(lock_name);
388*4882a593Smuzhiyun int cookie_len = strlen(cookie);
389*4882a593Smuzhiyun int tag_len = strlen(tag);
390*4882a593Smuzhiyun struct page **pages;
391*4882a593Smuzhiyun void *p, *end;
392*4882a593Smuzhiyun int ret;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun assert_op_buf_size = name_len + sizeof(__le32) +
395*4882a593Smuzhiyun cookie_len + sizeof(__le32) +
396*4882a593Smuzhiyun tag_len + sizeof(__le32) +
397*4882a593Smuzhiyun sizeof(u8) + CEPH_ENCODING_START_BLK_LEN;
398*4882a593Smuzhiyun if (assert_op_buf_size > PAGE_SIZE)
399*4882a593Smuzhiyun return -E2BIG;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun ret = osd_req_op_cls_init(req, which, "lock", "assert_locked");
402*4882a593Smuzhiyun if (ret)
403*4882a593Smuzhiyun return ret;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun pages = ceph_alloc_page_vector(1, GFP_NOIO);
406*4882a593Smuzhiyun if (IS_ERR(pages))
407*4882a593Smuzhiyun return PTR_ERR(pages);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun p = page_address(pages[0]);
410*4882a593Smuzhiyun end = p + assert_op_buf_size;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* encode cls_lock_assert_op struct */
413*4882a593Smuzhiyun ceph_start_encoding(&p, 1, 1,
414*4882a593Smuzhiyun assert_op_buf_size - CEPH_ENCODING_START_BLK_LEN);
415*4882a593Smuzhiyun ceph_encode_string(&p, end, lock_name, name_len);
416*4882a593Smuzhiyun ceph_encode_8(&p, type);
417*4882a593Smuzhiyun ceph_encode_string(&p, end, cookie, cookie_len);
418*4882a593Smuzhiyun ceph_encode_string(&p, end, tag, tag_len);
419*4882a593Smuzhiyun WARN_ON(p != end);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun osd_req_op_cls_request_data_pages(req, which, pages, assert_op_buf_size,
422*4882a593Smuzhiyun 0, false, true);
423*4882a593Smuzhiyun return 0;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_cls_assert_locked);
426