1// SPDX-License-Identifier: GPL-2.0 2#include <linux/ceph/ceph_debug.h> 3#include <linux/ceph/pagelist.h> 4 5#include "super.h" 6#include "mds_client.h" 7 8#include <linux/ceph/decode.h> 9 10#include <linux/xattr.h> 11#include <linux/security.h> 12#include <linux/posix_acl_xattr.h> 13#include <linux/slab.h> 14 15#define XATTR_CEPH_PREFIX "ceph." 16#define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) 17 18static int __remove_xattr(struct ceph_inode_info *ci, 19 struct ceph_inode_xattr *xattr); 20 21static bool ceph_is_valid_xattr(const char *name) 22{ 23 return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) || 24 !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) || 25 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || 26 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); 27} 28 29/* 30 * These define virtual xattrs exposing the recursive directory 31 * statistics and layout metadata. 32 */ 33struct ceph_vxattr { 34 char *name; 35 size_t name_size; /* strlen(name) + 1 (for '\0') */ 36 ssize_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val, 37 size_t size); 38 bool (*exists_cb)(struct ceph_inode_info *ci); 39 unsigned int flags; 40}; 41 42#define VXATTR_FLAG_READONLY (1<<0) 43#define VXATTR_FLAG_HIDDEN (1<<1) 44#define VXATTR_FLAG_RSTAT (1<<2) 45 46/* layouts */ 47 48static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci) 49{ 50 struct ceph_file_layout *fl = &ci->i_layout; 51 return (fl->stripe_unit > 0 || fl->stripe_count > 0 || 52 fl->object_size > 0 || fl->pool_id >= 0 || 53 rcu_dereference_raw(fl->pool_ns) != NULL); 54} 55 56static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val, 57 size_t size) 58{ 59 struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb); 60 struct ceph_osd_client *osdc = &fsc->client->osdc; 61 struct ceph_string *pool_ns; 62 s64 pool = ci->i_layout.pool_id; 63 const char *pool_name; 64 const char *ns_field = " pool_namespace="; 65 char buf[128]; 66 size_t len, total_len = 0; 67 ssize_t ret; 68 69 pool_ns = ceph_try_get_string(ci->i_layout.pool_ns); 70 71 dout("ceph_vxattrcb_layout %p\n", &ci->vfs_inode); 72 down_read(&osdc->lock); 73 pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool); 74 if (pool_name) { 75 len = snprintf(buf, sizeof(buf), 76 "stripe_unit=%u stripe_count=%u object_size=%u pool=", 77 ci->i_layout.stripe_unit, ci->i_layout.stripe_count, 78 ci->i_layout.object_size); 79 total_len = len + strlen(pool_name); 80 } else { 81 len = snprintf(buf, sizeof(buf), 82 "stripe_unit=%u stripe_count=%u object_size=%u pool=%lld", 83 ci->i_layout.stripe_unit, ci->i_layout.stripe_count, 84 ci->i_layout.object_size, pool); 85 total_len = len; 86 } 87 88 if (pool_ns) 89 total_len += strlen(ns_field) + pool_ns->len; 90 91 ret = total_len; 92 if (size >= total_len) { 93 memcpy(val, buf, len); 94 ret = len; 95 if (pool_name) { 96 len = strlen(pool_name); 97 memcpy(val + ret, pool_name, len); 98 ret += len; 99 } 100 if (pool_ns) { 101 len = strlen(ns_field); 102 memcpy(val + ret, ns_field, len); 103 ret += len; 104 memcpy(val + ret, pool_ns->str, pool_ns->len); 105 ret += pool_ns->len; 106 } 107 } 108 up_read(&osdc->lock); 109 ceph_put_string(pool_ns); 110 return ret; 111} 112 113/* 114 * The convention with strings in xattrs is that they should not be NULL 115 * terminated, since we're returning the length with them. snprintf always 116 * NULL terminates however, so call it on a temporary buffer and then memcpy 117 * the result into place. 118 */ 119static __printf(3, 4) 120int ceph_fmt_xattr(char *val, size_t size, const char *fmt, ...) 121{ 122 int ret; 123 va_list args; 124 char buf[96]; /* NB: reevaluate size if new vxattrs are added */ 125 126 va_start(args, fmt); 127 ret = vsnprintf(buf, size ? sizeof(buf) : 0, fmt, args); 128 va_end(args); 129 130 /* Sanity check */ 131 if (size && ret + 1 > sizeof(buf)) { 132 WARN_ONCE(true, "Returned length too big (%d)", ret); 133 return -E2BIG; 134 } 135 136 if (ret <= size) 137 memcpy(val, buf, ret); 138 return ret; 139} 140 141static ssize_t ceph_vxattrcb_layout_stripe_unit(struct ceph_inode_info *ci, 142 char *val, size_t size) 143{ 144 return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_unit); 145} 146 147static ssize_t ceph_vxattrcb_layout_stripe_count(struct ceph_inode_info *ci, 148 char *val, size_t size) 149{ 150 return ceph_fmt_xattr(val, size, "%u", ci->i_layout.stripe_count); 151} 152 153static ssize_t ceph_vxattrcb_layout_object_size(struct ceph_inode_info *ci, 154 char *val, size_t size) 155{ 156 return ceph_fmt_xattr(val, size, "%u", ci->i_layout.object_size); 157} 158 159static ssize_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci, 160 char *val, size_t size) 161{ 162 ssize_t ret; 163 struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb); 164 struct ceph_osd_client *osdc = &fsc->client->osdc; 165 s64 pool = ci->i_layout.pool_id; 166 const char *pool_name; 167 168 down_read(&osdc->lock); 169 pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool); 170 if (pool_name) { 171 ret = strlen(pool_name); 172 if (ret <= size) 173 memcpy(val, pool_name, ret); 174 } else { 175 ret = ceph_fmt_xattr(val, size, "%lld", pool); 176 } 177 up_read(&osdc->lock); 178 return ret; 179} 180 181static ssize_t ceph_vxattrcb_layout_pool_namespace(struct ceph_inode_info *ci, 182 char *val, size_t size) 183{ 184 ssize_t ret = 0; 185 struct ceph_string *ns = ceph_try_get_string(ci->i_layout.pool_ns); 186 187 if (ns) { 188 ret = ns->len; 189 if (ret <= size) 190 memcpy(val, ns->str, ret); 191 ceph_put_string(ns); 192 } 193 return ret; 194} 195 196/* directories */ 197 198static ssize_t ceph_vxattrcb_dir_entries(struct ceph_inode_info *ci, char *val, 199 size_t size) 200{ 201 return ceph_fmt_xattr(val, size, "%lld", ci->i_files + ci->i_subdirs); 202} 203 204static ssize_t ceph_vxattrcb_dir_files(struct ceph_inode_info *ci, char *val, 205 size_t size) 206{ 207 return ceph_fmt_xattr(val, size, "%lld", ci->i_files); 208} 209 210static ssize_t ceph_vxattrcb_dir_subdirs(struct ceph_inode_info *ci, char *val, 211 size_t size) 212{ 213 return ceph_fmt_xattr(val, size, "%lld", ci->i_subdirs); 214} 215 216static ssize_t ceph_vxattrcb_dir_rentries(struct ceph_inode_info *ci, char *val, 217 size_t size) 218{ 219 return ceph_fmt_xattr(val, size, "%lld", 220 ci->i_rfiles + ci->i_rsubdirs); 221} 222 223static ssize_t ceph_vxattrcb_dir_rfiles(struct ceph_inode_info *ci, char *val, 224 size_t size) 225{ 226 return ceph_fmt_xattr(val, size, "%lld", ci->i_rfiles); 227} 228 229static ssize_t ceph_vxattrcb_dir_rsubdirs(struct ceph_inode_info *ci, char *val, 230 size_t size) 231{ 232 return ceph_fmt_xattr(val, size, "%lld", ci->i_rsubdirs); 233} 234 235static ssize_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val, 236 size_t size) 237{ 238 return ceph_fmt_xattr(val, size, "%lld", ci->i_rbytes); 239} 240 241static ssize_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val, 242 size_t size) 243{ 244 return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_rctime.tv_sec, 245 ci->i_rctime.tv_nsec); 246} 247 248/* dir pin */ 249static bool ceph_vxattrcb_dir_pin_exists(struct ceph_inode_info *ci) 250{ 251 return ci->i_dir_pin != -ENODATA; 252} 253 254static ssize_t ceph_vxattrcb_dir_pin(struct ceph_inode_info *ci, char *val, 255 size_t size) 256{ 257 return ceph_fmt_xattr(val, size, "%d", (int)ci->i_dir_pin); 258} 259 260/* quotas */ 261static bool ceph_vxattrcb_quota_exists(struct ceph_inode_info *ci) 262{ 263 bool ret = false; 264 spin_lock(&ci->i_ceph_lock); 265 if ((ci->i_max_files || ci->i_max_bytes) && 266 ci->i_vino.snap == CEPH_NOSNAP && 267 ci->i_snap_realm && 268 ci->i_snap_realm->ino == ci->i_vino.ino) 269 ret = true; 270 spin_unlock(&ci->i_ceph_lock); 271 return ret; 272} 273 274static ssize_t ceph_vxattrcb_quota(struct ceph_inode_info *ci, char *val, 275 size_t size) 276{ 277 return ceph_fmt_xattr(val, size, "max_bytes=%llu max_files=%llu", 278 ci->i_max_bytes, ci->i_max_files); 279} 280 281static ssize_t ceph_vxattrcb_quota_max_bytes(struct ceph_inode_info *ci, 282 char *val, size_t size) 283{ 284 return ceph_fmt_xattr(val, size, "%llu", ci->i_max_bytes); 285} 286 287static ssize_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci, 288 char *val, size_t size) 289{ 290 return ceph_fmt_xattr(val, size, "%llu", ci->i_max_files); 291} 292 293/* snapshots */ 294static bool ceph_vxattrcb_snap_btime_exists(struct ceph_inode_info *ci) 295{ 296 return (ci->i_snap_btime.tv_sec != 0 || ci->i_snap_btime.tv_nsec != 0); 297} 298 299static ssize_t ceph_vxattrcb_snap_btime(struct ceph_inode_info *ci, char *val, 300 size_t size) 301{ 302 return ceph_fmt_xattr(val, size, "%lld.%09ld", ci->i_snap_btime.tv_sec, 303 ci->i_snap_btime.tv_nsec); 304} 305 306#define CEPH_XATTR_NAME(_type, _name) XATTR_CEPH_PREFIX #_type "." #_name 307#define CEPH_XATTR_NAME2(_type, _name, _name2) \ 308 XATTR_CEPH_PREFIX #_type "." #_name "." #_name2 309 310#define XATTR_NAME_CEPH(_type, _name, _flags) \ 311 { \ 312 .name = CEPH_XATTR_NAME(_type, _name), \ 313 .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \ 314 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \ 315 .exists_cb = NULL, \ 316 .flags = (VXATTR_FLAG_READONLY | _flags), \ 317 } 318#define XATTR_RSTAT_FIELD(_type, _name) \ 319 XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT) 320#define XATTR_RSTAT_FIELD_UPDATABLE(_type, _name) \ 321 { \ 322 .name = CEPH_XATTR_NAME(_type, _name), \ 323 .name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \ 324 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \ 325 .exists_cb = NULL, \ 326 .flags = VXATTR_FLAG_RSTAT, \ 327 } 328#define XATTR_LAYOUT_FIELD(_type, _name, _field) \ 329 { \ 330 .name = CEPH_XATTR_NAME2(_type, _name, _field), \ 331 .name_size = sizeof (CEPH_XATTR_NAME2(_type, _name, _field)), \ 332 .getxattr_cb = ceph_vxattrcb_ ## _name ## _ ## _field, \ 333 .exists_cb = ceph_vxattrcb_layout_exists, \ 334 .flags = VXATTR_FLAG_HIDDEN, \ 335 } 336#define XATTR_QUOTA_FIELD(_type, _name) \ 337 { \ 338 .name = CEPH_XATTR_NAME(_type, _name), \ 339 .name_size = sizeof(CEPH_XATTR_NAME(_type, _name)), \ 340 .getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \ 341 .exists_cb = ceph_vxattrcb_quota_exists, \ 342 .flags = VXATTR_FLAG_HIDDEN, \ 343 } 344 345static struct ceph_vxattr ceph_dir_vxattrs[] = { 346 { 347 .name = "ceph.dir.layout", 348 .name_size = sizeof("ceph.dir.layout"), 349 .getxattr_cb = ceph_vxattrcb_layout, 350 .exists_cb = ceph_vxattrcb_layout_exists, 351 .flags = VXATTR_FLAG_HIDDEN, 352 }, 353 XATTR_LAYOUT_FIELD(dir, layout, stripe_unit), 354 XATTR_LAYOUT_FIELD(dir, layout, stripe_count), 355 XATTR_LAYOUT_FIELD(dir, layout, object_size), 356 XATTR_LAYOUT_FIELD(dir, layout, pool), 357 XATTR_LAYOUT_FIELD(dir, layout, pool_namespace), 358 XATTR_NAME_CEPH(dir, entries, 0), 359 XATTR_NAME_CEPH(dir, files, 0), 360 XATTR_NAME_CEPH(dir, subdirs, 0), 361 XATTR_RSTAT_FIELD(dir, rentries), 362 XATTR_RSTAT_FIELD(dir, rfiles), 363 XATTR_RSTAT_FIELD(dir, rsubdirs), 364 XATTR_RSTAT_FIELD(dir, rbytes), 365 XATTR_RSTAT_FIELD_UPDATABLE(dir, rctime), 366 { 367 .name = "ceph.dir.pin", 368 .name_size = sizeof("ceph.dir.pin"), 369 .getxattr_cb = ceph_vxattrcb_dir_pin, 370 .exists_cb = ceph_vxattrcb_dir_pin_exists, 371 .flags = VXATTR_FLAG_HIDDEN, 372 }, 373 { 374 .name = "ceph.quota", 375 .name_size = sizeof("ceph.quota"), 376 .getxattr_cb = ceph_vxattrcb_quota, 377 .exists_cb = ceph_vxattrcb_quota_exists, 378 .flags = VXATTR_FLAG_HIDDEN, 379 }, 380 XATTR_QUOTA_FIELD(quota, max_bytes), 381 XATTR_QUOTA_FIELD(quota, max_files), 382 { 383 .name = "ceph.snap.btime", 384 .name_size = sizeof("ceph.snap.btime"), 385 .getxattr_cb = ceph_vxattrcb_snap_btime, 386 .exists_cb = ceph_vxattrcb_snap_btime_exists, 387 .flags = VXATTR_FLAG_READONLY, 388 }, 389 { .name = NULL, 0 } /* Required table terminator */ 390}; 391 392/* files */ 393 394static struct ceph_vxattr ceph_file_vxattrs[] = { 395 { 396 .name = "ceph.file.layout", 397 .name_size = sizeof("ceph.file.layout"), 398 .getxattr_cb = ceph_vxattrcb_layout, 399 .exists_cb = ceph_vxattrcb_layout_exists, 400 .flags = VXATTR_FLAG_HIDDEN, 401 }, 402 XATTR_LAYOUT_FIELD(file, layout, stripe_unit), 403 XATTR_LAYOUT_FIELD(file, layout, stripe_count), 404 XATTR_LAYOUT_FIELD(file, layout, object_size), 405 XATTR_LAYOUT_FIELD(file, layout, pool), 406 XATTR_LAYOUT_FIELD(file, layout, pool_namespace), 407 { 408 .name = "ceph.snap.btime", 409 .name_size = sizeof("ceph.snap.btime"), 410 .getxattr_cb = ceph_vxattrcb_snap_btime, 411 .exists_cb = ceph_vxattrcb_snap_btime_exists, 412 .flags = VXATTR_FLAG_READONLY, 413 }, 414 { .name = NULL, 0 } /* Required table terminator */ 415}; 416 417static struct ceph_vxattr *ceph_inode_vxattrs(struct inode *inode) 418{ 419 if (S_ISDIR(inode->i_mode)) 420 return ceph_dir_vxattrs; 421 else if (S_ISREG(inode->i_mode)) 422 return ceph_file_vxattrs; 423 return NULL; 424} 425 426static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, 427 const char *name) 428{ 429 struct ceph_vxattr *vxattr = ceph_inode_vxattrs(inode); 430 431 if (vxattr) { 432 while (vxattr->name) { 433 if (!strcmp(vxattr->name, name)) 434 return vxattr; 435 vxattr++; 436 } 437 } 438 439 return NULL; 440} 441 442static int __set_xattr(struct ceph_inode_info *ci, 443 const char *name, int name_len, 444 const char *val, int val_len, 445 int flags, int update_xattr, 446 struct ceph_inode_xattr **newxattr) 447{ 448 struct rb_node **p; 449 struct rb_node *parent = NULL; 450 struct ceph_inode_xattr *xattr = NULL; 451 int c; 452 int new = 0; 453 454 p = &ci->i_xattrs.index.rb_node; 455 while (*p) { 456 parent = *p; 457 xattr = rb_entry(parent, struct ceph_inode_xattr, node); 458 c = strncmp(name, xattr->name, min(name_len, xattr->name_len)); 459 if (c < 0) 460 p = &(*p)->rb_left; 461 else if (c > 0) 462 p = &(*p)->rb_right; 463 else { 464 if (name_len == xattr->name_len) 465 break; 466 else if (name_len < xattr->name_len) 467 p = &(*p)->rb_left; 468 else 469 p = &(*p)->rb_right; 470 } 471 xattr = NULL; 472 } 473 474 if (update_xattr) { 475 int err = 0; 476 477 if (xattr && (flags & XATTR_CREATE)) 478 err = -EEXIST; 479 else if (!xattr && (flags & XATTR_REPLACE)) 480 err = -ENODATA; 481 if (err) { 482 kfree(name); 483 kfree(val); 484 kfree(*newxattr); 485 return err; 486 } 487 if (update_xattr < 0) { 488 if (xattr) 489 __remove_xattr(ci, xattr); 490 kfree(name); 491 kfree(*newxattr); 492 return 0; 493 } 494 } 495 496 if (!xattr) { 497 new = 1; 498 xattr = *newxattr; 499 xattr->name = name; 500 xattr->name_len = name_len; 501 xattr->should_free_name = update_xattr; 502 503 ci->i_xattrs.count++; 504 dout("__set_xattr count=%d\n", ci->i_xattrs.count); 505 } else { 506 kfree(*newxattr); 507 *newxattr = NULL; 508 if (xattr->should_free_val) 509 kfree(xattr->val); 510 511 if (update_xattr) { 512 kfree(name); 513 name = xattr->name; 514 } 515 ci->i_xattrs.names_size -= xattr->name_len; 516 ci->i_xattrs.vals_size -= xattr->val_len; 517 } 518 ci->i_xattrs.names_size += name_len; 519 ci->i_xattrs.vals_size += val_len; 520 if (val) 521 xattr->val = val; 522 else 523 xattr->val = ""; 524 525 xattr->val_len = val_len; 526 xattr->dirty = update_xattr; 527 xattr->should_free_val = (val && update_xattr); 528 529 if (new) { 530 rb_link_node(&xattr->node, parent, p); 531 rb_insert_color(&xattr->node, &ci->i_xattrs.index); 532 dout("__set_xattr_val p=%p\n", p); 533 } 534 535 dout("__set_xattr_val added %llx.%llx xattr %p %.*s=%.*s\n", 536 ceph_vinop(&ci->vfs_inode), xattr, name_len, name, val_len, val); 537 538 return 0; 539} 540 541static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci, 542 const char *name) 543{ 544 struct rb_node **p; 545 struct rb_node *parent = NULL; 546 struct ceph_inode_xattr *xattr = NULL; 547 int name_len = strlen(name); 548 int c; 549 550 p = &ci->i_xattrs.index.rb_node; 551 while (*p) { 552 parent = *p; 553 xattr = rb_entry(parent, struct ceph_inode_xattr, node); 554 c = strncmp(name, xattr->name, xattr->name_len); 555 if (c == 0 && name_len > xattr->name_len) 556 c = 1; 557 if (c < 0) 558 p = &(*p)->rb_left; 559 else if (c > 0) 560 p = &(*p)->rb_right; 561 else { 562 dout("__get_xattr %s: found %.*s\n", name, 563 xattr->val_len, xattr->val); 564 return xattr; 565 } 566 } 567 568 dout("__get_xattr %s: not found\n", name); 569 570 return NULL; 571} 572 573static void __free_xattr(struct ceph_inode_xattr *xattr) 574{ 575 BUG_ON(!xattr); 576 577 if (xattr->should_free_name) 578 kfree(xattr->name); 579 if (xattr->should_free_val) 580 kfree(xattr->val); 581 582 kfree(xattr); 583} 584 585static int __remove_xattr(struct ceph_inode_info *ci, 586 struct ceph_inode_xattr *xattr) 587{ 588 if (!xattr) 589 return -ENODATA; 590 591 rb_erase(&xattr->node, &ci->i_xattrs.index); 592 593 if (xattr->should_free_name) 594 kfree(xattr->name); 595 if (xattr->should_free_val) 596 kfree(xattr->val); 597 598 ci->i_xattrs.names_size -= xattr->name_len; 599 ci->i_xattrs.vals_size -= xattr->val_len; 600 ci->i_xattrs.count--; 601 kfree(xattr); 602 603 return 0; 604} 605 606static char *__copy_xattr_names(struct ceph_inode_info *ci, 607 char *dest) 608{ 609 struct rb_node *p; 610 struct ceph_inode_xattr *xattr = NULL; 611 612 p = rb_first(&ci->i_xattrs.index); 613 dout("__copy_xattr_names count=%d\n", ci->i_xattrs.count); 614 615 while (p) { 616 xattr = rb_entry(p, struct ceph_inode_xattr, node); 617 memcpy(dest, xattr->name, xattr->name_len); 618 dest[xattr->name_len] = '\0'; 619 620 dout("dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name, 621 xattr->name_len, ci->i_xattrs.names_size); 622 623 dest += xattr->name_len + 1; 624 p = rb_next(p); 625 } 626 627 return dest; 628} 629 630void __ceph_destroy_xattrs(struct ceph_inode_info *ci) 631{ 632 struct rb_node *p, *tmp; 633 struct ceph_inode_xattr *xattr = NULL; 634 635 p = rb_first(&ci->i_xattrs.index); 636 637 dout("__ceph_destroy_xattrs p=%p\n", p); 638 639 while (p) { 640 xattr = rb_entry(p, struct ceph_inode_xattr, node); 641 tmp = p; 642 p = rb_next(tmp); 643 dout("__ceph_destroy_xattrs next p=%p (%.*s)\n", p, 644 xattr->name_len, xattr->name); 645 rb_erase(tmp, &ci->i_xattrs.index); 646 647 __free_xattr(xattr); 648 } 649 650 ci->i_xattrs.names_size = 0; 651 ci->i_xattrs.vals_size = 0; 652 ci->i_xattrs.index_version = 0; 653 ci->i_xattrs.count = 0; 654 ci->i_xattrs.index = RB_ROOT; 655} 656 657static int __build_xattrs(struct inode *inode) 658 __releases(ci->i_ceph_lock) 659 __acquires(ci->i_ceph_lock) 660{ 661 u32 namelen; 662 u32 numattr = 0; 663 void *p, *end; 664 u32 len; 665 const char *name, *val; 666 struct ceph_inode_info *ci = ceph_inode(inode); 667 u64 xattr_version; 668 struct ceph_inode_xattr **xattrs = NULL; 669 int err = 0; 670 int i; 671 672 dout("__build_xattrs() len=%d\n", 673 ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0); 674 675 if (ci->i_xattrs.index_version >= ci->i_xattrs.version) 676 return 0; /* already built */ 677 678 __ceph_destroy_xattrs(ci); 679 680start: 681 /* updated internal xattr rb tree */ 682 if (ci->i_xattrs.blob && ci->i_xattrs.blob->vec.iov_len > 4) { 683 p = ci->i_xattrs.blob->vec.iov_base; 684 end = p + ci->i_xattrs.blob->vec.iov_len; 685 ceph_decode_32_safe(&p, end, numattr, bad); 686 xattr_version = ci->i_xattrs.version; 687 spin_unlock(&ci->i_ceph_lock); 688 689 xattrs = kcalloc(numattr, sizeof(struct ceph_inode_xattr *), 690 GFP_NOFS); 691 err = -ENOMEM; 692 if (!xattrs) 693 goto bad_lock; 694 695 for (i = 0; i < numattr; i++) { 696 xattrs[i] = kmalloc(sizeof(struct ceph_inode_xattr), 697 GFP_NOFS); 698 if (!xattrs[i]) 699 goto bad_lock; 700 } 701 702 spin_lock(&ci->i_ceph_lock); 703 if (ci->i_xattrs.version != xattr_version) { 704 /* lost a race, retry */ 705 for (i = 0; i < numattr; i++) 706 kfree(xattrs[i]); 707 kfree(xattrs); 708 xattrs = NULL; 709 goto start; 710 } 711 err = -EIO; 712 while (numattr--) { 713 ceph_decode_32_safe(&p, end, len, bad); 714 namelen = len; 715 name = p; 716 p += len; 717 ceph_decode_32_safe(&p, end, len, bad); 718 val = p; 719 p += len; 720 721 err = __set_xattr(ci, name, namelen, val, len, 722 0, 0, &xattrs[numattr]); 723 724 if (err < 0) 725 goto bad; 726 } 727 kfree(xattrs); 728 } 729 ci->i_xattrs.index_version = ci->i_xattrs.version; 730 ci->i_xattrs.dirty = false; 731 732 return err; 733bad_lock: 734 spin_lock(&ci->i_ceph_lock); 735bad: 736 if (xattrs) { 737 for (i = 0; i < numattr; i++) 738 kfree(xattrs[i]); 739 kfree(xattrs); 740 } 741 ci->i_xattrs.names_size = 0; 742 return err; 743} 744 745static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size, 746 int val_size) 747{ 748 /* 749 * 4 bytes for the length, and additional 4 bytes per each xattr name, 750 * 4 bytes per each value 751 */ 752 int size = 4 + ci->i_xattrs.count*(4 + 4) + 753 ci->i_xattrs.names_size + 754 ci->i_xattrs.vals_size; 755 dout("__get_required_blob_size c=%d names.size=%d vals.size=%d\n", 756 ci->i_xattrs.count, ci->i_xattrs.names_size, 757 ci->i_xattrs.vals_size); 758 759 if (name_size) 760 size += 4 + 4 + name_size + val_size; 761 762 return size; 763} 764 765/* 766 * If there are dirty xattrs, reencode xattrs into the prealloc_blob 767 * and swap into place. It returns the old i_xattrs.blob (or NULL) so 768 * that it can be freed by the caller as the i_ceph_lock is likely to be 769 * held. 770 */ 771struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci) 772{ 773 struct rb_node *p; 774 struct ceph_inode_xattr *xattr = NULL; 775 struct ceph_buffer *old_blob = NULL; 776 void *dest; 777 778 dout("__build_xattrs_blob %p\n", &ci->vfs_inode); 779 if (ci->i_xattrs.dirty) { 780 int need = __get_required_blob_size(ci, 0, 0); 781 782 BUG_ON(need > ci->i_xattrs.prealloc_blob->alloc_len); 783 784 p = rb_first(&ci->i_xattrs.index); 785 dest = ci->i_xattrs.prealloc_blob->vec.iov_base; 786 787 ceph_encode_32(&dest, ci->i_xattrs.count); 788 while (p) { 789 xattr = rb_entry(p, struct ceph_inode_xattr, node); 790 791 ceph_encode_32(&dest, xattr->name_len); 792 memcpy(dest, xattr->name, xattr->name_len); 793 dest += xattr->name_len; 794 ceph_encode_32(&dest, xattr->val_len); 795 memcpy(dest, xattr->val, xattr->val_len); 796 dest += xattr->val_len; 797 798 p = rb_next(p); 799 } 800 801 /* adjust buffer len; it may be larger than we need */ 802 ci->i_xattrs.prealloc_blob->vec.iov_len = 803 dest - ci->i_xattrs.prealloc_blob->vec.iov_base; 804 805 if (ci->i_xattrs.blob) 806 old_blob = ci->i_xattrs.blob; 807 ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob; 808 ci->i_xattrs.prealloc_blob = NULL; 809 ci->i_xattrs.dirty = false; 810 ci->i_xattrs.version++; 811 } 812 813 return old_blob; 814} 815 816static inline int __get_request_mask(struct inode *in) { 817 struct ceph_mds_request *req = current->journal_info; 818 int mask = 0; 819 if (req && req->r_target_inode == in) { 820 if (req->r_op == CEPH_MDS_OP_LOOKUP || 821 req->r_op == CEPH_MDS_OP_LOOKUPINO || 822 req->r_op == CEPH_MDS_OP_LOOKUPPARENT || 823 req->r_op == CEPH_MDS_OP_GETATTR) { 824 mask = le32_to_cpu(req->r_args.getattr.mask); 825 } else if (req->r_op == CEPH_MDS_OP_OPEN || 826 req->r_op == CEPH_MDS_OP_CREATE) { 827 mask = le32_to_cpu(req->r_args.open.mask); 828 } 829 } 830 return mask; 831} 832 833ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, 834 size_t size) 835{ 836 struct ceph_inode_info *ci = ceph_inode(inode); 837 struct ceph_inode_xattr *xattr; 838 struct ceph_vxattr *vxattr = NULL; 839 int req_mask; 840 ssize_t err; 841 842 /* let's see if a virtual xattr was requested */ 843 vxattr = ceph_match_vxattr(inode, name); 844 if (vxattr) { 845 int mask = 0; 846 if (vxattr->flags & VXATTR_FLAG_RSTAT) 847 mask |= CEPH_STAT_RSTAT; 848 err = ceph_do_getattr(inode, mask, true); 849 if (err) 850 return err; 851 err = -ENODATA; 852 if (!(vxattr->exists_cb && !vxattr->exists_cb(ci))) { 853 err = vxattr->getxattr_cb(ci, value, size); 854 if (size && size < err) 855 err = -ERANGE; 856 } 857 return err; 858 } 859 860 req_mask = __get_request_mask(inode); 861 862 spin_lock(&ci->i_ceph_lock); 863 dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name, 864 ci->i_xattrs.version, ci->i_xattrs.index_version); 865 866 if (ci->i_xattrs.version == 0 || 867 !((req_mask & CEPH_CAP_XATTR_SHARED) || 868 __ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1))) { 869 spin_unlock(&ci->i_ceph_lock); 870 871 /* security module gets xattr while filling trace */ 872 if (current->journal_info) { 873 pr_warn_ratelimited("sync getxattr %p " 874 "during filling trace\n", inode); 875 return -EBUSY; 876 } 877 878 /* get xattrs from mds (if we don't already have them) */ 879 err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true); 880 if (err) 881 return err; 882 spin_lock(&ci->i_ceph_lock); 883 } 884 885 err = __build_xattrs(inode); 886 if (err < 0) 887 goto out; 888 889 err = -ENODATA; /* == ENOATTR */ 890 xattr = __get_xattr(ci, name); 891 if (!xattr) 892 goto out; 893 894 err = -ERANGE; 895 if (size && size < xattr->val_len) 896 goto out; 897 898 err = xattr->val_len; 899 if (size == 0) 900 goto out; 901 902 memcpy(value, xattr->val, xattr->val_len); 903 904 if (current->journal_info && 905 !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) && 906 security_ismaclabel(name + XATTR_SECURITY_PREFIX_LEN)) 907 ci->i_ceph_flags |= CEPH_I_SEC_INITED; 908out: 909 spin_unlock(&ci->i_ceph_lock); 910 return err; 911} 912 913ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) 914{ 915 struct inode *inode = d_inode(dentry); 916 struct ceph_inode_info *ci = ceph_inode(inode); 917 bool len_only = (size == 0); 918 u32 namelen; 919 int err; 920 921 spin_lock(&ci->i_ceph_lock); 922 dout("listxattr %p ver=%lld index_ver=%lld\n", inode, 923 ci->i_xattrs.version, ci->i_xattrs.index_version); 924 925 if (ci->i_xattrs.version == 0 || 926 !__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) { 927 spin_unlock(&ci->i_ceph_lock); 928 err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR, true); 929 if (err) 930 return err; 931 spin_lock(&ci->i_ceph_lock); 932 } 933 934 err = __build_xattrs(inode); 935 if (err < 0) 936 goto out; 937 938 /* add 1 byte for each xattr due to the null termination */ 939 namelen = ci->i_xattrs.names_size + ci->i_xattrs.count; 940 if (!len_only) { 941 if (namelen > size) { 942 err = -ERANGE; 943 goto out; 944 } 945 names = __copy_xattr_names(ci, names); 946 size -= namelen; 947 } 948 err = namelen; 949out: 950 spin_unlock(&ci->i_ceph_lock); 951 return err; 952} 953 954static int ceph_sync_setxattr(struct inode *inode, const char *name, 955 const char *value, size_t size, int flags) 956{ 957 struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb); 958 struct ceph_inode_info *ci = ceph_inode(inode); 959 struct ceph_mds_request *req; 960 struct ceph_mds_client *mdsc = fsc->mdsc; 961 struct ceph_pagelist *pagelist = NULL; 962 int op = CEPH_MDS_OP_SETXATTR; 963 int err; 964 965 if (size > 0) { 966 /* copy value into pagelist */ 967 pagelist = ceph_pagelist_alloc(GFP_NOFS); 968 if (!pagelist) 969 return -ENOMEM; 970 971 err = ceph_pagelist_append(pagelist, value, size); 972 if (err) 973 goto out; 974 } else if (!value) { 975 if (flags & CEPH_XATTR_REPLACE) 976 op = CEPH_MDS_OP_RMXATTR; 977 else 978 flags |= CEPH_XATTR_REMOVE; 979 } 980 981 dout("setxattr value=%.*s\n", (int)size, value); 982 983 /* do request */ 984 req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); 985 if (IS_ERR(req)) { 986 err = PTR_ERR(req); 987 goto out; 988 } 989 990 req->r_path2 = kstrdup(name, GFP_NOFS); 991 if (!req->r_path2) { 992 ceph_mdsc_put_request(req); 993 err = -ENOMEM; 994 goto out; 995 } 996 997 if (op == CEPH_MDS_OP_SETXATTR) { 998 req->r_args.setxattr.flags = cpu_to_le32(flags); 999 req->r_pagelist = pagelist; 1000 pagelist = NULL; 1001 } 1002 1003 req->r_inode = inode; 1004 ihold(inode); 1005 req->r_num_caps = 1; 1006 req->r_inode_drop = CEPH_CAP_XATTR_SHARED; 1007 1008 dout("xattr.ver (before): %lld\n", ci->i_xattrs.version); 1009 err = ceph_mdsc_do_request(mdsc, NULL, req); 1010 ceph_mdsc_put_request(req); 1011 dout("xattr.ver (after): %lld\n", ci->i_xattrs.version); 1012 1013out: 1014 if (pagelist) 1015 ceph_pagelist_release(pagelist); 1016 return err; 1017} 1018 1019int __ceph_setxattr(struct inode *inode, const char *name, 1020 const void *value, size_t size, int flags) 1021{ 1022 struct ceph_vxattr *vxattr; 1023 struct ceph_inode_info *ci = ceph_inode(inode); 1024 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; 1025 struct ceph_cap_flush *prealloc_cf = NULL; 1026 struct ceph_buffer *old_blob = NULL; 1027 int issued; 1028 int err; 1029 int dirty = 0; 1030 int name_len = strlen(name); 1031 int val_len = size; 1032 char *newname = NULL; 1033 char *newval = NULL; 1034 struct ceph_inode_xattr *xattr = NULL; 1035 int required_blob_size; 1036 bool check_realm = false; 1037 bool lock_snap_rwsem = false; 1038 1039 if (ceph_snap(inode) != CEPH_NOSNAP) 1040 return -EROFS; 1041 1042 vxattr = ceph_match_vxattr(inode, name); 1043 if (vxattr) { 1044 if (vxattr->flags & VXATTR_FLAG_READONLY) 1045 return -EOPNOTSUPP; 1046 if (value && !strncmp(vxattr->name, "ceph.quota", 10)) 1047 check_realm = true; 1048 } 1049 1050 /* pass any unhandled ceph.* xattrs through to the MDS */ 1051 if (!strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN)) 1052 goto do_sync_unlocked; 1053 1054 /* preallocate memory for xattr name, value, index node */ 1055 err = -ENOMEM; 1056 newname = kmemdup(name, name_len + 1, GFP_NOFS); 1057 if (!newname) 1058 goto out; 1059 1060 if (val_len) { 1061 newval = kmemdup(value, val_len, GFP_NOFS); 1062 if (!newval) 1063 goto out; 1064 } 1065 1066 xattr = kmalloc(sizeof(struct ceph_inode_xattr), GFP_NOFS); 1067 if (!xattr) 1068 goto out; 1069 1070 prealloc_cf = ceph_alloc_cap_flush(); 1071 if (!prealloc_cf) 1072 goto out; 1073 1074 spin_lock(&ci->i_ceph_lock); 1075retry: 1076 issued = __ceph_caps_issued(ci, NULL); 1077 if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) 1078 goto do_sync; 1079 1080 if (!lock_snap_rwsem && !ci->i_head_snapc) { 1081 lock_snap_rwsem = true; 1082 if (!down_read_trylock(&mdsc->snap_rwsem)) { 1083 spin_unlock(&ci->i_ceph_lock); 1084 down_read(&mdsc->snap_rwsem); 1085 spin_lock(&ci->i_ceph_lock); 1086 goto retry; 1087 } 1088 } 1089 1090 dout("setxattr %p name '%s' issued %s\n", inode, name, 1091 ceph_cap_string(issued)); 1092 __build_xattrs(inode); 1093 1094 required_blob_size = __get_required_blob_size(ci, name_len, val_len); 1095 1096 if (!ci->i_xattrs.prealloc_blob || 1097 required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { 1098 struct ceph_buffer *blob; 1099 1100 spin_unlock(&ci->i_ceph_lock); 1101 ceph_buffer_put(old_blob); /* Shouldn't be required */ 1102 dout(" pre-allocating new blob size=%d\n", required_blob_size); 1103 blob = ceph_buffer_new(required_blob_size, GFP_NOFS); 1104 if (!blob) 1105 goto do_sync_unlocked; 1106 spin_lock(&ci->i_ceph_lock); 1107 /* prealloc_blob can't be released while holding i_ceph_lock */ 1108 if (ci->i_xattrs.prealloc_blob) 1109 old_blob = ci->i_xattrs.prealloc_blob; 1110 ci->i_xattrs.prealloc_blob = blob; 1111 goto retry; 1112 } 1113 1114 err = __set_xattr(ci, newname, name_len, newval, val_len, 1115 flags, value ? 1 : -1, &xattr); 1116 1117 if (!err) { 1118 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL, 1119 &prealloc_cf); 1120 ci->i_xattrs.dirty = true; 1121 inode->i_ctime = current_time(inode); 1122 } 1123 1124 spin_unlock(&ci->i_ceph_lock); 1125 ceph_buffer_put(old_blob); 1126 if (lock_snap_rwsem) 1127 up_read(&mdsc->snap_rwsem); 1128 if (dirty) 1129 __mark_inode_dirty(inode, dirty); 1130 ceph_free_cap_flush(prealloc_cf); 1131 return err; 1132 1133do_sync: 1134 spin_unlock(&ci->i_ceph_lock); 1135do_sync_unlocked: 1136 if (lock_snap_rwsem) 1137 up_read(&mdsc->snap_rwsem); 1138 1139 /* security module set xattr while filling trace */ 1140 if (current->journal_info) { 1141 pr_warn_ratelimited("sync setxattr %p " 1142 "during filling trace\n", inode); 1143 err = -EBUSY; 1144 } else { 1145 err = ceph_sync_setxattr(inode, name, value, size, flags); 1146 if (err >= 0 && check_realm) { 1147 /* check if snaprealm was created for quota inode */ 1148 spin_lock(&ci->i_ceph_lock); 1149 if ((ci->i_max_files || ci->i_max_bytes) && 1150 !(ci->i_snap_realm && 1151 ci->i_snap_realm->ino == ci->i_vino.ino)) 1152 err = -EOPNOTSUPP; 1153 spin_unlock(&ci->i_ceph_lock); 1154 } 1155 } 1156out: 1157 ceph_free_cap_flush(prealloc_cf); 1158 kfree(newname); 1159 kfree(newval); 1160 kfree(xattr); 1161 return err; 1162} 1163 1164static int ceph_get_xattr_handler(const struct xattr_handler *handler, 1165 struct dentry *dentry, struct inode *inode, 1166 const char *name, void *value, size_t size) 1167{ 1168 if (!ceph_is_valid_xattr(name)) 1169 return -EOPNOTSUPP; 1170 return __ceph_getxattr(inode, name, value, size); 1171} 1172 1173static int ceph_set_xattr_handler(const struct xattr_handler *handler, 1174 struct dentry *unused, struct inode *inode, 1175 const char *name, const void *value, 1176 size_t size, int flags) 1177{ 1178 if (!ceph_is_valid_xattr(name)) 1179 return -EOPNOTSUPP; 1180 return __ceph_setxattr(inode, name, value, size, flags); 1181} 1182 1183static const struct xattr_handler ceph_other_xattr_handler = { 1184 .prefix = "", /* match any name => handlers called with full name */ 1185 .get = ceph_get_xattr_handler, 1186 .set = ceph_set_xattr_handler, 1187}; 1188 1189#ifdef CONFIG_SECURITY 1190bool ceph_security_xattr_wanted(struct inode *in) 1191{ 1192 return in->i_security != NULL; 1193} 1194 1195bool ceph_security_xattr_deadlock(struct inode *in) 1196{ 1197 struct ceph_inode_info *ci; 1198 bool ret; 1199 if (!in->i_security) 1200 return false; 1201 ci = ceph_inode(in); 1202 spin_lock(&ci->i_ceph_lock); 1203 ret = !(ci->i_ceph_flags & CEPH_I_SEC_INITED) && 1204 !(ci->i_xattrs.version > 0 && 1205 __ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0)); 1206 spin_unlock(&ci->i_ceph_lock); 1207 return ret; 1208} 1209 1210#ifdef CONFIG_CEPH_FS_SECURITY_LABEL 1211int ceph_security_init_secctx(struct dentry *dentry, umode_t mode, 1212 struct ceph_acl_sec_ctx *as_ctx) 1213{ 1214 struct ceph_pagelist *pagelist = as_ctx->pagelist; 1215 const char *name; 1216 size_t name_len; 1217 int err; 1218 1219 err = security_dentry_init_security(dentry, mode, &dentry->d_name, 1220 &as_ctx->sec_ctx, 1221 &as_ctx->sec_ctxlen); 1222 if (err < 0) { 1223 WARN_ON_ONCE(err != -EOPNOTSUPP); 1224 err = 0; /* do nothing */ 1225 goto out; 1226 } 1227 1228 err = -ENOMEM; 1229 if (!pagelist) { 1230 pagelist = ceph_pagelist_alloc(GFP_KERNEL); 1231 if (!pagelist) 1232 goto out; 1233 err = ceph_pagelist_reserve(pagelist, PAGE_SIZE); 1234 if (err) 1235 goto out; 1236 ceph_pagelist_encode_32(pagelist, 1); 1237 } 1238 1239 /* 1240 * FIXME: Make security_dentry_init_security() generic. Currently 1241 * It only supports single security module and only selinux has 1242 * dentry_init_security hook. 1243 */ 1244 name = XATTR_NAME_SELINUX; 1245 name_len = strlen(name); 1246 err = ceph_pagelist_reserve(pagelist, 1247 4 * 2 + name_len + as_ctx->sec_ctxlen); 1248 if (err) 1249 goto out; 1250 1251 if (as_ctx->pagelist) { 1252 /* update count of KV pairs */ 1253 BUG_ON(pagelist->length <= sizeof(__le32)); 1254 if (list_is_singular(&pagelist->head)) { 1255 le32_add_cpu((__le32*)pagelist->mapped_tail, 1); 1256 } else { 1257 struct page *page = list_first_entry(&pagelist->head, 1258 struct page, lru); 1259 void *addr = kmap_atomic(page); 1260 le32_add_cpu((__le32*)addr, 1); 1261 kunmap_atomic(addr); 1262 } 1263 } else { 1264 as_ctx->pagelist = pagelist; 1265 } 1266 1267 ceph_pagelist_encode_32(pagelist, name_len); 1268 ceph_pagelist_append(pagelist, name, name_len); 1269 1270 ceph_pagelist_encode_32(pagelist, as_ctx->sec_ctxlen); 1271 ceph_pagelist_append(pagelist, as_ctx->sec_ctx, as_ctx->sec_ctxlen); 1272 1273 err = 0; 1274out: 1275 if (pagelist && !as_ctx->pagelist) 1276 ceph_pagelist_release(pagelist); 1277 return err; 1278} 1279#endif /* CONFIG_CEPH_FS_SECURITY_LABEL */ 1280#endif /* CONFIG_SECURITY */ 1281 1282void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx) 1283{ 1284#ifdef CONFIG_CEPH_FS_POSIX_ACL 1285 posix_acl_release(as_ctx->acl); 1286 posix_acl_release(as_ctx->default_acl); 1287#endif 1288#ifdef CONFIG_CEPH_FS_SECURITY_LABEL 1289 security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen); 1290#endif 1291 if (as_ctx->pagelist) 1292 ceph_pagelist_release(as_ctx->pagelist); 1293} 1294 1295/* 1296 * List of handlers for synthetic system.* attributes. Other 1297 * attributes are handled directly. 1298 */ 1299const struct xattr_handler *ceph_xattr_handlers[] = { 1300#ifdef CONFIG_CEPH_FS_POSIX_ACL 1301 &posix_acl_access_xattr_handler, 1302 &posix_acl_default_xattr_handler, 1303#endif 1304 &ceph_other_xattr_handler, 1305 NULL, 1306}; 1307