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