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