2 * Copyright (C) 2007 Red Hat. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include <linux/init.h>
21 #include <linux/slab.h>
22 #include <linux/rwsem.h>
23 #include <linux/xattr.h>
25 #include "btrfs_inode.h"
26 #include "transaction.h"
30 static struct xattr_handler
*btrfs_xattr_handler_map
[] = {
31 [BTRFS_XATTR_INDEX_USER
] = &btrfs_xattr_user_handler
,
32 #ifdef CONFIG_FS_POSIX_ACL
33 [BTRFS_XATTR_INDEX_POSIX_ACL_ACCESS
] = &btrfs_xattr_acl_access_handler
,
34 [BTRFS_XATTR_INDEX_POSIX_ACL_DEFAULT
] = &btrfs_xattr_acl_default_handler
,
36 [BTRFS_XATTR_INDEX_TRUSTED
] = &btrfs_xattr_trusted_handler
,
37 [BTRFS_XATTR_INDEX_SECURITY
] = &btrfs_xattr_security_handler
,
38 [BTRFS_XATTR_INDEX_SYSTEM
] = &btrfs_xattr_system_handler
,
41 struct xattr_handler
*btrfs_xattr_handlers
[] = {
42 &btrfs_xattr_user_handler
,
43 #ifdef CONFIG_FS_POSIX_ACL
44 &btrfs_xattr_acl_access_handler
,
45 &btrfs_xattr_acl_default_handler
,
47 &btrfs_xattr_trusted_handler
,
48 &btrfs_xattr_security_handler
,
49 &btrfs_xattr_system_handler
,
54 * @param name_index - the index for the xattr handler
55 * @return the xattr_handler if we found it, NULL otherwise
57 * use this if we know the type of the xattr already
59 static struct xattr_handler
*btrfs_xattr_handler(int name_index
)
61 struct xattr_handler
*handler
= NULL
;
63 if (name_index
>= 0 &&
64 name_index
< ARRAY_SIZE(btrfs_xattr_handler_map
))
65 handler
= btrfs_xattr_handler_map
[name_index
];
70 static inline char *get_name(const char *name
, int name_index
)
73 struct xattr_handler
*handler
= btrfs_xattr_handler(name_index
);
79 prefix_len
= strlen(handler
->prefix
);
81 ret
= kmalloc(strlen(name
) + prefix_len
+ 1, GFP_KERNEL
);
85 memcpy(ret
, handler
->prefix
, prefix_len
);
86 memcpy(ret
+prefix_len
, name
, strlen(name
));
87 ret
[prefix_len
+ strlen(name
)] = '\0';
92 ssize_t
btrfs_xattr_get(struct inode
*inode
, int name_index
,
93 const char *attr_name
, void *buffer
, size_t size
)
95 struct btrfs_dir_item
*di
;
96 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
97 struct btrfs_path
*path
;
98 struct extent_buffer
*leaf
;
99 struct xattr_handler
*handler
= btrfs_xattr_handler(name_index
);
101 unsigned long data_ptr
;
106 name
= get_name(attr_name
, name_index
);
110 path
= btrfs_alloc_path();
116 /* lookup the xattr by name */
117 di
= btrfs_lookup_xattr(NULL
, root
, path
, inode
->i_ino
, name
,
119 if (!di
|| IS_ERR(di
)) {
124 leaf
= path
->nodes
[0];
125 /* if size is 0, that means we want the size of the attr */
127 ret
= btrfs_dir_data_len(leaf
, di
);
131 /* now get the data out of our dir_item */
132 if (btrfs_dir_data_len(leaf
, di
) > size
) {
136 data_ptr
= (unsigned long)((char *)(di
+ 1) +
137 btrfs_dir_name_len(leaf
, di
));
138 read_extent_buffer(leaf
, buffer
, data_ptr
,
139 btrfs_dir_data_len(leaf
, di
));
140 ret
= btrfs_dir_data_len(leaf
, di
);
144 btrfs_free_path(path
);
148 int btrfs_xattr_set(struct inode
*inode
, int name_index
,
149 const char *attr_name
, const void *value
, size_t size
,
152 struct btrfs_dir_item
*di
;
153 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
154 struct btrfs_trans_handle
*trans
;
155 struct btrfs_path
*path
;
156 struct xattr_handler
*handler
= btrfs_xattr_handler(name_index
);
158 int ret
= 0, mod
= 0;
161 name
= get_name(attr_name
, name_index
);
165 path
= btrfs_alloc_path();
171 trans
= btrfs_start_transaction(root
, 1);
172 btrfs_set_trans_block_group(trans
, inode
);
174 /* first lets see if we already have this xattr */
175 di
= btrfs_lookup_xattr(trans
, root
, path
, inode
->i_ino
, name
,
182 /* ok we already have this xattr, lets remove it */
184 /* if we want create only exit */
185 if (flags
& XATTR_CREATE
) {
190 ret
= btrfs_delete_one_dir_name(trans
, root
, path
, di
);
193 btrfs_release_path(root
, path
);
195 /* if we don't have a value then we are removing the xattr */
201 btrfs_release_path(root
, path
);
203 if (flags
& XATTR_REPLACE
) {
204 /* we couldn't find the attr to replace */
210 /* ok we have to create a completely new xattr */
211 ret
= btrfs_insert_xattr_item(trans
, root
, name
, strlen(name
),
212 value
, size
, inode
->i_ino
);
219 inode
->i_ctime
= CURRENT_TIME
;
220 ret
= btrfs_update_inode(trans
, root
, inode
);
223 btrfs_end_transaction(trans
, root
);
225 btrfs_free_path(path
);
230 ssize_t
btrfs_listxattr(struct dentry
*dentry
, char *buffer
, size_t size
)
232 struct btrfs_key key
, found_key
;
233 struct inode
*inode
= dentry
->d_inode
;
234 struct btrfs_root
*root
= BTRFS_I(inode
)->root
;
235 struct btrfs_path
*path
;
236 struct btrfs_item
*item
;
237 struct extent_buffer
*leaf
;
238 struct btrfs_dir_item
*di
;
239 int ret
= 0, slot
, advance
;
240 size_t total_size
= 0, size_left
= size
;
241 unsigned long name_ptr
;
246 * ok we want all objects associated with this id.
247 * NOTE: we set key.offset = 0; because we want to start with the
248 * first xattr that we find and walk forward
250 key
.objectid
= inode
->i_ino
;
251 btrfs_set_key_type(&key
, BTRFS_XATTR_ITEM_KEY
);
254 path
= btrfs_alloc_path();
259 /* search for our xattrs */
260 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
266 leaf
= path
->nodes
[0];
267 nritems
= btrfs_header_nritems(leaf
);
268 slot
= path
->slots
[0];
270 /* this is where we start walking through the path */
271 if (advance
|| slot
>= nritems
) {
273 * if we've reached the last slot in this leaf we need
274 * to go to the next leaf and reset everything
276 if (slot
>= nritems
-1) {
277 ret
= btrfs_next_leaf(root
, path
);
280 leaf
= path
->nodes
[0];
281 nritems
= btrfs_header_nritems(leaf
);
282 slot
= path
->slots
[0];
285 * just walking through the slots on this leaf
293 item
= btrfs_item_nr(leaf
, slot
);
294 btrfs_item_key_to_cpu(leaf
, &found_key
, slot
);
296 /* check to make sure this item is what we want */
297 if (found_key
.objectid
!= key
.objectid
)
299 if (btrfs_key_type(&found_key
) != BTRFS_XATTR_ITEM_KEY
)
302 di
= btrfs_item_ptr(leaf
, slot
, struct btrfs_dir_item
);
304 name_len
= btrfs_dir_name_len(leaf
, di
);
305 total_size
+= name_len
+ 1;
307 /* we are just looking for how big our buffer needs to be */
311 if (!buffer
|| (name_len
+ 1) > size_left
) {
316 name_ptr
= (unsigned long)(di
+ 1);
317 read_extent_buffer(leaf
, buffer
, name_ptr
, name_len
);
318 buffer
[name_len
] = '\0';
320 size_left
-= name_len
+ 1;
321 buffer
+= name_len
+ 1;
326 btrfs_free_path(path
);
334 #define BTRFS_XATTR_SETGET_FUNCS(name, index) \
335 static int btrfs_xattr_##name##_get(struct inode *inode, \
336 const char *name, void *value, \
341 return btrfs_xattr_get(inode, index, name, value, size); \
343 static int btrfs_xattr_##name##_set(struct inode *inode, \
344 const char *name, const void *value,\
345 size_t size, int flags) \
349 return btrfs_xattr_set(inode, index, name, value, size, flags); \
352 BTRFS_XATTR_SETGET_FUNCS(security
, BTRFS_XATTR_INDEX_SECURITY
);
353 BTRFS_XATTR_SETGET_FUNCS(system
, BTRFS_XATTR_INDEX_SYSTEM
);
354 BTRFS_XATTR_SETGET_FUNCS(user
, BTRFS_XATTR_INDEX_USER
);
355 BTRFS_XATTR_SETGET_FUNCS(trusted
, BTRFS_XATTR_INDEX_TRUSTED
);
357 struct xattr_handler btrfs_xattr_security_handler
= {
358 .prefix
= XATTR_SECURITY_PREFIX
,
359 .get
= btrfs_xattr_security_get
,
360 .set
= btrfs_xattr_security_set
,
363 struct xattr_handler btrfs_xattr_system_handler
= {
364 .prefix
= XATTR_SYSTEM_PREFIX
,
365 .get
= btrfs_xattr_system_get
,
366 .set
= btrfs_xattr_system_set
,
369 struct xattr_handler btrfs_xattr_user_handler
= {
370 .prefix
= XATTR_USER_PREFIX
,
371 .get
= btrfs_xattr_user_get
,
372 .set
= btrfs_xattr_user_set
,
375 struct xattr_handler btrfs_xattr_trusted_handler
= {
376 .prefix
= XATTR_TRUSTED_PREFIX
,
377 .get
= btrfs_xattr_trusted_get
,
378 .set
= btrfs_xattr_trusted_set
,