Blame view

fs/btrfs/xattr.c 12.4 KB
5103e947b   Josef Bacik   xattr support for...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   * Copyright (C) 2007 Red Hat.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License v2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
  
  #include <linux/init.h>
  #include <linux/fs.h>
  #include <linux/slab.h>
  #include <linux/rwsem.h>
  #include <linux/xattr.h>
0279b4cd8   Jim Owens   Btrfs: selinux su...
24
  #include <linux/security.h>
996a710d4   Christoph Hellwig   btrfs: use generi...
25
  #include <linux/posix_acl_xattr.h>
5103e947b   Josef Bacik   xattr support for...
26
27
28
29
30
  #include "ctree.h"
  #include "btrfs_inode.h"
  #include "transaction.h"
  #include "xattr.h"
  #include "disk-io.h"
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
31
  #include "props.h"
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
32
  #include "locking.h"
33268eaf0   Josef Bacik   Btrfs: Add ACL su...
33

5103e947b   Josef Bacik   xattr support for...
34

95819c057   Christoph Hellwig   Btrfs: optimize b...
35
36
  ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
  				void *buffer, size_t size)
5103e947b   Josef Bacik   xattr support for...
37
38
39
40
41
  {
  	struct btrfs_dir_item *di;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_path *path;
  	struct extent_buffer *leaf;
5103e947b   Josef Bacik   xattr support for...
42
43
  	int ret = 0;
  	unsigned long data_ptr;
5103e947b   Josef Bacik   xattr support for...
44
45
  
  	path = btrfs_alloc_path();
95819c057   Christoph Hellwig   Btrfs: optimize b...
46
  	if (!path)
5103e947b   Josef Bacik   xattr support for...
47
  		return -ENOMEM;
5103e947b   Josef Bacik   xattr support for...
48

5103e947b   Josef Bacik   xattr support for...
49
  	/* lookup the xattr by name */
f85b7379c   David Sterba   btrfs: fix over-8...
50
51
  	di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(BTRFS_I(inode)),
  			name, strlen(name), 0);
070604040   Josef Bacik   Btrfs: cleanup xa...
52
  	if (!di) {
5103e947b   Josef Bacik   xattr support for...
53
54
  		ret = -ENODATA;
  		goto out;
070604040   Josef Bacik   Btrfs: cleanup xa...
55
56
57
  	} else if (IS_ERR(di)) {
  		ret = PTR_ERR(di);
  		goto out;
5103e947b   Josef Bacik   xattr support for...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  	}
  
  	leaf = path->nodes[0];
  	/* if size is 0, that means we want the size of the attr */
  	if (!size) {
  		ret = btrfs_dir_data_len(leaf, di);
  		goto out;
  	}
  
  	/* now get the data out of our dir_item */
  	if (btrfs_dir_data_len(leaf, di) > size) {
  		ret = -ERANGE;
  		goto out;
  	}
070604040   Josef Bacik   Btrfs: cleanup xa...
72
73
74
75
76
77
78
79
  
  	/*
  	 * The way things are packed into the leaf is like this
  	 * |struct btrfs_dir_item|name|data|
  	 * where name is the xattr name, so security.foo, and data is the
  	 * content of the xattr.  data_ptr points to the location in memory
  	 * where the data starts in the in memory leaf
  	 */
5103e947b   Josef Bacik   xattr support for...
80
81
82
  	data_ptr = (unsigned long)((char *)(di + 1) +
  				   btrfs_dir_name_len(leaf, di));
  	read_extent_buffer(leaf, buffer, data_ptr,
3acd7ee87   Josef Bacik   Btrfs: xattr fixes
83
  			   btrfs_dir_data_len(leaf, di));
5103e947b   Josef Bacik   xattr support for...
84
85
86
  	ret = btrfs_dir_data_len(leaf, di);
  
  out:
5103e947b   Josef Bacik   xattr support for...
87
88
89
  	btrfs_free_path(path);
  	return ret;
  }
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
90
91
92
  static int do_setxattr(struct btrfs_trans_handle *trans,
  		       struct inode *inode, const char *name,
  		       const void *value, size_t size, int flags)
