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