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