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