5103e947b   Josef Bacik   xattr support for...
93
  {
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
94
  	struct btrfs_dir_item *di = NULL;
5103e947b   Josef Bacik   xattr support for...
95
  	struct btrfs_root *root = BTRFS_I(inode)->root;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
96
  	struct btrfs_fs_info *fs_info = root->fs_info;
5103e947b   Josef Bacik   xattr support for...
97
  	struct btrfs_path *path;
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
98
99
  	size_t name_len = strlen(name);
  	int ret = 0;
da17066c4   Jeff Mahoney   btrfs: pull node/...
100
  	if (name_len + size > BTRFS_MAX_XATTR_SIZE(root->fs_info))
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
101
  		return -ENOSPC;
5103e947b   Josef Bacik   xattr support for...
102
103
  
  	path = btrfs_alloc_path();
95819c057   Christoph Hellwig   Btrfs: optimize b...
104
  	if (!path)
5103e947b   Josef Bacik   xattr support for...
105
  		return -ENOMEM;
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
106
107
108
  	path->skip_release_on_error = 1;
  
  	if (!value) {
f85b7379c   David Sterba   btrfs: fix over-8...
109
110
  		di = btrfs_lookup_xattr(trans, root, path,
  				btrfs_ino(BTRFS_I(inode)), name, name_len, -1);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
111
112
  		if (!di && (flags & XATTR_REPLACE))
  			ret = -ENODATA;
5cdf83edb   Filipe Manana   Btrfs: do not ign...
113
114
  		else if (IS_ERR(di))
  			ret = PTR_ERR(di);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
115
116
117
118
  		else if (di)
  			ret = btrfs_delete_one_dir_name(trans, root, path, di);
  		goto out;
  	}
5103e947b   Josef Bacik   xattr support for...
119

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
120
121
122
123
124
125
126
  	/*
  	 * For a replace we can't just do the insert blindly.
  	 * Do a lookup first (read-only btrfs_search_slot), and return if xattr
  	 * doesn't exist. If it exists, fall down below to the insert/replace
  	 * path - we can't race with a concurrent xattr delete, because the VFS
  	 * locks the inode's i_mutex before calling setxattr or removexattr.
  	 */
fa09200b8   Josef Bacik   Btrfs: try to onl...
127
  	if (flags & XATTR_REPLACE) {
5955102c9   Al Viro   wrappers for ->i_...
128
  		ASSERT(inode_is_locked(inode));
f85b7379c   David Sterba   btrfs: fix over-8...
129
130
  		di = btrfs_lookup_xattr(NULL, root, path,
  				btrfs_ino(BTRFS_I(inode)), name, name_len, 0);
5cdf83edb   Filipe Manana   Btrfs: do not ign...
131
  		if (!di)
fa09200b8   Josef Bacik   Btrfs: try to onl...
132
  			ret = -ENODATA;
5cdf83edb   Filipe Manana   Btrfs: do not ign...
133
134
135
  		else if (IS_ERR(di))
  			ret = PTR_ERR(di);
  		if (ret)
5103e947b   Josef Bacik   xattr support for...
136
  			goto out;
b3b4aa74b   David Sterba   btrfs: drop unuse...
137
  		btrfs_release_path(path);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
138
139
  		di = NULL;
  	}
4815053ab   David Sterba   btrfs: xattr: fix...
140

4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
141
  	ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(BTRFS_I(inode)),
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
142
143
  				      name, name_len, value, size);
  	if (ret == -EOVERFLOW) {
4815053ab   David Sterba   btrfs: xattr: fix...
144
  		/*
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
145
146
147
  		 * We have an existing item in a leaf, split_leaf couldn't
  		 * expand it. That item might have or not a dir_item that
  		 * matches our target xattr, so lets check.
4815053ab   David Sterba   btrfs: xattr: fix...
148
  		 */
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
149
150
  		ret = 0;
  		btrfs_assert_tree_locked(path->nodes[0]);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
151
  		di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
152
153
  		if (!di && !(flags & XATTR_REPLACE)) {
  			ret = -ENOSPC;
01e6deb25   Liu Bo   Btrfs: don't add ...
154
155
  			goto out;
  		}
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
156
157
  	} else if (ret == -EEXIST) {
  		ret = 0;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
158
  		di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
159
160
161
  		ASSERT(di); /* logic error */
  	} else if (ret) {
  		goto out;
fa09200b8   Josef Bacik   Btrfs: try to onl...
162
  	}
