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