4 Extended attribute handling.
6 Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
7 Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
10 #include <linux/slab.h>
11 #include <linux/vmalloc.h>
12 #include <linux/smp_lock.h>
13 #include <linux/file.h>
14 #include <linux/xattr.h>
15 #include <asm/uaccess.h>
18 * Extended attribute memory allocation wrappers, originally
19 * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
20 * The vmalloc use here is very uncommon - extended attributes
21 * are supposed to be small chunks of metadata, and it is quite
22 * unusual to have very many extended attributes, so lists tend
23 * to be quite short as well. The 64K upper limit is derived
24 * from the extended attribute size limit used by XFS.
25 * Intentionally allow zero @size for value/list size requests.
28 xattr_alloc(size_t size
, size_t limit
)
33 return ERR_PTR(-E2BIG
);
35 if (!size
) /* size request, no buffer is needed */
37 else if (size
<= PAGE_SIZE
)
38 ptr
= kmalloc((unsigned long) size
, GFP_KERNEL
);
40 ptr
= vmalloc((unsigned long) size
);
42 return ERR_PTR(-ENOMEM
);
47 xattr_free(void *ptr
, size_t size
)
49 if (!size
) /* size request, no buffer was needed */
51 else if (size
<= PAGE_SIZE
)
58 * Extended attribute SET operations
61 setxattr(struct dentry
*d
, char *name
, void *value
, size_t size
, int flags
)
65 char kname
[XATTR_NAME_MAX
+ 1];
67 if (flags
& ~(XATTR_CREATE
|XATTR_REPLACE
))
70 error
= strncpy_from_user(kname
, name
, sizeof(kname
));
71 if (error
== 0 || error
== sizeof(kname
))
76 kvalue
= xattr_alloc(size
, XATTR_SIZE_MAX
);
78 return PTR_ERR(kvalue
);
80 if (size
> 0 && copy_from_user(kvalue
, value
, size
)) {
81 xattr_free(kvalue
, size
);
86 if (d
->d_inode
->i_op
&& d
->d_inode
->i_op
->setxattr
) {
87 down(&d
->d_inode
->i_sem
);
88 error
= d
->d_inode
->i_op
->setxattr(d
, kname
, kvalue
, size
, flags
);
89 up(&d
->d_inode
->i_sem
);
92 xattr_free(kvalue
, size
);
97 sys_setxattr(char *path
, char *name
, void *value
, size_t size
, int flags
)
102 error
= user_path_walk(path
, &nd
);
105 error
= setxattr(nd
.dentry
, name
, value
, size
, flags
);
111 sys_lsetxattr(char *path
, char *name
, void *value
, size_t size
, int flags
)
116 error
= user_path_walk_link(path
, &nd
);
119 error
= setxattr(nd
.dentry
, name
, value
, size
, flags
);
125 sys_fsetxattr(int fd
, char *name
, void *value
, size_t size
, int flags
)
133 error
= setxattr(f
->f_dentry
, name
, value
, size
, flags
);
139 * Extended attribute GET operations
142 getxattr(struct dentry
*d
, char *name
, void *value
, size_t size
)
146 char kname
[XATTR_NAME_MAX
+ 1];
148 error
= strncpy_from_user(kname
, name
, sizeof(kname
));
149 if (error
== 0 || error
== sizeof(kname
))
154 kvalue
= xattr_alloc(size
, XATTR_SIZE_MAX
);
156 return PTR_ERR(kvalue
);
159 if (d
->d_inode
->i_op
&& d
->d_inode
->i_op
->getxattr
) {
160 down(&d
->d_inode
->i_sem
);
161 error
= d
->d_inode
->i_op
->getxattr(d
, kname
, kvalue
, size
);
162 up(&d
->d_inode
->i_sem
);
165 if (kvalue
&& error
> 0)
166 if (copy_to_user(value
, kvalue
, error
))
168 xattr_free(kvalue
, size
);
173 sys_getxattr(char *path
, char *name
, void *value
, size_t size
)
178 error
= user_path_walk(path
, &nd
);
181 error
= getxattr(nd
.dentry
, name
, value
, size
);
187 sys_lgetxattr(char *path
, char *name
, void *value
, size_t size
)
192 error
= user_path_walk_link(path
, &nd
);
195 error
= getxattr(nd
.dentry
, name
, value
, size
);
201 sys_fgetxattr(int fd
, char *name
, void *value
, size_t size
)
204 ssize_t error
= -EBADF
;
209 error
= getxattr(f
->f_dentry
, name
, value
, size
);
215 * Extended attribute LIST operations
218 listxattr(struct dentry
*d
, char *list
, size_t size
)
223 klist
= (char *)xattr_alloc(size
, XATTR_LIST_MAX
);
225 return PTR_ERR(klist
);
228 if (d
->d_inode
->i_op
&& d
->d_inode
->i_op
->listxattr
) {
229 down(&d
->d_inode
->i_sem
);
230 error
= d
->d_inode
->i_op
->listxattr(d
, klist
, size
);
231 up(&d
->d_inode
->i_sem
);
234 if (klist
&& error
> 0)
235 if (copy_to_user(list
, klist
, error
))
237 xattr_free(klist
, size
);
242 sys_listxattr(char *path
, char *list
, size_t size
)
247 error
= user_path_walk(path
, &nd
);
250 error
= listxattr(nd
.dentry
, list
, size
);
256 sys_llistxattr(char *path
, char *list
, size_t size
)
261 error
= user_path_walk_link(path
, &nd
);
264 error
= listxattr(nd
.dentry
, list
, size
);
270 sys_flistxattr(int fd
, char *list
, size_t size
)
273 ssize_t error
= -EBADF
;
278 error
= listxattr(f
->f_dentry
, list
, size
);
284 * Extended attribute REMOVE operations
287 removexattr(struct dentry
*d
, char *name
)
290 char kname
[XATTR_NAME_MAX
+ 1];
292 error
= strncpy_from_user(kname
, name
, sizeof(kname
));
293 if (error
== 0 || error
== sizeof(kname
))
299 if (d
->d_inode
->i_op
&& d
->d_inode
->i_op
->removexattr
) {
300 down(&d
->d_inode
->i_sem
);
301 error
= d
->d_inode
->i_op
->removexattr(d
, kname
);
302 up(&d
->d_inode
->i_sem
);
308 sys_removexattr(char *path
, char *name
)
313 error
= user_path_walk(path
, &nd
);
316 error
= removexattr(nd
.dentry
, name
);
322 sys_lremovexattr(char *path
, char *name
)
327 error
= user_path_walk_link(path
, &nd
);
330 error
= removexattr(nd
.dentry
, name
);
336 sys_fremovexattr(int fd
, char *name
)
344 error
= removexattr(f
->f_dentry
, name
);