5103e947b   Josef Bacik   xattr support for...
163

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
164
  	if (di && (flags & XATTR_CREATE)) {
ed3ee9f44   Josef Bacik   Btrfs: fix regres...
165
  		ret = -EEXIST;
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
166
167
  		goto out;
  	}
ed3ee9f44   Josef Bacik   Btrfs: fix regres...
168

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
169
  	if (di) {
fa09200b8   Josef Bacik   Btrfs: try to onl...
170
  		/*
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
171
172
173
174
175
  		 * We're doing a replace, and it must be atomic, that is, at
  		 * any point in time we have either the old or the new xattr
  		 * value in the tree. We don't want readers (getxattr and
  		 * listxattrs) to miss a value, this is specially important
  		 * for ACLs.
fa09200b8   Josef Bacik   Btrfs: try to onl...
176
  		 */
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
177
178
179
180
181
182
183
184
185
186
  		const int slot = path->slots[0];
  		struct extent_buffer *leaf = path->nodes[0];
  		const u16 old_data_len = btrfs_dir_data_len(leaf, di);
  		const u32 item_size = btrfs_item_size_nr(leaf, slot);
  		const u32 data_size = sizeof(*di) + name_len + size;
  		struct btrfs_item *item;
  		unsigned long data_ptr;
  		char *ptr;
  
  		if (size > old_data_len) {
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
187
  			if (btrfs_leaf_free_space(fs_info, leaf) <
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
188
189
190
191
  			    (size - old_data_len)) {
  				ret = -ENOSPC;
  				goto out;
  			}
fa09200b8   Josef Bacik   Btrfs: try to onl...
192
  		}
33268eaf0   Josef Bacik   Btrfs: Add ACL su...
193

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
194
195
196
  		if (old_data_len + name_len + sizeof(*di) == item_size) {
  			/* No other xattrs packed in the same leaf item. */
  			if (size > old_data_len)
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
197
  				btrfs_extend_item(fs_info, path,
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
198
199
  						  size - old_data_len);
  			else if (size < old_data_len)
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
200
201
  				btrfs_truncate_item(fs_info, path,
  						    data_size, 1);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
202
203
204
205
206
  		} else {
  			/* There are other xattrs packed in the same item. */
  			ret = btrfs_delete_one_dir_name(trans, root, path, di);
  			if (ret)
  				goto out;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
207
  			btrfs_extend_item(fs_info, path, data_size);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
208
  		}
fa09200b8   Josef Bacik   Btrfs: try to onl...
209

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
210
211
212
213
214
215
216
217
218
  		item = btrfs_item_nr(slot);
  		ptr = btrfs_item_ptr(leaf, slot, char);
  		ptr += btrfs_item_size(leaf, item) - data_size;
  		di = (struct btrfs_dir_item *)ptr;
  		btrfs_set_dir_data_len(leaf, di, size);
  		data_ptr = ((unsigned long)(di + 1)) + name_len;
  		write_extent_buffer(leaf, value, data_ptr, size);
  		btrfs_mark_buffer_dirty(leaf);
  	} else {
fa09200b8   Josef Bacik   Btrfs: try to onl...
219
  		/*
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
220
221
222
  		 * Insert, and we had space for the xattr, so path->slots[0] is
  		 * where our xattr dir_item is and btrfs_insert_xattr_item()
  		 * filled it.
fa09200b8   Josef Bacik   Btrfs: try to onl...
223
  		 */
5103e947b   Josef Bacik   xattr support for...
224
  	}
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
225
226
227
228
  out:
  	btrfs_free_path(path);
  	return ret;
  }
