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