Whamcloud - gitweb
adding 2.6-sles10 target and kernel config files for the sles10 kernel
[fs/lustre-release.git] / lustre / kernel_patches / patches / linux-2.4.21-xattr-0.8.54-chaos.patch
1  Documentation/Configure.help  |   66 ++
2  arch/alpha/defconfig          |    7 
3  arch/alpha/kernel/entry.S     |   12 
4  arch/arm/defconfig            |    7 
5  arch/arm/kernel/calls.S       |   24 
6  arch/i386/defconfig           |    7 
7  arch/ia64/defconfig           |    7 
8  arch/ia64/kernel/entry.S      |   24 
9  arch/m68k/defconfig           |    7 
10  arch/mips/defconfig           |    7 
11  arch/mips64/defconfig         |    7 
12  arch/ppc/defconfig            |   14 
13  arch/ppc64/kernel/misc.S      |    2 
14  arch/s390/defconfig           |    7 
15  arch/s390/kernel/entry.S      |   24 
16  arch/s390x/defconfig          |    7 
17  arch/s390x/kernel/entry.S     |   24 
18  arch/s390x/kernel/wrapper32.S |   92 +++
19  arch/sparc/defconfig          |    7 
20  arch/sparc/kernel/systbls.S   |   10 
21  arch/sparc64/defconfig        |    7 
22  arch/sparc64/kernel/systbls.S |   20 
23  fs/Config.in                  |   14 
24  fs/Makefile                   |    3 
25  fs/ext2/Makefile              |    4 
26  fs/ext2/file.c                |    5 
27  fs/ext2/ialloc.c              |    2 
28  fs/ext2/inode.c               |   34 -
29  fs/ext2/namei.c               |   14 
30  fs/ext2/super.c               |   29 
31  fs/ext2/symlink.c             |   14 
32  fs/ext2/xattr.c               | 1212 +++++++++++++++++++++++++++++++++++++++++
33  fs/ext2/xattr_user.c          |  103 +++
34  fs/ext3/Makefile              |   10 
35  fs/ext3/file.c                |    5 
36  fs/ext3/ialloc.c              |    2 
37  fs/ext3/inode.c               |   35 -
38  fs/ext3/namei.c               |   21 
39  fs/ext3/super.c               |   36 +
40  fs/ext3/symlink.c             |   14 
41  fs/ext3/xattr.c               | 1225 ++++++++++++++++++++++++++++++++++++++++++
42  fs/ext3/xattr_user.c          |  111 +++
43  fs/jfs/jfs_xattr.h            |    6 
44  fs/jfs/xattr.c                |    6 
45  fs/mbcache.c                  |  648 ++++++++++++++++++++++
46  include/asm-arm/unistd.h      |    2 
47  include/asm-ia64/unistd.h     |   13 
48  include/asm-ppc64/unistd.h    |    2 
49  include/asm-s390/unistd.h     |   15 
50  include/asm-s390x/unistd.h    |   15 
51  include/asm-sparc/unistd.h    |   24 
52  include/asm-sparc64/unistd.h  |   24 
53  include/linux/cache_def.h     |   15 
54  include/linux/errno.h         |    4 
55  include/linux/ext2_fs.h       |   31 -
56  include/linux/ext2_xattr.h    |  157 +++++
57  include/linux/ext3_fs.h       |   31 -
58  include/linux/ext3_jbd.h      |    8 
59  include/linux/ext3_xattr.h    |  157 +++++
60  include/linux/fs.h            |    2 
61  include/linux/mbcache.h       |   69 ++
62  kernel/ksyms.c                |    4 
63  mm/vmscan.c                   |   35 +
64  fs/ext3/ext3-exports.c        |   14 +  
65  64 files changed, 4355 insertions(+), 195 deletions(-)
66
67 Index: linux-2.4.21-chaos/Documentation/Configure.help
68 ===================================================================
69 --- linux-2.4.21-chaos.orig/Documentation/Configure.help        2003-10-04 01:18:57.000000000 +0400
70 +++ linux-2.4.21-chaos/Documentation/Configure.help     2003-12-14 15:11:46.000000000 +0300
71 @@ -15939,6 +15939,39 @@
72    be compiled as a module, and so this could be dangerous.  Most
73    everyone wants to say Y here.
74  
75 +Ext2 extended attributes
76 +CONFIG_EXT2_FS_XATTR
77 +  Extended attributes are name:value pairs associated with inodes by
78 +  the kernel or by users (see the attr(5) manual page, or visit
79 +  <http://acl.bestbits.at/> for details).
80 +
81 +  If unsure, say N.
82 +
83 +Ext2 extended attribute block sharing
84 +CONFIG_EXT2_FS_XATTR_SHARING
85 +  This options enables code for sharing identical extended attribute
86 +  blocks among multiple inodes.
87 +
88 +  Usually, say Y.
89 +
90 +Ext2 extended user attributes
91 +CONFIG_EXT2_FS_XATTR_USER
92 +  This option enables extended user attributes on ext2. Processes can
93 +  associate extended user attributes with inodes to store additional
94 +  information such as the character encoding of files, etc. (see the
95 +  attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
96 +
97 +  If unsure, say N.
98 +
99 +Ext2 trusted extended attributes
100 +CONFIG_EXT2_FS_XATTR_TRUSTED
101 +  This option enables extended attributes on ext2 that are accessible
102 +  (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
103 +  is only the super user. Trusted extended attributes are meant for
104 +  implementing system/security services.
105 +
106 +  If unsure, say N.
107 +
108  Ext3 journalling file system support (EXPERIMENTAL)
109  CONFIG_EXT3_FS
110    This is the journalling version of the Second extended file system
111 @@ -16008,6 +16041,39 @@
112  
113    If unsure, say N.
114  
115 +Ext3 extended attributes
116 +CONFIG_EXT3_FS_XATTR
117 +  Extended attributes are name:value pairs associated with inodes by
118 +  the kernel or by users (see the attr(5) manual page, or visit
119 +  <http://acl.bestbits.at/> for details).
120 +
121 +  If unsure, say N.
122 +
123 +Ext3 extended attribute block sharing
124 +CONFIG_EXT3_FS_XATTR_SHARING
125 +  This options enables code for sharing identical extended attribute
126 +  blocks among multiple inodes.
127 +
128 +  Usually, say Y.
129 +
130 +Ext3 extended user attributes
131 +CONFIG_EXT3_FS_XATTR_USER
132 +  This option enables extended user attributes on ext3. Processes can
133 +  associate extended user attributes with inodes to store additional
134 +  information such as the character encoding of files, etc. (see the
135 +  attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
136 +
137 +  If unsure, say N.
138 +
139 +Ext3 trusted extended attributes
140 +CONFIG_EXT3_FS_XATTR_TRUSTED
141 +  This option enables extended attributes on ext3 that are accessible
142 +  (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
143 +  is only the super user. Trusted extended attributes are meant for
144 +  implementing system/security services.
145 +
146 +  If unsure, say N.
147 +
148  Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
149  CONFIG_JBD
150    This is a generic journalling layer for block devices.  It is
151 Index: linux-2.4.21-chaos/fs/Config.in
152 ===================================================================
153 --- linux-2.4.21-chaos.orig/fs/Config.in        2003-09-19 03:49:54.000000000 +0400
154 +++ linux-2.4.21-chaos/fs/Config.in     2003-12-14 15:11:46.000000000 +0300
155 @@ -108,6 +108,11 @@
156  tristate 'ROM file system support' CONFIG_ROMFS_FS
157  
158  tristate 'Second extended fs support' CONFIG_EXT2_FS
159 +dep_mbool '  Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
160 +dep_bool '    Ext2 extended attribute block sharing' \
161 +    CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
162 +dep_bool '    Ext2 extended user attributes' \
163 +    CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
164  
165  tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
166  
167 @@ -196,6 +201,10 @@
168     bool "POSIX ACL helper functions" CONFIG_FS_POSIX_ACL
169  fi
170  
171 +# Meta block cache for Extended Attributes (ext2/ext3)
172 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
173 +define_tristate CONFIG_FS_MBCACHE y 
174 +
175  mainmenu_option next_comment
176  comment 'Partition Types'
177  source fs/partitions/Config.in
178 Index: linux-2.4.21-chaos/fs/Makefile
179 ===================================================================
180 --- linux-2.4.21-chaos.orig/fs/Makefile 2003-12-14 15:09:27.000000000 +0300
181 +++ linux-2.4.21-chaos/fs/Makefile      2003-12-14 15:11:46.000000000 +0300
182 @@ -95,6 +95,9 @@
183  obj-$(CONFIG_NFS_ACL)          += solaris_acl.o
184  obj-$(CONFIG_NFSD_ACL)         += solaris_acl.o
185  
186 +export-objs += mbcache.o
187 +obj-$(CONFIG_FS_MBCACHE)       += mbcache.o
188 +
189  # persistent filesystems
190  obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
191  
192 Index: linux-2.4.21-chaos/fs/ext2/Makefile
193 ===================================================================
194 --- linux-2.4.21-chaos.orig/fs/ext2/Makefile    2002-05-08 01:53:46.000000000 +0400
195 +++ linux-2.4.21-chaos/fs/ext2/Makefile 2003-12-14 15:11:46.000000000 +0300
196 @@ -13,4 +13,8 @@
197                 ioctl.o namei.o super.o symlink.o
198  obj-m    := $(O_TARGET)
199  
200 +export-objs += xattr.o
201 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
202 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
203 +
204  include $(TOPDIR)/Rules.make
205 Index: linux-2.4.21-chaos/fs/ext2/file.c
206 ===================================================================
207 --- linux-2.4.21-chaos.orig/fs/ext2/file.c      2003-07-15 04:41:01.000000000 +0400
208 +++ linux-2.4.21-chaos/fs/ext2/file.c   2003-12-14 15:11:46.000000000 +0300
209 @@ -20,6 +20,7 @@
210  
211  #include <linux/fs.h>
212  #include <linux/ext2_fs.h>
213 +#include <linux/ext2_xattr.h>
214  #include <linux/sched.h>
215  
216  /*
217 @@ -55,4 +56,8 @@
218  
219  struct inode_operations ext2_file_inode_operations = {
220         truncate:       ext2_truncate,
221 +       setxattr:       ext2_setxattr,
222 +       getxattr:       ext2_getxattr,
223 +       listxattr:      ext2_listxattr,
224 +       removexattr:    ext2_removexattr,
225  };
226 Index: linux-2.4.21-chaos/fs/ext2/ialloc.c
227 ===================================================================
228 --- linux-2.4.21-chaos.orig/fs/ext2/ialloc.c    2003-07-15 02:09:35.000000000 +0400
229 +++ linux-2.4.21-chaos/fs/ext2/ialloc.c 2003-12-14 15:11:46.000000000 +0300
230 @@ -15,6 +15,7 @@
231  #include <linux/config.h>
232  #include <linux/fs.h>
233  #include <linux/ext2_fs.h>
234 +#include <linux/ext2_xattr.h>
235  #include <linux/locks.h>
236  #include <linux/quotaops.h>
237  
238 @@ -167,6 +168,7 @@
239          */
240         if (!is_bad_inode(inode)) {
241                 /* Quota is already initialized in iput() */
242 +               ext2_xattr_delete_inode(inode);
243                 DQUOT_FREE_INODE(inode);
244                 DQUOT_DROP(inode);
245         }
246 Index: linux-2.4.21-chaos/fs/ext2/inode.c
247 ===================================================================
248 --- linux-2.4.21-chaos.orig/fs/ext2/inode.c     2003-07-15 04:41:01.000000000 +0400
249 +++ linux-2.4.21-chaos/fs/ext2/inode.c  2003-12-14 15:11:46.000000000 +0300
250 @@ -53,9 +65,7 @@
251  {
252         lock_kernel();
253  
254 -       if (is_bad_inode(inode) ||
255 -           inode->i_ino == EXT2_ACL_IDX_INO ||
256 -           inode->i_ino == EXT2_ACL_DATA_INO)
257 +       if (is_bad_inode(inode))
258                 goto no_delete;
259         inode->u.ext2_i.i_dtime = CURRENT_TIME;
260         mark_inode_dirty(inode);
261 @@ -802,6 +812,8 @@
262         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
263             S_ISLNK(inode->i_mode)))
264                 return;
265 +       if (ext2_inode_is_fast_symlink(inode))
266 +               return;
267         if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
268                 return;
269  
270 @@ -904,8 +916,7 @@
271         unsigned long offset;
272         struct ext2_group_desc * gdp;
273  
274 -       if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
275 -            inode->i_ino != EXT2_ACL_DATA_INO &&
276 +       if ((inode->i_ino != EXT2_ROOT_INO &&
277              inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
278             inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
279                 ext2_error (inode->i_sb, "ext2_read_inode",
280 @@ -990,10 +1001,7 @@
281         for (block = 0; block < EXT2_N_BLOCKS; block++)
282                 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
283  
284 -       if (inode->i_ino == EXT2_ACL_IDX_INO ||
285 -           inode->i_ino == EXT2_ACL_DATA_INO)
286 -               /* Nothing to do */ ;
287 -       else if (S_ISREG(inode->i_mode)) {
288 +       if (S_ISREG(inode->i_mode)) {
289                 inode->i_op = &ext2_file_inode_operations;
290                 inode->i_fop = &ext2_file_operations;
291                 inode->i_mapping->a_ops = &ext2_aops;
292 @@ -1002,12 +1010,14 @@
293                 if (ext2_inode_is_fast_symlink(inode))
294                         inode->i_op = &ext2_fast_symlink_inode_operations;
295                 else {
296 -                       inode->i_op = &page_symlink_inode_operations;
297 +                       inode->i_op = &ext2_symlink_inode_operations;
298                         inode->i_mapping->a_ops = &ext2_aops;
299                 }
300 -       } else 
301 +       } else {
302 +               inode->i_op = &ext2_special_inode_operations;
303                 init_special_inode(inode, inode->i_mode,
304                                    le32_to_cpu(raw_inode->i_block[0]));
305 +       }
306         brelse (bh);
307         inode->i_attr_flags = 0;
308         ext2_set_inode_flags(inode);
309 Index: linux-2.4.21-chaos/fs/ext2/namei.c
310 ===================================================================
311 --- linux-2.4.21-chaos.orig/fs/ext2/namei.c     2002-05-08 01:53:46.000000000 +0400
312 +++ linux-2.4.21-chaos/fs/ext2/namei.c  2003-12-14 15:11:46.000000000 +0300
313 @@ -31,6 +31,7 @@
314  
315  #include <linux/fs.h>
316  #include <linux/ext2_fs.h>
317 +#include <linux/ext2_xattr.h>
318  #include <linux/pagemap.h>
319  
320  /*
321 @@ -136,7 +137,7 @@
322  
323         if (l > sizeof (inode->u.ext2_i.i_data)) {
324                 /* slow symlink */
325 -               inode->i_op = &page_symlink_inode_operations;
326 +               inode->i_op = &ext2_symlink_inode_operations;
327                 inode->i_mapping->a_ops = &ext2_aops;
328                 err = block_symlink(inode, symname, l);
329                 if (err)
330 @@ -345,4 +346,15 @@
331         rmdir:          ext2_rmdir,
332         mknod:          ext2_mknod,
333         rename:         ext2_rename,
334 +       setxattr:       ext2_setxattr,
335 +       getxattr:       ext2_getxattr,
336 +       listxattr:      ext2_listxattr,
337 +       removexattr:    ext2_removexattr,
338 +};
339 +
340 +struct inode_operations ext2_special_inode_operations = {
341 +       setxattr:       ext2_setxattr,
342 +       getxattr:       ext2_getxattr,
343 +       listxattr:      ext2_listxattr,
344 +       removexattr:    ext2_removexattr,
345  };
346 Index: linux-2.4.21-chaos/fs/ext2/super.c
347 ===================================================================
348 --- linux-2.4.21-chaos.orig/fs/ext2/super.c     2003-02-15 01:59:09.000000000 +0300
349 +++ linux-2.4.21-chaos/fs/ext2/super.c  2003-12-14 15:11:46.000000000 +0300
350 @@ -21,6 +21,7 @@
351  #include <linux/string.h>
352  #include <linux/fs.h>
353  #include <linux/ext2_fs.h>
354 +#include <linux/ext2_xattr.h>
355  #include <linux/slab.h>
356  #include <linux/init.h>
357  #include <linux/locks.h>
358 @@ -125,6 +126,7 @@
359         int db_count;
360         int i;
361  
362 +       ext2_xattr_put_super(sb);
363         if (!(sb->s_flags & MS_RDONLY)) {
364                 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
365  
366 @@ -175,6 +177,13 @@
367              this_char = strtok (NULL, ",")) {
368                 if ((value = strchr (this_char, '=')) != NULL)
369                         *value++ = 0;
370 +#ifdef CONFIG_EXT2_FS_XATTR_USER
371 +               if (!strcmp (this_char, "user_xattr"))
372 +                       set_opt (*mount_options, XATTR_USER);
373 +               else if (!strcmp (this_char, "nouser_xattr"))
374 +                       clear_opt (*mount_options, XATTR_USER);
375 +               else
376 +#endif
377                 if (!strcmp (this_char, "bsddf"))
378                         clear_opt (*mount_options, MINIX_DF);
379                 else if (!strcmp (this_char, "nouid32")) {
380 @@ -424,6 +433,9 @@
381             blocksize = BLOCK_SIZE;
382  
383         sb->u.ext2_sb.s_mount_opt = 0;
384 +#ifdef CONFIG_EXT2_FS_XATTR_USER
385 +       /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
386 +#endif
387         if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
388             &sb->u.ext2_sb.s_mount_opt)) {
389                 return NULL;
390 @@ -813,12 +825,27 @@
391  
392  static int __init init_ext2_fs(void)
393  {
394 -        return register_filesystem(&ext2_fs_type);
395 +       int error = init_ext2_xattr();
396 +       if (error)
397 +               return error;
398 +       error = init_ext2_xattr_user();
399 +       if (error)
400 +               goto fail;
401 +       error = register_filesystem(&ext2_fs_type);
402 +       if (!error)
403 +               return 0;
404 +
405 +       exit_ext2_xattr_user();
406 +fail:
407 +       exit_ext2_xattr();
408 +       return error;
409  }
410  
411  static void __exit exit_ext2_fs(void)
412  {
413         unregister_filesystem(&ext2_fs_type);
414 +       exit_ext2_xattr_user();
415 +       exit_ext2_xattr();
416  }
417  
418  EXPORT_NO_SYMBOLS;
419 Index: linux-2.4.21-chaos/fs/ext2/symlink.c
420 ===================================================================
421 --- linux-2.4.21-chaos.orig/fs/ext2/symlink.c   2002-05-08 01:53:46.000000000 +0400
422 +++ linux-2.4.21-chaos/fs/ext2/symlink.c        2003-12-14 15:11:46.000000000 +0300
423 @@ -19,6 +19,7 @@
424  
425  #include <linux/fs.h>
426  #include <linux/ext2_fs.h>
427 +#include <linux/ext2_xattr.h>
428  
429  static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
430  {
431 @@ -32,7 +33,20 @@
432         return vfs_follow_link(nd, s);
433  }
434  
435 +struct inode_operations ext2_symlink_inode_operations = {
436 +       readlink:       page_readlink,
437 +       follow_link:    page_follow_link,
438 +       setxattr:       ext2_setxattr,
439 +       getxattr:       ext2_getxattr,
440 +       listxattr:      ext2_listxattr,
441 +       removexattr:    ext2_removexattr,
442 +};
443 +
444  struct inode_operations ext2_fast_symlink_inode_operations = {
445         readlink:       ext2_readlink,
446         follow_link:    ext2_follow_link,
447 +       setxattr:       ext2_setxattr,
448 +       getxattr:       ext2_getxattr,
449 +       listxattr:      ext2_listxattr,
450 +       removexattr:    ext2_removexattr,
451  };
452 Index: linux-2.4.21-chaos/fs/ext2/xattr.c
453 ===================================================================
454 --- linux-2.4.21-chaos.orig/fs/ext2/xattr.c     2003-01-30 13:24:37.000000000 +0300
455 +++ linux-2.4.21-chaos/fs/ext2/xattr.c  2003-12-14 15:11:46.000000000 +0300
456 @@ -0,0 +1,1212 @@
457 +/*
458 + * linux/fs/ext2/xattr.c
459 + *
460 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
461 + *
462 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
463 + * Extended attributes for symlinks and special files added per
464 + *  suggestion of Luka Renko <luka.renko@hermes.si>.
465 + */
466 +
467 +/*
468 + * Extended attributes are stored on disk blocks allocated outside of
469 + * any inode. The i_file_acl field is then made to point to this allocated
470 + * block. If all extended attributes of an inode are identical, these
471 + * inodes may share the same extended attribute block. Such situations
472 + * are automatically detected by keeping a cache of recent attribute block
473 + * numbers and hashes over the block's contents in memory.
474 + *
475 + *
476 + * Extended attribute block layout:
477 + *
478 + *   +------------------+
479 + *   | header           |
480 + *   | entry 1          | |
481 + *   | entry 2          | | growing downwards
482 + *   | entry 3          | v
483 + *   | four null bytes  |
484 + *   | . . .            |
485 + *   | value 1          | ^
486 + *   | value 3          | | growing upwards
487 + *   | value 2          | |
488 + *   +------------------+
489 + *
490 + * The block header is followed by multiple entry descriptors. These entry
491 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
492 + * byte boundaries. The entry descriptors are sorted by attribute name,
493 + * so that two extended attribute blocks can be compared efficiently.
494 + *
495 + * Attribute values are aligned to the end of the block, stored in
496 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
497 + * boundaries. No additional gaps are left between them.
498 + *
499 + * Locking strategy
500 + * ----------------
501 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
502 + * the xattr inode operations are called, so we are guaranteed that only one
503 + * processes accesses extended attributes of an inode at any time.
504 + *
505 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
506 + * only a single process is modifying an extended attribute block, even
507 + * if the block is shared among inodes.
508 + *
509 + * Note for porting to 2.5
510 + * -----------------------
511 + * The BKL will no longer be held in the xattr inode operations.
512 + */
513 +
514 +#include <linux/module.h>
515 +#include <linux/locks.h>
516 +#include <linux/slab.h>
517 +#include <linux/fs.h>
518 +#include <linux/ext2_fs.h>
519 +#include <linux/ext2_xattr.h>
520 +#include <linux/mbcache.h>
521 +#include <linux/quotaops.h>
522 +#include <asm/semaphore.h>
523 +#include <linux/compatmac.h>
524 +
525 +/* These symbols may be needed by a module. */
526 +EXPORT_SYMBOL(ext2_xattr_register);
527 +EXPORT_SYMBOL(ext2_xattr_unregister);
528 +EXPORT_SYMBOL(ext2_xattr_get);
529 +EXPORT_SYMBOL(ext2_xattr_list);
530 +EXPORT_SYMBOL(ext2_xattr_set);
531 +
532 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
533 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
534 +#endif
535 +
536 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
537 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
538 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
539 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
540 +
541 +#ifdef EXT2_XATTR_DEBUG
542 +# define ea_idebug(inode, f...) do { \
543 +               printk(KERN_DEBUG "inode %s:%ld: ", \
544 +                       kdevname(inode->i_dev), inode->i_ino); \
545 +               printk(f); \
546 +               printk("\n"); \
547 +       } while (0)
548 +# define ea_bdebug(bh, f...) do { \
549 +               printk(KERN_DEBUG "block %s:%ld: ", \
550 +                       kdevname(bh->b_dev), bh->b_blocknr); \
551 +               printk(f); \
552 +               printk("\n"); \
553 +       } while (0)
554 +#else
555 +# define ea_idebug(f...)
556 +# define ea_bdebug(f...)
557 +#endif
558 +
559 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
560 +                          struct ext2_xattr_header *);
561 +
562 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
563 +
564 +static int ext2_xattr_cache_insert(struct buffer_head *);
565 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
566 +                                                struct ext2_xattr_header *);
567 +static void ext2_xattr_cache_remove(struct buffer_head *);
568 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
569 +                             struct ext2_xattr_entry *);
570 +
571 +static struct mb_cache *ext2_xattr_cache;
572 +
573 +#else
574 +# define ext2_xattr_cache_insert(bh) 0
575 +# define ext2_xattr_cache_find(inode, header) NULL
576 +# define ext2_xattr_cache_remove(bh) while(0) {}
577 +# define ext2_xattr_rehash(header, entry) while(0) {}
578 +#endif
579 +
580 +/*
581 + * If a file system does not share extended attributes among inodes,
582 + * we should not need the ext2_xattr_sem semaphore. However, the
583 + * filesystem may still contain shared blocks, so we always take
584 + * the lock.
585 + */
586 +
587 +DECLARE_MUTEX(ext2_xattr_sem);
588 +
589 +static inline int
590 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
591 +{
592 +       struct super_block *sb = inode->i_sb;
593 +       int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
594 +               EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
595 +
596 +       /* How can we enforce the allocation? */
597 +       int block = ext2_new_block(inode, goal, 0, 0, errp);
598 +#ifdef OLD_QUOTAS
599 +       if (!*errp)
600 +               inode->i_blocks += inode->i_sb->s_blocksize >> 9;
601 +#endif
602 +       return block;
603 +}
604 +
605 +static inline int
606 +ext2_xattr_quota_alloc(struct inode *inode, int force)
607 +{
608 +       /* How can we enforce the allocation? */
609 +#ifdef OLD_QUOTAS
610 +       int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
611 +       if (!error)
612 +               inode->i_blocks += inode->i_sb->s_blocksize >> 9;
613 +#else
614 +       int error = DQUOT_ALLOC_BLOCK(inode, 1);
615 +#endif
616 +       return error;
617 +}
618 +
619 +#ifdef OLD_QUOTAS
620 +
621 +static inline void
622 +ext2_xattr_quota_free(struct inode *inode)
623 +{
624 +       DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
625 +       inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
626 +}
627 +
628 +static inline void
629 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
630 +{
631 +       ext2_free_blocks(inode, block, 1);
632 +       inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
633 +}
634 +
635 +#else
636 +# define ext2_xattr_quota_free(inode) \
637 +       DQUOT_FREE_BLOCK(inode, 1)
638 +# define ext2_xattr_free_block(inode, block) \
639 +       ext2_free_blocks(inode, block, 1)
640 +#endif
641 +
642 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
643 +
644 +static inline struct buffer_head *
645 +sb_bread(struct super_block *sb, int block)
646 +{
647 +       return bread(sb->s_dev, block, sb->s_blocksize);
648 +}
649 +
650 +static inline struct buffer_head *
651 +sb_getblk(struct super_block *sb, int block)
652 +{
653 +       return getblk(sb->s_dev, block, sb->s_blocksize);
654 +}
655 +
656 +#endif
657 +
658 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
659 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
660 +
661 +int
662 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
663 +{
664 +       int error = -EINVAL;
665 +
666 +       if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
667 +               write_lock(&ext2_handler_lock);
668 +               if (!ext2_xattr_handlers[name_index-1]) {
669 +                       ext2_xattr_handlers[name_index-1] = handler;
670 +                       error = 0;
671 +               }
672 +               write_unlock(&ext2_handler_lock);
673 +       }
674 +       return error;
675 +}
676 +
677 +void
678 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
679 +{
680 +       if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
681 +               write_lock(&ext2_handler_lock);
682 +               ext2_xattr_handlers[name_index-1] = NULL;
683 +               write_unlock(&ext2_handler_lock);
684 +       }
685 +}
686 +
687 +static inline const char *
688 +strcmp_prefix(const char *a, const char *a_prefix)
689 +{
690 +       while (*a_prefix && *a == *a_prefix) {
691 +               a++;
692 +               a_prefix++;
693 +       }
694 +       return *a_prefix ? NULL : a;
695 +}
696 +
697 +/*
698 + * Decode the extended attribute name, and translate it into
699 + * the name_index and name suffix.
700 + */
701 +static struct ext2_xattr_handler *
702 +ext2_xattr_resolve_name(const char **name)
703 +{
704 +       struct ext2_xattr_handler *handler = NULL;
705 +       int i;
706 +
707 +       if (!*name)
708 +               return NULL;
709 +       read_lock(&ext2_handler_lock);
710 +       for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
711 +               if (ext2_xattr_handlers[i]) {
712 +                       const char *n = strcmp_prefix(*name,
713 +                               ext2_xattr_handlers[i]->prefix);
714 +                       if (n) {
715 +                               handler = ext2_xattr_handlers[i];
716 +                               *name = n;
717 +                               break;
718 +                       }
719 +               }
720 +       }
721 +       read_unlock(&ext2_handler_lock);
722 +       return handler;
723 +}
724 +
725 +static inline struct ext2_xattr_handler *
726 +ext2_xattr_handler(int name_index)
727 +{
728 +       struct ext2_xattr_handler *handler = NULL;
729 +       if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
730 +               read_lock(&ext2_handler_lock);
731 +               handler = ext2_xattr_handlers[name_index-1];
732 +               read_unlock(&ext2_handler_lock);
733 +       }
734 +       return handler;
735 +}
736 +
737 +/*
738 + * Inode operation getxattr()
739 + *
740 + * dentry->d_inode->i_sem down
741 + * BKL held [before 2.5.x]
742 + */
743 +ssize_t
744 +ext2_getxattr(struct dentry *dentry, const char *name,
745 +             void *buffer, size_t size)
746 +{
747 +       struct ext2_xattr_handler *handler;
748 +       struct inode *inode = dentry->d_inode;
749 +
750 +       handler = ext2_xattr_resolve_name(&name);
751 +       if (!handler)
752 +               return -ENOTSUP;
753 +       return handler->get(inode, name, buffer, size);
754 +}
755 +
756 +/*
757 + * Inode operation listxattr()
758 + *
759 + * dentry->d_inode->i_sem down
760 + * BKL held [before 2.5.x]
761 + */
762 +ssize_t
763 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
764 +{
765 +       return ext2_xattr_list(dentry->d_inode, buffer, size);
766 +}
767 +
768 +/*
769 + * Inode operation setxattr()
770 + *
771 + * dentry->d_inode->i_sem down
772 + * BKL held [before 2.5.x]
773 + */
774 +int
775 +ext2_setxattr(struct dentry *dentry, const char *name,
776 +             const void *value, size_t size, int flags)
777 +{
778 +       struct ext2_xattr_handler *handler;
779 +       struct inode *inode = dentry->d_inode;
780 +
781 +       if (size == 0)
782 +               value = "";  /* empty EA, do not remove */
783 +       handler = ext2_xattr_resolve_name(&name);
784 +       if (!handler)
785 +               return -ENOTSUP;
786 +       return handler->set(inode, name, value, size, flags);
787 +}
788 +
789 +/*
790 + * Inode operation removexattr()
791 + *
792 + * dentry->d_inode->i_sem down
793 + * BKL held [before 2.5.x]
794 + */
795 +int
796 +ext2_removexattr(struct dentry *dentry, const char *name)
797 +{
798 +       struct ext2_xattr_handler *handler;
799 +       struct inode *inode = dentry->d_inode;
800 +
801 +       handler = ext2_xattr_resolve_name(&name);
802 +       if (!handler)
803 +               return -ENOTSUP;
804 +       return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
805 +}
806 +
807 +/*
808 + * ext2_xattr_get()
809 + *
810 + * Copy an extended attribute into the buffer
811 + * provided, or compute the buffer size required.
812 + * Buffer is NULL to compute the size of the buffer required.
813 + *
814 + * Returns a negative error number on failure, or the number of bytes
815 + * used / required on success.
816 + */
817 +int
818 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
819 +              void *buffer, size_t buffer_size)
820 +{
821 +       struct buffer_head *bh = NULL;
822 +       struct ext2_xattr_entry *entry;
823 +       unsigned int block, size;
824 +       char *end;
825 +       int name_len, error;
826 +
827 +       ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
828 +                 name_index, name, buffer, (long)buffer_size);
829 +
830 +       if (name == NULL)
831 +               return -EINVAL;
832 +       if (!EXT2_I(inode)->i_file_acl)
833 +               return -ENOATTR;
834 +       block = EXT2_I(inode)->i_file_acl;
835 +       ea_idebug(inode, "reading block %d", block);
836 +       bh = sb_bread(inode->i_sb, block);
837 +       if (!bh)
838 +               return -EIO;
839 +       ea_bdebug(bh, "b_count=%d, refcount=%d",
840 +               atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
841 +       end = bh->b_data + bh->b_size;
842 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
843 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
844 +bad_block:     ext2_error(inode->i_sb, "ext2_xattr_get",
845 +                       "inode %ld: bad block %d", inode->i_ino, block);
846 +               error = -EIO;
847 +               goto cleanup;
848 +       }
849 +       /* find named attribute */
850 +       name_len = strlen(name);
851 +
852 +       error = -ERANGE;
853 +       if (name_len > 255)
854 +               goto cleanup;
855 +       entry = FIRST_ENTRY(bh);
856 +       while (!IS_LAST_ENTRY(entry)) {
857 +               struct ext2_xattr_entry *next =
858 +                       EXT2_XATTR_NEXT(entry);
859 +               if ((char *)next >= end)
860 +                       goto bad_block;
861 +               if (name_index == entry->e_name_index &&
862 +                   name_len == entry->e_name_len &&
863 +                   memcmp(name, entry->e_name, name_len) == 0)
864 +                       goto found;
865 +               entry = next;
866 +       }
867 +       /* Check the remaining name entries */
868 +       while (!IS_LAST_ENTRY(entry)) {
869 +               struct ext2_xattr_entry *next =
870 +                       EXT2_XATTR_NEXT(entry);
871 +               if ((char *)next >= end)
872 +                       goto bad_block;
873 +               entry = next;
874 +       }
875 +       if (ext2_xattr_cache_insert(bh))
876 +               ea_idebug(inode, "cache insert failed");
877 +       error = -ENOATTR;
878 +       goto cleanup;
879 +found:
880 +       /* check the buffer size */
881 +       if (entry->e_value_block != 0)
882 +               goto bad_block;
883 +       size = le32_to_cpu(entry->e_value_size);
884 +       if (size > inode->i_sb->s_blocksize ||
885 +           le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
886 +               goto bad_block;
887 +
888 +       if (ext2_xattr_cache_insert(bh))
889 +               ea_idebug(inode, "cache insert failed");
890 +       if (buffer) {
891 +               error = -ERANGE;
892 +               if (size > buffer_size)
893 +                       goto cleanup;
894 +               /* return value of attribute */
895 +               memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
896 +                       size);
897 +       }
898 +       error = size;
899 +
900 +cleanup:
901 +       brelse(bh);
902 +
903 +       return error;
904 +}
905 +
906 +/*
907 + * ext2_xattr_list()
908 + *
909 + * Copy a list of attribute names into the buffer
910 + * provided, or compute the buffer size required.
911 + * Buffer is NULL to compute the size of the buffer required.
912 + *
913 + * Returns a negative error number on failure, or the number of bytes
914 + * used / required on success.
915 + */
916 +int
917 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
918 +{
919 +       struct buffer_head *bh = NULL;
920 +       struct ext2_xattr_entry *entry;
921 +       unsigned int block, size = 0;
922 +       char *buf, *end;
923 +       int error;
924 +
925 +       ea_idebug(inode, "buffer=%p, buffer_size=%ld",
926 +                 buffer, (long)buffer_size);
927 +
928 +       if (!EXT2_I(inode)->i_file_acl)
929 +               return 0;
930 +       block = EXT2_I(inode)->i_file_acl;
931 +       ea_idebug(inode, "reading block %d", block);
932 +       bh = sb_bread(inode->i_sb, block);
933 +       if (!bh)
934 +               return -EIO;
935 +       ea_bdebug(bh, "b_count=%d, refcount=%d",
936 +               atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
937 +       end = bh->b_data + bh->b_size;
938 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
939 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
940 +bad_block:     ext2_error(inode->i_sb, "ext2_xattr_list",
941 +                       "inode %ld: bad block %d", inode->i_ino, block);
942 +               error = -EIO;
943 +               goto cleanup;
944 +       }
945 +       /* compute the size required for the list of attribute names */
946 +       for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
947 +            entry = EXT2_XATTR_NEXT(entry)) {
948 +               struct ext2_xattr_handler *handler;
949 +               struct ext2_xattr_entry *next =
950 +                       EXT2_XATTR_NEXT(entry);
951 +               if ((char *)next >= end)
952 +                       goto bad_block;
953 +
954 +               handler = ext2_xattr_handler(entry->e_name_index);
955 +               if (handler)
956 +                       size += handler->list(NULL, inode, entry->e_name,
957 +                                             entry->e_name_len);
958 +       }
959 +
960 +       if (ext2_xattr_cache_insert(bh))
961 +               ea_idebug(inode, "cache insert failed");
962 +       if (!buffer) {
963 +               error = size;
964 +               goto cleanup;
965 +       } else {
966 +               error = -ERANGE;
967 +               if (size > buffer_size)
968 +                       goto cleanup;
969 +       }
970 +
971 +       /* list the attribute names */
972 +       buf = buffer;
973 +       for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
974 +            entry = EXT2_XATTR_NEXT(entry)) {
975 +               struct ext2_xattr_handler *handler;
976 +               
977 +               handler = ext2_xattr_handler(entry->e_name_index);
978 +               if (handler)
979 +                       buf += handler->list(buf, inode, entry->e_name,
980 +                                            entry->e_name_len);
981 +       }
982 +       error = size;
983 +
984 +cleanup:
985 +       brelse(bh);
986 +
987 +       return error;
988 +}
989 +
990 +/*
991 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
992 + * not set, set it.
993 + */
994 +static void ext2_xattr_update_super_block(struct super_block *sb)
995 +{
996 +       if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
997 +               return;
998 +
999 +       lock_super(sb);
1000 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1001 +       EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1002 +#endif
1003 +       EXT2_SB(sb)->s_es->s_feature_compat |=
1004 +               cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1005 +       sb->s_dirt = 1;
1006 +       mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1007 +       unlock_super(sb);
1008 +}
1009 +
1010 +/*
1011 + * ext2_xattr_set()
1012 + *
1013 + * Create, replace or remove an extended attribute for this inode. Buffer
1014 + * is NULL to remove an existing extended attribute, and non-NULL to
1015 + * either replace an existing extended attribute, or create a new extended
1016 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1017 + * specify that an extended attribute must exist and must not exist
1018 + * previous to the call, respectively.
1019 + *
1020 + * Returns 0, or a negative error number on failure.
1021 + */
1022 +int
1023 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1024 +              const void *value, size_t value_len, int flags)
1025 +{
1026 +       struct super_block *sb = inode->i_sb;
1027 +       struct buffer_head *bh = NULL;
1028 +       struct ext2_xattr_header *header = NULL;
1029 +       struct ext2_xattr_entry *here, *last;
1030 +       unsigned int name_len;
1031 +       int block = EXT2_I(inode)->i_file_acl;
1032 +       int min_offs = sb->s_blocksize, not_found = 1, free, error;
1033 +       char *end;
1034 +       
1035 +       /*
1036 +        * header -- Points either into bh, or to a temporarily
1037 +        *           allocated buffer.
1038 +        * here -- The named entry found, or the place for inserting, within
1039 +        *         the block pointed to by header.
1040 +        * last -- Points right after the last named entry within the block
1041 +        *         pointed to by header.
1042 +        * min_offs -- The offset of the first value (values are aligned
1043 +        *             towards the end of the block).
1044 +        * end -- Points right after the block pointed to by header.
1045 +        */
1046 +       
1047 +       ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1048 +                 name_index, name, value, (long)value_len);
1049 +
1050 +       if (IS_RDONLY(inode))
1051 +               return -EROFS;
1052 +       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1053 +               return -EPERM;
1054 +       if (value == NULL)
1055 +               value_len = 0;
1056 +       if (name == NULL)
1057 +               return -EINVAL;
1058 +       name_len = strlen(name);
1059 +       if (name_len > 255 || value_len > sb->s_blocksize)
1060 +               return -ERANGE;
1061 +       down(&ext2_xattr_sem);
1062 +
1063 +       if (block) {
1064 +               /* The inode already has an extended attribute block. */
1065 +
1066 +               bh = sb_bread(sb, block);
1067 +               error = -EIO;
1068 +               if (!bh)
1069 +                       goto cleanup;
1070 +               ea_bdebug(bh, "b_count=%d, refcount=%d",
1071 +                       atomic_read(&(bh->b_count)),
1072 +                       le32_to_cpu(HDR(bh)->h_refcount));
1073 +               header = HDR(bh);
1074 +               end = bh->b_data + bh->b_size;
1075 +               if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1076 +                   header->h_blocks != cpu_to_le32(1)) {
1077 +bad_block:             ext2_error(sb, "ext2_xattr_set",
1078 +                               "inode %ld: bad block %d", inode->i_ino, block);
1079 +                       error = -EIO;
1080 +                       goto cleanup;
1081 +               }
1082 +               /* Find the named attribute. */
1083 +               here = FIRST_ENTRY(bh);
1084 +               while (!IS_LAST_ENTRY(here)) {
1085 +                       struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1086 +                       if ((char *)next >= end)
1087 +                               goto bad_block;
1088 +                       if (!here->e_value_block && here->e_value_size) {
1089 +                               int offs = le16_to_cpu(here->e_value_offs);
1090 +                               if (offs < min_offs)
1091 +                                       min_offs = offs;
1092 +                       }
1093 +                       not_found = name_index - here->e_name_index;
1094 +                       if (!not_found)
1095 +                               not_found = name_len - here->e_name_len;
1096 +                       if (!not_found)
1097 +                               not_found = memcmp(name, here->e_name,name_len);
1098 +                       if (not_found <= 0)
1099 +                               break;
1100 +                       here = next;
1101 +               }
1102 +               last = here;
1103 +               /* We still need to compute min_offs and last. */
1104 +               while (!IS_LAST_ENTRY(last)) {
1105 +                       struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1106 +                       if ((char *)next >= end)
1107 +                               goto bad_block;
1108 +                       if (!last->e_value_block && last->e_value_size) {
1109 +                               int offs = le16_to_cpu(last->e_value_offs);
1110 +                               if (offs < min_offs)
1111 +                                       min_offs = offs;
1112 +                       }
1113 +                       last = next;
1114 +               }
1115 +
1116 +               /* Check whether we have enough space left. */
1117 +               free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1118 +       } else {
1119 +               /* We will use a new extended attribute block. */
1120 +               free = sb->s_blocksize -
1121 +                       sizeof(struct ext2_xattr_header) - sizeof(__u32);
1122 +               here = last = NULL;  /* avoid gcc uninitialized warning. */
1123 +       }
1124 +
1125 +       if (not_found) {
1126 +               /* Request to remove a nonexistent attribute? */
1127 +               error = -ENOATTR;
1128 +               if (flags & XATTR_REPLACE)
1129 +                       goto cleanup;
1130 +               error = 0;
1131 +               if (value == NULL)
1132 +                       goto cleanup;
1133 +               else
1134 +                       free -= EXT2_XATTR_LEN(name_len);
1135 +       } else {
1136 +               /* Request to create an existing attribute? */
1137 +               error = -EEXIST;
1138 +               if (flags & XATTR_CREATE)
1139 +                       goto cleanup;
1140 +               if (!here->e_value_block && here->e_value_size) {
1141 +                       unsigned int size = le32_to_cpu(here->e_value_size);
1142 +
1143 +                       if (le16_to_cpu(here->e_value_offs) + size > 
1144 +                           sb->s_blocksize || size > sb->s_blocksize)
1145 +                               goto bad_block;
1146 +                       free += EXT2_XATTR_SIZE(size);
1147 +               }
1148 +       }
1149 +       free -= EXT2_XATTR_SIZE(value_len);
1150 +       error = -ENOSPC;
1151 +       if (free < 0)
1152 +               goto cleanup;
1153 +
1154 +       /* Here we know that we can set the new attribute. */
1155 +
1156 +       if (header) {
1157 +               if (header->h_refcount == cpu_to_le32(1)) {
1158 +                       ea_bdebug(bh, "modifying in-place");
1159 +                       ext2_xattr_cache_remove(bh);
1160 +               } else {
1161 +                       int offset;
1162 +
1163 +                       ea_bdebug(bh, "cloning");
1164 +                       header = kmalloc(bh->b_size, GFP_KERNEL);
1165 +                       error = -ENOMEM;
1166 +                       if (header == NULL)
1167 +                               goto cleanup;
1168 +                       memcpy(header, HDR(bh), bh->b_size);
1169 +                       header->h_refcount = cpu_to_le32(1);
1170 +                       offset = (char *)header - bh->b_data;
1171 +                       here = ENTRY((char *)here + offset);
1172 +                       last = ENTRY((char *)last + offset);
1173 +               }
1174 +       } else {
1175 +               /* Allocate a buffer where we construct the new block. */
1176 +               header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1177 +               error = -ENOMEM;
1178 +               if (header == NULL)
1179 +                       goto cleanup;
1180 +               memset(header, 0, sb->s_blocksize);
1181 +               end = (char *)header + sb->s_blocksize;
1182 +               header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1183 +               header->h_blocks = header->h_refcount = cpu_to_le32(1);
1184 +               last = here = ENTRY(header+1);
1185 +       }
1186 +
1187 +       if (not_found) {
1188 +               /* Insert the new name. */
1189 +               int size = EXT2_XATTR_LEN(name_len);
1190 +               int rest = (char *)last - (char *)here;
1191 +               memmove((char *)here + size, here, rest);
1192 +               memset(here, 0, size);
1193 +               here->e_name_index = name_index;
1194 +               here->e_name_len = name_len;
1195 +               memcpy(here->e_name, name, name_len);
1196 +       } else {
1197 +               /* Remove the old value. */
1198 +               if (!here->e_value_block && here->e_value_size) {
1199 +                       char *first_val = (char *)header + min_offs;
1200 +                       int offs = le16_to_cpu(here->e_value_offs);
1201 +                       char *val = (char *)header + offs;
1202 +                       size_t size = EXT2_XATTR_SIZE(
1203 +                               le32_to_cpu(here->e_value_size));
1204 +                       memmove(first_val + size, first_val, val - first_val);
1205 +                       memset(first_val, 0, size);
1206 +                       here->e_value_offs = 0;
1207 +                       min_offs += size;
1208 +
1209 +                       /* Adjust all value offsets. */
1210 +                       last = ENTRY(header+1);
1211 +                       while (!IS_LAST_ENTRY(last)) {
1212 +                               int o = le16_to_cpu(last->e_value_offs);
1213 +                               if (!last->e_value_block && o < offs)
1214 +                                       last->e_value_offs =
1215 +                                               cpu_to_le16(o + size);
1216 +                               last = EXT2_XATTR_NEXT(last);
1217 +                       }
1218 +               }
1219 +               if (value == NULL) {
1220 +                       /* Remove this attribute. */
1221 +                       if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1222 +                               /* This block is now empty. */
1223 +                               error = ext2_xattr_set2(inode, bh, NULL);
1224 +                               goto cleanup;
1225 +                       } else {
1226 +                               /* Remove the old name. */
1227 +                               int size = EXT2_XATTR_LEN(name_len);
1228 +                               last = ENTRY((char *)last - size);
1229 +                               memmove(here, (char*)here + size,
1230 +                                       (char*)last - (char*)here);
1231 +                               memset(last, 0, size);
1232 +                       }
1233 +               }
1234 +       }
1235 +
1236 +       if (value != NULL) {
1237 +               /* Insert the new value. */
1238 +               here->e_value_size = cpu_to_le32(value_len);
1239 +               if (value_len) {
1240 +                       size_t size = EXT2_XATTR_SIZE(value_len);
1241 +                       char *val = (char *)header + min_offs - size;
1242 +                       here->e_value_offs =
1243 +                               cpu_to_le16((char *)val - (char *)header);
1244 +                       memset(val + size - EXT2_XATTR_PAD, 0,
1245 +                              EXT2_XATTR_PAD); /* Clear the pad bytes. */
1246 +                       memcpy(val, value, value_len);
1247 +               }
1248 +       }
1249 +       ext2_xattr_rehash(header, here);
1250 +
1251 +       error = ext2_xattr_set2(inode, bh, header);
1252 +
1253 +cleanup:
1254 +       brelse(bh);
1255 +       if (!(bh && header == HDR(bh)))
1256 +               kfree(header);
1257 +       up(&ext2_xattr_sem);
1258 +
1259 +       return error;
1260 +}
1261 +
1262 +/*
1263 + * Second half of ext2_xattr_set(): Update the file system.
1264 + */
1265 +static int
1266 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1267 +               struct ext2_xattr_header *header)
1268 +{
1269 +       struct super_block *sb = inode->i_sb;
1270 +       struct buffer_head *new_bh = NULL;
1271 +       int error;
1272 +
1273 +       if (header) {
1274 +               new_bh = ext2_xattr_cache_find(inode, header);
1275 +               if (new_bh) {
1276 +                       /*
1277 +                        * We found an identical block in the cache.
1278 +                        * The old block will be released after updating
1279 +                        * the inode.
1280 +                        */
1281 +                       ea_bdebug(old_bh, "reusing block %ld",
1282 +                               new_bh->b_blocknr);
1283 +                       
1284 +                       error = -EDQUOT;
1285 +                       if (ext2_xattr_quota_alloc(inode, 1))
1286 +                               goto cleanup;
1287 +                       
1288 +                       HDR(new_bh)->h_refcount = cpu_to_le32(
1289 +                               le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1290 +                       ea_bdebug(new_bh, "refcount now=%d",
1291 +                               le32_to_cpu(HDR(new_bh)->h_refcount));
1292 +               } else if (old_bh && header == HDR(old_bh)) {
1293 +                       /* Keep this block. */
1294 +                       new_bh = old_bh;
1295 +                       (void)ext2_xattr_cache_insert(new_bh);
1296 +               } else {
1297 +                       /* We need to allocate a new block */
1298 +                       int force = EXT2_I(inode)->i_file_acl != 0;
1299 +                       int block = ext2_xattr_new_block(inode, &error, force);
1300 +                       if (error)
1301 +                               goto cleanup;
1302 +                       ea_idebug(inode, "creating block %d", block);
1303 +
1304 +                       new_bh = sb_getblk(sb, block);
1305 +                       if (!new_bh) {
1306 +                               ext2_xattr_free_block(inode, block);
1307 +                               error = -EIO;
1308 +                               goto cleanup;
1309 +                       }
1310 +                       lock_buffer(new_bh);
1311 +                       memcpy(new_bh->b_data, header, new_bh->b_size);
1312 +                       mark_buffer_uptodate(new_bh, 1);
1313 +                       unlock_buffer(new_bh);
1314 +                       (void)ext2_xattr_cache_insert(new_bh);
1315 +                       
1316 +                       ext2_xattr_update_super_block(sb);
1317 +               }
1318 +               mark_buffer_dirty(new_bh);
1319 +               if (IS_SYNC(inode)) {
1320 +                       ll_rw_block(WRITE, 1, &new_bh);
1321 +                       wait_on_buffer(new_bh); 
1322 +                       error = -EIO;
1323 +                       if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1324 +                               goto cleanup;
1325 +               }
1326 +       }
1327 +
1328 +       /* Update the inode. */
1329 +       EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1330 +       inode->i_ctime = CURRENT_TIME;
1331 +       if (IS_SYNC(inode)) {
1332 +               error = ext2_sync_inode (inode);
1333 +               if (error)
1334 +                       goto cleanup;
1335 +       } else
1336 +               mark_inode_dirty(inode);
1337 +
1338 +       error = 0;
1339 +       if (old_bh && old_bh != new_bh) {
1340 +               /*
1341 +                * If there was an old block, and we are not still using it,
1342 +                * we now release the old block.
1343 +               */
1344 +               unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1345 +
1346 +               if (refcount == 1) {
1347 +                       /* Free the old block. */
1348 +                       ea_bdebug(old_bh, "freeing");
1349 +                       ext2_xattr_free_block(inode, old_bh->b_blocknr);
1350 +                       mark_buffer_clean(old_bh);
1351 +               } else {
1352 +                       /* Decrement the refcount only. */
1353 +                       refcount--;
1354 +                       HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1355 +                       ext2_xattr_quota_free(inode);
1356 +                       mark_buffer_dirty(old_bh);
1357 +                       ea_bdebug(old_bh, "refcount now=%d", refcount);
1358 +               }
1359 +       }
1360 +
1361 +cleanup:
1362 +       if (old_bh != new_bh)
1363 +               brelse(new_bh);
1364 +
1365 +       return error;
1366 +}
1367 +
1368 +/*
1369 + * ext2_xattr_delete_inode()
1370 + *
1371 + * Free extended attribute resources associated with this inode. This
1372 + * is called immediately before an inode is freed.
1373 + */
1374 +void
1375 +ext2_xattr_delete_inode(struct inode *inode)
1376 +{
1377 +       struct buffer_head *bh;
1378 +       unsigned int block = EXT2_I(inode)->i_file_acl;
1379 +
1380 +       if (!block)
1381 +               return;
1382 +       down(&ext2_xattr_sem);
1383 +
1384 +       bh = sb_bread(inode->i_sb, block);
1385 +       if (!bh) {
1386 +               ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1387 +                       "inode %ld: block %d read error", inode->i_ino, block);
1388 +               goto cleanup;
1389 +       }
1390 +       ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1391 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1392 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
1393 +               ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1394 +                       "inode %ld: bad block %d", inode->i_ino, block);
1395 +               goto cleanup;
1396 +       }
1397 +       ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1398 +       if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1399 +               ext2_xattr_cache_remove(bh);
1400 +               ext2_xattr_free_block(inode, block);
1401 +               bforget(bh);
1402 +               bh = NULL;
1403 +       } else {
1404 +               HDR(bh)->h_refcount = cpu_to_le32(
1405 +                       le32_to_cpu(HDR(bh)->h_refcount) - 1);
1406 +               mark_buffer_dirty(bh);
1407 +               if (IS_SYNC(inode)) {
1408 +                       ll_rw_block(WRITE, 1, &bh);
1409 +                       wait_on_buffer(bh);
1410 +               }
1411 +               ext2_xattr_quota_free(inode);
1412 +       }
1413 +       EXT2_I(inode)->i_file_acl = 0;
1414 +
1415 +cleanup:
1416 +       brelse(bh);
1417 +       up(&ext2_xattr_sem);
1418 +}
1419 +
1420 +/*
1421 + * ext2_xattr_put_super()
1422 + *
1423 + * This is called when a file system is unmounted.
1424 + */
1425 +void
1426 +ext2_xattr_put_super(struct super_block *sb)
1427 +{
1428 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1429 +       mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
1430 +#endif
1431 +}
1432 +
1433 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1434 +
1435 +/*
1436 + * ext2_xattr_cache_insert()
1437 + *
1438 + * Create a new entry in the extended attribute cache, and insert
1439 + * it unless such an entry is already in the cache.
1440 + *
1441 + * Returns 0, or a negative error number on failure.
1442 + */
1443 +static int
1444 +ext2_xattr_cache_insert(struct buffer_head *bh)
1445 +{
1446 +       __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
1447 +       struct mb_cache_entry *ce;
1448 +       int error;
1449 +
1450 +       ce = mb_cache_entry_alloc(ext2_xattr_cache);
1451 +       if (!ce)
1452 +               return -ENOMEM;
1453 +       error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
1454 +       if (error) {
1455 +               mb_cache_entry_free(ce);
1456 +               if (error == -EBUSY) {
1457 +                       ea_bdebug(bh, "already in cache (%d cache entries)",
1458 +                               atomic_read(&ext2_xattr_cache->c_entry_count));
1459 +                       error = 0;
1460 +               }
1461 +       } else {
1462 +               ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
1463 +                         atomic_read(&ext2_xattr_cache->c_entry_count));
1464 +               mb_cache_entry_release(ce);
1465 +       }
1466 +       return error;
1467 +}
1468 +
1469 +/*
1470 + * ext2_xattr_cmp()
1471 + *
1472 + * Compare two extended attribute blocks for equality.
1473 + *
1474 + * Returns 0 if the blocks are equal, 1 if they differ, and
1475 + * a negative error number on errors.
1476 + */
1477 +static int
1478 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
1479 +              struct ext2_xattr_header *header2)
1480 +{
1481 +       struct ext2_xattr_entry *entry1, *entry2;
1482 +
1483 +       entry1 = ENTRY(header1+1);
1484 +       entry2 = ENTRY(header2+1);
1485 +       while (!IS_LAST_ENTRY(entry1)) {
1486 +               if (IS_LAST_ENTRY(entry2))
1487 +                       return 1;
1488 +               if (entry1->e_hash != entry2->e_hash ||
1489 +                   entry1->e_name_len != entry2->e_name_len ||
1490 +                   entry1->e_value_size != entry2->e_value_size ||
1491 +                   memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
1492 +                       return 1;
1493 +               if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
1494 +                       return -EIO;
1495 +               if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
1496 +                          (char *)header2 + le16_to_cpu(entry2->e_value_offs),
1497 +                          le32_to_cpu(entry1->e_value_size)))
1498 +                       return 1;
1499 +
1500 +               entry1 = EXT2_XATTR_NEXT(entry1);
1501 +               entry2 = EXT2_XATTR_NEXT(entry2);
1502 +       }
1503 +       if (!IS_LAST_ENTRY(entry2))
1504 +               return 1;
1505 +       return 0;
1506 +}
1507 +
1508 +/*
1509 + * ext2_xattr_cache_find()
1510 + *
1511 + * Find an identical extended attribute block.
1512 + *
1513 + * Returns a pointer to the block found, or NULL if such a block was
1514 + * not found or an error occurred.
1515 + */
1516 +static struct buffer_head *
1517 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
1518 +{
1519 +       __u32 hash = le32_to_cpu(header->h_hash);
1520 +       struct mb_cache_entry *ce;
1521 +
1522 +       if (!header->h_hash)
1523 +               return NULL;  /* never share */
1524 +       ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
1525 +       ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
1526 +       while (ce) {
1527 +               struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
1528 +
1529 +               if (!bh) {
1530 +                       ext2_error(inode->i_sb, "ext2_xattr_cache_find",
1531 +                               "inode %ld: block %ld read error",
1532 +                               inode->i_ino, ce->e_block);
1533 +               } else if (le32_to_cpu(HDR(bh)->h_refcount) >
1534 +                          EXT2_XATTR_REFCOUNT_MAX) {
1535 +                       ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
1536 +                               le32_to_cpu(HDR(bh)->h_refcount),
1537 +                               EXT2_XATTR_REFCOUNT_MAX);
1538 +               } else if (!ext2_xattr_cmp(header, HDR(bh))) {
1539 +                       ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
1540 +                       mb_cache_entry_release(ce);
1541 +                       return bh;
1542 +               }
1543 +               brelse(bh);
1544 +               ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
1545 +       }
1546 +       return NULL;
1547 +}
1548 +
1549 +/*
1550 + * ext2_xattr_cache_remove()
1551 + *
1552 + * Remove the cache entry of a block from the cache. Called when a
1553 + * block becomes invalid.
1554 + */
1555 +static void
1556 +ext2_xattr_cache_remove(struct buffer_head *bh)
1557 +{
1558 +       struct mb_cache_entry *ce;
1559 +
1560 +       ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
1561 +       if (ce) {
1562 +               ea_bdebug(bh, "removing (%d cache entries remaining)",
1563 +                         atomic_read(&ext2_xattr_cache->c_entry_count)-1);
1564 +               mb_cache_entry_free(ce);
1565 +       } else 
1566 +               ea_bdebug(bh, "no cache entry");
1567 +}
1568 +
1569 +#define NAME_HASH_SHIFT 5
1570 +#define VALUE_HASH_SHIFT 16
1571 +
1572 +/*
1573 + * ext2_xattr_hash_entry()
1574 + *
1575 + * Compute the hash of an extended attribute.
1576 + */
1577 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
1578 +                                        struct ext2_xattr_entry *entry)
1579 +{
1580 +       __u32 hash = 0;
1581 +       char *name = entry->e_name;
1582 +       int n;
1583 +
1584 +       for (n=0; n < entry->e_name_len; n++) {
1585 +               hash = (hash << NAME_HASH_SHIFT) ^
1586 +                      (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
1587 +                      *name++;
1588 +       }
1589 +
1590 +       if (entry->e_value_block == 0 && entry->e_value_size != 0) {
1591 +               __u32 *value = (__u32 *)((char *)header +
1592 +                       le16_to_cpu(entry->e_value_offs));
1593 +               for (n = (le32_to_cpu(entry->e_value_size) +
1594 +                    EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
1595 +                       hash = (hash << VALUE_HASH_SHIFT) ^
1596 +                              (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
1597 +                              le32_to_cpu(*value++);
1598 +               }
1599 +       }
1600 +       entry->e_hash = cpu_to_le32(hash);
1601 +}
1602 +
1603 +#undef NAME_HASH_SHIFT
1604 +#undef VALUE_HASH_SHIFT
1605 +
1606 +#define BLOCK_HASH_SHIFT 16
1607 +
1608 +/*
1609 + * ext2_xattr_rehash()
1610 + *
1611 + * Re-compute the extended attribute hash value after an entry has changed.
1612 + */
1613 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
1614 +                             struct ext2_xattr_entry *entry)
1615 +{
1616 +       struct ext2_xattr_entry *here;
1617 +       __u32 hash = 0;
1618 +       
1619 +       ext2_xattr_hash_entry(header, entry);
1620 +       here = ENTRY(header+1);
1621 +       while (!IS_LAST_ENTRY(here)) {
1622 +               if (!here->e_hash) {
1623 +                       /* Block is not shared if an entry's hash value == 0 */
1624 +                       hash = 0;
1625 +                       break;
1626 +               }
1627 +               hash = (hash << BLOCK_HASH_SHIFT) ^
1628 +                      (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
1629 +                      le32_to_cpu(here->e_hash);
1630 +               here = EXT2_XATTR_NEXT(here);
1631 +       }
1632 +       header->h_hash = cpu_to_le32(hash);
1633 +}
1634 +
1635 +#undef BLOCK_HASH_SHIFT
1636 +
1637 +int __init
1638 +init_ext2_xattr(void)
1639 +{
1640 +       ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
1641 +               sizeof(struct mb_cache_entry) +
1642 +               sizeof(struct mb_cache_entry_index), 1, 61);
1643 +       if (!ext2_xattr_cache)
1644 +               return -ENOMEM;
1645 +
1646 +       return 0;
1647 +}
1648 +
1649 +void
1650 +exit_ext2_xattr(void)
1651 +{
1652 +       mb_cache_destroy(ext2_xattr_cache);
1653 +}
1654 +
1655 +#else  /* CONFIG_EXT2_FS_XATTR_SHARING */
1656 +
1657 +int __init
1658 +init_ext2_xattr(void)
1659 +{
1660 +       return 0;
1661 +}
1662 +
1663 +void
1664 +exit_ext2_xattr(void)
1665 +{
1666 +}
1667 +
1668 +#endif  /* CONFIG_EXT2_FS_XATTR_SHARING */
1669 Index: linux-2.4.21-chaos/fs/ext2/xattr_user.c
1670 ===================================================================
1671 --- linux-2.4.21-chaos.orig/fs/ext2/xattr_user.c        2003-01-30 13:24:37.000000000 +0300
1672 +++ linux-2.4.21-chaos/fs/ext2/xattr_user.c     2003-12-14 15:11:46.000000000 +0300
1673 @@ -0,0 +1,103 @@
1674 +/*
1675 + * linux/fs/ext2/xattr_user.c
1676 + * Handler for extended user attributes.
1677 + *
1678 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
1679 + */
1680 +
1681 +#include <linux/module.h>
1682 +#include <linux/string.h>
1683 +#include <linux/fs.h>
1684 +#include <linux/ext2_fs.h>
1685 +#include <linux/ext2_xattr.h>
1686 +
1687 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
1688 +# include <linux/ext2_acl.h>
1689 +#endif
1690 +
1691 +#define XATTR_USER_PREFIX "user."
1692 +
1693 +static size_t
1694 +ext2_xattr_user_list(char *list, struct inode *inode,
1695 +                    const char *name, int name_len)
1696 +{
1697 +       const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
1698 +
1699 +       if (!test_opt(inode->i_sb, XATTR_USER))
1700 +               return 0;
1701 +
1702 +       if (list) {
1703 +               memcpy(list, XATTR_USER_PREFIX, prefix_len);
1704 +               memcpy(list+prefix_len, name, name_len);
1705 +               list[prefix_len + name_len] = '\0';
1706 +       }
1707 +       return prefix_len + name_len + 1;
1708 +}
1709 +
1710 +static int
1711 +ext2_xattr_user_get(struct inode *inode, const char *name,
1712 +                   void *buffer, size_t size)
1713 +{
1714 +       int error;
1715 +
1716 +       if (strcmp(name, "") == 0)
1717 +               return -EINVAL;
1718 +       if (!test_opt(inode->i_sb, XATTR_USER))
1719 +               return -ENOTSUP;
1720 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
1721 +       error = ext2_permission_locked(inode, MAY_READ);
1722 +#else
1723 +       error = permission(inode, MAY_READ);
1724 +#endif
1725 +       if (error)
1726 +               return error;
1727 +
1728 +       return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
1729 +                             buffer, size);
1730 +}
1731 +
1732 +static int
1733 +ext2_xattr_user_set(struct inode *inode, const char *name,
1734 +                   const void *value, size_t size, int flags)
1735 +{
1736 +       int error;
1737 +
1738 +       if (strcmp(name, "") == 0)
1739 +               return -EINVAL;
1740 +       if (!test_opt(inode->i_sb, XATTR_USER))
1741 +               return -ENOTSUP;
1742 +       if ( !S_ISREG(inode->i_mode) &&
1743 +           (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
1744 +               return -EPERM;
1745 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
1746 +       error = ext2_permission_locked(inode, MAY_WRITE);
1747 +#else
1748 +       error = permission(inode, MAY_WRITE);
1749 +#endif
1750 +       if (error)
1751 +               return error;
1752 +
1753 +       return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
1754 +                             value, size, flags);
1755 +}
1756 +
1757 +struct ext2_xattr_handler ext2_xattr_user_handler = {
1758 +       prefix: XATTR_USER_PREFIX,
1759 +       list:   ext2_xattr_user_list,
1760 +       get:    ext2_xattr_user_get,
1761 +       set:    ext2_xattr_user_set,
1762 +};
1763 +
1764 +int __init
1765 +init_ext2_xattr_user(void)
1766 +{
1767 +       return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
1768 +                                  &ext2_xattr_user_handler);
1769 +}
1770 +
1771 +void
1772 +exit_ext2_xattr_user(void)
1773 +{
1774 +       ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
1775 +                             &ext2_xattr_user_handler);
1776 +}
1777 Index: linux-2.4.21-chaos/fs/ext3/Makefile
1778 ===================================================================
1779 --- linux-2.4.21-chaos.orig/fs/ext3/Makefile    2003-12-14 15:09:30.000000000 +0300
1780 +++ linux-2.4.21-chaos/fs/ext3/Makefile 2003-12-14 15:11:46.000000000 +0300
1781 @@ -9,10 +9,10 @@
1782  
1783  O_TARGET := ext3.o
1784  
1785 -export-objs := super.o inode.o
1786 +export-objs := ext3-exports.o
1787  
1788  obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
1789 -               ioctl.o namei.o super.o symlink.o hash.o
1790 +               ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
1791  obj-m    := $(O_TARGET)
1792  
1793  export-objs += xattr.o
1794 Index: linux-2.4.21-chaos/fs/ext3/super.c
1795 ===================================================================
1796 --- linux-2.4.21-chaos.orig/fs/ext3/super.c     2003-12-14 15:09:30.000000000 +0300
1797 +++ linux-2.4.21-chaos/fs/ext3/super.c  2003-12-14 15:11:46.000000000 +0300
1798 @@ -1944,9 +1944,6 @@
1799         unregister_filesystem(&ext3_fs_type);
1800  }
1801  
1802 -EXPORT_SYMBOL(ext3_force_commit);
1803 -EXPORT_SYMBOL(ext3_bread);
1804 -
1805  MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
1806  MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
1807  MODULE_LICENSE("GPL");
1808 Index: linux-2.4.21-chaos/fs/ext3/ext3-exports.c
1809 ===================================================================
1810 --- linux-2.4.21-chaos.orig/fs/ext3/ext3-exports.c      2003-01-30 13:24:37.000000000 +0300
1811 +++ linux-2.4.21-chaos/fs/ext3/ext3-exports.c   2003-12-14 15:11:46.000000000 +0300
1812 @@ -0,0 +1,14 @@
1813 +#include <linux/config.h>
1814 +#include <linux/module.h>
1815 +#include <linux/ext3_fs.h>
1816 +#include <linux/ext3_jbd.h>
1817 +#include <linux/ext3_xattr.h>
1818 +
1819 +EXPORT_SYMBOL(ext3_force_commit);
1820 +EXPORT_SYMBOL(ext3_bread);
1821 +EXPORT_SYMBOL(ext3_journal_abort_handle);
1822 +EXPORT_SYMBOL(ext3_xattr_register);
1823 +EXPORT_SYMBOL(ext3_xattr_unregister);
1824 +EXPORT_SYMBOL(ext3_xattr_get);
1825 +EXPORT_SYMBOL(ext3_xattr_list);
1826 +EXPORT_SYMBOL(ext3_xattr_set);
1827 Index: linux-2.4.21-chaos/fs/ext3/xattr_trusted.c
1828 ===================================================================
1829 --- linux-2.4.21-chaos.orig/fs/ext3/xattr_trusted.c     2003-07-15 04:41:01.000000000 +0400
1830 +++ linux-2.4.21-chaos/fs/ext3/xattr_trusted.c  2003-12-14 15:11:46.000000000 +0300
1831 @@ -50,7 +50,7 @@
1832                 return -EINVAL;
1833         if (!capable(CAP_SYS_ADMIN))
1834                 return -EPERM;
1835 -       return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
1836 +       return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_TRUSTED, name,
1837                               value, size, flags);
1838  }
1839  
1840 Index: linux-2.4.21-chaos/fs/ext3/xattr.c
1841 ===================================================================
1842 --- linux-2.4.21-chaos.orig/fs/ext3/xattr.c     2003-07-30 04:11:55.000000000 +0400
1843 +++ linux-2.4.21-chaos/fs/ext3/xattr.c  2003-12-14 15:11:46.000000000 +0300
1844 @@ -868,7 +868,7 @@
1845  }
1846  
1847  /*
1848 - * ext3_xattr_set()
1849 + * ext3_xattr_set_trans()
1850   *
1851   * Like ext3_xattr_set_handle, but start from an inode. This extended
1852   * attribute modification is a filesystem transaction by itself.
1853 @@ -876,7 +876,7 @@
1854   * Returns 0, or a negative error number on failure.
1855   */
1856  int
1857 -ext3_xattr_set(struct inode *inode, int name_index, const char *name,
1858 +ext3_xattr_set_trans(struct inode *inode, int name_index, const char *name,
1859                 const void *value, size_t value_len, int flags)
1860  {
1861         handle_t *handle;
1862 @@ -895,6 +895,20 @@
1863         return error ? error : error2;
1864  }
1865  
1866 +int
1867 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
1868 +               const char *name, const void *value, size_t value_len,
1869 +               int flags)
1870 +{
1871 +       int error;
1872 +
1873 +       lock_kernel();
1874 +       error = ext3_xattr_set_handle(handle, inode, name_index, name,
1875 +                                             value, value_len, flags);
1876 +       unlock_kernel();
1877 +       return error;
1878 +}
1879 +
1880  /*
1881   * ext3_xattr_delete_inode()
1882   *
1883 Index: linux-2.4.21-chaos/fs/ext3/xattr_user.c
1884 ===================================================================
1885 --- linux-2.4.21-chaos.orig/fs/ext3/xattr_user.c        2003-07-30 04:11:55.000000000 +0400
1886 +++ linux-2.4.21-chaos/fs/ext3/xattr_user.c     2003-12-14 15:26:58.000000000 +0300
1887 @@ -70,7 +70,7 @@
1888         if (error)
1889                 return error;
1890    
1891 -       return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
1892 +       return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_USER, name,
1893                               value, size, flags);
1894  }
1895  
1896 Index: linux-2.4.21-chaos/include/linux/errno.h
1897 ===================================================================
1898 --- linux-2.4.21-chaos.orig/include/linux/errno.h       2003-07-15 04:41:12.000000000 +0400
1899 +++ linux-2.4.21-chaos/include/linux/errno.h    2003-12-14 15:11:46.000000000 +0300
1900 @@ -26,4 +26,8 @@
1901  
1902  #endif
1903  
1904 +/* Defined for extended attributes */
1905 +#define ENOATTR ENODATA                /* No such attribute */
1906 +#define ENOTSUP EOPNOTSUPP     /* Operation not supported */
1907 +
1908  #endif
1909 Index: linux-2.4.21-chaos/include/linux/ext2_fs.h
1910 ===================================================================
1911 --- linux-2.4.21-chaos.orig/include/linux/ext2_fs.h     2003-12-05 16:54:33.000000000 +0300
1912 +++ linux-2.4.21-chaos/include/linux/ext2_fs.h  2003-12-14 15:13:54.000000000 +0300
1913 @@ -57,8 +57,6 @@
1914   */
1915  #define        EXT2_BAD_INO             1      /* Bad blocks inode */
1916  #define EXT2_ROOT_INO           2      /* Root inode */
1917 -#define EXT2_ACL_IDX_INO        3      /* ACL inode */
1918 -#define EXT2_ACL_DATA_INO       4      /* ACL inode */
1919  #define EXT2_BOOT_LOADER_INO    5      /* Boot loader inode */
1920  #define EXT2_UNDEL_DIR_INO      6      /* Undelete directory inode */
1921  
1922 @@ -86,7 +84,6 @@
1923  #else
1924  # define EXT2_BLOCK_SIZE(s)            (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
1925  #endif
1926 -#define EXT2_ACLE_PER_BLOCK(s)         (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
1927  #define        EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
1928  #ifdef __KERNEL__
1929  # define EXT2_BLOCK_SIZE_BITS(s)       ((s)->s_blocksize_bits)
1930 @@ -121,28 +118,6 @@
1931  #endif
1932  
1933  /*
1934 - * ACL structures
1935 - */
1936 -struct ext2_acl_header /* Header of Access Control Lists */
1937 -{
1938 -       __u32   aclh_size;
1939 -       __u32   aclh_file_count;
1940 -       __u32   aclh_acle_count;
1941 -       __u32   aclh_first_acle;
1942 -};
1943 -
1944 -struct ext2_acl_entry  /* Access Control List Entry */
1945 -{
1946 -       __u32   acle_size;
1947 -       __u16   acle_perms;     /* Access permissions */
1948 -       __u16   acle_type;      /* Type of entry */
1949 -       __u16   acle_tag;       /* User or group identity */
1950 -       __u16   acle_pad1;
1951 -       __u32   acle_next;      /* Pointer on next entry for the */
1952 -                                       /* same inode or on next free entry */
1953 -};
1954 -
1955 -/*
1956   * Structure of a blocks group descriptor
1957   */
1958  struct ext2_group_desc
1959 @@ -314,6 +289,7 @@
1960  #define EXT2_MOUNT_ERRORS_PANIC                0x0040  /* Panic on errors */
1961  #define EXT2_MOUNT_MINIX_DF            0x0080  /* Mimics the Minix statfs */
1962  #define EXT2_MOUNT_NO_UID32            0x0200  /* Disable 32-bit UIDs */
1963 +#define EXT2_MOUNT_XATTR_USER          0x4000  /* Extended user attributes */
1964  
1965  #define clear_opt(o, opt)              o &= ~EXT2_MOUNT_##opt
1966  #define set_opt(o, opt)                        o |= EXT2_MOUNT_##opt
1967 @@ -397,6 +373,7 @@
1968  
1969  #ifdef __KERNEL__
1970  #define EXT2_SB(sb)    (&((sb)->u.ext2_sb))
1971 +#define EXT2_I(inode)  (&((inode)->u.ext2_i))
1972  #else
1973  /* Assume that user mode programs are passing in an ext2fs superblock, not
1974   * a kernel struct super_block.  This will allow us to call the feature-test
1975 @@ -466,7 +443,7 @@
1976  #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008
1977  #define EXT2_FEATURE_INCOMPAT_ANY              0xffffffff
1978  
1979 -#define EXT2_FEATURE_COMPAT_SUPP       0
1980 +#define EXT2_FEATURE_COMPAT_SUPP       EXT2_FEATURE_COMPAT_EXT_ATTR
1981  #define EXT2_FEATURE_INCOMPAT_SUPP     EXT2_FEATURE_INCOMPAT_FILETYPE
1982  #define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
1983                                          EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
1984 @@ -624,8 +601,10 @@
1985  
1986  /* namei.c */
1987  extern struct inode_operations ext2_dir_inode_operations;
1988 +extern struct inode_operations ext2_special_inode_operations;
1989  
1990  /* symlink.c */
1991 +extern struct inode_operations ext2_symlink_inode_operations;
1992  extern struct inode_operations ext2_fast_symlink_inode_operations;
1993  
1994  #endif /* __KERNEL__ */
1995 Index: linux-2.4.21-chaos/include/linux/ext2_xattr.h
1996 ===================================================================
1997 --- linux-2.4.21-chaos.orig/include/linux/ext2_xattr.h  2003-01-30 13:24:37.000000000 +0300
1998 +++ linux-2.4.21-chaos/include/linux/ext2_xattr.h       2003-12-14 15:13:54.000000000 +0300
1999 @@ -0,0 +1,157 @@
2000 +/*
2001 +  File: linux/ext2_xattr.h
2002 +
2003 +  On-disk format of extended attributes for the ext2 filesystem.
2004 +
2005 +  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
2006 +*/
2007 +
2008 +#include <linux/config.h>
2009 +#include <linux/init.h>
2010 +#include <linux/xattr.h>
2011 +
2012 +/* Magic value in attribute blocks */
2013 +#define EXT2_XATTR_MAGIC               0xEA020000
2014 +
2015 +/* Maximum number of references to one attribute block */
2016 +#define EXT2_XATTR_REFCOUNT_MAX                1024
2017 +
2018 +/* Name indexes */
2019 +#define EXT2_XATTR_INDEX_MAX                   10
2020 +#define EXT2_XATTR_INDEX_USER                  1
2021 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS      2
2022 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT     3
2023 +
2024 +struct ext2_xattr_header {
2025 +       __u32   h_magic;        /* magic number for identification */
2026 +       __u32   h_refcount;     /* reference count */
2027 +       __u32   h_blocks;       /* number of disk blocks used */
2028 +       __u32   h_hash;         /* hash value of all attributes */
2029 +       __u32   h_reserved[4];  /* zero right now */
2030 +};
2031 +
2032 +struct ext2_xattr_entry {
2033 +       __u8    e_name_len;     /* length of name */
2034 +       __u8    e_name_index;   /* attribute name index */
2035 +       __u16   e_value_offs;   /* offset in disk block of value */
2036 +       __u32   e_value_block;  /* disk block attribute is stored on (n/i) */
2037 +       __u32   e_value_size;   /* size of attribute value */
2038 +       __u32   e_hash;         /* hash value of name and value */
2039 +       char    e_name[0];      /* attribute name */
2040 +};
2041 +
2042 +#define EXT2_XATTR_PAD_BITS            2
2043 +#define EXT2_XATTR_PAD         (1<<EXT2_XATTR_PAD_BITS)
2044 +#define EXT2_XATTR_ROUND               (EXT2_XATTR_PAD-1)
2045 +#define EXT2_XATTR_LEN(name_len) \
2046 +       (((name_len) + EXT2_XATTR_ROUND + \
2047 +       sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
2048 +#define EXT2_XATTR_NEXT(entry) \
2049 +       ( (struct ext2_xattr_entry *)( \
2050 +         (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
2051 +#define EXT2_XATTR_SIZE(size) \
2052 +       (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
2053 +
2054 +#ifdef __KERNEL__
2055 +
2056 +# ifdef CONFIG_EXT2_FS_XATTR
2057 +
2058 +struct ext2_xattr_handler {
2059 +       char *prefix;
2060 +       size_t (*list)(char *list, struct inode *inode, const char *name,
2061 +                      int name_len);
2062 +       int (*get)(struct inode *inode, const char *name, void *buffer,
2063 +                  size_t size);
2064 +       int (*set)(struct inode *inode, const char *name, const void *buffer,
2065 +                  size_t size, int flags);
2066 +};
2067 +
2068 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
2069 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
2070 +
2071 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
2072 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
2073 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
2074 +extern int ext2_removexattr(struct dentry *, const char *);
2075 +
2076 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
2077 +extern int ext2_xattr_list(struct inode *, char *, size_t);
2078 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
2079 +
2080 +extern void ext2_xattr_delete_inode(struct inode *);
2081 +extern void ext2_xattr_put_super(struct super_block *);
2082 +
2083 +extern int init_ext2_xattr(void) __init;
2084 +extern void exit_ext2_xattr(void);
2085 +
2086 +# else  /* CONFIG_EXT2_FS_XATTR */
2087 +#  define ext2_setxattr                NULL
2088 +#  define ext2_getxattr                NULL
2089 +#  define ext2_listxattr       NULL
2090 +#  define ext2_removexattr     NULL
2091 +
2092 +static inline int
2093 +ext2_xattr_get(struct inode *inode, int name_index,
2094 +              const char *name, void *buffer, size_t size)
2095 +{
2096 +       return -ENOTSUP;
2097 +}
2098 +
2099 +static inline int
2100 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
2101 +{
2102 +       return -ENOTSUP;
2103 +}
2104 +
2105 +static inline int
2106 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
2107 +              const void *value, size_t size, int flags)
2108 +{
2109 +       return -ENOTSUP;
2110 +}
2111 +
2112 +static inline void
2113 +ext2_xattr_delete_inode(struct inode *inode)
2114 +{
2115 +}
2116 +
2117 +static inline void
2118 +ext2_xattr_put_super(struct super_block *sb)
2119 +{
2120 +}
2121 +
2122 +static inline int
2123 +init_ext2_xattr(void)
2124 +{
2125 +       return 0;
2126 +}
2127 +
2128 +static inline void
2129 +exit_ext2_xattr(void)
2130 +{
2131 +}
2132 +
2133 +# endif  /* CONFIG_EXT2_FS_XATTR */
2134 +
2135 +# ifdef CONFIG_EXT2_FS_XATTR_USER
2136 +
2137 +extern int init_ext2_xattr_user(void) __init;
2138 +extern void exit_ext2_xattr_user(void);
2139 +
2140 +# else  /* CONFIG_EXT2_FS_XATTR_USER */
2141 +
2142 +static inline int
2143 +init_ext2_xattr_user(void)
2144 +{
2145 +       return 0;
2146 +}
2147 +
2148 +static inline void
2149 +exit_ext2_xattr_user(void)
2150 +{
2151 +}
2152 +
2153 +# endif  /* CONFIG_EXT2_FS_XATTR_USER */
2154 +
2155 +#endif  /* __KERNEL__ */
2156 +
2157 Index: linux-2.4.21-chaos/include/linux/ext3_xattr.h
2158 ===================================================================
2159 --- linux-2.4.21-chaos.orig/include/linux/ext3_xattr.h  2003-12-05 16:54:33.000000000 +0300
2160 +++ linux-2.4.21-chaos/include/linux/ext3_xattr.h       2003-12-14 15:21:13.000000000 +0300
2161 @@ -82,8 +82,10 @@
2162  extern int ext3_xattr_list(struct inode *, char *, size_t);
2163  extern int ext3_xattr_set_handle(handle_t *handle, struct inode *, int,
2164                                  const char *, const void *, size_t, int);
2165 -extern int ext3_xattr_set(struct inode *, int, const char *, const void *,
2166 +extern int ext3_xattr_set_trans(struct inode *, int, const char *, const void *,
2167                           size_t, int);
2168 +extern int ext3_xattr_set(handle_t *, struct inode *, int, const char *,
2169 +                               const void *, size_t, int);
2170  
2171  extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
2172  extern void ext3_xattr_put_super(struct super_block *);