4815053ab   David Sterba   btrfs: xattr: fix...
229
230
231
  /*
   * @value: "" makes the attribute to empty, NULL removes it
   */
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
232
233
234
235
236
237
  int __btrfs_setxattr(struct btrfs_trans_handle *trans,
  		     struct inode *inode, const char *name,
  		     const void *value, size_t size, int flags)
  {
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret;
e0d46f5c6   Andreas Gruenbacher   btrfs: Switch to ...
238
239
  	if (btrfs_root_readonly(root))
  		return -EROFS;
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
240
241
  	if (trans)
  		return do_setxattr(trans, inode, name, value, size, flags);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
242
243
244
  	trans = btrfs_start_transaction(root, 2);
  	if (IS_ERR(trans))
  		return PTR_ERR(trans);
5103e947b   Josef Bacik   xattr support for...
245

f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
246
247
248
  	ret = do_setxattr(trans, inode, name, value, size, flags);
  	if (ret)
  		goto out;
0c4d2d95d   Josef Bacik   Btrfs: use i_vers...
249
  	inode_inc_iversion(inode);
c2050a454   Deepa Dinamani   fs: Replace curre...
250
  	inode->i_ctime = current_time(inode);
e99761514   Josef Bacik   Btrfs: only log t...
251
  	set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
252
253
254
  	ret = btrfs_update_inode(trans, root, inode);
  	BUG_ON(ret);
  out:
3a45bb207   Jeff Mahoney   btrfs: remove roo...
255
  	btrfs_end_transaction(trans);
5103e947b   Josef Bacik   xattr support for...
256
257
258
259
260
  	return ret;
  }
  
  ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
  {
daac7ba61   Filipe Manana   Btrfs: fix listxa...
261
  	struct btrfs_key key;
2b0143b5c   David Howells   VFS: normal files...
262
  	struct inode *inode = d_inode(dentry);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
263
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
5103e947b   Josef Bacik   xattr support for...
264
265
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_path *path;
daac7ba61   Filipe Manana   Btrfs: fix listxa...
266
  	int ret = 0;
eaa47d861   Christoph Hellwig   btrfs: optmize li...
267
  	size_t total_size = 0, size_left = size;
5103e947b   Josef Bacik   xattr support for...
268
269
270
271
272
273
  
  	/*
  	 * ok we want all objects associated with this id.
  	 * NOTE: we set key.offset = 0; because we want to start with the
  	 * first xattr that we find and walk forward
  	 */
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
274
  	key.objectid = btrfs_ino(BTRFS_I(inode));
962a298f3   David Sterba   btrfs: kill the k...
275
  	key.type = BTRFS_XATTR_ITEM_KEY;
5103e947b   Josef Bacik   xattr support for...
276
277
278
  	key.offset = 0;
  
  	path = btrfs_alloc_path();
5103e947b   Josef Bacik   xattr support for...
279
280
  	if (!path)
  		return -ENOMEM;
e4058b54d   David Sterba   btrfs: cleanup, u...
281
  	path->reada = READA_FORWARD;
5103e947b   Josef Bacik   xattr support for...
282

5103e947b   Josef Bacik   xattr support for...
283
284
285
286
  	/* search for our xattrs */
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	if (ret < 0)
  		goto err;
2e6a00356   Li Zefan   Btrfs: Check if b...
287

5103e947b   Josef Bacik   xattr support for...
288
  	while (1) {
daac7ba61   Filipe Manana   Btrfs: fix listxa...
289
290
291
292
293
294
  		struct extent_buffer *leaf;
  		int slot;
  		struct btrfs_dir_item *di;
  		struct btrfs_key found_key;
  		u32 item_size;
  		u32 cur;
5103e947b   Josef Bacik   xattr support for...
295
  		leaf = path->nodes[0];
5103e947b   Josef Bacik   xattr support for...
296
297
298
  		slot = path->slots[0];
  
  		/* this is where we start walking through the path */
2e6a00356   Li Zefan   Btrfs: Check if b...
299
  		if (slot >= btrfs_header_nritems(leaf)) {
5103e947b   Josef Bacik   xattr support for...
300
301
302
303
  			/*
  			 * if we've reached the last slot in this leaf we need
  			 * to go to the next leaf and reset everything
  			 */
2e6a00356   Li Zefan   Btrfs: Check if b...
304
305
306
307
308
309
  			ret = btrfs_next_leaf(root, path);
  			if (ret < 0)
  				goto err;
  			else if (ret > 0)
  				break;
  			continue;
5103e947b   Josef Bacik   xattr support for...
310
  		}
5103e947b   Josef Bacik   xattr support for...
311

5103e947b   Josef Bacik   xattr support for...
312
313
314
315
316
  		btrfs_item_key_to_cpu(leaf, &found_key, slot);
  
  		/* check to make sure this item is what we want */
  		if (found_key.objectid != key.objectid)
  			break;
f1cd1f0b7   Filipe Manana   Btrfs: fix race w...
317
  		if (found_key.type > BTRFS_XATTR_ITEM_KEY)
5103e947b   Josef Bacik   xattr support for...
318
  			break;
f1cd1f0b7   Filipe Manana   Btrfs: fix race w...
319
  		if (found_key.type < BTRFS_XATTR_ITEM_KEY)
daac7ba61   Filipe Manana   Btrfs: fix listxa...
320
  			goto next_item;
5103e947b   Josef Bacik   xattr support for...
321
322
  
  		di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
daac7ba61   Filipe Manana   Btrfs: fix listxa...
323
324
325
326
327
328
329
  		item_size = btrfs_item_size_nr(leaf, slot);
  		cur = 0;
  		while (cur < item_size) {
  			u16 name_len = btrfs_dir_name_len(leaf, di);
  			u16 data_len = btrfs_dir_data_len(leaf, di);
  			u32 this_len = sizeof(*di) + name_len + data_len;
  			unsigned long name_ptr = (unsigned long)(di + 1);
e79a33270   Su Yue   btrfs: Check name...
330
  			if (verify_dir_item(fs_info, leaf, slot, di)) {
daac7ba61   Filipe Manana   Btrfs: fix listxa...
331
332
333
  				ret = -EIO;
  				goto err;
  			}
5103e947b   Josef Bacik   xattr support for...
334

daac7ba61   Filipe Manana   Btrfs: fix listxa...
335
336
337
338
339
340
341
  			total_size += name_len + 1;
  			/*
  			 * We are just looking for how big our buffer needs to
  			 * be.
  			 */
  			if (!size)
  				goto next;
5103e947b   Josef Bacik   xattr support for...
342

daac7ba61   Filipe Manana   Btrfs: fix listxa...
343
344
345
346
  			if (!buffer || (name_len + 1) > size_left) {
  				ret = -ERANGE;
  				goto err;
  			}
5103e947b   Josef Bacik   xattr support for...
347

daac7ba61   Filipe Manana   Btrfs: fix listxa...
348
349
  			read_extent_buffer(leaf, buffer, name_ptr, name_len);
  			buffer[name_len] = '\0';
eaa47d861   Christoph Hellwig   btrfs: optmize li...
350

daac7ba61   Filipe Manana   Btrfs: fix listxa...
351
352
  			size_left -= name_len + 1;
  			buffer += name_len + 1;
2e6a00356   Li Zefan   Btrfs: Check if b...
353
  next:
daac7ba61   Filipe Manana   Btrfs: fix listxa...
354
355
356
357
  			cur += this_len;
  			di = (struct btrfs_dir_item *)((char *)di + this_len);
  		}
  next_item:
2e6a00356   Li Zefan   Btrfs: Check if b...
358
  		path->slots[0]++;
5103e947b   Josef Bacik   xattr support for...
359
360
361
362
  	}
  	ret = total_size;
  
  err:
5103e947b   Josef Bacik   xattr support for...
363
364
365
366
  	btrfs_free_path(path);
  
  	return ret;
  }
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
367
  static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
