1 Documentation/Configure.help | 66 ++
2 arch/alpha/defconfig | 7
3 arch/alpha/kernel/entry.S | 12
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
27 fs/ext2/inode.c | 34 -
30 fs/ext2/symlink.c | 14
31 fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++
32 fs/ext2/xattr_user.c | 103 +++
34 fs/ext3/ext3-exports.c | 13
37 fs/ext3/inode.c | 35 -
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
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 ++
63 62 files changed, 4344 insertions(+), 183 deletions(-)
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.
71 +Ext2 extended attributes
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).
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.
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).
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.
104 Ext3 journalling file system support (EXPERIMENTAL)
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.
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).
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.
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).
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.
144 Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
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
151 # Automatically generated make config: don't edit
153 +# CONFIG_EXT3_FS_XATTR is not set
154 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
155 +# CONFIG_EXT3_FS_XATTR_USER is not set
156 +# CONFIG_EXT2_FS_XATTR is not set
157 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
158 +# CONFIG_EXT2_FS_XATTR_USER is not set
159 +# CONFIG_FS_MBCACHE is not set
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:
167 .quad sys_ni_syscall /* 380, sys_security */
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
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
188 # Automatically generated make config: don't edit
190 +# CONFIG_EXT3_FS_XATTR is not set
191 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
192 +# CONFIG_EXT3_FS_XATTR_USER is not set
193 +# CONFIG_EXT2_FS_XATTR is not set
194 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
195 +# CONFIG_EXT2_FS_XATTR_USER is not set
196 +# CONFIG_FS_MBCACHE is not set
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)
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
237 # Automatically generated make config: don't edit
239 +# CONFIG_EXT3_FS_XATTR is not set
240 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
241 +# CONFIG_EXT3_FS_XATTR_USER is not set
242 +# CONFIG_EXT2_FS_XATTR is not set
243 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
244 +# CONFIG_EXT2_FS_XATTR_USER is not set
245 +# CONFIG_FS_MBCACHE is not set
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
253 # Automatically generated make config: don't edit
255 +# CONFIG_EXT3_FS_XATTR is not set
256 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
257 +# CONFIG_EXT3_FS_XATTR_USER is not set
258 +# CONFIG_EXT2_FS_XATTR is not set
259 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
260 +# CONFIG_EXT2_FS_XATTR_USER is not set
261 +# CONFIG_FS_MBCACHE is not set
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
269 # Automatically generated make config: don't edit
271 +# CONFIG_EXT3_FS_XATTR is not set
272 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
273 +# CONFIG_EXT3_FS_XATTR_USER is not set
274 +# CONFIG_EXT2_FS_XATTR is not set
275 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
276 +# CONFIG_EXT2_FS_XATTR_USER is not set
277 +# CONFIG_FS_MBCACHE is not set
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
285 # Automatically generated make config: don't edit
287 +# CONFIG_EXT3_FS_XATTR is not set
288 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
289 +# CONFIG_EXT3_FS_XATTR_USER is not set
290 +# CONFIG_EXT2_FS_XATTR is not set
291 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
292 +# CONFIG_EXT2_FS_XATTR_USER is not set
293 +# CONFIG_FS_MBCACHE is not set
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
301 # Automatically generated make config: don't edit
303 +# CONFIG_EXT3_FS_XATTR is not set
304 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
305 +# CONFIG_EXT3_FS_XATTR_USER is not set
306 +# CONFIG_EXT2_FS_XATTR is not set
307 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
308 +# CONFIG_EXT2_FS_XATTR_USER is not set
309 +# CONFIG_FS_MBCACHE is not set
311 # CONFIG_MIPS32 is not set
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
317 # Automatically generated make config: don't edit
319 +# CONFIG_EXT3_FS_XATTR is not set
320 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
321 +# CONFIG_EXT3_FS_XATTR_USER is not set
322 +# CONFIG_EXT2_FS_XATTR is not set
323 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
324 +# CONFIG_EXT2_FS_XATTR_USER is not set
325 +# CONFIG_FS_MBCACHE is not set
326 +# CONFIG_EXT3_FS_XATTR is not set
327 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
328 +# CONFIG_EXT3_FS_XATTR_USER is not set
329 +# CONFIG_EXT2_FS_XATTR is not set
330 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
331 +# CONFIG_EXT2_FS_XATTR_USER is not set
332 +# CONFIG_FS_MBCACHE is not set
333 # CONFIG_UID16 is not set
334 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
335 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
336 --- kernel-2.4.20-6chaos_18_7/arch/ppc64/kernel/misc.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
337 +++ kernel-2.4.20-6chaos_18_7-braam/arch/ppc64/kernel/misc.S 2003-07-12 15:34:44.000000000 -0600
338 @@ -731,6 +731,7 @@ _GLOBAL(sys_call_table32)
339 .llong .sys_gettid /* 207 */
340 #if 0 /* Reserved syscalls */
341 .llong .sys_tkill /* 208 */
344 .llong .sys_lsetxattr /* 210 */
345 .llong .sys_fsetxattr
346 @@ -743,6 +744,7 @@ _GLOBAL(sys_call_table32)
347 .llong .sys_removexattr
348 .llong .sys_lremovexattr
349 .llong .sys_fremovexattr /* 220 */
350 +#if 0 /* Reserved syscalls */
353 .llong .sys_perfmonctl /* Put this here for now ... */
354 --- kernel-2.4.20-6chaos_18_7/arch/s390/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
355 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/defconfig 2003-07-12 15:34:44.000000000 -0600
358 # Automatically generated make config: don't edit
360 +# CONFIG_EXT3_FS_XATTR is not set
361 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
362 +# CONFIG_EXT3_FS_XATTR_USER is not set
363 +# CONFIG_EXT2_FS_XATTR is not set
364 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
365 +# CONFIG_EXT2_FS_XATTR_USER is not set
366 +# CONFIG_FS_MBCACHE is not set
367 # CONFIG_ISA is not set
368 # CONFIG_EISA is not set
369 # CONFIG_MCA is not set
370 --- kernel-2.4.20-6chaos_18_7/arch/s390/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
371 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/kernel/entry.S 2003-07-12 15:34:44.000000000 -0600
372 @@ -558,18 +558,18 @@ sys_call_table:
376 - .long sys_ni_syscall /* 224 - reserved for setxattr */
377 - .long sys_ni_syscall /* 225 - reserved for lsetxattr */
378 - .long sys_ni_syscall /* 226 - reserved for fsetxattr */
379 - .long sys_ni_syscall /* 227 - reserved for getxattr */
380 - .long sys_ni_syscall /* 228 - reserved for lgetxattr */
381 - .long sys_ni_syscall /* 229 - reserved for fgetxattr */
382 - .long sys_ni_syscall /* 230 - reserved for listxattr */
383 - .long sys_ni_syscall /* 231 - reserved for llistxattr */
384 - .long sys_ni_syscall /* 232 - reserved for flistxattr */
385 - .long sys_ni_syscall /* 233 - reserved for removexattr */
386 - .long sys_ni_syscall /* 234 - reserved for lremovexattr */
387 - .long sys_ni_syscall /* 235 - reserved for fremovexattr */
389 + .long sys_lsetxattr /* 225 */
390 + .long sys_fsetxattr
392 + .long sys_lgetxattr
393 + .long sys_fgetxattr
394 + .long sys_listxattr /* 230 */
395 + .long sys_llistxattr
396 + .long sys_flistxattr
397 + .long sys_removexattr
398 + .long sys_lremovexattr
399 + .long sys_fremovexattr /* 235 */
403 --- kernel-2.4.20-6chaos_18_7/arch/s390x/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:21.000000000 -0700
404 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/defconfig 2003-07-12 15:34:44.000000000 -0600
407 # Automatically generated make config: don't edit
409 +# CONFIG_EXT3_FS_XATTR is not set
410 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
411 +# CONFIG_EXT3_FS_XATTR_USER is not set
412 +# CONFIG_EXT2_FS_XATTR is not set
413 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
414 +# CONFIG_EXT2_FS_XATTR_USER is not set
415 +# CONFIG_FS_MBCACHE is not set
416 # CONFIG_ISA is not set
417 # CONFIG_EISA is not set
418 # CONFIG_MCA is not set
419 --- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:21.000000000 -0700
420 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/entry.S 2003-07-12 15:34:44.000000000 -0600
421 @@ -591,18 +591,18 @@ sys_call_table:
422 .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
423 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
424 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
425 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
426 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
427 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
428 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
429 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
430 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
431 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
432 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
433 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
434 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
435 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
436 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
437 + .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
438 + .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
439 + .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
440 + .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
441 + .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
442 + .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
443 + .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
444 + .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
445 + .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
446 + .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
447 + .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
448 + .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
449 .long SYSCALL(sys_gettid,sys_gettid)
450 .long SYSCALL(sys_tkill,sys_tkill)
452 --- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/wrapper32.S~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:59.000000000 -0600
453 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/wrapper32.S 2003-07-12 15:34:44.000000000 -0600
454 @@ -1091,3 +1091,95 @@ sys32_fstat64_wrapper:
455 llgtr %r3,%r3 # struct stat64 *
457 jg sys32_fstat64 # branch to system call
459 + .globl sys32_setxattr_wrapper
460 +sys32_setxattr_wrapper:
461 + llgtr %r2,%r2 # char *
462 + llgtr %r3,%r3 # char *
463 + llgtr %r4,%r4 # void *
464 + llgfr %r5,%r5 # size_t
468 + .globl sys32_lsetxattr_wrapper
469 +sys32_lsetxattr_wrapper:
470 + llgtr %r2,%r2 # char *
471 + llgtr %r3,%r3 # char *
472 + llgtr %r4,%r4 # void *
473 + llgfr %r5,%r5 # size_t
477 + .globl sys32_fsetxattr_wrapper
478 +sys32_fsetxattr_wrapper:
480 + llgtr %r3,%r3 # char *
481 + llgtr %r4,%r4 # void *
482 + llgfr %r5,%r5 # size_t
486 + .globl sys32_getxattr_wrapper
487 +sys32_getxattr_wrapper:
488 + llgtr %r2,%r2 # char *
489 + llgtr %r3,%r3 # char *
490 + llgtr %r4,%r4 # void *
491 + llgfr %r5,%r5 # size_t
494 + .globl sys32_lgetxattr_wrapper
495 +sys32_lgetxattr_wrapper:
496 + llgtr %r2,%r2 # char *
497 + llgtr %r3,%r3 # char *
498 + llgtr %r4,%r4 # void *
499 + llgfr %r5,%r5 # size_t
502 + .globl sys32_fgetxattr_wrapper
503 +sys32_fgetxattr_wrapper:
505 + llgtr %r3,%r3 # char *
506 + llgtr %r4,%r4 # void *
507 + llgfr %r5,%r5 # size_t
510 + .globl sys32_listxattr_wrapper
511 +sys32_listxattr_wrapper:
512 + llgtr %r2,%r2 # char *
513 + llgtr %r3,%r3 # char *
514 + llgfr %r4,%r4 # size_t
517 + .globl sys32_llistxattr_wrapper
518 +sys32_llistxattr_wrapper:
519 + llgtr %r2,%r2 # char *
520 + llgtr %r3,%r3 # char *
521 + llgfr %r4,%r4 # size_t
524 + .globl sys32_flistxattr_wrapper
525 +sys32_flistxattr_wrapper:
527 + llgtr %r3,%r3 # char *
528 + llgfr %r4,%r4 # size_t
531 + .globl sys32_removexattr_wrapper
532 +sys32_removexattr_wrapper:
533 + llgtr %r2,%r2 # char *
534 + llgtr %r3,%r3 # char *
537 + .globl sys32_lremovexattr_wrapper
538 +sys32_lremovexattr_wrapper:
539 + llgtr %r2,%r2 # char *
540 + llgtr %r3,%r3 # char *
541 + jg sys_lremovexattr
543 + .globl sys32_fremovexattr_wrapper
544 +sys32_fremovexattr_wrapper:
546 + llgtr %r3,%r3 # char *
547 + jg sys_fremovexattr
550 --- kernel-2.4.20-6chaos_18_7/arch/sparc/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:50.000000000 -0600
551 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/defconfig 2003-07-12 15:34:44.000000000 -0600
554 # Automatically generated make config: don't edit
556 +# CONFIG_EXT3_FS_XATTR is not set
557 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
558 +# CONFIG_EXT3_FS_XATTR_USER is not set
559 +# CONFIG_EXT2_FS_XATTR is not set
560 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
561 +# CONFIG_EXT2_FS_XATTR_USER is not set
562 +# CONFIG_FS_MBCACHE is not set
566 --- kernel-2.4.20-6chaos_18_7/arch/sparc/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:52.000000000 -0600
567 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/kernel/systbls.S 2003-07-12 15:34:44.000000000 -0600
568 @@ -51,11 +51,11 @@ sys_call_table:
569 /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
570 /*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
571 /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
572 -/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
573 -/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
574 -/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
575 -/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
576 -/*185*/ .long sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sys_newuname
577 +/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
578 +/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
579 +/*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
580 +/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
581 +/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
582 /*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
583 /*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
584 /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
585 --- kernel-2.4.20-6chaos_18_7/arch/sparc64/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:12:29.000000000 -0600
586 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/defconfig 2003-07-12 15:34:44.000000000 -0600
589 # Automatically generated make config: don't edit
591 +# CONFIG_EXT3_FS_XATTR is not set
592 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
593 +# CONFIG_EXT3_FS_XATTR_USER is not set
594 +# CONFIG_EXT2_FS_XATTR is not set
595 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
596 +# CONFIG_EXT2_FS_XATTR_USER is not set
597 +# CONFIG_FS_MBCACHE is not set
600 # Code maturity level options
601 --- kernel-2.4.20-6chaos_18_7/arch/sparc64/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:55.000000000 -0600
602 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/kernel/systbls.S 2003-07-12 15:34:44.000000000 -0600
603 @@ -52,11 +52,11 @@ sys_call_table32:
604 /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
605 .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
606 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
607 - .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
608 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
609 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
610 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
611 - .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
612 + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
613 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
614 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
615 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
616 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
617 /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
618 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
619 /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
620 @@ -111,11 +111,11 @@ sys_call_table:
621 /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
622 .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
623 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
624 - .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
625 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
626 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
627 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
628 - .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
629 + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
630 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
631 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
632 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
633 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
634 /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
635 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
636 /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
637 --- kernel-2.4.20-6chaos_18_7/fs/Config.in~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:24.000000000 -0600
638 +++ kernel-2.4.20-6chaos_18_7-braam/fs/Config.in 2003-07-12 15:34:44.000000000 -0600
639 @@ -34,6 +34,11 @@ dep_mbool ' Debug Befs' CONFIG_BEFS_DEB
640 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
642 tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
643 +dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
644 +dep_bool ' Ext3 extended attribute block sharing' \
645 + CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
646 +dep_bool ' Ext3 extended user attributes' \
647 + CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
648 # CONFIG_JBD could be its own option (even modular), but until there are
649 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
650 # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
651 @@ -93,6 +98,11 @@ dep_mbool ' QNX4FS write support (DANGE
652 tristate 'ROM file system support' CONFIG_ROMFS_FS
654 tristate 'Second extended fs support' CONFIG_EXT2_FS
655 +dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
656 +dep_bool ' Ext2 extended attribute block sharing' \
657 + CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
658 +dep_bool ' Ext2 extended user attributes' \
659 + CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
661 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
663 @@ -164,6 +174,10 @@ else
664 define_tristate CONFIG_ZISOFS_FS n
667 +# Meta block cache for Extended Attributes (ext2/ext3)
668 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
669 +define_tristate CONFIG_FS_MBCACHE y
671 mainmenu_option next_comment
672 comment 'Partition Types'
673 source fs/partitions/Config.in
674 --- kernel-2.4.20-6chaos_18_7/fs/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:34.000000000 -0600
675 +++ kernel-2.4.20-6chaos_18_7-braam/fs/Makefile 2003-07-12 15:34:44.000000000 -0600
676 @@ -84,6 +84,9 @@ obj-y += binfmt_script.o
678 obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
680 +export-objs += mbcache.o
681 +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
683 # persistent filesystems
684 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
686 --- kernel-2.4.20-6chaos_18_7/fs/ext2/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
687 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/Makefile 2003-07-12 15:34:44.000000000 -0600
688 @@ -13,4 +13,8 @@ obj-y := balloc.o bitmap.o dir.o file
689 ioctl.o namei.o super.o symlink.o
692 +export-objs += xattr.o
693 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
694 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
696 include $(TOPDIR)/Rules.make
697 --- kernel-2.4.20-6chaos_18_7/fs/ext2/file.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
698 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/file.c 2003-07-12 15:34:44.000000000 -0600
701 #include <linux/fs.h>
702 #include <linux/ext2_fs.h>
703 +#include <linux/ext2_xattr.h>
704 #include <linux/sched.h>
707 @@ -51,4 +52,8 @@ struct file_operations ext2_file_operati
709 struct inode_operations ext2_file_inode_operations = {
710 truncate: ext2_truncate,
711 + setxattr: ext2_setxattr,
712 + getxattr: ext2_getxattr,
713 + listxattr: ext2_listxattr,
714 + removexattr: ext2_removexattr,
716 --- kernel-2.4.20-6chaos_18_7/fs/ext2/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
717 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/ialloc.c 2003-07-12 15:34:44.000000000 -0600
719 #include <linux/config.h>
720 #include <linux/fs.h>
721 #include <linux/ext2_fs.h>
722 +#include <linux/ext2_xattr.h>
723 #include <linux/locks.h>
724 #include <linux/quotaops.h>
726 @@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino
728 if (!is_bad_inode(inode)) {
729 /* Quota is already initialized in iput() */
730 + ext2_xattr_delete_inode(inode);
731 DQUOT_FREE_INODE(inode);
734 --- kernel-2.4.20-6chaos_18_7/fs/ext2/inode.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
735 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/inode.c 2003-07-12 15:34:44.000000000 -0600
736 @@ -39,6 +39,18 @@ MODULE_LICENSE("GPL");
737 static int ext2_update_inode(struct inode * inode, int do_sync);
740 + * Test whether an inode is a fast symlink.
742 +static inline int ext2_inode_is_fast_symlink(struct inode *inode)
744 + int ea_blocks = inode->u.ext2_i.i_file_acl ?
745 + (inode->i_sb->s_blocksize >> 9) : 0;
747 + return (S_ISLNK(inode->i_mode) &&
748 + inode->i_blocks - ea_blocks == 0);
752 * Called at each iput()
754 void ext2_put_inode (struct inode * inode)
755 @@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i
759 - if (is_bad_inode(inode) ||
760 - inode->i_ino == EXT2_ACL_IDX_INO ||
761 - inode->i_ino == EXT2_ACL_DATA_INO)
762 + if (is_bad_inode(inode))
764 inode->u.ext2_i.i_dtime = CURRENT_TIME;
765 mark_inode_dirty(inode);
766 @@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode
767 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
768 S_ISLNK(inode->i_mode)))
770 + if (ext2_inode_is_fast_symlink(inode))
772 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
775 @@ -888,8 +900,7 @@ void ext2_read_inode (struct inode * ino
776 unsigned long offset;
777 struct ext2_group_desc * gdp;
779 - if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
780 - inode->i_ino != EXT2_ACL_DATA_INO &&
781 + if ((inode->i_ino != EXT2_ROOT_INO &&
782 inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
783 inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
784 ext2_error (inode->i_sb, "ext2_read_inode",
785 @@ -974,10 +985,7 @@ void ext2_read_inode (struct inode * ino
786 for (block = 0; block < EXT2_N_BLOCKS; block++)
787 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
789 - if (inode->i_ino == EXT2_ACL_IDX_INO ||
790 - inode->i_ino == EXT2_ACL_DATA_INO)
791 - /* Nothing to do */ ;
792 - else if (S_ISREG(inode->i_mode)) {
793 + if (S_ISREG(inode->i_mode)) {
794 inode->i_op = &ext2_file_inode_operations;
795 inode->i_fop = &ext2_file_operations;
796 inode->i_mapping->a_ops = &ext2_aops;
797 @@ -986,15 +994,17 @@ void ext2_read_inode (struct inode * ino
798 inode->i_fop = &ext2_dir_operations;
799 inode->i_mapping->a_ops = &ext2_aops;
800 } else if (S_ISLNK(inode->i_mode)) {
801 - if (!inode->i_blocks)
802 + if (ext2_inode_is_fast_symlink(inode))
803 inode->i_op = &ext2_fast_symlink_inode_operations;
805 - inode->i_op = &page_symlink_inode_operations;
806 + inode->i_op = &ext2_symlink_inode_operations;
807 inode->i_mapping->a_ops = &ext2_aops;
811 + inode->i_op = &ext2_special_inode_operations;
812 init_special_inode(inode, inode->i_mode,
813 le32_to_cpu(raw_inode->i_block[0]));
816 inode->i_attr_flags = 0;
817 if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
818 --- kernel-2.4.20-6chaos_18_7/fs/ext2/namei.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
819 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/namei.c 2003-07-12 15:34:44.000000000 -0600
822 #include <linux/fs.h>
823 #include <linux/ext2_fs.h>
824 +#include <linux/ext2_xattr.h>
825 #include <linux/pagemap.h>
828 @@ -136,7 +137,7 @@ static int ext2_symlink (struct inode *
830 if (l > sizeof (inode->u.ext2_i.i_data)) {
832 - inode->i_op = &page_symlink_inode_operations;
833 + inode->i_op = &ext2_symlink_inode_operations;
834 inode->i_mapping->a_ops = &ext2_aops;
835 err = block_symlink(inode, symname, l);
837 @@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o
841 + setxattr: ext2_setxattr,
842 + getxattr: ext2_getxattr,
843 + listxattr: ext2_listxattr,
844 + removexattr: ext2_removexattr,
847 +struct inode_operations ext2_special_inode_operations = {
848 + setxattr: ext2_setxattr,
849 + getxattr: ext2_getxattr,
850 + listxattr: ext2_listxattr,
851 + removexattr: ext2_removexattr,
853 --- kernel-2.4.20-6chaos_18_7/fs/ext2/super.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
854 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/super.c 2003-07-12 15:34:44.000000000 -0600
856 #include <linux/string.h>
857 #include <linux/fs.h>
858 #include <linux/ext2_fs.h>
859 +#include <linux/ext2_xattr.h>
860 #include <linux/slab.h>
861 #include <linux/init.h>
862 #include <linux/locks.h>
863 @@ -125,6 +126,7 @@ void ext2_put_super (struct super_block
867 + ext2_xattr_put_super(sb);
868 if (!(sb->s_flags & MS_RDONLY)) {
869 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
871 @@ -175,6 +177,13 @@ static int parse_options (char * options
872 this_char = strtok (NULL, ",")) {
873 if ((value = strchr (this_char, '=')) != NULL)
875 +#ifdef CONFIG_EXT2_FS_XATTR_USER
876 + if (!strcmp (this_char, "user_xattr"))
877 + set_opt (*mount_options, XATTR_USER);
878 + else if (!strcmp (this_char, "nouser_xattr"))
879 + clear_opt (*mount_options, XATTR_USER);
882 if (!strcmp (this_char, "bsddf"))
883 clear_opt (*mount_options, MINIX_DF);
884 else if (!strcmp (this_char, "nouid32")) {
885 @@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st
886 blocksize = BLOCK_SIZE;
888 sb->u.ext2_sb.s_mount_opt = 0;
889 +#ifdef CONFIG_EXT2_FS_XATTR_USER
890 + /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
892 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
893 &sb->u.ext2_sb.s_mount_opt)) {
895 @@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type,
897 static int __init init_ext2_fs(void)
899 - return register_filesystem(&ext2_fs_type);
900 + int error = init_ext2_xattr();
903 + error = init_ext2_xattr_user();
906 + error = register_filesystem(&ext2_fs_type);
910 + exit_ext2_xattr_user();
916 static void __exit exit_ext2_fs(void)
918 unregister_filesystem(&ext2_fs_type);
919 + exit_ext2_xattr_user();
924 --- kernel-2.4.20-6chaos_18_7/fs/ext2/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
925 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/symlink.c 2003-07-12 15:34:44.000000000 -0600
928 #include <linux/fs.h>
929 #include <linux/ext2_fs.h>
930 +#include <linux/ext2_xattr.h>
932 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
934 @@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr
935 return vfs_follow_link(nd, s);
938 +struct inode_operations ext2_symlink_inode_operations = {
939 + readlink: page_readlink,
940 + follow_link: page_follow_link,
941 + setxattr: ext2_setxattr,
942 + getxattr: ext2_getxattr,
943 + listxattr: ext2_listxattr,
944 + removexattr: ext2_removexattr,
947 struct inode_operations ext2_fast_symlink_inode_operations = {
948 readlink: ext2_readlink,
949 follow_link: ext2_follow_link,
950 + setxattr: ext2_setxattr,
951 + getxattr: ext2_getxattr,
952 + listxattr: ext2_listxattr,
953 + removexattr: ext2_removexattr,
955 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
956 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr.c 2003-07-12 15:34:44.000000000 -0600
959 + * linux/fs/ext2/xattr.c
961 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
963 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
964 + * Extended attributes for symlinks and special files added per
965 + * suggestion of Luka Renko <luka.renko@hermes.si>.
969 + * Extended attributes are stored on disk blocks allocated outside of
970 + * any inode. The i_file_acl field is then made to point to this allocated
971 + * block. If all extended attributes of an inode are identical, these
972 + * inodes may share the same extended attribute block. Such situations
973 + * are automatically detected by keeping a cache of recent attribute block
974 + * numbers and hashes over the block's contents in memory.
977 + * Extended attribute block layout:
979 + * +------------------+
982 + * | entry 2 | | growing downwards
984 + * | four null bytes |
987 + * | value 3 | | growing upwards
989 + * +------------------+
991 + * The block header is followed by multiple entry descriptors. These entry
992 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
993 + * byte boundaries. The entry descriptors are sorted by attribute name,
994 + * so that two extended attribute blocks can be compared efficiently.
996 + * Attribute values are aligned to the end of the block, stored in
997 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
998 + * boundaries. No additional gaps are left between them.
1000 + * Locking strategy
1001 + * ----------------
1002 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
1003 + * the xattr inode operations are called, so we are guaranteed that only one
1004 + * processes accesses extended attributes of an inode at any time.
1006 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
1007 + * only a single process is modifying an extended attribute block, even
1008 + * if the block is shared among inodes.
1010 + * Note for porting to 2.5
1011 + * -----------------------
1012 + * The BKL will no longer be held in the xattr inode operations.
1015 +#include <linux/module.h>
1016 +#include <linux/locks.h>
1017 +#include <linux/slab.h>
1018 +#include <linux/fs.h>
1019 +#include <linux/ext2_fs.h>
1020 +#include <linux/ext2_xattr.h>
1021 +#include <linux/mbcache.h>
1022 +#include <linux/quotaops.h>
1023 +#include <asm/semaphore.h>
1024 +#include <linux/compatmac.h>
1026 +/* These symbols may be needed by a module. */
1027 +EXPORT_SYMBOL(ext2_xattr_register);
1028 +EXPORT_SYMBOL(ext2_xattr_unregister);
1029 +EXPORT_SYMBOL(ext2_xattr_get);
1030 +EXPORT_SYMBOL(ext2_xattr_list);
1031 +EXPORT_SYMBOL(ext2_xattr_set);
1033 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1034 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
1037 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
1038 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
1039 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
1040 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
1042 +#ifdef EXT2_XATTR_DEBUG
1043 +# define ea_idebug(inode, f...) do { \
1044 + printk(KERN_DEBUG "inode %s:%ld: ", \
1045 + kdevname(inode->i_dev), inode->i_ino); \
1049 +# define ea_bdebug(bh, f...) do { \
1050 + printk(KERN_DEBUG "block %s:%ld: ", \
1051 + kdevname(bh->b_dev), bh->b_blocknr); \
1056 +# define ea_idebug(f...)
1057 +# define ea_bdebug(f...)
1060 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
1061 + struct ext2_xattr_header *);
1063 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1065 +static int ext2_xattr_cache_insert(struct buffer_head *);
1066 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
1067 + struct ext2_xattr_header *);
1068 +static void ext2_xattr_cache_remove(struct buffer_head *);
1069 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
1070 + struct ext2_xattr_entry *);
1072 +static struct mb_cache *ext2_xattr_cache;
1075 +# define ext2_xattr_cache_insert(bh) 0
1076 +# define ext2_xattr_cache_find(inode, header) NULL
1077 +# define ext2_xattr_cache_remove(bh) while(0) {}
1078 +# define ext2_xattr_rehash(header, entry) while(0) {}
1082 + * If a file system does not share extended attributes among inodes,
1083 + * we should not need the ext2_xattr_sem semaphore. However, the
1084 + * filesystem may still contain shared blocks, so we always take
1088 +DECLARE_MUTEX(ext2_xattr_sem);
1091 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
1093 + struct super_block *sb = inode->i_sb;
1094 + int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
1095 + EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
1097 + /* How can we enforce the allocation? */
1098 + int block = ext2_new_block(inode, goal, 0, 0, errp);
1101 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1107 +ext2_xattr_quota_alloc(struct inode *inode, int force)
1109 + /* How can we enforce the allocation? */
1111 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
1113 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1115 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
1123 +ext2_xattr_quota_free(struct inode *inode)
1125 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
1126 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1130 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
1132 + ext2_free_blocks(inode, block, 1);
1133 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1137 +# define ext2_xattr_quota_free(inode) \
1138 + DQUOT_FREE_BLOCK(inode, 1)
1139 +# define ext2_xattr_free_block(inode, block) \
1140 + ext2_free_blocks(inode, block, 1)
1143 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1145 +static inline struct buffer_head *
1146 +sb_bread(struct super_block *sb, int block)
1148 + return bread(sb->s_dev, block, sb->s_blocksize);
1151 +static inline struct buffer_head *
1152 +sb_getblk(struct super_block *sb, int block)
1154 + return getblk(sb->s_dev, block, sb->s_blocksize);
1159 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1160 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1163 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1165 + int error = -EINVAL;
1167 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1168 + write_lock(&ext2_handler_lock);
1169 + if (!ext2_xattr_handlers[name_index-1]) {
1170 + ext2_xattr_handlers[name_index-1] = handler;
1173 + write_unlock(&ext2_handler_lock);
1179 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1181 + if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
1182 + write_lock(&ext2_handler_lock);
1183 + ext2_xattr_handlers[name_index-1] = NULL;
1184 + write_unlock(&ext2_handler_lock);
1188 +static inline const char *
1189 +strcmp_prefix(const char *a, const char *a_prefix)
1191 + while (*a_prefix && *a == *a_prefix) {
1195 + return *a_prefix ? NULL : a;
1199 + * Decode the extended attribute name, and translate it into
1200 + * the name_index and name suffix.
1202 +static struct ext2_xattr_handler *
1203 +ext2_xattr_resolve_name(const char **name)
1205 + struct ext2_xattr_handler *handler = NULL;
1210 + read_lock(&ext2_handler_lock);
1211 + for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1212 + if (ext2_xattr_handlers[i]) {
1213 + const char *n = strcmp_prefix(*name,
1214 + ext2_xattr_handlers[i]->prefix);
1216 + handler = ext2_xattr_handlers[i];
1222 + read_unlock(&ext2_handler_lock);
1226 +static inline struct ext2_xattr_handler *
1227 +ext2_xattr_handler(int name_index)
1229 + struct ext2_xattr_handler *handler = NULL;
1230 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1231 + read_lock(&ext2_handler_lock);
1232 + handler = ext2_xattr_handlers[name_index-1];
1233 + read_unlock(&ext2_handler_lock);
1239 + * Inode operation getxattr()
1241 + * dentry->d_inode->i_sem down
1242 + * BKL held [before 2.5.x]
1245 +ext2_getxattr(struct dentry *dentry, const char *name,
1246 + void *buffer, size_t size)
1248 + struct ext2_xattr_handler *handler;
1249 + struct inode *inode = dentry->d_inode;
1251 + handler = ext2_xattr_resolve_name(&name);
1254 + return handler->get(inode, name, buffer, size);
1258 + * Inode operation listxattr()
1260 + * dentry->d_inode->i_sem down
1261 + * BKL held [before 2.5.x]
1264 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1266 + return ext2_xattr_list(dentry->d_inode, buffer, size);
1270 + * Inode operation setxattr()
1272 + * dentry->d_inode->i_sem down
1273 + * BKL held [before 2.5.x]
1276 +ext2_setxattr(struct dentry *dentry, const char *name,
1277 + const void *value, size_t size, int flags)
1279 + struct ext2_xattr_handler *handler;
1280 + struct inode *inode = dentry->d_inode;
1283 + value = ""; /* empty EA, do not remove */
1284 + handler = ext2_xattr_resolve_name(&name);
1287 + return handler->set(inode, name, value, size, flags);
1291 + * Inode operation removexattr()
1293 + * dentry->d_inode->i_sem down
1294 + * BKL held [before 2.5.x]
1297 +ext2_removexattr(struct dentry *dentry, const char *name)
1299 + struct ext2_xattr_handler *handler;
1300 + struct inode *inode = dentry->d_inode;
1302 + handler = ext2_xattr_resolve_name(&name);
1305 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1309 + * ext2_xattr_get()
1311 + * Copy an extended attribute into the buffer
1312 + * provided, or compute the buffer size required.
1313 + * Buffer is NULL to compute the size of the buffer required.
1315 + * Returns a negative error number on failure, or the number of bytes
1316 + * used / required on success.
1319 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1320 + void *buffer, size_t buffer_size)
1322 + struct buffer_head *bh = NULL;
1323 + struct ext2_xattr_entry *entry;
1324 + unsigned int block, size;
1326 + int name_len, error;
1328 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1329 + name_index, name, buffer, (long)buffer_size);
1333 + if (!EXT2_I(inode)->i_file_acl)
1335 + block = EXT2_I(inode)->i_file_acl;
1336 + ea_idebug(inode, "reading block %d", block);
1337 + bh = sb_bread(inode->i_sb, block);
1340 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1341 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1342 + end = bh->b_data + bh->b_size;
1343 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1344 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1345 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
1346 + "inode %ld: bad block %d", inode->i_ino, block);
1350 + /* find named attribute */
1351 + name_len = strlen(name);
1354 + if (name_len > 255)
1356 + entry = FIRST_ENTRY(bh);
1357 + while (!IS_LAST_ENTRY(entry)) {
1358 + struct ext2_xattr_entry *next =
1359 + EXT2_XATTR_NEXT(entry);
1360 + if ((char *)next >= end)
1362 + if (name_index == entry->e_name_index &&
1363 + name_len == entry->e_name_len &&
1364 + memcmp(name, entry->e_name, name_len) == 0)
1368 + /* Check the remaining name entries */
1369 + while (!IS_LAST_ENTRY(entry)) {
1370 + struct ext2_xattr_entry *next =
1371 + EXT2_XATTR_NEXT(entry);
1372 + if ((char *)next >= end)
1376 + if (ext2_xattr_cache_insert(bh))
1377 + ea_idebug(inode, "cache insert failed");
1381 + /* check the buffer size */
1382 + if (entry->e_value_block != 0)
1384 + size = le32_to_cpu(entry->e_value_size);
1385 + if (size > inode->i_sb->s_blocksize ||
1386 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1389 + if (ext2_xattr_cache_insert(bh))
1390 + ea_idebug(inode, "cache insert failed");
1393 + if (size > buffer_size)
1395 + /* return value of attribute */
1396 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1408 + * ext2_xattr_list()
1410 + * Copy a list of attribute names into the buffer
1411 + * provided, or compute the buffer size required.
1412 + * Buffer is NULL to compute the size of the buffer required.
1414 + * Returns a negative error number on failure, or the number of bytes
1415 + * used / required on success.
1418 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1420 + struct buffer_head *bh = NULL;
1421 + struct ext2_xattr_entry *entry;
1422 + unsigned int block, size = 0;
1426 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1427 + buffer, (long)buffer_size);
1429 + if (!EXT2_I(inode)->i_file_acl)
1431 + block = EXT2_I(inode)->i_file_acl;
1432 + ea_idebug(inode, "reading block %d", block);
1433 + bh = sb_bread(inode->i_sb, block);
1436 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1437 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1438 + end = bh->b_data + bh->b_size;
1439 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1440 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1441 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
1442 + "inode %ld: bad block %d", inode->i_ino, block);
1446 + /* compute the size required for the list of attribute names */
1447 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1448 + entry = EXT2_XATTR_NEXT(entry)) {
1449 + struct ext2_xattr_handler *handler;
1450 + struct ext2_xattr_entry *next =
1451 + EXT2_XATTR_NEXT(entry);
1452 + if ((char *)next >= end)
1455 + handler = ext2_xattr_handler(entry->e_name_index);
1457 + size += handler->list(NULL, inode, entry->e_name,
1458 + entry->e_name_len);
1461 + if (ext2_xattr_cache_insert(bh))
1462 + ea_idebug(inode, "cache insert failed");
1468 + if (size > buffer_size)
1472 + /* list the attribute names */
1474 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1475 + entry = EXT2_XATTR_NEXT(entry)) {
1476 + struct ext2_xattr_handler *handler;
1478 + handler = ext2_xattr_handler(entry->e_name_index);
1480 + buf += handler->list(buf, inode, entry->e_name,
1481 + entry->e_name_len);
1492 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1493 + * not set, set it.
1495 +static void ext2_xattr_update_super_block(struct super_block *sb)
1497 + if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1501 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1502 + EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1504 + EXT2_SB(sb)->s_es->s_feature_compat |=
1505 + cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1507 + mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1512 + * ext2_xattr_set()
1514 + * Create, replace or remove an extended attribute for this inode. Buffer
1515 + * is NULL to remove an existing extended attribute, and non-NULL to
1516 + * either replace an existing extended attribute, or create a new extended
1517 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1518 + * specify that an extended attribute must exist and must not exist
1519 + * previous to the call, respectively.
1521 + * Returns 0, or a negative error number on failure.
1524 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1525 + const void *value, size_t value_len, int flags)
1527 + struct super_block *sb = inode->i_sb;
1528 + struct buffer_head *bh = NULL;
1529 + struct ext2_xattr_header *header = NULL;
1530 + struct ext2_xattr_entry *here, *last;
1531 + unsigned int name_len;
1532 + int block = EXT2_I(inode)->i_file_acl;
1533 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
1537 + * header -- Points either into bh, or to a temporarily
1538 + * allocated buffer.
1539 + * here -- The named entry found, or the place for inserting, within
1540 + * the block pointed to by header.
1541 + * last -- Points right after the last named entry within the block
1542 + * pointed to by header.
1543 + * min_offs -- The offset of the first value (values are aligned
1544 + * towards the end of the block).
1545 + * end -- Points right after the block pointed to by header.
1548 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1549 + name_index, name, value, (long)value_len);
1551 + if (IS_RDONLY(inode))
1553 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1555 + if (value == NULL)
1559 + name_len = strlen(name);
1560 + if (name_len > 255 || value_len > sb->s_blocksize)
1562 + down(&ext2_xattr_sem);
1565 + /* The inode already has an extended attribute block. */
1567 + bh = sb_bread(sb, block);
1571 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1572 + atomic_read(&(bh->b_count)),
1573 + le32_to_cpu(HDR(bh)->h_refcount));
1575 + end = bh->b_data + bh->b_size;
1576 + if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1577 + header->h_blocks != cpu_to_le32(1)) {
1578 +bad_block: ext2_error(sb, "ext2_xattr_set",
1579 + "inode %ld: bad block %d", inode->i_ino, block);
1583 + /* Find the named attribute. */
1584 + here = FIRST_ENTRY(bh);
1585 + while (!IS_LAST_ENTRY(here)) {
1586 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1587 + if ((char *)next >= end)
1589 + if (!here->e_value_block && here->e_value_size) {
1590 + int offs = le16_to_cpu(here->e_value_offs);
1591 + if (offs < min_offs)
1594 + not_found = name_index - here->e_name_index;
1596 + not_found = name_len - here->e_name_len;
1598 + not_found = memcmp(name, here->e_name,name_len);
1599 + if (not_found <= 0)
1604 + /* We still need to compute min_offs and last. */
1605 + while (!IS_LAST_ENTRY(last)) {
1606 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1607 + if ((char *)next >= end)
1609 + if (!last->e_value_block && last->e_value_size) {
1610 + int offs = le16_to_cpu(last->e_value_offs);
1611 + if (offs < min_offs)
1617 + /* Check whether we have enough space left. */
1618 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1620 + /* We will use a new extended attribute block. */
1621 + free = sb->s_blocksize -
1622 + sizeof(struct ext2_xattr_header) - sizeof(__u32);
1623 + here = last = NULL; /* avoid gcc uninitialized warning. */
1627 + /* Request to remove a nonexistent attribute? */
1629 + if (flags & XATTR_REPLACE)
1632 + if (value == NULL)
1635 + free -= EXT2_XATTR_LEN(name_len);
1637 + /* Request to create an existing attribute? */
1639 + if (flags & XATTR_CREATE)
1641 + if (!here->e_value_block && here->e_value_size) {
1642 + unsigned int size = le32_to_cpu(here->e_value_size);
1644 + if (le16_to_cpu(here->e_value_offs) + size >
1645 + sb->s_blocksize || size > sb->s_blocksize)
1647 + free += EXT2_XATTR_SIZE(size);
1650 + free -= EXT2_XATTR_SIZE(value_len);
1655 + /* Here we know that we can set the new attribute. */
1658 + if (header->h_refcount == cpu_to_le32(1)) {
1659 + ea_bdebug(bh, "modifying in-place");
1660 + ext2_xattr_cache_remove(bh);
1664 + ea_bdebug(bh, "cloning");
1665 + header = kmalloc(bh->b_size, GFP_KERNEL);
1667 + if (header == NULL)
1669 + memcpy(header, HDR(bh), bh->b_size);
1670 + header->h_refcount = cpu_to_le32(1);
1671 + offset = (char *)header - bh->b_data;
1672 + here = ENTRY((char *)here + offset);
1673 + last = ENTRY((char *)last + offset);
1676 + /* Allocate a buffer where we construct the new block. */
1677 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1679 + if (header == NULL)
1681 + memset(header, 0, sb->s_blocksize);
1682 + end = (char *)header + sb->s_blocksize;
1683 + header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1684 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
1685 + last = here = ENTRY(header+1);
1689 + /* Insert the new name. */
1690 + int size = EXT2_XATTR_LEN(name_len);
1691 + int rest = (char *)last - (char *)here;
1692 + memmove((char *)here + size, here, rest);
1693 + memset(here, 0, size);
1694 + here->e_name_index = name_index;
1695 + here->e_name_len = name_len;
1696 + memcpy(here->e_name, name, name_len);
1698 + /* Remove the old value. */
1699 + if (!here->e_value_block && here->e_value_size) {
1700 + char *first_val = (char *)header + min_offs;
1701 + int offs = le16_to_cpu(here->e_value_offs);
1702 + char *val = (char *)header + offs;
1703 + size_t size = EXT2_XATTR_SIZE(
1704 + le32_to_cpu(here->e_value_size));
1705 + memmove(first_val + size, first_val, val - first_val);
1706 + memset(first_val, 0, size);
1707 + here->e_value_offs = 0;
1710 + /* Adjust all value offsets. */
1711 + last = ENTRY(header+1);
1712 + while (!IS_LAST_ENTRY(last)) {
1713 + int o = le16_to_cpu(last->e_value_offs);
1714 + if (!last->e_value_block && o < offs)
1715 + last->e_value_offs =
1716 + cpu_to_le16(o + size);
1717 + last = EXT2_XATTR_NEXT(last);
1720 + if (value == NULL) {
1721 + /* Remove this attribute. */
1722 + if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1723 + /* This block is now empty. */
1724 + error = ext2_xattr_set2(inode, bh, NULL);
1727 + /* Remove the old name. */
1728 + int size = EXT2_XATTR_LEN(name_len);
1729 + last = ENTRY((char *)last - size);
1730 + memmove(here, (char*)here + size,
1731 + (char*)last - (char*)here);
1732 + memset(last, 0, size);
1737 + if (value != NULL) {
1738 + /* Insert the new value. */
1739 + here->e_value_size = cpu_to_le32(value_len);
1741 + size_t size = EXT2_XATTR_SIZE(value_len);
1742 + char *val = (char *)header + min_offs - size;
1743 + here->e_value_offs =
1744 + cpu_to_le16((char *)val - (char *)header);
1745 + memset(val + size - EXT2_XATTR_PAD, 0,
1746 + EXT2_XATTR_PAD); /* Clear the pad bytes. */
1747 + memcpy(val, value, value_len);
1750 + ext2_xattr_rehash(header, here);
1752 + error = ext2_xattr_set2(inode, bh, header);
1756 + if (!(bh && header == HDR(bh)))
1758 + up(&ext2_xattr_sem);
1764 + * Second half of ext2_xattr_set(): Update the file system.
1767 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1768 + struct ext2_xattr_header *header)
1770 + struct super_block *sb = inode->i_sb;
1771 + struct buffer_head *new_bh = NULL;
1775 + new_bh = ext2_xattr_cache_find(inode, header);
1778 + * We found an identical block in the cache.
1779 + * The old block will be released after updating
1782 + ea_bdebug(old_bh, "reusing block %ld",
1783 + new_bh->b_blocknr);
1786 + if (ext2_xattr_quota_alloc(inode, 1))
1789 + HDR(new_bh)->h_refcount = cpu_to_le32(
1790 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1791 + ea_bdebug(new_bh, "refcount now=%d",
1792 + le32_to_cpu(HDR(new_bh)->h_refcount));
1793 + } else if (old_bh && header == HDR(old_bh)) {
1794 + /* Keep this block. */
1796 + ext2_xattr_cache_insert(new_bh);
1798 + /* We need to allocate a new block */
1799 + int force = EXT2_I(inode)->i_file_acl != 0;
1800 + int block = ext2_xattr_new_block(inode, &error, force);
1803 + ea_idebug(inode, "creating block %d", block);
1805 + new_bh = sb_getblk(sb, block);
1807 + ext2_xattr_free_block(inode, block);
1811 + lock_buffer(new_bh);
1812 + memcpy(new_bh->b_data, header, new_bh->b_size);
1813 + mark_buffer_uptodate(new_bh, 1);
1814 + unlock_buffer(new_bh);
1815 + ext2_xattr_cache_insert(new_bh);
1817 + ext2_xattr_update_super_block(sb);
1819 + mark_buffer_dirty(new_bh);
1820 + if (IS_SYNC(inode)) {
1821 + ll_rw_block(WRITE, 1, &new_bh);
1822 + wait_on_buffer(new_bh);
1824 + if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1829 + /* Update the inode. */
1830 + EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1831 + inode->i_ctime = CURRENT_TIME;
1832 + if (IS_SYNC(inode)) {
1833 + error = ext2_sync_inode (inode);
1837 + mark_inode_dirty(inode);
1840 + if (old_bh && old_bh != new_bh) {
1842 + * If there was an old block, and we are not still using it,
1843 + * we now release the old block.
1845 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1847 + if (refcount == 1) {
1848 + /* Free the old block. */
1849 + ea_bdebug(old_bh, "freeing");
1850 + ext2_xattr_free_block(inode, old_bh->b_blocknr);
1851 + mark_buffer_clean(old_bh);
1853 + /* Decrement the refcount only. */
1855 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1856 + ext2_xattr_quota_free(inode);
1857 + mark_buffer_dirty(old_bh);
1858 + ea_bdebug(old_bh, "refcount now=%d", refcount);
1863 + if (old_bh != new_bh)
1870 + * ext2_xattr_delete_inode()
1872 + * Free extended attribute resources associated with this inode. This
1873 + * is called immediately before an inode is freed.
1876 +ext2_xattr_delete_inode(struct inode *inode)
1878 + struct buffer_head *bh;
1879 + unsigned int block = EXT2_I(inode)->i_file_acl;
1883 + down(&ext2_xattr_sem);
1885 + bh = sb_bread(inode->i_sb, block);
1887 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1888 + "inode %ld: block %d read error", inode->i_ino, block);
1891 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1892 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1893 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1894 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1895 + "inode %ld: bad block %d", inode->i_ino, block);
1898 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1899 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1900 + ext2_xattr_cache_remove(bh);
1901 + ext2_xattr_free_block(inode, block);
1905 + HDR(bh)->h_refcount = cpu_to_le32(
1906 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
1907 + mark_buffer_dirty(bh);
1908 + if (IS_SYNC(inode)) {
1909 + ll_rw_block(WRITE, 1, &bh);
1910 + wait_on_buffer(bh);
1912 + ext2_xattr_quota_free(inode);
1914 + EXT2_I(inode)->i_file_acl = 0;
1918 + up(&ext2_xattr_sem);
1922 + * ext2_xattr_put_super()
1924 + * This is called when a file system is unmounted.
1927 +ext2_xattr_put_super(struct super_block *sb)
1929 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1930 + mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
1934 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1937 + * ext2_xattr_cache_insert()
1939 + * Create a new entry in the extended attribute cache, and insert
1940 + * it unless such an entry is already in the cache.
1942 + * Returns 0, or a negative error number on failure.
1945 +ext2_xattr_cache_insert(struct buffer_head *bh)
1947 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
1948 + struct mb_cache_entry *ce;
1951 + ce = mb_cache_entry_alloc(ext2_xattr_cache);
1954 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
1956 + mb_cache_entry_free(ce);
1957 + if (error == -EBUSY) {
1958 + ea_bdebug(bh, "already in cache (%d cache entries)",
1959 + atomic_read(&ext2_xattr_cache->c_entry_count));
1963 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
1964 + atomic_read(&ext2_xattr_cache->c_entry_count));
1965 + mb_cache_entry_release(ce);
1971 + * ext2_xattr_cmp()
1973 + * Compare two extended attribute blocks for equality.
1975 + * Returns 0 if the blocks are equal, 1 if they differ, and
1976 + * a negative error number on errors.
1979 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
1980 + struct ext2_xattr_header *header2)
1982 + struct ext2_xattr_entry *entry1, *entry2;
1984 + entry1 = ENTRY(header1+1);
1985 + entry2 = ENTRY(header2+1);
1986 + while (!IS_LAST_ENTRY(entry1)) {
1987 + if (IS_LAST_ENTRY(entry2))
1989 + if (entry1->e_hash != entry2->e_hash ||
1990 + entry1->e_name_len != entry2->e_name_len ||
1991 + entry1->e_value_size != entry2->e_value_size ||
1992 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
1994 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
1996 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
1997 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
1998 + le32_to_cpu(entry1->e_value_size)))
2001 + entry1 = EXT2_XATTR_NEXT(entry1);
2002 + entry2 = EXT2_XATTR_NEXT(entry2);
2004 + if (!IS_LAST_ENTRY(entry2))
2010 + * ext2_xattr_cache_find()
2012 + * Find an identical extended attribute block.
2014 + * Returns a pointer to the block found, or NULL if such a block was
2015 + * not found or an error occurred.
2017 +static struct buffer_head *
2018 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
2020 + __u32 hash = le32_to_cpu(header->h_hash);
2021 + struct mb_cache_entry *ce;
2023 + if (!header->h_hash)
2024 + return NULL; /* never share */
2025 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
2026 + ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
2028 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
2031 + ext2_error(inode->i_sb, "ext2_xattr_cache_find",
2032 + "inode %ld: block %ld read error",
2033 + inode->i_ino, ce->e_block);
2034 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
2035 + EXT2_XATTR_REFCOUNT_MAX) {
2036 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
2037 + le32_to_cpu(HDR(bh)->h_refcount),
2038 + EXT2_XATTR_REFCOUNT_MAX);
2039 + } else if (!ext2_xattr_cmp(header, HDR(bh))) {
2040 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
2041 + mb_cache_entry_release(ce);
2045 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
2051 + * ext2_xattr_cache_remove()
2053 + * Remove the cache entry of a block from the cache. Called when a
2054 + * block becomes invalid.
2057 +ext2_xattr_cache_remove(struct buffer_head *bh)
2059 + struct mb_cache_entry *ce;
2061 + ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
2063 + ea_bdebug(bh, "removing (%d cache entries remaining)",
2064 + atomic_read(&ext2_xattr_cache->c_entry_count)-1);
2065 + mb_cache_entry_free(ce);
2067 + ea_bdebug(bh, "no cache entry");
2070 +#define NAME_HASH_SHIFT 5
2071 +#define VALUE_HASH_SHIFT 16
2074 + * ext2_xattr_hash_entry()
2076 + * Compute the hash of an extended attribute.
2078 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
2079 + struct ext2_xattr_entry *entry)
2082 + char *name = entry->e_name;
2085 + for (n=0; n < entry->e_name_len; n++) {
2086 + hash = (hash << NAME_HASH_SHIFT) ^
2087 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
2091 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
2092 + __u32 *value = (__u32 *)((char *)header +
2093 + le16_to_cpu(entry->e_value_offs));
2094 + for (n = (le32_to_cpu(entry->e_value_size) +
2095 + EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
2096 + hash = (hash << VALUE_HASH_SHIFT) ^
2097 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
2098 + le32_to_cpu(*value++);
2101 + entry->e_hash = cpu_to_le32(hash);
2104 +#undef NAME_HASH_SHIFT
2105 +#undef VALUE_HASH_SHIFT
2107 +#define BLOCK_HASH_SHIFT 16
2110 + * ext2_xattr_rehash()
2112 + * Re-compute the extended attribute hash value after an entry has changed.
2114 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
2115 + struct ext2_xattr_entry *entry)
2117 + struct ext2_xattr_entry *here;
2120 + ext2_xattr_hash_entry(header, entry);
2121 + here = ENTRY(header+1);
2122 + while (!IS_LAST_ENTRY(here)) {
2123 + if (!here->e_hash) {
2124 + /* Block is not shared if an entry's hash value == 0 */
2128 + hash = (hash << BLOCK_HASH_SHIFT) ^
2129 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
2130 + le32_to_cpu(here->e_hash);
2131 + here = EXT2_XATTR_NEXT(here);
2133 + header->h_hash = cpu_to_le32(hash);
2136 +#undef BLOCK_HASH_SHIFT
2139 +init_ext2_xattr(void)
2141 + ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
2142 + sizeof(struct mb_cache_entry) +
2143 + sizeof(struct mb_cache_entry_index), 1, 61);
2144 + if (!ext2_xattr_cache)
2151 +exit_ext2_xattr(void)
2153 + mb_cache_destroy(ext2_xattr_cache);
2156 +#else /* CONFIG_EXT2_FS_XATTR_SHARING */
2159 +init_ext2_xattr(void)
2165 +exit_ext2_xattr(void)
2169 +#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
2170 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
2171 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr_user.c 2003-07-12 15:34:44.000000000 -0600
2174 + * linux/fs/ext2/xattr_user.c
2175 + * Handler for extended user attributes.
2177 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2180 +#include <linux/module.h>
2181 +#include <linux/string.h>
2182 +#include <linux/fs.h>
2183 +#include <linux/ext2_fs.h>
2184 +#include <linux/ext2_xattr.h>
2186 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2187 +# include <linux/ext2_acl.h>
2190 +#define XATTR_USER_PREFIX "user."
2193 +ext2_xattr_user_list(char *list, struct inode *inode,
2194 + const char *name, int name_len)
2196 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2198 + if (!test_opt(inode->i_sb, XATTR_USER))
2202 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
2203 + memcpy(list+prefix_len, name, name_len);
2204 + list[prefix_len + name_len] = '\0';
2206 + return prefix_len + name_len + 1;
2210 +ext2_xattr_user_get(struct inode *inode, const char *name,
2211 + void *buffer, size_t size)
2215 + if (strcmp(name, "") == 0)
2217 + if (!test_opt(inode->i_sb, XATTR_USER))
2219 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2220 + error = ext2_permission_locked(inode, MAY_READ);
2222 + error = permission(inode, MAY_READ);
2227 + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2232 +ext2_xattr_user_set(struct inode *inode, const char *name,
2233 + const void *value, size_t size, int flags)
2237 + if (strcmp(name, "") == 0)
2239 + if (!test_opt(inode->i_sb, XATTR_USER))
2241 + if ( !S_ISREG(inode->i_mode) &&
2242 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2244 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2245 + error = ext2_permission_locked(inode, MAY_WRITE);
2247 + error = permission(inode, MAY_WRITE);
2252 + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2253 + value, size, flags);
2256 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2257 + prefix: XATTR_USER_PREFIX,
2258 + list: ext2_xattr_user_list,
2259 + get: ext2_xattr_user_get,
2260 + set: ext2_xattr_user_set,
2264 +init_ext2_xattr_user(void)
2266 + return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2267 + &ext2_xattr_user_handler);
2271 +exit_ext2_xattr_user(void)
2273 + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2274 + &ext2_xattr_user_handler);
2276 --- kernel-2.4.20-6chaos_18_7/fs/ext3/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
2277 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/Makefile 2003-07-12 15:34:44.000000000 -0600
2280 -# Makefile for the linux ext2-filesystem routines.
2281 +# Makefile for the linux ext3-filesystem routines.
2283 # Note! Dependencies are done automagically by 'make dep', which also
2284 # removes any old dependencies. DON'T put your own dependencies here
2289 -export-objs := super.o inode.o
2290 +export-objs := ext3-exports.o
2292 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2293 - ioctl.o namei.o super.o symlink.o hash.o
2294 + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2295 obj-m := $(O_TARGET)
2297 +export-objs += xattr.o
2298 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2299 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2301 include $(TOPDIR)/Rules.make
2302 --- kernel-2.4.20-6chaos_18_7/fs/ext3/file.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
2303 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/file.c 2003-07-12 15:34:44.000000000 -0600
2305 #include <linux/locks.h>
2306 #include <linux/jbd.h>
2307 #include <linux/ext3_fs.h>
2308 +#include <linux/ext3_xattr.h>
2309 #include <linux/ext3_jbd.h>
2310 #include <linux/smp_lock.h>
2312 @@ -126,5 +127,9 @@ struct file_operations ext3_file_operati
2313 struct inode_operations ext3_file_inode_operations = {
2314 truncate: ext3_truncate, /* BKL held */
2315 setattr: ext3_setattr, /* BKL held */
2316 + setxattr: ext3_setxattr, /* BKL held */
2317 + getxattr: ext3_getxattr, /* BKL held */
2318 + listxattr: ext3_listxattr, /* BKL held */
2319 + removexattr: ext3_removexattr, /* BKL held */
2322 --- kernel-2.4.20-6chaos_18_7/fs/ext3/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:30.000000000 -0600
2323 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ialloc.c 2003-07-12 15:34:44.000000000 -0600
2325 #include <linux/jbd.h>
2326 #include <linux/ext3_fs.h>
2327 #include <linux/ext3_jbd.h>
2328 +#include <linux/ext3_xattr.h>
2329 #include <linux/stat.h>
2330 #include <linux/string.h>
2331 #include <linux/locks.h>
2332 @@ -216,6 +217,7 @@ void ext3_free_inode (handle_t *handle,
2333 * as writing the quota to disk may need the lock as well.
2336 + ext3_xattr_delete_inode(handle, inode);
2337 DQUOT_FREE_INODE(inode);
2340 --- kernel-2.4.20-6chaos_18_7/fs/ext3/inode.c~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:30.000000000 -0600
2341 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/inode.c 2003-07-12 15:34:44.000000000 -0600
2344 #undef SEARCH_FROM_ZERO
2347 + * Test whether an inode is a fast symlink.
2349 +static inline int ext3_inode_is_fast_symlink(struct inode *inode)
2351 + int ea_blocks = inode->u.ext3_i.i_file_acl ?
2352 + (inode->i_sb->s_blocksize >> 9) : 0;
2354 + return (S_ISLNK(inode->i_mode) &&
2355 + inode->i_blocks - ea_blocks == 0);
2358 /* The ext3 forget function must perform a revoke if we are freeing data
2359 * which has been journaled. Metadata (eg. indirect blocks) must be
2360 * revoked in all cases.
2362 * still needs to be revoked.
2365 -static int ext3_forget(handle_t *handle, int is_metadata,
2366 +int ext3_forget(handle_t *handle, int is_metadata,
2367 struct inode *inode, struct buffer_head *bh,
2370 @@ -179,9 +191,7 @@ void ext3_delete_inode (struct inode * i
2374 - if (is_bad_inode(inode) ||
2375 - inode->i_ino == EXT3_ACL_IDX_INO ||
2376 - inode->i_ino == EXT3_ACL_DATA_INO)
2377 + if (is_bad_inode(inode))
2381 @@ -1874,6 +1884,8 @@ void ext3_truncate(struct inode * inode)
2382 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
2383 S_ISLNK(inode->i_mode)))
2385 + if (ext3_inode_is_fast_symlink(inode))
2387 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2390 @@ -2021,8 +2033,6 @@ int ext3_get_inode_loc (struct inode *in
2391 struct ext3_group_desc * gdp;
2393 if ((inode->i_ino != EXT3_ROOT_INO &&
2394 - inode->i_ino != EXT3_ACL_IDX_INO &&
2395 - inode->i_ino != EXT3_ACL_DATA_INO &&
2396 inode->i_ino != EXT3_JOURNAL_INO &&
2397 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2398 inode->i_ino > le32_to_cpu(
2399 @@ -2149,10 +2159,7 @@ void ext3_read_inode(struct inode * inod
2403 - if (inode->i_ino == EXT3_ACL_IDX_INO ||
2404 - inode->i_ino == EXT3_ACL_DATA_INO)
2405 - /* Nothing to do */ ;
2406 - else if (S_ISREG(inode->i_mode)) {
2407 + if (S_ISREG(inode->i_mode)) {
2408 inode->i_op = &ext3_file_inode_operations;
2409 inode->i_fop = &ext3_file_operations;
2410 inode->i_mapping->a_ops = &ext3_aops;
2411 @@ -2160,15 +2167,17 @@ void ext3_read_inode(struct inode * inod
2412 inode->i_op = &ext3_dir_inode_operations;
2413 inode->i_fop = &ext3_dir_operations;
2414 } else if (S_ISLNK(inode->i_mode)) {
2415 - if (!inode->i_blocks)
2416 + if (ext3_inode_is_fast_symlink(inode))
2417 inode->i_op = &ext3_fast_symlink_inode_operations;
2419 - inode->i_op = &page_symlink_inode_operations;
2420 + inode->i_op = &ext3_symlink_inode_operations;
2421 inode->i_mapping->a_ops = &ext3_aops;
2425 + inode->i_op = &ext3_special_inode_operations;
2426 init_special_inode(inode, inode->i_mode,
2427 le32_to_cpu(iloc.raw_inode->i_block[0]));
2429 /* inode->i_attr_flags = 0; unused */
2430 if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
2431 /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
2432 --- kernel-2.4.20-6chaos_18_7/fs/ext3/namei.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:43.000000000 -0600
2433 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/namei.c 2003-07-12 15:34:44.000000000 -0600
2435 #include <linux/sched.h>
2436 #include <linux/ext3_fs.h>
2437 #include <linux/ext3_jbd.h>
2438 +#include <linux/ext3_xattr.h>
2439 #include <linux/fcntl.h>
2440 #include <linux/stat.h>
2441 #include <linux/string.h>
2442 @@ -1613,7 +1614,7 @@ static int ext3_mkdir(struct inode * dir
2446 - inode = ext3_new_inode (handle, dir, S_IFDIR);
2447 + inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2448 err = PTR_ERR(inode);
2451 @@ -1621,7 +1622,6 @@ static int ext3_mkdir(struct inode * dir
2452 inode->i_op = &ext3_dir_inode_operations;
2453 inode->i_fop = &ext3_dir_operations;
2454 inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2455 - inode->i_blocks = 0;
2456 dir_block = ext3_bread (handle, inode, 0, 1, &err);
2458 inode->i_nlink--; /* is this nlink == 0? */
2459 @@ -1648,9 +1648,6 @@ static int ext3_mkdir(struct inode * dir
2460 BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2461 ext3_journal_dirty_metadata(handle, dir_block);
2463 - inode->i_mode = S_IFDIR | mode;
2464 - if (dir->i_mode & S_ISGID)
2465 - inode->i_mode |= S_ISGID;
2466 ext3_mark_inode_dirty(handle, inode);
2467 err = ext3_add_entry (handle, dentry, inode);
2469 @@ -2019,7 +2016,7 @@ static int ext3_symlink (struct inode *
2472 if (l > sizeof (EXT3_I(inode)->i_data)) {
2473 - inode->i_op = &page_symlink_inode_operations;
2474 + inode->i_op = &ext3_symlink_inode_operations;
2475 inode->i_mapping->a_ops = &ext3_aops;
2477 * block_symlink() calls back into ext3_prepare/commit_write.
2478 @@ -2245,4 +2242,16 @@ struct inode_operations ext3_dir_inode_o
2479 rmdir: ext3_rmdir, /* BKL held */
2480 mknod: ext3_mknod, /* BKL held */
2481 rename: ext3_rename, /* BKL held */
2482 + setxattr: ext3_setxattr, /* BKL held */
2483 + getxattr: ext3_getxattr, /* BKL held */
2484 + listxattr: ext3_listxattr, /* BKL held */
2485 + removexattr: ext3_removexattr, /* BKL held */
2488 +struct inode_operations ext3_special_inode_operations = {
2489 + setxattr: ext3_setxattr, /* BKL held */
2490 + getxattr: ext3_getxattr, /* BKL held */
2491 + listxattr: ext3_listxattr, /* BKL held */
2492 + removexattr: ext3_removexattr, /* BKL held */
2495 --- kernel-2.4.20-6chaos_18_7/fs/ext3/super.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
2496 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/super.c 2003-07-12 15:34:44.000000000 -0600
2498 #include <linux/jbd.h>
2499 #include <linux/ext3_fs.h>
2500 #include <linux/ext3_jbd.h>
2501 +#include <linux/ext3_xattr.h>
2502 #include <linux/slab.h>
2503 #include <linux/init.h>
2504 #include <linux/locks.h>
2505 @@ -406,6 +407,7 @@ void ext3_put_super (struct super_block
2506 kdev_t j_dev = sbi->s_journal->j_dev;
2509 + ext3_xattr_put_super(sb);
2510 journal_destroy(sbi->s_journal);
2511 if (!(sb->s_flags & MS_RDONLY)) {
2512 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2513 @@ -502,6 +504,7 @@ static int parse_options (char * options
2516 unsigned long *mount_options = &sbi->s_mount_opt;
2518 uid_t *resuid = &sbi->s_resuid;
2519 gid_t *resgid = &sbi->s_resgid;
2521 @@ -514,6 +517,13 @@ static int parse_options (char * options
2522 this_char = strtok (NULL, ",")) {
2523 if ((value = strchr (this_char, '=')) != NULL)
2525 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2526 + if (!strcmp (this_char, "user_xattr"))
2527 + set_opt (*mount_options, XATTR_USER);
2528 + else if (!strcmp (this_char, "nouser_xattr"))
2529 + clear_opt (*mount_options, XATTR_USER);
2532 if (!strcmp (this_char, "bsddf"))
2533 clear_opt (*mount_options, MINIX_DF);
2534 else if (!strcmp (this_char, "nouid32")) {
2535 @@ -931,6 +941,12 @@ struct super_block * ext3_read_super (st
2536 sbi->s_mount_opt = 0;
2537 sbi->s_resuid = EXT3_DEF_RESUID;
2538 sbi->s_resgid = EXT3_DEF_RESGID;
2540 + /* Default extended attribute flags */
2541 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2542 + /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2545 if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2548 @@ -1768,17 +1784,29 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type,
2550 static int __init init_ext3_fs(void)
2552 - return register_filesystem(&ext3_fs_type);
2553 + int error = init_ext3_xattr();
2556 + error = init_ext3_xattr_user();
2559 + error = register_filesystem(&ext3_fs_type);
2563 + exit_ext3_xattr_user();
2565 + exit_ext3_xattr();
2569 static void __exit exit_ext3_fs(void)
2571 unregister_filesystem(&ext3_fs_type);
2572 + exit_ext3_xattr_user();
2573 + exit_ext3_xattr();
2576 -EXPORT_SYMBOL(ext3_force_commit);
2577 -EXPORT_SYMBOL(ext3_bread);
2579 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2580 MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2581 MODULE_LICENSE("GPL");
2582 --- kernel-2.4.20-6chaos_18_7/fs/ext3/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
2583 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/symlink.c 2003-07-12 15:34:44.000000000 -0600
2585 #include <linux/fs.h>
2586 #include <linux/jbd.h>
2587 #include <linux/ext3_fs.h>
2588 +#include <linux/ext3_xattr.h>
2590 static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2592 @@ -33,7 +34,20 @@ static int ext3_follow_link(struct dentr
2593 return vfs_follow_link(nd, s);
2596 +struct inode_operations ext3_symlink_inode_operations = {
2597 + readlink: page_readlink, /* BKL not held. Don't need */
2598 + follow_link: page_follow_link, /* BKL not held. Don't need */
2599 + setxattr: ext3_setxattr, /* BKL held */
2600 + getxattr: ext3_getxattr, /* BKL held */
2601 + listxattr: ext3_listxattr, /* BKL held */
2602 + removexattr: ext3_removexattr, /* BKL held */
2605 struct inode_operations ext3_fast_symlink_inode_operations = {
2606 readlink: ext3_readlink, /* BKL not held. Don't need */
2607 follow_link: ext3_follow_link, /* BKL not held. Don't need */
2608 + setxattr: ext3_setxattr, /* BKL held */
2609 + getxattr: ext3_getxattr, /* BKL held */
2610 + listxattr: ext3_listxattr, /* BKL held */
2611 + removexattr: ext3_removexattr, /* BKL held */
2613 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
2614 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr.c 2003-07-12 15:34:44.000000000 -0600
2617 + * linux/fs/ext3/xattr.c
2619 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2621 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2622 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2623 + * Extended attributes for symlinks and special files added per
2624 + * suggestion of Luka Renko <luka.renko@hermes.si>.
2628 + * Extended attributes are stored on disk blocks allocated outside of
2629 + * any inode. The i_file_acl field is then made to point to this allocated
2630 + * block. If all extended attributes of an inode are identical, these
2631 + * inodes may share the same extended attribute block. Such situations
2632 + * are automatically detected by keeping a cache of recent attribute block
2633 + * numbers and hashes over the block's contents in memory.
2636 + * Extended attribute block layout:
2638 + * +------------------+
2641 + * | entry 2 | | growing downwards
2643 + * | four null bytes |
2646 + * | value 3 | | growing upwards
2648 + * +------------------+
2650 + * The block header is followed by multiple entry descriptors. These entry
2651 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2652 + * byte boundaries. The entry descriptors are sorted by attribute name,
2653 + * so that two extended attribute blocks can be compared efficiently.
2655 + * Attribute values are aligned to the end of the block, stored in
2656 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2657 + * boundaries. No additional gaps are left between them.
2659 + * Locking strategy
2660 + * ----------------
2661 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2662 + * the xattr inode operations are called, so we are guaranteed that only one
2663 + * processes accesses extended attributes of an inode at any time.
2665 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2666 + * only a single process is modifying an extended attribute block, even
2667 + * if the block is shared among inodes.
2669 + * Note for porting to 2.5
2670 + * -----------------------
2671 + * The BKL will no longer be held in the xattr inode operations.
2674 +#include <linux/module.h>
2675 +#include <linux/fs.h>
2676 +#include <linux/locks.h>
2677 +#include <linux/slab.h>
2678 +#include <linux/ext3_jbd.h>
2679 +#include <linux/ext3_fs.h>
2680 +#include <linux/ext3_xattr.h>
2681 +#include <linux/mbcache.h>
2682 +#include <linux/quotaops.h>
2683 +#include <asm/semaphore.h>
2684 +#include <linux/compatmac.h>
2686 +#define EXT3_EA_USER "user."
2688 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2689 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2692 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2693 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2694 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2695 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2697 +#ifdef EXT3_XATTR_DEBUG
2698 +# define ea_idebug(inode, f...) do { \
2699 + printk(KERN_DEBUG "inode %s:%ld: ", \
2700 + kdevname(inode->i_dev), inode->i_ino); \
2704 +# define ea_bdebug(bh, f...) do { \
2705 + printk(KERN_DEBUG "block %s:%ld: ", \
2706 + kdevname(bh->b_dev), bh->b_blocknr); \
2711 +# define ea_idebug(f...)
2712 +# define ea_bdebug(f...)
2715 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2716 + struct ext3_xattr_header *);
2718 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2720 +static int ext3_xattr_cache_insert(struct buffer_head *);
2721 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2722 + struct ext3_xattr_header *);
2723 +static void ext3_xattr_cache_remove(struct buffer_head *);
2724 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2725 + struct ext3_xattr_entry *);
2727 +static struct mb_cache *ext3_xattr_cache;
2730 +# define ext3_xattr_cache_insert(bh) 0
2731 +# define ext3_xattr_cache_find(inode, header) NULL
2732 +# define ext3_xattr_cache_remove(bh) while(0) {}
2733 +# define ext3_xattr_rehash(header, entry) while(0) {}
2737 + * If a file system does not share extended attributes among inodes,
2738 + * we should not need the ext3_xattr_sem semaphore. However, the
2739 + * filesystem may still contain shared blocks, so we always take
2743 +DECLARE_MUTEX(ext3_xattr_sem);
2746 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2747 + int * errp, int force)
2749 + struct super_block *sb = inode->i_sb;
2750 + int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2751 + EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2753 + /* How can we enforce the allocation? */
2754 + int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2757 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2763 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2765 + /* How can we enforce the allocation? */
2767 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2769 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2771 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
2779 +ext3_xattr_quota_free(struct inode *inode)
2781 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2782 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2786 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2787 + unsigned long block)
2789 + ext3_free_blocks(handle, inode, block, 1);
2790 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2794 +# define ext3_xattr_quota_free(inode) \
2795 + DQUOT_FREE_BLOCK(inode, 1)
2796 +# define ext3_xattr_free_block(handle, inode, block) \
2797 + ext3_free_blocks(handle, inode, block, 1)
2800 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2802 +static inline struct buffer_head *
2803 +sb_bread(struct super_block *sb, int block)
2805 + return bread(sb->s_dev, block, sb->s_blocksize);
2808 +static inline struct buffer_head *
2809 +sb_getblk(struct super_block *sb, int block)
2811 + return getblk(sb->s_dev, block, sb->s_blocksize);
2816 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2817 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2820 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2822 + int error = -EINVAL;
2824 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2825 + write_lock(&ext3_handler_lock);
2826 + if (!ext3_xattr_handlers[name_index-1]) {
2827 + ext3_xattr_handlers[name_index-1] = handler;
2830 + write_unlock(&ext3_handler_lock);
2836 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2838 + if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2839 + write_lock(&ext3_handler_lock);
2840 + ext3_xattr_handlers[name_index-1] = NULL;
2841 + write_unlock(&ext3_handler_lock);
2845 +static inline const char *
2846 +strcmp_prefix(const char *a, const char *a_prefix)
2848 + while (*a_prefix && *a == *a_prefix) {
2852 + return *a_prefix ? NULL : a;
2856 + * Decode the extended attribute name, and translate it into
2857 + * the name_index and name suffix.
2859 +static inline struct ext3_xattr_handler *
2860 +ext3_xattr_resolve_name(const char **name)
2862 + struct ext3_xattr_handler *handler = NULL;
2867 + read_lock(&ext3_handler_lock);
2868 + for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2869 + if (ext3_xattr_handlers[i]) {
2870 + const char *n = strcmp_prefix(*name,
2871 + ext3_xattr_handlers[i]->prefix);
2873 + handler = ext3_xattr_handlers[i];
2879 + read_unlock(&ext3_handler_lock);
2883 +static inline struct ext3_xattr_handler *
2884 +ext3_xattr_handler(int name_index)
2886 + struct ext3_xattr_handler *handler = NULL;
2887 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2888 + read_lock(&ext3_handler_lock);
2889 + handler = ext3_xattr_handlers[name_index-1];
2890 + read_unlock(&ext3_handler_lock);
2896 + * Inode operation getxattr()
2898 + * dentry->d_inode->i_sem down
2899 + * BKL held [before 2.5.x]
2902 +ext3_getxattr(struct dentry *dentry, const char *name,
2903 + void *buffer, size_t size)
2905 + struct ext3_xattr_handler *handler;
2906 + struct inode *inode = dentry->d_inode;
2908 + handler = ext3_xattr_resolve_name(&name);
2911 + return handler->get(inode, name, buffer, size);
2915 + * Inode operation listxattr()
2917 + * dentry->d_inode->i_sem down
2918 + * BKL held [before 2.5.x]
2921 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
2923 + return ext3_xattr_list(dentry->d_inode, buffer, size);
2927 + * Inode operation setxattr()
2929 + * dentry->d_inode->i_sem down
2930 + * BKL held [before 2.5.x]
2933 +ext3_setxattr(struct dentry *dentry, const char *name,
2934 + const void *value, size_t size, int flags)
2936 + struct ext3_xattr_handler *handler;
2937 + struct inode *inode = dentry->d_inode;
2940 + value = ""; /* empty EA, do not remove */
2941 + handler = ext3_xattr_resolve_name(&name);
2944 + return handler->set(inode, name, value, size, flags);
2948 + * Inode operation removexattr()
2950 + * dentry->d_inode->i_sem down
2951 + * BKL held [before 2.5.x]
2954 +ext3_removexattr(struct dentry *dentry, const char *name)
2956 + struct ext3_xattr_handler *handler;
2957 + struct inode *inode = dentry->d_inode;
2959 + handler = ext3_xattr_resolve_name(&name);
2962 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
2966 + * ext3_xattr_get()
2968 + * Copy an extended attribute into the buffer
2969 + * provided, or compute the buffer size required.
2970 + * Buffer is NULL to compute the size of the buffer required.
2972 + * Returns a negative error number on failure, or the number of bytes
2973 + * used / required on success.
2976 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
2977 + void *buffer, size_t buffer_size)
2979 + struct buffer_head *bh = NULL;
2980 + struct ext3_xattr_entry *entry;
2981 + unsigned int block, size;
2983 + int name_len, error;
2985 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
2986 + name_index, name, buffer, (long)buffer_size);
2990 + if (!EXT3_I(inode)->i_file_acl)
2992 + block = EXT3_I(inode)->i_file_acl;
2993 + ea_idebug(inode, "reading block %d", block);
2994 + bh = sb_bread(inode->i_sb, block);
2997 + ea_bdebug(bh, "b_count=%d, refcount=%d",
2998 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
2999 + end = bh->b_data + bh->b_size;
3000 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3001 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3002 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
3003 + "inode %ld: bad block %d", inode->i_ino, block);
3007 + /* find named attribute */
3008 + name_len = strlen(name);
3011 + if (name_len > 255)
3013 + entry = FIRST_ENTRY(bh);
3014 + while (!IS_LAST_ENTRY(entry)) {
3015 + struct ext3_xattr_entry *next =
3016 + EXT3_XATTR_NEXT(entry);
3017 + if ((char *)next >= end)
3019 + if (name_index == entry->e_name_index &&
3020 + name_len == entry->e_name_len &&
3021 + memcmp(name, entry->e_name, name_len) == 0)
3025 + /* Check the remaining name entries */
3026 + while (!IS_LAST_ENTRY(entry)) {
3027 + struct ext3_xattr_entry *next =
3028 + EXT3_XATTR_NEXT(entry);
3029 + if ((char *)next >= end)
3033 + if (ext3_xattr_cache_insert(bh))
3034 + ea_idebug(inode, "cache insert failed");
3038 + /* check the buffer size */
3039 + if (entry->e_value_block != 0)
3041 + size = le32_to_cpu(entry->e_value_size);
3042 + if (size > inode->i_sb->s_blocksize ||
3043 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
3046 + if (ext3_xattr_cache_insert(bh))
3047 + ea_idebug(inode, "cache insert failed");
3050 + if (size > buffer_size)
3052 + /* return value of attribute */
3053 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
3065 + * ext3_xattr_list()
3067 + * Copy a list of attribute names into the buffer
3068 + * provided, or compute the buffer size required.
3069 + * Buffer is NULL to compute the size of the buffer required.
3071 + * Returns a negative error number on failure, or the number of bytes
3072 + * used / required on success.
3075 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
3077 + struct buffer_head *bh = NULL;
3078 + struct ext3_xattr_entry *entry;
3079 + unsigned int block, size = 0;
3083 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
3084 + buffer, (long)buffer_size);
3086 + if (!EXT3_I(inode)->i_file_acl)
3088 + block = EXT3_I(inode)->i_file_acl;
3089 + ea_idebug(inode, "reading block %d", block);
3090 + bh = sb_bread(inode->i_sb, block);
3093 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3094 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3095 + end = bh->b_data + bh->b_size;
3096 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3097 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3098 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
3099 + "inode %ld: bad block %d", inode->i_ino, block);
3103 + /* compute the size required for the list of attribute names */
3104 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3105 + entry = EXT3_XATTR_NEXT(entry)) {
3106 + struct ext3_xattr_handler *handler;
3107 + struct ext3_xattr_entry *next =
3108 + EXT3_XATTR_NEXT(entry);
3109 + if ((char *)next >= end)
3112 + handler = ext3_xattr_handler(entry->e_name_index);
3114 + size += handler->list(NULL, inode, entry->e_name,
3115 + entry->e_name_len);
3118 + if (ext3_xattr_cache_insert(bh))
3119 + ea_idebug(inode, "cache insert failed");
3125 + if (size > buffer_size)
3129 + /* list the attribute names */
3131 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3132 + entry = EXT3_XATTR_NEXT(entry)) {
3133 + struct ext3_xattr_handler *handler;
3135 + handler = ext3_xattr_handler(entry->e_name_index);
3137 + buf += handler->list(buf, inode, entry->e_name,
3138 + entry->e_name_len);
3149 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3150 + * not set, set it.
3152 +static void ext3_xattr_update_super_block(handle_t *handle,
3153 + struct super_block *sb)
3155 + if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3159 + ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3160 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3161 + EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3163 + EXT3_SB(sb)->s_es->s_feature_compat |=
3164 + cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3166 + ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3171 + * ext3_xattr_set()
3173 + * Create, replace or remove an extended attribute for this inode. Buffer
3174 + * is NULL to remove an existing extended attribute, and non-NULL to
3175 + * either replace an existing extended attribute, or create a new extended
3176 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3177 + * specify that an extended attribute must exist and must not exist
3178 + * previous to the call, respectively.
3180 + * Returns 0, or a negative error number on failure.
3183 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3184 + const char *name, const void *value, size_t value_len, int flags)
3186 + struct super_block *sb = inode->i_sb;
3187 + struct buffer_head *bh = NULL;
3188 + struct ext3_xattr_header *header = NULL;
3189 + struct ext3_xattr_entry *here, *last;
3190 + unsigned int name_len;
3191 + int block = EXT3_I(inode)->i_file_acl;
3192 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
3196 + * header -- Points either into bh, or to a temporarily
3197 + * allocated buffer.
3198 + * here -- The named entry found, or the place for inserting, within
3199 + * the block pointed to by header.
3200 + * last -- Points right after the last named entry within the block
3201 + * pointed to by header.
3202 + * min_offs -- The offset of the first value (values are aligned
3203 + * towards the end of the block).
3204 + * end -- Points right after the block pointed to by header.
3207 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3208 + name_index, name, value, (long)value_len);
3210 + if (IS_RDONLY(inode))
3212 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3214 + if (value == NULL)
3218 + name_len = strlen(name);
3219 + if (name_len > 255 || value_len > sb->s_blocksize)
3221 + down(&ext3_xattr_sem);
3224 + /* The inode already has an extended attribute block. */
3225 + bh = sb_bread(sb, block);
3229 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3230 + atomic_read(&(bh->b_count)),
3231 + le32_to_cpu(HDR(bh)->h_refcount));
3233 + end = bh->b_data + bh->b_size;
3234 + if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3235 + header->h_blocks != cpu_to_le32(1)) {
3236 +bad_block: ext3_error(sb, "ext3_xattr_set",
3237 + "inode %ld: bad block %d", inode->i_ino, block);
3241 + /* Find the named attribute. */
3242 + here = FIRST_ENTRY(bh);
3243 + while (!IS_LAST_ENTRY(here)) {
3244 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3245 + if ((char *)next >= end)
3247 + if (!here->e_value_block && here->e_value_size) {
3248 + int offs = le16_to_cpu(here->e_value_offs);
3249 + if (offs < min_offs)
3252 + not_found = name_index - here->e_name_index;
3254 + not_found = name_len - here->e_name_len;
3256 + not_found = memcmp(name, here->e_name,name_len);
3257 + if (not_found <= 0)
3262 + /* We still need to compute min_offs and last. */
3263 + while (!IS_LAST_ENTRY(last)) {
3264 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3265 + if ((char *)next >= end)
3267 + if (!last->e_value_block && last->e_value_size) {
3268 + int offs = le16_to_cpu(last->e_value_offs);
3269 + if (offs < min_offs)
3275 + /* Check whether we have enough space left. */
3276 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3278 + /* We will use a new extended attribute block. */
3279 + free = sb->s_blocksize -
3280 + sizeof(struct ext3_xattr_header) - sizeof(__u32);
3281 + here = last = NULL; /* avoid gcc uninitialized warning. */
3285 + /* Request to remove a nonexistent attribute? */
3287 + if (flags & XATTR_REPLACE)
3290 + if (value == NULL)
3293 + free -= EXT3_XATTR_LEN(name_len);
3295 + /* Request to create an existing attribute? */
3297 + if (flags & XATTR_CREATE)
3299 + if (!here->e_value_block && here->e_value_size) {
3300 + unsigned int size = le32_to_cpu(here->e_value_size);
3302 + if (le16_to_cpu(here->e_value_offs) + size >
3303 + sb->s_blocksize || size > sb->s_blocksize)
3305 + free += EXT3_XATTR_SIZE(size);
3308 + free -= EXT3_XATTR_SIZE(value_len);
3313 + /* Here we know that we can set the new attribute. */
3316 + if (header->h_refcount == cpu_to_le32(1)) {
3317 + ea_bdebug(bh, "modifying in-place");
3318 + ext3_xattr_cache_remove(bh);
3319 + error = ext3_journal_get_write_access(handle, bh);
3325 + ea_bdebug(bh, "cloning");
3326 + header = kmalloc(bh->b_size, GFP_KERNEL);
3328 + if (header == NULL)
3330 + memcpy(header, HDR(bh), bh->b_size);
3331 + header->h_refcount = cpu_to_le32(1);
3332 + offset = (char *)header - bh->b_data;
3333 + here = ENTRY((char *)here + offset);
3334 + last = ENTRY((char *)last + offset);
3337 + /* Allocate a buffer where we construct the new block. */
3338 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3340 + if (header == NULL)
3342 + memset(header, 0, sb->s_blocksize);
3343 + end = (char *)header + sb->s_blocksize;
3344 + header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3345 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
3346 + last = here = ENTRY(header+1);
3350 + /* Insert the new name. */
3351 + int size = EXT3_XATTR_LEN(name_len);
3352 + int rest = (char *)last - (char *)here;
3353 + memmove((char *)here + size, here, rest);
3354 + memset(here, 0, size);
3355 + here->e_name_index = name_index;
3356 + here->e_name_len = name_len;
3357 + memcpy(here->e_name, name, name_len);
3359 + /* Remove the old value. */
3360 + if (!here->e_value_block && here->e_value_size) {
3361 + char *first_val = (char *)header + min_offs;
3362 + int offs = le16_to_cpu(here->e_value_offs);
3363 + char *val = (char *)header + offs;
3364 + size_t size = EXT3_XATTR_SIZE(
3365 + le32_to_cpu(here->e_value_size));
3366 + memmove(first_val + size, first_val, val - first_val);
3367 + memset(first_val, 0, size);
3368 + here->e_value_offs = 0;
3371 + /* Adjust all value offsets. */
3372 + last = ENTRY(header+1);
3373 + while (!IS_LAST_ENTRY(last)) {
3374 + int o = le16_to_cpu(last->e_value_offs);
3375 + if (!last->e_value_block && o < offs)
3376 + last->e_value_offs =
3377 + cpu_to_le16(o + size);
3378 + last = EXT3_XATTR_NEXT(last);
3381 + if (value == NULL) {
3382 + /* Remove this attribute. */
3383 + if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3384 + /* This block is now empty. */
3385 + error = ext3_xattr_set2(handle, inode, bh,NULL);
3388 + /* Remove the old name. */
3389 + int size = EXT3_XATTR_LEN(name_len);
3390 + last = ENTRY((char *)last - size);
3391 + memmove(here, (char*)here + size,
3392 + (char*)last - (char*)here);
3393 + memset(last, 0, size);
3398 + if (value != NULL) {
3399 + /* Insert the new value. */
3400 + here->e_value_size = cpu_to_le32(value_len);
3402 + size_t size = EXT3_XATTR_SIZE(value_len);
3403 + char *val = (char *)header + min_offs - size;
3404 + here->e_value_offs =
3405 + cpu_to_le16((char *)val - (char *)header);
3406 + memset(val + size - EXT3_XATTR_PAD, 0,
3407 + EXT3_XATTR_PAD); /* Clear the pad bytes. */
3408 + memcpy(val, value, value_len);
3411 + ext3_xattr_rehash(header, here);
3413 + error = ext3_xattr_set2(handle, inode, bh, header);
3417 + if (!(bh && header == HDR(bh)))
3419 + up(&ext3_xattr_sem);
3425 + * Second half of ext3_xattr_set(): Update the file system.
3428 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3429 + struct buffer_head *old_bh, struct ext3_xattr_header *header)
3431 + struct super_block *sb = inode->i_sb;
3432 + struct buffer_head *new_bh = NULL;
3436 + new_bh = ext3_xattr_cache_find(inode, header);
3439 + * We found an identical block in the cache.
3440 + * The old block will be released after updating
3443 + ea_bdebug(old_bh, "reusing block %ld",
3444 + new_bh->b_blocknr);
3447 + if (ext3_xattr_quota_alloc(inode, 1))
3450 + error = ext3_journal_get_write_access(handle, new_bh);
3453 + HDR(new_bh)->h_refcount = cpu_to_le32(
3454 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3455 + ea_bdebug(new_bh, "refcount now=%d",
3456 + le32_to_cpu(HDR(new_bh)->h_refcount));
3457 + } else if (old_bh && header == HDR(old_bh)) {
3458 + /* Keep this block. */
3460 + ext3_xattr_cache_insert(new_bh);
3462 + /* We need to allocate a new block */
3463 + int force = EXT3_I(inode)->i_file_acl != 0;
3464 + int block = ext3_xattr_new_block(handle, inode,
3468 + ea_idebug(inode, "creating block %d", block);
3470 + new_bh = sb_getblk(sb, block);
3472 +getblk_failed: ext3_xattr_free_block(handle, inode, block);
3476 + lock_buffer(new_bh);
3477 + error = ext3_journal_get_create_access(handle, new_bh);
3479 + unlock_buffer(new_bh);
3480 + goto getblk_failed;
3482 + memcpy(new_bh->b_data, header, new_bh->b_size);
3483 + mark_buffer_uptodate(new_bh, 1);
3484 + unlock_buffer(new_bh);
3485 + ext3_xattr_cache_insert(new_bh);
3487 + ext3_xattr_update_super_block(handle, sb);
3489 + error = ext3_journal_dirty_metadata(handle, new_bh);
3494 + /* Update the inode. */
3495 + EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3496 + inode->i_ctime = CURRENT_TIME;
3497 + ext3_mark_inode_dirty(handle, inode);
3498 + if (IS_SYNC(inode))
3499 + handle->h_sync = 1;
3502 + if (old_bh && old_bh != new_bh) {
3504 + * If there was an old block, and we are not still using it,
3505 + * we now release the old block.
3507 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3509 + error = ext3_journal_get_write_access(handle, old_bh);
3512 + if (refcount == 1) {
3513 + /* Free the old block. */
3514 + ea_bdebug(old_bh, "freeing");
3515 + ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3517 + /* ext3_forget() calls bforget() for us, but we
3518 + let our caller release old_bh, so we need to
3519 + duplicate the handle before. */
3521 + ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3523 + /* Decrement the refcount only. */
3525 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3526 + ext3_xattr_quota_free(inode);
3527 + ext3_journal_dirty_metadata(handle, old_bh);
3528 + ea_bdebug(old_bh, "refcount now=%d", refcount);
3533 + if (old_bh != new_bh)
3540 + * ext3_xattr_delete_inode()
3542 + * Free extended attribute resources associated with this inode. This
3543 + * is called immediately before an inode is freed.
3546 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3548 + struct buffer_head *bh;
3549 + unsigned int block = EXT3_I(inode)->i_file_acl;
3553 + down(&ext3_xattr_sem);
3555 + bh = sb_bread(inode->i_sb, block);
3557 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3558 + "inode %ld: block %d read error", inode->i_ino, block);
3561 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3562 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3563 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3564 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3565 + "inode %ld: bad block %d", inode->i_ino, block);
3568 + ext3_journal_get_write_access(handle, bh);
3569 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3570 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3571 + ext3_xattr_cache_remove(bh);
3572 + ext3_xattr_free_block(handle, inode, block);
3573 + ext3_forget(handle, 1, inode, bh, block);
3576 + HDR(bh)->h_refcount = cpu_to_le32(
3577 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
3578 + ext3_journal_dirty_metadata(handle, bh);
3579 + if (IS_SYNC(inode))
3580 + handle->h_sync = 1;
3581 + ext3_xattr_quota_free(inode);
3583 + EXT3_I(inode)->i_file_acl = 0;
3587 + up(&ext3_xattr_sem);
3591 + * ext3_xattr_put_super()
3593 + * This is called when a file system is unmounted.
3596 +ext3_xattr_put_super(struct super_block *sb)
3598 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3599 + mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3603 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3606 + * ext3_xattr_cache_insert()
3608 + * Create a new entry in the extended attribute cache, and insert
3609 + * it unless such an entry is already in the cache.
3611 + * Returns 0, or a negative error number on failure.
3614 +ext3_xattr_cache_insert(struct buffer_head *bh)
3616 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3617 + struct mb_cache_entry *ce;
3620 + ce = mb_cache_entry_alloc(ext3_xattr_cache);
3623 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3625 + mb_cache_entry_free(ce);
3626 + if (error == -EBUSY) {
3627 + ea_bdebug(bh, "already in cache (%d cache entries)",
3628 + atomic_read(&ext3_xattr_cache->c_entry_count));
3632 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3633 + atomic_read(&ext3_xattr_cache->c_entry_count));
3634 + mb_cache_entry_release(ce);
3640 + * ext3_xattr_cmp()
3642 + * Compare two extended attribute blocks for equality.
3644 + * Returns 0 if the blocks are equal, 1 if they differ, and
3645 + * a negative error number on errors.
3648 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3649 + struct ext3_xattr_header *header2)
3651 + struct ext3_xattr_entry *entry1, *entry2;
3653 + entry1 = ENTRY(header1+1);
3654 + entry2 = ENTRY(header2+1);
3655 + while (!IS_LAST_ENTRY(entry1)) {
3656 + if (IS_LAST_ENTRY(entry2))
3658 + if (entry1->e_hash != entry2->e_hash ||
3659 + entry1->e_name_len != entry2->e_name_len ||
3660 + entry1->e_value_size != entry2->e_value_size ||
3661 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3663 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3665 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3666 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3667 + le32_to_cpu(entry1->e_value_size)))
3670 + entry1 = EXT3_XATTR_NEXT(entry1);
3671 + entry2 = EXT3_XATTR_NEXT(entry2);
3673 + if (!IS_LAST_ENTRY(entry2))
3679 + * ext3_xattr_cache_find()
3681 + * Find an identical extended attribute block.
3683 + * Returns a pointer to the block found, or NULL if such a block was
3684 + * not found or an error occurred.
3686 +static struct buffer_head *
3687 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3689 + __u32 hash = le32_to_cpu(header->h_hash);
3690 + struct mb_cache_entry *ce;
3692 + if (!header->h_hash)
3693 + return NULL; /* never share */
3694 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3695 + ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3697 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3700 + ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3701 + "inode %ld: block %ld read error",
3702 + inode->i_ino, ce->e_block);
3703 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3704 + EXT3_XATTR_REFCOUNT_MAX) {
3705 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3706 + le32_to_cpu(HDR(bh)->h_refcount),
3707 + EXT3_XATTR_REFCOUNT_MAX);
3708 + } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3709 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3710 + mb_cache_entry_release(ce);
3714 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3720 + * ext3_xattr_cache_remove()
3722 + * Remove the cache entry of a block from the cache. Called when a
3723 + * block becomes invalid.
3726 +ext3_xattr_cache_remove(struct buffer_head *bh)
3728 + struct mb_cache_entry *ce;
3730 + ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3732 + ea_bdebug(bh, "removing (%d cache entries remaining)",
3733 + atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3734 + mb_cache_entry_free(ce);
3736 + ea_bdebug(bh, "no cache entry");
3739 +#define NAME_HASH_SHIFT 5
3740 +#define VALUE_HASH_SHIFT 16
3743 + * ext3_xattr_hash_entry()
3745 + * Compute the hash of an extended attribute.
3747 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3748 + struct ext3_xattr_entry *entry)
3751 + char *name = entry->e_name;
3754 + for (n=0; n < entry->e_name_len; n++) {
3755 + hash = (hash << NAME_HASH_SHIFT) ^
3756 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3760 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3761 + __u32 *value = (__u32 *)((char *)header +
3762 + le16_to_cpu(entry->e_value_offs));
3763 + for (n = (le32_to_cpu(entry->e_value_size) +
3764 + EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3765 + hash = (hash << VALUE_HASH_SHIFT) ^
3766 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3767 + le32_to_cpu(*value++);
3770 + entry->e_hash = cpu_to_le32(hash);
3773 +#undef NAME_HASH_SHIFT
3774 +#undef VALUE_HASH_SHIFT
3776 +#define BLOCK_HASH_SHIFT 16
3779 + * ext3_xattr_rehash()
3781 + * Re-compute the extended attribute hash value after an entry has changed.
3783 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3784 + struct ext3_xattr_entry *entry)
3786 + struct ext3_xattr_entry *here;
3789 + ext3_xattr_hash_entry(header, entry);
3790 + here = ENTRY(header+1);
3791 + while (!IS_LAST_ENTRY(here)) {
3792 + if (!here->e_hash) {
3793 + /* Block is not shared if an entry's hash value == 0 */
3797 + hash = (hash << BLOCK_HASH_SHIFT) ^
3798 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3799 + le32_to_cpu(here->e_hash);
3800 + here = EXT3_XATTR_NEXT(here);
3802 + header->h_hash = cpu_to_le32(hash);
3805 +#undef BLOCK_HASH_SHIFT
3808 +init_ext3_xattr(void)
3810 + ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3811 + sizeof(struct mb_cache_entry) +
3812 + sizeof(struct mb_cache_entry_index), 1, 61);
3813 + if (!ext3_xattr_cache)
3820 +exit_ext3_xattr(void)
3822 + if (ext3_xattr_cache)
3823 + mb_cache_destroy(ext3_xattr_cache);
3824 + ext3_xattr_cache = NULL;
3827 +#else /* CONFIG_EXT3_FS_XATTR_SHARING */
3830 +init_ext3_xattr(void)
3836 +exit_ext3_xattr(void)
3840 +#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
3841 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
3842 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr_user.c 2003-07-12 15:34:44.000000000 -0600
3845 + * linux/fs/ext3/xattr_user.c
3846 + * Handler for extended user attributes.
3848 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3851 +#include <linux/module.h>
3852 +#include <linux/string.h>
3853 +#include <linux/fs.h>
3854 +#include <linux/ext3_jbd.h>
3855 +#include <linux/ext3_fs.h>
3856 +#include <linux/ext3_xattr.h>
3858 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3859 +# include <linux/ext3_acl.h>
3862 +#define XATTR_USER_PREFIX "user."
3865 +ext3_xattr_user_list(char *list, struct inode *inode,
3866 + const char *name, int name_len)
3868 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3870 + if (!test_opt(inode->i_sb, XATTR_USER))
3874 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
3875 + memcpy(list+prefix_len, name, name_len);
3876 + list[prefix_len + name_len] = '\0';
3878 + return prefix_len + name_len + 1;
3882 +ext3_xattr_user_get(struct inode *inode, const char *name,
3883 + void *buffer, size_t size)
3887 + if (strcmp(name, "") == 0)
3889 + if (!test_opt(inode->i_sb, XATTR_USER))
3891 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3892 + error = ext3_permission_locked(inode, MAY_READ);
3894 + error = permission(inode, MAY_READ);
3899 + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
3904 +ext3_xattr_user_set(struct inode *inode, const char *name,
3905 + const void *value, size_t size, int flags)
3910 + if (strcmp(name, "") == 0)
3912 + if (!test_opt(inode->i_sb, XATTR_USER))
3914 + if ( !S_ISREG(inode->i_mode) &&
3915 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
3917 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3918 + error = ext3_permission_locked(inode, MAY_WRITE);
3920 + error = permission(inode, MAY_WRITE);
3925 + handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
3926 + if (IS_ERR(handle))
3927 + return PTR_ERR(handle);
3928 + error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
3929 + value, size, flags);
3930 + ext3_journal_stop(handle, inode);
3935 +struct ext3_xattr_handler ext3_xattr_user_handler = {
3936 + prefix: XATTR_USER_PREFIX,
3937 + list: ext3_xattr_user_list,
3938 + get: ext3_xattr_user_get,
3939 + set: ext3_xattr_user_set,
3943 +init_ext3_xattr_user(void)
3945 + return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
3946 + &ext3_xattr_user_handler);
3950 +exit_ext3_xattr_user(void)
3952 + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
3953 + &ext3_xattr_user_handler);
3955 --- kernel-2.4.20-6chaos_18_7/fs/jfs/jfs_xattr.h~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:11.000000000 -0700
3956 +++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/jfs_xattr.h 2003-07-12 15:34:44.000000000 -0600
3957 @@ -52,8 +52,10 @@ struct jfs_ea_list {
3958 #define END_EALIST(ealist) \
3959 ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
3961 -extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
3962 -extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
3963 +extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
3965 +extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
3967 extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
3968 extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
3969 extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
3970 --- kernel-2.4.20-6chaos_18_7/fs/jfs/xattr.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:11.000000000 -0700
3971 +++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/xattr.c 2003-07-12 15:34:44.000000000 -0600
3972 @@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s
3975 static int can_set_xattr(struct inode *inode, const char *name,
3976 - void *value, size_t value_len)
3977 + const void *value, size_t value_len)
3979 if (IS_RDONLY(inode))
3981 @@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i
3982 return permission(inode, MAY_WRITE);
3985 -int __jfs_setxattr(struct inode *inode, const char *name, void *value,
3986 +int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
3987 size_t value_len, int flags)
3989 struct jfs_ea_list *ealist;
3990 @@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode,
3994 -int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
3995 +int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
3996 size_t value_len, int flags)
3998 if (value == NULL) { /* empty EA, do not remove */
3999 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
4000 +++ kernel-2.4.20-6chaos_18_7-braam/fs/mbcache.c 2003-07-12 15:34:44.000000000 -0600
4003 + * linux/fs/mbcache.c
4004 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4008 + * Filesystem Meta Information Block Cache (mbcache)
4010 + * The mbcache caches blocks of block devices that need to be located
4011 + * by their device/block number, as well as by other criteria (such
4012 + * as the block's contents).
4014 + * There can only be one cache entry in a cache per device and block number.
4015 + * Additional indexes need not be unique in this sense. The number of
4016 + * additional indexes (=other criteria) can be hardwired at compile time
4017 + * or specified at cache create time.
4019 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
4020 + * in the cache. A valid entry is in the main hash tables of the cache,
4021 + * and may also be in the lru list. An invalid entry is not in any hashes
4024 + * A valid cache entry is only in the lru list if no handles refer to it.
4025 + * Invalid cache entries will be freed when the last handle to the cache
4026 + * entry is released. Entries that cannot be freed immediately are put
4027 + * back on the lru list.
4030 +#include <linux/kernel.h>
4031 +#include <linux/module.h>
4033 +#include <linux/fs.h>
4034 +#include <linux/slab.h>
4035 +#include <linux/sched.h>
4036 +#include <linux/cache_def.h>
4037 +#include <linux/version.h>
4038 +#include <linux/init.h>
4039 +#include <linux/mbcache.h>
4042 +#ifdef MB_CACHE_DEBUG
4043 +# define mb_debug(f...) do { \
4044 + printk(KERN_DEBUG f); \
4047 +#define mb_assert(c) do { if (!(c)) \
4048 + printk(KERN_ERR "assertion " #c " failed\n"); \
4051 +# define mb_debug(f...) do { } while(0)
4052 +# define mb_assert(c) do { } while(0)
4054 +#define mb_error(f...) do { \
4055 + printk(KERN_ERR f); \
4059 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
4060 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
4061 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4062 +MODULE_LICENSE("GPL");
4065 +EXPORT_SYMBOL(mb_cache_create);
4066 +EXPORT_SYMBOL(mb_cache_shrink);
4067 +EXPORT_SYMBOL(mb_cache_destroy);
4068 +EXPORT_SYMBOL(mb_cache_entry_alloc);
4069 +EXPORT_SYMBOL(mb_cache_entry_insert);
4070 +EXPORT_SYMBOL(mb_cache_entry_release);
4071 +EXPORT_SYMBOL(mb_cache_entry_takeout);
4072 +EXPORT_SYMBOL(mb_cache_entry_free);
4073 +EXPORT_SYMBOL(mb_cache_entry_dup);
4074 +EXPORT_SYMBOL(mb_cache_entry_get);
4075 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4076 +EXPORT_SYMBOL(mb_cache_entry_find_first);
4077 +EXPORT_SYMBOL(mb_cache_entry_find_next);
4082 + * Global data: list of all mbcache's, lru list, and a spinlock for
4083 + * accessing cache data structures on SMP machines. The lru list is
4084 + * global across all mbcaches.
4087 +static LIST_HEAD(mb_cache_list);
4088 +static LIST_HEAD(mb_cache_lru_list);
4089 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
4092 +mb_cache_indexes(struct mb_cache *cache)
4094 +#ifdef MB_CACHE_INDEXES_COUNT
4095 + return MB_CACHE_INDEXES_COUNT;
4097 + return cache->c_indexes_count;
4102 + * What the mbcache registers as to get shrunk dynamically.
4106 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
4108 +static struct cache_definition mb_cache_definition = {
4110 + mb_cache_memory_pressure
4115 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4117 + return !list_empty(&ce->e_block_list);
4122 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4126 + if (__mb_cache_entry_is_hashed(ce)) {
4127 + list_del_init(&ce->e_block_list);
4128 + for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4129 + list_del(&ce->e_indexes[n].o_list);
4135 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4137 + struct mb_cache *cache = ce->e_cache;
4139 + mb_assert(atomic_read(&ce->e_used) == 0);
4140 + if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4141 + /* free failed -- put back on the lru list
4142 + for freeing later. */
4143 + spin_lock(&mb_cache_spinlock);
4144 + list_add(&ce->e_lru_list, &mb_cache_lru_list);
4145 + spin_unlock(&mb_cache_spinlock);
4147 + kmem_cache_free(cache->c_entry_cache, ce);
4148 + atomic_dec(&cache->c_entry_count);
4154 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4156 + if (atomic_dec_and_test(&ce->e_used)) {
4157 + if (__mb_cache_entry_is_hashed(ce))
4158 + list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4160 + spin_unlock(&mb_cache_spinlock);
4161 + __mb_cache_entry_forget(ce, GFP_KERNEL);
4165 + spin_unlock(&mb_cache_spinlock);
4170 + * mb_cache_memory_pressure() memory pressure callback
4172 + * This function is called by the kernel memory management when memory
4175 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4176 + * @gfp_mask: (ignored)
4179 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4181 + LIST_HEAD(free_list);
4182 + struct list_head *l, *ltmp;
4185 + spin_lock(&mb_cache_spinlock);
4186 + list_for_each(l, &mb_cache_list) {
4187 + struct mb_cache *cache =
4188 + list_entry(l, struct mb_cache, c_cache_list);
4189 + mb_debug("cache %s (%d)", cache->c_name,
4190 + atomic_read(&cache->c_entry_count));
4191 + count += atomic_read(&cache->c_entry_count);
4193 + mb_debug("trying to free %d of %d entries",
4194 + count / (priority ? priority : 1), count);
4196 + count /= priority;
4197 + while (count-- && !list_empty(&mb_cache_lru_list)) {
4198 + struct mb_cache_entry *ce =
4199 + list_entry(mb_cache_lru_list.next,
4200 + struct mb_cache_entry, e_lru_list);
4201 + list_del(&ce->e_lru_list);
4202 + __mb_cache_entry_unhash(ce);
4203 + list_add_tail(&ce->e_lru_list, &free_list);
4205 + spin_unlock(&mb_cache_spinlock);
4206 + list_for_each_safe(l, ltmp, &free_list) {
4207 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4208 + e_lru_list), gfp_mask);
4214 + * mb_cache_create() create a new cache
4216 + * All entries in one cache are equal size. Cache entries may be from
4217 + * multiple devices. If this is the first mbcache created, registers
4218 + * the cache with kernel memory management. Returns NULL if no more
4219 + * memory was available.
4221 + * @name: name of the cache (informal)
4222 + * @cache_op: contains the callback called when freeing a cache entry
4223 + * @entry_size: The size of a cache entry, including
4224 + * struct mb_cache_entry
4225 + * @indexes_count: number of additional indexes in the cache. Must equal
4226 + * MB_CACHE_INDEXES_COUNT if the number of indexes is
4228 + * @bucket_count: number of hash buckets
4231 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4232 + size_t entry_size, int indexes_count, int bucket_count)
4235 + struct mb_cache *cache = NULL;
4237 + if(entry_size < sizeof(struct mb_cache_entry) +
4238 + indexes_count * sizeof(struct mb_cache_entry_index))
4241 + MOD_INC_USE_COUNT;
4242 + cache = kmalloc(sizeof(struct mb_cache) +
4243 + indexes_count * sizeof(struct list_head), GFP_KERNEL);
4246 + cache->c_name = name;
4247 + cache->c_op.free = NULL;
4249 + cache->c_op.free = cache_op->free;
4250 + atomic_set(&cache->c_entry_count, 0);
4251 + cache->c_bucket_count = bucket_count;
4252 +#ifdef MB_CACHE_INDEXES_COUNT
4253 + mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4255 + cache->c_indexes_count = indexes_count;
4257 + cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4259 + if (!cache->c_block_hash)
4261 + for (n=0; n<bucket_count; n++)
4262 + INIT_LIST_HEAD(&cache->c_block_hash[n]);
4263 + for (m=0; m<indexes_count; m++) {
4264 + cache->c_indexes_hash[m] = kmalloc(bucket_count *
4265 + sizeof(struct list_head),
4267 + if (!cache->c_indexes_hash[m])
4269 + for (n=0; n<bucket_count; n++)
4270 + INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4272 + cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4273 + 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4274 + if (!cache->c_entry_cache)
4277 + spin_lock(&mb_cache_spinlock);
4278 + list_add(&cache->c_cache_list, &mb_cache_list);
4279 + spin_unlock(&mb_cache_spinlock);
4285 + kfree(cache->c_indexes_hash[m]);
4286 + if (cache->c_block_hash)
4287 + kfree(cache->c_block_hash);
4290 + MOD_DEC_USE_COUNT;
4296 + * mb_cache_shrink()
4298 + * Removes all cache entires of a device from the cache. All cache entries
4299 + * currently in use cannot be freed, and thus remain in the cache.
4301 + * @cache: which cache to shrink
4302 + * @dev: which device's cache entries to shrink
4305 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4307 + LIST_HEAD(free_list);
4308 + struct list_head *l, *ltmp;
4310 + spin_lock(&mb_cache_spinlock);
4311 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4312 + struct mb_cache_entry *ce =
4313 + list_entry(l, struct mb_cache_entry, e_lru_list);
4314 + if (ce->e_dev == dev) {
4315 + list_del(&ce->e_lru_list);
4316 + list_add_tail(&ce->e_lru_list, &free_list);
4317 + __mb_cache_entry_unhash(ce);
4320 + spin_unlock(&mb_cache_spinlock);
4321 + list_for_each_safe(l, ltmp, &free_list) {
4322 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4323 + e_lru_list), GFP_KERNEL);
4329 + * mb_cache_destroy()
4331 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4332 + * and then destroys it. If this was the last mbcache, un-registers the
4333 + * mbcache from kernel memory management.
4336 +mb_cache_destroy(struct mb_cache *cache)
4338 + LIST_HEAD(free_list);
4339 + struct list_head *l, *ltmp;
4342 + spin_lock(&mb_cache_spinlock);
4343 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4344 + struct mb_cache_entry *ce =
4345 + list_entry(l, struct mb_cache_entry, e_lru_list);
4346 + if (ce->e_cache == cache) {
4347 + list_del(&ce->e_lru_list);
4348 + list_add_tail(&ce->e_lru_list, &free_list);
4349 + __mb_cache_entry_unhash(ce);
4352 + list_del(&cache->c_cache_list);
4353 + spin_unlock(&mb_cache_spinlock);
4354 + list_for_each_safe(l, ltmp, &free_list) {
4355 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4356 + e_lru_list), GFP_KERNEL);
4359 + if (atomic_read(&cache->c_entry_count) > 0) {
4360 + mb_error("cache %s: %d orphaned entries",
4362 + atomic_read(&cache->c_entry_count));
4365 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4366 + /* We don't have kmem_cache_destroy() in 2.2.x */
4367 + kmem_cache_shrink(cache->c_entry_cache);
4369 + kmem_cache_destroy(cache->c_entry_cache);
4371 + for (n=0; n < mb_cache_indexes(cache); n++)
4372 + kfree(cache->c_indexes_hash[n]);
4373 + kfree(cache->c_block_hash);
4376 + MOD_DEC_USE_COUNT;
4381 + * mb_cache_entry_alloc()
4383 + * Allocates a new cache entry. The new entry will not be valid initially,
4384 + * and thus cannot be looked up yet. It should be filled with data, and
4385 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4386 + * if no more memory was available.
4388 +struct mb_cache_entry *
4389 +mb_cache_entry_alloc(struct mb_cache *cache)
4391 + struct mb_cache_entry *ce;
4393 + atomic_inc(&cache->c_entry_count);
4394 + ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4396 + INIT_LIST_HEAD(&ce->e_lru_list);
4397 + INIT_LIST_HEAD(&ce->e_block_list);
4398 + ce->e_cache = cache;
4399 + atomic_set(&ce->e_used, 1);
4406 + * mb_cache_entry_insert()
4408 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4409 + * the cache. After this, the cache entry can be looked up, but is not yet
4410 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4411 + * success, or -EBUSY if a cache entry for that device + inode exists
4412 + * already (this may happen after a failed lookup, if another process has
4413 + * inserted the same cache entry in the meantime).
4415 + * @dev: device the cache entry belongs to
4416 + * @block: block number
4417 + * @keys: array of additional keys. There must be indexes_count entries
4418 + * in the array (as specified when creating the cache).
4421 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4422 + unsigned long block, unsigned int keys[])
4424 + struct mb_cache *cache = ce->e_cache;
4425 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4426 + struct list_head *l;
4427 + int error = -EBUSY, n;
4429 + spin_lock(&mb_cache_spinlock);
4430 + list_for_each(l, &cache->c_block_hash[bucket]) {
4431 + struct mb_cache_entry *ce =
4432 + list_entry(l, struct mb_cache_entry, e_block_list);
4433 + if (ce->e_dev == dev && ce->e_block == block)
4436 + __mb_cache_entry_unhash(ce);
4438 + ce->e_block = block;
4439 + list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4440 + for (n=0; n<mb_cache_indexes(cache); n++) {
4441 + ce->e_indexes[n].o_key = keys[n];
4442 + bucket = keys[n] % cache->c_bucket_count;
4443 + list_add(&ce->e_indexes[n].o_list,
4444 + &cache->c_indexes_hash[n][bucket]);
4447 + spin_unlock(&mb_cache_spinlock);
4453 + * mb_cache_entry_release()
4455 + * Release a handle to a cache entry. When the last handle to a cache entry
4456 + * is released it is either freed (if it is invalid) or otherwise inserted
4457 + * in to the lru list.
4460 +mb_cache_entry_release(struct mb_cache_entry *ce)
4462 + spin_lock(&mb_cache_spinlock);
4463 + __mb_cache_entry_release_unlock(ce);
4468 + * mb_cache_entry_takeout()
4470 + * Take a cache entry out of the cache, making it invalid. The entry can later
4471 + * be re-inserted using mb_cache_entry_insert(), or released using
4472 + * mb_cache_entry_release().
4475 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4477 + spin_lock(&mb_cache_spinlock);
4478 + mb_assert(list_empty(&ce->e_lru_list));
4479 + __mb_cache_entry_unhash(ce);
4480 + spin_unlock(&mb_cache_spinlock);
4485 + * mb_cache_entry_free()
4487 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4488 + * mb_cache_entry_release().
4491 +mb_cache_entry_free(struct mb_cache_entry *ce)
4493 + spin_lock(&mb_cache_spinlock);
4494 + mb_assert(list_empty(&ce->e_lru_list));
4495 + __mb_cache_entry_unhash(ce);
4496 + __mb_cache_entry_release_unlock(ce);
4501 + * mb_cache_entry_dup()
4503 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4504 + * itself). After the call, both the old and the new handle must be released.
4506 +struct mb_cache_entry *
4507 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4509 + atomic_inc(&ce->e_used);
4515 + * mb_cache_entry_get()
4517 + * Get a cache entry by device / block number. (There can only be one entry
4518 + * in the cache per device and block.) Returns NULL if no such cache entry
4521 +struct mb_cache_entry *
4522 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4524 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4525 + struct list_head *l;
4526 + struct mb_cache_entry *ce;
4528 + spin_lock(&mb_cache_spinlock);
4529 + list_for_each(l, &cache->c_block_hash[bucket]) {
4530 + ce = list_entry(l, struct mb_cache_entry, e_block_list);
4531 + if (ce->e_dev == dev && ce->e_block == block) {
4532 + if (!list_empty(&ce->e_lru_list))
4533 + list_del_init(&ce->e_lru_list);
4534 + atomic_inc(&ce->e_used);
4541 + spin_unlock(&mb_cache_spinlock);
4545 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4547 +static struct mb_cache_entry *
4548 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4549 + int index, kdev_t dev, unsigned int key)
4551 + while (l != head) {
4552 + struct mb_cache_entry *ce =
4553 + list_entry(l, struct mb_cache_entry,
4554 + e_indexes[index].o_list);
4555 + if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4556 + if (!list_empty(&ce->e_lru_list))
4557 + list_del_init(&ce->e_lru_list);
4558 + atomic_inc(&ce->e_used);
4568 + * mb_cache_entry_find_first()
4570 + * Find the first cache entry on a given device with a certain key in
4571 + * an additional index. Additonal matches can be found with
4572 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4574 + * @cache: the cache to search
4575 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4576 + * @dev: the device the cache entry should belong to
4577 + * @key: the key in the index
4579 +struct mb_cache_entry *
4580 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4583 + unsigned int bucket = key % cache->c_bucket_count;
4584 + struct list_head *l;
4585 + struct mb_cache_entry *ce;
4587 + mb_assert(index < mb_cache_indexes(cache));
4588 + spin_lock(&mb_cache_spinlock);
4589 + l = cache->c_indexes_hash[index][bucket].next;
4590 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4592 + spin_unlock(&mb_cache_spinlock);
4598 + * mb_cache_entry_find_next()
4600 + * Find the next cache entry on a given device with a certain key in an
4601 + * additional index. Returns NULL if no match could be found. The previous
4602 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4603 + * be called like this:
4605 + * entry = mb_cache_entry_find_first();
4608 + * entry = mb_cache_entry_find_next(entry, ...);
4611 + * @prev: The previous match
4612 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4613 + * @dev: the device the cache entry should belong to
4614 + * @key: the key in the index
4616 +struct mb_cache_entry *
4617 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4620 + struct mb_cache *cache = prev->e_cache;
4621 + unsigned int bucket = key % cache->c_bucket_count;
4622 + struct list_head *l;
4623 + struct mb_cache_entry *ce;
4625 + mb_assert(index < mb_cache_indexes(cache));
4626 + spin_lock(&mb_cache_spinlock);
4627 + l = prev->e_indexes[index].o_list.next;
4628 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4630 + __mb_cache_entry_release_unlock(prev);
4634 +#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4636 +static int __init init_mbcache(void)
4638 + register_cache(&mb_cache_definition);
4642 +static void __exit exit_mbcache(void)
4644 + unregister_cache(&mb_cache_definition);
4647 +module_init(init_mbcache)
4648 +module_exit(exit_mbcache)
4650 --- kernel-2.4.20-6chaos_18_7/include/asm-arm/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:42.000000000 -0600
4651 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-arm/unistd.h 2003-07-12 15:34:44.000000000 -0600
4653 #define __NR_security (__NR_SYSCALL_BASE+223)
4654 #define __NR_gettid (__NR_SYSCALL_BASE+224)
4655 #define __NR_readahead (__NR_SYSCALL_BASE+225)
4656 -#if 0 /* allocated in 2.5 */
4657 #define __NR_setxattr (__NR_SYSCALL_BASE+226)
4658 #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
4659 #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
4661 #define __NR_removexattr (__NR_SYSCALL_BASE+235)
4662 #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
4663 #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
4665 #define __NR_tkill (__NR_SYSCALL_BASE+238)
4667 * Please check 2.5 _before_ adding calls here,
4668 --- kernel-2.4.20-6chaos_18_7/include/asm-ppc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:42.000000000 -0600
4669 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-ppc64/unistd.h 2003-07-12 15:34:44.000000000 -0600
4671 #define __NR_gettid 207
4672 #if 0 /* Reserved syscalls */
4673 #define __NR_tkill 208
4675 #define __NR_setxattr 209
4676 #define __NR_lsetxattr 210
4677 #define __NR_fsetxattr 211
4679 #define __NR_removexattr 218
4680 #define __NR_lremovexattr 219
4681 #define __NR_fremovexattr 220
4682 +#if 0 /* Reserved syscalls */
4683 #define __NR_futex 221
4686 --- kernel-2.4.20-6chaos_18_7/include/asm-s390/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:44.000000000 -0600
4687 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390/unistd.h 2003-07-12 15:34:44.000000000 -0600
4688 @@ -212,9 +212,18 @@
4689 #define __NR_madvise 219
4690 #define __NR_getdents64 220
4691 #define __NR_fcntl64 221
4693 - * Numbers 224-235 are reserved for posix acl
4695 +#define __NR_setxattr 224
4696 +#define __NR_lsetxattr 225
4697 +#define __NR_fsetxattr 226
4698 +#define __NR_getxattr 227
4699 +#define __NR_lgetxattr 228
4700 +#define __NR_fgetxattr 229
4701 +#define __NR_listxattr 230
4702 +#define __NR_llistxattr 231
4703 +#define __NR_flistxattr 232
4704 +#define __NR_removexattr 233
4705 +#define __NR_lremovexattr 234
4706 +#define __NR_fremovexattr 235
4707 #define __NR_gettid 236
4708 #define __NR_tkill 237
4710 --- kernel-2.4.20-6chaos_18_7/include/asm-s390x/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:45.000000000 -0600
4711 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390x/unistd.h 2003-07-12 15:34:44.000000000 -0600
4712 @@ -180,9 +180,18 @@
4713 #define __NR_pivot_root 217
4714 #define __NR_mincore 218
4715 #define __NR_madvise 219
4717 - * Numbers 224-235 are reserved for posix acl
4719 +#define __NR_setxattr 224
4720 +#define __NR_lsetxattr 225
4721 +#define __NR_fsetxattr 226
4722 +#define __NR_getxattr 227
4723 +#define __NR_lgetxattr 228
4724 +#define __NR_fgetxattr 229
4725 +#define __NR_listxattr 230
4726 +#define __NR_llistxattr 231
4727 +#define __NR_flistxattr 232
4728 +#define __NR_removexattr 233
4729 +#define __NR_lremovexattr 234
4730 +#define __NR_fremovexattr 235
4731 #define __NR_gettid 236
4732 #define __NR_tkill 237
4734 --- kernel-2.4.20-6chaos_18_7/include/asm-sparc/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:46.000000000 -0600
4735 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc/unistd.h 2003-07-12 15:34:44.000000000 -0600
4736 @@ -184,24 +184,24 @@
4737 /* #define __NR_exportfs 166 SunOS Specific */
4738 #define __NR_mount 167 /* Common */
4739 #define __NR_ustat 168 /* Common */
4740 -/* #define __NR_semsys 169 SunOS Specific */
4741 -/* #define __NR_msgsys 170 SunOS Specific */
4742 -/* #define __NR_shmsys 171 SunOS Specific */
4743 -/* #define __NR_auditsys 172 SunOS Specific */
4744 -/* #define __NR_rfssys 173 SunOS Specific */
4745 +#define __NR_setxattr 169 /* SunOS: semsys */
4746 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4747 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4748 +#define __NR_getxattr 172 /* SunOS: auditsys */
4749 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4750 #define __NR_getdents 174 /* Common */
4751 #define __NR_setsid 175 /* Common */
4752 #define __NR_fchdir 176 /* Common */
4753 -/* #define __NR_fchroot 177 SunOS Specific */
4754 -/* #define __NR_vpixsys 178 SunOS Specific */
4755 -/* #define __NR_aioread 179 SunOS Specific */
4756 -/* #define __NR_aiowrite 180 SunOS Specific */
4757 -/* #define __NR_aiowait 181 SunOS Specific */
4758 -/* #define __NR_aiocancel 182 SunOS Specific */
4759 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4760 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4761 +#define __NR_llistxattr 179 /* SunOS: aioread */
4762 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4763 +#define __NR_removexattr 181 /* SunOS: aiowait */
4764 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4765 #define __NR_sigpending 183 /* Common */
4766 #define __NR_query_module 184 /* Linux Specific */
4767 #define __NR_setpgid 185 /* Common */
4768 -/* #define __NR_pathconf 186 SunOS Specific */
4769 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4770 #define __NR_tkill 187 /* SunOS: fpathconf */
4771 /* #define __NR_sysconf 188 SunOS Specific */
4772 #define __NR_uname 189 /* Linux Specific */
4773 --- kernel-2.4.20-6chaos_18_7/include/asm-sparc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:48.000000000 -0600
4774 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc64/unistd.h 2003-07-12 15:34:44.000000000 -0600
4775 @@ -184,24 +184,24 @@
4776 /* #define __NR_exportfs 166 SunOS Specific */
4777 #define __NR_mount 167 /* Common */
4778 #define __NR_ustat 168 /* Common */
4779 -/* #define __NR_semsys 169 SunOS Specific */
4780 -/* #define __NR_msgsys 170 SunOS Specific */
4781 -/* #define __NR_shmsys 171 SunOS Specific */
4782 -/* #define __NR_auditsys 172 SunOS Specific */
4783 -/* #define __NR_rfssys 173 SunOS Specific */
4784 +#define __NR_setxattr 169 /* SunOS: semsys */
4785 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4786 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4787 +#define __NR_getxattr 172 /* SunOS: auditsys */
4788 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4789 #define __NR_getdents 174 /* Common */
4790 #define __NR_setsid 175 /* Common */
4791 #define __NR_fchdir 176 /* Common */
4792 -/* #define __NR_fchroot 177 SunOS Specific */
4793 -/* #define __NR_vpixsys 178 SunOS Specific */
4794 -/* #define __NR_aioread 179 SunOS Specific */
4795 -/* #define __NR_aiowrite 180 SunOS Specific */
4796 -/* #define __NR_aiowait 181 SunOS Specific */
4797 -/* #define __NR_aiocancel 182 SunOS Specific */
4798 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4799 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4800 +#define __NR_llistxattr 179 /* SunOS: aioread */
4801 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4802 +#define __NR_removexattr 181 /* SunOS: aiowait */
4803 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4804 #define __NR_sigpending 183 /* Common */
4805 #define __NR_query_module 184 /* Linux Specific */
4806 #define __NR_setpgid 185 /* Common */
4807 -/* #define __NR_pathconf 186 SunOS Specific */
4808 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4809 #define __NR_tkill 187 /* SunOS: fpathconf */
4810 /* #define __NR_sysconf 188 SunOS Specific */
4811 #define __NR_uname 189 /* Linux Specific */
4812 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
4813 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/cache_def.h 2003-07-12 15:34:44.000000000 -0600
4816 + * linux/cache_def.h
4817 + * Handling of caches defined in drivers, filesystems, ...
4819 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
4822 +struct cache_definition {
4824 + void (*shrink)(int, unsigned int);
4825 + struct list_head link;
4828 +extern void register_cache(struct cache_definition *);
4829 +extern void unregister_cache(struct cache_definition *);
4830 --- kernel-2.4.20-6chaos_18_7/include/linux/errno.h~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:15:06.000000000 -0600
4831 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/errno.h 2003-07-12 15:34:44.000000000 -0600
4836 +/* Defined for extended attributes */
4837 +#define ENOATTR ENODATA /* No such attribute */
4838 +#define ENOTSUP EOPNOTSUPP /* Operation not supported */
4841 --- kernel-2.4.20-6chaos_18_7/include/linux/ext2_fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-06-24 11:31:16.000000000 -0600
4842 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_fs.h 2003-07-12 15:34:44.000000000 -0600
4845 #define EXT2_BAD_INO 1 /* Bad blocks inode */
4846 #define EXT2_ROOT_INO 2 /* Root inode */
4847 -#define EXT2_ACL_IDX_INO 3 /* ACL inode */
4848 -#define EXT2_ACL_DATA_INO 4 /* ACL inode */
4849 #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
4850 #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
4854 # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
4856 -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
4857 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
4859 # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
4860 @@ -121,28 +118,6 @@
4866 -struct ext2_acl_header /* Header of Access Control Lists */
4869 - __u32 aclh_file_count;
4870 - __u32 aclh_acle_count;
4871 - __u32 aclh_first_acle;
4874 -struct ext2_acl_entry /* Access Control List Entry */
4877 - __u16 acle_perms; /* Access permissions */
4878 - __u16 acle_type; /* Type of entry */
4879 - __u16 acle_tag; /* User or group identity */
4881 - __u32 acle_next; /* Pointer on next entry for the */
4882 - /* same inode or on next free entry */
4886 * Structure of a blocks group descriptor
4888 struct ext2_group_desc
4889 @@ -314,6 +289,7 @@ struct ext2_inode {
4890 #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
4891 #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
4892 #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
4893 +#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
4895 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
4896 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
4897 @@ -397,6 +373,7 @@ struct ext2_super_block {
4900 #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
4901 +#define EXT2_I(inode) (&((inode)->u.ext2_i))
4903 /* Assume that user mode programs are passing in an ext2fs superblock, not
4904 * a kernel struct super_block. This will allow us to call the feature-test
4905 @@ -466,7 +443,7 @@ struct ext2_super_block {
4906 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
4907 #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
4909 -#define EXT2_FEATURE_COMPAT_SUPP 0
4910 +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
4911 #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
4912 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
4913 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
4914 @@ -624,8 +601,10 @@ extern struct address_space_operations e
4917 extern struct inode_operations ext2_dir_inode_operations;
4918 +extern struct inode_operations ext2_special_inode_operations;
4921 +extern struct inode_operations ext2_symlink_inode_operations;
4922 extern struct inode_operations ext2_fast_symlink_inode_operations;
4924 #endif /* __KERNEL__ */
4925 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
4926 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_xattr.h 2003-07-12 15:34:44.000000000 -0600
4929 + File: linux/ext2_xattr.h
4931 + On-disk format of extended attributes for the ext2 filesystem.
4933 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4936 +#include <linux/config.h>
4937 +#include <linux/init.h>
4938 +#include <linux/xattr.h>
4940 +/* Magic value in attribute blocks */
4941 +#define EXT2_XATTR_MAGIC 0xEA020000
4943 +/* Maximum number of references to one attribute block */
4944 +#define EXT2_XATTR_REFCOUNT_MAX 1024
4947 +#define EXT2_XATTR_INDEX_MAX 10
4948 +#define EXT2_XATTR_INDEX_USER 1
4949 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
4950 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
4952 +struct ext2_xattr_header {
4953 + __u32 h_magic; /* magic number for identification */
4954 + __u32 h_refcount; /* reference count */
4955 + __u32 h_blocks; /* number of disk blocks used */
4956 + __u32 h_hash; /* hash value of all attributes */
4957 + __u32 h_reserved[4]; /* zero right now */
4960 +struct ext2_xattr_entry {
4961 + __u8 e_name_len; /* length of name */
4962 + __u8 e_name_index; /* attribute name index */
4963 + __u16 e_value_offs; /* offset in disk block of value */
4964 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
4965 + __u32 e_value_size; /* size of attribute value */
4966 + __u32 e_hash; /* hash value of name and value */
4967 + char e_name[0]; /* attribute name */
4970 +#define EXT2_XATTR_PAD_BITS 2
4971 +#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
4972 +#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
4973 +#define EXT2_XATTR_LEN(name_len) \
4974 + (((name_len) + EXT2_XATTR_ROUND + \
4975 + sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
4976 +#define EXT2_XATTR_NEXT(entry) \
4977 + ( (struct ext2_xattr_entry *)( \
4978 + (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
4979 +#define EXT2_XATTR_SIZE(size) \
4980 + (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
4984 +# ifdef CONFIG_EXT2_FS_XATTR
4986 +struct ext2_xattr_handler {
4988 + size_t (*list)(char *list, struct inode *inode, const char *name,
4990 + int (*get)(struct inode *inode, const char *name, void *buffer,
4992 + int (*set)(struct inode *inode, const char *name, const void *buffer,
4993 + size_t size, int flags);
4996 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
4997 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
4999 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
5000 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
5001 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
5002 +extern int ext2_removexattr(struct dentry *, const char *);
5004 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
5005 +extern int ext2_xattr_list(struct inode *, char *, size_t);
5006 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
5008 +extern void ext2_xattr_delete_inode(struct inode *);
5009 +extern void ext2_xattr_put_super(struct super_block *);
5011 +extern int init_ext2_xattr(void) __init;
5012 +extern void exit_ext2_xattr(void);
5014 +# else /* CONFIG_EXT2_FS_XATTR */
5015 +# define ext2_setxattr NULL
5016 +# define ext2_getxattr NULL
5017 +# define ext2_listxattr NULL
5018 +# define ext2_removexattr NULL
5021 +ext2_xattr_get(struct inode *inode, int name_index,
5022 + const char *name, void *buffer, size_t size)
5028 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
5034 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
5035 + const void *value, size_t size, int flags)
5041 +ext2_xattr_delete_inode(struct inode *inode)
5046 +ext2_xattr_put_super(struct super_block *sb)
5051 +init_ext2_xattr(void)
5057 +exit_ext2_xattr(void)
5061 +# endif /* CONFIG_EXT2_FS_XATTR */
5063 +# ifdef CONFIG_EXT2_FS_XATTR_USER
5065 +extern int init_ext2_xattr_user(void) __init;
5066 +extern void exit_ext2_xattr_user(void);
5068 +# else /* CONFIG_EXT2_FS_XATTR_USER */
5071 +init_ext2_xattr_user(void)
5077 +exit_ext2_xattr_user(void)
5081 +# endif /* CONFIG_EXT2_FS_XATTR_USER */
5083 +#endif /* __KERNEL__ */
5085 --- kernel-2.4.20-6chaos_18_7/include/linux/ext3_fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:41.000000000 -0600
5086 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_fs.h 2003-07-12 15:34:44.000000000 -0600
5089 #define EXT3_BAD_INO 1 /* Bad blocks inode */
5090 #define EXT3_ROOT_INO 2 /* Root inode */
5091 -#define EXT3_ACL_IDX_INO 3 /* ACL inode */
5092 -#define EXT3_ACL_DATA_INO 4 /* ACL inode */
5093 #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
5094 #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
5095 #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
5098 # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5100 -#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
5101 #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
5103 # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5104 @@ -129,28 +126,6 @@
5110 -struct ext3_acl_header /* Header of Access Control Lists */
5113 - __u32 aclh_file_count;
5114 - __u32 aclh_acle_count;
5115 - __u32 aclh_first_acle;
5118 -struct ext3_acl_entry /* Access Control List Entry */
5121 - __u16 acle_perms; /* Access permissions */
5122 - __u16 acle_type; /* Type of entry */
5123 - __u16 acle_tag; /* User or group identity */
5125 - __u32 acle_next; /* Pointer on next entry for the */
5126 - /* same inode or on next free entry */
5130 * Structure of a blocks group descriptor
5132 struct ext3_group_desc
5133 @@ -344,6 +319,7 @@ struct ext3_inode {
5134 #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
5135 #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
5136 #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
5137 +#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5139 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
5140 #ifndef _LINUX_EXT2_FS_H
5141 @@ -521,7 +497,7 @@ struct ext3_super_block {
5142 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
5143 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
5145 -#define EXT3_FEATURE_COMPAT_SUPP 0
5146 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5147 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
5148 EXT3_FEATURE_INCOMPAT_RECOVER)
5149 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5150 @@ -704,6 +680,7 @@ extern void ext3_check_inodes_bitmap (st
5151 extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
5154 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
5155 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
5156 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
5158 @@ -773,8 +750,10 @@ extern struct address_space_operations e
5161 extern struct inode_operations ext3_dir_inode_operations;
5162 +extern struct inode_operations ext3_special_inode_operations;
5165 +extern struct inode_operations ext3_symlink_inode_operations;
5166 extern struct inode_operations ext3_fast_symlink_inode_operations;
5169 --- kernel-2.4.20-6chaos_18_7/include/linux/ext3_jbd.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
5170 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_jbd.h 2003-07-12 15:34:44.000000000 -0600
5173 #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U
5175 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5176 + * and two group and summaries. */
5178 +#define EXT3_XATTR_TRANS_BLOCKS 8
5180 /* Define the minimum size for a transaction which modifies data. This
5181 * needs to take into account the fact that we may end up modifying two
5182 * quota files too (one for the group, one for the user quota). The
5183 * superblock only gets updated once, of course, so don't bother
5184 * counting that again for the quota updates. */
5186 -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5187 +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5188 + EXT3_XATTR_TRANS_BLOCKS - 2)
5190 extern int ext3_writepage_trans_blocks(struct inode *inode);
5192 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
5193 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_xattr.h 2003-07-12 15:34:44.000000000 -0600
5196 + File: linux/ext3_xattr.h
5198 + On-disk format of extended attributes for the ext3 filesystem.
5200 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5203 +#include <linux/config.h>
5204 +#include <linux/init.h>
5205 +#include <linux/xattr.h>
5207 +/* Magic value in attribute blocks */
5208 +#define EXT3_XATTR_MAGIC 0xEA020000
5210 +/* Maximum number of references to one attribute block */
5211 +#define EXT3_XATTR_REFCOUNT_MAX 1024
5214 +#define EXT3_XATTR_INDEX_MAX 10
5215 +#define EXT3_XATTR_INDEX_USER 1
5216 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
5217 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5219 +struct ext3_xattr_header {
5220 + __u32 h_magic; /* magic number for identification */
5221 + __u32 h_refcount; /* reference count */
5222 + __u32 h_blocks; /* number of disk blocks used */
5223 + __u32 h_hash; /* hash value of all attributes */
5224 + __u32 h_reserved[4]; /* zero right now */
5227 +struct ext3_xattr_entry {
5228 + __u8 e_name_len; /* length of name */
5229 + __u8 e_name_index; /* attribute name index */
5230 + __u16 e_value_offs; /* offset in disk block of value */
5231 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5232 + __u32 e_value_size; /* size of attribute value */
5233 + __u32 e_hash; /* hash value of name and value */
5234 + char e_name[0]; /* attribute name */
5237 +#define EXT3_XATTR_PAD_BITS 2
5238 +#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
5239 +#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
5240 +#define EXT3_XATTR_LEN(name_len) \
5241 + (((name_len) + EXT3_XATTR_ROUND + \
5242 + sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5243 +#define EXT3_XATTR_NEXT(entry) \
5244 + ( (struct ext3_xattr_entry *)( \
5245 + (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5246 +#define EXT3_XATTR_SIZE(size) \
5247 + (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5251 +# ifdef CONFIG_EXT3_FS_XATTR
5253 +struct ext3_xattr_handler {
5255 + size_t (*list)(char *list, struct inode *inode, const char *name,
5257 + int (*get)(struct inode *inode, const char *name, void *buffer,
5259 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5260 + size_t size, int flags);
5263 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5264 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5266 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5267 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5268 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5269 +extern int ext3_removexattr(struct dentry *, const char *);
5271 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5272 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5273 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5275 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5276 +extern void ext3_xattr_put_super(struct super_block *);
5278 +extern int init_ext3_xattr(void) __init;
5279 +extern void exit_ext3_xattr(void);
5281 +# else /* CONFIG_EXT3_FS_XATTR */
5282 +# define ext3_setxattr NULL
5283 +# define ext3_getxattr NULL
5284 +# define ext3_listxattr NULL
5285 +# define ext3_removexattr NULL
5288 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5289 + void *buffer, size_t size)
5295 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5301 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5302 + const char *name, const void *value, size_t size, int flags)
5308 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5313 +ext3_xattr_put_super(struct super_block *sb)
5318 +init_ext3_xattr(void)
5324 +exit_ext3_xattr(void)
5328 +# endif /* CONFIG_EXT3_FS_XATTR */
5330 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5332 +extern int init_ext3_xattr_user(void) __init;
5333 +extern void exit_ext3_xattr_user(void);
5335 +# else /* CONFIG_EXT3_FS_XATTR_USER */
5338 +init_ext3_xattr_user(void)
5344 +exit_ext3_xattr_user(void)
5348 +#endif /* CONFIG_EXT3_FS_XATTR_USER */
5350 +#endif /* __KERNEL__ */
5352 --- kernel-2.4.20-6chaos_18_7/include/linux/fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:31:35.000000000 -0600
5353 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/fs.h 2003-07-12 15:34:44.000000000 -0600
5354 @@ -914,7 +914,7 @@ struct inode_operations {
5355 int (*setattr) (struct dentry *, struct iattr *);
5356 int (*setattr_raw) (struct inode *, struct iattr *);
5357 int (*getattr) (struct dentry *, struct iattr *);
5358 - int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
5359 + int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5360 ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5361 ssize_t (*listxattr) (struct dentry *, char *, size_t);
5362 int (*removexattr) (struct dentry *, const char *);
5363 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
5364 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/mbcache.h 2003-07-12 15:34:44.000000000 -0600
5367 + File: linux/mbcache.h
5369 + (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5372 +/* Hardwire the number of additional indexes */
5373 +#define MB_CACHE_INDEXES_COUNT 1
5375 +struct mb_cache_entry;
5377 +struct mb_cache_op {
5378 + int (*free)(struct mb_cache_entry *, int);
5382 + struct list_head c_cache_list;
5383 + const char *c_name;
5384 + struct mb_cache_op c_op;
5385 + atomic_t c_entry_count;
5386 + int c_bucket_count;
5387 +#ifndef MB_CACHE_INDEXES_COUNT
5388 + int c_indexes_count;
5390 + kmem_cache_t *c_entry_cache;
5391 + struct list_head *c_block_hash;
5392 + struct list_head *c_indexes_hash[0];
5395 +struct mb_cache_entry_index {
5396 + struct list_head o_list;
5397 + unsigned int o_key;
5400 +struct mb_cache_entry {
5401 + struct list_head e_lru_list;
5402 + struct mb_cache *e_cache;
5405 + unsigned long e_block;
5406 + struct list_head e_block_list;
5407 + struct mb_cache_entry_index e_indexes[0];
5410 +/* Functions on caches */
5412 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5414 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5415 +void mb_cache_destroy(struct mb_cache *);
5417 +/* Functions on cache entries */
5419 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5420 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5422 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5423 +void mb_cache_entry_release(struct mb_cache_entry *);
5424 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5425 +void mb_cache_entry_free(struct mb_cache_entry *);
5426 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5427 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5429 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5430 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5431 + kdev_t, unsigned int);
5432 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5433 + kdev_t, unsigned int);
5435 --- kernel-2.4.20-6chaos_18_7/kernel/ksyms.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:14:02.000000000 -0600
5436 +++ kernel-2.4.20-6chaos_18_7-braam/kernel/ksyms.c 2003-07-12 15:35:19.000000000 -0600
5438 #define __KERNEL_SYSCALLS__
5439 #include <linux/config.h>
5440 #include <linux/slab.h>
5441 +#include <linux/cache_def.h>
5442 #include <linux/smp.h>
5443 #include <linux/module.h>
5444 #include <linux/blkdev.h>
5445 @@ -106,6 +107,7 @@ EXPORT_SYMBOL(do_brk);
5446 EXPORT_SYMBOL(exit_mm);
5447 EXPORT_SYMBOL(exit_files);
5448 EXPORT_SYMBOL(exit_fs);
5449 +EXPORT_SYMBOL(copy_fs_struct);
5450 EXPORT_SYMBOL(exit_sighand);
5451 EXPORT_SYMBOL_GPL(make_pages_present);
5453 @@ -126,6 +128,8 @@ EXPORT_SYMBOL(kmem_cache_alloc);
5454 EXPORT_SYMBOL(kmem_cache_free);
5455 EXPORT_SYMBOL(kmem_cache_validate);
5456 EXPORT_SYMBOL(kmem_cache_size);
5457 +EXPORT_SYMBOL(register_cache);
5458 +EXPORT_SYMBOL(unregister_cache);
5459 EXPORT_SYMBOL(kmalloc);
5460 EXPORT_SYMBOL(kfree);
5461 EXPORT_SYMBOL(vfree);
5462 --- kernel-2.4.20-6chaos_18_7/mm/vmscan.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:34.000000000 -0600
5463 +++ kernel-2.4.20-6chaos_18_7-braam/mm/vmscan.c 2003-07-12 15:34:44.000000000 -0600
5465 #include <linux/kernel_stat.h>
5466 #include <linux/swap.h>
5467 #include <linux/swapctl.h>
5468 +#include <linux/cache_def.h>
5469 #include <linux/smp_lock.h>
5470 #include <linux/pagemap.h>
5471 #include <linux/init.h>
5472 @@ -444,6 +445,39 @@ static inline void kachunk_cache(struct
5474 #define BATCH_WORK_AMOUNT 64
5476 +static DECLARE_MUTEX(other_caches_sem);
5477 +static LIST_HEAD(cache_definitions);
5479 +void register_cache(struct cache_definition *cache)
5481 + down(&other_caches_sem);
5482 + list_add(&cache->link, &cache_definitions);
5483 + up(&other_caches_sem);
5486 +void unregister_cache(struct cache_definition *cache)
5488 + down(&other_caches_sem);
5489 + list_del(&cache->link);
5490 + up(&other_caches_sem);
5493 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
5495 + struct list_head *p;
5497 + if (down_trylock(&other_caches_sem))
5500 + list_for_each_prev(p, &cache_definitions) {
5501 + struct cache_definition *cache =
5502 + list_entry(p, struct cache_definition, link);
5504 + cache->shrink(priority, gfp_mask);
5506 + up(&other_caches_sem);
5510 * returns the active cache ratio relative to the total active list
5511 * times 10 (eg. 30% cache returns 3)
5512 @@ -887,7 +921,7 @@ static int do_try_to_free_pages_kswapd(u
5514 ret += shrink_dcache_memory(DEF_PRIORITY, gfp_mask);
5515 ret += shrink_icache_memory(DEF_PRIORITY, gfp_mask);
5516 - // ret += shrink_other_caches(DEF_PRIORITY, gfp_mask);
5517 + shrink_other_caches(DEF_PRIORITY, gfp_mask);
5519 ret += shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
5521 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
5522 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ext3-exports.c 2003-07-12 15:34:44.000000000 -0600
5524 +#include <linux/config.h>
5525 +#include <linux/module.h>
5526 +#include <linux/ext3_fs.h>
5527 +#include <linux/ext3_jbd.h>
5528 +#include <linux/ext3_xattr.h>
5530 +EXPORT_SYMBOL(ext3_force_commit);
5531 +EXPORT_SYMBOL(ext3_bread);
5532 +EXPORT_SYMBOL(ext3_xattr_register);
5533 +EXPORT_SYMBOL(ext3_xattr_unregister);
5534 +EXPORT_SYMBOL(ext3_xattr_get);
5535 +EXPORT_SYMBOL(ext3_xattr_list);
5536 +EXPORT_SYMBOL(ext3_xattr_set);