Whamcloud - gitweb
land v0.9.1 on HEAD, in preparation for a 1.0.x branch
[fs/lustre-release.git] / lustre / kernel_patches / patches / linux-2.4.20-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/m68k/defconfig           |    7 
9  arch/mips/defconfig           |    7 
10  arch/mips64/defconfig         |    7 
11  arch/ppc/defconfig            |   14 
12  arch/ppc64/kernel/misc.S      |    2 
13  arch/s390/defconfig           |    7 
14  arch/s390/kernel/entry.S      |   24 
15  arch/s390x/defconfig          |    7 
16  arch/s390x/kernel/entry.S     |   24 
17  arch/s390x/kernel/wrapper32.S |   92 +++
18  arch/sparc/defconfig          |    7 
19  arch/sparc/kernel/systbls.S   |   10 
20  arch/sparc64/defconfig        |    7 
21  arch/sparc64/kernel/systbls.S |   20 
22  fs/Config.in                  |   14 
23  fs/Makefile                   |    3 
24  fs/ext2/Makefile              |    4 
25  fs/ext2/file.c                |    5 
26  fs/ext2/ialloc.c              |    2 
27  fs/ext2/inode.c               |   34 -
28  fs/ext2/namei.c               |   14 
29  fs/ext2/super.c               |   29 
30  fs/ext2/symlink.c             |   14 
31  fs/ext2/xattr.c               | 1212 +++++++++++++++++++++++++++++++++++++++++
32  fs/ext2/xattr_user.c          |  103 +++
33  fs/ext3/Makefile              |   10 
34  fs/ext3/ext3-exports.c        |   13 
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-ppc64/unistd.h    |    2 
48  include/asm-s390/unistd.h     |   15 
49  include/asm-s390x/unistd.h    |   15 
50  include/asm-sparc/unistd.h    |   24 
51  include/asm-sparc64/unistd.h  |   24 
52  include/linux/cache_def.h     |   15 
53  include/linux/errno.h         |    4 
54  include/linux/ext2_fs.h       |   31 -
55  include/linux/ext2_xattr.h    |  157 +++++
56  include/linux/ext3_fs.h       |   31 -
57  include/linux/ext3_jbd.h      |    8 
58  include/linux/ext3_xattr.h    |  157 +++++
59  include/linux/fs.h            |    2 
60  include/linux/mbcache.h       |   69 ++
61  kernel/ksyms.c                |    4 
62  mm/vmscan.c                   |   36 +
63  62 files changed, 4344 insertions(+), 183 deletions(-)
64
65 --- kernel-2.4.20-6chaos_18_7/Documentation/Configure.help~linux-2.4.20-xattr-0.8.54-chaos      2003-06-23 10:39:21.000000000 -0600
66 +++ kernel-2.4.20-6chaos_18_7-braam/Documentation/Configure.help        2003-07-12 15:34:44.000000000 -0600
67 @@ -15253,6 +15253,39 @@ CONFIG_EXT2_FS
68    be compiled as a module, and so this could be dangerous.  Most
69    everyone wants to say Y here.
70  
71 +Ext2 extended attributes
72 +CONFIG_EXT2_FS_XATTR
73 +  Extended attributes are name:value pairs associated with inodes by
74 +  the kernel or by users (see the attr(5) manual page, or visit
75 +  <http://acl.bestbits.at/> for details).
76 +
77 +  If unsure, say N.
78 +
79 +Ext2 extended attribute block sharing
80 +CONFIG_EXT2_FS_XATTR_SHARING
81 +  This options enables code for sharing identical extended attribute
82 +  blocks among multiple inodes.
83 +
84 +  Usually, say Y.
85 +
86 +Ext2 extended user attributes
87 +CONFIG_EXT2_FS_XATTR_USER
88 +  This option enables extended user attributes on ext2. Processes can
89 +  associate extended user attributes with inodes to store additional
90 +  information such as the character encoding of files, etc. (see the
91 +  attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
92 +
93 +  If unsure, say N.
94 +
95 +Ext2 trusted extended attributes
96 +CONFIG_EXT2_FS_XATTR_TRUSTED
97 +  This option enables extended attributes on ext2 that are accessible
98 +  (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
99 +  is only the super user. Trusted extended attributes are meant for
100 +  implementing system/security services.
101 +
102 +  If unsure, say N.
103 +
104  Ext3 journalling file system support (EXPERIMENTAL)
105  CONFIG_EXT3_FS
106    This is the journalling version of the Second extended file system
107 @@ -15285,6 +15318,39 @@ CONFIG_EXT3_FS
108    of your root partition (the one containing the directory /) cannot
109    be compiled as a module, and so this may be dangerous.
110  
111 +Ext3 extended attributes
112 +CONFIG_EXT3_FS_XATTR
113 +  Extended attributes are name:value pairs associated with inodes by
114 +  the kernel or by users (see the attr(5) manual page, or visit
115 +  <http://acl.bestbits.at/> for details).
116 +
117 +  If unsure, say N.
118 +
119 +Ext3 extended attribute block sharing
120 +CONFIG_EXT3_FS_XATTR_SHARING
121 +  This options enables code for sharing identical extended attribute
122 +  blocks among multiple inodes.
123 +
124 +  Usually, say Y.
125 +
126 +Ext3 extended user attributes
127 +CONFIG_EXT3_FS_XATTR_USER
128 +  This option enables extended user attributes on ext3. Processes can
129 +  associate extended user attributes with inodes to store additional
130 +  information such as the character encoding of files, etc. (see the
131 +  attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
132 +
133 +  If unsure, say N.
134 +
135 +Ext3 trusted extended attributes
136 +CONFIG_EXT3_FS_XATTR_TRUSTED
137 +  This option enables extended attributes on ext3 that are accessible
138 +  (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
139 +  is only the super user. Trusted extended attributes are meant for
140 +  implementing system/security services.
141 +
142 +  If unsure, say N.
143 +
144  Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
145  CONFIG_JBD
146    This is a generic journalling layer for block devices.  It is
147 --- kernel-2.4.20-6chaos_18_7/arch/alpha/defconfig~linux-2.4.20-xattr-0.8.54-chaos      2002-05-07 15:53:54.000000000 -0600
148 +++ kernel-2.4.20-6chaos_18_7-braam/arch/alpha/defconfig        2003-07-12 15:34:44.000000000 -0600
149 @@ -1,6 +1,13 @@
150  #
151  # Automatically generated make config: don't edit
152  #
153 +# CONFIG_EXT3_FS_XATTR is not set
154 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
155 +# CONFIG_EXT3_FS_XATTR_USER is not set
156 +# CONFIG_EXT2_FS_XATTR is not set
157 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
158 +# CONFIG_EXT2_FS_XATTR_USER is not set
159 +# CONFIG_FS_MBCACHE is not set
160  CONFIG_ALPHA=y
161  # CONFIG_UID16 is not set
162  # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
163 --- kernel-2.4.20-6chaos_18_7/arch/alpha/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:11:53.000000000 -0600
164 +++ kernel-2.4.20-6chaos_18_7-braam/arch/alpha/kernel/entry.S   2003-07-12 15:34:44.000000000 -0600
165 @@ -1162,6 +1162,18 @@ sys_call_table:
166         .quad sys_readahead
167         .quad sys_ni_syscall                    /* 380, sys_security */
168         .quad sys_tkill
169 +       .quad sys_setxattr
170 +       .quad sys_lsetxattr
171 +       .quad sys_fsetxattr
172 +       .quad sys_getxattr                      /* 385 */
173 +       .quad sys_lgetxattr
174 +       .quad sys_fgetxattr
175 +       .quad sys_listxattr
176 +       .quad sys_llistxattr
177 +       .quad sys_flistxattr                    /* 390 */
178 +       .quad sys_removexattr
179 +       .quad sys_lremovexattr
180 +       .quad sys_fremovexattr
181  
182  /* Remember to update everything, kids.  */
183  .ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
184 --- kernel-2.4.20-6chaos_18_7/arch/arm/defconfig~linux-2.4.20-xattr-0.8.54-chaos        2002-05-07 15:53:56.000000000 -0600
185 +++ kernel-2.4.20-6chaos_18_7-braam/arch/arm/defconfig  2003-07-12 15:34:44.000000000 -0600
186 @@ -1,6 +1,13 @@
187  #
188  # Automatically generated make config: don't edit
189  #
190 +# CONFIG_EXT3_FS_XATTR is not set
191 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
192 +# CONFIG_EXT3_FS_XATTR_USER is not set
193 +# CONFIG_EXT2_FS_XATTR is not set
194 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
195 +# CONFIG_EXT2_FS_XATTR_USER is not set
196 +# CONFIG_FS_MBCACHE is not set
197  CONFIG_ARM=y
198  # CONFIG_EISA is not set
199  # CONFIG_SBUS is not set
200 --- kernel-2.4.20-6chaos_18_7/arch/arm/kernel/calls.S~linux-2.4.20-xattr-0.8.54-chaos   2002-09-25 11:09:16.000000000 -0600
201 +++ kernel-2.4.20-6chaos_18_7-braam/arch/arm/kernel/calls.S     2003-07-12 15:34:44.000000000 -0600
202 @@ -240,18 +240,18 @@ __syscall_start:
203                 .long   SYMBOL_NAME(sys_ni_syscall) /* Security */
204                 .long   SYMBOL_NAME(sys_gettid)
205  /* 225 */      .long   SYMBOL_NAME(sys_readahead)
206 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_setxattr */
207 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_lsetxattr */
208 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_fsetxattr */
209 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_getxattr */
210 -/* 230 */      .long   SYMBOL_NAME(sys_ni_syscall) /* sys_lgetxattr */
211 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_fgetxattr */
212 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_listxattr */
213 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_llistxattr */
214 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_flistxattr */
215 -/* 235 */      .long   SYMBOL_NAME(sys_ni_syscall) /* sys_removexattr */
216 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_lremovexattr */
217 -               .long   SYMBOL_NAME(sys_ni_syscall) /* sys_fremovexattr */
218 +               .long   SYMBOL_NAME(sys_setxattr)
219 +               .long   SYMBOL_NAME(sys_lsetxattr)
220 +               .long   SYMBOL_NAME(sys_fsetxattr)
221 +               .long   SYMBOL_NAME(sys_getxattr)
222 +/* 230 */      .long   SYMBOL_NAME(sys_lgetxattr)
223 +               .long   SYMBOL_NAME(sys_fgetxattr)
224 +               .long   SYMBOL_NAME(sys_listxattr)
225 +               .long   SYMBOL_NAME(sys_llistxattr)
226 +               .long   SYMBOL_NAME(sys_flistxattr)
227 +/* 235 */      .long   SYMBOL_NAME(sys_removexattr)
228 +               .long   SYMBOL_NAME(sys_lremovexattr)
229 +               .long   SYMBOL_NAME(sys_fremovexattr)
230                 .long   SYMBOL_NAME(sys_tkill)
231                 /*
232                  * Please check 2.5 _before_ adding calls here,
233 --- kernel-2.4.20-6chaos_18_7/arch/i386/defconfig~linux-2.4.20-xattr-0.8.54-chaos       2003-05-15 21:12:00.000000000 -0600
234 +++ kernel-2.4.20-6chaos_18_7-braam/arch/i386/defconfig 2003-07-12 15:34:44.000000000 -0600
235 @@ -1,6 +1,13 @@
236  #
237  # Automatically generated make config: don't edit
238  #
239 +# CONFIG_EXT3_FS_XATTR is not set
240 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
241 +# CONFIG_EXT3_FS_XATTR_USER is not set
242 +# CONFIG_EXT2_FS_XATTR is not set
243 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
244 +# CONFIG_EXT2_FS_XATTR_USER is not set
245 +# CONFIG_FS_MBCACHE is not set
246  CONFIG_X86=y
247  CONFIG_ISA=y
248  # CONFIG_SBUS is not set
249 --- kernel-2.4.20-6chaos_18_7/arch/ia64/defconfig~linux-2.4.20-xattr-0.8.54-chaos       2003-05-15 21:12:04.000000000 -0600
250 +++ kernel-2.4.20-6chaos_18_7-braam/arch/ia64/defconfig 2003-07-12 15:34:44.000000000 -0600
251 @@ -1,6 +1,13 @@
252  #
253  # Automatically generated make config: don't edit
254  #
255 +# CONFIG_EXT3_FS_XATTR is not set
256 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
257 +# CONFIG_EXT3_FS_XATTR_USER is not set
258 +# CONFIG_EXT2_FS_XATTR is not set
259 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
260 +# CONFIG_EXT2_FS_XATTR_USER is not set
261 +# CONFIG_FS_MBCACHE is not set
262  
263  #
264  # Code maturity level options
265 --- kernel-2.4.20-6chaos_18_7/arch/m68k/defconfig~linux-2.4.20-xattr-0.8.54-chaos       2002-05-07 15:53:55.000000000 -0600
266 +++ kernel-2.4.20-6chaos_18_7-braam/arch/m68k/defconfig 2003-07-12 15:34:44.000000000 -0600
267 @@ -1,6 +1,13 @@
268  #
269  # Automatically generated make config: don't edit
270  #
271 +# CONFIG_EXT3_FS_XATTR is not set
272 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
273 +# CONFIG_EXT3_FS_XATTR_USER is not set
274 +# CONFIG_EXT2_FS_XATTR is not set
275 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
276 +# CONFIG_EXT2_FS_XATTR_USER is not set
277 +# CONFIG_FS_MBCACHE is not set
278  CONFIG_UID16=y
279  
280  #
281 --- kernel-2.4.20-6chaos_18_7/arch/mips/defconfig~linux-2.4.20-xattr-0.8.54-chaos       2003-02-14 15:58:06.000000000 -0700
282 +++ kernel-2.4.20-6chaos_18_7-braam/arch/mips/defconfig 2003-07-12 15:34:44.000000000 -0600
283 @@ -1,6 +1,13 @@
284  #
285  # Automatically generated make config: don't edit
286  #
287 +# CONFIG_EXT3_FS_XATTR is not set
288 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
289 +# CONFIG_EXT3_FS_XATTR_USER is not set
290 +# CONFIG_EXT2_FS_XATTR is not set
291 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
292 +# CONFIG_EXT2_FS_XATTR_USER is not set
293 +# CONFIG_FS_MBCACHE is not set
294  CONFIG_MIPS=y
295  CONFIG_MIPS32=y
296  # CONFIG_MIPS64 is not set
297 --- kernel-2.4.20-6chaos_18_7/arch/mips64/defconfig~linux-2.4.20-xattr-0.8.54-chaos     2003-02-14 15:58:11.000000000 -0700
298 +++ kernel-2.4.20-6chaos_18_7-braam/arch/mips64/defconfig       2003-07-12 15:34:44.000000000 -0600
299 @@ -1,6 +1,13 @@
300  #
301  # Automatically generated make config: don't edit
302  #
303 +# CONFIG_EXT3_FS_XATTR is not set
304 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
305 +# CONFIG_EXT3_FS_XATTR_USER is not set
306 +# CONFIG_EXT2_FS_XATTR is not set
307 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
308 +# CONFIG_EXT2_FS_XATTR_USER is not set
309 +# CONFIG_FS_MBCACHE is not set
310  CONFIG_MIPS=y
311  # CONFIG_MIPS32 is not set
312  CONFIG_MIPS64=y
313 --- kernel-2.4.20-6chaos_18_7/arch/ppc/defconfig~linux-2.4.20-xattr-0.8.54-chaos        2003-05-15 21:12:20.000000000 -0600
314 +++ kernel-2.4.20-6chaos_18_7-braam/arch/ppc/defconfig  2003-07-12 15:34:44.000000000 -0600
315 @@ -1,6 +1,20 @@
316  #
317  # Automatically generated make config: don't edit
318  #
319 +# CONFIG_EXT3_FS_XATTR is not set
320 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
321 +# CONFIG_EXT3_FS_XATTR_USER is not set
322 +# CONFIG_EXT2_FS_XATTR is not set
323 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
324 +# CONFIG_EXT2_FS_XATTR_USER is not set
325 +# CONFIG_FS_MBCACHE is not set
326 +# CONFIG_EXT3_FS_XATTR is not set
327 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
328 +# CONFIG_EXT3_FS_XATTR_USER is not set
329 +# CONFIG_EXT2_FS_XATTR is not set
330 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
331 +# CONFIG_EXT2_FS_XATTR_USER is not set
332 +# CONFIG_FS_MBCACHE is not set
333  # CONFIG_UID16 is not set
334  # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
335  CONFIG_RWSEM_XCHGADD_ALGORITHM=y
336 --- kernel-2.4.20-6chaos_18_7/arch/ppc64/kernel/misc.S~linux-2.4.20-xattr-0.8.54-chaos  2003-02-14 15:58:20.000000000 -0700
337 +++ kernel-2.4.20-6chaos_18_7-braam/arch/ppc64/kernel/misc.S    2003-07-12 15:34:44.000000000 -0600
338 @@ -731,6 +731,7 @@ _GLOBAL(sys_call_table32)
339         .llong .sys_gettid              /* 207 */
340  #if 0 /* Reserved syscalls */
341         .llong .sys_tkill               /* 208 */
342 +#endif
343         .llong .sys_setxattr
344         .llong .sys_lsetxattr   /* 210 */
345         .llong .sys_fsetxattr
346 @@ -743,6 +744,7 @@ _GLOBAL(sys_call_table32)
347         .llong .sys_removexattr
348         .llong .sys_lremovexattr
349         .llong .sys_fremovexattr        /* 220 */
350 +#if 0 /* Reserved syscalls */
351         .llong .sys_futex
352  #endif
353         .llong .sys_perfmonctl   /* Put this here for now ... */
354 --- kernel-2.4.20-6chaos_18_7/arch/s390/defconfig~linux-2.4.20-xattr-0.8.54-chaos       2003-02-14 15:58:20.000000000 -0700
355 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/defconfig 2003-07-12 15:34:44.000000000 -0600
356 @@ -1,6 +1,13 @@
357  #
358  # Automatically generated make config: don't edit
359  #
360 +# CONFIG_EXT3_FS_XATTR is not set
361 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
362 +# CONFIG_EXT3_FS_XATTR_USER is not set
363 +# CONFIG_EXT2_FS_XATTR is not set
364 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
365 +# CONFIG_EXT2_FS_XATTR_USER is not set
366 +# CONFIG_FS_MBCACHE is not set
367  # CONFIG_ISA is not set
368  # CONFIG_EISA is not set
369  # CONFIG_MCA is not set
370 --- kernel-2.4.20-6chaos_18_7/arch/s390/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos  2003-02-14 15:58:20.000000000 -0700
371 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/kernel/entry.S    2003-07-12 15:34:44.000000000 -0600
372 @@ -558,18 +558,18 @@ sys_call_table:
373          .long  sys_fcntl64 
374         .long  sys_ni_syscall
375         .long  sys_ni_syscall
376 -       .long  sys_ni_syscall            /* 224 - reserved for setxattr  */
377 -       .long  sys_ni_syscall            /* 225 - reserved for lsetxattr */
378 -       .long  sys_ni_syscall            /* 226 - reserved for fsetxattr */
379 -       .long  sys_ni_syscall            /* 227 - reserved for getxattr  */
380 -       .long  sys_ni_syscall            /* 228 - reserved for lgetxattr */
381 -       .long  sys_ni_syscall            /* 229 - reserved for fgetxattr */
382 -       .long  sys_ni_syscall            /* 230 - reserved for listxattr */
383 -       .long  sys_ni_syscall            /* 231 - reserved for llistxattr */
384 -       .long  sys_ni_syscall            /* 232 - reserved for flistxattr */
385 -       .long  sys_ni_syscall            /* 233 - reserved for removexattr */
386 -       .long  sys_ni_syscall            /* 234 - reserved for lremovexattr */
387 -       .long  sys_ni_syscall            /* 235 - reserved for fremovexattr */
388 +       .long  sys_setxattr
389 +       .long  sys_lsetxattr            /* 225 */
390 +       .long  sys_fsetxattr
391 +       .long  sys_getxattr
392 +       .long  sys_lgetxattr
393 +       .long  sys_fgetxattr
394 +       .long  sys_listxattr            /* 230 */
395 +       .long  sys_llistxattr
396 +       .long  sys_flistxattr
397 +       .long  sys_removexattr
398 +       .long  sys_lremovexattr
399 +       .long  sys_fremovexattr         /* 235 */
400         .long  sys_gettid
401         .long  sys_tkill
402         .rept  255-237
403 --- kernel-2.4.20-6chaos_18_7/arch/s390x/defconfig~linux-2.4.20-xattr-0.8.54-chaos      2003-02-14 15:58:21.000000000 -0700
404 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/defconfig        2003-07-12 15:34:44.000000000 -0600
405 @@ -1,6 +1,13 @@
406  #
407  # Automatically generated make config: don't edit
408  #
409 +# CONFIG_EXT3_FS_XATTR is not set
410 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
411 +# CONFIG_EXT3_FS_XATTR_USER is not set
412 +# CONFIG_EXT2_FS_XATTR is not set
413 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
414 +# CONFIG_EXT2_FS_XATTR_USER is not set
415 +# CONFIG_FS_MBCACHE is not set
416  # CONFIG_ISA is not set
417  # CONFIG_EISA is not set
418  # CONFIG_MCA is not set
419 --- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:21.000000000 -0700
420 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/entry.S   2003-07-12 15:34:44.000000000 -0600
421 @@ -591,18 +591,18 @@ sys_call_table:
422         .long  SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
423         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
424         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
425 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr  */
426 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
427 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
428 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr  */
429 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
430 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
431 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
432 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
433 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
434 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
435 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
436 -       .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
437 +       .long  SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
438 +       .long  SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper)   /* 225 */
439 +       .long  SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
440 +       .long  SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
441 +       .long  SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
442 +       .long  SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
443 +       .long  SYSCALL(sys_listxattr,sys32_listxattr_wrapper)   /* 230 */
444 +       .long  SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
445 +       .long  SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
446 +       .long  SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
447 +       .long  SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
448 +       .long  SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
449         .long  SYSCALL(sys_gettid,sys_gettid)
450         .long  SYSCALL(sys_tkill,sys_tkill)
451         .rept  255-237
452 --- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/wrapper32.S~linux-2.4.20-xattr-0.8.54-chaos     2002-05-07 15:53:59.000000000 -0600
453 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/wrapper32.S       2003-07-12 15:34:44.000000000 -0600
454 @@ -1091,3 +1091,95 @@ sys32_fstat64_wrapper:
455         llgtr   %r3,%r3                 # struct stat64 *
456         llgfr   %r4,%r4                 # long
457         jg      sys32_fstat64           # branch to system call
458 +
459 +       .globl  sys32_setxattr_wrapper
460 +sys32_setxattr_wrapper:
461 +       llgtr   %r2,%r2                 # char *
462 +       llgtr   %r3,%r3                 # char *
463 +       llgtr   %r4,%r4                 # void *
464 +       llgfr   %r5,%r5                 # size_t
465 +       lgfr    %r6,%r6                 # int
466 +       jg      sys_setxattr
467 +
468 +       .globl  sys32_lsetxattr_wrapper
469 +sys32_lsetxattr_wrapper:
470 +       llgtr   %r2,%r2                 # char *
471 +       llgtr   %r3,%r3                 # char *
472 +       llgtr   %r4,%r4                 # void *
473 +       llgfr   %r5,%r5                 # size_t
474 +       lgfr    %r6,%r6                 # int
475 +       jg      sys_lsetxattr
476 +
477 +       .globl  sys32_fsetxattr_wrapper
478 +sys32_fsetxattr_wrapper:
479 +       lgfr    %r2,%r2                 # int
480 +       llgtr   %r3,%r3                 # char *
481 +       llgtr   %r4,%r4                 # void *
482 +       llgfr   %r5,%r5                 # size_t
483 +       lgfr    %r6,%r6                 # int
484 +       jg      sys_fsetxattr
485 +
486 +       .globl  sys32_getxattr_wrapper
487 +sys32_getxattr_wrapper:
488 +       llgtr   %r2,%r2                 # char *
489 +       llgtr   %r3,%r3                 # char *
490 +       llgtr   %r4,%r4                 # void *
491 +       llgfr   %r5,%r5                 # size_t
492 +       jg      sys_getxattr
493 +
494 +       .globl  sys32_lgetxattr_wrapper
495 +sys32_lgetxattr_wrapper:
496 +       llgtr   %r2,%r2                 # char *
497 +       llgtr   %r3,%r3                 # char *
498 +       llgtr   %r4,%r4                 # void *
499 +       llgfr   %r5,%r5                 # size_t
500 +       jg      sys_lgetxattr
501 +
502 +       .globl  sys32_fgetxattr_wrapper
503 +sys32_fgetxattr_wrapper:
504 +       lgfr    %r2,%r2                 # int
505 +       llgtr   %r3,%r3                 # char *
506 +       llgtr   %r4,%r4                 # void *
507 +       llgfr   %r5,%r5                 # size_t
508 +       jg      sys_fgetxattr
509 +
510 +       .globl  sys32_listxattr_wrapper
511 +sys32_listxattr_wrapper:
512 +       llgtr   %r2,%r2                 # char *
513 +       llgtr   %r3,%r3                 # char *
514 +       llgfr   %r4,%r4                 # size_t
515 +       jg      sys_listxattr
516 +
517 +       .globl  sys32_llistxattr_wrapper
518 +sys32_llistxattr_wrapper:
519 +       llgtr   %r2,%r2                 # char *
520 +       llgtr   %r3,%r3                 # char *
521 +       llgfr   %r4,%r4                 # size_t
522 +       jg      sys_llistxattr
523 +
524 +       .globl  sys32_flistxattr_wrapper
525 +sys32_flistxattr_wrapper:
526 +       lgfr    %r2,%r2                 # int
527 +       llgtr   %r3,%r3                 # char *
528 +       llgfr   %r4,%r4                 # size_t
529 +       jg      sys_flistxattr
530 +
531 +       .globl  sys32_removexattr_wrapper
532 +sys32_removexattr_wrapper:
533 +       llgtr   %r2,%r2                 # char *
534 +       llgtr   %r3,%r3                 # char *
535 +       jg      sys_removexattr
536 +
537 +       .globl  sys32_lremovexattr_wrapper
538 +sys32_lremovexattr_wrapper:
539 +       llgtr   %r2,%r2                 # char *
540 +       llgtr   %r3,%r3                 # char *
541 +       jg      sys_lremovexattr
542 +
543 +       .globl  sys32_fremovexattr_wrapper
544 +sys32_fremovexattr_wrapper:
545 +       lgfr    %r2,%r2                 # int
546 +       llgtr   %r3,%r3                 # char *
547 +       jg      sys_fremovexattr
548 +
549 +
550 --- kernel-2.4.20-6chaos_18_7/arch/sparc/defconfig~linux-2.4.20-xattr-0.8.54-chaos      2002-09-25 11:10:50.000000000 -0600
551 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/defconfig        2003-07-12 15:34:44.000000000 -0600
552 @@ -1,6 +1,13 @@
553  #
554  # Automatically generated make config: don't edit
555  #
556 +# CONFIG_EXT3_FS_XATTR is not set
557 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
558 +# CONFIG_EXT3_FS_XATTR_USER is not set
559 +# CONFIG_EXT2_FS_XATTR is not set
560 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
561 +# CONFIG_EXT2_FS_XATTR_USER is not set
562 +# CONFIG_FS_MBCACHE is not set
563  CONFIG_UID16=y
564  CONFIG_HIGHMEM=y
565  
566 --- kernel-2.4.20-6chaos_18_7/arch/sparc/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos       2002-09-25 11:10:52.000000000 -0600
567 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/kernel/systbls.S 2003-07-12 15:34:44.000000000 -0600
568 @@ -51,11 +51,11 @@ sys_call_table:
569  /*150*/        .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
570  /*155*/        .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
571  /*160*/        .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
572 -/*165*/        .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
573 -/*170*/        .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
574 -/*175*/        .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
575 -/*180*/        .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
576 -/*185*/        .long sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sys_newuname
577 +/*165*/        .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
578 +/*170*/        .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
579 +/*175*/        .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
580 +/*180*/        .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
581 +/*185*/        .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
582  /*190*/        .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
583  /*195*/        .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
584  /*200*/        .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
585 --- kernel-2.4.20-6chaos_18_7/arch/sparc64/defconfig~linux-2.4.20-xattr-0.8.54-chaos    2003-05-15 21:12:29.000000000 -0600
586 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/defconfig      2003-07-12 15:34:44.000000000 -0600
587 @@ -1,6 +1,13 @@
588  #
589  # Automatically generated make config: don't edit
590  #
591 +# CONFIG_EXT3_FS_XATTR is not set
592 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
593 +# CONFIG_EXT3_FS_XATTR_USER is not set
594 +# CONFIG_EXT2_FS_XATTR is not set
595 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
596 +# CONFIG_EXT2_FS_XATTR_USER is not set
597 +# CONFIG_FS_MBCACHE is not set
598  
599  #
600  # Code maturity level options
601 --- kernel-2.4.20-6chaos_18_7/arch/sparc64/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos     2002-09-25 11:10:55.000000000 -0600
602 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/kernel/systbls.S       2003-07-12 15:34:44.000000000 -0600
603 @@ -52,11 +52,11 @@ sys_call_table32:
604  /*150*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
605         .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
606  /*160*/        .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
607 -       .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
608 -/*170*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
609 -       .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
610 -/*180*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
611 -       .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
612 +       .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
613 +/*170*/        .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
614 +       .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
615 +/*180*/        .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
616 +       .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
617  /*190*/        .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
618         .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
619  /*200*/        .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
620 @@ -111,11 +111,11 @@ sys_call_table:
621  /*150*/        .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
622         .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
623  /*160*/        .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
624 -       .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
625 -/*170*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
626 -       .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
627 -/*180*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
628 -       .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
629 +       .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
630 +/*170*/        .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
631 +       .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
632 +/*180*/        .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
633 +       .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
634  /*190*/        .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
635         .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
636  /*200*/        .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
637 --- kernel-2.4.20-6chaos_18_7/fs/Config.in~linux-2.4.20-xattr-0.8.54-chaos      2003-05-15 21:14:24.000000000 -0600
638 +++ kernel-2.4.20-6chaos_18_7-braam/fs/Config.in        2003-07-12 15:34:44.000000000 -0600
639 @@ -34,6 +34,11 @@ dep_mbool '  Debug Befs' CONFIG_BEFS_DEB
640  dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
641  
642  tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
643 +dep_mbool '  Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
644 +dep_bool '    Ext3 extended attribute block sharing' \
645 +    CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
646 +dep_bool '    Ext3 extended user attributes' \
647 +    CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
648  # CONFIG_JBD could be its own option (even modular), but until there are
649  # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
650  # dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
651 @@ -93,6 +98,11 @@ dep_mbool '  QNX4FS write support (DANGE
652  tristate 'ROM file system support' CONFIG_ROMFS_FS
653  
654  tristate 'Second extended fs support' CONFIG_EXT2_FS
655 +dep_mbool '  Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
656 +dep_bool '    Ext2 extended attribute block sharing' \
657 +    CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
658 +dep_bool '    Ext2 extended user attributes' \
659 +    CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
660  
661  tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
662  
663 @@ -164,6 +174,10 @@ else
664     define_tristate CONFIG_ZISOFS_FS n
665  fi
666  
667 +# Meta block cache for Extended Attributes (ext2/ext3)
668 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
669 +define_tristate CONFIG_FS_MBCACHE y
670 +
671  mainmenu_option next_comment
672  comment 'Partition Types'
673  source fs/partitions/Config.in
674 --- kernel-2.4.20-6chaos_18_7/fs/Makefile~linux-2.4.20-xattr-0.8.54-chaos       2003-07-12 15:33:34.000000000 -0600
675 +++ kernel-2.4.20-6chaos_18_7-braam/fs/Makefile 2003-07-12 15:34:44.000000000 -0600
676 @@ -84,6 +84,9 @@ obj-y                         += binfmt_script.o
677  
678  obj-$(CONFIG_BINFMT_ELF)       += binfmt_elf.o
679  
680 +export-objs += mbcache.o
681 +obj-$(CONFIG_FS_MBCACHE)       += mbcache.o
682 +
683  # persistent filesystems
684  obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
685  
686 --- kernel-2.4.20-6chaos_18_7/fs/ext2/Makefile~linux-2.4.20-xattr-0.8.54-chaos  2002-05-07 15:53:46.000000000 -0600
687 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/Makefile    2003-07-12 15:34:44.000000000 -0600
688 @@ -13,4 +13,8 @@ obj-y    := balloc.o bitmap.o dir.o file
689                 ioctl.o namei.o super.o symlink.o
690  obj-m    := $(O_TARGET)
691  
692 +export-objs += xattr.o
693 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
694 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
695 +
696  include $(TOPDIR)/Rules.make
697 --- kernel-2.4.20-6chaos_18_7/fs/ext2/file.c~linux-2.4.20-xattr-0.8.54-chaos    2002-05-07 15:53:46.000000000 -0600
698 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/file.c      2003-07-12 15:34:44.000000000 -0600
699 @@ -20,6 +20,7 @@
700  
701  #include <linux/fs.h>
702  #include <linux/ext2_fs.h>
703 +#include <linux/ext2_xattr.h>
704  #include <linux/sched.h>
705  
706  /*
707 @@ -51,4 +52,8 @@ struct file_operations ext2_file_operati
708  
709  struct inode_operations ext2_file_inode_operations = {
710         truncate:       ext2_truncate,
711 +       setxattr:       ext2_setxattr,
712 +       getxattr:       ext2_getxattr,
713 +       listxattr:      ext2_listxattr,
714 +       removexattr:    ext2_removexattr,
715  };
716 --- kernel-2.4.20-6chaos_18_7/fs/ext2/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos  2003-02-14 15:59:09.000000000 -0700
717 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/ialloc.c    2003-07-12 15:34:44.000000000 -0600
718 @@ -15,6 +15,7 @@
719  #include <linux/config.h>
720  #include <linux/fs.h>
721  #include <linux/ext2_fs.h>
722 +#include <linux/ext2_xattr.h>
723  #include <linux/locks.h>
724  #include <linux/quotaops.h>
725  
726 @@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino
727          */
728         if (!is_bad_inode(inode)) {
729                 /* Quota is already initialized in iput() */
730 +               ext2_xattr_delete_inode(inode);
731                 DQUOT_FREE_INODE(inode);
732                 DQUOT_DROP(inode);
733         }
734 --- kernel-2.4.20-6chaos_18_7/fs/ext2/inode.c~linux-2.4.20-xattr-0.8.54-chaos   2003-02-14 15:59:09.000000000 -0700
735 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/inode.c     2003-07-12 15:34:44.000000000 -0600
736 @@ -39,6 +39,18 @@ MODULE_LICENSE("GPL");
737  static int ext2_update_inode(struct inode * inode, int do_sync);
738  
739  /*
740 + * Test whether an inode is a fast symlink.
741 + */
742 +static inline int ext2_inode_is_fast_symlink(struct inode *inode)
743 +{
744 +       int ea_blocks = inode->u.ext2_i.i_file_acl ?
745 +               (inode->i_sb->s_blocksize >> 9) : 0;
746 +
747 +       return (S_ISLNK(inode->i_mode) &&
748 +               inode->i_blocks - ea_blocks == 0);
749 +}
750 +
751 +/*
752   * Called at each iput()
753   */
754  void ext2_put_inode (struct inode * inode)
755 @@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i
756  {
757         lock_kernel();
758  
759 -       if (is_bad_inode(inode) ||
760 -           inode->i_ino == EXT2_ACL_IDX_INO ||
761 -           inode->i_ino == EXT2_ACL_DATA_INO)
762 +       if (is_bad_inode(inode))
763                 goto no_delete;
764         inode->u.ext2_i.i_dtime = CURRENT_TIME;
765         mark_inode_dirty(inode);
766 @@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode
767         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
768             S_ISLNK(inode->i_mode)))
769                 return;
770 +       if (ext2_inode_is_fast_symlink(inode))
771 +               return;
772         if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
773                 return;
774  
775 @@ -888,8 +900,7 @@ void ext2_read_inode (struct inode * ino
776         unsigned long offset;
777         struct ext2_group_desc * gdp;
778  
779 -       if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
780 -            inode->i_ino != EXT2_ACL_DATA_INO &&
781 +       if ((inode->i_ino != EXT2_ROOT_INO &&
782              inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
783             inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
784                 ext2_error (inode->i_sb, "ext2_read_inode",
785 @@ -974,10 +985,7 @@ void ext2_read_inode (struct inode * ino
786         for (block = 0; block < EXT2_N_BLOCKS; block++)
787                 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
788  
789 -       if (inode->i_ino == EXT2_ACL_IDX_INO ||
790 -           inode->i_ino == EXT2_ACL_DATA_INO)
791 -               /* Nothing to do */ ;
792 -       else if (S_ISREG(inode->i_mode)) {
793 +       if (S_ISREG(inode->i_mode)) {
794                 inode->i_op = &ext2_file_inode_operations;
795                 inode->i_fop = &ext2_file_operations;
796                 inode->i_mapping->a_ops = &ext2_aops;
797 @@ -986,15 +994,17 @@ void ext2_read_inode (struct inode * ino
798                 inode->i_fop = &ext2_dir_operations;
799                 inode->i_mapping->a_ops = &ext2_aops;
800         } else if (S_ISLNK(inode->i_mode)) {
801 -               if (!inode->i_blocks)
802 +               if (ext2_inode_is_fast_symlink(inode))
803                         inode->i_op = &ext2_fast_symlink_inode_operations;
804                 else {
805 -                       inode->i_op = &page_symlink_inode_operations;
806 +                       inode->i_op = &ext2_symlink_inode_operations;
807                         inode->i_mapping->a_ops = &ext2_aops;
808                 }
809 -       } else 
810 +       } else {
811 +               inode->i_op = &ext2_special_inode_operations;
812                 init_special_inode(inode, inode->i_mode,
813                                    le32_to_cpu(raw_inode->i_block[0]));
814 +       }
815         brelse (bh);
816         inode->i_attr_flags = 0;
817         if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
818 --- kernel-2.4.20-6chaos_18_7/fs/ext2/namei.c~linux-2.4.20-xattr-0.8.54-chaos   2002-05-07 15:53:46.000000000 -0600
819 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/namei.c     2003-07-12 15:34:44.000000000 -0600
820 @@ -31,6 +31,7 @@
821  
822  #include <linux/fs.h>
823  #include <linux/ext2_fs.h>
824 +#include <linux/ext2_xattr.h>
825  #include <linux/pagemap.h>
826  
827  /*
828 @@ -136,7 +137,7 @@ static int ext2_symlink (struct inode * 
829  
830         if (l > sizeof (inode->u.ext2_i.i_data)) {
831                 /* slow symlink */
832 -               inode->i_op = &page_symlink_inode_operations;
833 +               inode->i_op = &ext2_symlink_inode_operations;
834                 inode->i_mapping->a_ops = &ext2_aops;
835                 err = block_symlink(inode, symname, l);
836                 if (err)
837 @@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o
838         rmdir:          ext2_rmdir,
839         mknod:          ext2_mknod,
840         rename:         ext2_rename,
841 +       setxattr:       ext2_setxattr,
842 +       getxattr:       ext2_getxattr,
843 +       listxattr:      ext2_listxattr,
844 +       removexattr:    ext2_removexattr,
845 +};
846 +
847 +struct inode_operations ext2_special_inode_operations = {
848 +       setxattr:       ext2_setxattr,
849 +       getxattr:       ext2_getxattr,
850 +       listxattr:      ext2_listxattr,
851 +       removexattr:    ext2_removexattr,
852  };
853 --- kernel-2.4.20-6chaos_18_7/fs/ext2/super.c~linux-2.4.20-xattr-0.8.54-chaos   2003-02-14 15:59:09.000000000 -0700
854 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/super.c     2003-07-12 15:34:44.000000000 -0600
855 @@ -21,6 +21,7 @@
856  #include <linux/string.h>
857  #include <linux/fs.h>
858  #include <linux/ext2_fs.h>
859 +#include <linux/ext2_xattr.h>
860  #include <linux/slab.h>
861  #include <linux/init.h>
862  #include <linux/locks.h>
863 @@ -125,6 +126,7 @@ void ext2_put_super (struct super_block 
864         int db_count;
865         int i;
866  
867 +       ext2_xattr_put_super(sb);
868         if (!(sb->s_flags & MS_RDONLY)) {
869                 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
870  
871 @@ -175,6 +177,13 @@ static int parse_options (char * options
872              this_char = strtok (NULL, ",")) {
873                 if ((value = strchr (this_char, '=')) != NULL)
874                         *value++ = 0;
875 +#ifdef CONFIG_EXT2_FS_XATTR_USER
876 +               if (!strcmp (this_char, "user_xattr"))
877 +                       set_opt (*mount_options, XATTR_USER);
878 +               else if (!strcmp (this_char, "nouser_xattr"))
879 +                       clear_opt (*mount_options, XATTR_USER);
880 +               else
881 +#endif
882                 if (!strcmp (this_char, "bsddf"))
883                         clear_opt (*mount_options, MINIX_DF);
884                 else if (!strcmp (this_char, "nouid32")) {
885 @@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st
886             blocksize = BLOCK_SIZE;
887  
888         sb->u.ext2_sb.s_mount_opt = 0;
889 +#ifdef CONFIG_EXT2_FS_XATTR_USER
890 +       /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
891 +#endif
892         if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
893             &sb->u.ext2_sb.s_mount_opt)) {
894                 return NULL;
895 @@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type, 
896  
897  static int __init init_ext2_fs(void)
898  {
899 -        return register_filesystem(&ext2_fs_type);
900 +       int error = init_ext2_xattr();
901 +       if (error)
902 +               return error;
903 +       error = init_ext2_xattr_user();
904 +       if (error)
905 +               goto fail;
906 +       error = register_filesystem(&ext2_fs_type);
907 +       if (!error)
908 +               return 0;
909 +
910 +       exit_ext2_xattr_user();
911 +fail:
912 +       exit_ext2_xattr();
913 +       return error;
914  }
915  
916  static void __exit exit_ext2_fs(void)
917  {
918         unregister_filesystem(&ext2_fs_type);
919 +       exit_ext2_xattr_user();
920 +       exit_ext2_xattr();
921  }
922  
923  EXPORT_NO_SYMBOLS;
924 --- kernel-2.4.20-6chaos_18_7/fs/ext2/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
925 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/symlink.c   2003-07-12 15:34:44.000000000 -0600
926 @@ -19,6 +19,7 @@
927  
928  #include <linux/fs.h>
929  #include <linux/ext2_fs.h>
930 +#include <linux/ext2_xattr.h>
931  
932  static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
933  {
934 @@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr
935         return vfs_follow_link(nd, s);
936  }
937  
938 +struct inode_operations ext2_symlink_inode_operations = {
939 +       readlink:       page_readlink,
940 +       follow_link:    page_follow_link,
941 +       setxattr:       ext2_setxattr,
942 +       getxattr:       ext2_getxattr,
943 +       listxattr:      ext2_listxattr,
944 +       removexattr:    ext2_removexattr,
945 +};
946 +
947  struct inode_operations ext2_fast_symlink_inode_operations = {
948         readlink:       ext2_readlink,
949         follow_link:    ext2_follow_link,
950 +       setxattr:       ext2_setxattr,
951 +       getxattr:       ext2_getxattr,
952 +       listxattr:      ext2_listxattr,
953 +       removexattr:    ext2_removexattr,
954  };
955 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
956 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr.c     2003-07-12 15:34:44.000000000 -0600
957 @@ -0,0 +1,1212 @@
958 +/*
959 + * linux/fs/ext2/xattr.c
960 + *
961 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
962 + *
963 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
964 + * Extended attributes for symlinks and special files added per
965 + *  suggestion of Luka Renko <luka.renko@hermes.si>.
966 + */
967 +
968 +/*
969 + * Extended attributes are stored on disk blocks allocated outside of
970 + * any inode. The i_file_acl field is then made to point to this allocated
971 + * block. If all extended attributes of an inode are identical, these
972 + * inodes may share the same extended attribute block. Such situations
973 + * are automatically detected by keeping a cache of recent attribute block
974 + * numbers and hashes over the block's contents in memory.
975 + *
976 + *
977 + * Extended attribute block layout:
978 + *
979 + *   +------------------+
980 + *   | header           |
981 + *   | entry 1          | |
982 + *   | entry 2          | | growing downwards
983 + *   | entry 3          | v
984 + *   | four null bytes  |
985 + *   | . . .            |
986 + *   | value 1          | ^
987 + *   | value 3          | | growing upwards
988 + *   | value 2          | |
989 + *   +------------------+
990 + *
991 + * The block header is followed by multiple entry descriptors. These entry
992 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
993 + * byte boundaries. The entry descriptors are sorted by attribute name,
994 + * so that two extended attribute blocks can be compared efficiently.
995 + *
996 + * Attribute values are aligned to the end of the block, stored in
997 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
998 + * boundaries. No additional gaps are left between them.
999 + *
1000 + * Locking strategy
1001 + * ----------------
1002 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
1003 + * the xattr inode operations are called, so we are guaranteed that only one
1004 + * processes accesses extended attributes of an inode at any time.
1005 + *
1006 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
1007 + * only a single process is modifying an extended attribute block, even
1008 + * if the block is shared among inodes.
1009 + *
1010 + * Note for porting to 2.5
1011 + * -----------------------
1012 + * The BKL will no longer be held in the xattr inode operations.
1013 + */
1014 +
1015 +#include <linux/module.h>
1016 +#include <linux/locks.h>
1017 +#include <linux/slab.h>
1018 +#include <linux/fs.h>
1019 +#include <linux/ext2_fs.h>
1020 +#include <linux/ext2_xattr.h>
1021 +#include <linux/mbcache.h>
1022 +#include <linux/quotaops.h>
1023 +#include <asm/semaphore.h>
1024 +#include <linux/compatmac.h>
1025 +
1026 +/* These symbols may be needed by a module. */
1027 +EXPORT_SYMBOL(ext2_xattr_register);
1028 +EXPORT_SYMBOL(ext2_xattr_unregister);
1029 +EXPORT_SYMBOL(ext2_xattr_get);
1030 +EXPORT_SYMBOL(ext2_xattr_list);
1031 +EXPORT_SYMBOL(ext2_xattr_set);
1032 +
1033 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1034 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
1035 +#endif
1036 +
1037 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
1038 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
1039 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
1040 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
1041 +
1042 +#ifdef EXT2_XATTR_DEBUG
1043 +# define ea_idebug(inode, f...) do { \
1044 +               printk(KERN_DEBUG "inode %s:%ld: ", \
1045 +                       kdevname(inode->i_dev), inode->i_ino); \
1046 +               printk(f); \
1047 +               printk("\n"); \
1048 +       } while (0)
1049 +# define ea_bdebug(bh, f...) do { \
1050 +               printk(KERN_DEBUG "block %s:%ld: ", \
1051 +                       kdevname(bh->b_dev), bh->b_blocknr); \
1052 +               printk(f); \
1053 +               printk("\n"); \
1054 +       } while (0)
1055 +#else
1056 +# define ea_idebug(f...)
1057 +# define ea_bdebug(f...)
1058 +#endif
1059 +
1060 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
1061 +                          struct ext2_xattr_header *);
1062 +
1063 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1064 +
1065 +static int ext2_xattr_cache_insert(struct buffer_head *);
1066 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
1067 +                                                struct ext2_xattr_header *);
1068 +static void ext2_xattr_cache_remove(struct buffer_head *);
1069 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
1070 +                             struct ext2_xattr_entry *);
1071 +
1072 +static struct mb_cache *ext2_xattr_cache;
1073 +
1074 +#else
1075 +# define ext2_xattr_cache_insert(bh) 0
1076 +# define ext2_xattr_cache_find(inode, header) NULL
1077 +# define ext2_xattr_cache_remove(bh) while(0) {}
1078 +# define ext2_xattr_rehash(header, entry) while(0) {}
1079 +#endif
1080 +
1081 +/*
1082 + * If a file system does not share extended attributes among inodes,
1083 + * we should not need the ext2_xattr_sem semaphore. However, the
1084 + * filesystem may still contain shared blocks, so we always take
1085 + * the lock.
1086 + */
1087 +
1088 +DECLARE_MUTEX(ext2_xattr_sem);
1089 +
1090 +static inline int
1091 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
1092 +{
1093 +       struct super_block *sb = inode->i_sb;
1094 +       int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
1095 +               EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
1096 +
1097 +       /* How can we enforce the allocation? */
1098 +       int block = ext2_new_block(inode, goal, 0, 0, errp);
1099 +#ifdef OLD_QUOTAS
1100 +       if (!*errp)
1101 +               inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1102 +#endif
1103 +       return block;
1104 +}
1105 +
1106 +static inline int
1107 +ext2_xattr_quota_alloc(struct inode *inode, int force)
1108 +{
1109 +       /* How can we enforce the allocation? */
1110 +#ifdef OLD_QUOTAS
1111 +       int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
1112 +       if (!error)
1113 +               inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1114 +#else
1115 +       int error = DQUOT_ALLOC_BLOCK(inode, 1);
1116 +#endif
1117 +       return error;
1118 +}
1119 +
1120 +#ifdef OLD_QUOTAS
1121 +
1122 +static inline void
1123 +ext2_xattr_quota_free(struct inode *inode)
1124 +{
1125 +       DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
1126 +       inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1127 +}
1128 +
1129 +static inline void
1130 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
1131 +{
1132 +       ext2_free_blocks(inode, block, 1);
1133 +       inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1134 +}
1135 +
1136 +#else
1137 +# define ext2_xattr_quota_free(inode) \
1138 +       DQUOT_FREE_BLOCK(inode, 1)
1139 +# define ext2_xattr_free_block(inode, block) \
1140 +       ext2_free_blocks(inode, block, 1)
1141 +#endif
1142 +
1143 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1144 +
1145 +static inline struct buffer_head *
1146 +sb_bread(struct super_block *sb, int block)
1147 +{
1148 +       return bread(sb->s_dev, block, sb->s_blocksize);
1149 +}
1150 +
1151 +static inline struct buffer_head *
1152 +sb_getblk(struct super_block *sb, int block)
1153 +{
1154 +       return getblk(sb->s_dev, block, sb->s_blocksize);
1155 +}
1156 +
1157 +#endif
1158 +
1159 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1160 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1161 +
1162 +int
1163 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1164 +{
1165 +       int error = -EINVAL;
1166 +
1167 +       if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1168 +               write_lock(&ext2_handler_lock);
1169 +               if (!ext2_xattr_handlers[name_index-1]) {
1170 +                       ext2_xattr_handlers[name_index-1] = handler;
1171 +                       error = 0;
1172 +               }
1173 +               write_unlock(&ext2_handler_lock);
1174 +       }
1175 +       return error;
1176 +}
1177 +
1178 +void
1179 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1180 +{
1181 +       if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
1182 +               write_lock(&ext2_handler_lock);
1183 +               ext2_xattr_handlers[name_index-1] = NULL;
1184 +               write_unlock(&ext2_handler_lock);
1185 +       }
1186 +}
1187 +
1188 +static inline const char *
1189 +strcmp_prefix(const char *a, const char *a_prefix)
1190 +{
1191 +       while (*a_prefix && *a == *a_prefix) {
1192 +               a++;
1193 +               a_prefix++;
1194 +       }
1195 +       return *a_prefix ? NULL : a;
1196 +}
1197 +
1198 +/*
1199 + * Decode the extended attribute name, and translate it into
1200 + * the name_index and name suffix.
1201 + */
1202 +static struct ext2_xattr_handler *
1203 +ext2_xattr_resolve_name(const char **name)
1204 +{
1205 +       struct ext2_xattr_handler *handler = NULL;
1206 +       int i;
1207 +
1208 +       if (!*name)
1209 +               return NULL;
1210 +       read_lock(&ext2_handler_lock);
1211 +       for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1212 +               if (ext2_xattr_handlers[i]) {
1213 +                       const char *n = strcmp_prefix(*name,
1214 +                               ext2_xattr_handlers[i]->prefix);
1215 +                       if (n) {
1216 +                               handler = ext2_xattr_handlers[i];
1217 +                               *name = n;
1218 +                               break;
1219 +                       }
1220 +               }
1221 +       }
1222 +       read_unlock(&ext2_handler_lock);
1223 +       return handler;
1224 +}
1225 +
1226 +static inline struct ext2_xattr_handler *
1227 +ext2_xattr_handler(int name_index)
1228 +{
1229 +       struct ext2_xattr_handler *handler = NULL;
1230 +       if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1231 +               read_lock(&ext2_handler_lock);
1232 +               handler = ext2_xattr_handlers[name_index-1];
1233 +               read_unlock(&ext2_handler_lock);
1234 +       }
1235 +       return handler;
1236 +}
1237 +
1238 +/*
1239 + * Inode operation getxattr()
1240 + *
1241 + * dentry->d_inode->i_sem down
1242 + * BKL held [before 2.5.x]
1243 + */
1244 +ssize_t
1245 +ext2_getxattr(struct dentry *dentry, const char *name,
1246 +             void *buffer, size_t size)
1247 +{
1248 +       struct ext2_xattr_handler *handler;
1249 +       struct inode *inode = dentry->d_inode;
1250 +
1251 +       handler = ext2_xattr_resolve_name(&name);
1252 +       if (!handler)
1253 +               return -ENOTSUP;
1254 +       return handler->get(inode, name, buffer, size);
1255 +}
1256 +
1257 +/*
1258 + * Inode operation listxattr()
1259 + *
1260 + * dentry->d_inode->i_sem down
1261 + * BKL held [before 2.5.x]
1262 + */
1263 +ssize_t
1264 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1265 +{
1266 +       return ext2_xattr_list(dentry->d_inode, buffer, size);
1267 +}
1268 +
1269 +/*
1270 + * Inode operation setxattr()
1271 + *
1272 + * dentry->d_inode->i_sem down
1273 + * BKL held [before 2.5.x]
1274 + */
1275 +int
1276 +ext2_setxattr(struct dentry *dentry, const char *name,
1277 +             const void *value, size_t size, int flags)
1278 +{
1279 +       struct ext2_xattr_handler *handler;
1280 +       struct inode *inode = dentry->d_inode;
1281 +
1282 +       if (size == 0)
1283 +               value = "";  /* empty EA, do not remove */
1284 +       handler = ext2_xattr_resolve_name(&name);
1285 +       if (!handler)
1286 +               return -ENOTSUP;
1287 +       return handler->set(inode, name, value, size, flags);
1288 +}
1289 +
1290 +/*
1291 + * Inode operation removexattr()
1292 + *
1293 + * dentry->d_inode->i_sem down
1294 + * BKL held [before 2.5.x]
1295 + */
1296 +int
1297 +ext2_removexattr(struct dentry *dentry, const char *name)
1298 +{
1299 +       struct ext2_xattr_handler *handler;
1300 +       struct inode *inode = dentry->d_inode;
1301 +
1302 +       handler = ext2_xattr_resolve_name(&name);
1303 +       if (!handler)
1304 +               return -ENOTSUP;
1305 +       return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1306 +}
1307 +
1308 +/*
1309 + * ext2_xattr_get()
1310 + *
1311 + * Copy an extended attribute into the buffer
1312 + * provided, or compute the buffer size required.
1313 + * Buffer is NULL to compute the size of the buffer required.
1314 + *
1315 + * Returns a negative error number on failure, or the number of bytes
1316 + * used / required on success.
1317 + */
1318 +int
1319 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1320 +              void *buffer, size_t buffer_size)
1321 +{
1322 +       struct buffer_head *bh = NULL;
1323 +       struct ext2_xattr_entry *entry;
1324 +       unsigned int block, size;
1325 +       char *end;
1326 +       int name_len, error;
1327 +
1328 +       ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1329 +                 name_index, name, buffer, (long)buffer_size);
1330 +
1331 +       if (name == NULL)
1332 +               return -EINVAL;
1333 +       if (!EXT2_I(inode)->i_file_acl)
1334 +               return -ENOATTR;
1335 +       block = EXT2_I(inode)->i_file_acl;
1336 +       ea_idebug(inode, "reading block %d", block);
1337 +       bh = sb_bread(inode->i_sb, block);
1338 +       if (!bh)
1339 +               return -EIO;
1340 +       ea_bdebug(bh, "b_count=%d, refcount=%d",
1341 +               atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1342 +       end = bh->b_data + bh->b_size;
1343 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1344 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
1345 +bad_block:     ext2_error(inode->i_sb, "ext2_xattr_get",
1346 +                       "inode %ld: bad block %d", inode->i_ino, block);
1347 +               error = -EIO;
1348 +               goto cleanup;
1349 +       }
1350 +       /* find named attribute */
1351 +       name_len = strlen(name);
1352 +
1353 +       error = -ERANGE;
1354 +       if (name_len > 255)
1355 +               goto cleanup;
1356 +       entry = FIRST_ENTRY(bh);
1357 +       while (!IS_LAST_ENTRY(entry)) {
1358 +               struct ext2_xattr_entry *next =
1359 +                       EXT2_XATTR_NEXT(entry);
1360 +               if ((char *)next >= end)
1361 +                       goto bad_block;
1362 +               if (name_index == entry->e_name_index &&
1363 +                   name_len == entry->e_name_len &&
1364 +                   memcmp(name, entry->e_name, name_len) == 0)
1365 +                       goto found;
1366 +               entry = next;
1367 +       }
1368 +       /* Check the remaining name entries */
1369 +       while (!IS_LAST_ENTRY(entry)) {
1370 +               struct ext2_xattr_entry *next =
1371 +                       EXT2_XATTR_NEXT(entry);
1372 +               if ((char *)next >= end)
1373 +                       goto bad_block;
1374 +               entry = next;
1375 +       }
1376 +       if (ext2_xattr_cache_insert(bh))
1377 +               ea_idebug(inode, "cache insert failed");
1378 +       error = -ENOATTR;
1379 +       goto cleanup;
1380 +found:
1381 +       /* check the buffer size */
1382 +       if (entry->e_value_block != 0)
1383 +               goto bad_block;
1384 +       size = le32_to_cpu(entry->e_value_size);
1385 +       if (size > inode->i_sb->s_blocksize ||
1386 +           le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1387 +               goto bad_block;
1388 +
1389 +       if (ext2_xattr_cache_insert(bh))
1390 +               ea_idebug(inode, "cache insert failed");
1391 +       if (buffer) {
1392 +               error = -ERANGE;
1393 +               if (size > buffer_size)
1394 +                       goto cleanup;
1395 +               /* return value of attribute */
1396 +               memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1397 +                       size);
1398 +       }
1399 +       error = size;
1400 +
1401 +cleanup:
1402 +       brelse(bh);
1403 +
1404 +       return error;
1405 +}
1406 +
1407 +/*
1408 + * ext2_xattr_list()
1409 + *
1410 + * Copy a list of attribute names into the buffer
1411 + * provided, or compute the buffer size required.
1412 + * Buffer is NULL to compute the size of the buffer required.
1413 + *
1414 + * Returns a negative error number on failure, or the number of bytes
1415 + * used / required on success.
1416 + */
1417 +int
1418 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1419 +{
1420 +       struct buffer_head *bh = NULL;
1421 +       struct ext2_xattr_entry *entry;
1422 +       unsigned int block, size = 0;
1423 +       char *buf, *end;
1424 +       int error;
1425 +
1426 +       ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1427 +                 buffer, (long)buffer_size);
1428 +
1429 +       if (!EXT2_I(inode)->i_file_acl)
1430 +               return 0;
1431 +       block = EXT2_I(inode)->i_file_acl;
1432 +       ea_idebug(inode, "reading block %d", block);
1433 +       bh = sb_bread(inode->i_sb, block);
1434 +       if (!bh)
1435 +               return -EIO;
1436 +       ea_bdebug(bh, "b_count=%d, refcount=%d",
1437 +               atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1438 +       end = bh->b_data + bh->b_size;
1439 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1440 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
1441 +bad_block:     ext2_error(inode->i_sb, "ext2_xattr_list",
1442 +                       "inode %ld: bad block %d", inode->i_ino, block);
1443 +               error = -EIO;
1444 +               goto cleanup;
1445 +       }
1446 +       /* compute the size required for the list of attribute names */
1447 +       for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1448 +            entry = EXT2_XATTR_NEXT(entry)) {
1449 +               struct ext2_xattr_handler *handler;
1450 +               struct ext2_xattr_entry *next =
1451 +                       EXT2_XATTR_NEXT(entry);
1452 +               if ((char *)next >= end)
1453 +                       goto bad_block;
1454 +
1455 +               handler = ext2_xattr_handler(entry->e_name_index);
1456 +               if (handler)
1457 +                       size += handler->list(NULL, inode, entry->e_name,
1458 +                                             entry->e_name_len);
1459 +       }
1460 +
1461 +       if (ext2_xattr_cache_insert(bh))
1462 +               ea_idebug(inode, "cache insert failed");
1463 +       if (!buffer) {
1464 +               error = size;
1465 +               goto cleanup;
1466 +       } else {
1467 +               error = -ERANGE;
1468 +               if (size > buffer_size)
1469 +                       goto cleanup;
1470 +       }
1471 +
1472 +       /* list the attribute names */
1473 +       buf = buffer;
1474 +       for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1475 +            entry = EXT2_XATTR_NEXT(entry)) {
1476 +               struct ext2_xattr_handler *handler;
1477 +               
1478 +               handler = ext2_xattr_handler(entry->e_name_index);
1479 +               if (handler)
1480 +                       buf += handler->list(buf, inode, entry->e_name,
1481 +                                            entry->e_name_len);
1482 +       }
1483 +       error = size;
1484 +
1485 +cleanup:
1486 +       brelse(bh);
1487 +
1488 +       return error;
1489 +}
1490 +
1491 +/*
1492 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1493 + * not set, set it.
1494 + */
1495 +static void ext2_xattr_update_super_block(struct super_block *sb)
1496 +{
1497 +       if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1498 +               return;
1499 +
1500 +       lock_super(sb);
1501 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1502 +       EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1503 +#endif
1504 +       EXT2_SB(sb)->s_es->s_feature_compat |=
1505 +               cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1506 +       sb->s_dirt = 1;
1507 +       mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1508 +       unlock_super(sb);
1509 +}
1510 +
1511 +/*
1512 + * ext2_xattr_set()
1513 + *
1514 + * Create, replace or remove an extended attribute for this inode. Buffer
1515 + * is NULL to remove an existing extended attribute, and non-NULL to
1516 + * either replace an existing extended attribute, or create a new extended
1517 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1518 + * specify that an extended attribute must exist and must not exist
1519 + * previous to the call, respectively.
1520 + *
1521 + * Returns 0, or a negative error number on failure.
1522 + */
1523 +int
1524 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1525 +              const void *value, size_t value_len, int flags)
1526 +{
1527 +       struct super_block *sb = inode->i_sb;
1528 +       struct buffer_head *bh = NULL;
1529 +       struct ext2_xattr_header *header = NULL;
1530 +       struct ext2_xattr_entry *here, *last;
1531 +       unsigned int name_len;
1532 +       int block = EXT2_I(inode)->i_file_acl;
1533 +       int min_offs = sb->s_blocksize, not_found = 1, free, error;
1534 +       char *end;
1535 +       
1536 +       /*
1537 +        * header -- Points either into bh, or to a temporarily
1538 +        *           allocated buffer.
1539 +        * here -- The named entry found, or the place for inserting, within
1540 +        *         the block pointed to by header.
1541 +        * last -- Points right after the last named entry within the block
1542 +        *         pointed to by header.
1543 +        * min_offs -- The offset of the first value (values are aligned
1544 +        *             towards the end of the block).
1545 +        * end -- Points right after the block pointed to by header.
1546 +        */
1547 +       
1548 +       ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1549 +                 name_index, name, value, (long)value_len);
1550 +
1551 +       if (IS_RDONLY(inode))
1552 +               return -EROFS;
1553 +       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1554 +               return -EPERM;
1555 +       if (value == NULL)
1556 +               value_len = 0;
1557 +       if (name == NULL)
1558 +               return -EINVAL;
1559 +       name_len = strlen(name);
1560 +       if (name_len > 255 || value_len > sb->s_blocksize)
1561 +               return -ERANGE;
1562 +       down(&ext2_xattr_sem);
1563 +
1564 +       if (block) {
1565 +               /* The inode already has an extended attribute block. */
1566 +
1567 +               bh = sb_bread(sb, block);
1568 +               error = -EIO;
1569 +               if (!bh)
1570 +                       goto cleanup;
1571 +               ea_bdebug(bh, "b_count=%d, refcount=%d",
1572 +                       atomic_read(&(bh->b_count)),
1573 +                       le32_to_cpu(HDR(bh)->h_refcount));
1574 +               header = HDR(bh);
1575 +               end = bh->b_data + bh->b_size;
1576 +               if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1577 +                   header->h_blocks != cpu_to_le32(1)) {
1578 +bad_block:             ext2_error(sb, "ext2_xattr_set",
1579 +                               "inode %ld: bad block %d", inode->i_ino, block);
1580 +                       error = -EIO;
1581 +                       goto cleanup;
1582 +               }
1583 +               /* Find the named attribute. */
1584 +               here = FIRST_ENTRY(bh);
1585 +               while (!IS_LAST_ENTRY(here)) {
1586 +                       struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1587 +                       if ((char *)next >= end)
1588 +                               goto bad_block;
1589 +                       if (!here->e_value_block && here->e_value_size) {
1590 +                               int offs = le16_to_cpu(here->e_value_offs);
1591 +                               if (offs < min_offs)
1592 +                                       min_offs = offs;
1593 +                       }
1594 +                       not_found = name_index - here->e_name_index;
1595 +                       if (!not_found)
1596 +                               not_found = name_len - here->e_name_len;
1597 +                       if (!not_found)
1598 +                               not_found = memcmp(name, here->e_name,name_len);
1599 +                       if (not_found <= 0)
1600 +                               break;
1601 +                       here = next;
1602 +               }
1603 +               last = here;
1604 +               /* We still need to compute min_offs and last. */
1605 +               while (!IS_LAST_ENTRY(last)) {
1606 +                       struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1607 +                       if ((char *)next >= end)
1608 +                               goto bad_block;
1609 +                       if (!last->e_value_block && last->e_value_size) {
1610 +                               int offs = le16_to_cpu(last->e_value_offs);
1611 +                               if (offs < min_offs)
1612 +                                       min_offs = offs;
1613 +                       }
1614 +                       last = next;
1615 +               }
1616 +
1617 +               /* Check whether we have enough space left. */
1618 +               free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1619 +       } else {
1620 +               /* We will use a new extended attribute block. */
1621 +               free = sb->s_blocksize -
1622 +                       sizeof(struct ext2_xattr_header) - sizeof(__u32);
1623 +               here = last = NULL;  /* avoid gcc uninitialized warning. */
1624 +       }
1625 +
1626 +       if (not_found) {
1627 +               /* Request to remove a nonexistent attribute? */
1628 +               error = -ENOATTR;
1629 +               if (flags & XATTR_REPLACE)
1630 +                       goto cleanup;
1631 +               error = 0;
1632 +               if (value == NULL)
1633 +                       goto cleanup;
1634 +               else
1635 +                       free -= EXT2_XATTR_LEN(name_len);
1636 +       } else {
1637 +               /* Request to create an existing attribute? */
1638 +               error = -EEXIST;
1639 +               if (flags & XATTR_CREATE)
1640 +                       goto cleanup;
1641 +               if (!here->e_value_block && here->e_value_size) {
1642 +                       unsigned int size = le32_to_cpu(here->e_value_size);
1643 +
1644 +                       if (le16_to_cpu(here->e_value_offs) + size > 
1645 +                           sb->s_blocksize || size > sb->s_blocksize)
1646 +                               goto bad_block;
1647 +                       free += EXT2_XATTR_SIZE(size);
1648 +               }
1649 +       }
1650 +       free -= EXT2_XATTR_SIZE(value_len);
1651 +       error = -ENOSPC;
1652 +       if (free < 0)
1653 +               goto cleanup;
1654 +
1655 +       /* Here we know that we can set the new attribute. */
1656 +
1657 +       if (header) {
1658 +               if (header->h_refcount == cpu_to_le32(1)) {
1659 +                       ea_bdebug(bh, "modifying in-place");
1660 +                       ext2_xattr_cache_remove(bh);
1661 +               } else {
1662 +                       int offset;
1663 +
1664 +                       ea_bdebug(bh, "cloning");
1665 +                       header = kmalloc(bh->b_size, GFP_KERNEL);
1666 +                       error = -ENOMEM;
1667 +                       if (header == NULL)
1668 +                               goto cleanup;
1669 +                       memcpy(header, HDR(bh), bh->b_size);
1670 +                       header->h_refcount = cpu_to_le32(1);
1671 +                       offset = (char *)header - bh->b_data;
1672 +                       here = ENTRY((char *)here + offset);
1673 +                       last = ENTRY((char *)last + offset);
1674 +               }
1675 +       } else {
1676 +               /* Allocate a buffer where we construct the new block. */
1677 +               header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1678 +               error = -ENOMEM;
1679 +               if (header == NULL)
1680 +                       goto cleanup;
1681 +               memset(header, 0, sb->s_blocksize);
1682 +               end = (char *)header + sb->s_blocksize;
1683 +               header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1684 +               header->h_blocks = header->h_refcount = cpu_to_le32(1);
1685 +               last = here = ENTRY(header+1);
1686 +       }
1687 +
1688 +       if (not_found) {
1689 +               /* Insert the new name. */
1690 +               int size = EXT2_XATTR_LEN(name_len);
1691 +               int rest = (char *)last - (char *)here;
1692 +               memmove((char *)here + size, here, rest);
1693 +               memset(here, 0, size);
1694 +               here->e_name_index = name_index;
1695 +               here->e_name_len = name_len;
1696 +               memcpy(here->e_name, name, name_len);
1697 +       } else {
1698 +               /* Remove the old value. */
1699 +               if (!here->e_value_block && here->e_value_size) {
1700 +                       char *first_val = (char *)header + min_offs;
1701 +                       int offs = le16_to_cpu(here->e_value_offs);
1702 +                       char *val = (char *)header + offs;
1703 +                       size_t size = EXT2_XATTR_SIZE(
1704 +                               le32_to_cpu(here->e_value_size));
1705 +                       memmove(first_val + size, first_val, val - first_val);
1706 +                       memset(first_val, 0, size);
1707 +                       here->e_value_offs = 0;
1708 +                       min_offs += size;
1709 +
1710 +                       /* Adjust all value offsets. */
1711 +                       last = ENTRY(header+1);
1712 +                       while (!IS_LAST_ENTRY(last)) {
1713 +                               int o = le16_to_cpu(last->e_value_offs);
1714 +                               if (!last->e_value_block && o < offs)
1715 +                                       last->e_value_offs =
1716 +                                               cpu_to_le16(o + size);
1717 +                               last = EXT2_XATTR_NEXT(last);
1718 +                       }
1719 +               }
1720 +               if (value == NULL) {
1721 +                       /* Remove this attribute. */
1722 +                       if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1723 +                               /* This block is now empty. */
1724 +                               error = ext2_xattr_set2(inode, bh, NULL);
1725 +                               goto cleanup;
1726 +                       } else {
1727 +                               /* Remove the old name. */
1728 +                               int size = EXT2_XATTR_LEN(name_len);
1729 +                               last = ENTRY((char *)last - size);
1730 +                               memmove(here, (char*)here + size,
1731 +                                       (char*)last - (char*)here);
1732 +                               memset(last, 0, size);
1733 +                       }
1734 +               }
1735 +       }
1736 +
1737 +       if (value != NULL) {
1738 +               /* Insert the new value. */
1739 +               here->e_value_size = cpu_to_le32(value_len);
1740 +               if (value_len) {
1741 +                       size_t size = EXT2_XATTR_SIZE(value_len);
1742 +                       char *val = (char *)header + min_offs - size;
1743 +                       here->e_value_offs =
1744 +                               cpu_to_le16((char *)val - (char *)header);
1745 +                       memset(val + size - EXT2_XATTR_PAD, 0,
1746 +                              EXT2_XATTR_PAD); /* Clear the pad bytes. */
1747 +                       memcpy(val, value, value_len);
1748 +               }
1749 +       }
1750 +       ext2_xattr_rehash(header, here);
1751 +
1752 +       error = ext2_xattr_set2(inode, bh, header);
1753 +
1754 +cleanup:
1755 +       brelse(bh);
1756 +       if (!(bh && header == HDR(bh)))
1757 +               kfree(header);
1758 +       up(&ext2_xattr_sem);
1759 +
1760 +       return error;
1761 +}
1762 +
1763 +/*
1764 + * Second half of ext2_xattr_set(): Update the file system.
1765 + */
1766 +static int
1767 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1768 +               struct ext2_xattr_header *header)
1769 +{
1770 +       struct super_block *sb = inode->i_sb;
1771 +       struct buffer_head *new_bh = NULL;
1772 +       int error;
1773 +
1774 +       if (header) {
1775 +               new_bh = ext2_xattr_cache_find(inode, header);
1776 +               if (new_bh) {
1777 +                       /*
1778 +                        * We found an identical block in the cache.
1779 +                        * The old block will be released after updating
1780 +                        * the inode.
1781 +                        */
1782 +                       ea_bdebug(old_bh, "reusing block %ld",
1783 +                               new_bh->b_blocknr);
1784 +                       
1785 +                       error = -EDQUOT;
1786 +                       if (ext2_xattr_quota_alloc(inode, 1))
1787 +                               goto cleanup;
1788 +                       
1789 +                       HDR(new_bh)->h_refcount = cpu_to_le32(
1790 +                               le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1791 +                       ea_bdebug(new_bh, "refcount now=%d",
1792 +                               le32_to_cpu(HDR(new_bh)->h_refcount));
1793 +               } else if (old_bh && header == HDR(old_bh)) {
1794 +                       /* Keep this block. */
1795 +                       new_bh = old_bh;
1796 +                       ext2_xattr_cache_insert(new_bh);
1797 +               } else {
1798 +                       /* We need to allocate a new block */
1799 +                       int force = EXT2_I(inode)->i_file_acl != 0;
1800 +                       int block = ext2_xattr_new_block(inode, &error, force);
1801 +                       if (error)
1802 +                               goto cleanup;
1803 +                       ea_idebug(inode, "creating block %d", block);
1804 +
1805 +                       new_bh = sb_getblk(sb, block);
1806 +                       if (!new_bh) {
1807 +                               ext2_xattr_free_block(inode, block);
1808 +                               error = -EIO;
1809 +                               goto cleanup;
1810 +                       }
1811 +                       lock_buffer(new_bh);
1812 +                       memcpy(new_bh->b_data, header, new_bh->b_size);
1813 +                       mark_buffer_uptodate(new_bh, 1);
1814 +                       unlock_buffer(new_bh);
1815 +                       ext2_xattr_cache_insert(new_bh);
1816 +                       
1817 +                       ext2_xattr_update_super_block(sb);
1818 +               }
1819 +               mark_buffer_dirty(new_bh);
1820 +               if (IS_SYNC(inode)) {
1821 +                       ll_rw_block(WRITE, 1, &new_bh);
1822 +                       wait_on_buffer(new_bh); 
1823 +                       error = -EIO;
1824 +                       if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1825 +                               goto cleanup;
1826 +               }
1827 +       }
1828 +
1829 +       /* Update the inode. */
1830 +       EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1831 +       inode->i_ctime = CURRENT_TIME;
1832 +       if (IS_SYNC(inode)) {
1833 +               error = ext2_sync_inode (inode);
1834 +               if (error)
1835 +                       goto cleanup;
1836 +       } else
1837 +               mark_inode_dirty(inode);
1838 +
1839 +       error = 0;
1840 +       if (old_bh && old_bh != new_bh) {
1841 +               /*
1842 +                * If there was an old block, and we are not still using it,
1843 +                * we now release the old block.
1844 +               */
1845 +               unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1846 +
1847 +               if (refcount == 1) {
1848 +                       /* Free the old block. */
1849 +                       ea_bdebug(old_bh, "freeing");
1850 +                       ext2_xattr_free_block(inode, old_bh->b_blocknr);
1851 +                       mark_buffer_clean(old_bh);
1852 +               } else {
1853 +                       /* Decrement the refcount only. */
1854 +                       refcount--;
1855 +                       HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1856 +                       ext2_xattr_quota_free(inode);
1857 +                       mark_buffer_dirty(old_bh);
1858 +                       ea_bdebug(old_bh, "refcount now=%d", refcount);
1859 +               }
1860 +       }
1861 +
1862 +cleanup:
1863 +       if (old_bh != new_bh)
1864 +               brelse(new_bh);
1865 +
1866 +       return error;
1867 +}
1868 +
1869 +/*
1870 + * ext2_xattr_delete_inode()
1871 + *
1872 + * Free extended attribute resources associated with this inode. This
1873 + * is called immediately before an inode is freed.
1874 + */
1875 +void
1876 +ext2_xattr_delete_inode(struct inode *inode)
1877 +{
1878 +       struct buffer_head *bh;
1879 +       unsigned int block = EXT2_I(inode)->i_file_acl;
1880 +
1881 +       if (!block)
1882 +               return;
1883 +       down(&ext2_xattr_sem);
1884 +
1885 +       bh = sb_bread(inode->i_sb, block);
1886 +       if (!bh) {
1887 +               ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1888 +                       "inode %ld: block %d read error", inode->i_ino, block);
1889 +               goto cleanup;
1890 +       }
1891 +       ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1892 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1893 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
1894 +               ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1895 +                       "inode %ld: bad block %d", inode->i_ino, block);
1896 +               goto cleanup;
1897 +       }
1898 +       ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1899 +       if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1900 +               ext2_xattr_cache_remove(bh);
1901 +               ext2_xattr_free_block(inode, block);
1902 +               bforget(bh);
1903 +               bh = NULL;
1904 +       } else {
1905 +               HDR(bh)->h_refcount = cpu_to_le32(
1906 +                       le32_to_cpu(HDR(bh)->h_refcount) - 1);
1907 +               mark_buffer_dirty(bh);
1908 +               if (IS_SYNC(inode)) {
1909 +                       ll_rw_block(WRITE, 1, &bh);
1910 +                       wait_on_buffer(bh);
1911 +               }
1912 +               ext2_xattr_quota_free(inode);
1913 +       }
1914 +       EXT2_I(inode)->i_file_acl = 0;
1915 +
1916 +cleanup:
1917 +       brelse(bh);
1918 +       up(&ext2_xattr_sem);
1919 +}
1920 +
1921 +/*
1922 + * ext2_xattr_put_super()
1923 + *
1924 + * This is called when a file system is unmounted.
1925 + */
1926 +void
1927 +ext2_xattr_put_super(struct super_block *sb)
1928 +{
1929 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1930 +       mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
1931 +#endif
1932 +}
1933 +
1934 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1935 +
1936 +/*
1937 + * ext2_xattr_cache_insert()
1938 + *
1939 + * Create a new entry in the extended attribute cache, and insert
1940 + * it unless such an entry is already in the cache.
1941 + *
1942 + * Returns 0, or a negative error number on failure.
1943 + */
1944 +static int
1945 +ext2_xattr_cache_insert(struct buffer_head *bh)
1946 +{
1947 +       __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
1948 +       struct mb_cache_entry *ce;
1949 +       int error;
1950 +
1951 +       ce = mb_cache_entry_alloc(ext2_xattr_cache);
1952 +       if (!ce)
1953 +               return -ENOMEM;
1954 +       error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
1955 +       if (error) {
1956 +               mb_cache_entry_free(ce);
1957 +               if (error == -EBUSY) {
1958 +                       ea_bdebug(bh, "already in cache (%d cache entries)",
1959 +                               atomic_read(&ext2_xattr_cache->c_entry_count));
1960 +                       error = 0;
1961 +               }
1962 +       } else {
1963 +               ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
1964 +                         atomic_read(&ext2_xattr_cache->c_entry_count));
1965 +               mb_cache_entry_release(ce);
1966 +       }
1967 +       return error;
1968 +}
1969 +
1970 +/*
1971 + * ext2_xattr_cmp()
1972 + *
1973 + * Compare two extended attribute blocks for equality.
1974 + *
1975 + * Returns 0 if the blocks are equal, 1 if they differ, and
1976 + * a negative error number on errors.
1977 + */
1978 +static int
1979 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
1980 +              struct ext2_xattr_header *header2)
1981 +{
1982 +       struct ext2_xattr_entry *entry1, *entry2;
1983 +
1984 +       entry1 = ENTRY(header1+1);
1985 +       entry2 = ENTRY(header2+1);
1986 +       while (!IS_LAST_ENTRY(entry1)) {
1987 +               if (IS_LAST_ENTRY(entry2))
1988 +                       return 1;
1989 +               if (entry1->e_hash != entry2->e_hash ||
1990 +                   entry1->e_name_len != entry2->e_name_len ||
1991 +                   entry1->e_value_size != entry2->e_value_size ||
1992 +                   memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
1993 +                       return 1;
1994 +               if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
1995 +                       return -EIO;
1996 +               if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
1997 +                          (char *)header2 + le16_to_cpu(entry2->e_value_offs),
1998 +                          le32_to_cpu(entry1->e_value_size)))
1999 +                       return 1;
2000 +
2001 +               entry1 = EXT2_XATTR_NEXT(entry1);
2002 +               entry2 = EXT2_XATTR_NEXT(entry2);
2003 +       }
2004 +       if (!IS_LAST_ENTRY(entry2))
2005 +               return 1;
2006 +       return 0;
2007 +}
2008 +
2009 +/*
2010 + * ext2_xattr_cache_find()
2011 + *
2012 + * Find an identical extended attribute block.
2013 + *
2014 + * Returns a pointer to the block found, or NULL if such a block was
2015 + * not found or an error occurred.
2016 + */
2017 +static struct buffer_head *
2018 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
2019 +{
2020 +       __u32 hash = le32_to_cpu(header->h_hash);
2021 +       struct mb_cache_entry *ce;
2022 +
2023 +       if (!header->h_hash)
2024 +               return NULL;  /* never share */
2025 +       ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
2026 +       ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
2027 +       while (ce) {
2028 +               struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
2029 +
2030 +               if (!bh) {
2031 +                       ext2_error(inode->i_sb, "ext2_xattr_cache_find",
2032 +                               "inode %ld: block %ld read error",
2033 +                               inode->i_ino, ce->e_block);
2034 +               } else if (le32_to_cpu(HDR(bh)->h_refcount) >
2035 +                          EXT2_XATTR_REFCOUNT_MAX) {
2036 +                       ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
2037 +                               le32_to_cpu(HDR(bh)->h_refcount),
2038 +                               EXT2_XATTR_REFCOUNT_MAX);
2039 +               } else if (!ext2_xattr_cmp(header, HDR(bh))) {
2040 +                       ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
2041 +                       mb_cache_entry_release(ce);
2042 +                       return bh;
2043 +               }
2044 +               brelse(bh);
2045 +               ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
2046 +       }
2047 +       return NULL;
2048 +}
2049 +
2050 +/*
2051 + * ext2_xattr_cache_remove()
2052 + *
2053 + * Remove the cache entry of a block from the cache. Called when a
2054 + * block becomes invalid.
2055 + */
2056 +static void
2057 +ext2_xattr_cache_remove(struct buffer_head *bh)
2058 +{
2059 +       struct mb_cache_entry *ce;
2060 +
2061 +       ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
2062 +       if (ce) {
2063 +               ea_bdebug(bh, "removing (%d cache entries remaining)",
2064 +                         atomic_read(&ext2_xattr_cache->c_entry_count)-1);
2065 +               mb_cache_entry_free(ce);
2066 +       } else 
2067 +               ea_bdebug(bh, "no cache entry");
2068 +}
2069 +
2070 +#define NAME_HASH_SHIFT 5
2071 +#define VALUE_HASH_SHIFT 16
2072 +
2073 +/*
2074 + * ext2_xattr_hash_entry()
2075 + *
2076 + * Compute the hash of an extended attribute.
2077 + */
2078 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
2079 +                                        struct ext2_xattr_entry *entry)
2080 +{
2081 +       __u32 hash = 0;
2082 +       char *name = entry->e_name;
2083 +       int n;
2084 +
2085 +       for (n=0; n < entry->e_name_len; n++) {
2086 +               hash = (hash << NAME_HASH_SHIFT) ^
2087 +                      (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
2088 +                      *name++;
2089 +       }
2090 +
2091 +       if (entry->e_value_block == 0 && entry->e_value_size != 0) {
2092 +               __u32 *value = (__u32 *)((char *)header +
2093 +                       le16_to_cpu(entry->e_value_offs));
2094 +               for (n = (le32_to_cpu(entry->e_value_size) +
2095 +                    EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
2096 +                       hash = (hash << VALUE_HASH_SHIFT) ^
2097 +                              (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
2098 +                              le32_to_cpu(*value++);
2099 +               }
2100 +       }
2101 +       entry->e_hash = cpu_to_le32(hash);
2102 +}
2103 +
2104 +#undef NAME_HASH_SHIFT
2105 +#undef VALUE_HASH_SHIFT
2106 +
2107 +#define BLOCK_HASH_SHIFT 16
2108 +
2109 +/*
2110 + * ext2_xattr_rehash()
2111 + *
2112 + * Re-compute the extended attribute hash value after an entry has changed.
2113 + */
2114 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
2115 +                             struct ext2_xattr_entry *entry)
2116 +{
2117 +       struct ext2_xattr_entry *here;
2118 +       __u32 hash = 0;
2119 +       
2120 +       ext2_xattr_hash_entry(header, entry);
2121 +       here = ENTRY(header+1);
2122 +       while (!IS_LAST_ENTRY(here)) {
2123 +               if (!here->e_hash) {
2124 +                       /* Block is not shared if an entry's hash value == 0 */
2125 +                       hash = 0;
2126 +                       break;
2127 +               }
2128 +               hash = (hash << BLOCK_HASH_SHIFT) ^
2129 +                      (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
2130 +                      le32_to_cpu(here->e_hash);
2131 +               here = EXT2_XATTR_NEXT(here);
2132 +       }
2133 +       header->h_hash = cpu_to_le32(hash);
2134 +}
2135 +
2136 +#undef BLOCK_HASH_SHIFT
2137 +
2138 +int __init
2139 +init_ext2_xattr(void)
2140 +{
2141 +       ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
2142 +               sizeof(struct mb_cache_entry) +
2143 +               sizeof(struct mb_cache_entry_index), 1, 61);
2144 +       if (!ext2_xattr_cache)
2145 +               return -ENOMEM;
2146 +
2147 +       return 0;
2148 +}
2149 +
2150 +void
2151 +exit_ext2_xattr(void)
2152 +{
2153 +       mb_cache_destroy(ext2_xattr_cache);
2154 +}
2155 +
2156 +#else  /* CONFIG_EXT2_FS_XATTR_SHARING */
2157 +
2158 +int __init
2159 +init_ext2_xattr(void)
2160 +{
2161 +       return 0;
2162 +}
2163 +
2164 +void
2165 +exit_ext2_xattr(void)
2166 +{
2167 +}
2168 +
2169 +#endif  /* CONFIG_EXT2_FS_XATTR_SHARING */
2170 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
2171 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr_user.c        2003-07-12 15:34:44.000000000 -0600
2172 @@ -0,0 +1,103 @@
2173 +/*
2174 + * linux/fs/ext2/xattr_user.c
2175 + * Handler for extended user attributes.
2176 + *
2177 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2178 + */
2179 +
2180 +#include <linux/module.h>
2181 +#include <linux/string.h>
2182 +#include <linux/fs.h>
2183 +#include <linux/ext2_fs.h>
2184 +#include <linux/ext2_xattr.h>
2185 +
2186 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2187 +# include <linux/ext2_acl.h>
2188 +#endif
2189 +
2190 +#define XATTR_USER_PREFIX "user."
2191 +
2192 +static size_t
2193 +ext2_xattr_user_list(char *list, struct inode *inode,
2194 +                    const char *name, int name_len)
2195 +{
2196 +       const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2197 +
2198 +       if (!test_opt(inode->i_sb, XATTR_USER))
2199 +               return 0;
2200 +
2201 +       if (list) {
2202 +               memcpy(list, XATTR_USER_PREFIX, prefix_len);
2203 +               memcpy(list+prefix_len, name, name_len);
2204 +               list[prefix_len + name_len] = '\0';
2205 +       }
2206 +       return prefix_len + name_len + 1;
2207 +}
2208 +
2209 +static int
2210 +ext2_xattr_user_get(struct inode *inode, const char *name,
2211 +                   void *buffer, size_t size)
2212 +{
2213 +       int error;
2214 +
2215 +       if (strcmp(name, "") == 0)
2216 +               return -EINVAL;
2217 +       if (!test_opt(inode->i_sb, XATTR_USER))
2218 +               return -ENOTSUP;
2219 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2220 +       error = ext2_permission_locked(inode, MAY_READ);
2221 +#else
2222 +       error = permission(inode, MAY_READ);
2223 +#endif
2224 +       if (error)
2225 +               return error;
2226 +
2227 +       return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2228 +                             buffer, size);
2229 +}
2230 +
2231 +static int
2232 +ext2_xattr_user_set(struct inode *inode, const char *name,
2233 +                   const void *value, size_t size, int flags)
2234 +{
2235 +       int error;
2236 +
2237 +       if (strcmp(name, "") == 0)
2238 +               return -EINVAL;
2239 +       if (!test_opt(inode->i_sb, XATTR_USER))
2240 +               return -ENOTSUP;
2241 +       if ( !S_ISREG(inode->i_mode) &&
2242 +           (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2243 +               return -EPERM;
2244 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2245 +       error = ext2_permission_locked(inode, MAY_WRITE);
2246 +#else
2247 +       error = permission(inode, MAY_WRITE);
2248 +#endif
2249 +       if (error)
2250 +               return error;
2251 +
2252 +       return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2253 +                             value, size, flags);
2254 +}
2255 +
2256 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2257 +       prefix: XATTR_USER_PREFIX,
2258 +       list:   ext2_xattr_user_list,
2259 +       get:    ext2_xattr_user_get,
2260 +       set:    ext2_xattr_user_set,
2261 +};
2262 +
2263 +int __init
2264 +init_ext2_xattr_user(void)
2265 +{
2266 +       return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2267 +                                  &ext2_xattr_user_handler);
2268 +}
2269 +
2270 +void
2271 +exit_ext2_xattr_user(void)
2272 +{
2273 +       ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2274 +                             &ext2_xattr_user_handler);
2275 +}
2276 --- kernel-2.4.20-6chaos_18_7/fs/ext3/Makefile~linux-2.4.20-xattr-0.8.54-chaos  2003-07-12 15:33:38.000000000 -0600
2277 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/Makefile    2003-07-12 15:34:44.000000000 -0600
2278 @@ -1,5 +1,5 @@
2279  #
2280 -# Makefile for the linux ext2-filesystem routines.
2281 +# Makefile for the linux ext3-filesystem routines.
2282  #
2283  # Note! Dependencies are done automagically by 'make dep', which also
2284  # removes any old dependencies. DON'T put your own dependencies here
2285 @@ -9,10 +9,14 @@
2286  
2287  O_TARGET := ext3.o
2288  
2289 -export-objs := super.o inode.o
2290 +export-objs := ext3-exports.o
2291  
2292  obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2293 -               ioctl.o namei.o super.o symlink.o hash.o
2294 +               ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2295  obj-m    := $(O_TARGET)
2296  
2297 +export-objs += xattr.o
2298 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2299 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2300 +
2301  include $(TOPDIR)/Rules.make
2302 --- kernel-2.4.20-6chaos_18_7/fs/ext3/file.c~linux-2.4.20-xattr-0.8.54-chaos    2003-07-12 15:33:38.000000000 -0600
2303 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/file.c      2003-07-12 15:34:44.000000000 -0600
2304 @@ -23,6 +23,7 @@
2305  #include <linux/locks.h>
2306  #include <linux/jbd.h>
2307  #include <linux/ext3_fs.h>
2308 +#include <linux/ext3_xattr.h>
2309  #include <linux/ext3_jbd.h>
2310  #include <linux/smp_lock.h>
2311  
2312 @@ -126,5 +127,9 @@ struct file_operations ext3_file_operati
2313  struct inode_operations ext3_file_inode_operations = {
2314         truncate:       ext3_truncate,          /* BKL held */
2315         setattr:        ext3_setattr,           /* BKL held */
2316 +       setxattr:       ext3_setxattr,          /* BKL held */
2317 +       getxattr:       ext3_getxattr,          /* BKL held */
2318 +       listxattr:      ext3_listxattr,         /* BKL held */
2319 +       removexattr:    ext3_removexattr,       /* BKL held */
2320  };
2321  
2322 --- kernel-2.4.20-6chaos_18_7/fs/ext3/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos  2003-05-15 21:14:30.000000000 -0600
2323 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ialloc.c    2003-07-12 15:34:44.000000000 -0600
2324 @@ -17,6 +17,7 @@
2325  #include <linux/jbd.h>
2326  #include <linux/ext3_fs.h>
2327  #include <linux/ext3_jbd.h>
2328 +#include <linux/ext3_xattr.h>
2329  #include <linux/stat.h>
2330  #include <linux/string.h>
2331  #include <linux/locks.h>
2332 @@ -216,6 +217,7 @@ void ext3_free_inode (handle_t *handle, 
2333          * as writing the quota to disk may need the lock as well.
2334          */
2335         DQUOT_INIT(inode);
2336 +       ext3_xattr_delete_inode(handle, inode);
2337         DQUOT_FREE_INODE(inode);
2338         DQUOT_DROP(inode);
2339  
2340 --- kernel-2.4.20-6chaos_18_7/fs/ext3/inode.c~linux-2.4.20-xattr-0.8.54-chaos   2003-05-15 21:14:30.000000000 -0600
2341 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/inode.c     2003-07-12 15:34:44.000000000 -0600
2342 @@ -39,6 +39,18 @@
2343   */
2344  #undef SEARCH_FROM_ZERO
2345  
2346 +/*
2347 + * Test whether an inode is a fast symlink.
2348 + */
2349 +static inline int ext3_inode_is_fast_symlink(struct inode *inode)
2350 +{
2351 +       int ea_blocks = inode->u.ext3_i.i_file_acl ?
2352 +               (inode->i_sb->s_blocksize >> 9) : 0;
2353 +
2354 +       return (S_ISLNK(inode->i_mode) &&
2355 +               inode->i_blocks - ea_blocks == 0);
2356 +}
2357 +
2358  /* The ext3 forget function must perform a revoke if we are freeing data
2359   * which has been journaled.  Metadata (eg. indirect blocks) must be
2360   * revoked in all cases. 
2361 @@ -48,7 +60,7 @@
2362   * still needs to be revoked.
2363   */
2364  
2365 -static int ext3_forget(handle_t *handle, int is_metadata,
2366 +int ext3_forget(handle_t *handle, int is_metadata,
2367                        struct inode *inode, struct buffer_head *bh,
2368                        int blocknr)
2369  {
2370 @@ -179,9 +191,7 @@ void ext3_delete_inode (struct inode * i
2371  {
2372         handle_t *handle;
2373         
2374 -       if (is_bad_inode(inode) ||
2375 -           inode->i_ino == EXT3_ACL_IDX_INO ||
2376 -           inode->i_ino == EXT3_ACL_DATA_INO)
2377 +       if (is_bad_inode(inode))
2378                 goto no_delete;
2379  
2380         lock_kernel();
2381 @@ -1874,6 +1884,8 @@ void ext3_truncate(struct inode * inode)
2382         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
2383             S_ISLNK(inode->i_mode)))
2384                 return;
2385 +       if (ext3_inode_is_fast_symlink(inode))
2386 +               return;
2387         if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2388                 return;
2389  
2390 @@ -2021,8 +2033,6 @@ int ext3_get_inode_loc (struct inode *in
2391         struct ext3_group_desc * gdp;
2392                 
2393         if ((inode->i_ino != EXT3_ROOT_INO &&
2394 -               inode->i_ino != EXT3_ACL_IDX_INO &&
2395 -               inode->i_ino != EXT3_ACL_DATA_INO &&
2396                 inode->i_ino != EXT3_JOURNAL_INO &&
2397                 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2398                 inode->i_ino > le32_to_cpu(
2399 @@ -2149,10 +2159,7 @@ void ext3_read_inode(struct inode * inod
2400  
2401         brelse (iloc.bh);
2402  
2403 -       if (inode->i_ino == EXT3_ACL_IDX_INO ||
2404 -           inode->i_ino == EXT3_ACL_DATA_INO)
2405 -               /* Nothing to do */ ;
2406 -       else if (S_ISREG(inode->i_mode)) {
2407 +       if (S_ISREG(inode->i_mode)) {
2408                 inode->i_op = &ext3_file_inode_operations;
2409                 inode->i_fop = &ext3_file_operations;
2410                 inode->i_mapping->a_ops = &ext3_aops;
2411 @@ -2160,15 +2167,17 @@ void ext3_read_inode(struct inode * inod
2412                 inode->i_op = &ext3_dir_inode_operations;
2413                 inode->i_fop = &ext3_dir_operations;
2414         } else if (S_ISLNK(inode->i_mode)) {
2415 -               if (!inode->i_blocks)
2416 +               if (ext3_inode_is_fast_symlink(inode))
2417                         inode->i_op = &ext3_fast_symlink_inode_operations;
2418                 else {
2419 -                       inode->i_op = &page_symlink_inode_operations;
2420 +                       inode->i_op = &ext3_symlink_inode_operations;
2421                         inode->i_mapping->a_ops = &ext3_aops;
2422                 }
2423 -       } else 
2424 +       } else {
2425 +               inode->i_op = &ext3_special_inode_operations;
2426                 init_special_inode(inode, inode->i_mode,
2427                                    le32_to_cpu(iloc.raw_inode->i_block[0]));
2428 +       }
2429         /* inode->i_attr_flags = 0;                             unused */
2430         if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
2431                 /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
2432 --- kernel-2.4.20-6chaos_18_7/fs/ext3/namei.c~linux-2.4.20-xattr-0.8.54-chaos   2003-07-12 15:33:43.000000000 -0600
2433 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/namei.c     2003-07-12 15:34:44.000000000 -0600
2434 @@ -29,6 +29,7 @@
2435  #include <linux/sched.h>
2436  #include <linux/ext3_fs.h>
2437  #include <linux/ext3_jbd.h>
2438 +#include <linux/ext3_xattr.h>
2439  #include <linux/fcntl.h>
2440  #include <linux/stat.h>
2441  #include <linux/string.h>
2442 @@ -1613,7 +1614,7 @@ static int ext3_mkdir(struct inode * dir
2443         if (IS_SYNC(dir))
2444                 handle->h_sync = 1;
2445  
2446 -       inode = ext3_new_inode (handle, dir, S_IFDIR);
2447 +       inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2448         err = PTR_ERR(inode);
2449         if (IS_ERR(inode))
2450                 goto out_stop;
2451 @@ -1621,7 +1622,6 @@ static int ext3_mkdir(struct inode * dir
2452         inode->i_op = &ext3_dir_inode_operations;
2453         inode->i_fop = &ext3_dir_operations;
2454         inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2455 -       inode->i_blocks = 0;    
2456         dir_block = ext3_bread (handle, inode, 0, 1, &err);
2457         if (!dir_block) {
2458                 inode->i_nlink--; /* is this nlink == 0? */
2459 @@ -1648,9 +1648,6 @@ static int ext3_mkdir(struct inode * dir
2460         BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2461         ext3_journal_dirty_metadata(handle, dir_block);
2462         brelse (dir_block);
2463 -       inode->i_mode = S_IFDIR | mode;
2464 -       if (dir->i_mode & S_ISGID)
2465 -               inode->i_mode |= S_ISGID;
2466         ext3_mark_inode_dirty(handle, inode);
2467         err = ext3_add_entry (handle, dentry, inode);
2468         if (err) {
2469 @@ -2019,7 +2016,7 @@ static int ext3_symlink (struct inode * 
2470                 goto out_stop;
2471  
2472         if (l > sizeof (EXT3_I(inode)->i_data)) {
2473 -               inode->i_op = &page_symlink_inode_operations;
2474 +               inode->i_op = &ext3_symlink_inode_operations;
2475                 inode->i_mapping->a_ops = &ext3_aops;
2476                 /*
2477                  * block_symlink() calls back into ext3_prepare/commit_write.
2478 @@ -2245,4 +2242,16 @@ struct inode_operations ext3_dir_inode_o
2479         rmdir:          ext3_rmdir,             /* BKL held */
2480         mknod:          ext3_mknod,             /* BKL held */
2481         rename:         ext3_rename,            /* BKL held */
2482 +       setxattr:       ext3_setxattr,          /* BKL held */
2483 +       getxattr:       ext3_getxattr,          /* BKL held */
2484 +       listxattr:      ext3_listxattr,         /* BKL held */
2485 +       removexattr:    ext3_removexattr,       /* BKL held */
2486  };
2487 +
2488 +struct inode_operations ext3_special_inode_operations = {
2489 +       setxattr:       ext3_setxattr,          /* BKL held */
2490 +       getxattr:       ext3_getxattr,          /* BKL held */
2491 +       listxattr:      ext3_listxattr,         /* BKL held */
2492 +       removexattr:    ext3_removexattr,       /* BKL held */
2493 +};
2494 +
2495 --- kernel-2.4.20-6chaos_18_7/fs/ext3/super.c~linux-2.4.20-xattr-0.8.54-chaos   2003-07-12 15:33:38.000000000 -0600
2496 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/super.c     2003-07-12 15:34:44.000000000 -0600
2497 @@ -24,6 +24,7 @@
2498  #include <linux/jbd.h>
2499  #include <linux/ext3_fs.h>
2500  #include <linux/ext3_jbd.h>
2501 +#include <linux/ext3_xattr.h>
2502  #include <linux/slab.h>
2503  #include <linux/init.h>
2504  #include <linux/locks.h>
2505 @@ -406,6 +407,7 @@ void ext3_put_super (struct super_block 
2506         kdev_t j_dev = sbi->s_journal->j_dev;
2507         int i;
2508  
2509 +       ext3_xattr_put_super(sb);
2510         journal_destroy(sbi->s_journal);
2511         if (!(sb->s_flags & MS_RDONLY)) {
2512                 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2513 @@ -502,6 +504,7 @@ static int parse_options (char * options
2514                           int is_remount)
2515  {
2516         unsigned long *mount_options = &sbi->s_mount_opt;
2517 +       
2518         uid_t *resuid = &sbi->s_resuid;
2519         gid_t *resgid = &sbi->s_resgid;
2520         char * this_char;
2521 @@ -514,6 +517,13 @@ static int parse_options (char * options
2522              this_char = strtok (NULL, ",")) {
2523                 if ((value = strchr (this_char, '=')) != NULL)
2524                         *value++ = 0;
2525 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2526 +               if (!strcmp (this_char, "user_xattr"))
2527 +                       set_opt (*mount_options, XATTR_USER);
2528 +               else if (!strcmp (this_char, "nouser_xattr"))
2529 +                       clear_opt (*mount_options, XATTR_USER);
2530 +               else
2531 +#endif
2532                 if (!strcmp (this_char, "bsddf"))
2533                         clear_opt (*mount_options, MINIX_DF);
2534                 else if (!strcmp (this_char, "nouid32")) {
2535 @@ -931,6 +941,12 @@ struct super_block * ext3_read_super (st
2536         sbi->s_mount_opt = 0;
2537         sbi->s_resuid = EXT3_DEF_RESUID;
2538         sbi->s_resgid = EXT3_DEF_RESGID;
2539 +
2540 +       /* Default extended attribute flags */
2541 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2542 +       /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2543 +#endif
2544 +
2545         if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2546                 sb->s_dev = 0;
2547                 goto out_fail;
2548 @@ -1768,17 +1784,29 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type, 
2549  
2550  static int __init init_ext3_fs(void)
2551  {
2552 -        return register_filesystem(&ext3_fs_type);
2553 +       int error = init_ext3_xattr();
2554 +       if (error)
2555 +               return error;
2556 +       error = init_ext3_xattr_user();
2557 +       if (error)
2558 +               goto fail;
2559 +       error = register_filesystem(&ext3_fs_type);
2560 +       if (!error)
2561 +               return 0;
2562 +       
2563 +       exit_ext3_xattr_user();
2564 +fail:
2565 +       exit_ext3_xattr();
2566 +       return error;
2567  }
2568  
2569  static void __exit exit_ext3_fs(void)
2570  {
2571         unregister_filesystem(&ext3_fs_type);
2572 +       exit_ext3_xattr_user();
2573 +       exit_ext3_xattr();
2574  }
2575  
2576 -EXPORT_SYMBOL(ext3_force_commit);
2577 -EXPORT_SYMBOL(ext3_bread);
2578 -
2579  MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2580  MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2581  MODULE_LICENSE("GPL");
2582 --- kernel-2.4.20-6chaos_18_7/fs/ext3/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
2583 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/symlink.c   2003-07-12 15:34:44.000000000 -0600
2584 @@ -20,6 +20,7 @@
2585  #include <linux/fs.h>
2586  #include <linux/jbd.h>
2587  #include <linux/ext3_fs.h>
2588 +#include <linux/ext3_xattr.h>
2589  
2590  static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2591  {
2592 @@ -33,7 +34,20 @@ static int ext3_follow_link(struct dentr
2593         return vfs_follow_link(nd, s);
2594  }
2595  
2596 +struct inode_operations ext3_symlink_inode_operations = {
2597 +       readlink:       page_readlink,          /* BKL not held.  Don't need */
2598 +       follow_link:    page_follow_link,       /* BKL not held.  Don't need */
2599 +       setxattr:       ext3_setxattr,          /* BKL held */
2600 +       getxattr:       ext3_getxattr,          /* BKL held */
2601 +       listxattr:      ext3_listxattr,         /* BKL held */
2602 +       removexattr:    ext3_removexattr,       /* BKL held */
2603 +};
2604 +
2605  struct inode_operations ext3_fast_symlink_inode_operations = {
2606         readlink:       ext3_readlink,          /* BKL not held.  Don't need */
2607         follow_link:    ext3_follow_link,       /* BKL not held.  Don't need */
2608 +       setxattr:       ext3_setxattr,          /* BKL held */
2609 +       getxattr:       ext3_getxattr,          /* BKL held */
2610 +       listxattr:      ext3_listxattr,         /* BKL held */
2611 +       removexattr:    ext3_removexattr,       /* BKL held */
2612  };
2613 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
2614 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr.c     2003-07-12 15:34:44.000000000 -0600
2615 @@ -0,0 +1,1225 @@
2616 +/*
2617 + * linux/fs/ext3/xattr.c
2618 + *
2619 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2620 + *
2621 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2622 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2623 + * Extended attributes for symlinks and special files added per
2624 + *  suggestion of Luka Renko <luka.renko@hermes.si>.
2625 + */
2626 +
2627 +/*
2628 + * Extended attributes are stored on disk blocks allocated outside of
2629 + * any inode. The i_file_acl field is then made to point to this allocated
2630 + * block. If all extended attributes of an inode are identical, these
2631 + * inodes may share the same extended attribute block. Such situations
2632 + * are automatically detected by keeping a cache of recent attribute block
2633 + * numbers and hashes over the block's contents in memory.
2634 + *
2635 + *
2636 + * Extended attribute block layout:
2637 + *
2638 + *   +------------------+
2639 + *   | header           |
2640 + *   | entry 1          | |
2641 + *   | entry 2          | | growing downwards
2642 + *   | entry 3          | v
2643 + *   | four null bytes  |
2644 + *   | . . .            |
2645 + *   | value 1          | ^
2646 + *   | value 3          | | growing upwards
2647 + *   | value 2          | |
2648 + *   +------------------+
2649 + *
2650 + * The block header is followed by multiple entry descriptors. These entry
2651 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2652 + * byte boundaries. The entry descriptors are sorted by attribute name,
2653 + * so that two extended attribute blocks can be compared efficiently.
2654 + *
2655 + * Attribute values are aligned to the end of the block, stored in
2656 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2657 + * boundaries. No additional gaps are left between them.
2658 + *
2659 + * Locking strategy
2660 + * ----------------
2661 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2662 + * the xattr inode operations are called, so we are guaranteed that only one
2663 + * processes accesses extended attributes of an inode at any time.
2664 + *
2665 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2666 + * only a single process is modifying an extended attribute block, even
2667 + * if the block is shared among inodes.
2668 + *
2669 + * Note for porting to 2.5
2670 + * -----------------------
2671 + * The BKL will no longer be held in the xattr inode operations.
2672 + */
2673 +
2674 +#include <linux/module.h>
2675 +#include <linux/fs.h>
2676 +#include <linux/locks.h>
2677 +#include <linux/slab.h>
2678 +#include <linux/ext3_jbd.h>
2679 +#include <linux/ext3_fs.h>
2680 +#include <linux/ext3_xattr.h>
2681 +#include <linux/mbcache.h>
2682 +#include <linux/quotaops.h>
2683 +#include <asm/semaphore.h>
2684 +#include <linux/compatmac.h>
2685 +
2686 +#define EXT3_EA_USER "user."
2687 +
2688 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2689 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2690 +#endif
2691 +
2692 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2693 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2694 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2695 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2696 +
2697 +#ifdef EXT3_XATTR_DEBUG
2698 +# define ea_idebug(inode, f...) do { \
2699 +               printk(KERN_DEBUG "inode %s:%ld: ", \
2700 +                       kdevname(inode->i_dev), inode->i_ino); \
2701 +               printk(f); \
2702 +               printk("\n"); \
2703 +       } while (0)
2704 +# define ea_bdebug(bh, f...) do { \
2705 +               printk(KERN_DEBUG "block %s:%ld: ", \
2706 +                       kdevname(bh->b_dev), bh->b_blocknr); \
2707 +               printk(f); \
2708 +               printk("\n"); \
2709 +       } while (0)
2710 +#else
2711 +# define ea_idebug(f...)
2712 +# define ea_bdebug(f...)
2713 +#endif
2714 +
2715 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2716 +                          struct ext3_xattr_header *);
2717 +
2718 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2719 +
2720 +static int ext3_xattr_cache_insert(struct buffer_head *);
2721 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2722 +                                                struct ext3_xattr_header *);
2723 +static void ext3_xattr_cache_remove(struct buffer_head *);
2724 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2725 +                             struct ext3_xattr_entry *);
2726 +
2727 +static struct mb_cache *ext3_xattr_cache;
2728 +
2729 +#else
2730 +# define ext3_xattr_cache_insert(bh) 0
2731 +# define ext3_xattr_cache_find(inode, header) NULL
2732 +# define ext3_xattr_cache_remove(bh) while(0) {}
2733 +# define ext3_xattr_rehash(header, entry) while(0) {}
2734 +#endif
2735 +
2736 +/*
2737 + * If a file system does not share extended attributes among inodes,
2738 + * we should not need the ext3_xattr_sem semaphore. However, the
2739 + * filesystem may still contain shared blocks, so we always take
2740 + * the lock.
2741 + */
2742 +
2743 +DECLARE_MUTEX(ext3_xattr_sem);
2744 +
2745 +static inline int
2746 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2747 +                    int * errp, int force)
2748 +{
2749 +       struct super_block *sb = inode->i_sb;
2750 +       int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2751 +               EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2752 +
2753 +       /* How can we enforce the allocation? */
2754 +       int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2755 +#ifdef OLD_QUOTAS
2756 +       if (!*errp)
2757 +               inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2758 +#endif
2759 +       return block;
2760 +}
2761 +
2762 +static inline int
2763 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2764 +{
2765 +       /* How can we enforce the allocation? */
2766 +#ifdef OLD_QUOTAS
2767 +       int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2768 +       if (!error)
2769 +               inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2770 +#else
2771 +       int error = DQUOT_ALLOC_BLOCK(inode, 1);
2772 +#endif
2773 +       return error;
2774 +}
2775 +
2776 +#ifdef OLD_QUOTAS
2777 +
2778 +static inline void
2779 +ext3_xattr_quota_free(struct inode *inode)
2780 +{
2781 +       DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2782 +       inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2783 +}
2784 +
2785 +static inline void
2786 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2787 +                     unsigned long block)
2788 +{
2789 +       ext3_free_blocks(handle, inode, block, 1);
2790 +       inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2791 +}
2792 +
2793 +#else
2794 +# define ext3_xattr_quota_free(inode) \
2795 +       DQUOT_FREE_BLOCK(inode, 1)
2796 +# define ext3_xattr_free_block(handle, inode, block) \
2797 +       ext3_free_blocks(handle, inode, block, 1)
2798 +#endif
2799 +
2800 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2801 +
2802 +static inline struct buffer_head *
2803 +sb_bread(struct super_block *sb, int block)
2804 +{
2805 +       return bread(sb->s_dev, block, sb->s_blocksize);
2806 +}
2807 +
2808 +static inline struct buffer_head *
2809 +sb_getblk(struct super_block *sb, int block)
2810 +{
2811 +       return getblk(sb->s_dev, block, sb->s_blocksize);
2812 +}
2813 +
2814 +#endif
2815 +
2816 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2817 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2818 +
2819 +int
2820 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2821 +{
2822 +       int error = -EINVAL;
2823 +
2824 +       if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2825 +               write_lock(&ext3_handler_lock);
2826 +               if (!ext3_xattr_handlers[name_index-1]) {
2827 +                       ext3_xattr_handlers[name_index-1] = handler;
2828 +                       error = 0;
2829 +               }
2830 +               write_unlock(&ext3_handler_lock);
2831 +       }
2832 +       return error;
2833 +}
2834 +
2835 +void
2836 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2837 +{
2838 +       if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2839 +               write_lock(&ext3_handler_lock);
2840 +               ext3_xattr_handlers[name_index-1] = NULL;
2841 +               write_unlock(&ext3_handler_lock);
2842 +       }
2843 +}
2844 +
2845 +static inline const char *
2846 +strcmp_prefix(const char *a, const char *a_prefix)
2847 +{
2848 +       while (*a_prefix && *a == *a_prefix) {
2849 +               a++;
2850 +               a_prefix++;
2851 +       }
2852 +       return *a_prefix ? NULL : a;
2853 +}
2854 +
2855 +/*
2856 + * Decode the extended attribute name, and translate it into
2857 + * the name_index and name suffix.
2858 + */
2859 +static inline struct ext3_xattr_handler *
2860 +ext3_xattr_resolve_name(const char **name)
2861 +{
2862 +       struct ext3_xattr_handler *handler = NULL;
2863 +       int i;
2864 +
2865 +       if (!*name)
2866 +               return NULL;
2867 +       read_lock(&ext3_handler_lock);
2868 +       for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2869 +               if (ext3_xattr_handlers[i]) {
2870 +                       const char *n = strcmp_prefix(*name,
2871 +                               ext3_xattr_handlers[i]->prefix);
2872 +                       if (n) {
2873 +                               handler = ext3_xattr_handlers[i];
2874 +                               *name = n;
2875 +                               break;
2876 +                       }
2877 +               }
2878 +       }
2879 +       read_unlock(&ext3_handler_lock);
2880 +       return handler;
2881 +}
2882 +
2883 +static inline struct ext3_xattr_handler *
2884 +ext3_xattr_handler(int name_index)
2885 +{
2886 +       struct ext3_xattr_handler *handler = NULL;
2887 +       if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2888 +               read_lock(&ext3_handler_lock);
2889 +               handler = ext3_xattr_handlers[name_index-1];
2890 +               read_unlock(&ext3_handler_lock);
2891 +       }
2892 +       return handler;
2893 +}
2894 +
2895 +/*
2896 + * Inode operation getxattr()
2897 + *
2898 + * dentry->d_inode->i_sem down
2899 + * BKL held [before 2.5.x]
2900 + */
2901 +ssize_t
2902 +ext3_getxattr(struct dentry *dentry, const char *name,
2903 +             void *buffer, size_t size)
2904 +{
2905 +       struct ext3_xattr_handler *handler;
2906 +       struct inode *inode = dentry->d_inode;
2907 +
2908 +       handler = ext3_xattr_resolve_name(&name);
2909 +       if (!handler)
2910 +               return -ENOTSUP;
2911 +       return handler->get(inode, name, buffer, size);
2912 +}
2913 +
2914 +/*
2915 + * Inode operation listxattr()
2916 + *
2917 + * dentry->d_inode->i_sem down
2918 + * BKL held [before 2.5.x]
2919 + */
2920 +ssize_t
2921 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
2922 +{
2923 +       return ext3_xattr_list(dentry->d_inode, buffer, size);
2924 +}
2925 +
2926 +/*
2927 + * Inode operation setxattr()
2928 + *
2929 + * dentry->d_inode->i_sem down
2930 + * BKL held [before 2.5.x]
2931 + */
2932 +int
2933 +ext3_setxattr(struct dentry *dentry, const char *name,
2934 +             const void *value, size_t size, int flags)
2935 +{
2936 +       struct ext3_xattr_handler *handler;
2937 +       struct inode *inode = dentry->d_inode;
2938 +
2939 +       if (size == 0)
2940 +               value = "";  /* empty EA, do not remove */
2941 +       handler = ext3_xattr_resolve_name(&name);
2942 +       if (!handler)
2943 +               return -ENOTSUP;
2944 +       return handler->set(inode, name, value, size, flags);
2945 +}
2946 +
2947 +/*
2948 + * Inode operation removexattr()
2949 + *
2950 + * dentry->d_inode->i_sem down
2951 + * BKL held [before 2.5.x]
2952 + */
2953 +int
2954 +ext3_removexattr(struct dentry *dentry, const char *name)
2955 +{
2956 +       struct ext3_xattr_handler *handler;
2957 +       struct inode *inode = dentry->d_inode;
2958 +
2959 +       handler = ext3_xattr_resolve_name(&name);
2960 +       if (!handler)
2961 +               return -ENOTSUP;
2962 +       return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
2963 +}
2964 +
2965 +/*
2966 + * ext3_xattr_get()
2967 + *
2968 + * Copy an extended attribute into the buffer
2969 + * provided, or compute the buffer size required.
2970 + * Buffer is NULL to compute the size of the buffer required.
2971 + *
2972 + * Returns a negative error number on failure, or the number of bytes
2973 + * used / required on success.
2974 + */
2975 +int
2976 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
2977 +              void *buffer, size_t buffer_size)
2978 +{
2979 +       struct buffer_head *bh = NULL;
2980 +       struct ext3_xattr_entry *entry;
2981 +       unsigned int block, size;
2982 +       char *end;
2983 +       int name_len, error;
2984 +
2985 +       ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
2986 +                 name_index, name, buffer, (long)buffer_size);
2987 +
2988 +       if (name == NULL)
2989 +               return -EINVAL;
2990 +       if (!EXT3_I(inode)->i_file_acl)
2991 +               return -ENOATTR;
2992 +       block = EXT3_I(inode)->i_file_acl;
2993 +       ea_idebug(inode, "reading block %d", block);
2994 +       bh = sb_bread(inode->i_sb, block);
2995 +       if (!bh)
2996 +               return -EIO;
2997 +       ea_bdebug(bh, "b_count=%d, refcount=%d",
2998 +               atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
2999 +       end = bh->b_data + bh->b_size;
3000 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3001 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
3002 +bad_block:     ext3_error(inode->i_sb, "ext3_xattr_get",
3003 +                       "inode %ld: bad block %d", inode->i_ino, block);
3004 +               error = -EIO;
3005 +               goto cleanup;
3006 +       }
3007 +       /* find named attribute */
3008 +       name_len = strlen(name);
3009 +
3010 +       error = -ERANGE;
3011 +       if (name_len > 255)
3012 +               goto cleanup;
3013 +       entry = FIRST_ENTRY(bh);
3014 +       while (!IS_LAST_ENTRY(entry)) {
3015 +               struct ext3_xattr_entry *next =
3016 +                       EXT3_XATTR_NEXT(entry);
3017 +               if ((char *)next >= end)
3018 +                       goto bad_block;
3019 +               if (name_index == entry->e_name_index &&
3020 +                   name_len == entry->e_name_len &&
3021 +                   memcmp(name, entry->e_name, name_len) == 0)
3022 +                       goto found;
3023 +               entry = next;
3024 +       }
3025 +       /* Check the remaining name entries */
3026 +       while (!IS_LAST_ENTRY(entry)) {
3027 +               struct ext3_xattr_entry *next =
3028 +                       EXT3_XATTR_NEXT(entry);
3029 +               if ((char *)next >= end)
3030 +                       goto bad_block;
3031 +               entry = next;
3032 +       }
3033 +       if (ext3_xattr_cache_insert(bh))
3034 +               ea_idebug(inode, "cache insert failed");
3035 +       error = -ENOATTR;
3036 +       goto cleanup;
3037 +found:
3038 +       /* check the buffer size */
3039 +       if (entry->e_value_block != 0)
3040 +               goto bad_block;
3041 +       size = le32_to_cpu(entry->e_value_size);
3042 +       if (size > inode->i_sb->s_blocksize ||
3043 +           le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
3044 +               goto bad_block;
3045 +
3046 +       if (ext3_xattr_cache_insert(bh))
3047 +               ea_idebug(inode, "cache insert failed");
3048 +       if (buffer) {
3049 +               error = -ERANGE;
3050 +               if (size > buffer_size)
3051 +                       goto cleanup;
3052 +               /* return value of attribute */
3053 +               memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
3054 +                       size);
3055 +       }
3056 +       error = size;
3057 +
3058 +cleanup:
3059 +       brelse(bh);
3060 +
3061 +       return error;
3062 +}
3063 +
3064 +/*
3065 + * ext3_xattr_list()
3066 + *
3067 + * Copy a list of attribute names into the buffer
3068 + * provided, or compute the buffer size required.
3069 + * Buffer is NULL to compute the size of the buffer required.
3070 + *
3071 + * Returns a negative error number on failure, or the number of bytes
3072 + * used / required on success.
3073 + */
3074 +int
3075 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
3076 +{
3077 +       struct buffer_head *bh = NULL;
3078 +       struct ext3_xattr_entry *entry;
3079 +       unsigned int block, size = 0;
3080 +       char *buf, *end;
3081 +       int error;
3082 +
3083 +       ea_idebug(inode, "buffer=%p, buffer_size=%ld",
3084 +                 buffer, (long)buffer_size);
3085 +
3086 +       if (!EXT3_I(inode)->i_file_acl)
3087 +               return 0;
3088 +       block = EXT3_I(inode)->i_file_acl;
3089 +       ea_idebug(inode, "reading block %d", block);
3090 +       bh = sb_bread(inode->i_sb, block);
3091 +       if (!bh)
3092 +               return -EIO;
3093 +       ea_bdebug(bh, "b_count=%d, refcount=%d",
3094 +               atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3095 +       end = bh->b_data + bh->b_size;
3096 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3097 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
3098 +bad_block:     ext3_error(inode->i_sb, "ext3_xattr_list",
3099 +                       "inode %ld: bad block %d", inode->i_ino, block);
3100 +               error = -EIO;
3101 +               goto cleanup;
3102 +       }
3103 +       /* compute the size required for the list of attribute names */
3104 +       for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3105 +            entry = EXT3_XATTR_NEXT(entry)) {
3106 +               struct ext3_xattr_handler *handler;
3107 +               struct ext3_xattr_entry *next =
3108 +                       EXT3_XATTR_NEXT(entry);
3109 +               if ((char *)next >= end)
3110 +                       goto bad_block;
3111 +
3112 +               handler = ext3_xattr_handler(entry->e_name_index);
3113 +               if (handler)
3114 +                       size += handler->list(NULL, inode, entry->e_name,
3115 +                                             entry->e_name_len);
3116 +       }
3117 +
3118 +       if (ext3_xattr_cache_insert(bh))
3119 +               ea_idebug(inode, "cache insert failed");
3120 +       if (!buffer) {
3121 +               error = size;
3122 +               goto cleanup;
3123 +       } else {
3124 +               error = -ERANGE;
3125 +               if (size > buffer_size)
3126 +                       goto cleanup;
3127 +       }
3128 +
3129 +       /* list the attribute names */
3130 +       buf = buffer;
3131 +       for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3132 +            entry = EXT3_XATTR_NEXT(entry)) {
3133 +               struct ext3_xattr_handler *handler;
3134 +
3135 +               handler = ext3_xattr_handler(entry->e_name_index);
3136 +               if (handler)
3137 +                       buf += handler->list(buf, inode, entry->e_name,
3138 +                                            entry->e_name_len);
3139 +       }
3140 +       error = size;
3141 +
3142 +cleanup:
3143 +       brelse(bh);
3144 +
3145 +       return error;
3146 +}
3147 +
3148 +/*
3149 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3150 + * not set, set it.
3151 + */
3152 +static void ext3_xattr_update_super_block(handle_t *handle,
3153 +                                         struct super_block *sb)
3154 +{
3155 +       if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3156 +               return;
3157 +
3158 +       lock_super(sb);
3159 +       ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3160 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3161 +       EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3162 +#endif
3163 +       EXT3_SB(sb)->s_es->s_feature_compat |=
3164 +               cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3165 +       sb->s_dirt = 1;
3166 +       ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3167 +       unlock_super(sb);
3168 +}
3169 +
3170 +/*
3171 + * ext3_xattr_set()
3172 + *
3173 + * Create, replace or remove an extended attribute for this inode. Buffer
3174 + * is NULL to remove an existing extended attribute, and non-NULL to
3175 + * either replace an existing extended attribute, or create a new extended
3176 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3177 + * specify that an extended attribute must exist and must not exist
3178 + * previous to the call, respectively.
3179 + *
3180 + * Returns 0, or a negative error number on failure.
3181 + */
3182 +int
3183 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3184 +              const char *name, const void *value, size_t value_len, int flags)
3185 +{
3186 +       struct super_block *sb = inode->i_sb;
3187 +       struct buffer_head *bh = NULL;
3188 +       struct ext3_xattr_header *header = NULL;
3189 +       struct ext3_xattr_entry *here, *last;
3190 +       unsigned int name_len;
3191 +       int block = EXT3_I(inode)->i_file_acl;
3192 +       int min_offs = sb->s_blocksize, not_found = 1, free, error;
3193 +       char *end;
3194 +       
3195 +       /*
3196 +        * header -- Points either into bh, or to a temporarily
3197 +        *           allocated buffer.
3198 +        * here -- The named entry found, or the place for inserting, within
3199 +        *         the block pointed to by header.
3200 +        * last -- Points right after the last named entry within the block
3201 +        *         pointed to by header.
3202 +        * min_offs -- The offset of the first value (values are aligned
3203 +        *             towards the end of the block).
3204 +        * end -- Points right after the block pointed to by header.
3205 +        */
3206 +       
3207 +       ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3208 +                 name_index, name, value, (long)value_len);
3209 +
3210 +       if (IS_RDONLY(inode))
3211 +               return -EROFS;
3212 +       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3213 +               return -EPERM;
3214 +       if (value == NULL)
3215 +               value_len = 0;
3216 +       if (name == NULL)
3217 +               return -EINVAL;
3218 +       name_len = strlen(name);
3219 +       if (name_len > 255 || value_len > sb->s_blocksize)
3220 +               return -ERANGE;
3221 +       down(&ext3_xattr_sem);
3222 +
3223 +       if (block) {
3224 +               /* The inode already has an extended attribute block. */
3225 +               bh = sb_bread(sb, block);
3226 +               error = -EIO;
3227 +               if (!bh)
3228 +                       goto cleanup;
3229 +               ea_bdebug(bh, "b_count=%d, refcount=%d",
3230 +                       atomic_read(&(bh->b_count)),
3231 +                       le32_to_cpu(HDR(bh)->h_refcount));
3232 +               header = HDR(bh);
3233 +               end = bh->b_data + bh->b_size;
3234 +               if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3235 +                   header->h_blocks != cpu_to_le32(1)) {
3236 +bad_block:             ext3_error(sb, "ext3_xattr_set",
3237 +                               "inode %ld: bad block %d", inode->i_ino, block);
3238 +                       error = -EIO;
3239 +                       goto cleanup;
3240 +               }
3241 +               /* Find the named attribute. */
3242 +               here = FIRST_ENTRY(bh);
3243 +               while (!IS_LAST_ENTRY(here)) {
3244 +                       struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3245 +                       if ((char *)next >= end)
3246 +                               goto bad_block;
3247 +                       if (!here->e_value_block && here->e_value_size) {
3248 +                               int offs = le16_to_cpu(here->e_value_offs);
3249 +                               if (offs < min_offs)
3250 +                                       min_offs = offs;
3251 +                       }
3252 +                       not_found = name_index - here->e_name_index;
3253 +                       if (!not_found)
3254 +                               not_found = name_len - here->e_name_len;
3255 +                       if (!not_found)
3256 +                               not_found = memcmp(name, here->e_name,name_len);
3257 +                       if (not_found <= 0)
3258 +                               break;
3259 +                       here = next;
3260 +               }
3261 +               last = here;
3262 +               /* We still need to compute min_offs and last. */
3263 +               while (!IS_LAST_ENTRY(last)) {
3264 +                       struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3265 +                       if ((char *)next >= end)
3266 +                               goto bad_block;
3267 +                       if (!last->e_value_block && last->e_value_size) {
3268 +                               int offs = le16_to_cpu(last->e_value_offs);
3269 +                               if (offs < min_offs)
3270 +                                       min_offs = offs;
3271 +                       }
3272 +                       last = next;
3273 +               }
3274 +
3275 +               /* Check whether we have enough space left. */
3276 +               free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3277 +       } else {
3278 +               /* We will use a new extended attribute block. */
3279 +               free = sb->s_blocksize -
3280 +                       sizeof(struct ext3_xattr_header) - sizeof(__u32);
3281 +               here = last = NULL;  /* avoid gcc uninitialized warning. */
3282 +       }
3283 +
3284 +       if (not_found) {
3285 +               /* Request to remove a nonexistent attribute? */
3286 +               error = -ENOATTR;
3287 +               if (flags & XATTR_REPLACE)
3288 +                       goto cleanup;
3289 +               error = 0;
3290 +               if (value == NULL)
3291 +                       goto cleanup;
3292 +               else
3293 +                       free -= EXT3_XATTR_LEN(name_len);
3294 +       } else {
3295 +               /* Request to create an existing attribute? */
3296 +               error = -EEXIST;
3297 +               if (flags & XATTR_CREATE)
3298 +                       goto cleanup;
3299 +               if (!here->e_value_block && here->e_value_size) {
3300 +                       unsigned int size = le32_to_cpu(here->e_value_size);
3301 +
3302 +                       if (le16_to_cpu(here->e_value_offs) + size > 
3303 +                           sb->s_blocksize || size > sb->s_blocksize)
3304 +                               goto bad_block;
3305 +                       free += EXT3_XATTR_SIZE(size);
3306 +               }
3307 +       }
3308 +       free -= EXT3_XATTR_SIZE(value_len);
3309 +       error = -ENOSPC;
3310 +       if (free < 0)
3311 +               goto cleanup;
3312 +
3313 +       /* Here we know that we can set the new attribute. */
3314 +
3315 +       if (header) {
3316 +               if (header->h_refcount == cpu_to_le32(1)) {
3317 +                       ea_bdebug(bh, "modifying in-place");
3318 +                       ext3_xattr_cache_remove(bh);
3319 +                       error = ext3_journal_get_write_access(handle, bh);
3320 +                       if (error)
3321 +                               goto cleanup;
3322 +               } else {
3323 +                       int offset;
3324 +
3325 +                       ea_bdebug(bh, "cloning");
3326 +                       header = kmalloc(bh->b_size, GFP_KERNEL);
3327 +                       error = -ENOMEM;
3328 +                       if (header == NULL)
3329 +                               goto cleanup;
3330 +                       memcpy(header, HDR(bh), bh->b_size);
3331 +                       header->h_refcount = cpu_to_le32(1);
3332 +                       offset = (char *)header - bh->b_data;
3333 +                       here = ENTRY((char *)here + offset);
3334 +                       last = ENTRY((char *)last + offset);
3335 +               }
3336 +       } else {
3337 +               /* Allocate a buffer where we construct the new block. */
3338 +               header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3339 +               error = -ENOMEM;
3340 +               if (header == NULL)
3341 +                       goto cleanup;
3342 +               memset(header, 0, sb->s_blocksize);
3343 +               end = (char *)header + sb->s_blocksize;
3344 +               header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3345 +               header->h_blocks = header->h_refcount = cpu_to_le32(1);
3346 +               last = here = ENTRY(header+1);
3347 +       }
3348 +
3349 +       if (not_found) {
3350 +               /* Insert the new name. */
3351 +               int size = EXT3_XATTR_LEN(name_len);
3352 +               int rest = (char *)last - (char *)here;
3353 +               memmove((char *)here + size, here, rest);
3354 +               memset(here, 0, size);
3355 +               here->e_name_index = name_index;
3356 +               here->e_name_len = name_len;
3357 +               memcpy(here->e_name, name, name_len);
3358 +       } else {
3359 +               /* Remove the old value. */
3360 +               if (!here->e_value_block && here->e_value_size) {
3361 +                       char *first_val = (char *)header + min_offs;
3362 +                       int offs = le16_to_cpu(here->e_value_offs);
3363 +                       char *val = (char *)header + offs;
3364 +                       size_t size = EXT3_XATTR_SIZE(
3365 +                               le32_to_cpu(here->e_value_size));
3366 +                       memmove(first_val + size, first_val, val - first_val);
3367 +                       memset(first_val, 0, size);
3368 +                       here->e_value_offs = 0;
3369 +                       min_offs += size;
3370 +
3371 +                       /* Adjust all value offsets. */
3372 +                       last = ENTRY(header+1);
3373 +                       while (!IS_LAST_ENTRY(last)) {
3374 +                               int o = le16_to_cpu(last->e_value_offs);
3375 +                               if (!last->e_value_block && o < offs)
3376 +                                       last->e_value_offs =
3377 +                                               cpu_to_le16(o + size);
3378 +                               last = EXT3_XATTR_NEXT(last);
3379 +                       }
3380 +               }
3381 +               if (value == NULL) {
3382 +                       /* Remove this attribute. */
3383 +                       if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3384 +                               /* This block is now empty. */
3385 +                               error = ext3_xattr_set2(handle, inode, bh,NULL);
3386 +                               goto cleanup;
3387 +                       } else {
3388 +                               /* Remove the old name. */
3389 +                               int size = EXT3_XATTR_LEN(name_len);
3390 +                               last = ENTRY((char *)last - size);
3391 +                               memmove(here, (char*)here + size,
3392 +                                       (char*)last - (char*)here);
3393 +                               memset(last, 0, size);
3394 +                       }
3395 +               }
3396 +       }
3397 +
3398 +       if (value != NULL) {
3399 +               /* Insert the new value. */
3400 +               here->e_value_size = cpu_to_le32(value_len);
3401 +               if (value_len) {
3402 +                       size_t size = EXT3_XATTR_SIZE(value_len);
3403 +                       char *val = (char *)header + min_offs - size;
3404 +                       here->e_value_offs =
3405 +                               cpu_to_le16((char *)val - (char *)header);
3406 +                       memset(val + size - EXT3_XATTR_PAD, 0,
3407 +                              EXT3_XATTR_PAD); /* Clear the pad bytes. */
3408 +                       memcpy(val, value, value_len);
3409 +               }
3410 +       }
3411 +       ext3_xattr_rehash(header, here);
3412 +
3413 +       error = ext3_xattr_set2(handle, inode, bh, header);
3414 +
3415 +cleanup:
3416 +       brelse(bh);
3417 +       if (!(bh && header == HDR(bh)))
3418 +               kfree(header);
3419 +       up(&ext3_xattr_sem);
3420 +
3421 +       return error;
3422 +}
3423 +
3424 +/*
3425 + * Second half of ext3_xattr_set(): Update the file system.
3426 + */
3427 +static int
3428 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3429 +               struct buffer_head *old_bh, struct ext3_xattr_header *header)
3430 +{
3431 +       struct super_block *sb = inode->i_sb;
3432 +       struct buffer_head *new_bh = NULL;
3433 +       int error;
3434 +
3435 +       if (header) {
3436 +               new_bh = ext3_xattr_cache_find(inode, header);
3437 +               if (new_bh) {
3438 +                       /*
3439 +                        * We found an identical block in the cache.
3440 +                        * The old block will be released after updating
3441 +                        * the inode.
3442 +                        */
3443 +                       ea_bdebug(old_bh, "reusing block %ld",
3444 +                               new_bh->b_blocknr);
3445 +                       
3446 +                       error = -EDQUOT;
3447 +                       if (ext3_xattr_quota_alloc(inode, 1))
3448 +                               goto cleanup;
3449 +                       
3450 +                       error = ext3_journal_get_write_access(handle, new_bh);
3451 +                       if (error)
3452 +                               goto cleanup;
3453 +                       HDR(new_bh)->h_refcount = cpu_to_le32(
3454 +                               le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3455 +                       ea_bdebug(new_bh, "refcount now=%d",
3456 +                               le32_to_cpu(HDR(new_bh)->h_refcount));
3457 +               } else if (old_bh && header == HDR(old_bh)) {
3458 +                       /* Keep this block. */
3459 +                       new_bh = old_bh;
3460 +                       ext3_xattr_cache_insert(new_bh);
3461 +               } else {
3462 +                       /* We need to allocate a new block */
3463 +                       int force = EXT3_I(inode)->i_file_acl != 0;
3464 +                       int block = ext3_xattr_new_block(handle, inode,
3465 +                                                        &error, force);
3466 +                       if (error)
3467 +                               goto cleanup;
3468 +                       ea_idebug(inode, "creating block %d", block);
3469 +
3470 +                       new_bh = sb_getblk(sb, block);
3471 +                       if (!new_bh) {
3472 +getblk_failed:                 ext3_xattr_free_block(handle, inode, block);
3473 +                               error = -EIO;
3474 +                               goto cleanup;
3475 +                       }
3476 +                       lock_buffer(new_bh);
3477 +                       error = ext3_journal_get_create_access(handle, new_bh);
3478 +                       if (error) {
3479 +                               unlock_buffer(new_bh);
3480 +                               goto getblk_failed;
3481 +                       }
3482 +                       memcpy(new_bh->b_data, header, new_bh->b_size);
3483 +                       mark_buffer_uptodate(new_bh, 1);
3484 +                       unlock_buffer(new_bh);
3485 +                       ext3_xattr_cache_insert(new_bh);
3486 +                       
3487 +                       ext3_xattr_update_super_block(handle, sb);
3488 +               }
3489 +               error = ext3_journal_dirty_metadata(handle, new_bh);
3490 +               if (error)
3491 +                       goto cleanup;
3492 +       }
3493 +
3494 +       /* Update the inode. */
3495 +       EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3496 +       inode->i_ctime = CURRENT_TIME;
3497 +       ext3_mark_inode_dirty(handle, inode);
3498 +       if (IS_SYNC(inode))
3499 +               handle->h_sync = 1;
3500 +
3501 +       error = 0;
3502 +       if (old_bh && old_bh != new_bh) {
3503 +               /*
3504 +                * If there was an old block, and we are not still using it,
3505 +                * we now release the old block.
3506 +               */
3507 +               unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3508 +
3509 +               error = ext3_journal_get_write_access(handle, old_bh);
3510 +               if (error)
3511 +                       goto cleanup;
3512 +               if (refcount == 1) {
3513 +                       /* Free the old block. */
3514 +                       ea_bdebug(old_bh, "freeing");
3515 +                       ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3516 +
3517 +                       /* ext3_forget() calls bforget() for us, but we
3518 +                          let our caller release old_bh, so we need to
3519 +                          duplicate the handle before. */
3520 +                       get_bh(old_bh);
3521 +                       ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3522 +               } else {
3523 +                       /* Decrement the refcount only. */
3524 +                       refcount--;
3525 +                       HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3526 +                       ext3_xattr_quota_free(inode);
3527 +                       ext3_journal_dirty_metadata(handle, old_bh);
3528 +                       ea_bdebug(old_bh, "refcount now=%d", refcount);
3529 +               }
3530 +       }
3531 +
3532 +cleanup:
3533 +       if (old_bh != new_bh)
3534 +               brelse(new_bh);
3535 +
3536 +       return error;
3537 +}
3538 +
3539 +/*
3540 + * ext3_xattr_delete_inode()
3541 + *
3542 + * Free extended attribute resources associated with this inode. This
3543 + * is called immediately before an inode is freed.
3544 + */
3545 +void
3546 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3547 +{
3548 +       struct buffer_head *bh;
3549 +       unsigned int block = EXT3_I(inode)->i_file_acl;
3550 +
3551 +       if (!block)
3552 +               return;
3553 +       down(&ext3_xattr_sem);
3554 +
3555 +       bh = sb_bread(inode->i_sb, block);
3556 +       if (!bh) {
3557 +               ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3558 +                       "inode %ld: block %d read error", inode->i_ino, block);
3559 +               goto cleanup;
3560 +       }
3561 +       ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3562 +       if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3563 +           HDR(bh)->h_blocks != cpu_to_le32(1)) {
3564 +               ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3565 +                       "inode %ld: bad block %d", inode->i_ino, block);
3566 +               goto cleanup;
3567 +       }
3568 +       ext3_journal_get_write_access(handle, bh);
3569 +       ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3570 +       if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3571 +               ext3_xattr_cache_remove(bh);
3572 +               ext3_xattr_free_block(handle, inode, block);
3573 +               ext3_forget(handle, 1, inode, bh, block);
3574 +               bh = NULL;
3575 +       } else {
3576 +               HDR(bh)->h_refcount = cpu_to_le32(
3577 +                       le32_to_cpu(HDR(bh)->h_refcount) - 1);
3578 +               ext3_journal_dirty_metadata(handle, bh);
3579 +               if (IS_SYNC(inode))
3580 +                       handle->h_sync = 1;
3581 +               ext3_xattr_quota_free(inode);
3582 +       }
3583 +       EXT3_I(inode)->i_file_acl = 0;
3584 +
3585 +cleanup:
3586 +       brelse(bh);
3587 +       up(&ext3_xattr_sem);
3588 +}
3589 +
3590 +/*
3591 + * ext3_xattr_put_super()
3592 + *
3593 + * This is called when a file system is unmounted.
3594 + */
3595 +void
3596 +ext3_xattr_put_super(struct super_block *sb)
3597 +{
3598 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3599 +       mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3600 +#endif
3601 +}
3602 +
3603 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3604 +
3605 +/*
3606 + * ext3_xattr_cache_insert()
3607 + *
3608 + * Create a new entry in the extended attribute cache, and insert
3609 + * it unless such an entry is already in the cache.
3610 + *
3611 + * Returns 0, or a negative error number on failure.
3612 + */
3613 +static int
3614 +ext3_xattr_cache_insert(struct buffer_head *bh)
3615 +{
3616 +       __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3617 +       struct mb_cache_entry *ce;
3618 +       int error;
3619 +
3620 +       ce = mb_cache_entry_alloc(ext3_xattr_cache);
3621 +       if (!ce)
3622 +               return -ENOMEM;
3623 +       error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3624 +       if (error) {
3625 +               mb_cache_entry_free(ce);
3626 +               if (error == -EBUSY) {
3627 +                       ea_bdebug(bh, "already in cache (%d cache entries)",
3628 +                               atomic_read(&ext3_xattr_cache->c_entry_count));
3629 +                       error = 0;
3630 +               }
3631 +       } else {
3632 +               ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3633 +                         atomic_read(&ext3_xattr_cache->c_entry_count));
3634 +               mb_cache_entry_release(ce);
3635 +       }
3636 +       return error;
3637 +}
3638 +
3639 +/*
3640 + * ext3_xattr_cmp()
3641 + *
3642 + * Compare two extended attribute blocks for equality.
3643 + *
3644 + * Returns 0 if the blocks are equal, 1 if they differ, and
3645 + * a negative error number on errors.
3646 + */
3647 +static int
3648 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3649 +              struct ext3_xattr_header *header2)
3650 +{
3651 +       struct ext3_xattr_entry *entry1, *entry2;
3652 +
3653 +       entry1 = ENTRY(header1+1);
3654 +       entry2 = ENTRY(header2+1);
3655 +       while (!IS_LAST_ENTRY(entry1)) {
3656 +               if (IS_LAST_ENTRY(entry2))
3657 +                       return 1;
3658 +               if (entry1->e_hash != entry2->e_hash ||
3659 +                   entry1->e_name_len != entry2->e_name_len ||
3660 +                   entry1->e_value_size != entry2->e_value_size ||
3661 +                   memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3662 +                       return 1;
3663 +               if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3664 +                       return -EIO;
3665 +               if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3666 +                          (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3667 +                          le32_to_cpu(entry1->e_value_size)))
3668 +                       return 1;
3669 +
3670 +               entry1 = EXT3_XATTR_NEXT(entry1);
3671 +               entry2 = EXT3_XATTR_NEXT(entry2);
3672 +       }
3673 +       if (!IS_LAST_ENTRY(entry2))
3674 +               return 1;
3675 +       return 0;
3676 +}
3677 +
3678 +/*
3679 + * ext3_xattr_cache_find()
3680 + *
3681 + * Find an identical extended attribute block.
3682 + *
3683 + * Returns a pointer to the block found, or NULL if such a block was
3684 + * not found or an error occurred.
3685 + */
3686 +static struct buffer_head *
3687 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3688 +{
3689 +       __u32 hash = le32_to_cpu(header->h_hash);
3690 +       struct mb_cache_entry *ce;
3691 +
3692 +       if (!header->h_hash)
3693 +               return NULL;  /* never share */
3694 +       ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3695 +       ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3696 +       while (ce) {
3697 +               struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3698 +
3699 +               if (!bh) {
3700 +                       ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3701 +                               "inode %ld: block %ld read error",
3702 +                               inode->i_ino, ce->e_block);
3703 +               } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3704 +                          EXT3_XATTR_REFCOUNT_MAX) {
3705 +                       ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3706 +                               le32_to_cpu(HDR(bh)->h_refcount),
3707 +                               EXT3_XATTR_REFCOUNT_MAX);
3708 +               } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3709 +                       ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3710 +                       mb_cache_entry_release(ce);
3711 +                       return bh;
3712 +               }
3713 +               brelse(bh);
3714 +               ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3715 +       }
3716 +       return NULL;
3717 +}
3718 +
3719 +/*
3720 + * ext3_xattr_cache_remove()
3721 + *
3722 + * Remove the cache entry of a block from the cache. Called when a
3723 + * block becomes invalid.
3724 + */
3725 +static void
3726 +ext3_xattr_cache_remove(struct buffer_head *bh)
3727 +{
3728 +       struct mb_cache_entry *ce;
3729 +
3730 +       ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3731 +       if (ce) {
3732 +               ea_bdebug(bh, "removing (%d cache entries remaining)",
3733 +                         atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3734 +               mb_cache_entry_free(ce);
3735 +       } else 
3736 +               ea_bdebug(bh, "no cache entry");
3737 +}
3738 +
3739 +#define NAME_HASH_SHIFT 5
3740 +#define VALUE_HASH_SHIFT 16
3741 +
3742 +/*
3743 + * ext3_xattr_hash_entry()
3744 + *
3745 + * Compute the hash of an extended attribute.
3746 + */
3747 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3748 +                                        struct ext3_xattr_entry *entry)
3749 +{
3750 +       __u32 hash = 0;
3751 +       char *name = entry->e_name;
3752 +       int n;
3753 +
3754 +       for (n=0; n < entry->e_name_len; n++) {
3755 +               hash = (hash << NAME_HASH_SHIFT) ^
3756 +                      (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3757 +                      *name++;
3758 +       }
3759 +
3760 +       if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3761 +               __u32 *value = (__u32 *)((char *)header +
3762 +                       le16_to_cpu(entry->e_value_offs));
3763 +               for (n = (le32_to_cpu(entry->e_value_size) +
3764 +                    EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3765 +                       hash = (hash << VALUE_HASH_SHIFT) ^
3766 +                              (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3767 +                              le32_to_cpu(*value++);
3768 +               }
3769 +       }
3770 +       entry->e_hash = cpu_to_le32(hash);
3771 +}
3772 +
3773 +#undef NAME_HASH_SHIFT
3774 +#undef VALUE_HASH_SHIFT
3775 +
3776 +#define BLOCK_HASH_SHIFT 16
3777 +
3778 +/*
3779 + * ext3_xattr_rehash()
3780 + *
3781 + * Re-compute the extended attribute hash value after an entry has changed.
3782 + */
3783 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3784 +                             struct ext3_xattr_entry *entry)
3785 +{
3786 +       struct ext3_xattr_entry *here;
3787 +       __u32 hash = 0;
3788 +       
3789 +       ext3_xattr_hash_entry(header, entry);
3790 +       here = ENTRY(header+1);
3791 +       while (!IS_LAST_ENTRY(here)) {
3792 +               if (!here->e_hash) {
3793 +                       /* Block is not shared if an entry's hash value == 0 */
3794 +                       hash = 0;
3795 +                       break;
3796 +               }
3797 +               hash = (hash << BLOCK_HASH_SHIFT) ^
3798 +                      (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3799 +                      le32_to_cpu(here->e_hash);
3800 +               here = EXT3_XATTR_NEXT(here);
3801 +       }
3802 +       header->h_hash = cpu_to_le32(hash);
3803 +}
3804 +
3805 +#undef BLOCK_HASH_SHIFT
3806 +
3807 +int __init
3808 +init_ext3_xattr(void)
3809 +{
3810 +       ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3811 +               sizeof(struct mb_cache_entry) +
3812 +               sizeof(struct mb_cache_entry_index), 1, 61);
3813 +       if (!ext3_xattr_cache)
3814 +               return -ENOMEM;
3815 +
3816 +       return 0;
3817 +}
3818 +
3819 +void
3820 +exit_ext3_xattr(void)
3821 +{
3822 +       if (ext3_xattr_cache)
3823 +               mb_cache_destroy(ext3_xattr_cache);
3824 +       ext3_xattr_cache = NULL;
3825 +}
3826 +
3827 +#else  /* CONFIG_EXT3_FS_XATTR_SHARING */
3828 +
3829 +int __init
3830 +init_ext3_xattr(void)
3831 +{
3832 +       return 0;
3833 +}
3834 +
3835 +void
3836 +exit_ext3_xattr(void)
3837 +{
3838 +}
3839 +
3840 +#endif  /* CONFIG_EXT3_FS_XATTR_SHARING */
3841 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
3842 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr_user.c        2003-07-12 15:34:44.000000000 -0600
3843 @@ -0,0 +1,111 @@
3844 +/*
3845 + * linux/fs/ext3/xattr_user.c
3846 + * Handler for extended user attributes.
3847 + *
3848 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3849 + */
3850 +
3851 +#include <linux/module.h>
3852 +#include <linux/string.h>
3853 +#include <linux/fs.h>
3854 +#include <linux/ext3_jbd.h>
3855 +#include <linux/ext3_fs.h>
3856 +#include <linux/ext3_xattr.h>
3857 +
3858 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3859 +# include <linux/ext3_acl.h>
3860 +#endif
3861 +
3862 +#define XATTR_USER_PREFIX "user."
3863 +
3864 +static size_t
3865 +ext3_xattr_user_list(char *list, struct inode *inode,
3866 +                    const char *name, int name_len)
3867 +{
3868 +       const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3869 +
3870 +       if (!test_opt(inode->i_sb, XATTR_USER))
3871 +               return 0;
3872 +
3873 +       if (list) {
3874 +               memcpy(list, XATTR_USER_PREFIX, prefix_len);
3875 +               memcpy(list+prefix_len, name, name_len);
3876 +               list[prefix_len + name_len] = '\0';
3877 +       }
3878 +       return prefix_len + name_len + 1;
3879 +}
3880 +
3881 +static int
3882 +ext3_xattr_user_get(struct inode *inode, const char *name,
3883 +                   void *buffer, size_t size)
3884 +{
3885 +       int error;
3886 +
3887 +       if (strcmp(name, "") == 0)
3888 +               return -EINVAL;
3889 +       if (!test_opt(inode->i_sb, XATTR_USER))
3890 +               return -ENOTSUP;
3891 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3892 +       error = ext3_permission_locked(inode, MAY_READ);
3893 +#else
3894 +       error = permission(inode, MAY_READ);
3895 +#endif
3896 +       if (error)
3897 +               return error;
3898 +
3899 +       return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
3900 +                             buffer, size);
3901 +}
3902 +
3903 +static int
3904 +ext3_xattr_user_set(struct inode *inode, const char *name,
3905 +                   const void *value, size_t size, int flags)
3906 +{
3907 +       handle_t *handle;
3908 +       int error;
3909 +
3910 +       if (strcmp(name, "") == 0)
3911 +               return -EINVAL;
3912 +       if (!test_opt(inode->i_sb, XATTR_USER))
3913 +               return -ENOTSUP;
3914 +       if ( !S_ISREG(inode->i_mode) &&
3915 +           (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
3916 +               return -EPERM;
3917 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3918 +       error = ext3_permission_locked(inode, MAY_WRITE);
3919 +#else
3920 +       error = permission(inode, MAY_WRITE);
3921 +#endif
3922 +       if (error)
3923 +               return error;
3924 +
3925 +       handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
3926 +       if (IS_ERR(handle))
3927 +               return PTR_ERR(handle);
3928 +       error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
3929 +                              value, size, flags);
3930 +       ext3_journal_stop(handle, inode);
3931 +
3932 +       return error;
3933 +}
3934 +
3935 +struct ext3_xattr_handler ext3_xattr_user_handler = {
3936 +       prefix: XATTR_USER_PREFIX,
3937 +       list:   ext3_xattr_user_list,
3938 +       get:    ext3_xattr_user_get,
3939 +       set:    ext3_xattr_user_set,
3940 +};
3941 +
3942 +int __init
3943 +init_ext3_xattr_user(void)
3944 +{
3945 +       return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
3946 +                                  &ext3_xattr_user_handler);
3947 +}
3948 +
3949 +void
3950 +exit_ext3_xattr_user(void)
3951 +{
3952 +       ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
3953 +                             &ext3_xattr_user_handler);
3954 +}
3955 --- kernel-2.4.20-6chaos_18_7/fs/jfs/jfs_xattr.h~linux-2.4.20-xattr-0.8.54-chaos        2003-02-14 15:59:11.000000000 -0700
3956 +++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/jfs_xattr.h  2003-07-12 15:34:44.000000000 -0600
3957 @@ -52,8 +52,10 @@ struct jfs_ea_list {
3958  #define        END_EALIST(ealist) \
3959         ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
3960  
3961 -extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
3962 -extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
3963 +extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
3964 +                         int);
3965 +extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
3966 +                       int);
3967  extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
3968  extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
3969  extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
3970 --- kernel-2.4.20-6chaos_18_7/fs/jfs/xattr.c~linux-2.4.20-xattr-0.8.54-chaos    2003-02-14 15:59:11.000000000 -0700
3971 +++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/xattr.c      2003-07-12 15:34:44.000000000 -0600
3972 @@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s
3973  }
3974  
3975  static int can_set_xattr(struct inode *inode, const char *name,
3976 -                        void *value, size_t value_len)
3977 +                        const void *value, size_t value_len)
3978  {
3979         if (IS_RDONLY(inode))
3980                 return -EROFS;
3981 @@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i
3982         return permission(inode, MAY_WRITE);
3983  }
3984  
3985 -int __jfs_setxattr(struct inode *inode, const char *name, void *value,
3986 +int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
3987                    size_t value_len, int flags)
3988  {
3989         struct jfs_ea_list *ealist;
3990 @@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode, 
3991         return rc;
3992  }
3993  
3994 -int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
3995 +int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
3996                  size_t value_len, int flags)
3997  {
3998         if (value == NULL) {    /* empty EA, do not remove */
3999 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
4000 +++ kernel-2.4.20-6chaos_18_7-braam/fs/mbcache.c        2003-07-12 15:34:44.000000000 -0600
4001 @@ -0,0 +1,648 @@
4002 +/*
4003 + * linux/fs/mbcache.c
4004 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4005 + */
4006 +
4007 +/*
4008 + * Filesystem Meta Information Block Cache (mbcache)
4009 + *
4010 + * The mbcache caches blocks of block devices that need to be located
4011 + * by their device/block number, as well as by other criteria (such
4012 + * as the block's contents).
4013 + *
4014 + * There can only be one cache entry in a cache per device and block number.
4015 + * Additional indexes need not be unique in this sense. The number of
4016 + * additional indexes (=other criteria) can be hardwired at compile time
4017 + * or specified at cache create time.
4018 + *
4019 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
4020 + * in the cache. A valid entry is in the main hash tables of the cache,
4021 + * and may also be in the lru list. An invalid entry is not in any hashes
4022 + * or lists.
4023 + *
4024 + * A valid cache entry is only in the lru list if no handles refer to it.
4025 + * Invalid cache entries will be freed when the last handle to the cache
4026 + * entry is released. Entries that cannot be freed immediately are put
4027 + * back on the lru list.
4028 + */
4029 +
4030 +#include <linux/kernel.h>
4031 +#include <linux/module.h>
4032 +
4033 +#include <linux/fs.h>
4034 +#include <linux/slab.h>
4035 +#include <linux/sched.h>
4036 +#include <linux/cache_def.h>
4037 +#include <linux/version.h>
4038 +#include <linux/init.h>
4039 +#include <linux/mbcache.h>
4040 +
4041 +
4042 +#ifdef MB_CACHE_DEBUG
4043 +# define mb_debug(f...) do { \
4044 +               printk(KERN_DEBUG f); \
4045 +               printk("\n"); \
4046 +       } while (0)
4047 +#define mb_assert(c) do { if (!(c)) \
4048 +               printk(KERN_ERR "assertion " #c " failed\n"); \
4049 +       } while(0)
4050 +#else
4051 +# define mb_debug(f...) do { } while(0)
4052 +# define mb_assert(c) do { } while(0)
4053 +#endif
4054 +#define mb_error(f...) do { \
4055 +               printk(KERN_ERR f); \
4056 +               printk("\n"); \
4057 +       } while(0)
4058 +               
4059 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
4060 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
4061 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4062 +MODULE_LICENSE("GPL");
4063 +#endif
4064 +
4065 +EXPORT_SYMBOL(mb_cache_create);
4066 +EXPORT_SYMBOL(mb_cache_shrink);
4067 +EXPORT_SYMBOL(mb_cache_destroy);
4068 +EXPORT_SYMBOL(mb_cache_entry_alloc);
4069 +EXPORT_SYMBOL(mb_cache_entry_insert);
4070 +EXPORT_SYMBOL(mb_cache_entry_release);
4071 +EXPORT_SYMBOL(mb_cache_entry_takeout);
4072 +EXPORT_SYMBOL(mb_cache_entry_free);
4073 +EXPORT_SYMBOL(mb_cache_entry_dup);
4074 +EXPORT_SYMBOL(mb_cache_entry_get);
4075 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4076 +EXPORT_SYMBOL(mb_cache_entry_find_first);
4077 +EXPORT_SYMBOL(mb_cache_entry_find_next);
4078 +#endif
4079 +
4080 +
4081 +/*
4082 + * Global data: list of all mbcache's, lru list, and a spinlock for
4083 + * accessing cache data structures on SMP machines. The lru list is
4084 + * global across all mbcaches.
4085 + */
4086 +
4087 +static LIST_HEAD(mb_cache_list);
4088 +static LIST_HEAD(mb_cache_lru_list);
4089 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
4090 +
4091 +static inline int
4092 +mb_cache_indexes(struct mb_cache *cache)
4093 +{
4094 +#ifdef MB_CACHE_INDEXES_COUNT
4095 +       return MB_CACHE_INDEXES_COUNT;
4096 +#else
4097 +       return cache->c_indexes_count;
4098 +#endif
4099 +}
4100 +
4101 +/*
4102 + * What the mbcache registers as to get shrunk dynamically.
4103 + */
4104 +
4105 +static void
4106 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
4107 +
4108 +static struct cache_definition mb_cache_definition = {
4109 +       "mb_cache",
4110 +       mb_cache_memory_pressure
4111 +};
4112 +
4113 +
4114 +static inline int
4115 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4116 +{
4117 +       return !list_empty(&ce->e_block_list);
4118 +}
4119 +
4120 +
4121 +static inline void
4122 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4123 +{
4124 +       int n;
4125 +
4126 +       if (__mb_cache_entry_is_hashed(ce)) {
4127 +               list_del_init(&ce->e_block_list);
4128 +               for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4129 +                       list_del(&ce->e_indexes[n].o_list);
4130 +       }
4131 +}
4132 +
4133 +
4134 +static inline void
4135 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4136 +{
4137 +       struct mb_cache *cache = ce->e_cache;
4138 +
4139 +       mb_assert(atomic_read(&ce->e_used) == 0);
4140 +       if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4141 +               /* free failed -- put back on the lru list
4142 +                  for freeing later. */
4143 +               spin_lock(&mb_cache_spinlock);
4144 +               list_add(&ce->e_lru_list, &mb_cache_lru_list);
4145 +               spin_unlock(&mb_cache_spinlock);
4146 +       } else {
4147 +               kmem_cache_free(cache->c_entry_cache, ce);
4148 +               atomic_dec(&cache->c_entry_count);
4149 +       }
4150 +}
4151 +
4152 +
4153 +static inline void
4154 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4155 +{
4156 +       if (atomic_dec_and_test(&ce->e_used)) {
4157 +               if (__mb_cache_entry_is_hashed(ce))
4158 +                       list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4159 +               else {
4160 +                       spin_unlock(&mb_cache_spinlock);
4161 +                       __mb_cache_entry_forget(ce, GFP_KERNEL);
4162 +                       return;
4163 +               }
4164 +       }
4165 +       spin_unlock(&mb_cache_spinlock);
4166 +}
4167 +
4168 +
4169 +/*
4170 + * mb_cache_memory_pressure()  memory pressure callback
4171 + *
4172 + * This function is called by the kernel memory management when memory
4173 + * gets low.
4174 + *
4175 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4176 + * @gfp_mask: (ignored)
4177 + */
4178 +static void
4179 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4180 +{
4181 +       LIST_HEAD(free_list);
4182 +       struct list_head *l, *ltmp;
4183 +       int count = 0;
4184 +
4185 +       spin_lock(&mb_cache_spinlock);
4186 +       list_for_each(l, &mb_cache_list) {
4187 +               struct mb_cache *cache =
4188 +                       list_entry(l, struct mb_cache, c_cache_list);
4189 +               mb_debug("cache %s (%d)", cache->c_name,
4190 +                         atomic_read(&cache->c_entry_count));
4191 +               count += atomic_read(&cache->c_entry_count);
4192 +       }
4193 +       mb_debug("trying to free %d of %d entries",
4194 +                 count / (priority ? priority : 1), count);
4195 +       if (priority)
4196 +               count /= priority;
4197 +       while (count-- && !list_empty(&mb_cache_lru_list)) {
4198 +               struct mb_cache_entry *ce =
4199 +                       list_entry(mb_cache_lru_list.next,
4200 +                                  struct mb_cache_entry, e_lru_list);
4201 +               list_del(&ce->e_lru_list);
4202 +               __mb_cache_entry_unhash(ce);
4203 +               list_add_tail(&ce->e_lru_list, &free_list);
4204 +       }
4205 +       spin_unlock(&mb_cache_spinlock);
4206 +       list_for_each_safe(l, ltmp, &free_list) {
4207 +               __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4208 +                                                  e_lru_list), gfp_mask);
4209 +       }
4210 +}
4211 +
4212 +
4213 +/*
4214 + * mb_cache_create()  create a new cache
4215 + *
4216 + * All entries in one cache are equal size. Cache entries may be from
4217 + * multiple devices. If this is the first mbcache created, registers
4218 + * the cache with kernel memory management. Returns NULL if no more
4219 + * memory was available.
4220 + *
4221 + * @name: name of the cache (informal)
4222 + * @cache_op: contains the callback called when freeing a cache entry
4223 + * @entry_size: The size of a cache entry, including
4224 + *              struct mb_cache_entry
4225 + * @indexes_count: number of additional indexes in the cache. Must equal
4226 + *                 MB_CACHE_INDEXES_COUNT if the number of indexes is
4227 + *                 hardwired.
4228 + * @bucket_count: number of hash buckets
4229 + */
4230 +struct mb_cache *
4231 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4232 +               size_t entry_size, int indexes_count, int bucket_count)
4233 +{
4234 +       int m=0, n;
4235 +       struct mb_cache *cache = NULL;
4236 +
4237 +       if(entry_size < sizeof(struct mb_cache_entry) +
4238 +          indexes_count * sizeof(struct mb_cache_entry_index))
4239 +               return NULL;
4240 +
4241 +       MOD_INC_USE_COUNT;
4242 +       cache = kmalloc(sizeof(struct mb_cache) +
4243 +                       indexes_count * sizeof(struct list_head), GFP_KERNEL);
4244 +       if (!cache)
4245 +               goto fail;
4246 +       cache->c_name = name;
4247 +       cache->c_op.free = NULL;
4248 +       if (cache_op)
4249 +               cache->c_op.free = cache_op->free;
4250 +       atomic_set(&cache->c_entry_count, 0);
4251 +       cache->c_bucket_count = bucket_count;
4252 +#ifdef MB_CACHE_INDEXES_COUNT
4253 +       mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4254 +#else
4255 +       cache->c_indexes_count = indexes_count;
4256 +#endif
4257 +       cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4258 +                                     GFP_KERNEL);
4259 +       if (!cache->c_block_hash)
4260 +               goto fail;
4261 +       for (n=0; n<bucket_count; n++)
4262 +               INIT_LIST_HEAD(&cache->c_block_hash[n]);
4263 +       for (m=0; m<indexes_count; m++) {
4264 +               cache->c_indexes_hash[m] = kmalloc(bucket_count *
4265 +                                                sizeof(struct list_head),
4266 +                                                GFP_KERNEL);
4267 +               if (!cache->c_indexes_hash[m])
4268 +                       goto fail;
4269 +               for (n=0; n<bucket_count; n++)
4270 +                       INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4271 +       }
4272 +       cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4273 +               0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4274 +       if (!cache->c_entry_cache)
4275 +               goto fail;
4276 +
4277 +       spin_lock(&mb_cache_spinlock);
4278 +       list_add(&cache->c_cache_list, &mb_cache_list);
4279 +       spin_unlock(&mb_cache_spinlock);
4280 +       return cache;
4281 +
4282 +fail:
4283 +       if (cache) {
4284 +               while (--m >= 0)
4285 +                       kfree(cache->c_indexes_hash[m]);
4286 +               if (cache->c_block_hash)
4287 +                       kfree(cache->c_block_hash);
4288 +               kfree(cache);
4289 +       }
4290 +       MOD_DEC_USE_COUNT;
4291 +       return NULL;
4292 +}
4293 +
4294 +
4295 +/*
4296 + * mb_cache_shrink()
4297 + *
4298 + * Removes all cache entires of a device from the cache. All cache entries
4299 + * currently in use cannot be freed, and thus remain in the cache.
4300 + *
4301 + * @cache: which cache to shrink
4302 + * @dev: which device's cache entries to shrink
4303 + */
4304 +void
4305 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4306 +{
4307 +       LIST_HEAD(free_list);
4308 +       struct list_head *l, *ltmp;
4309 +
4310 +       spin_lock(&mb_cache_spinlock);
4311 +       list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4312 +               struct mb_cache_entry *ce =
4313 +                       list_entry(l, struct mb_cache_entry, e_lru_list);
4314 +               if (ce->e_dev == dev) {
4315 +                       list_del(&ce->e_lru_list);
4316 +                       list_add_tail(&ce->e_lru_list, &free_list);
4317 +                       __mb_cache_entry_unhash(ce);
4318 +               }
4319 +       }
4320 +       spin_unlock(&mb_cache_spinlock);
4321 +       list_for_each_safe(l, ltmp, &free_list) {
4322 +               __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4323 +                                                  e_lru_list), GFP_KERNEL);
4324 +       }
4325 +}
4326 +
4327 +
4328 +/*
4329 + * mb_cache_destroy()
4330 + *
4331 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4332 + * and then destroys it. If this was the last mbcache, un-registers the
4333 + * mbcache from kernel memory management.
4334 + */
4335 +void
4336 +mb_cache_destroy(struct mb_cache *cache)
4337 +{
4338 +       LIST_HEAD(free_list);
4339 +       struct list_head *l, *ltmp;
4340 +       int n;
4341 +
4342 +       spin_lock(&mb_cache_spinlock);
4343 +       list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4344 +               struct mb_cache_entry *ce =
4345 +                       list_entry(l, struct mb_cache_entry, e_lru_list);
4346 +               if (ce->e_cache == cache) {
4347 +                       list_del(&ce->e_lru_list);
4348 +                       list_add_tail(&ce->e_lru_list, &free_list);
4349 +                       __mb_cache_entry_unhash(ce);
4350 +               }
4351 +       }
4352 +       list_del(&cache->c_cache_list);
4353 +       spin_unlock(&mb_cache_spinlock);
4354 +       list_for_each_safe(l, ltmp, &free_list) {
4355 +               __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4356 +                                                  e_lru_list), GFP_KERNEL);
4357 +       }
4358 +
4359 +       if (atomic_read(&cache->c_entry_count) > 0) {
4360 +               mb_error("cache %s: %d orphaned entries",
4361 +                         cache->c_name,
4362 +                         atomic_read(&cache->c_entry_count));
4363 +       }
4364 +
4365 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4366 +       /* We don't have kmem_cache_destroy() in 2.2.x */
4367 +       kmem_cache_shrink(cache->c_entry_cache);
4368 +#else
4369 +       kmem_cache_destroy(cache->c_entry_cache);
4370 +#endif
4371 +       for (n=0; n < mb_cache_indexes(cache); n++)
4372 +               kfree(cache->c_indexes_hash[n]);
4373 +       kfree(cache->c_block_hash);
4374 +       kfree(cache);
4375 +
4376 +       MOD_DEC_USE_COUNT;
4377 +}
4378 +
4379 +
4380 +/*
4381 + * mb_cache_entry_alloc()
4382 + *
4383 + * Allocates a new cache entry. The new entry will not be valid initially,
4384 + * and thus cannot be looked up yet. It should be filled with data, and
4385 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4386 + * if no more memory was available.
4387 + */
4388 +struct mb_cache_entry *
4389 +mb_cache_entry_alloc(struct mb_cache *cache)
4390 +{
4391 +       struct mb_cache_entry *ce;
4392 +
4393 +       atomic_inc(&cache->c_entry_count);
4394 +       ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4395 +       if (ce) {
4396 +               INIT_LIST_HEAD(&ce->e_lru_list);
4397 +               INIT_LIST_HEAD(&ce->e_block_list);
4398 +               ce->e_cache = cache;
4399 +               atomic_set(&ce->e_used, 1);
4400 +       }
4401 +       return ce;
4402 +}
4403 +
4404 +
4405 +/*
4406 + * mb_cache_entry_insert()
4407 + *
4408 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4409 + * the cache. After this, the cache entry can be looked up, but is not yet
4410 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4411 + * success, or -EBUSY if a cache entry for that device + inode exists
4412 + * already (this may happen after a failed lookup, if another process has
4413 + * inserted the same cache entry in the meantime).
4414 + *
4415 + * @dev: device the cache entry belongs to
4416 + * @block: block number
4417 + * @keys: array of additional keys. There must be indexes_count entries
4418 + *        in the array (as specified when creating the cache).
4419 + */
4420 +int
4421 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4422 +                     unsigned long block, unsigned int keys[])
4423 +{
4424 +       struct mb_cache *cache = ce->e_cache;
4425 +       unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4426 +       struct list_head *l;
4427 +       int error = -EBUSY, n;
4428 +
4429 +       spin_lock(&mb_cache_spinlock);
4430 +       list_for_each(l, &cache->c_block_hash[bucket]) {
4431 +               struct mb_cache_entry *ce =
4432 +                       list_entry(l, struct mb_cache_entry, e_block_list);
4433 +               if (ce->e_dev == dev && ce->e_block == block)
4434 +                       goto out;
4435 +       }
4436 +       __mb_cache_entry_unhash(ce);
4437 +       ce->e_dev = dev;
4438 +       ce->e_block = block;
4439 +       list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4440 +       for (n=0; n<mb_cache_indexes(cache); n++) {
4441 +               ce->e_indexes[n].o_key = keys[n];
4442 +               bucket = keys[n] % cache->c_bucket_count;
4443 +               list_add(&ce->e_indexes[n].o_list,
4444 +                        &cache->c_indexes_hash[n][bucket]);
4445 +       }
4446 +out:
4447 +       spin_unlock(&mb_cache_spinlock);
4448 +       return error;
4449 +}
4450 +
4451 +
4452 +/*
4453 + * mb_cache_entry_release()
4454 + *
4455 + * Release a handle to a cache entry. When the last handle to a cache entry
4456 + * is released it is either freed (if it is invalid) or otherwise inserted
4457 + * in to the lru list.
4458 + */
4459 +void
4460 +mb_cache_entry_release(struct mb_cache_entry *ce)
4461 +{
4462 +       spin_lock(&mb_cache_spinlock);
4463 +       __mb_cache_entry_release_unlock(ce);
4464 +}
4465 +
4466 +
4467 +/*
4468 + * mb_cache_entry_takeout()
4469 + *
4470 + * Take a cache entry out of the cache, making it invalid. The entry can later
4471 + * be re-inserted using mb_cache_entry_insert(), or released using
4472 + * mb_cache_entry_release().
4473 + */
4474 +void
4475 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4476 +{
4477 +       spin_lock(&mb_cache_spinlock);
4478 +       mb_assert(list_empty(&ce->e_lru_list));
4479 +       __mb_cache_entry_unhash(ce);
4480 +       spin_unlock(&mb_cache_spinlock);
4481 +}
4482 +
4483 +
4484 +/*
4485 + * mb_cache_entry_free()
4486 + *
4487 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4488 + * mb_cache_entry_release().
4489 + */
4490 +void
4491 +mb_cache_entry_free(struct mb_cache_entry *ce)
4492 +{
4493 +       spin_lock(&mb_cache_spinlock);
4494 +       mb_assert(list_empty(&ce->e_lru_list));
4495 +       __mb_cache_entry_unhash(ce);
4496 +       __mb_cache_entry_release_unlock(ce);
4497 +}
4498 +
4499 +
4500 +/*
4501 + * mb_cache_entry_dup()
4502 + *
4503 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4504 + * itself). After the call, both the old and the new handle must be released.
4505 + */
4506 +struct mb_cache_entry *
4507 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4508 +{
4509 +       atomic_inc(&ce->e_used);
4510 +       return ce;
4511 +}
4512 +
4513 +
4514 +/*
4515 + * mb_cache_entry_get()
4516 + *
4517 + * Get a cache entry  by device / block number. (There can only be one entry
4518 + * in the cache per device and block.) Returns NULL if no such cache entry
4519 + * exists.
4520 + */
4521 +struct mb_cache_entry *
4522 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4523 +{
4524 +       unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4525 +       struct list_head *l;
4526 +       struct mb_cache_entry *ce;
4527 +
4528 +       spin_lock(&mb_cache_spinlock);
4529 +       list_for_each(l, &cache->c_block_hash[bucket]) {
4530 +               ce = list_entry(l, struct mb_cache_entry, e_block_list);
4531 +               if (ce->e_dev == dev && ce->e_block == block) {
4532 +                       if (!list_empty(&ce->e_lru_list))
4533 +                               list_del_init(&ce->e_lru_list);
4534 +                       atomic_inc(&ce->e_used);
4535 +                       goto cleanup;
4536 +               }
4537 +       }
4538 +       ce = NULL;
4539 +
4540 +cleanup:
4541 +       spin_unlock(&mb_cache_spinlock);
4542 +       return ce;
4543 +}
4544 +
4545 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4546 +
4547 +static struct mb_cache_entry *
4548 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4549 +                     int index, kdev_t dev, unsigned int key)
4550 +{
4551 +       while (l != head) {
4552 +               struct mb_cache_entry *ce =
4553 +                       list_entry(l, struct mb_cache_entry,
4554 +                                  e_indexes[index].o_list);
4555 +               if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4556 +                       if (!list_empty(&ce->e_lru_list))
4557 +                               list_del_init(&ce->e_lru_list);
4558 +                       atomic_inc(&ce->e_used);
4559 +                       return ce;
4560 +               }
4561 +               l = l->next;
4562 +       }
4563 +       return NULL;
4564 +}
4565 +
4566 +
4567 +/*
4568 + * mb_cache_entry_find_first()
4569 + *
4570 + * Find the first cache entry on a given device with a certain key in
4571 + * an additional index. Additonal matches can be found with
4572 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4573 + *
4574 + * @cache: the cache to search
4575 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4576 + * @dev: the device the cache entry should belong to
4577 + * @key: the key in the index
4578 + */
4579 +struct mb_cache_entry *
4580 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4581 +                         unsigned int key)
4582 +{
4583 +       unsigned int bucket = key % cache->c_bucket_count;
4584 +       struct list_head *l;
4585 +       struct mb_cache_entry *ce;
4586 +
4587 +       mb_assert(index < mb_cache_indexes(cache));
4588 +       spin_lock(&mb_cache_spinlock);
4589 +       l = cache->c_indexes_hash[index][bucket].next;
4590 +       ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4591 +                                  index, dev, key);
4592 +       spin_unlock(&mb_cache_spinlock);
4593 +       return ce;
4594 +}
4595 +
4596 +
4597 +/*
4598 + * mb_cache_entry_find_next()
4599 + *
4600 + * Find the next cache entry on a given device with a certain key in an
4601 + * additional index. Returns NULL if no match could be found. The previous
4602 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4603 + * be called like this:
4604 + *
4605 + * entry = mb_cache_entry_find_first();
4606 + * while (entry) {
4607 + *     ...
4608 + *     entry = mb_cache_entry_find_next(entry, ...);
4609 + * }
4610 + *
4611 + * @prev: The previous match
4612 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4613 + * @dev: the device the cache entry should belong to
4614 + * @key: the key in the index
4615 + */
4616 +struct mb_cache_entry *
4617 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4618 +                        unsigned int key)
4619 +{
4620 +       struct mb_cache *cache = prev->e_cache;
4621 +       unsigned int bucket = key % cache->c_bucket_count;
4622 +       struct list_head *l;
4623 +       struct mb_cache_entry *ce;
4624 +
4625 +       mb_assert(index < mb_cache_indexes(cache));
4626 +       spin_lock(&mb_cache_spinlock);
4627 +       l = prev->e_indexes[index].o_list.next;
4628 +       ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4629 +                                  index, dev, key);
4630 +       __mb_cache_entry_release_unlock(prev);
4631 +       return ce;
4632 +}
4633 +
4634 +#endif  /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4635 +
4636 +static int __init init_mbcache(void)
4637 +{
4638 +       register_cache(&mb_cache_definition);
4639 +       return 0;
4640 +}
4641 +
4642 +static void __exit exit_mbcache(void)
4643 +{
4644 +       unregister_cache(&mb_cache_definition);
4645 +}
4646 +
4647 +module_init(init_mbcache)
4648 +module_exit(exit_mbcache)
4649 +
4650 --- kernel-2.4.20-6chaos_18_7/include/asm-arm/unistd.h~linux-2.4.20-xattr-0.8.54-chaos  2003-05-15 21:14:42.000000000 -0600
4651 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-arm/unistd.h    2003-07-12 15:34:44.000000000 -0600
4652 @@ -244,7 +244,6 @@
4653  #define __NR_security                  (__NR_SYSCALL_BASE+223)
4654  #define __NR_gettid                    (__NR_SYSCALL_BASE+224)
4655  #define __NR_readahead                 (__NR_SYSCALL_BASE+225)
4656 -#if 0 /* allocated in 2.5 */
4657  #define __NR_setxattr                  (__NR_SYSCALL_BASE+226)
4658  #define __NR_lsetxattr                 (__NR_SYSCALL_BASE+227)
4659  #define __NR_fsetxattr                 (__NR_SYSCALL_BASE+228)
4660 @@ -257,7 +256,6 @@
4661  #define __NR_removexattr               (__NR_SYSCALL_BASE+235)
4662  #define __NR_lremovexattr              (__NR_SYSCALL_BASE+236)
4663  #define __NR_fremovexattr              (__NR_SYSCALL_BASE+237)
4664 -#endif
4665  #define __NR_tkill                     (__NR_SYSCALL_BASE+238)
4666  /*
4667   * Please check 2.5 _before_ adding calls here,
4668 --- kernel-2.4.20-6chaos_18_7/include/asm-ppc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos        2002-09-25 11:13:42.000000000 -0600
4669 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-ppc64/unistd.h  2003-07-12 15:34:44.000000000 -0600
4670 @@ -218,6 +218,7 @@
4671  #define __NR_gettid            207
4672  #if 0 /* Reserved syscalls */
4673  #define __NR_tkill             208
4674 +#endif
4675  #define __NR_setxattr          209
4676  #define __NR_lsetxattr         210
4677  #define __NR_fsetxattr         211
4678 @@ -230,6 +231,7 @@
4679  #define __NR_removexattr       218
4680  #define __NR_lremovexattr      219
4681  #define __NR_fremovexattr      220
4682 +#if 0 /* Reserved syscalls */
4683  #define __NR_futex             221
4684  #endif
4685  
4686 --- kernel-2.4.20-6chaos_18_7/include/asm-s390/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:44.000000000 -0600
4687 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390/unistd.h   2003-07-12 15:34:44.000000000 -0600
4688 @@ -212,9 +212,18 @@
4689  #define __NR_madvise            219
4690  #define __NR_getdents64                220
4691  #define __NR_fcntl64           221
4692 -/*
4693 - * Numbers 224-235 are reserved for posix acl
4694 - */
4695 +#define __NR_setxattr          224
4696 +#define __NR_lsetxattr         225
4697 +#define __NR_fsetxattr         226
4698 +#define __NR_getxattr          227
4699 +#define __NR_lgetxattr         228
4700 +#define __NR_fgetxattr         229
4701 +#define __NR_listxattr         230
4702 +#define __NR_llistxattr                231
4703 +#define __NR_flistxattr                232
4704 +#define __NR_removexattr       233
4705 +#define __NR_lremovexattr      234
4706 +#define __NR_fremovexattr      235
4707  #define __NR_gettid            236
4708  #define __NR_tkill             237
4709  
4710 --- kernel-2.4.20-6chaos_18_7/include/asm-s390x/unistd.h~linux-2.4.20-xattr-0.8.54-chaos        2002-09-25 11:13:45.000000000 -0600
4711 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390x/unistd.h  2003-07-12 15:34:44.000000000 -0600
4712 @@ -180,9 +180,18 @@
4713  #define __NR_pivot_root         217
4714  #define __NR_mincore            218
4715  #define __NR_madvise            219
4716 -/*
4717 - * Numbers 224-235 are reserved for posix acl
4718 - */
4719 +#define __NR_setxattr          224
4720 +#define __NR_lsetxattr         225
4721 +#define __NR_fsetxattr         226
4722 +#define __NR_getxattr          227
4723 +#define __NR_lgetxattr         228
4724 +#define __NR_fgetxattr         229
4725 +#define __NR_listxattr         230
4726 +#define __NR_llistxattr                231
4727 +#define __NR_flistxattr                232
4728 +#define __NR_removexattr       233
4729 +#define __NR_lremovexattr      234
4730 +#define __NR_fremovexattr      235
4731  #define __NR_gettid            236
4732  #define __NR_tkill             237
4733  
4734 --- kernel-2.4.20-6chaos_18_7/include/asm-sparc/unistd.h~linux-2.4.20-xattr-0.8.54-chaos        2002-09-25 11:13:46.000000000 -0600
4735 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc/unistd.h  2003-07-12 15:34:44.000000000 -0600
4736 @@ -184,24 +184,24 @@
4737  /* #define __NR_exportfs        166    SunOS Specific                              */
4738  #define __NR_mount              167 /* Common                                      */
4739  #define __NR_ustat              168 /* Common                                      */
4740 -/* #define __NR_semsys          169    SunOS Specific                              */
4741 -/* #define __NR_msgsys          170    SunOS Specific                              */
4742 -/* #define __NR_shmsys          171    SunOS Specific                              */
4743 -/* #define __NR_auditsys        172    SunOS Specific                              */
4744 -/* #define __NR_rfssys          173    SunOS Specific                              */
4745 +#define __NR_setxattr           169 /* SunOS: semsys                               */
4746 +#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
4747 +#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
4748 +#define __NR_getxattr           172 /* SunOS: auditsys                             */
4749 +#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
4750  #define __NR_getdents           174 /* Common                                      */
4751  #define __NR_setsid             175 /* Common                                      */
4752  #define __NR_fchdir             176 /* Common                                      */
4753 -/* #define __NR_fchroot         177    SunOS Specific                              */
4754 -/* #define __NR_vpixsys         178    SunOS Specific                              */
4755 -/* #define __NR_aioread         179    SunOS Specific                              */
4756 -/* #define __NR_aiowrite        180    SunOS Specific                              */
4757 -/* #define __NR_aiowait         181    SunOS Specific                              */
4758 -/* #define __NR_aiocancel       182    SunOS Specific                              */
4759 +#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
4760 +#define __NR_listxattr          178 /* SunOS: vpixsys                              */
4761 +#define __NR_llistxattr         179 /* SunOS: aioread                              */
4762 +#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
4763 +#define __NR_removexattr        181 /* SunOS: aiowait                              */
4764 +#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
4765  #define __NR_sigpending         183 /* Common                                      */
4766  #define __NR_query_module      184 /* Linux Specific                              */
4767  #define __NR_setpgid            185 /* Common                                      */
4768 -/* #define __NR_pathconf        186    SunOS Specific                              */
4769 +#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
4770  #define __NR_tkill              187 /* SunOS: fpathconf                            */
4771  /* #define __NR_sysconf         188    SunOS Specific                              */
4772  #define __NR_uname              189 /* Linux Specific                              */
4773 --- kernel-2.4.20-6chaos_18_7/include/asm-sparc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos      2002-09-25 11:13:48.000000000 -0600
4774 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc64/unistd.h        2003-07-12 15:34:44.000000000 -0600
4775 @@ -184,24 +184,24 @@
4776  /* #define __NR_exportfs        166    SunOS Specific                              */
4777  #define __NR_mount              167 /* Common                                      */
4778  #define __NR_ustat              168 /* Common                                      */
4779 -/* #define __NR_semsys          169    SunOS Specific                              */
4780 -/* #define __NR_msgsys          170    SunOS Specific                              */
4781 -/* #define __NR_shmsys          171    SunOS Specific                              */
4782 -/* #define __NR_auditsys        172    SunOS Specific                              */
4783 -/* #define __NR_rfssys          173    SunOS Specific                              */
4784 +#define __NR_setxattr           169 /* SunOS: semsys                               */
4785 +#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
4786 +#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
4787 +#define __NR_getxattr           172 /* SunOS: auditsys                             */
4788 +#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
4789  #define __NR_getdents           174 /* Common                                      */
4790  #define __NR_setsid             175 /* Common                                      */
4791  #define __NR_fchdir             176 /* Common                                      */
4792 -/* #define __NR_fchroot         177    SunOS Specific                              */
4793 -/* #define __NR_vpixsys         178    SunOS Specific                              */
4794 -/* #define __NR_aioread         179    SunOS Specific                              */
4795 -/* #define __NR_aiowrite        180    SunOS Specific                              */
4796 -/* #define __NR_aiowait         181    SunOS Specific                              */
4797 -/* #define __NR_aiocancel       182    SunOS Specific                              */
4798 +#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
4799 +#define __NR_listxattr          178 /* SunOS: vpixsys                              */
4800 +#define __NR_llistxattr         179 /* SunOS: aioread                              */
4801 +#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
4802 +#define __NR_removexattr        181 /* SunOS: aiowait                              */
4803 +#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
4804  #define __NR_sigpending         183 /* Common                                      */
4805  #define __NR_query_module      184 /* Linux Specific                              */
4806  #define __NR_setpgid            185 /* Common                                      */
4807 -/* #define __NR_pathconf        186    SunOS Specific                              */
4808 +#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
4809  #define __NR_tkill              187 /* SunOS: fpathconf                            */
4810  /* #define __NR_sysconf         188    SunOS Specific                              */
4811  #define __NR_uname              189 /* Linux Specific                              */
4812 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
4813 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/cache_def.h   2003-07-12 15:34:44.000000000 -0600
4814 @@ -0,0 +1,15 @@
4815 +/*
4816 + * linux/cache_def.h
4817 + * Handling of caches defined in drivers, filesystems, ...
4818 + *
4819 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
4820 + */
4821 +
4822 +struct cache_definition {
4823 +       const char *name;
4824 +       void (*shrink)(int, unsigned int);
4825 +       struct list_head link;
4826 +};
4827 +
4828 +extern void register_cache(struct cache_definition *);
4829 +extern void unregister_cache(struct cache_definition *);
4830 --- kernel-2.4.20-6chaos_18_7/include/linux/errno.h~linux-2.4.20-xattr-0.8.54-chaos     2003-05-15 21:15:06.000000000 -0600
4831 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/errno.h       2003-07-12 15:34:44.000000000 -0600
4832 @@ -26,4 +26,8 @@
4833  
4834  #endif
4835  
4836 +/* Defined for extended attributes */
4837 +#define ENOATTR ENODATA                /* No such attribute */
4838 +#define ENOTSUP EOPNOTSUPP     /* Operation not supported */
4839 +
4840  #endif
4841 --- kernel-2.4.20-6chaos_18_7/include/linux/ext2_fs.h~linux-2.4.20-xattr-0.8.54-chaos   2003-06-24 11:31:16.000000000 -0600
4842 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_fs.h     2003-07-12 15:34:44.000000000 -0600
4843 @@ -57,8 +57,6 @@
4844   */
4845  #define        EXT2_BAD_INO             1      /* Bad blocks inode */
4846  #define EXT2_ROOT_INO           2      /* Root inode */
4847 -#define EXT2_ACL_IDX_INO        3      /* ACL inode */
4848 -#define EXT2_ACL_DATA_INO       4      /* ACL inode */
4849  #define EXT2_BOOT_LOADER_INO    5      /* Boot loader inode */
4850  #define EXT2_UNDEL_DIR_INO      6      /* Undelete directory inode */
4851  
4852 @@ -86,7 +84,6 @@
4853  #else
4854  # define EXT2_BLOCK_SIZE(s)            (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
4855  #endif
4856 -#define EXT2_ACLE_PER_BLOCK(s)         (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
4857  #define        EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
4858  #ifdef __KERNEL__
4859  # define EXT2_BLOCK_SIZE_BITS(s)       ((s)->s_blocksize_bits)
4860 @@ -121,28 +118,6 @@
4861  #endif
4862  
4863  /*
4864 - * ACL structures
4865 - */
4866 -struct ext2_acl_header /* Header of Access Control Lists */
4867 -{
4868 -       __u32   aclh_size;
4869 -       __u32   aclh_file_count;
4870 -       __u32   aclh_acle_count;
4871 -       __u32   aclh_first_acle;
4872 -};
4873 -
4874 -struct ext2_acl_entry  /* Access Control List Entry */
4875 -{
4876 -       __u32   acle_size;
4877 -       __u16   acle_perms;     /* Access permissions */
4878 -       __u16   acle_type;      /* Type of entry */
4879 -       __u16   acle_tag;       /* User or group identity */
4880 -       __u16   acle_pad1;
4881 -       __u32   acle_next;      /* Pointer on next entry for the */
4882 -                                       /* same inode or on next free entry */
4883 -};
4884 -
4885 -/*
4886   * Structure of a blocks group descriptor
4887   */
4888  struct ext2_group_desc
4889 @@ -314,6 +289,7 @@ struct ext2_inode {
4890  #define EXT2_MOUNT_ERRORS_PANIC                0x0040  /* Panic on errors */
4891  #define EXT2_MOUNT_MINIX_DF            0x0080  /* Mimics the Minix statfs */
4892  #define EXT2_MOUNT_NO_UID32            0x0200  /* Disable 32-bit UIDs */
4893 +#define EXT2_MOUNT_XATTR_USER          0x4000  /* Extended user attributes */
4894  
4895  #define clear_opt(o, opt)              o &= ~EXT2_MOUNT_##opt
4896  #define set_opt(o, opt)                        o |= EXT2_MOUNT_##opt
4897 @@ -397,6 +373,7 @@ struct ext2_super_block {
4898  
4899  #ifdef __KERNEL__
4900  #define EXT2_SB(sb)    (&((sb)->u.ext2_sb))
4901 +#define EXT2_I(inode)  (&((inode)->u.ext2_i))
4902  #else
4903  /* Assume that user mode programs are passing in an ext2fs superblock, not
4904   * a kernel struct super_block.  This will allow us to call the feature-test
4905 @@ -466,7 +443,7 @@ struct ext2_super_block {
4906  #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008
4907  #define EXT2_FEATURE_INCOMPAT_ANY              0xffffffff
4908  
4909 -#define EXT2_FEATURE_COMPAT_SUPP       0
4910 +#define EXT2_FEATURE_COMPAT_SUPP       EXT2_FEATURE_COMPAT_EXT_ATTR
4911  #define EXT2_FEATURE_INCOMPAT_SUPP     EXT2_FEATURE_INCOMPAT_FILETYPE
4912  #define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
4913                                          EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
4914 @@ -624,8 +601,10 @@ extern struct address_space_operations e
4915  
4916  /* namei.c */
4917  extern struct inode_operations ext2_dir_inode_operations;
4918 +extern struct inode_operations ext2_special_inode_operations;
4919  
4920  /* symlink.c */
4921 +extern struct inode_operations ext2_symlink_inode_operations;
4922  extern struct inode_operations ext2_fast_symlink_inode_operations;
4923  
4924  #endif /* __KERNEL__ */
4925 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
4926 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_xattr.h  2003-07-12 15:34:44.000000000 -0600
4927 @@ -0,0 +1,157 @@
4928 +/*
4929 +  File: linux/ext2_xattr.h
4930 +
4931 +  On-disk format of extended attributes for the ext2 filesystem.
4932 +
4933 +  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4934 +*/
4935 +
4936 +#include <linux/config.h>
4937 +#include <linux/init.h>
4938 +#include <linux/xattr.h>
4939 +
4940 +/* Magic value in attribute blocks */
4941 +#define EXT2_XATTR_MAGIC               0xEA020000
4942 +
4943 +/* Maximum number of references to one attribute block */
4944 +#define EXT2_XATTR_REFCOUNT_MAX                1024
4945 +
4946 +/* Name indexes */
4947 +#define EXT2_XATTR_INDEX_MAX                   10
4948 +#define EXT2_XATTR_INDEX_USER                  1
4949 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS      2
4950 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT     3
4951 +
4952 +struct ext2_xattr_header {
4953 +       __u32   h_magic;        /* magic number for identification */
4954 +       __u32   h_refcount;     /* reference count */
4955 +       __u32   h_blocks;       /* number of disk blocks used */
4956 +       __u32   h_hash;         /* hash value of all attributes */
4957 +       __u32   h_reserved[4];  /* zero right now */
4958 +};
4959 +
4960 +struct ext2_xattr_entry {
4961 +       __u8    e_name_len;     /* length of name */
4962 +       __u8    e_name_index;   /* attribute name index */
4963 +       __u16   e_value_offs;   /* offset in disk block of value */
4964 +       __u32   e_value_block;  /* disk block attribute is stored on (n/i) */
4965 +       __u32   e_value_size;   /* size of attribute value */
4966 +       __u32   e_hash;         /* hash value of name and value */
4967 +       char    e_name[0];      /* attribute name */
4968 +};
4969 +
4970 +#define EXT2_XATTR_PAD_BITS            2
4971 +#define EXT2_XATTR_PAD         (1<<EXT2_XATTR_PAD_BITS)
4972 +#define EXT2_XATTR_ROUND               (EXT2_XATTR_PAD-1)
4973 +#define EXT2_XATTR_LEN(name_len) \
4974 +       (((name_len) + EXT2_XATTR_ROUND + \
4975 +       sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
4976 +#define EXT2_XATTR_NEXT(entry) \
4977 +       ( (struct ext2_xattr_entry *)( \
4978 +         (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
4979 +#define EXT2_XATTR_SIZE(size) \
4980 +       (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
4981 +
4982 +#ifdef __KERNEL__
4983 +
4984 +# ifdef CONFIG_EXT2_FS_XATTR
4985 +
4986 +struct ext2_xattr_handler {
4987 +       char *prefix;
4988 +       size_t (*list)(char *list, struct inode *inode, const char *name,
4989 +                      int name_len);
4990 +       int (*get)(struct inode *inode, const char *name, void *buffer,
4991 +                  size_t size);
4992 +       int (*set)(struct inode *inode, const char *name, const void *buffer,
4993 +                  size_t size, int flags);
4994 +};
4995 +
4996 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
4997 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
4998 +
4999 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
5000 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
5001 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
5002 +extern int ext2_removexattr(struct dentry *, const char *);
5003 +
5004 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
5005 +extern int ext2_xattr_list(struct inode *, char *, size_t);
5006 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
5007 +
5008 +extern void ext2_xattr_delete_inode(struct inode *);
5009 +extern void ext2_xattr_put_super(struct super_block *);
5010 +
5011 +extern int init_ext2_xattr(void) __init;
5012 +extern void exit_ext2_xattr(void);
5013 +
5014 +# else  /* CONFIG_EXT2_FS_XATTR */
5015 +#  define ext2_setxattr                NULL
5016 +#  define ext2_getxattr                NULL
5017 +#  define ext2_listxattr       NULL
5018 +#  define ext2_removexattr     NULL
5019 +
5020 +static inline int
5021 +ext2_xattr_get(struct inode *inode, int name_index,
5022 +              const char *name, void *buffer, size_t size)
5023 +{
5024 +       return -ENOTSUP;
5025 +}
5026 +
5027 +static inline int
5028 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
5029 +{
5030 +       return -ENOTSUP;
5031 +}
5032 +
5033 +static inline int
5034 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
5035 +              const void *value, size_t size, int flags)
5036 +{
5037 +       return -ENOTSUP;
5038 +}
5039 +
5040 +static inline void
5041 +ext2_xattr_delete_inode(struct inode *inode)
5042 +{
5043 +}
5044 +
5045 +static inline void
5046 +ext2_xattr_put_super(struct super_block *sb)
5047 +{
5048 +}
5049 +
5050 +static inline int
5051 +init_ext2_xattr(void)
5052 +{
5053 +       return 0;
5054 +}
5055 +
5056 +static inline void
5057 +exit_ext2_xattr(void)
5058 +{
5059 +}
5060 +
5061 +# endif  /* CONFIG_EXT2_FS_XATTR */
5062 +
5063 +# ifdef CONFIG_EXT2_FS_XATTR_USER
5064 +
5065 +extern int init_ext2_xattr_user(void) __init;
5066 +extern void exit_ext2_xattr_user(void);
5067 +
5068 +# else  /* CONFIG_EXT2_FS_XATTR_USER */
5069 +
5070 +static inline int
5071 +init_ext2_xattr_user(void)
5072 +{
5073 +       return 0;
5074 +}
5075 +
5076 +static inline void
5077 +exit_ext2_xattr_user(void)
5078 +{
5079 +}
5080 +
5081 +# endif  /* CONFIG_EXT2_FS_XATTR_USER */
5082 +
5083 +#endif  /* __KERNEL__ */
5084 +
5085 --- kernel-2.4.20-6chaos_18_7/include/linux/ext3_fs.h~linux-2.4.20-xattr-0.8.54-chaos   2003-07-12 15:33:41.000000000 -0600
5086 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_fs.h     2003-07-12 15:34:44.000000000 -0600
5087 @@ -63,8 +63,6 @@
5088   */
5089  #define        EXT3_BAD_INO             1      /* Bad blocks inode */
5090  #define EXT3_ROOT_INO           2      /* Root inode */
5091 -#define EXT3_ACL_IDX_INO        3      /* ACL inode */
5092 -#define EXT3_ACL_DATA_INO       4      /* ACL inode */
5093  #define EXT3_BOOT_LOADER_INO    5      /* Boot loader inode */
5094  #define EXT3_UNDEL_DIR_INO      6      /* Undelete directory inode */
5095  #define EXT3_RESIZE_INO                 7      /* Reserved group descriptors inode */
5096 @@ -94,7 +92,6 @@
5097  #else
5098  # define EXT3_BLOCK_SIZE(s)            (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5099  #endif
5100 -#define EXT3_ACLE_PER_BLOCK(s)         (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
5101  #define        EXT3_ADDR_PER_BLOCK(s)          (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
5102  #ifdef __KERNEL__
5103  # define EXT3_BLOCK_SIZE_BITS(s)       ((s)->s_blocksize_bits)
5104 @@ -129,28 +126,6 @@
5105  #endif
5106  
5107  /*
5108 - * ACL structures
5109 - */
5110 -struct ext3_acl_header /* Header of Access Control Lists */
5111 -{
5112 -       __u32   aclh_size;
5113 -       __u32   aclh_file_count;
5114 -       __u32   aclh_acle_count;
5115 -       __u32   aclh_first_acle;
5116 -};
5117 -
5118 -struct ext3_acl_entry  /* Access Control List Entry */
5119 -{
5120 -       __u32   acle_size;
5121 -       __u16   acle_perms;     /* Access permissions */
5122 -       __u16   acle_type;      /* Type of entry */
5123 -       __u16   acle_tag;       /* User or group identity */
5124 -       __u16   acle_pad1;
5125 -       __u32   acle_next;      /* Pointer on next entry for the */
5126 -                                       /* same inode or on next free entry */
5127 -};
5128 -
5129 -/*
5130   * Structure of a blocks group descriptor
5131   */
5132  struct ext3_group_desc
5133 @@ -344,6 +319,7 @@ struct ext3_inode {
5134    #define EXT3_MOUNT_WRITEBACK_DATA    0x0C00  /* No data ordering */
5135  #define EXT3_MOUNT_UPDATE_JOURNAL      0x1000  /* Update the journal format */
5136  #define EXT3_MOUNT_NO_UID32            0x2000  /* Disable 32-bit UIDs */
5137 +#define EXT3_MOUNT_XATTR_USER          0x4000  /* Extended user attributes */
5138  
5139  /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
5140  #ifndef _LINUX_EXT2_FS_H
5141 @@ -521,7 +497,7 @@ struct ext3_super_block {
5142  #define EXT3_FEATURE_INCOMPAT_RECOVER          0x0004 /* Needs recovery */
5143  #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008 /* Journal device */
5144  
5145 -#define EXT3_FEATURE_COMPAT_SUPP       0
5146 +#define EXT3_FEATURE_COMPAT_SUPP       EXT2_FEATURE_COMPAT_EXT_ATTR
5147  #define EXT3_FEATURE_INCOMPAT_SUPP     (EXT3_FEATURE_INCOMPAT_FILETYPE| \
5148                                          EXT3_FEATURE_INCOMPAT_RECOVER)
5149  #define EXT3_FEATURE_RO_COMPAT_SUPP    (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5150 @@ -704,6 +680,7 @@ extern void ext3_check_inodes_bitmap (st
5151  extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
5152  
5153  /* inode.c */
5154 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
5155  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
5156  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
5157  
5158 @@ -773,8 +750,10 @@ extern struct address_space_operations e
5159  
5160  /* namei.c */
5161  extern struct inode_operations ext3_dir_inode_operations;
5162 +extern struct inode_operations ext3_special_inode_operations;
5163  
5164  /* symlink.c */
5165 +extern struct inode_operations ext3_symlink_inode_operations;
5166  extern struct inode_operations ext3_fast_symlink_inode_operations;
5167  
5168  
5169 --- kernel-2.4.20-6chaos_18_7/include/linux/ext3_jbd.h~linux-2.4.20-xattr-0.8.54-chaos  2003-07-12 15:33:38.000000000 -0600
5170 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_jbd.h    2003-07-12 15:34:44.000000000 -0600
5171 @@ -30,13 +30,19 @@
5172  
5173  #define EXT3_SINGLEDATA_TRANS_BLOCKS   8U
5174  
5175 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5176 + * and two group and summaries. */
5177 +
5178 +#define EXT3_XATTR_TRANS_BLOCKS                8
5179 +
5180  /* Define the minimum size for a transaction which modifies data.  This
5181   * needs to take into account the fact that we may end up modifying two
5182   * quota files too (one for the group, one for the user quota).  The
5183   * superblock only gets updated once, of course, so don't bother
5184   * counting that again for the quota updates. */
5185  
5186 -#define EXT3_DATA_TRANS_BLOCKS         (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5187 +#define EXT3_DATA_TRANS_BLOCKS         (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5188 +                                        EXT3_XATTR_TRANS_BLOCKS - 2)
5189  
5190  extern int ext3_writepage_trans_blocks(struct inode *inode);
5191  
5192 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
5193 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_xattr.h  2003-07-12 15:34:44.000000000 -0600
5194 @@ -0,0 +1,157 @@
5195 +/*
5196 +  File: linux/ext3_xattr.h
5197 +
5198 +  On-disk format of extended attributes for the ext3 filesystem.
5199 +
5200 +  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5201 +*/
5202 +
5203 +#include <linux/config.h>
5204 +#include <linux/init.h>
5205 +#include <linux/xattr.h>
5206 +
5207 +/* Magic value in attribute blocks */
5208 +#define EXT3_XATTR_MAGIC               0xEA020000
5209 +
5210 +/* Maximum number of references to one attribute block */
5211 +#define EXT3_XATTR_REFCOUNT_MAX                1024
5212 +
5213 +/* Name indexes */
5214 +#define EXT3_XATTR_INDEX_MAX                   10
5215 +#define EXT3_XATTR_INDEX_USER                  1
5216 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS      2
5217 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT     3
5218 +
5219 +struct ext3_xattr_header {
5220 +       __u32   h_magic;        /* magic number for identification */
5221 +       __u32   h_refcount;     /* reference count */
5222 +       __u32   h_blocks;       /* number of disk blocks used */
5223 +       __u32   h_hash;         /* hash value of all attributes */
5224 +       __u32   h_reserved[4];  /* zero right now */
5225 +};
5226 +
5227 +struct ext3_xattr_entry {
5228 +       __u8    e_name_len;     /* length of name */
5229 +       __u8    e_name_index;   /* attribute name index */
5230 +       __u16   e_value_offs;   /* offset in disk block of value */
5231 +       __u32   e_value_block;  /* disk block attribute is stored on (n/i) */
5232 +       __u32   e_value_size;   /* size of attribute value */
5233 +       __u32   e_hash;         /* hash value of name and value */
5234 +       char    e_name[0];      /* attribute name */
5235 +};
5236 +
5237 +#define EXT3_XATTR_PAD_BITS            2
5238 +#define EXT3_XATTR_PAD         (1<<EXT3_XATTR_PAD_BITS)
5239 +#define EXT3_XATTR_ROUND               (EXT3_XATTR_PAD-1)
5240 +#define EXT3_XATTR_LEN(name_len) \
5241 +       (((name_len) + EXT3_XATTR_ROUND + \
5242 +       sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5243 +#define EXT3_XATTR_NEXT(entry) \
5244 +       ( (struct ext3_xattr_entry *)( \
5245 +         (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5246 +#define EXT3_XATTR_SIZE(size) \
5247 +       (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5248 +
5249 +#ifdef __KERNEL__
5250 +
5251 +# ifdef CONFIG_EXT3_FS_XATTR
5252 +
5253 +struct ext3_xattr_handler {
5254 +       char *prefix;
5255 +       size_t (*list)(char *list, struct inode *inode, const char *name,
5256 +                      int name_len);
5257 +       int (*get)(struct inode *inode, const char *name, void *buffer,
5258 +                  size_t size);
5259 +       int (*set)(struct inode *inode, const char *name, const void *buffer,
5260 +                  size_t size, int flags);
5261 +};
5262 +
5263 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5264 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5265 +
5266 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5267 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5268 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5269 +extern int ext3_removexattr(struct dentry *, const char *);
5270 +
5271 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5272 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5273 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5274 +
5275 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5276 +extern void ext3_xattr_put_super(struct super_block *);
5277 +
5278 +extern int init_ext3_xattr(void) __init;
5279 +extern void exit_ext3_xattr(void);
5280 +
5281 +# else  /* CONFIG_EXT3_FS_XATTR */
5282 +#  define ext3_setxattr                NULL
5283 +#  define ext3_getxattr                NULL
5284 +#  define ext3_listxattr       NULL
5285 +#  define ext3_removexattr     NULL
5286 +
5287 +static inline int
5288 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5289 +              void *buffer, size_t size)
5290 +{
5291 +       return -ENOTSUP;
5292 +}
5293 +
5294 +static inline int
5295 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5296 +{
5297 +       return -ENOTSUP;
5298 +}
5299 +
5300 +static inline int
5301 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5302 +              const char *name, const void *value, size_t size, int flags)
5303 +{
5304 +       return -ENOTSUP;
5305 +}
5306 +
5307 +static inline void
5308 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5309 +{
5310 +}
5311 +
5312 +static inline void
5313 +ext3_xattr_put_super(struct super_block *sb)
5314 +{
5315 +}
5316 +
5317 +static inline int
5318 +init_ext3_xattr(void)
5319 +{
5320 +       return 0;
5321 +}
5322 +
5323 +static inline void
5324 +exit_ext3_xattr(void)
5325 +{
5326 +}
5327 +
5328 +# endif  /* CONFIG_EXT3_FS_XATTR */
5329 +
5330 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5331 +
5332 +extern int init_ext3_xattr_user(void) __init;
5333 +extern void exit_ext3_xattr_user(void);
5334 +
5335 +# else  /* CONFIG_EXT3_FS_XATTR_USER */
5336 +
5337 +static inline int
5338 +init_ext3_xattr_user(void)
5339 +{
5340 +       return 0;
5341 +}
5342 +
5343 +static inline void
5344 +exit_ext3_xattr_user(void)
5345 +{
5346 +}
5347 +
5348 +#endif  /* CONFIG_EXT3_FS_XATTR_USER */
5349 +
5350 +#endif  /* __KERNEL__ */
5351 +
5352 --- kernel-2.4.20-6chaos_18_7/include/linux/fs.h~linux-2.4.20-xattr-0.8.54-chaos        2003-07-12 15:31:35.000000000 -0600
5353 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/fs.h  2003-07-12 15:34:44.000000000 -0600
5354 @@ -914,7 +914,7 @@ struct inode_operations {
5355         int (*setattr) (struct dentry *, struct iattr *);
5356         int (*setattr_raw) (struct inode *, struct iattr *);
5357         int (*getattr) (struct dentry *, struct iattr *);
5358 -       int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
5359 +       int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5360         ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5361         ssize_t (*listxattr) (struct dentry *, char *, size_t);
5362         int (*removexattr) (struct dentry *, const char *);
5363 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
5364 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/mbcache.h     2003-07-12 15:34:44.000000000 -0600
5365 @@ -0,0 +1,69 @@
5366 +/*
5367 +  File: linux/mbcache.h
5368 +
5369 +  (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5370 +*/
5371 +
5372 +/* Hardwire the number of additional indexes */
5373 +#define MB_CACHE_INDEXES_COUNT 1
5374 +
5375 +struct mb_cache_entry;
5376 +
5377 +struct mb_cache_op {
5378 +       int (*free)(struct mb_cache_entry *, int);
5379 +};
5380 +
5381 +struct mb_cache {
5382 +       struct list_head                c_cache_list;
5383 +       const char                      *c_name;
5384 +       struct mb_cache_op              c_op;
5385 +       atomic_t                        c_entry_count;
5386 +       int                             c_bucket_count;
5387 +#ifndef MB_CACHE_INDEXES_COUNT
5388 +       int                             c_indexes_count;
5389 +#endif
5390 +       kmem_cache_t                    *c_entry_cache;
5391 +       struct list_head                *c_block_hash;
5392 +       struct list_head                *c_indexes_hash[0];
5393 +};
5394 +
5395 +struct mb_cache_entry_index {
5396 +       struct list_head                o_list;
5397 +       unsigned int                    o_key;
5398 +};
5399 +
5400 +struct mb_cache_entry {
5401 +       struct list_head                e_lru_list;
5402 +       struct mb_cache                 *e_cache;
5403 +       atomic_t                        e_used;
5404 +       kdev_t                          e_dev;
5405 +       unsigned long                   e_block;
5406 +       struct list_head                e_block_list;
5407 +       struct mb_cache_entry_index     e_indexes[0];
5408 +};
5409 +
5410 +/* Functions on caches */
5411 +
5412 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5413 +                                 int, int);
5414 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5415 +void mb_cache_destroy(struct mb_cache *);
5416 +
5417 +/* Functions on cache entries */
5418 +
5419 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5420 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5421 +                         unsigned int[]);
5422 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5423 +void mb_cache_entry_release(struct mb_cache_entry *);
5424 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5425 +void mb_cache_entry_free(struct mb_cache_entry *);
5426 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5427 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5428 +                                         unsigned long);
5429 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5430 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5431 +                                                kdev_t, unsigned int);
5432 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5433 +                                               kdev_t, unsigned int);
5434 +#endif
5435 --- kernel-2.4.20-6chaos_18_7/kernel/ksyms.c~linux-2.4.20-xattr-0.8.54-chaos    2003-07-12 15:14:02.000000000 -0600
5436 +++ kernel-2.4.20-6chaos_18_7-braam/kernel/ksyms.c      2003-07-12 15:35:19.000000000 -0600
5437 @@ -12,6 +12,7 @@
5438  #define __KERNEL_SYSCALLS__
5439  #include <linux/config.h>
5440  #include <linux/slab.h>
5441 +#include <linux/cache_def.h>
5442  #include <linux/smp.h>
5443  #include <linux/module.h>
5444  #include <linux/blkdev.h>
5445 @@ -106,6 +107,7 @@ EXPORT_SYMBOL(do_brk);
5446  EXPORT_SYMBOL(exit_mm);
5447  EXPORT_SYMBOL(exit_files);
5448  EXPORT_SYMBOL(exit_fs);
5449 +EXPORT_SYMBOL(copy_fs_struct);
5450  EXPORT_SYMBOL(exit_sighand);
5451  EXPORT_SYMBOL_GPL(make_pages_present);
5452  
5453 @@ -126,6 +128,8 @@ EXPORT_SYMBOL(kmem_cache_alloc);
5454  EXPORT_SYMBOL(kmem_cache_free);
5455  EXPORT_SYMBOL(kmem_cache_validate);
5456  EXPORT_SYMBOL(kmem_cache_size);
5457 +EXPORT_SYMBOL(register_cache);
5458 +EXPORT_SYMBOL(unregister_cache);
5459  EXPORT_SYMBOL(kmalloc);
5460  EXPORT_SYMBOL(kfree);
5461  EXPORT_SYMBOL(vfree);
5462 --- kernel-2.4.20-6chaos_18_7/mm/vmscan.c~linux-2.4.20-xattr-0.8.54-chaos       2003-07-12 15:33:34.000000000 -0600
5463 +++ kernel-2.4.20-6chaos_18_7-braam/mm/vmscan.c 2003-07-12 15:34:44.000000000 -0600
5464 @@ -21,6 +21,7 @@
5465  #include <linux/kernel_stat.h>
5466  #include <linux/swap.h>
5467  #include <linux/swapctl.h>
5468 +#include <linux/cache_def.h>
5469  #include <linux/smp_lock.h>
5470  #include <linux/pagemap.h>
5471  #include <linux/init.h>
5472 @@ -444,6 +445,39 @@ static inline void kachunk_cache(struct 
5473  
5474  #define BATCH_WORK_AMOUNT      64
5475  
5476 +static DECLARE_MUTEX(other_caches_sem);
5477 +static LIST_HEAD(cache_definitions);
5478 +
5479 +void register_cache(struct cache_definition *cache)
5480 +{
5481 +       down(&other_caches_sem);
5482 +       list_add(&cache->link, &cache_definitions);
5483 +       up(&other_caches_sem);
5484 +}
5485 +
5486 +void unregister_cache(struct cache_definition *cache)
5487 +{
5488 +       down(&other_caches_sem);
5489 +       list_del(&cache->link);
5490 +       up(&other_caches_sem);
5491 +}
5492 +
5493 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
5494 +{
5495 +       struct list_head *p;
5496 +
5497 +       if (down_trylock(&other_caches_sem))
5498 +               return;
5499 +
5500 +       list_for_each_prev(p, &cache_definitions) {
5501 +               struct cache_definition *cache =
5502 +                       list_entry(p, struct cache_definition, link);
5503 +
5504 +               cache->shrink(priority, gfp_mask);
5505 +       }
5506 +       up(&other_caches_sem);
5507 +}
5508 +
5509  /*
5510   * returns the active cache ratio relative to the total active list
5511   * times 10 (eg. 30% cache returns 3)
5512 @@ -887,7 +921,7 @@ static int do_try_to_free_pages_kswapd(u
5513  
5514         ret += shrink_dcache_memory(DEF_PRIORITY, gfp_mask);
5515         ret += shrink_icache_memory(DEF_PRIORITY, gfp_mask);
5516 -       // ret += shrink_other_caches(DEF_PRIORITY, gfp_mask); 
5517 +       shrink_other_caches(DEF_PRIORITY, gfp_mask); 
5518  #ifdef CONFIG_QUOTA
5519         ret += shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
5520  #endif
5521 --- /dev/null   2003-01-30 03:24:37.000000000 -0700
5522 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ext3-exports.c      2003-07-12 15:34:44.000000000 -0600
5523 @@ -0,0 +1,13 @@
5524 +#include <linux/config.h>
5525 +#include <linux/module.h>
5526 +#include <linux/ext3_fs.h>
5527 +#include <linux/ext3_jbd.h>
5528 +#include <linux/ext3_xattr.h>
5529 +
5530 +EXPORT_SYMBOL(ext3_force_commit);
5531 +EXPORT_SYMBOL(ext3_bread);
5532 +EXPORT_SYMBOL(ext3_xattr_register);
5533 +EXPORT_SYMBOL(ext3_xattr_unregister);
5534 +EXPORT_SYMBOL(ext3_xattr_get);
5535 +EXPORT_SYMBOL(ext3_xattr_list);
5536 +EXPORT_SYMBOL(ext3_xattr_set);
5537
5538 _