b296821a7   Al Viro   xattr_handler: pa...
368
369
  				   struct dentry *unused, struct inode *inode,
  				   const char *name, void *buffer, size_t size)
95819c057   Christoph Hellwig   Btrfs: optimize b...
370
  {
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
371
372
  	name = xattr_full_name(handler, name);
  	return __btrfs_getxattr(inode, name, buffer, size);
69a32ac51   Chris Mason   Btrfs: Change mag...
373
  }
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
374
  static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
593012268   Al Viro   switch xattr_hand...
375
376
377
  				   struct dentry *unused, struct inode *inode,
  				   const char *name, const void *buffer,
  				   size_t size, int flags)
95819c057   Christoph Hellwig   Btrfs: optimize b...
378
  {
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
379
380
381
  	name = xattr_full_name(handler, name);
  	return __btrfs_setxattr(NULL, inode, name, buffer, size, flags);
  }
5103e947b   Josef Bacik   xattr support for...
382

9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
383
  static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
593012268   Al Viro   switch xattr_hand...
384
  					struct dentry *unused, struct inode *inode,
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
385
386
387
388
  					const char *name, const void *value,
  					size_t size, int flags)
  {
  	name = xattr_full_name(handler, name);
593012268   Al Viro   switch xattr_hand...
389
  	return btrfs_set_prop(inode, name, value, size, flags);
95819c057   Christoph Hellwig   Btrfs: optimize b...
390
  }
