xref: /OK3568_Linux_fs/kernel/net/ceph/cls_lock_client.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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