1 #include "ceph_debug.h" 2 #include "super.h" 3 #include "decode.h" 4 5 #include <linux/xattr.h> 6 #include <linux/slab.h> 7 8 static bool ceph_is_valid_xattr(const char *name) 9 { 10 return !strncmp(name, "ceph.", 5) || 11 !strncmp(name, XATTR_SECURITY_PREFIX, 12 XATTR_SECURITY_PREFIX_LEN) || 13 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || 14 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); 15 } 16 17 /* 18 * These define virtual xattrs exposing the recursive directory 19 * statistics and layout metadata. 20 */ 21 struct ceph_vxattr_cb { 22 bool readonly; 23 char *name; 24 size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val, 25 size_t size); 26 }; 27 28 /* directories */ 29 30 static size_t ceph_vxattrcb_entries(struct ceph_inode_info *ci, char *val, 31 size_t size) 32 { 33 return snprintf(val, size, "%lld", ci->i_files + ci->i_subdirs); 34 } 35 36 static size_t ceph_vxattrcb_files(struct ceph_inode_info *ci, char *val, 37 size_t size) 38 { 39 return snprintf(val, size, "%lld", ci->i_files); 40 } 41 42 static size_t ceph_vxattrcb_subdirs(struct ceph_inode_info *ci, char *val, 43 size_t size) 44 { 45 return snprintf(val, size, "%lld", ci->i_subdirs); 46 } 47 48 static size_t ceph_vxattrcb_rentries(struct ceph_inode_info *ci, char *val, 49 size_t size) 50 { 51 return snprintf(val, size, "%lld", ci->i_rfiles + ci->i_rsubdirs); 52 } 53 54 static size_t ceph_vxattrcb_rfiles(struct ceph_inode_info *ci, char *val, 55 size_t size) 56 { 57 return snprintf(val, size, "%lld", ci->i_rfiles); 58 } 59 60 static size_t ceph_vxattrcb_rsubdirs(struct ceph_inode_info *ci, char *val, 61 size_t size) 62 { 63 return snprintf(val, size, "%lld", ci->i_rsubdirs); 64 } 65 66 static size_t ceph_vxattrcb_rbytes(struct ceph_inode_info *ci, char *val, 67 size_t size) 68 { 69 return snprintf(val, size, "%lld", ci->i_rbytes); 70 } 71 72 static size_t ceph_vxattrcb_rctime(struct ceph_inode_info *ci, char *val, 73 size_t size) 74 { 75 return snprintf(val, size, "%ld.%ld", (long)ci->i_rctime.tv_sec, 76 (long)ci->i_rctime.tv_nsec); 77 } 78 79 static struct ceph_vxattr_cb ceph_dir_vxattrs[] = { 80 { true, "ceph.dir.entries", ceph_vxattrcb_entries}, 81 { true, "ceph.dir.files", ceph_vxattrcb_files}, 82 { true, "ceph.dir.subdirs", ceph_vxattrcb_subdirs}, 83 { true, "ceph.dir.rentries", ceph_vxattrcb_rentries}, 84 { true, "ceph.dir.rfiles", ceph_vxattrcb_rfiles}, 85 { true, "ceph.dir.rsubdirs", ceph_vxattrcb_rsubdirs}, 86 { true, "ceph.dir.rbytes", ceph_vxattrcb_rbytes}, 87 { true, "ceph.dir.rctime", ceph_vxattrcb_rctime}, 88 { true, NULL, NULL } 89 }; 90 91 /* files */ 92 93 static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val, 94 size_t size) 95 { 96 int ret; 97 98 ret = snprintf(val, size, 99 "chunk_bytes=%lld\nstripe_count=%lld\nobject_size=%lld\n", 100 (unsigned long long)ceph_file_layout_su(ci->i_layout), 101 (unsigned long long)ceph_file_layout_stripe_count(ci->i_layout), 102 (unsigned long long)ceph_file_layout_object_size(ci->i_layout)); 103 if (ceph_file_layout_pg_preferred(ci->i_layout)) 104 ret += snprintf(val + ret, size, "preferred_osd=%lld\n", 105 (unsigned long long)ceph_file_layout_pg_preferred( 106 ci->i_layout)); 107 return ret; 108 } 109 110 static struct ceph_vxattr_cb ceph_file_vxattrs[] = { 111 { true, "ceph.layout", ceph_vxattrcb_layout}, 112 { NULL, NULL } 113 }; 114 115 static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) 116 { 117 if (S_ISDIR(inode->i_mode)) 118 return ceph_dir_vxattrs; 119 else if (S_ISREG(inode->i_mode)) 120 return ceph_file_vxattrs; 121 return NULL; 122 } 123 124 static struct ceph_vxattr_cb *ceph_match_vxattr(struct ceph_vxattr_cb *vxattr, 125 const char *name) 126 { 127 do { 128 if (strcmp(vxattr->name, name) == 0) 129 return vxattr; 130 vxattr++; 131 } while (vxattr->name); 132 return NULL; 133 } 134 135 static int __set_xattr(struct ceph_inode_info *ci, 136 const char *name, int name_len, 137 const char *val, int val_len, 138 int dirty, 139 int should_free_name, int should_free_val, 140 struct ceph_inode_xattr **newxattr) 141 { 142 struct rb_node **p; 143 struct rb_node *parent = NULL; 144 struct ceph_inode_xattr *xattr = NULL; 145 int c; 146 int new = 0; 147 148 p = &ci->i_xattrs.index.rb_node; 149 while (*p) { 150 parent = *p; 151 xattr = rb_entry(parent, struct ceph_inode_xattr, node); 152 c = strncmp(name, xattr->name, min(name_len, xattr->name_len)); 153 if (c < 0) 154 p = &(*p)->rb_left; 155 else if (c > 0) 156 p = &(*p)->rb_right; 157 else { 158 if (name_len == xattr->name_len) 159 break; 160 else if (name_len < xattr->name_len) 161 p = &(*p)->rb_left; 162 else 163 p = &(*p)->rb_right; 164 } 165 xattr = NULL; 166 } 167 168 if (!xattr) { 169 new = 1; 170 xattr = *newxattr; 171 xattr->name = name; 172 xattr->name_len = name_len; 173 xattr->should_free_name = should_free_name; 174 175 ci->i_xattrs.count++; 176 dout("__set_xattr count=%d\n", ci->i_xattrs.count); 177 } else { 178 kfree(*newxattr); 179 *newxattr = NULL; 180 if (xattr->should_free_val) 181 kfree((void *)xattr->val); 182 183 if (should_free_name) { 184 kfree((void *)name); 185 name = xattr->name; 186 } 187 ci->i_xattrs.names_size -= xattr->name_len; 188 ci->i_xattrs.vals_size -= xattr->val_len; 189 } 190 ci->i_xattrs.names_size += name_len; 191 ci->i_xattrs.vals_size += val_len; 192 if (val) 193 xattr->val = val; 194 else 195 xattr->val = ""; 196 197 xattr->val_len = val_len; 198 xattr->dirty = dirty; 199 xattr->should_free_val = (val && should_free_val); 200 201 if (new) { 202 rb_link_node(&xattr->node, parent, p); 203 rb_insert_color(&xattr->node, &ci->i_xattrs.index); 204 dout("__set_xattr_val p=%p\n", p); 205 } 206 207 dout("__set_xattr_val added %llx.%llx xattr %p %s=%.*s\n", 208 ceph_vinop(&ci->vfs_inode), xattr, name, val_len, val); 209 210 return 0; 211 } 212 213 static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci, 214 const char *name) 215 { 216 struct rb_node **p; 217 struct rb_node *parent = NULL; 218 struct ceph_inode_xattr *xattr = NULL; 219 int c; 220 221 p = &ci->i_xattrs.index.rb_node; 222 while (*p) { 223 parent = *p; 224 xattr = rb_entry(parent, struct ceph_inode_xattr, node); 225 c = strncmp(name, xattr->name, xattr->name_len); 226 if (c < 0) 227 p = &(*p)->rb_left; 228 else if (c > 0) 229 p = &(*p)->rb_right; 230 else { 231 dout("__get_xattr %s: found %.*s\n", name, 232 xattr->val_len, xattr->val); 233 return xattr; 234 } 235 } 236 237 dout("__get_xattr %s: not found\n", name); 238 239 return NULL; 240 } 241 242 static void __free_xattr(struct ceph_inode_xattr *xattr) 243 { 244 BUG_ON(!xattr); 245 246 if (xattr->should_free_name) 247 kfree((void *)xattr->name); 248 if (xattr->should_free_val) 249 kfree((void *)xattr->val); 250 251 kfree(xattr); 252 } 253 254 static int __remove_xattr(struct ceph_inode_info *ci, 255 struct ceph_inode_xattr *xattr) 256 { 257 if (!xattr) 258 return -EOPNOTSUPP; 259 260 rb_erase(&xattr->node, &ci->i_xattrs.index); 261 262 if (xattr->should_free_name) 263 kfree((void *)xattr->name); 264 if (xattr->should_free_val) 265 kfree((void *)xattr->val); 266 267 ci->i_xattrs.names_size -= xattr->name_len; 268 ci->i_xattrs.vals_size -= xattr->val_len; 269 ci->i_xattrs.count--; 270 kfree(xattr); 271 272 return 0; 273 } 274 275 static int __remove_xattr_by_name(struct ceph_inode_info *ci, 276 const char *name) 277 { 278 struct rb_node **p; 279 struct ceph_inode_xattr *xattr; 280 int err; 281 282 p = &ci->i_xattrs.index.rb_node; 283 xattr = __get_xattr(ci, name); 284 err = __remove_xattr(ci, xattr); 285 return err; 286 } 287 288 static char *__copy_xattr_names(struct ceph_inode_info *ci, 289 char *dest) 290 { 291 struct rb_node *p; 292 struct ceph_inode_xattr *xattr = NULL; 293 294 p = rb_first(&ci->i_xattrs.index); 295 dout("__copy_xattr_names count=%d\n", ci->i_xattrs.count); 296 297 while (p) { 298 xattr = rb_entry(p, struct ceph_inode_xattr, node); 299 memcpy(dest, xattr->name, xattr->name_len); 300 dest[xattr->name_len] = '\0'; 301 302 dout("dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name, 303 xattr->name_len, ci->i_xattrs.names_size); 304 305 dest += xattr->name_len + 1; 306 p = rb_next(p); 307 } 308 309 return dest; 310 } 311 312 void __ceph_destroy_xattrs(struct ceph_inode_info *ci) 313 { 314 struct rb_node *p, *tmp; 315 struct ceph_inode_xattr *xattr = NULL; 316 317 p = rb_first(&ci->i_xattrs.index); 318 319 dout("__ceph_destroy_xattrs p=%p\n", p); 320 321 while (p) { 322 xattr = rb_entry(p, struct ceph_inode_xattr, node); 323 tmp = p; 324 p = rb_next(tmp); 325 dout("__ceph_destroy_xattrs next p=%p (%.*s)\n", p, 326 xattr->name_len, xattr->name); 327 rb_erase(tmp, &ci->i_xattrs.index); 328 329 __free_xattr(xattr); 330 } 331 332 ci->i_xattrs.names_size = 0; 333 ci->i_xattrs.vals_size = 0; 334 ci->i_xattrs.index_version = 0; 335 ci->i_xattrs.count = 0; 336 ci->i_xattrs.index = RB_ROOT; 337 } 338 339 static int __build_xattrs(struct inode *inode) 340 __releases(inode->i_lock) 341 __acquires(inode->i_lock) 342 { 343 u32 namelen; 344 u32 numattr = 0; 345 void *p, *end; 346 u32 len; 347 const char *name, *val; 348 struct ceph_inode_info *ci = ceph_inode(inode); 349 int xattr_version; 350 struct ceph_inode_xattr **xattrs = NULL; 351 int err = 0; 352 int i; 353 354 dout("__build_xattrs() len=%d\n", 355 ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0); 356 357 if (ci->i_xattrs.index_version >= ci->i_xattrs.version) 358 return 0; /* already built */ 359 360 __ceph_destroy_xattrs(ci); 361 362 start: 363 /* updated internal xattr rb tree */ 364 if (ci->i_xattrs.blob && ci->i_xattrs.blob->vec.iov_len > 4) { 365 p = ci->i_xattrs.blob->vec.iov_base; 366 end = p + ci->i_xattrs.blob->vec.iov_len; 367 ceph_decode_32_safe(&p, end, numattr, bad); 368 xattr_version = ci->i_xattrs.version; 369 spin_unlock(&inode->i_lock); 370 371 xattrs = kcalloc(numattr, sizeof(struct ceph_xattr *), 372 GFP_NOFS); 373 err = -ENOMEM; 374 if (!xattrs) 375 goto bad_lock; 376 memset(xattrs, 0, numattr*sizeof(struct ceph_xattr *)); 377 for (i = 0; i < numattr; i++) { 378 xattrs[i] = kmalloc(sizeof(struct ceph_inode_xattr), 379 GFP_NOFS); 380 if (!xattrs[i]) 381 goto bad_lock; 382 } 383 384 spin_lock(&inode->i_lock); 385 if (ci->i_xattrs.version != xattr_version) { 386 /* lost a race, retry */ 387 for (i = 0; i < numattr; i++) 388 kfree(xattrs[i]); 389 kfree(xattrs); 390 goto start; 391 } 392 err = -EIO; 393 while (numattr--) { 394 ceph_decode_32_safe(&p, end, len, bad); 395 namelen = len; 396 name = p; 397 p += len; 398 ceph_decode_32_safe(&p, end, len, bad); 399 val = p; 400 p += len; 401 402 err = __set_xattr(ci, name, namelen, val, len, 403 0, 0, 0, &xattrs[numattr]); 404 405 if (err < 0) 406 goto bad; 407 } 408 kfree(xattrs); 409 } 410 ci->i_xattrs.index_version = ci->i_xattrs.version; 411 ci->i_xattrs.dirty = false; 412 413 return err; 414 bad_lock: 415 spin_lock(&inode->i_lock); 416 bad: 417 if (xattrs) { 418 for (i = 0; i < numattr; i++) 419 kfree(xattrs[i]); 420 kfree(xattrs); 421 } 422 ci->i_xattrs.names_size = 0; 423 return err; 424 } 425 426 static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size, 427 int val_size) 428 { 429 /* 430 * 4 bytes for the length, and additional 4 bytes per each xattr name, 431 * 4 bytes per each value 432 */ 433 int size = 4 + ci->i_xattrs.count*(4 + 4) + 434 ci->i_xattrs.names_size + 435 ci->i_xattrs.vals_size; 436 dout("__get_required_blob_size c=%d names.size=%d vals.size=%d\n", 437 ci->i_xattrs.count, ci->i_xattrs.names_size, 438 ci->i_xattrs.vals_size); 439 440 if (name_size) 441 size += 4 + 4 + name_size + val_size; 442 443 return size; 444 } 445 446 /* 447 * If there are dirty xattrs, reencode xattrs into the prealloc_blob 448 * and swap into place. 449 */ 450 void __ceph_build_xattrs_blob(struct ceph_inode_info *ci) 451 { 452 struct rb_node *p; 453 struct ceph_inode_xattr *xattr = NULL; 454 void *dest; 455 456 dout("__build_xattrs_blob %p\n", &ci->vfs_inode); 457 if (ci->i_xattrs.dirty) { 458 int need = __get_required_blob_size(ci, 0, 0); 459 460 BUG_ON(need > ci->i_xattrs.prealloc_blob->alloc_len); 461 462 p = rb_first(&ci->i_xattrs.index); 463 dest = ci->i_xattrs.prealloc_blob->vec.iov_base; 464 465 ceph_encode_32(&dest, ci->i_xattrs.count); 466 while (p) { 467 xattr = rb_entry(p, struct ceph_inode_xattr, node); 468 469 ceph_encode_32(&dest, xattr->name_len); 470 memcpy(dest, xattr->name, xattr->name_len); 471 dest += xattr->name_len; 472 ceph_encode_32(&dest, xattr->val_len); 473 memcpy(dest, xattr->val, xattr->val_len); 474 dest += xattr->val_len; 475 476 p = rb_next(p); 477 } 478 479 /* adjust buffer len; it may be larger than we need */ 480 ci->i_xattrs.prealloc_blob->vec.iov_len = 481 dest - ci->i_xattrs.prealloc_blob->vec.iov_base; 482 483 if (ci->i_xattrs.blob) 484 ceph_buffer_put(ci->i_xattrs.blob); 485 ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob; 486 ci->i_xattrs.prealloc_blob = NULL; 487 ci->i_xattrs.dirty = false; 488 ci->i_xattrs.version++; 489 } 490 } 491 492 ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, 493 size_t size) 494 { 495 struct inode *inode = dentry->d_inode; 496 struct ceph_inode_info *ci = ceph_inode(inode); 497 struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); 498 int err; 499 struct ceph_inode_xattr *xattr; 500 struct ceph_vxattr_cb *vxattr = NULL; 501 502 if (!ceph_is_valid_xattr(name)) 503 return -ENODATA; 504 505 /* let's see if a virtual xattr was requested */ 506 if (vxattrs) 507 vxattr = ceph_match_vxattr(vxattrs, name); 508 509 spin_lock(&inode->i_lock); 510 dout("getxattr %p ver=%lld index_ver=%lld\n", inode, 511 ci->i_xattrs.version, ci->i_xattrs.index_version); 512 513 if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1) && 514 (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { 515 goto get_xattr; 516 } else { 517 spin_unlock(&inode->i_lock); 518 /* get xattrs from mds (if we don't already have them) */ 519 err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); 520 if (err) 521 return err; 522 } 523 524 spin_lock(&inode->i_lock); 525 526 if (vxattr && vxattr->readonly) { 527 err = vxattr->getxattr_cb(ci, value, size); 528 goto out; 529 } 530 531 err = __build_xattrs(inode); 532 if (err < 0) 533 goto out; 534 535 get_xattr: 536 err = -ENODATA; /* == ENOATTR */ 537 xattr = __get_xattr(ci, name); 538 if (!xattr) { 539 if (vxattr) 540 err = vxattr->getxattr_cb(ci, value, size); 541 goto out; 542 } 543 544 err = -ERANGE; 545 if (size && size < xattr->val_len) 546 goto out; 547 548 err = xattr->val_len; 549 if (size == 0) 550 goto out; 551 552 memcpy(value, xattr->val, xattr->val_len); 553 554 out: 555 spin_unlock(&inode->i_lock); 556 return err; 557 } 558 559 ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) 560 { 561 struct inode *inode = dentry->d_inode; 562 struct ceph_inode_info *ci = ceph_inode(inode); 563 struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); 564 u32 vir_namelen = 0; 565 u32 namelen; 566 int err; 567 u32 len; 568 int i; 569 570 spin_lock(&inode->i_lock); 571 dout("listxattr %p ver=%lld index_ver=%lld\n", inode, 572 ci->i_xattrs.version, ci->i_xattrs.index_version); 573 574 if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1) && 575 (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { 576 goto list_xattr; 577 } else { 578 spin_unlock(&inode->i_lock); 579 err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); 580 if (err) 581 return err; 582 } 583 584 spin_lock(&inode->i_lock); 585 586 err = __build_xattrs(inode); 587 if (err < 0) 588 goto out; 589 590 list_xattr: 591 vir_namelen = 0; 592 /* include virtual dir xattrs */ 593 if (vxattrs) 594 for (i = 0; vxattrs[i].name; i++) 595 vir_namelen += strlen(vxattrs[i].name) + 1; 596 /* adding 1 byte per each variable due to the null termination */ 597 namelen = vir_namelen + ci->i_xattrs.names_size + ci->i_xattrs.count; 598 err = -ERANGE; 599 if (size && namelen > size) 600 goto out; 601 602 err = namelen; 603 if (size == 0) 604 goto out; 605 606 names = __copy_xattr_names(ci, names); 607 608 /* virtual xattr names, too */ 609 if (vxattrs) 610 for (i = 0; vxattrs[i].name; i++) { 611 len = sprintf(names, "%s", vxattrs[i].name); 612 names += len + 1; 613 } 614 615 out: 616 spin_unlock(&inode->i_lock); 617 return err; 618 } 619 620 static int ceph_sync_setxattr(struct dentry *dentry, const char *name, 621 const char *value, size_t size, int flags) 622 { 623 struct ceph_client *client = ceph_sb_to_client(dentry->d_sb); 624 struct inode *inode = dentry->d_inode; 625 struct ceph_inode_info *ci = ceph_inode(inode); 626 struct inode *parent_inode = dentry->d_parent->d_inode; 627 struct ceph_mds_request *req; 628 struct ceph_mds_client *mdsc = &client->mdsc; 629 int err; 630 int i, nr_pages; 631 struct page **pages = NULL; 632 void *kaddr; 633 634 /* copy value into some pages */ 635 nr_pages = calc_pages_for(0, size); 636 if (nr_pages) { 637 pages = kmalloc(sizeof(pages[0])*nr_pages, GFP_NOFS); 638 if (!pages) 639 return -ENOMEM; 640 err = -ENOMEM; 641 for (i = 0; i < nr_pages; i++) { 642 pages[i] = __page_cache_alloc(GFP_NOFS); 643 if (!pages[i]) { 644 nr_pages = i; 645 goto out; 646 } 647 kaddr = kmap(pages[i]); 648 memcpy(kaddr, value + i*PAGE_CACHE_SIZE, 649 min(PAGE_CACHE_SIZE, size-i*PAGE_CACHE_SIZE)); 650 } 651 } 652 653 dout("setxattr value=%.*s\n", (int)size, value); 654 655 /* do request */ 656 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, 657 USE_AUTH_MDS); 658 if (IS_ERR(req)) { 659 err = PTR_ERR(req); 660 goto out; 661 } 662 req->r_inode = igrab(inode); 663 req->r_inode_drop = CEPH_CAP_XATTR_SHARED; 664 req->r_num_caps = 1; 665 req->r_args.setxattr.flags = cpu_to_le32(flags); 666 req->r_path2 = kstrdup(name, GFP_NOFS); 667 668 req->r_pages = pages; 669 req->r_num_pages = nr_pages; 670 req->r_data_len = size; 671 672 dout("xattr.ver (before): %lld\n", ci->i_xattrs.version); 673 err = ceph_mdsc_do_request(mdsc, parent_inode, req); 674 ceph_mdsc_put_request(req); 675 dout("xattr.ver (after): %lld\n", ci->i_xattrs.version); 676 677 out: 678 if (pages) { 679 for (i = 0; i < nr_pages; i++) 680 __free_page(pages[i]); 681 kfree(pages); 682 } 683 return err; 684 } 685 686 int ceph_setxattr(struct dentry *dentry, const char *name, 687 const void *value, size_t size, int flags) 688 { 689 struct inode *inode = dentry->d_inode; 690 struct ceph_inode_info *ci = ceph_inode(inode); 691 struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); 692 int err; 693 int name_len = strlen(name); 694 int val_len = size; 695 char *newname = NULL; 696 char *newval = NULL; 697 struct ceph_inode_xattr *xattr = NULL; 698 int issued; 699 int required_blob_size; 700 701 if (ceph_snap(inode) != CEPH_NOSNAP) 702 return -EROFS; 703 704 if (!ceph_is_valid_xattr(name)) 705 return -EOPNOTSUPP; 706 707 if (vxattrs) { 708 struct ceph_vxattr_cb *vxattr = 709 ceph_match_vxattr(vxattrs, name); 710 if (vxattr && vxattr->readonly) 711 return -EOPNOTSUPP; 712 } 713 714 /* preallocate memory for xattr name, value, index node */ 715 err = -ENOMEM; 716 newname = kmalloc(name_len + 1, GFP_NOFS); 717 if (!newname) 718 goto out; 719 memcpy(newname, name, name_len + 1); 720 721 if (val_len) { 722 newval = kmalloc(val_len + 1, GFP_NOFS); 723 if (!newval) 724 goto out; 725 memcpy(newval, value, val_len); 726 newval[val_len] = '\0'; 727 } 728 729 xattr = kmalloc(sizeof(struct ceph_inode_xattr), GFP_NOFS); 730 if (!xattr) 731 goto out; 732 733 spin_lock(&inode->i_lock); 734 retry: 735 issued = __ceph_caps_issued(ci, NULL); 736 if (!(issued & CEPH_CAP_XATTR_EXCL)) 737 goto do_sync; 738 __build_xattrs(inode); 739 740 required_blob_size = __get_required_blob_size(ci, name_len, val_len); 741 742 if (!ci->i_xattrs.prealloc_blob || 743 required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { 744 struct ceph_buffer *blob = NULL; 745 746 spin_unlock(&inode->i_lock); 747 dout(" preaallocating new blob size=%d\n", required_blob_size); 748 blob = ceph_buffer_new(required_blob_size, GFP_NOFS); 749 if (!blob) 750 goto out; 751 spin_lock(&inode->i_lock); 752 if (ci->i_xattrs.prealloc_blob) 753 ceph_buffer_put(ci->i_xattrs.prealloc_blob); 754 ci->i_xattrs.prealloc_blob = blob; 755 goto retry; 756 } 757 758 dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued)); 759 err = __set_xattr(ci, newname, name_len, newval, 760 val_len, 1, 1, 1, &xattr); 761 __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); 762 ci->i_xattrs.dirty = true; 763 inode->i_ctime = CURRENT_TIME; 764 spin_unlock(&inode->i_lock); 765 766 return err; 767 768 do_sync: 769 spin_unlock(&inode->i_lock); 770 err = ceph_sync_setxattr(dentry, name, value, size, flags); 771 out: 772 kfree(newname); 773 kfree(newval); 774 kfree(xattr); 775 return err; 776 } 777 778 static int ceph_send_removexattr(struct dentry *dentry, const char *name) 779 { 780 struct ceph_client *client = ceph_sb_to_client(dentry->d_sb); 781 struct ceph_mds_client *mdsc = &client->mdsc; 782 struct inode *inode = dentry->d_inode; 783 struct inode *parent_inode = dentry->d_parent->d_inode; 784 struct ceph_mds_request *req; 785 int err; 786 787 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_RMXATTR, 788 USE_AUTH_MDS); 789 if (IS_ERR(req)) 790 return PTR_ERR(req); 791 req->r_inode = igrab(inode); 792 req->r_inode_drop = CEPH_CAP_XATTR_SHARED; 793 req->r_num_caps = 1; 794 req->r_path2 = kstrdup(name, GFP_NOFS); 795 796 err = ceph_mdsc_do_request(mdsc, parent_inode, req); 797 ceph_mdsc_put_request(req); 798 return err; 799 } 800 801 int ceph_removexattr(struct dentry *dentry, const char *name) 802 { 803 struct inode *inode = dentry->d_inode; 804 struct ceph_inode_info *ci = ceph_inode(inode); 805 struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); 806 int issued; 807 int err; 808 809 if (ceph_snap(inode) != CEPH_NOSNAP) 810 return -EROFS; 811 812 if (!ceph_is_valid_xattr(name)) 813 return -EOPNOTSUPP; 814 815 if (vxattrs) { 816 struct ceph_vxattr_cb *vxattr = 817 ceph_match_vxattr(vxattrs, name); 818 if (vxattr && vxattr->readonly) 819 return -EOPNOTSUPP; 820 } 821 822 spin_lock(&inode->i_lock); 823 __build_xattrs(inode); 824 issued = __ceph_caps_issued(ci, NULL); 825 dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); 826 827 if (!(issued & CEPH_CAP_XATTR_EXCL)) 828 goto do_sync; 829 830 err = __remove_xattr_by_name(ceph_inode(inode), name); 831 __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); 832 ci->i_xattrs.dirty = true; 833 inode->i_ctime = CURRENT_TIME; 834 835 spin_unlock(&inode->i_lock); 836 837 return err; 838 do_sync: 839 spin_unlock(&inode->i_lock); 840 err = ceph_send_removexattr(dentry, name); 841 return err; 842 } 843 844