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