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