root/net/ceph/cls_lock_client.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ceph_cls_lock
  2. ceph_cls_unlock
  3. ceph_cls_break_lock
  4. ceph_cls_set_cookie
  5. ceph_free_lockers
  6. decode_locker
  7. decode_lockers
  8. ceph_cls_lock_info
  9. ceph_cls_assert_locked

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

/* [<][>][^][v][top][bottom][index][help] */