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