5103e947b   Josef Bacik   xattr support for...
391

9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  static const struct xattr_handler btrfs_security_xattr_handler = {
  	.prefix = XATTR_SECURITY_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set,
  };
  
  static const struct xattr_handler btrfs_trusted_xattr_handler = {
  	.prefix = XATTR_TRUSTED_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set,
  };
  
  static const struct xattr_handler btrfs_user_xattr_handler = {
  	.prefix = XATTR_USER_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set,
  };
  
  static const struct xattr_handler btrfs_btrfs_xattr_handler = {
  	.prefix = XATTR_BTRFS_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set_prop,
  };
  
  const struct xattr_handler *btrfs_xattr_handlers[] = {
  	&btrfs_security_xattr_handler,
  #ifdef CONFIG_BTRFS_FS_POSIX_ACL
  	&posix_acl_access_xattr_handler,
  	&posix_acl_default_xattr_handler,
  #endif
  	&btrfs_trusted_xattr_handler,
  	&btrfs_user_xattr_handler,
  	&btrfs_btrfs_xattr_handler,
  	NULL,
  };
48a3b6366   Eric Sandeen   btrfs: make stati...
427
428
  static int btrfs_initxattrs(struct inode *inode,
  			    const struct xattr *xattr_array, void *fs_info)
0279b4cd8   Jim Owens   Btrfs: selinux su...
429
  {
9d8f13ba3   Mimi Zohar   security: new sec...
430
431
  	const struct xattr *xattr;
  	struct btrfs_trans_handle *trans = fs_info;
0279b4cd8   Jim Owens   Btrfs: selinux su...
432
  	char *name;
9d8f13ba3   Mimi Zohar   security: new sec...
433
  	int err = 0;
0279b4cd8   Jim Owens   Btrfs: selinux su...
434

9d8f13ba3   Mimi Zohar   security: new sec...
435
436
  	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
  		name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
39a27ec10   David Sterba   btrfs: use GFP_KE...
437
  			       strlen(xattr->name) + 1, GFP_KERNEL);
9d8f13ba3   Mimi Zohar   security: new sec...
438
439
440
441
  		if (!name) {
  			err = -ENOMEM;
  			break;
  		}
0279b4cd8   Jim Owens   Btrfs: selinux su...
442
  		strcpy(name, XATTR_SECURITY_PREFIX);
9d8f13ba3   Mimi Zohar   security: new sec...
443
444
445
  		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
  		err = __btrfs_setxattr(trans, inode, name,
  				       xattr->value, xattr->value_len, 0);
0279b4cd8   Jim Owens   Btrfs: selinux su...
446
  		kfree(name);
9d8f13ba3   Mimi Zohar   security: new sec...
447
448
  		if (err < 0)
  			break;
0279b4cd8   Jim Owens   Btrfs: selinux su...
449
  	}
0279b4cd8   Jim Owens   Btrfs: selinux su...
450
451
  	return err;
  }
9d8f13ba3   Mimi Zohar   security: new sec...
452
453
454
455
456
457
458
459
  
  int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
  			      struct inode *inode, struct inode *dir,
  			      const struct qstr *qstr)
  {
  	return security_inode_init_security(inode, dir, qstr,
  					    &btrfs_initxattrs, trans);
  }