1 diff -rupN --exclude='ide*' linux-2.4.20.orig/fs/Config.in linux-2.4.20/fs/Config.in
2 --- linux-2.4.20.orig/fs/Config.in 2002-11-29 01:53:15.000000000 +0200
3 +++ linux-2.4.20/fs/Config.in 2004-02-08 21:37:47.000000000 +0200
4 @@ -48,6 +48,9 @@ if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFI
6 tristate 'Compressed ROM file system support' CONFIG_CRAMFS
7 bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
8 +if [ "$CONFIG_TMPFS" = "y" ]; then
9 + bool ' tmpfs Extended Attributes' CONFIG_TMPFS_XATTR
11 define_bool CONFIG_RAMFS y
13 tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS
14 diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/mm.h linux-2.4.20/include/linux/mm.h
15 --- linux-2.4.20.orig/include/linux/mm.h 2002-08-03 03:39:45.000000000 +0300
16 +++ linux-2.4.20/include/linux/mm.h 2004-02-10 11:43:10.000000000 +0200
17 @@ -468,6 +468,7 @@ extern void clear_page_tables(struct mm_
18 extern int fail_writepage(struct page *);
19 struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused);
20 struct file *shmem_file_setup(char * name, loff_t size);
21 +int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr);
22 extern void shmem_lock(struct file * file, int lock);
23 extern int shmem_zero_setup(struct vm_area_struct *);
25 diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/shmem_fs.h linux-2.4.20/include/linux/shmem_fs.h
26 --- linux-2.4.20.orig/include/linux/shmem_fs.h 2001-12-21 19:42:03.000000000 +0200
27 +++ linux-2.4.20/include/linux/shmem_fs.h 2004-02-10 18:39:17.000000000 +0200
30 /* inode in-kernel data */
32 +#include <linux/config.h>
34 #define SHMEM_NR_DIRECT 16
37 @@ -28,6 +30,10 @@ struct shmem_inode_info {
38 unsigned long swapped;
39 int locked; /* into memory */
40 struct list_head list;
41 +#ifdef CONFIG_TMPFS_XATTR
42 + struct list_head xattrs;
43 + struct list_head *xtail;
48 @@ -39,6 +45,32 @@ struct shmem_sb_info {
52 +#ifdef CONFIG_TMPFS_XATTR
57 + struct list_head list;
60 +extern struct shmem_xattr *
61 +shmem_xattr_find(struct inode *inode, const char *name);
64 +shmem_xattr_set(struct inode *inode, const char *name,
65 + const void *value, u16 valuelen, int flags);
68 +shmem_xattr_get(struct inode *inode, const char *name,
69 + void *value, size_t valuelen);
72 +shmem_xattr_delete(struct inode *inode, struct shmem_xattr *xattr);
75 +shmem_xattr_remove(struct inode *inode, const char *name);
78 #define SHMEM_I(inode) (&inode->u.shmem_i)
81 diff -rupN --exclude='ide*' linux-2.4.20.orig/mm/shmem.c linux-2.4.20/mm/shmem.c
82 --- linux-2.4.20.orig/mm/shmem.c 2002-11-29 01:53:15.000000000 +0200
83 +++ linux-2.4.20/mm/shmem.c 2004-02-10 18:44:05.000000000 +0200
85 #include <linux/string.h>
86 #include <linux/locks.h>
87 #include <linux/smp_lock.h>
88 +#include <linux/slab.h>
89 +#include <linux/xattr.h>
91 #include <asm/uaccess.h>
93 @@ -58,6 +60,344 @@ atomic_t shmem_nrpages = ATOMIC_INIT(0);
95 static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long);
98 +static struct inode_operations shmem_symlink_inode_operations;
99 +static struct inode_operations shmem_symlink_inline_operations;
102 +#ifdef CONFIG_TMPFS_XATTR
103 +#define xattr_name(xattr) \
104 + ((char *)xattr->entity)
106 +#define xattr_value(xattr) \
107 + ((void *)xattr->entity + xattr->namelen + 1)
109 +/* allocates memory for new xattr with name length of @namelen and value size of
111 +static struct shmem_xattr *
112 +shmem_xattr_alloc(u8 namelen, u16 valuelen)
115 + struct shmem_xattr *xattr;
117 + size = namelen + 1 + valuelen;
119 + if (!(xattr = kmalloc(sizeof(*xattr), GFP_KERNEL)))
122 + if (!(xattr->entity = kmalloc(size, GFP_KERNEL))) {
127 + xattr->namelen = namelen;
128 + xattr->valuelen = valuelen;
132 +/* reallocs passed @xattr with new @value. */
134 +shmem_xattr_realloc(struct shmem_xattr *xattr, u16 valuelen)
136 + if (xattr->valuelen != valuelen) {
140 + /* allocating new entity. */
141 + new_size = xattr->namelen + 1 + valuelen;
143 + if (!(entity = kmalloc(new_size, GFP_KERNEL)))
146 + /* copying old name to new entity.*/
147 + memcpy(entity, xattr->entity, xattr->namelen);
148 + *((char *)(entity + xattr->namelen)) = '\0';
150 + /* finishing the change.*/
151 + kfree(xattr->entity);
152 + xattr->entity = entity;
153 + xattr->valuelen = valuelen;
159 +/* assigns @name and @value to passed @xattr. */
161 +shmem_xattr_assign(struct shmem_xattr *xattr,
162 + const char *name, const void *value)
165 + if (xattr->namelen != strlen(name))
168 + memcpy(xattr->entity, name, xattr->namelen);
169 + *((char *)(xattr->entity + xattr->namelen)) = '\0';
173 + memcpy(xattr_value(xattr),
174 + value, xattr->valuelen);
180 +/* frees passed @xattr. */
182 +shmem_xattr_free(struct shmem_xattr *xattr)
184 + kfree(xattr->entity);
188 +/* lookups passed @name inside @inode's xattr list. */
189 +struct shmem_xattr *
190 +shmem_xattr_find(struct inode *inode, const char *name)
193 + struct list_head *p;
194 + struct shmem_xattr *xattr;
195 + struct shmem_inode_info *info;
197 + info = SHMEM_I(inode);
198 + namelen = strlen(name);
200 + list_for_each(p, &info->xattrs) {
201 + xattr = list_entry(p, struct shmem_xattr, list);
203 + if (xattr->namelen == namelen &&
204 + !memcmp(xattr->entity, name, namelen))
213 +/* allocates new xattr and fills it with passed value, name, etc. */
215 +shmem_xattr_set(struct inode *inode, const char *name,
216 + const void *value, u16 valuelen, int flags)
219 + struct shmem_xattr *xattr;
220 + struct shmem_inode_info *info;
222 + xattr = shmem_xattr_find(inode, name);
225 + if (flags & XATTR_CREATE)
228 + if ((error = shmem_xattr_realloc(xattr, valuelen)))
231 + if ((error = shmem_xattr_assign(xattr, NULL, value)))
234 + info = SHMEM_I(inode);
236 + if (flags & XATTR_REPLACE)
239 + if (!(xattr = shmem_xattr_alloc(strlen(name), valuelen)))
242 + if ((error = shmem_xattr_assign(xattr, name, value)))
245 + list_add(&xattr->list, info->xtail);
246 + info->xtail = &xattr->list;
252 +/* fills passed @value by attribute value found by @name. */
254 +shmem_xattr_get(struct inode *inode, const char *name,
255 + void *value, size_t valuelen)
257 + struct shmem_xattr *xattr;
259 + if (!(xattr = shmem_xattr_find(inode, name)))
262 + /* handling value size guess request */
263 + if (valuelen == 0 || value == NULL)
264 + return xattr->valuelen;
266 + if (xattr->valuelen > valuelen)
269 + memcpy(value, xattr_value(xattr),
272 + return xattr->valuelen;
275 +/* deletes passed @xattr from inode xattr list and frees it. */
277 +shmem_xattr_delete(struct inode *inode, struct shmem_xattr *xattr)
279 + struct shmem_inode_info *info;
281 + info = SHMEM_I(inode);
283 + if (&xattr->list == info->xtail)
284 + info->xtail = xattr->list.prev;
286 + list_del(&xattr->list);
287 + shmem_xattr_free(xattr);
292 +/* removes attribute found by passed @name. */
294 +shmem_xattr_remove(struct inode *inode, const char *name)
296 + struct shmem_xattr *xattr;
298 + if (!(xattr = shmem_xattr_find(inode, name)))
301 + return shmem_xattr_delete(inode, xattr);
305 +shmem_xattr_can_read(struct inode *inode, const char *name)
307 + /* check for inlined symlinks. They store path inside inode info and
308 + * thus, cannot be used for access xattrs. */
309 + if (S_ISLNK(inode->i_mode) &&
310 + inode->i_op == &shmem_symlink_inline_operations)
315 + return permission(inode, MAY_READ);
319 +shmem_xattr_can_write(struct inode *inode, const char *name)
321 + if (IS_RDONLY(inode))
324 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode) ||
325 + S_ISLNK(inode->i_mode))
330 + if ((!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) ||
331 + inode->i_mode & S_ISVTX)
336 + return permission(inode, MAY_WRITE);
339 +/* fills passed @value with data of attribute @name from @dentry->d_inode
340 + * attribute list. */
342 +shmem_getxattr(struct dentry *dentry, const char *name,
343 + void *value, size_t valuelen)
346 + struct inode *inode = dentry->d_inode;
351 + if ((error = shmem_xattr_can_read(inode, name)))
354 + return shmem_xattr_get(inode, name,
359 +/* updates attribute with @name inside @dentry->d_inode attributes list (if
360 + * any), or creates new attribute with name @name and value @value and put it to
361 + * inode attributes list.*/
363 +shmem_setxattr(struct dentry *dentry, const char *name,
364 + void *value, size_t valuelen, int flags)
367 + struct inode *inode = dentry->d_inode;
372 + if ((error = shmem_xattr_can_write(inode, name)))
375 + if (value == NULL) {
380 + return shmem_xattr_set(inode, name, value,
384 +/* removes attribute with passed @name from @dentry->d_inode attributes list. */
386 +shmem_removexattr(struct dentry *dentry, const char *name)
389 + struct inode *inode = dentry->d_inode;
394 + if ((error = shmem_xattr_can_write(inode, name)))
397 + return shmem_xattr_remove(inode, name);
400 +/* fills passed @data with list of @dentry->d_inode attributes. Returns size of
401 + * actuall data put to @data. */
403 +shmem_listxattr(struct dentry *dentry, char *data, size_t buf_size)
406 + struct list_head *p;
407 + struct shmem_xattr *xattr;
408 + struct shmem_inode_info *info;
409 + struct inode *inode = dentry->d_inode;
411 + info = SHMEM_I(inode);
413 + list_for_each(p, &info->xattrs) {
414 + xattr = list_entry(p, struct shmem_xattr, list);
415 + size += xattr->namelen + 1;
418 + /* handling data size guess request. */
419 + if (buf_size == 0 || data == NULL)
422 + if (size > buf_size)
425 + list_for_each(p, &info->xattrs) {
426 + xattr = list_entry(p, struct shmem_xattr, list);
427 + memcpy(data, xattr->entity, xattr->namelen + 1);
428 + data += xattr->namelen + 1;
436 * shmem_recalc_inode - recalculate the size of an inode
438 @@ -359,6 +699,11 @@ static void shmem_truncate (struct inode
440 static void shmem_delete_inode(struct inode * inode)
442 +#ifdef CONFIG_TMPFS_XATTR
443 + struct list_head *tmp, *p;
444 + struct shmem_xattr *xattr;
445 + struct shmem_inode_info * info = SHMEM_I(inode);
447 struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
449 if (inode->i_op->truncate == shmem_truncate) {
450 @@ -371,6 +716,12 @@ static void shmem_delete_inode(struct in
451 spin_lock (&sbinfo->stat_lock);
452 sbinfo->free_inodes++;
453 spin_unlock (&sbinfo->stat_lock);
454 +#ifdef CONFIG_TMPFS_XATTR
455 + list_for_each_safe(p, tmp, &info->xattrs) {
456 + xattr = list_entry(p, struct shmem_xattr, list);
457 + shmem_xattr_delete(inode, xattr);
463 @@ -634,7 +985,7 @@ wait_retry:
467 -static int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr)
468 +int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr)
470 struct shmem_inode_info *info = SHMEM_I(inode);
472 @@ -727,6 +1078,11 @@ struct inode *shmem_get_inode(struct sup
474 spin_lock_init (&info->lock);
475 sema_init (&info->sem, 1);
477 +#ifdef CONFIG_TMPFS_XATTR
478 + INIT_LIST_HEAD(&info->xattrs);
479 + info->xtail = &info->xattrs;
481 switch (mode & S_IFMT) {
483 init_special_inode(inode, mode, dev);
484 @@ -777,10 +1133,6 @@ out:
489 -static struct inode_operations shmem_symlink_inode_operations;
490 -static struct inode_operations shmem_symlink_inline_operations;
493 shmem_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
495 @@ -1250,6 +1602,12 @@ static struct inode_operations shmem_sym
496 truncate: shmem_truncate,
497 readlink: shmem_readlink,
498 follow_link: shmem_follow_link,
499 +#ifdef CONFIG_TMPFS_XATTR
500 + setxattr: shmem_setxattr,
501 + getxattr: shmem_getxattr,
502 + listxattr: shmem_listxattr,
503 + removexattr: shmem_removexattr,
507 static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long * blocks, unsigned long *inodes)
508 @@ -1398,6 +1756,12 @@ static struct file_operations shmem_file
510 static struct inode_operations shmem_inode_operations = {
511 truncate: shmem_truncate,
512 +#ifdef CONFIG_TMPFS_XATTR
513 + setxattr: shmem_setxattr,
514 + getxattr: shmem_getxattr,
515 + listxattr: shmem_listxattr,
516 + removexattr: shmem_removexattr,
520 static struct inode_operations shmem_dir_inode_operations = {
521 @@ -1411,6 +1775,12 @@ static struct inode_operations shmem_dir
524 rename: shmem_rename,
525 +#ifdef CONFIG_TMPFS_XATTR
526 + setxattr: shmem_setxattr,
527 + getxattr: shmem_getxattr,
528 + listxattr: shmem_listxattr,
529 + removexattr: shmem_removexattr,
534 @@ -1557,3 +1927,9 @@ int shmem_zero_setup(struct vm_area_stru
537 EXPORT_SYMBOL(shmem_file_setup);
538 +EXPORT_SYMBOL(shmem_getpage);
539 +EXPORT_SYMBOL(shmem_xattr_find);
540 +EXPORT_SYMBOL(shmem_xattr_set);
541 +EXPORT_SYMBOL(shmem_xattr_get);
542 +EXPORT_SYMBOL(shmem_xattr_delete);
543 +EXPORT_SYMBOL(shmem_xattr_remove);