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=y
154 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
155 +# CONFIG_EXT3_FS_XATTR_USER is not set
156 +# CONFIG_EXT2_FS_XATTR is not set
157 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
158 +# CONFIG_EXT2_FS_XATTR_USER is not set
159 +# CONFIG_FS_MBCACHE is not set
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=y
191 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
192 +# CONFIG_EXT3_FS_XATTR_USER is not set
193 +# CONFIG_EXT2_FS_XATTR is not set
194 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
195 +# CONFIG_EXT2_FS_XATTR_USER is not set
196 +# CONFIG_FS_MBCACHE is not set
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=y
240 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
241 +# CONFIG_EXT3_FS_XATTR_USER is not set
242 +# CONFIG_EXT2_FS_XATTR is not set
243 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
244 +# CONFIG_EXT2_FS_XATTR_USER is not set
245 +# CONFIG_FS_MBCACHE is not set
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=y
256 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
257 +# CONFIG_EXT3_FS_XATTR_USER is not set
258 +# CONFIG_EXT2_FS_XATTR is not set
259 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
260 +# CONFIG_EXT2_FS_XATTR_USER is not set
261 +# CONFIG_FS_MBCACHE is not set
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=y
272 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
273 +# CONFIG_EXT3_FS_XATTR_USER is not set
274 +# CONFIG_EXT2_FS_XATTR is not set
275 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
276 +# CONFIG_EXT2_FS_XATTR_USER is not set
277 +# CONFIG_FS_MBCACHE is not set
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=y
288 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
289 +# CONFIG_EXT3_FS_XATTR_USER is not set
290 +# CONFIG_EXT2_FS_XATTR is not set
291 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
292 +# CONFIG_EXT2_FS_XATTR_USER is not set
293 +# CONFIG_FS_MBCACHE is not set
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=y
304 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
305 +# CONFIG_EXT3_FS_XATTR_USER is not set
306 +# CONFIG_EXT2_FS_XATTR is not set
307 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
308 +# CONFIG_EXT2_FS_XATTR_USER is not set
309 +# CONFIG_FS_MBCACHE is not set
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=y
320 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
321 +# CONFIG_EXT3_FS_XATTR_USER is not set
322 +# CONFIG_EXT2_FS_XATTR is not set
323 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
324 +# CONFIG_EXT2_FS_XATTR_USER is not set
325 +# CONFIG_FS_MBCACHE is not set
326 # CONFIG_UID16 is not set
327 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
328 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
329 --- kernel-2.4.20-6chaos_18_7/arch/ppc64/kernel/misc.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
330 +++ kernel-2.4.20-6chaos_18_7-braam/arch/ppc64/kernel/misc.S 2003-07-12 15:34:44.000000000 -0600
331 @@ -731,6 +731,7 @@ _GLOBAL(sys_call_table32)
332 .llong .sys_gettid /* 207 */
333 #if 0 /* Reserved syscalls */
334 .llong .sys_tkill /* 208 */
337 .llong .sys_lsetxattr /* 210 */
338 .llong .sys_fsetxattr
339 @@ -743,6 +744,7 @@ _GLOBAL(sys_call_table32)
340 .llong .sys_removexattr
341 .llong .sys_lremovexattr
342 .llong .sys_fremovexattr /* 220 */
343 +#if 0 /* Reserved syscalls */
346 .llong .sys_perfmonctl /* Put this here for now ... */
347 --- kernel-2.4.20-6chaos_18_7/arch/s390/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
348 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/defconfig 2003-07-12 15:34:44.000000000 -0600
351 # Automatically generated make config: don't edit
353 +CONFIG_EXT3_FS_XATTR=y
354 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
355 +# CONFIG_EXT3_FS_XATTR_USER is not set
356 +# CONFIG_EXT2_FS_XATTR is not set
357 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
358 +# CONFIG_EXT2_FS_XATTR_USER is not set
359 +# CONFIG_FS_MBCACHE is not set
360 # CONFIG_ISA is not set
361 # CONFIG_EISA is not set
362 # CONFIG_MCA is not set
363 --- kernel-2.4.20-6chaos_18_7/arch/s390/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:20.000000000 -0700
364 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390/kernel/entry.S 2003-07-12 15:34:44.000000000 -0600
365 @@ -558,18 +558,18 @@ sys_call_table:
369 - .long sys_ni_syscall /* 224 - reserved for setxattr */
370 - .long sys_ni_syscall /* 225 - reserved for lsetxattr */
371 - .long sys_ni_syscall /* 226 - reserved for fsetxattr */
372 - .long sys_ni_syscall /* 227 - reserved for getxattr */
373 - .long sys_ni_syscall /* 228 - reserved for lgetxattr */
374 - .long sys_ni_syscall /* 229 - reserved for fgetxattr */
375 - .long sys_ni_syscall /* 230 - reserved for listxattr */
376 - .long sys_ni_syscall /* 231 - reserved for llistxattr */
377 - .long sys_ni_syscall /* 232 - reserved for flistxattr */
378 - .long sys_ni_syscall /* 233 - reserved for removexattr */
379 - .long sys_ni_syscall /* 234 - reserved for lremovexattr */
380 - .long sys_ni_syscall /* 235 - reserved for fremovexattr */
382 + .long sys_lsetxattr /* 225 */
383 + .long sys_fsetxattr
385 + .long sys_lgetxattr
386 + .long sys_fgetxattr
387 + .long sys_listxattr /* 230 */
388 + .long sys_llistxattr
389 + .long sys_flistxattr
390 + .long sys_removexattr
391 + .long sys_lremovexattr
392 + .long sys_fremovexattr /* 235 */
396 --- kernel-2.4.20-6chaos_18_7/arch/s390x/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:21.000000000 -0700
397 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/defconfig 2003-07-12 15:34:44.000000000 -0600
400 # Automatically generated make config: don't edit
402 +CONFIG_EXT3_FS_XATTR=y
403 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
404 +# CONFIG_EXT3_FS_XATTR_USER is not set
405 +# CONFIG_EXT2_FS_XATTR is not set
406 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
407 +# CONFIG_EXT2_FS_XATTR_USER is not set
408 +# CONFIG_FS_MBCACHE is not set
409 # CONFIG_ISA is not set
410 # CONFIG_EISA is not set
411 # CONFIG_MCA is not set
412 --- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/entry.S~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:58:21.000000000 -0700
413 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/entry.S 2003-07-12 15:34:44.000000000 -0600
414 @@ -591,18 +591,18 @@ sys_call_table:
415 .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
416 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
417 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
418 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
419 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
420 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
421 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
422 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
423 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
424 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
425 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
426 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
427 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
428 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
429 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
430 + .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
431 + .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
432 + .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
433 + .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
434 + .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
435 + .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
436 + .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
437 + .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
438 + .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
439 + .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
440 + .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
441 + .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
442 .long SYSCALL(sys_gettid,sys_gettid)
443 .long SYSCALL(sys_tkill,sys_tkill)
445 --- kernel-2.4.20-6chaos_18_7/arch/s390x/kernel/wrapper32.S~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:59.000000000 -0600
446 +++ kernel-2.4.20-6chaos_18_7-braam/arch/s390x/kernel/wrapper32.S 2003-07-12 15:34:44.000000000 -0600
447 @@ -1091,3 +1091,95 @@ sys32_fstat64_wrapper:
448 llgtr %r3,%r3 # struct stat64 *
450 jg sys32_fstat64 # branch to system call
452 + .globl sys32_setxattr_wrapper
453 +sys32_setxattr_wrapper:
454 + llgtr %r2,%r2 # char *
455 + llgtr %r3,%r3 # char *
456 + llgtr %r4,%r4 # void *
457 + llgfr %r5,%r5 # size_t
461 + .globl sys32_lsetxattr_wrapper
462 +sys32_lsetxattr_wrapper:
463 + llgtr %r2,%r2 # char *
464 + llgtr %r3,%r3 # char *
465 + llgtr %r4,%r4 # void *
466 + llgfr %r5,%r5 # size_t
470 + .globl sys32_fsetxattr_wrapper
471 +sys32_fsetxattr_wrapper:
473 + llgtr %r3,%r3 # char *
474 + llgtr %r4,%r4 # void *
475 + llgfr %r5,%r5 # size_t
479 + .globl sys32_getxattr_wrapper
480 +sys32_getxattr_wrapper:
481 + llgtr %r2,%r2 # char *
482 + llgtr %r3,%r3 # char *
483 + llgtr %r4,%r4 # void *
484 + llgfr %r5,%r5 # size_t
487 + .globl sys32_lgetxattr_wrapper
488 +sys32_lgetxattr_wrapper:
489 + llgtr %r2,%r2 # char *
490 + llgtr %r3,%r3 # char *
491 + llgtr %r4,%r4 # void *
492 + llgfr %r5,%r5 # size_t
495 + .globl sys32_fgetxattr_wrapper
496 +sys32_fgetxattr_wrapper:
498 + llgtr %r3,%r3 # char *
499 + llgtr %r4,%r4 # void *
500 + llgfr %r5,%r5 # size_t
503 + .globl sys32_listxattr_wrapper
504 +sys32_listxattr_wrapper:
505 + llgtr %r2,%r2 # char *
506 + llgtr %r3,%r3 # char *
507 + llgfr %r4,%r4 # size_t
510 + .globl sys32_llistxattr_wrapper
511 +sys32_llistxattr_wrapper:
512 + llgtr %r2,%r2 # char *
513 + llgtr %r3,%r3 # char *
514 + llgfr %r4,%r4 # size_t
517 + .globl sys32_flistxattr_wrapper
518 +sys32_flistxattr_wrapper:
520 + llgtr %r3,%r3 # char *
521 + llgfr %r4,%r4 # size_t
524 + .globl sys32_removexattr_wrapper
525 +sys32_removexattr_wrapper:
526 + llgtr %r2,%r2 # char *
527 + llgtr %r3,%r3 # char *
530 + .globl sys32_lremovexattr_wrapper
531 +sys32_lremovexattr_wrapper:
532 + llgtr %r2,%r2 # char *
533 + llgtr %r3,%r3 # char *
534 + jg sys_lremovexattr
536 + .globl sys32_fremovexattr_wrapper
537 +sys32_fremovexattr_wrapper:
539 + llgtr %r3,%r3 # char *
540 + jg sys_fremovexattr
543 --- kernel-2.4.20-6chaos_18_7/arch/sparc/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:50.000000000 -0600
544 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/defconfig 2003-07-12 15:34:44.000000000 -0600
547 # Automatically generated make config: don't edit
549 +CONFIG_EXT3_FS_XATTR=y
550 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
551 +# CONFIG_EXT3_FS_XATTR_USER is not set
552 +# CONFIG_EXT2_FS_XATTR is not set
553 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
554 +# CONFIG_EXT2_FS_XATTR_USER is not set
555 +# CONFIG_FS_MBCACHE is not set
559 --- kernel-2.4.20-6chaos_18_7/arch/sparc/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:52.000000000 -0600
560 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc/kernel/systbls.S 2003-07-12 15:34:44.000000000 -0600
561 @@ -51,11 +51,11 @@ sys_call_table:
562 /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
563 /*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
564 /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
565 -/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
566 -/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
567 -/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
568 -/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
569 -/*185*/ .long sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sys_newuname
570 +/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
571 +/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
572 +/*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
573 +/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
574 +/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
575 /*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
576 /*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
577 /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
578 --- kernel-2.4.20-6chaos_18_7/arch/sparc64/defconfig~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:12:29.000000000 -0600
579 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/defconfig 2003-07-12 15:34:44.000000000 -0600
582 # Automatically generated make config: don't edit
584 +CONFIG_EXT3_FS_XATTR=y
585 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
586 +# CONFIG_EXT3_FS_XATTR_USER is not set
587 +# CONFIG_EXT2_FS_XATTR is not set
588 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
589 +# CONFIG_EXT2_FS_XATTR_USER is not set
590 +# CONFIG_FS_MBCACHE is not set
593 # Code maturity level options
594 --- kernel-2.4.20-6chaos_18_7/arch/sparc64/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:10:55.000000000 -0600
595 +++ kernel-2.4.20-6chaos_18_7-braam/arch/sparc64/kernel/systbls.S 2003-07-12 15:34:44.000000000 -0600
596 @@ -52,11 +52,11 @@ sys_call_table32:
597 /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
598 .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
599 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
600 - .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
601 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
602 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
603 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
604 - .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
605 + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
606 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
607 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
608 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
609 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
610 /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
611 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
612 /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
613 @@ -111,11 +111,11 @@ sys_call_table:
614 /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
615 .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
616 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
617 - .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
618 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
619 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
620 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
621 - .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
622 + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
623 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
624 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
625 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
626 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
627 /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
628 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
629 /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
630 --- kernel-2.4.20-6chaos_18_7/fs/Config.in~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:24.000000000 -0600
631 +++ kernel-2.4.20-6chaos_18_7-braam/fs/Config.in 2003-07-12 15:34:44.000000000 -0600
632 @@ -34,6 +34,11 @@ dep_mbool ' Debug Befs' CONFIG_BEFS_DEB
633 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
635 tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
636 +dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
637 +dep_bool ' Ext3 extended attribute block sharing' \
638 + CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
639 +dep_bool ' Ext3 extended user attributes' \
640 + CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
641 # CONFIG_JBD could be its own option (even modular), but until there are
642 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
643 # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
644 @@ -93,6 +98,11 @@ dep_mbool ' QNX4FS write support (DANGE
645 tristate 'ROM file system support' CONFIG_ROMFS_FS
647 tristate 'Second extended fs support' CONFIG_EXT2_FS
648 +dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
649 +dep_bool ' Ext2 extended attribute block sharing' \
650 + CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
651 +dep_bool ' Ext2 extended user attributes' \
652 + CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
654 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
656 @@ -164,6 +174,10 @@ else
657 define_tristate CONFIG_ZISOFS_FS n
660 +# Meta block cache for Extended Attributes (ext2/ext3)
661 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
662 +define_tristate CONFIG_FS_MBCACHE y
664 mainmenu_option next_comment
665 comment 'Partition Types'
666 source fs/partitions/Config.in
667 --- kernel-2.4.20-6chaos_18_7/fs/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:34.000000000 -0600
668 +++ kernel-2.4.20-6chaos_18_7-braam/fs/Makefile 2003-07-12 15:34:44.000000000 -0600
669 @@ -84,6 +84,9 @@ obj-y += binfmt_script.o
671 obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
673 +export-objs += mbcache.o
674 +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
676 # persistent filesystems
677 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
679 --- kernel-2.4.20-6chaos_18_7/fs/ext2/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
680 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/Makefile 2003-07-12 15:34:44.000000000 -0600
681 @@ -13,4 +13,8 @@ obj-y := balloc.o bitmap.o dir.o file
682 ioctl.o namei.o super.o symlink.o
685 +export-objs += xattr.o
686 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
687 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
689 include $(TOPDIR)/Rules.make
690 --- kernel-2.4.20-6chaos_18_7/fs/ext2/file.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
691 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/file.c 2003-07-12 15:34:44.000000000 -0600
694 #include <linux/fs.h>
695 #include <linux/ext2_fs.h>
696 +#include <linux/ext2_xattr.h>
697 #include <linux/sched.h>
700 @@ -51,4 +52,8 @@ struct file_operations ext2_file_operati
702 struct inode_operations ext2_file_inode_operations = {
703 truncate: ext2_truncate,
704 + setxattr: ext2_setxattr,
705 + getxattr: ext2_getxattr,
706 + listxattr: ext2_listxattr,
707 + removexattr: ext2_removexattr,
709 --- kernel-2.4.20-6chaos_18_7/fs/ext2/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
710 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/ialloc.c 2003-07-12 15:34:44.000000000 -0600
712 #include <linux/config.h>
713 #include <linux/fs.h>
714 #include <linux/ext2_fs.h>
715 +#include <linux/ext2_xattr.h>
716 #include <linux/locks.h>
717 #include <linux/quotaops.h>
719 @@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino
721 if (!is_bad_inode(inode)) {
722 /* Quota is already initialized in iput() */
723 + ext2_xattr_delete_inode(inode);
724 DQUOT_FREE_INODE(inode);
727 --- kernel-2.4.20-6chaos_18_7/fs/ext2/inode.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
728 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/inode.c 2003-07-12 15:34:44.000000000 -0600
729 @@ -39,6 +39,18 @@ MODULE_LICENSE("GPL");
730 static int ext2_update_inode(struct inode * inode, int do_sync);
733 + * Test whether an inode is a fast symlink.
735 +static inline int ext2_inode_is_fast_symlink(struct inode *inode)
737 + int ea_blocks = inode->u.ext2_i.i_file_acl ?
738 + (inode->i_sb->s_blocksize >> 9) : 0;
740 + return (S_ISLNK(inode->i_mode) &&
741 + inode->i_blocks - ea_blocks == 0);
745 * Called at each iput()
747 void ext2_put_inode (struct inode * inode)
748 @@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i
752 - if (is_bad_inode(inode) ||
753 - inode->i_ino == EXT2_ACL_IDX_INO ||
754 - inode->i_ino == EXT2_ACL_DATA_INO)
755 + if (is_bad_inode(inode))
757 inode->u.ext2_i.i_dtime = CURRENT_TIME;
758 mark_inode_dirty(inode);
759 @@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode
760 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
761 S_ISLNK(inode->i_mode)))
763 + if (ext2_inode_is_fast_symlink(inode))
765 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
768 @@ -888,8 +900,7 @@ void ext2_read_inode (struct inode * ino
769 unsigned long offset;
770 struct ext2_group_desc * gdp;
772 - if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
773 - inode->i_ino != EXT2_ACL_DATA_INO &&
774 + if ((inode->i_ino != EXT2_ROOT_INO &&
775 inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
776 inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
777 ext2_error (inode->i_sb, "ext2_read_inode",
778 @@ -974,10 +985,7 @@ void ext2_read_inode (struct inode * ino
779 for (block = 0; block < EXT2_N_BLOCKS; block++)
780 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
782 - if (inode->i_ino == EXT2_ACL_IDX_INO ||
783 - inode->i_ino == EXT2_ACL_DATA_INO)
784 - /* Nothing to do */ ;
785 - else if (S_ISREG(inode->i_mode)) {
786 + if (S_ISREG(inode->i_mode)) {
787 inode->i_op = &ext2_file_inode_operations;
788 inode->i_fop = &ext2_file_operations;
789 inode->i_mapping->a_ops = &ext2_aops;
790 @@ -986,15 +994,17 @@ void ext2_read_inode (struct inode * ino
791 inode->i_fop = &ext2_dir_operations;
792 inode->i_mapping->a_ops = &ext2_aops;
793 } else if (S_ISLNK(inode->i_mode)) {
794 - if (!inode->i_blocks)
795 + if (ext2_inode_is_fast_symlink(inode))
796 inode->i_op = &ext2_fast_symlink_inode_operations;
798 - inode->i_op = &page_symlink_inode_operations;
799 + inode->i_op = &ext2_symlink_inode_operations;
800 inode->i_mapping->a_ops = &ext2_aops;
804 + inode->i_op = &ext2_special_inode_operations;
805 init_special_inode(inode, inode->i_mode,
806 le32_to_cpu(raw_inode->i_block[0]));
809 inode->i_attr_flags = 0;
810 if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
811 --- kernel-2.4.20-6chaos_18_7/fs/ext2/namei.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
812 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/namei.c 2003-07-12 15:34:44.000000000 -0600
815 #include <linux/fs.h>
816 #include <linux/ext2_fs.h>
817 +#include <linux/ext2_xattr.h>
818 #include <linux/pagemap.h>
821 @@ -136,7 +137,7 @@ static int ext2_symlink (struct inode *
823 if (l > sizeof (inode->u.ext2_i.i_data)) {
825 - inode->i_op = &page_symlink_inode_operations;
826 + inode->i_op = &ext2_symlink_inode_operations;
827 inode->i_mapping->a_ops = &ext2_aops;
828 err = block_symlink(inode, symname, l);
830 @@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o
834 + setxattr: ext2_setxattr,
835 + getxattr: ext2_getxattr,
836 + listxattr: ext2_listxattr,
837 + removexattr: ext2_removexattr,
840 +struct inode_operations ext2_special_inode_operations = {
841 + setxattr: ext2_setxattr,
842 + getxattr: ext2_getxattr,
843 + listxattr: ext2_listxattr,
844 + removexattr: ext2_removexattr,
846 --- kernel-2.4.20-6chaos_18_7/fs/ext2/super.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:09.000000000 -0700
847 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/super.c 2003-07-12 15:34:44.000000000 -0600
849 #include <linux/string.h>
850 #include <linux/fs.h>
851 #include <linux/ext2_fs.h>
852 +#include <linux/ext2_xattr.h>
853 #include <linux/slab.h>
854 #include <linux/init.h>
855 #include <linux/locks.h>
856 @@ -125,6 +126,7 @@ void ext2_put_super (struct super_block
860 + ext2_xattr_put_super(sb);
861 if (!(sb->s_flags & MS_RDONLY)) {
862 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
864 @@ -175,6 +177,13 @@ static int parse_options (char * options
865 this_char = strtok (NULL, ",")) {
866 if ((value = strchr (this_char, '=')) != NULL)
868 +#ifdef CONFIG_EXT2_FS_XATTR_USER
869 + if (!strcmp (this_char, "user_xattr"))
870 + set_opt (*mount_options, XATTR_USER);
871 + else if (!strcmp (this_char, "nouser_xattr"))
872 + clear_opt (*mount_options, XATTR_USER);
875 if (!strcmp (this_char, "bsddf"))
876 clear_opt (*mount_options, MINIX_DF);
877 else if (!strcmp (this_char, "nouid32")) {
878 @@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st
879 blocksize = BLOCK_SIZE;
881 sb->u.ext2_sb.s_mount_opt = 0;
882 +#ifdef CONFIG_EXT2_FS_XATTR_USER
883 + /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
885 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
886 &sb->u.ext2_sb.s_mount_opt)) {
888 @@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type,
890 static int __init init_ext2_fs(void)
892 - return register_filesystem(&ext2_fs_type);
893 + int error = init_ext2_xattr();
896 + error = init_ext2_xattr_user();
899 + error = register_filesystem(&ext2_fs_type);
903 + exit_ext2_xattr_user();
909 static void __exit exit_ext2_fs(void)
911 unregister_filesystem(&ext2_fs_type);
912 + exit_ext2_xattr_user();
917 --- kernel-2.4.20-6chaos_18_7/fs/ext2/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
918 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/symlink.c 2003-07-12 15:34:44.000000000 -0600
921 #include <linux/fs.h>
922 #include <linux/ext2_fs.h>
923 +#include <linux/ext2_xattr.h>
925 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
927 @@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr
928 return vfs_follow_link(nd, s);
931 +struct inode_operations ext2_symlink_inode_operations = {
932 + readlink: page_readlink,
933 + follow_link: page_follow_link,
934 + setxattr: ext2_setxattr,
935 + getxattr: ext2_getxattr,
936 + listxattr: ext2_listxattr,
937 + removexattr: ext2_removexattr,
940 struct inode_operations ext2_fast_symlink_inode_operations = {
941 readlink: ext2_readlink,
942 follow_link: ext2_follow_link,
943 + setxattr: ext2_setxattr,
944 + getxattr: ext2_getxattr,
945 + listxattr: ext2_listxattr,
946 + removexattr: ext2_removexattr,
948 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
949 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr.c 2003-07-12 15:34:44.000000000 -0600
952 + * linux/fs/ext2/xattr.c
954 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
956 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
957 + * Extended attributes for symlinks and special files added per
958 + * suggestion of Luka Renko <luka.renko@hermes.si>.
962 + * Extended attributes are stored on disk blocks allocated outside of
963 + * any inode. The i_file_acl field is then made to point to this allocated
964 + * block. If all extended attributes of an inode are identical, these
965 + * inodes may share the same extended attribute block. Such situations
966 + * are automatically detected by keeping a cache of recent attribute block
967 + * numbers and hashes over the block's contents in memory.
970 + * Extended attribute block layout:
972 + * +------------------+
975 + * | entry 2 | | growing downwards
977 + * | four null bytes |
980 + * | value 3 | | growing upwards
982 + * +------------------+
984 + * The block header is followed by multiple entry descriptors. These entry
985 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
986 + * byte boundaries. The entry descriptors are sorted by attribute name,
987 + * so that two extended attribute blocks can be compared efficiently.
989 + * Attribute values are aligned to the end of the block, stored in
990 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
991 + * boundaries. No additional gaps are left between them.
995 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
996 + * the xattr inode operations are called, so we are guaranteed that only one
997 + * processes accesses extended attributes of an inode at any time.
999 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
1000 + * only a single process is modifying an extended attribute block, even
1001 + * if the block is shared among inodes.
1003 + * Note for porting to 2.5
1004 + * -----------------------
1005 + * The BKL will no longer be held in the xattr inode operations.
1008 +#include <linux/module.h>
1009 +#include <linux/locks.h>
1010 +#include <linux/slab.h>
1011 +#include <linux/fs.h>
1012 +#include <linux/ext2_fs.h>
1013 +#include <linux/ext2_xattr.h>
1014 +#include <linux/mbcache.h>
1015 +#include <linux/quotaops.h>
1016 +#include <asm/semaphore.h>
1017 +#include <linux/compatmac.h>
1019 +/* These symbols may be needed by a module. */
1020 +EXPORT_SYMBOL(ext2_xattr_register);
1021 +EXPORT_SYMBOL(ext2_xattr_unregister);
1022 +EXPORT_SYMBOL(ext2_xattr_get);
1023 +EXPORT_SYMBOL(ext2_xattr_list);
1024 +EXPORT_SYMBOL(ext2_xattr_set);
1026 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1027 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
1030 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
1031 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
1032 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
1033 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
1035 +#ifdef EXT2_XATTR_DEBUG
1036 +# define ea_idebug(inode, f...) do { \
1037 + printk(KERN_DEBUG "inode %s:%ld: ", \
1038 + kdevname(inode->i_dev), inode->i_ino); \
1042 +# define ea_bdebug(bh, f...) do { \
1043 + printk(KERN_DEBUG "block %s:%ld: ", \
1044 + kdevname(bh->b_dev), bh->b_blocknr); \
1049 +# define ea_idebug(f...)
1050 +# define ea_bdebug(f...)
1053 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
1054 + struct ext2_xattr_header *);
1056 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1058 +static int ext2_xattr_cache_insert(struct buffer_head *);
1059 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
1060 + struct ext2_xattr_header *);
1061 +static void ext2_xattr_cache_remove(struct buffer_head *);
1062 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
1063 + struct ext2_xattr_entry *);
1065 +static struct mb_cache *ext2_xattr_cache;
1068 +# define ext2_xattr_cache_insert(bh) 0
1069 +# define ext2_xattr_cache_find(inode, header) NULL
1070 +# define ext2_xattr_cache_remove(bh) while(0) {}
1071 +# define ext2_xattr_rehash(header, entry) while(0) {}
1075 + * If a file system does not share extended attributes among inodes,
1076 + * we should not need the ext2_xattr_sem semaphore. However, the
1077 + * filesystem may still contain shared blocks, so we always take
1081 +DECLARE_MUTEX(ext2_xattr_sem);
1084 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
1086 + struct super_block *sb = inode->i_sb;
1087 + int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
1088 + EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
1090 + /* How can we enforce the allocation? */
1091 + int block = ext2_new_block(inode, goal, 0, 0, errp);
1094 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1100 +ext2_xattr_quota_alloc(struct inode *inode, int force)
1102 + /* How can we enforce the allocation? */
1104 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
1106 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1108 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
1116 +ext2_xattr_quota_free(struct inode *inode)
1118 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
1119 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1123 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
1125 + ext2_free_blocks(inode, block, 1);
1126 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1130 +# define ext2_xattr_quota_free(inode) \
1131 + DQUOT_FREE_BLOCK(inode, 1)
1132 +# define ext2_xattr_free_block(inode, block) \
1133 + ext2_free_blocks(inode, block, 1)
1136 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1138 +static inline struct buffer_head *
1139 +sb_bread(struct super_block *sb, int block)
1141 + return bread(sb->s_dev, block, sb->s_blocksize);
1144 +static inline struct buffer_head *
1145 +sb_getblk(struct super_block *sb, int block)
1147 + return getblk(sb->s_dev, block, sb->s_blocksize);
1152 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1153 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1156 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1158 + int error = -EINVAL;
1160 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1161 + write_lock(&ext2_handler_lock);
1162 + if (!ext2_xattr_handlers[name_index-1]) {
1163 + ext2_xattr_handlers[name_index-1] = handler;
1166 + write_unlock(&ext2_handler_lock);
1172 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1174 + if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
1175 + write_lock(&ext2_handler_lock);
1176 + ext2_xattr_handlers[name_index-1] = NULL;
1177 + write_unlock(&ext2_handler_lock);
1181 +static inline const char *
1182 +strcmp_prefix(const char *a, const char *a_prefix)
1184 + while (*a_prefix && *a == *a_prefix) {
1188 + return *a_prefix ? NULL : a;
1192 + * Decode the extended attribute name, and translate it into
1193 + * the name_index and name suffix.
1195 +static struct ext2_xattr_handler *
1196 +ext2_xattr_resolve_name(const char **name)
1198 + struct ext2_xattr_handler *handler = NULL;
1203 + read_lock(&ext2_handler_lock);
1204 + for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1205 + if (ext2_xattr_handlers[i]) {
1206 + const char *n = strcmp_prefix(*name,
1207 + ext2_xattr_handlers[i]->prefix);
1209 + handler = ext2_xattr_handlers[i];
1215 + read_unlock(&ext2_handler_lock);
1219 +static inline struct ext2_xattr_handler *
1220 +ext2_xattr_handler(int name_index)
1222 + struct ext2_xattr_handler *handler = NULL;
1223 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1224 + read_lock(&ext2_handler_lock);
1225 + handler = ext2_xattr_handlers[name_index-1];
1226 + read_unlock(&ext2_handler_lock);
1232 + * Inode operation getxattr()
1234 + * dentry->d_inode->i_sem down
1235 + * BKL held [before 2.5.x]
1238 +ext2_getxattr(struct dentry *dentry, const char *name,
1239 + void *buffer, size_t size)
1241 + struct ext2_xattr_handler *handler;
1242 + struct inode *inode = dentry->d_inode;
1244 + handler = ext2_xattr_resolve_name(&name);
1247 + return handler->get(inode, name, buffer, size);
1251 + * Inode operation listxattr()
1253 + * dentry->d_inode->i_sem down
1254 + * BKL held [before 2.5.x]
1257 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1259 + return ext2_xattr_list(dentry->d_inode, buffer, size);
1263 + * Inode operation setxattr()
1265 + * dentry->d_inode->i_sem down
1266 + * BKL held [before 2.5.x]
1269 +ext2_setxattr(struct dentry *dentry, const char *name,
1270 + const void *value, size_t size, int flags)
1272 + struct ext2_xattr_handler *handler;
1273 + struct inode *inode = dentry->d_inode;
1276 + value = ""; /* empty EA, do not remove */
1277 + handler = ext2_xattr_resolve_name(&name);
1280 + return handler->set(inode, name, value, size, flags);
1284 + * Inode operation removexattr()
1286 + * dentry->d_inode->i_sem down
1287 + * BKL held [before 2.5.x]
1290 +ext2_removexattr(struct dentry *dentry, const char *name)
1292 + struct ext2_xattr_handler *handler;
1293 + struct inode *inode = dentry->d_inode;
1295 + handler = ext2_xattr_resolve_name(&name);
1298 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1302 + * ext2_xattr_get()
1304 + * Copy an extended attribute into the buffer
1305 + * provided, or compute the buffer size required.
1306 + * Buffer is NULL to compute the size of the buffer required.
1308 + * Returns a negative error number on failure, or the number of bytes
1309 + * used / required on success.
1312 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1313 + void *buffer, size_t buffer_size)
1315 + struct buffer_head *bh = NULL;
1316 + struct ext2_xattr_entry *entry;
1317 + unsigned int block, size;
1319 + int name_len, error;
1321 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1322 + name_index, name, buffer, (long)buffer_size);
1326 + if (!EXT2_I(inode)->i_file_acl)
1328 + block = EXT2_I(inode)->i_file_acl;
1329 + ea_idebug(inode, "reading block %d", block);
1330 + bh = sb_bread(inode->i_sb, block);
1333 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1334 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1335 + end = bh->b_data + bh->b_size;
1336 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1337 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1338 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
1339 + "inode %ld: bad block %d", inode->i_ino, block);
1343 + /* find named attribute */
1344 + name_len = strlen(name);
1347 + if (name_len > 255)
1349 + entry = FIRST_ENTRY(bh);
1350 + while (!IS_LAST_ENTRY(entry)) {
1351 + struct ext2_xattr_entry *next =
1352 + EXT2_XATTR_NEXT(entry);
1353 + if ((char *)next >= end)
1355 + if (name_index == entry->e_name_index &&
1356 + name_len == entry->e_name_len &&
1357 + memcmp(name, entry->e_name, name_len) == 0)
1361 + /* Check the remaining name entries */
1362 + while (!IS_LAST_ENTRY(entry)) {
1363 + struct ext2_xattr_entry *next =
1364 + EXT2_XATTR_NEXT(entry);
1365 + if ((char *)next >= end)
1369 + if (ext2_xattr_cache_insert(bh))
1370 + ea_idebug(inode, "cache insert failed");
1374 + /* check the buffer size */
1375 + if (entry->e_value_block != 0)
1377 + size = le32_to_cpu(entry->e_value_size);
1378 + if (size > inode->i_sb->s_blocksize ||
1379 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1382 + if (ext2_xattr_cache_insert(bh))
1383 + ea_idebug(inode, "cache insert failed");
1386 + if (size > buffer_size)
1388 + /* return value of attribute */
1389 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1401 + * ext2_xattr_list()
1403 + * Copy a list of attribute names into the buffer
1404 + * provided, or compute the buffer size required.
1405 + * Buffer is NULL to compute the size of the buffer required.
1407 + * Returns a negative error number on failure, or the number of bytes
1408 + * used / required on success.
1411 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1413 + struct buffer_head *bh = NULL;
1414 + struct ext2_xattr_entry *entry;
1415 + unsigned int block, size = 0;
1419 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1420 + buffer, (long)buffer_size);
1422 + if (!EXT2_I(inode)->i_file_acl)
1424 + block = EXT2_I(inode)->i_file_acl;
1425 + ea_idebug(inode, "reading block %d", block);
1426 + bh = sb_bread(inode->i_sb, block);
1429 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1430 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1431 + end = bh->b_data + bh->b_size;
1432 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1433 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1434 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
1435 + "inode %ld: bad block %d", inode->i_ino, block);
1439 + /* compute the size required for the list of attribute names */
1440 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1441 + entry = EXT2_XATTR_NEXT(entry)) {
1442 + struct ext2_xattr_handler *handler;
1443 + struct ext2_xattr_entry *next =
1444 + EXT2_XATTR_NEXT(entry);
1445 + if ((char *)next >= end)
1448 + handler = ext2_xattr_handler(entry->e_name_index);
1450 + size += handler->list(NULL, inode, entry->e_name,
1451 + entry->e_name_len);
1454 + if (ext2_xattr_cache_insert(bh))
1455 + ea_idebug(inode, "cache insert failed");
1461 + if (size > buffer_size)
1465 + /* list the attribute names */
1467 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1468 + entry = EXT2_XATTR_NEXT(entry)) {
1469 + struct ext2_xattr_handler *handler;
1471 + handler = ext2_xattr_handler(entry->e_name_index);
1473 + buf += handler->list(buf, inode, entry->e_name,
1474 + entry->e_name_len);
1485 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1486 + * not set, set it.
1488 +static void ext2_xattr_update_super_block(struct super_block *sb)
1490 + if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1494 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1495 + EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1497 + EXT2_SB(sb)->s_es->s_feature_compat |=
1498 + cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1500 + mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1505 + * ext2_xattr_set()
1507 + * Create, replace or remove an extended attribute for this inode. Buffer
1508 + * is NULL to remove an existing extended attribute, and non-NULL to
1509 + * either replace an existing extended attribute, or create a new extended
1510 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1511 + * specify that an extended attribute must exist and must not exist
1512 + * previous to the call, respectively.
1514 + * Returns 0, or a negative error number on failure.
1517 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1518 + const void *value, size_t value_len, int flags)
1520 + struct super_block *sb = inode->i_sb;
1521 + struct buffer_head *bh = NULL;
1522 + struct ext2_xattr_header *header = NULL;
1523 + struct ext2_xattr_entry *here, *last;
1524 + unsigned int name_len;
1525 + int block = EXT2_I(inode)->i_file_acl;
1526 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
1530 + * header -- Points either into bh, or to a temporarily
1531 + * allocated buffer.
1532 + * here -- The named entry found, or the place for inserting, within
1533 + * the block pointed to by header.
1534 + * last -- Points right after the last named entry within the block
1535 + * pointed to by header.
1536 + * min_offs -- The offset of the first value (values are aligned
1537 + * towards the end of the block).
1538 + * end -- Points right after the block pointed to by header.
1541 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1542 + name_index, name, value, (long)value_len);
1544 + if (IS_RDONLY(inode))
1546 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1548 + if (value == NULL)
1552 + name_len = strlen(name);
1553 + if (name_len > 255 || value_len > sb->s_blocksize)
1555 + down(&ext2_xattr_sem);
1558 + /* The inode already has an extended attribute block. */
1560 + bh = sb_bread(sb, block);
1564 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1565 + atomic_read(&(bh->b_count)),
1566 + le32_to_cpu(HDR(bh)->h_refcount));
1568 + end = bh->b_data + bh->b_size;
1569 + if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1570 + header->h_blocks != cpu_to_le32(1)) {
1571 +bad_block: ext2_error(sb, "ext2_xattr_set",
1572 + "inode %ld: bad block %d", inode->i_ino, block);
1576 + /* Find the named attribute. */
1577 + here = FIRST_ENTRY(bh);
1578 + while (!IS_LAST_ENTRY(here)) {
1579 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1580 + if ((char *)next >= end)
1582 + if (!here->e_value_block && here->e_value_size) {
1583 + int offs = le16_to_cpu(here->e_value_offs);
1584 + if (offs < min_offs)
1587 + not_found = name_index - here->e_name_index;
1589 + not_found = name_len - here->e_name_len;
1591 + not_found = memcmp(name, here->e_name,name_len);
1592 + if (not_found <= 0)
1597 + /* We still need to compute min_offs and last. */
1598 + while (!IS_LAST_ENTRY(last)) {
1599 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1600 + if ((char *)next >= end)
1602 + if (!last->e_value_block && last->e_value_size) {
1603 + int offs = le16_to_cpu(last->e_value_offs);
1604 + if (offs < min_offs)
1610 + /* Check whether we have enough space left. */
1611 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1613 + /* We will use a new extended attribute block. */
1614 + free = sb->s_blocksize -
1615 + sizeof(struct ext2_xattr_header) - sizeof(__u32);
1616 + here = last = NULL; /* avoid gcc uninitialized warning. */
1620 + /* Request to remove a nonexistent attribute? */
1622 + if (flags & XATTR_REPLACE)
1625 + if (value == NULL)
1628 + free -= EXT2_XATTR_LEN(name_len);
1630 + /* Request to create an existing attribute? */
1632 + if (flags & XATTR_CREATE)
1634 + if (!here->e_value_block && here->e_value_size) {
1635 + unsigned int size = le32_to_cpu(here->e_value_size);
1637 + if (le16_to_cpu(here->e_value_offs) + size >
1638 + sb->s_blocksize || size > sb->s_blocksize)
1640 + free += EXT2_XATTR_SIZE(size);
1643 + free -= EXT2_XATTR_SIZE(value_len);
1648 + /* Here we know that we can set the new attribute. */
1651 + if (header->h_refcount == cpu_to_le32(1)) {
1652 + ea_bdebug(bh, "modifying in-place");
1653 + ext2_xattr_cache_remove(bh);
1657 + ea_bdebug(bh, "cloning");
1658 + header = kmalloc(bh->b_size, GFP_KERNEL);
1660 + if (header == NULL)
1662 + memcpy(header, HDR(bh), bh->b_size);
1663 + header->h_refcount = cpu_to_le32(1);
1664 + offset = (char *)header - bh->b_data;
1665 + here = ENTRY((char *)here + offset);
1666 + last = ENTRY((char *)last + offset);
1669 + /* Allocate a buffer where we construct the new block. */
1670 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1672 + if (header == NULL)
1674 + memset(header, 0, sb->s_blocksize);
1675 + end = (char *)header + sb->s_blocksize;
1676 + header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1677 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
1678 + last = here = ENTRY(header+1);
1682 + /* Insert the new name. */
1683 + int size = EXT2_XATTR_LEN(name_len);
1684 + int rest = (char *)last - (char *)here;
1685 + memmove((char *)here + size, here, rest);
1686 + memset(here, 0, size);
1687 + here->e_name_index = name_index;
1688 + here->e_name_len = name_len;
1689 + memcpy(here->e_name, name, name_len);
1691 + /* Remove the old value. */
1692 + if (!here->e_value_block && here->e_value_size) {
1693 + char *first_val = (char *)header + min_offs;
1694 + int offs = le16_to_cpu(here->e_value_offs);
1695 + char *val = (char *)header + offs;
1696 + size_t size = EXT2_XATTR_SIZE(
1697 + le32_to_cpu(here->e_value_size));
1698 + memmove(first_val + size, first_val, val - first_val);
1699 + memset(first_val, 0, size);
1700 + here->e_value_offs = 0;
1703 + /* Adjust all value offsets. */
1704 + last = ENTRY(header+1);
1705 + while (!IS_LAST_ENTRY(last)) {
1706 + int o = le16_to_cpu(last->e_value_offs);
1707 + if (!last->e_value_block && o < offs)
1708 + last->e_value_offs =
1709 + cpu_to_le16(o + size);
1710 + last = EXT2_XATTR_NEXT(last);
1713 + if (value == NULL) {
1714 + /* Remove this attribute. */
1715 + if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1716 + /* This block is now empty. */
1717 + error = ext2_xattr_set2(inode, bh, NULL);
1720 + /* Remove the old name. */
1721 + int size = EXT2_XATTR_LEN(name_len);
1722 + last = ENTRY((char *)last - size);
1723 + memmove(here, (char*)here + size,
1724 + (char*)last - (char*)here);
1725 + memset(last, 0, size);
1730 + if (value != NULL) {
1731 + /* Insert the new value. */
1732 + here->e_value_size = cpu_to_le32(value_len);
1734 + size_t size = EXT2_XATTR_SIZE(value_len);
1735 + char *val = (char *)header + min_offs - size;
1736 + here->e_value_offs =
1737 + cpu_to_le16((char *)val - (char *)header);
1738 + memset(val + size - EXT2_XATTR_PAD, 0,
1739 + EXT2_XATTR_PAD); /* Clear the pad bytes. */
1740 + memcpy(val, value, value_len);
1743 + ext2_xattr_rehash(header, here);
1745 + error = ext2_xattr_set2(inode, bh, header);
1749 + if (!(bh && header == HDR(bh)))
1751 + up(&ext2_xattr_sem);
1757 + * Second half of ext2_xattr_set(): Update the file system.
1760 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1761 + struct ext2_xattr_header *header)
1763 + struct super_block *sb = inode->i_sb;
1764 + struct buffer_head *new_bh = NULL;
1768 + new_bh = ext2_xattr_cache_find(inode, header);
1771 + * We found an identical block in the cache.
1772 + * The old block will be released after updating
1775 + ea_bdebug(old_bh, "reusing block %ld",
1776 + new_bh->b_blocknr);
1779 + if (ext2_xattr_quota_alloc(inode, 1))
1782 + HDR(new_bh)->h_refcount = cpu_to_le32(
1783 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1784 + ea_bdebug(new_bh, "refcount now=%d",
1785 + le32_to_cpu(HDR(new_bh)->h_refcount));
1786 + } else if (old_bh && header == HDR(old_bh)) {
1787 + /* Keep this block. */
1789 + (void)ext2_xattr_cache_insert(new_bh);
1791 + /* We need to allocate a new block */
1792 + int force = EXT2_I(inode)->i_file_acl != 0;
1793 + int block = ext2_xattr_new_block(inode, &error, force);
1796 + ea_idebug(inode, "creating block %d", block);
1798 + new_bh = sb_getblk(sb, block);
1800 + ext2_xattr_free_block(inode, block);
1804 + lock_buffer(new_bh);
1805 + memcpy(new_bh->b_data, header, new_bh->b_size);
1806 + mark_buffer_uptodate(new_bh, 1);
1807 + unlock_buffer(new_bh);
1808 + (void)ext2_xattr_cache_insert(new_bh);
1810 + ext2_xattr_update_super_block(sb);
1812 + mark_buffer_dirty(new_bh);
1813 + if (IS_SYNC(inode)) {
1814 + ll_rw_block(WRITE, 1, &new_bh);
1815 + wait_on_buffer(new_bh);
1817 + if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1822 + /* Update the inode. */
1823 + EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1824 + inode->i_ctime = CURRENT_TIME;
1825 + if (IS_SYNC(inode)) {
1826 + error = ext2_sync_inode (inode);
1830 + mark_inode_dirty(inode);
1833 + if (old_bh && old_bh != new_bh) {
1835 + * If there was an old block, and we are not still using it,
1836 + * we now release the old block.
1838 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1840 + if (refcount == 1) {
1841 + /* Free the old block. */
1842 + ea_bdebug(old_bh, "freeing");
1843 + ext2_xattr_free_block(inode, old_bh->b_blocknr);
1844 + mark_buffer_clean(old_bh);
1846 + /* Decrement the refcount only. */
1848 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1849 + ext2_xattr_quota_free(inode);
1850 + mark_buffer_dirty(old_bh);
1851 + ea_bdebug(old_bh, "refcount now=%d", refcount);
1856 + if (old_bh != new_bh)
1863 + * ext2_xattr_delete_inode()
1865 + * Free extended attribute resources associated with this inode. This
1866 + * is called immediately before an inode is freed.
1869 +ext2_xattr_delete_inode(struct inode *inode)
1871 + struct buffer_head *bh;
1872 + unsigned int block = EXT2_I(inode)->i_file_acl;
1876 + down(&ext2_xattr_sem);
1878 + bh = sb_bread(inode->i_sb, block);
1880 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1881 + "inode %ld: block %d read error", inode->i_ino, block);
1884 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1885 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1886 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1887 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1888 + "inode %ld: bad block %d", inode->i_ino, block);
1891 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1892 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1893 + ext2_xattr_cache_remove(bh);
1894 + ext2_xattr_free_block(inode, block);
1898 + HDR(bh)->h_refcount = cpu_to_le32(
1899 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
1900 + mark_buffer_dirty(bh);
1901 + if (IS_SYNC(inode)) {
1902 + ll_rw_block(WRITE, 1, &bh);
1903 + wait_on_buffer(bh);
1905 + ext2_xattr_quota_free(inode);
1907 + EXT2_I(inode)->i_file_acl = 0;
1911 + up(&ext2_xattr_sem);
1915 + * ext2_xattr_put_super()
1917 + * This is called when a file system is unmounted.
1920 +ext2_xattr_put_super(struct super_block *sb)
1922 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1923 + mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
1927 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1930 + * ext2_xattr_cache_insert()
1932 + * Create a new entry in the extended attribute cache, and insert
1933 + * it unless such an entry is already in the cache.
1935 + * Returns 0, or a negative error number on failure.
1938 +ext2_xattr_cache_insert(struct buffer_head *bh)
1940 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
1941 + struct mb_cache_entry *ce;
1944 + ce = mb_cache_entry_alloc(ext2_xattr_cache);
1947 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
1949 + mb_cache_entry_free(ce);
1950 + if (error == -EBUSY) {
1951 + ea_bdebug(bh, "already in cache (%d cache entries)",
1952 + atomic_read(&ext2_xattr_cache->c_entry_count));
1956 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
1957 + atomic_read(&ext2_xattr_cache->c_entry_count));
1958 + mb_cache_entry_release(ce);
1964 + * ext2_xattr_cmp()
1966 + * Compare two extended attribute blocks for equality.
1968 + * Returns 0 if the blocks are equal, 1 if they differ, and
1969 + * a negative error number on errors.
1972 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
1973 + struct ext2_xattr_header *header2)
1975 + struct ext2_xattr_entry *entry1, *entry2;
1977 + entry1 = ENTRY(header1+1);
1978 + entry2 = ENTRY(header2+1);
1979 + while (!IS_LAST_ENTRY(entry1)) {
1980 + if (IS_LAST_ENTRY(entry2))
1982 + if (entry1->e_hash != entry2->e_hash ||
1983 + entry1->e_name_len != entry2->e_name_len ||
1984 + entry1->e_value_size != entry2->e_value_size ||
1985 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
1987 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
1989 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
1990 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
1991 + le32_to_cpu(entry1->e_value_size)))
1994 + entry1 = EXT2_XATTR_NEXT(entry1);
1995 + entry2 = EXT2_XATTR_NEXT(entry2);
1997 + if (!IS_LAST_ENTRY(entry2))
2003 + * ext2_xattr_cache_find()
2005 + * Find an identical extended attribute block.
2007 + * Returns a pointer to the block found, or NULL if such a block was
2008 + * not found or an error occurred.
2010 +static struct buffer_head *
2011 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
2013 + __u32 hash = le32_to_cpu(header->h_hash);
2014 + struct mb_cache_entry *ce;
2016 + if (!header->h_hash)
2017 + return NULL; /* never share */
2018 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
2019 + ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
2021 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
2024 + ext2_error(inode->i_sb, "ext2_xattr_cache_find",
2025 + "inode %ld: block %ld read error",
2026 + inode->i_ino, ce->e_block);
2027 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
2028 + EXT2_XATTR_REFCOUNT_MAX) {
2029 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
2030 + le32_to_cpu(HDR(bh)->h_refcount),
2031 + EXT2_XATTR_REFCOUNT_MAX);
2032 + } else if (!ext2_xattr_cmp(header, HDR(bh))) {
2033 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
2034 + mb_cache_entry_release(ce);
2038 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
2044 + * ext2_xattr_cache_remove()
2046 + * Remove the cache entry of a block from the cache. Called when a
2047 + * block becomes invalid.
2050 +ext2_xattr_cache_remove(struct buffer_head *bh)
2052 + struct mb_cache_entry *ce;
2054 + ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
2056 + ea_bdebug(bh, "removing (%d cache entries remaining)",
2057 + atomic_read(&ext2_xattr_cache->c_entry_count)-1);
2058 + mb_cache_entry_free(ce);
2060 + ea_bdebug(bh, "no cache entry");
2063 +#define NAME_HASH_SHIFT 5
2064 +#define VALUE_HASH_SHIFT 16
2067 + * ext2_xattr_hash_entry()
2069 + * Compute the hash of an extended attribute.
2071 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
2072 + struct ext2_xattr_entry *entry)
2075 + char *name = entry->e_name;
2078 + for (n=0; n < entry->e_name_len; n++) {
2079 + hash = (hash << NAME_HASH_SHIFT) ^
2080 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
2084 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
2085 + __u32 *value = (__u32 *)((char *)header +
2086 + le16_to_cpu(entry->e_value_offs));
2087 + for (n = (le32_to_cpu(entry->e_value_size) +
2088 + EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
2089 + hash = (hash << VALUE_HASH_SHIFT) ^
2090 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
2091 + le32_to_cpu(*value++);
2094 + entry->e_hash = cpu_to_le32(hash);
2097 +#undef NAME_HASH_SHIFT
2098 +#undef VALUE_HASH_SHIFT
2100 +#define BLOCK_HASH_SHIFT 16
2103 + * ext2_xattr_rehash()
2105 + * Re-compute the extended attribute hash value after an entry has changed.
2107 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
2108 + struct ext2_xattr_entry *entry)
2110 + struct ext2_xattr_entry *here;
2113 + ext2_xattr_hash_entry(header, entry);
2114 + here = ENTRY(header+1);
2115 + while (!IS_LAST_ENTRY(here)) {
2116 + if (!here->e_hash) {
2117 + /* Block is not shared if an entry's hash value == 0 */
2121 + hash = (hash << BLOCK_HASH_SHIFT) ^
2122 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
2123 + le32_to_cpu(here->e_hash);
2124 + here = EXT2_XATTR_NEXT(here);
2126 + header->h_hash = cpu_to_le32(hash);
2129 +#undef BLOCK_HASH_SHIFT
2132 +init_ext2_xattr(void)
2134 + ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
2135 + sizeof(struct mb_cache_entry) +
2136 + sizeof(struct mb_cache_entry_index), 1, 61);
2137 + if (!ext2_xattr_cache)
2144 +exit_ext2_xattr(void)
2146 + mb_cache_destroy(ext2_xattr_cache);
2149 +#else /* CONFIG_EXT2_FS_XATTR_SHARING */
2152 +init_ext2_xattr(void)
2158 +exit_ext2_xattr(void)
2162 +#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
2163 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
2164 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext2/xattr_user.c 2003-07-12 15:34:44.000000000 -0600
2167 + * linux/fs/ext2/xattr_user.c
2168 + * Handler for extended user attributes.
2170 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2173 +#include <linux/module.h>
2174 +#include <linux/string.h>
2175 +#include <linux/fs.h>
2176 +#include <linux/ext2_fs.h>
2177 +#include <linux/ext2_xattr.h>
2179 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2180 +# include <linux/ext2_acl.h>
2183 +#define XATTR_USER_PREFIX "user."
2186 +ext2_xattr_user_list(char *list, struct inode *inode,
2187 + const char *name, int name_len)
2189 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2191 + if (!test_opt(inode->i_sb, XATTR_USER))
2195 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
2196 + memcpy(list+prefix_len, name, name_len);
2197 + list[prefix_len + name_len] = '\0';
2199 + return prefix_len + name_len + 1;
2203 +ext2_xattr_user_get(struct inode *inode, const char *name,
2204 + void *buffer, size_t size)
2208 + if (strcmp(name, "") == 0)
2210 + if (!test_opt(inode->i_sb, XATTR_USER))
2212 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2213 + error = ext2_permission_locked(inode, MAY_READ);
2215 + error = permission(inode, MAY_READ);
2220 + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2225 +ext2_xattr_user_set(struct inode *inode, const char *name,
2226 + const void *value, size_t size, int flags)
2230 + if (strcmp(name, "") == 0)
2232 + if (!test_opt(inode->i_sb, XATTR_USER))
2234 + if ( !S_ISREG(inode->i_mode) &&
2235 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2237 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2238 + error = ext2_permission_locked(inode, MAY_WRITE);
2240 + error = permission(inode, MAY_WRITE);
2245 + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2246 + value, size, flags);
2249 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2250 + prefix: XATTR_USER_PREFIX,
2251 + list: ext2_xattr_user_list,
2252 + get: ext2_xattr_user_get,
2253 + set: ext2_xattr_user_set,
2257 +init_ext2_xattr_user(void)
2259 + return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2260 + &ext2_xattr_user_handler);
2264 +exit_ext2_xattr_user(void)
2266 + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2267 + &ext2_xattr_user_handler);
2269 --- kernel-2.4.20-6chaos_18_7/fs/ext3/Makefile~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
2270 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/Makefile 2003-07-12 15:34:44.000000000 -0600
2273 -# Makefile for the linux ext2-filesystem routines.
2274 +# Makefile for the linux ext3-filesystem routines.
2276 # Note! Dependencies are done automagically by 'make dep', which also
2277 # removes any old dependencies. DON'T put your own dependencies here
2282 -export-objs := super.o inode.o
2283 +export-objs := ext3-exports.o
2285 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2286 - ioctl.o namei.o super.o symlink.o hash.o
2287 + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2288 obj-m := $(O_TARGET)
2290 +export-objs += xattr.o
2291 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2292 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2294 include $(TOPDIR)/Rules.make
2295 --- kernel-2.4.20-6chaos_18_7/fs/ext3/file.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
2296 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/file.c 2003-07-12 15:34:44.000000000 -0600
2298 #include <linux/locks.h>
2299 #include <linux/jbd.h>
2300 #include <linux/ext3_fs.h>
2301 +#include <linux/ext3_xattr.h>
2302 #include <linux/ext3_jbd.h>
2303 #include <linux/smp_lock.h>
2305 @@ -126,5 +127,9 @@ struct file_operations ext3_file_operati
2306 struct inode_operations ext3_file_inode_operations = {
2307 truncate: ext3_truncate, /* BKL held */
2308 setattr: ext3_setattr, /* BKL held */
2309 + setxattr: ext3_setxattr, /* BKL held */
2310 + getxattr: ext3_getxattr, /* BKL held */
2311 + listxattr: ext3_listxattr, /* BKL held */
2312 + removexattr: ext3_removexattr, /* BKL held */
2315 --- kernel-2.4.20-6chaos_18_7/fs/ext3/ialloc.c~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:30.000000000 -0600
2316 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ialloc.c 2003-07-12 15:34:44.000000000 -0600
2318 #include <linux/jbd.h>
2319 #include <linux/ext3_fs.h>
2320 #include <linux/ext3_jbd.h>
2321 +#include <linux/ext3_xattr.h>
2322 #include <linux/stat.h>
2323 #include <linux/string.h>
2324 #include <linux/locks.h>
2325 @@ -216,6 +217,7 @@ void ext3_free_inode (handle_t *handle,
2326 * as writing the quota to disk may need the lock as well.
2329 + ext3_xattr_delete_inode(handle, inode);
2330 DQUOT_FREE_INODE(inode);
2333 --- kernel-2.4.20-6chaos_18_7/fs/ext3/inode.c~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:30.000000000 -0600
2334 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/inode.c 2003-07-12 15:34:44.000000000 -0600
2337 #undef SEARCH_FROM_ZERO
2340 + * Test whether an inode is a fast symlink.
2342 +static inline int ext3_inode_is_fast_symlink(struct inode *inode)
2344 + int ea_blocks = inode->u.ext3_i.i_file_acl ?
2345 + (inode->i_sb->s_blocksize >> 9) : 0;
2347 + return (S_ISLNK(inode->i_mode) &&
2348 + inode->i_blocks - ea_blocks == 0);
2351 /* The ext3 forget function must perform a revoke if we are freeing data
2352 * which has been journaled. Metadata (eg. indirect blocks) must be
2353 * revoked in all cases.
2355 * still needs to be revoked.
2358 -static int ext3_forget(handle_t *handle, int is_metadata,
2359 +int ext3_forget(handle_t *handle, int is_metadata,
2360 struct inode *inode, struct buffer_head *bh,
2363 @@ -179,9 +191,7 @@ void ext3_delete_inode (struct inode * i
2367 - if (is_bad_inode(inode) ||
2368 - inode->i_ino == EXT3_ACL_IDX_INO ||
2369 - inode->i_ino == EXT3_ACL_DATA_INO)
2370 + if (is_bad_inode(inode))
2374 @@ -1874,6 +1884,8 @@ void ext3_truncate(struct inode * inode)
2375 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
2376 S_ISLNK(inode->i_mode)))
2378 + if (ext3_inode_is_fast_symlink(inode))
2380 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2383 @@ -2021,8 +2033,6 @@ int ext3_get_inode_loc (struct inode *in
2384 struct ext3_group_desc * gdp;
2386 if ((inode->i_ino != EXT3_ROOT_INO &&
2387 - inode->i_ino != EXT3_ACL_IDX_INO &&
2388 - inode->i_ino != EXT3_ACL_DATA_INO &&
2389 inode->i_ino != EXT3_JOURNAL_INO &&
2390 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2391 inode->i_ino > le32_to_cpu(
2392 @@ -2149,10 +2159,7 @@ void ext3_read_inode(struct inode * inod
2396 - if (inode->i_ino == EXT3_ACL_IDX_INO ||
2397 - inode->i_ino == EXT3_ACL_DATA_INO)
2398 - /* Nothing to do */ ;
2399 - else if (S_ISREG(inode->i_mode)) {
2400 + if (S_ISREG(inode->i_mode)) {
2401 inode->i_op = &ext3_file_inode_operations;
2402 inode->i_fop = &ext3_file_operations;
2403 inode->i_mapping->a_ops = &ext3_aops;
2404 @@ -2160,15 +2167,17 @@ void ext3_read_inode(struct inode * inod
2405 inode->i_op = &ext3_dir_inode_operations;
2406 inode->i_fop = &ext3_dir_operations;
2407 } else if (S_ISLNK(inode->i_mode)) {
2408 - if (!inode->i_blocks)
2409 + if (ext3_inode_is_fast_symlink(inode))
2410 inode->i_op = &ext3_fast_symlink_inode_operations;
2412 - inode->i_op = &page_symlink_inode_operations;
2413 + inode->i_op = &ext3_symlink_inode_operations;
2414 inode->i_mapping->a_ops = &ext3_aops;
2418 + inode->i_op = &ext3_special_inode_operations;
2419 init_special_inode(inode, inode->i_mode,
2420 le32_to_cpu(iloc.raw_inode->i_block[0]));
2422 /* inode->i_attr_flags = 0; unused */
2423 if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
2424 /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
2425 --- kernel-2.4.20-6chaos_18_7/fs/ext3/namei.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:43.000000000 -0600
2426 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/namei.c 2003-07-12 15:34:44.000000000 -0600
2428 #include <linux/sched.h>
2429 #include <linux/ext3_fs.h>
2430 #include <linux/ext3_jbd.h>
2431 +#include <linux/ext3_xattr.h>
2432 #include <linux/fcntl.h>
2433 #include <linux/stat.h>
2434 #include <linux/string.h>
2435 @@ -1613,7 +1614,7 @@ static int ext3_mkdir(struct inode * dir
2439 - inode = ext3_new_inode (handle, dir, S_IFDIR);
2440 + inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2441 err = PTR_ERR(inode);
2444 @@ -1621,7 +1622,6 @@ static int ext3_mkdir(struct inode * dir
2445 inode->i_op = &ext3_dir_inode_operations;
2446 inode->i_fop = &ext3_dir_operations;
2447 inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2448 - inode->i_blocks = 0;
2449 dir_block = ext3_bread (handle, inode, 0, 1, &err);
2451 inode->i_nlink--; /* is this nlink == 0? */
2452 @@ -1648,9 +1648,6 @@ static int ext3_mkdir(struct inode * dir
2453 BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2454 ext3_journal_dirty_metadata(handle, dir_block);
2456 - inode->i_mode = S_IFDIR | mode;
2457 - if (dir->i_mode & S_ISGID)
2458 - inode->i_mode |= S_ISGID;
2459 ext3_mark_inode_dirty(handle, inode);
2460 err = ext3_add_entry (handle, dentry, inode);
2462 @@ -2019,7 +2016,7 @@ static int ext3_symlink (struct inode *
2465 if (l > sizeof (EXT3_I(inode)->i_data)) {
2466 - inode->i_op = &page_symlink_inode_operations;
2467 + inode->i_op = &ext3_symlink_inode_operations;
2468 inode->i_mapping->a_ops = &ext3_aops;
2470 * block_symlink() calls back into ext3_prepare/commit_write.
2471 @@ -2245,4 +2242,16 @@ struct inode_operations ext3_dir_inode_o
2472 rmdir: ext3_rmdir, /* BKL held */
2473 mknod: ext3_mknod, /* BKL held */
2474 rename: ext3_rename, /* BKL held */
2475 + setxattr: ext3_setxattr, /* BKL held */
2476 + getxattr: ext3_getxattr, /* BKL held */
2477 + listxattr: ext3_listxattr, /* BKL held */
2478 + removexattr: ext3_removexattr, /* BKL held */
2481 +struct inode_operations ext3_special_inode_operations = {
2482 + setxattr: ext3_setxattr, /* BKL held */
2483 + getxattr: ext3_getxattr, /* BKL held */
2484 + listxattr: ext3_listxattr, /* BKL held */
2485 + removexattr: ext3_removexattr, /* BKL held */
2488 --- kernel-2.4.20-6chaos_18_7/fs/ext3/super.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
2489 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/super.c 2003-07-12 15:34:44.000000000 -0600
2491 #include <linux/jbd.h>
2492 #include <linux/ext3_fs.h>
2493 #include <linux/ext3_jbd.h>
2494 +#include <linux/ext3_xattr.h>
2495 #include <linux/slab.h>
2496 #include <linux/init.h>
2497 #include <linux/locks.h>
2498 @@ -406,6 +407,7 @@ void ext3_put_super (struct super_block
2499 kdev_t j_dev = sbi->s_journal->j_dev;
2502 + ext3_xattr_put_super(sb);
2503 journal_destroy(sbi->s_journal);
2504 if (!(sb->s_flags & MS_RDONLY)) {
2505 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2506 @@ -502,6 +504,7 @@ static int parse_options (char * options
2509 unsigned long *mount_options = &sbi->s_mount_opt;
2511 uid_t *resuid = &sbi->s_resuid;
2512 gid_t *resgid = &sbi->s_resgid;
2514 @@ -514,6 +517,13 @@ static int parse_options (char * options
2515 this_char = strtok (NULL, ",")) {
2516 if ((value = strchr (this_char, '=')) != NULL)
2518 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2519 + if (!strcmp (this_char, "user_xattr"))
2520 + set_opt (*mount_options, XATTR_USER);
2521 + else if (!strcmp (this_char, "nouser_xattr"))
2522 + clear_opt (*mount_options, XATTR_USER);
2525 if (!strcmp (this_char, "bsddf"))
2526 clear_opt (*mount_options, MINIX_DF);
2527 else if (!strcmp (this_char, "nouid32")) {
2528 @@ -931,6 +941,12 @@ struct super_block * ext3_read_super (st
2529 sbi->s_mount_opt = 0;
2530 sbi->s_resuid = EXT3_DEF_RESUID;
2531 sbi->s_resgid = EXT3_DEF_RESGID;
2533 + /* Default extended attribute flags */
2534 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2535 + /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2538 if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2541 @@ -1768,17 +1784,29 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type,
2543 static int __init init_ext3_fs(void)
2545 - return register_filesystem(&ext3_fs_type);
2546 + int error = init_ext3_xattr();
2549 + error = init_ext3_xattr_user();
2552 + error = register_filesystem(&ext3_fs_type);
2556 + exit_ext3_xattr_user();
2558 + exit_ext3_xattr();
2562 static void __exit exit_ext3_fs(void)
2564 unregister_filesystem(&ext3_fs_type);
2565 + exit_ext3_xattr_user();
2566 + exit_ext3_xattr();
2569 -EXPORT_SYMBOL(ext3_force_commit);
2570 -EXPORT_SYMBOL(ext3_bread);
2572 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2573 MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2574 MODULE_LICENSE("GPL");
2575 --- kernel-2.4.20-6chaos_18_7/fs/ext3/symlink.c~linux-2.4.20-xattr-0.8.54-chaos 2002-05-07 15:53:46.000000000 -0600
2576 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/symlink.c 2003-07-12 15:34:44.000000000 -0600
2578 #include <linux/fs.h>
2579 #include <linux/jbd.h>
2580 #include <linux/ext3_fs.h>
2581 +#include <linux/ext3_xattr.h>
2583 static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2585 @@ -33,7 +34,20 @@ static int ext3_follow_link(struct dentr
2586 return vfs_follow_link(nd, s);
2589 +struct inode_operations ext3_symlink_inode_operations = {
2590 + readlink: page_readlink, /* BKL not held. Don't need */
2591 + follow_link: page_follow_link, /* BKL not held. Don't need */
2592 + setxattr: ext3_setxattr, /* BKL held */
2593 + getxattr: ext3_getxattr, /* BKL held */
2594 + listxattr: ext3_listxattr, /* BKL held */
2595 + removexattr: ext3_removexattr, /* BKL held */
2598 struct inode_operations ext3_fast_symlink_inode_operations = {
2599 readlink: ext3_readlink, /* BKL not held. Don't need */
2600 follow_link: ext3_follow_link, /* BKL not held. Don't need */
2601 + setxattr: ext3_setxattr, /* BKL held */
2602 + getxattr: ext3_getxattr, /* BKL held */
2603 + listxattr: ext3_listxattr, /* BKL held */
2604 + removexattr: ext3_removexattr, /* BKL held */
2606 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
2607 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr.c 2003-07-12 15:34:44.000000000 -0600
2610 + * linux/fs/ext3/xattr.c
2612 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2614 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2615 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2616 + * Extended attributes for symlinks and special files added per
2617 + * suggestion of Luka Renko <luka.renko@hermes.si>.
2621 + * Extended attributes are stored on disk blocks allocated outside of
2622 + * any inode. The i_file_acl field is then made to point to this allocated
2623 + * block. If all extended attributes of an inode are identical, these
2624 + * inodes may share the same extended attribute block. Such situations
2625 + * are automatically detected by keeping a cache of recent attribute block
2626 + * numbers and hashes over the block's contents in memory.
2629 + * Extended attribute block layout:
2631 + * +------------------+
2634 + * | entry 2 | | growing downwards
2636 + * | four null bytes |
2639 + * | value 3 | | growing upwards
2641 + * +------------------+
2643 + * The block header is followed by multiple entry descriptors. These entry
2644 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2645 + * byte boundaries. The entry descriptors are sorted by attribute name,
2646 + * so that two extended attribute blocks can be compared efficiently.
2648 + * Attribute values are aligned to the end of the block, stored in
2649 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2650 + * boundaries. No additional gaps are left between them.
2652 + * Locking strategy
2653 + * ----------------
2654 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2655 + * the xattr inode operations are called, so we are guaranteed that only one
2656 + * processes accesses extended attributes of an inode at any time.
2658 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2659 + * only a single process is modifying an extended attribute block, even
2660 + * if the block is shared among inodes.
2662 + * Note for porting to 2.5
2663 + * -----------------------
2664 + * The BKL will no longer be held in the xattr inode operations.
2667 +#include <linux/module.h>
2668 +#include <linux/fs.h>
2669 +#include <linux/locks.h>
2670 +#include <linux/slab.h>
2671 +#include <linux/ext3_jbd.h>
2672 +#include <linux/ext3_fs.h>
2673 +#include <linux/ext3_xattr.h>
2674 +#include <linux/mbcache.h>
2675 +#include <linux/quotaops.h>
2676 +#include <asm/semaphore.h>
2677 +#include <linux/compatmac.h>
2679 +#define EXT3_EA_USER "user."
2681 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2682 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2685 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2686 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2687 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2688 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2690 +#ifdef EXT3_XATTR_DEBUG
2691 +# define ea_idebug(inode, f...) do { \
2692 + printk(KERN_DEBUG "inode %s:%ld: ", \
2693 + kdevname(inode->i_dev), inode->i_ino); \
2697 +# define ea_bdebug(bh, f...) do { \
2698 + printk(KERN_DEBUG "block %s:%ld: ", \
2699 + kdevname(bh->b_dev), bh->b_blocknr); \
2704 +# define ea_idebug(f...)
2705 +# define ea_bdebug(f...)
2708 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2709 + struct ext3_xattr_header *);
2711 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2713 +static int ext3_xattr_cache_insert(struct buffer_head *);
2714 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2715 + struct ext3_xattr_header *);
2716 +static void ext3_xattr_cache_remove(struct buffer_head *);
2717 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2718 + struct ext3_xattr_entry *);
2720 +static struct mb_cache *ext3_xattr_cache;
2723 +# define ext3_xattr_cache_insert(bh) 0
2724 +# define ext3_xattr_cache_find(inode, header) NULL
2725 +# define ext3_xattr_cache_remove(bh) while(0) {}
2726 +# define ext3_xattr_rehash(header, entry) while(0) {}
2730 + * If a file system does not share extended attributes among inodes,
2731 + * we should not need the ext3_xattr_sem semaphore. However, the
2732 + * filesystem may still contain shared blocks, so we always take
2736 +DECLARE_MUTEX(ext3_xattr_sem);
2739 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2740 + int * errp, int force)
2742 + struct super_block *sb = inode->i_sb;
2743 + int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2744 + EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2746 + /* How can we enforce the allocation? */
2747 + int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2750 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2756 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2758 + /* How can we enforce the allocation? */
2760 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2762 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2764 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
2772 +ext3_xattr_quota_free(struct inode *inode)
2774 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2775 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2779 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2780 + unsigned long block)
2782 + ext3_free_blocks(handle, inode, block, 1);
2783 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2787 +# define ext3_xattr_quota_free(inode) \
2788 + DQUOT_FREE_BLOCK(inode, 1)
2789 +# define ext3_xattr_free_block(handle, inode, block) \
2790 + ext3_free_blocks(handle, inode, block, 1)
2793 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2795 +static inline struct buffer_head *
2796 +sb_bread(struct super_block *sb, int block)
2798 + return bread(sb->s_dev, block, sb->s_blocksize);
2801 +static inline struct buffer_head *
2802 +sb_getblk(struct super_block *sb, int block)
2804 + return getblk(sb->s_dev, block, sb->s_blocksize);
2809 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2810 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2813 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2815 + int error = -EINVAL;
2817 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2818 + write_lock(&ext3_handler_lock);
2819 + if (!ext3_xattr_handlers[name_index-1]) {
2820 + ext3_xattr_handlers[name_index-1] = handler;
2823 + write_unlock(&ext3_handler_lock);
2829 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2831 + if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2832 + write_lock(&ext3_handler_lock);
2833 + ext3_xattr_handlers[name_index-1] = NULL;
2834 + write_unlock(&ext3_handler_lock);
2838 +static inline const char *
2839 +strcmp_prefix(const char *a, const char *a_prefix)
2841 + while (*a_prefix && *a == *a_prefix) {
2845 + return *a_prefix ? NULL : a;
2849 + * Decode the extended attribute name, and translate it into
2850 + * the name_index and name suffix.
2852 +static inline struct ext3_xattr_handler *
2853 +ext3_xattr_resolve_name(const char **name)
2855 + struct ext3_xattr_handler *handler = NULL;
2860 + read_lock(&ext3_handler_lock);
2861 + for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2862 + if (ext3_xattr_handlers[i]) {
2863 + const char *n = strcmp_prefix(*name,
2864 + ext3_xattr_handlers[i]->prefix);
2866 + handler = ext3_xattr_handlers[i];
2872 + read_unlock(&ext3_handler_lock);
2876 +static inline struct ext3_xattr_handler *
2877 +ext3_xattr_handler(int name_index)
2879 + struct ext3_xattr_handler *handler = NULL;
2880 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2881 + read_lock(&ext3_handler_lock);
2882 + handler = ext3_xattr_handlers[name_index-1];
2883 + read_unlock(&ext3_handler_lock);
2889 + * Inode operation getxattr()
2891 + * dentry->d_inode->i_sem down
2892 + * BKL held [before 2.5.x]
2895 +ext3_getxattr(struct dentry *dentry, const char *name,
2896 + void *buffer, size_t size)
2898 + struct ext3_xattr_handler *handler;
2899 + struct inode *inode = dentry->d_inode;
2901 + handler = ext3_xattr_resolve_name(&name);
2904 + return handler->get(inode, name, buffer, size);
2908 + * Inode operation listxattr()
2910 + * dentry->d_inode->i_sem down
2911 + * BKL held [before 2.5.x]
2914 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
2916 + return ext3_xattr_list(dentry->d_inode, buffer, size);
2920 + * Inode operation setxattr()
2922 + * dentry->d_inode->i_sem down
2923 + * BKL held [before 2.5.x]
2926 +ext3_setxattr(struct dentry *dentry, const char *name,
2927 + const void *value, size_t size, int flags)
2929 + struct ext3_xattr_handler *handler;
2930 + struct inode *inode = dentry->d_inode;
2933 + value = ""; /* empty EA, do not remove */
2934 + handler = ext3_xattr_resolve_name(&name);
2937 + return handler->set(inode, name, value, size, flags);
2941 + * Inode operation removexattr()
2943 + * dentry->d_inode->i_sem down
2944 + * BKL held [before 2.5.x]
2947 +ext3_removexattr(struct dentry *dentry, const char *name)
2949 + struct ext3_xattr_handler *handler;
2950 + struct inode *inode = dentry->d_inode;
2952 + handler = ext3_xattr_resolve_name(&name);
2955 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
2959 + * ext3_xattr_get()
2961 + * Copy an extended attribute into the buffer
2962 + * provided, or compute the buffer size required.
2963 + * Buffer is NULL to compute the size of the buffer required.
2965 + * Returns a negative error number on failure, or the number of bytes
2966 + * used / required on success.
2969 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
2970 + void *buffer, size_t buffer_size)
2972 + struct buffer_head *bh = NULL;
2973 + struct ext3_xattr_entry *entry;
2974 + unsigned int block, size;
2976 + int name_len, error;
2978 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
2979 + name_index, name, buffer, (long)buffer_size);
2983 + if (!EXT3_I(inode)->i_file_acl)
2985 + block = EXT3_I(inode)->i_file_acl;
2986 + ea_idebug(inode, "reading block %d", block);
2987 + bh = sb_bread(inode->i_sb, block);
2990 + ea_bdebug(bh, "b_count=%d, refcount=%d",
2991 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
2992 + end = bh->b_data + bh->b_size;
2993 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
2994 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
2995 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
2996 + "inode %ld: bad block %d", inode->i_ino, block);
3000 + /* find named attribute */
3001 + name_len = strlen(name);
3004 + if (name_len > 255)
3006 + entry = FIRST_ENTRY(bh);
3007 + while (!IS_LAST_ENTRY(entry)) {
3008 + struct ext3_xattr_entry *next =
3009 + EXT3_XATTR_NEXT(entry);
3010 + if ((char *)next >= end)
3012 + if (name_index == entry->e_name_index &&
3013 + name_len == entry->e_name_len &&
3014 + memcmp(name, entry->e_name, name_len) == 0)
3018 + /* Check the remaining name entries */
3019 + while (!IS_LAST_ENTRY(entry)) {
3020 + struct ext3_xattr_entry *next =
3021 + EXT3_XATTR_NEXT(entry);
3022 + if ((char *)next >= end)
3026 + if (ext3_xattr_cache_insert(bh))
3027 + ea_idebug(inode, "cache insert failed");
3031 + /* check the buffer size */
3032 + if (entry->e_value_block != 0)
3034 + size = le32_to_cpu(entry->e_value_size);
3035 + if (size > inode->i_sb->s_blocksize ||
3036 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
3039 + if (ext3_xattr_cache_insert(bh))
3040 + ea_idebug(inode, "cache insert failed");
3043 + if (size > buffer_size)
3045 + /* return value of attribute */
3046 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
3058 + * ext3_xattr_list()
3060 + * Copy a list of attribute names into the buffer
3061 + * provided, or compute the buffer size required.
3062 + * Buffer is NULL to compute the size of the buffer required.
3064 + * Returns a negative error number on failure, or the number of bytes
3065 + * used / required on success.
3068 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
3070 + struct buffer_head *bh = NULL;
3071 + struct ext3_xattr_entry *entry;
3072 + unsigned int block, size = 0;
3076 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
3077 + buffer, (long)buffer_size);
3079 + if (!EXT3_I(inode)->i_file_acl)
3081 + block = EXT3_I(inode)->i_file_acl;
3082 + ea_idebug(inode, "reading block %d", block);
3083 + bh = sb_bread(inode->i_sb, block);
3086 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3087 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3088 + end = bh->b_data + bh->b_size;
3089 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3090 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3091 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
3092 + "inode %ld: bad block %d", inode->i_ino, block);
3096 + /* compute the size required for the list of attribute names */
3097 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3098 + entry = EXT3_XATTR_NEXT(entry)) {
3099 + struct ext3_xattr_handler *handler;
3100 + struct ext3_xattr_entry *next =
3101 + EXT3_XATTR_NEXT(entry);
3102 + if ((char *)next >= end)
3105 + handler = ext3_xattr_handler(entry->e_name_index);
3107 + size += handler->list(NULL, inode, entry->e_name,
3108 + entry->e_name_len);
3111 + if (ext3_xattr_cache_insert(bh))
3112 + ea_idebug(inode, "cache insert failed");
3118 + if (size > buffer_size)
3122 + /* list the attribute names */
3124 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3125 + entry = EXT3_XATTR_NEXT(entry)) {
3126 + struct ext3_xattr_handler *handler;
3128 + handler = ext3_xattr_handler(entry->e_name_index);
3130 + buf += handler->list(buf, inode, entry->e_name,
3131 + entry->e_name_len);
3142 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3143 + * not set, set it.
3145 +static void ext3_xattr_update_super_block(handle_t *handle,
3146 + struct super_block *sb)
3148 + if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3152 + ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3153 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3154 + EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3156 + EXT3_SB(sb)->s_es->s_feature_compat |=
3157 + cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3159 + ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3164 + * ext3_xattr_set()
3166 + * Create, replace or remove an extended attribute for this inode. Buffer
3167 + * is NULL to remove an existing extended attribute, and non-NULL to
3168 + * either replace an existing extended attribute, or create a new extended
3169 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3170 + * specify that an extended attribute must exist and must not exist
3171 + * previous to the call, respectively.
3173 + * Returns 0, or a negative error number on failure.
3176 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3177 + const char *name, const void *value, size_t value_len, int flags)
3179 + struct super_block *sb = inode->i_sb;
3180 + struct buffer_head *bh = NULL;
3181 + struct ext3_xattr_header *header = NULL;
3182 + struct ext3_xattr_entry *here, *last;
3183 + unsigned int name_len;
3184 + int block = EXT3_I(inode)->i_file_acl;
3185 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
3189 + * header -- Points either into bh, or to a temporarily
3190 + * allocated buffer.
3191 + * here -- The named entry found, or the place for inserting, within
3192 + * the block pointed to by header.
3193 + * last -- Points right after the last named entry within the block
3194 + * pointed to by header.
3195 + * min_offs -- The offset of the first value (values are aligned
3196 + * towards the end of the block).
3197 + * end -- Points right after the block pointed to by header.
3200 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3201 + name_index, name, value, (long)value_len);
3203 + if (IS_RDONLY(inode))
3205 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3207 + if (value == NULL)
3211 + name_len = strlen(name);
3212 + if (name_len > 255 || value_len > sb->s_blocksize)
3214 + down(&ext3_xattr_sem);
3217 + /* The inode already has an extended attribute block. */
3218 + bh = sb_bread(sb, block);
3222 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3223 + atomic_read(&(bh->b_count)),
3224 + le32_to_cpu(HDR(bh)->h_refcount));
3226 + end = bh->b_data + bh->b_size;
3227 + if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3228 + header->h_blocks != cpu_to_le32(1)) {
3229 +bad_block: ext3_error(sb, "ext3_xattr_set",
3230 + "inode %ld: bad block %d", inode->i_ino, block);
3234 + /* Find the named attribute. */
3235 + here = FIRST_ENTRY(bh);
3236 + while (!IS_LAST_ENTRY(here)) {
3237 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3238 + if ((char *)next >= end)
3240 + if (!here->e_value_block && here->e_value_size) {
3241 + int offs = le16_to_cpu(here->e_value_offs);
3242 + if (offs < min_offs)
3245 + not_found = name_index - here->e_name_index;
3247 + not_found = name_len - here->e_name_len;
3249 + not_found = memcmp(name, here->e_name,name_len);
3250 + if (not_found <= 0)
3255 + /* We still need to compute min_offs and last. */
3256 + while (!IS_LAST_ENTRY(last)) {
3257 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3258 + if ((char *)next >= end)
3260 + if (!last->e_value_block && last->e_value_size) {
3261 + int offs = le16_to_cpu(last->e_value_offs);
3262 + if (offs < min_offs)
3268 + /* Check whether we have enough space left. */
3269 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3271 + /* We will use a new extended attribute block. */
3272 + free = sb->s_blocksize -
3273 + sizeof(struct ext3_xattr_header) - sizeof(__u32);
3274 + here = last = NULL; /* avoid gcc uninitialized warning. */
3278 + /* Request to remove a nonexistent attribute? */
3280 + if (flags & XATTR_REPLACE)
3283 + if (value == NULL)
3286 + free -= EXT3_XATTR_LEN(name_len);
3288 + /* Request to create an existing attribute? */
3290 + if (flags & XATTR_CREATE)
3292 + if (!here->e_value_block && here->e_value_size) {
3293 + unsigned int size = le32_to_cpu(here->e_value_size);
3295 + if (le16_to_cpu(here->e_value_offs) + size >
3296 + sb->s_blocksize || size > sb->s_blocksize)
3298 + free += EXT3_XATTR_SIZE(size);
3301 + free -= EXT3_XATTR_SIZE(value_len);
3306 + /* Here we know that we can set the new attribute. */
3309 + if (header->h_refcount == cpu_to_le32(1)) {
3310 + ea_bdebug(bh, "modifying in-place");
3311 + ext3_xattr_cache_remove(bh);
3312 + error = ext3_journal_get_write_access(handle, bh);
3318 + ea_bdebug(bh, "cloning");
3319 + header = kmalloc(bh->b_size, GFP_KERNEL);
3321 + if (header == NULL)
3323 + memcpy(header, HDR(bh), bh->b_size);
3324 + header->h_refcount = cpu_to_le32(1);
3325 + offset = (char *)header - bh->b_data;
3326 + here = ENTRY((char *)here + offset);
3327 + last = ENTRY((char *)last + offset);
3330 + /* Allocate a buffer where we construct the new block. */
3331 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3333 + if (header == NULL)
3335 + memset(header, 0, sb->s_blocksize);
3336 + end = (char *)header + sb->s_blocksize;
3337 + header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3338 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
3339 + last = here = ENTRY(header+1);
3343 + /* Insert the new name. */
3344 + int size = EXT3_XATTR_LEN(name_len);
3345 + int rest = (char *)last - (char *)here;
3346 + memmove((char *)here + size, here, rest);
3347 + memset(here, 0, size);
3348 + here->e_name_index = name_index;
3349 + here->e_name_len = name_len;
3350 + memcpy(here->e_name, name, name_len);
3352 + /* Remove the old value. */
3353 + if (!here->e_value_block && here->e_value_size) {
3354 + char *first_val = (char *)header + min_offs;
3355 + int offs = le16_to_cpu(here->e_value_offs);
3356 + char *val = (char *)header + offs;
3357 + size_t size = EXT3_XATTR_SIZE(
3358 + le32_to_cpu(here->e_value_size));
3359 + memmove(first_val + size, first_val, val - first_val);
3360 + memset(first_val, 0, size);
3361 + here->e_value_offs = 0;
3364 + /* Adjust all value offsets. */
3365 + last = ENTRY(header+1);
3366 + while (!IS_LAST_ENTRY(last)) {
3367 + int o = le16_to_cpu(last->e_value_offs);
3368 + if (!last->e_value_block && o < offs)
3369 + last->e_value_offs =
3370 + cpu_to_le16(o + size);
3371 + last = EXT3_XATTR_NEXT(last);
3374 + if (value == NULL) {
3375 + /* Remove this attribute. */
3376 + if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3377 + /* This block is now empty. */
3378 + error = ext3_xattr_set2(handle, inode, bh,NULL);
3381 + /* Remove the old name. */
3382 + int size = EXT3_XATTR_LEN(name_len);
3383 + last = ENTRY((char *)last - size);
3384 + memmove(here, (char*)here + size,
3385 + (char*)last - (char*)here);
3386 + memset(last, 0, size);
3391 + if (value != NULL) {
3392 + /* Insert the new value. */
3393 + here->e_value_size = cpu_to_le32(value_len);
3395 + size_t size = EXT3_XATTR_SIZE(value_len);
3396 + char *val = (char *)header + min_offs - size;
3397 + here->e_value_offs =
3398 + cpu_to_le16((char *)val - (char *)header);
3399 + memset(val + size - EXT3_XATTR_PAD, 0,
3400 + EXT3_XATTR_PAD); /* Clear the pad bytes. */
3401 + memcpy(val, value, value_len);
3404 + ext3_xattr_rehash(header, here);
3406 + error = ext3_xattr_set2(handle, inode, bh, header);
3410 + if (!(bh && header == HDR(bh)))
3412 + up(&ext3_xattr_sem);
3418 + * Second half of ext3_xattr_set(): Update the file system.
3421 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3422 + struct buffer_head *old_bh, struct ext3_xattr_header *header)
3424 + struct super_block *sb = inode->i_sb;
3425 + struct buffer_head *new_bh = NULL;
3429 + new_bh = ext3_xattr_cache_find(inode, header);
3432 + * We found an identical block in the cache.
3433 + * The old block will be released after updating
3436 + ea_bdebug(old_bh, "reusing block %ld",
3437 + new_bh->b_blocknr);
3440 + if (ext3_xattr_quota_alloc(inode, 1))
3443 + error = ext3_journal_get_write_access(handle, new_bh);
3446 + HDR(new_bh)->h_refcount = cpu_to_le32(
3447 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3448 + ea_bdebug(new_bh, "refcount now=%d",
3449 + le32_to_cpu(HDR(new_bh)->h_refcount));
3450 + } else if (old_bh && header == HDR(old_bh)) {
3451 + /* Keep this block. */
3453 + (void)ext3_xattr_cache_insert(new_bh);
3455 + /* We need to allocate a new block */
3456 + int force = EXT3_I(inode)->i_file_acl != 0;
3457 + int block = ext3_xattr_new_block(handle, inode,
3461 + ea_idebug(inode, "creating block %d", block);
3463 + new_bh = sb_getblk(sb, block);
3465 +getblk_failed: ext3_xattr_free_block(handle, inode, block);
3469 + lock_buffer(new_bh);
3470 + error = ext3_journal_get_create_access(handle, new_bh);
3472 + unlock_buffer(new_bh);
3473 + goto getblk_failed;
3475 + memcpy(new_bh->b_data, header, new_bh->b_size);
3476 + mark_buffer_uptodate(new_bh, 1);
3477 + unlock_buffer(new_bh);
3478 + (void)ext3_xattr_cache_insert(new_bh);
3480 + ext3_xattr_update_super_block(handle, sb);
3482 + error = ext3_journal_dirty_metadata(handle, new_bh);
3487 + /* Update the inode. */
3488 + EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3489 + inode->i_ctime = CURRENT_TIME;
3490 + ext3_mark_inode_dirty(handle, inode);
3491 + if (IS_SYNC(inode))
3492 + handle->h_sync = 1;
3495 + if (old_bh && old_bh != new_bh) {
3497 + * If there was an old block, and we are not still using it,
3498 + * we now release the old block.
3500 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3502 + error = ext3_journal_get_write_access(handle, old_bh);
3505 + if (refcount == 1) {
3506 + /* Free the old block. */
3507 + ea_bdebug(old_bh, "freeing");
3508 + ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3510 + /* ext3_forget() calls bforget() for us, but we
3511 + let our caller release old_bh, so we need to
3512 + duplicate the handle before. */
3514 + ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3516 + /* Decrement the refcount only. */
3518 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3519 + ext3_xattr_quota_free(inode);
3520 + ext3_journal_dirty_metadata(handle, old_bh);
3521 + ea_bdebug(old_bh, "refcount now=%d", refcount);
3526 + if (old_bh != new_bh)
3533 + * ext3_xattr_delete_inode()
3535 + * Free extended attribute resources associated with this inode. This
3536 + * is called immediately before an inode is freed.
3539 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3541 + struct buffer_head *bh;
3542 + unsigned int block = EXT3_I(inode)->i_file_acl;
3546 + down(&ext3_xattr_sem);
3548 + bh = sb_bread(inode->i_sb, block);
3550 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3551 + "inode %ld: block %d read error", inode->i_ino, block);
3554 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3555 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3556 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3557 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3558 + "inode %ld: bad block %d", inode->i_ino, block);
3561 + ext3_journal_get_write_access(handle, bh);
3562 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3563 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3564 + ext3_xattr_cache_remove(bh);
3565 + ext3_xattr_free_block(handle, inode, block);
3566 + ext3_forget(handle, 1, inode, bh, block);
3569 + HDR(bh)->h_refcount = cpu_to_le32(
3570 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
3571 + ext3_journal_dirty_metadata(handle, bh);
3572 + if (IS_SYNC(inode))
3573 + handle->h_sync = 1;
3574 + ext3_xattr_quota_free(inode);
3576 + EXT3_I(inode)->i_file_acl = 0;
3580 + up(&ext3_xattr_sem);
3584 + * ext3_xattr_put_super()
3586 + * This is called when a file system is unmounted.
3589 +ext3_xattr_put_super(struct super_block *sb)
3591 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3592 + mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3596 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3599 + * ext3_xattr_cache_insert()
3601 + * Create a new entry in the extended attribute cache, and insert
3602 + * it unless such an entry is already in the cache.
3604 + * Returns 0, or a negative error number on failure.
3607 +ext3_xattr_cache_insert(struct buffer_head *bh)
3609 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3610 + struct mb_cache_entry *ce;
3613 + ce = mb_cache_entry_alloc(ext3_xattr_cache);
3616 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3618 + mb_cache_entry_free(ce);
3619 + if (error == -EBUSY) {
3620 + ea_bdebug(bh, "already in cache (%d cache entries)",
3621 + atomic_read(&ext3_xattr_cache->c_entry_count));
3625 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3626 + atomic_read(&ext3_xattr_cache->c_entry_count));
3627 + mb_cache_entry_release(ce);
3633 + * ext3_xattr_cmp()
3635 + * Compare two extended attribute blocks for equality.
3637 + * Returns 0 if the blocks are equal, 1 if they differ, and
3638 + * a negative error number on errors.
3641 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3642 + struct ext3_xattr_header *header2)
3644 + struct ext3_xattr_entry *entry1, *entry2;
3646 + entry1 = ENTRY(header1+1);
3647 + entry2 = ENTRY(header2+1);
3648 + while (!IS_LAST_ENTRY(entry1)) {
3649 + if (IS_LAST_ENTRY(entry2))
3651 + if (entry1->e_hash != entry2->e_hash ||
3652 + entry1->e_name_len != entry2->e_name_len ||
3653 + entry1->e_value_size != entry2->e_value_size ||
3654 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3656 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3658 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3659 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3660 + le32_to_cpu(entry1->e_value_size)))
3663 + entry1 = EXT3_XATTR_NEXT(entry1);
3664 + entry2 = EXT3_XATTR_NEXT(entry2);
3666 + if (!IS_LAST_ENTRY(entry2))
3672 + * ext3_xattr_cache_find()
3674 + * Find an identical extended attribute block.
3676 + * Returns a pointer to the block found, or NULL if such a block was
3677 + * not found or an error occurred.
3679 +static struct buffer_head *
3680 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3682 + __u32 hash = le32_to_cpu(header->h_hash);
3683 + struct mb_cache_entry *ce;
3685 + if (!header->h_hash)
3686 + return NULL; /* never share */
3687 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3688 + ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3690 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3693 + ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3694 + "inode %ld: block %ld read error",
3695 + inode->i_ino, ce->e_block);
3696 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3697 + EXT3_XATTR_REFCOUNT_MAX) {
3698 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3699 + le32_to_cpu(HDR(bh)->h_refcount),
3700 + EXT3_XATTR_REFCOUNT_MAX);
3701 + } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3702 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3703 + mb_cache_entry_release(ce);
3707 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3713 + * ext3_xattr_cache_remove()
3715 + * Remove the cache entry of a block from the cache. Called when a
3716 + * block becomes invalid.
3719 +ext3_xattr_cache_remove(struct buffer_head *bh)
3721 + struct mb_cache_entry *ce;
3723 + ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3725 + ea_bdebug(bh, "removing (%d cache entries remaining)",
3726 + atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3727 + mb_cache_entry_free(ce);
3729 + ea_bdebug(bh, "no cache entry");
3732 +#define NAME_HASH_SHIFT 5
3733 +#define VALUE_HASH_SHIFT 16
3736 + * ext3_xattr_hash_entry()
3738 + * Compute the hash of an extended attribute.
3740 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3741 + struct ext3_xattr_entry *entry)
3744 + char *name = entry->e_name;
3747 + for (n=0; n < entry->e_name_len; n++) {
3748 + hash = (hash << NAME_HASH_SHIFT) ^
3749 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3753 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3754 + __u32 *value = (__u32 *)((char *)header +
3755 + le16_to_cpu(entry->e_value_offs));
3756 + for (n = (le32_to_cpu(entry->e_value_size) +
3757 + EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3758 + hash = (hash << VALUE_HASH_SHIFT) ^
3759 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3760 + le32_to_cpu(*value++);
3763 + entry->e_hash = cpu_to_le32(hash);
3766 +#undef NAME_HASH_SHIFT
3767 +#undef VALUE_HASH_SHIFT
3769 +#define BLOCK_HASH_SHIFT 16
3772 + * ext3_xattr_rehash()
3774 + * Re-compute the extended attribute hash value after an entry has changed.
3776 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3777 + struct ext3_xattr_entry *entry)
3779 + struct ext3_xattr_entry *here;
3782 + ext3_xattr_hash_entry(header, entry);
3783 + here = ENTRY(header+1);
3784 + while (!IS_LAST_ENTRY(here)) {
3785 + if (!here->e_hash) {
3786 + /* Block is not shared if an entry's hash value == 0 */
3790 + hash = (hash << BLOCK_HASH_SHIFT) ^
3791 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3792 + le32_to_cpu(here->e_hash);
3793 + here = EXT3_XATTR_NEXT(here);
3795 + header->h_hash = cpu_to_le32(hash);
3798 +#undef BLOCK_HASH_SHIFT
3801 +init_ext3_xattr(void)
3803 + ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3804 + sizeof(struct mb_cache_entry) +
3805 + sizeof(struct mb_cache_entry_index), 1, 61);
3806 + if (!ext3_xattr_cache)
3813 +exit_ext3_xattr(void)
3815 + if (ext3_xattr_cache)
3816 + mb_cache_destroy(ext3_xattr_cache);
3817 + ext3_xattr_cache = NULL;
3820 +#else /* CONFIG_EXT3_FS_XATTR_SHARING */
3823 +init_ext3_xattr(void)
3829 +exit_ext3_xattr(void)
3833 +#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
3834 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
3835 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/xattr_user.c 2003-07-12 15:34:44.000000000 -0600
3838 + * linux/fs/ext3/xattr_user.c
3839 + * Handler for extended user attributes.
3841 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3844 +#include <linux/module.h>
3845 +#include <linux/string.h>
3846 +#include <linux/fs.h>
3847 +#include <linux/ext3_jbd.h>
3848 +#include <linux/ext3_fs.h>
3849 +#include <linux/ext3_xattr.h>
3851 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3852 +# include <linux/ext3_acl.h>
3855 +#define XATTR_USER_PREFIX "user."
3858 +ext3_xattr_user_list(char *list, struct inode *inode,
3859 + const char *name, int name_len)
3861 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3863 + if (!test_opt(inode->i_sb, XATTR_USER))
3867 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
3868 + memcpy(list+prefix_len, name, name_len);
3869 + list[prefix_len + name_len] = '\0';
3871 + return prefix_len + name_len + 1;
3875 +ext3_xattr_user_get(struct inode *inode, const char *name,
3876 + void *buffer, size_t size)
3880 + if (strcmp(name, "") == 0)
3882 + if (!test_opt(inode->i_sb, XATTR_USER))
3884 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3885 + error = ext3_permission_locked(inode, MAY_READ);
3887 + error = permission(inode, MAY_READ);
3892 + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
3897 +ext3_xattr_user_set(struct inode *inode, const char *name,
3898 + const void *value, size_t size, int flags)
3903 + if (strcmp(name, "") == 0)
3905 + if (!test_opt(inode->i_sb, XATTR_USER))
3907 + if ( !S_ISREG(inode->i_mode) &&
3908 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
3910 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3911 + error = ext3_permission_locked(inode, MAY_WRITE);
3913 + error = permission(inode, MAY_WRITE);
3918 + handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
3919 + if (IS_ERR(handle))
3920 + return PTR_ERR(handle);
3921 + error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
3922 + value, size, flags);
3923 + ext3_journal_stop(handle, inode);
3928 +struct ext3_xattr_handler ext3_xattr_user_handler = {
3929 + prefix: XATTR_USER_PREFIX,
3930 + list: ext3_xattr_user_list,
3931 + get: ext3_xattr_user_get,
3932 + set: ext3_xattr_user_set,
3936 +init_ext3_xattr_user(void)
3938 + return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
3939 + &ext3_xattr_user_handler);
3943 +exit_ext3_xattr_user(void)
3945 + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
3946 + &ext3_xattr_user_handler);
3948 --- kernel-2.4.20-6chaos_18_7/fs/jfs/jfs_xattr.h~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:11.000000000 -0700
3949 +++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/jfs_xattr.h 2003-07-12 15:34:44.000000000 -0600
3950 @@ -52,8 +52,10 @@ struct jfs_ea_list {
3951 #define END_EALIST(ealist) \
3952 ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
3954 -extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
3955 -extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
3956 +extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
3958 +extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
3960 extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
3961 extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
3962 extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
3963 --- kernel-2.4.20-6chaos_18_7/fs/jfs/xattr.c~linux-2.4.20-xattr-0.8.54-chaos 2003-02-14 15:59:11.000000000 -0700
3964 +++ kernel-2.4.20-6chaos_18_7-braam/fs/jfs/xattr.c 2003-07-12 15:34:44.000000000 -0600
3965 @@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s
3968 static int can_set_xattr(struct inode *inode, const char *name,
3969 - void *value, size_t value_len)
3970 + const void *value, size_t value_len)
3972 if (IS_RDONLY(inode))
3974 @@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i
3975 return permission(inode, MAY_WRITE);
3978 -int __jfs_setxattr(struct inode *inode, const char *name, void *value,
3979 +int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
3980 size_t value_len, int flags)
3982 struct jfs_ea_list *ealist;
3983 @@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode,
3987 -int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
3988 +int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
3989 size_t value_len, int flags)
3991 if (value == NULL) { /* empty EA, do not remove */
3992 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
3993 +++ kernel-2.4.20-6chaos_18_7-braam/fs/mbcache.c 2003-07-12 15:34:44.000000000 -0600
3996 + * linux/fs/mbcache.c
3997 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4001 + * Filesystem Meta Information Block Cache (mbcache)
4003 + * The mbcache caches blocks of block devices that need to be located
4004 + * by their device/block number, as well as by other criteria (such
4005 + * as the block's contents).
4007 + * There can only be one cache entry in a cache per device and block number.
4008 + * Additional indexes need not be unique in this sense. The number of
4009 + * additional indexes (=other criteria) can be hardwired at compile time
4010 + * or specified at cache create time.
4012 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
4013 + * in the cache. A valid entry is in the main hash tables of the cache,
4014 + * and may also be in the lru list. An invalid entry is not in any hashes
4017 + * A valid cache entry is only in the lru list if no handles refer to it.
4018 + * Invalid cache entries will be freed when the last handle to the cache
4019 + * entry is released. Entries that cannot be freed immediately are put
4020 + * back on the lru list.
4023 +#include <linux/kernel.h>
4024 +#include <linux/module.h>
4026 +#include <linux/fs.h>
4027 +#include <linux/slab.h>
4028 +#include <linux/sched.h>
4029 +#include <linux/cache_def.h>
4030 +#include <linux/version.h>
4031 +#include <linux/init.h>
4032 +#include <linux/mbcache.h>
4035 +#ifdef MB_CACHE_DEBUG
4036 +# define mb_debug(f...) do { \
4037 + printk(KERN_DEBUG f); \
4040 +#define mb_assert(c) do { if (!(c)) \
4041 + printk(KERN_ERR "assertion " #c " failed\n"); \
4044 +# define mb_debug(f...) do { } while(0)
4045 +# define mb_assert(c) do { } while(0)
4047 +#define mb_error(f...) do { \
4048 + printk(KERN_ERR f); \
4052 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
4053 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
4054 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4055 +MODULE_LICENSE("GPL");
4058 +EXPORT_SYMBOL(mb_cache_create);
4059 +EXPORT_SYMBOL(mb_cache_shrink);
4060 +EXPORT_SYMBOL(mb_cache_destroy);
4061 +EXPORT_SYMBOL(mb_cache_entry_alloc);
4062 +EXPORT_SYMBOL(mb_cache_entry_insert);
4063 +EXPORT_SYMBOL(mb_cache_entry_release);
4064 +EXPORT_SYMBOL(mb_cache_entry_takeout);
4065 +EXPORT_SYMBOL(mb_cache_entry_free);
4066 +EXPORT_SYMBOL(mb_cache_entry_dup);
4067 +EXPORT_SYMBOL(mb_cache_entry_get);
4068 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4069 +EXPORT_SYMBOL(mb_cache_entry_find_first);
4070 +EXPORT_SYMBOL(mb_cache_entry_find_next);
4075 + * Global data: list of all mbcache's, lru list, and a spinlock for
4076 + * accessing cache data structures on SMP machines. The lru list is
4077 + * global across all mbcaches.
4080 +static LIST_HEAD(mb_cache_list);
4081 +static LIST_HEAD(mb_cache_lru_list);
4082 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
4085 +mb_cache_indexes(struct mb_cache *cache)
4087 +#ifdef MB_CACHE_INDEXES_COUNT
4088 + return MB_CACHE_INDEXES_COUNT;
4090 + return cache->c_indexes_count;
4095 + * What the mbcache registers as to get shrunk dynamically.
4099 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
4101 +static struct cache_definition mb_cache_definition = {
4103 + mb_cache_memory_pressure
4108 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4110 + return !list_empty(&ce->e_block_list);
4115 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4119 + if (__mb_cache_entry_is_hashed(ce)) {
4120 + list_del_init(&ce->e_block_list);
4121 + for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4122 + list_del(&ce->e_indexes[n].o_list);
4128 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4130 + struct mb_cache *cache = ce->e_cache;
4132 + mb_assert(atomic_read(&ce->e_used) == 0);
4133 + if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4134 + /* free failed -- put back on the lru list
4135 + for freeing later. */
4136 + spin_lock(&mb_cache_spinlock);
4137 + list_add(&ce->e_lru_list, &mb_cache_lru_list);
4138 + spin_unlock(&mb_cache_spinlock);
4140 + kmem_cache_free(cache->c_entry_cache, ce);
4141 + atomic_dec(&cache->c_entry_count);
4147 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4149 + if (atomic_dec_and_test(&ce->e_used)) {
4150 + if (__mb_cache_entry_is_hashed(ce))
4151 + list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4153 + spin_unlock(&mb_cache_spinlock);
4154 + __mb_cache_entry_forget(ce, GFP_KERNEL);
4158 + spin_unlock(&mb_cache_spinlock);
4163 + * mb_cache_memory_pressure() memory pressure callback
4165 + * This function is called by the kernel memory management when memory
4168 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4169 + * @gfp_mask: (ignored)
4172 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4174 + LIST_HEAD(free_list);
4175 + struct list_head *l, *ltmp;
4178 + spin_lock(&mb_cache_spinlock);
4179 + list_for_each(l, &mb_cache_list) {
4180 + struct mb_cache *cache =
4181 + list_entry(l, struct mb_cache, c_cache_list);
4182 + mb_debug("cache %s (%d)", cache->c_name,
4183 + atomic_read(&cache->c_entry_count));
4184 + count += atomic_read(&cache->c_entry_count);
4186 + mb_debug("trying to free %d of %d entries",
4187 + count / (priority ? priority : 1), count);
4189 + count /= priority;
4190 + while (count-- && !list_empty(&mb_cache_lru_list)) {
4191 + struct mb_cache_entry *ce =
4192 + list_entry(mb_cache_lru_list.next,
4193 + struct mb_cache_entry, e_lru_list);
4194 + list_del(&ce->e_lru_list);
4195 + __mb_cache_entry_unhash(ce);
4196 + list_add_tail(&ce->e_lru_list, &free_list);
4198 + spin_unlock(&mb_cache_spinlock);
4199 + list_for_each_safe(l, ltmp, &free_list) {
4200 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4201 + e_lru_list), gfp_mask);
4207 + * mb_cache_create() create a new cache
4209 + * All entries in one cache are equal size. Cache entries may be from
4210 + * multiple devices. If this is the first mbcache created, registers
4211 + * the cache with kernel memory management. Returns NULL if no more
4212 + * memory was available.
4214 + * @name: name of the cache (informal)
4215 + * @cache_op: contains the callback called when freeing a cache entry
4216 + * @entry_size: The size of a cache entry, including
4217 + * struct mb_cache_entry
4218 + * @indexes_count: number of additional indexes in the cache. Must equal
4219 + * MB_CACHE_INDEXES_COUNT if the number of indexes is
4221 + * @bucket_count: number of hash buckets
4224 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4225 + size_t entry_size, int indexes_count, int bucket_count)
4228 + struct mb_cache *cache = NULL;
4230 + if(entry_size < sizeof(struct mb_cache_entry) +
4231 + indexes_count * sizeof(struct mb_cache_entry_index))
4234 + MOD_INC_USE_COUNT;
4235 + cache = kmalloc(sizeof(struct mb_cache) +
4236 + indexes_count * sizeof(struct list_head), GFP_KERNEL);
4239 + cache->c_name = name;
4240 + cache->c_op.free = NULL;
4242 + cache->c_op.free = cache_op->free;
4243 + atomic_set(&cache->c_entry_count, 0);
4244 + cache->c_bucket_count = bucket_count;
4245 +#ifdef MB_CACHE_INDEXES_COUNT
4246 + mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4248 + cache->c_indexes_count = indexes_count;
4250 + cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4252 + if (!cache->c_block_hash)
4254 + for (n=0; n<bucket_count; n++)
4255 + INIT_LIST_HEAD(&cache->c_block_hash[n]);
4256 + for (m=0; m<indexes_count; m++) {
4257 + cache->c_indexes_hash[m] = kmalloc(bucket_count *
4258 + sizeof(struct list_head),
4260 + if (!cache->c_indexes_hash[m])
4262 + for (n=0; n<bucket_count; n++)
4263 + INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4265 + cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4266 + 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4267 + if (!cache->c_entry_cache)
4270 + spin_lock(&mb_cache_spinlock);
4271 + list_add(&cache->c_cache_list, &mb_cache_list);
4272 + spin_unlock(&mb_cache_spinlock);
4278 + kfree(cache->c_indexes_hash[m]);
4279 + if (cache->c_block_hash)
4280 + kfree(cache->c_block_hash);
4283 + MOD_DEC_USE_COUNT;
4289 + * mb_cache_shrink()
4291 + * Removes all cache entires of a device from the cache. All cache entries
4292 + * currently in use cannot be freed, and thus remain in the cache.
4294 + * @cache: which cache to shrink
4295 + * @dev: which device's cache entries to shrink
4298 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4300 + LIST_HEAD(free_list);
4301 + struct list_head *l, *ltmp;
4303 + spin_lock(&mb_cache_spinlock);
4304 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4305 + struct mb_cache_entry *ce =
4306 + list_entry(l, struct mb_cache_entry, e_lru_list);
4307 + if (ce->e_dev == dev) {
4308 + list_del(&ce->e_lru_list);
4309 + list_add_tail(&ce->e_lru_list, &free_list);
4310 + __mb_cache_entry_unhash(ce);
4313 + spin_unlock(&mb_cache_spinlock);
4314 + list_for_each_safe(l, ltmp, &free_list) {
4315 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4316 + e_lru_list), GFP_KERNEL);
4322 + * mb_cache_destroy()
4324 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4325 + * and then destroys it. If this was the last mbcache, un-registers the
4326 + * mbcache from kernel memory management.
4329 +mb_cache_destroy(struct mb_cache *cache)
4331 + LIST_HEAD(free_list);
4332 + struct list_head *l, *ltmp;
4335 + spin_lock(&mb_cache_spinlock);
4336 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4337 + struct mb_cache_entry *ce =
4338 + list_entry(l, struct mb_cache_entry, e_lru_list);
4339 + if (ce->e_cache == cache) {
4340 + list_del(&ce->e_lru_list);
4341 + list_add_tail(&ce->e_lru_list, &free_list);
4342 + __mb_cache_entry_unhash(ce);
4345 + list_del(&cache->c_cache_list);
4346 + spin_unlock(&mb_cache_spinlock);
4347 + list_for_each_safe(l, ltmp, &free_list) {
4348 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4349 + e_lru_list), GFP_KERNEL);
4352 + if (atomic_read(&cache->c_entry_count) > 0) {
4353 + mb_error("cache %s: %d orphaned entries",
4355 + atomic_read(&cache->c_entry_count));
4358 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4359 + /* We don't have kmem_cache_destroy() in 2.2.x */
4360 + kmem_cache_shrink(cache->c_entry_cache);
4362 + kmem_cache_destroy(cache->c_entry_cache);
4364 + for (n=0; n < mb_cache_indexes(cache); n++)
4365 + kfree(cache->c_indexes_hash[n]);
4366 + kfree(cache->c_block_hash);
4369 + MOD_DEC_USE_COUNT;
4374 + * mb_cache_entry_alloc()
4376 + * Allocates a new cache entry. The new entry will not be valid initially,
4377 + * and thus cannot be looked up yet. It should be filled with data, and
4378 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4379 + * if no more memory was available.
4381 +struct mb_cache_entry *
4382 +mb_cache_entry_alloc(struct mb_cache *cache)
4384 + struct mb_cache_entry *ce;
4386 + atomic_inc(&cache->c_entry_count);
4387 + ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4389 + INIT_LIST_HEAD(&ce->e_lru_list);
4390 + INIT_LIST_HEAD(&ce->e_block_list);
4391 + ce->e_cache = cache;
4392 + atomic_set(&ce->e_used, 1);
4399 + * mb_cache_entry_insert()
4401 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4402 + * the cache. After this, the cache entry can be looked up, but is not yet
4403 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4404 + * success, or -EBUSY if a cache entry for that device + inode exists
4405 + * already (this may happen after a failed lookup, if another process has
4406 + * inserted the same cache entry in the meantime).
4408 + * @dev: device the cache entry belongs to
4409 + * @block: block number
4410 + * @keys: array of additional keys. There must be indexes_count entries
4411 + * in the array (as specified when creating the cache).
4414 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4415 + unsigned long block, unsigned int keys[])
4417 + struct mb_cache *cache = ce->e_cache;
4418 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4419 + struct list_head *l;
4420 + int error = -EBUSY, n;
4422 + spin_lock(&mb_cache_spinlock);
4423 + list_for_each(l, &cache->c_block_hash[bucket]) {
4424 + struct mb_cache_entry *ce =
4425 + list_entry(l, struct mb_cache_entry, e_block_list);
4426 + if (ce->e_dev == dev && ce->e_block == block)
4429 + __mb_cache_entry_unhash(ce);
4431 + ce->e_block = block;
4432 + list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4433 + for (n=0; n<mb_cache_indexes(cache); n++) {
4434 + ce->e_indexes[n].o_key = keys[n];
4435 + bucket = keys[n] % cache->c_bucket_count;
4436 + list_add(&ce->e_indexes[n].o_list,
4437 + &cache->c_indexes_hash[n][bucket]);
4440 + spin_unlock(&mb_cache_spinlock);
4446 + * mb_cache_entry_release()
4448 + * Release a handle to a cache entry. When the last handle to a cache entry
4449 + * is released it is either freed (if it is invalid) or otherwise inserted
4450 + * in to the lru list.
4453 +mb_cache_entry_release(struct mb_cache_entry *ce)
4455 + spin_lock(&mb_cache_spinlock);
4456 + __mb_cache_entry_release_unlock(ce);
4461 + * mb_cache_entry_takeout()
4463 + * Take a cache entry out of the cache, making it invalid. The entry can later
4464 + * be re-inserted using mb_cache_entry_insert(), or released using
4465 + * mb_cache_entry_release().
4468 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4470 + spin_lock(&mb_cache_spinlock);
4471 + mb_assert(list_empty(&ce->e_lru_list));
4472 + __mb_cache_entry_unhash(ce);
4473 + spin_unlock(&mb_cache_spinlock);
4478 + * mb_cache_entry_free()
4480 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4481 + * mb_cache_entry_release().
4484 +mb_cache_entry_free(struct mb_cache_entry *ce)
4486 + spin_lock(&mb_cache_spinlock);
4487 + mb_assert(list_empty(&ce->e_lru_list));
4488 + __mb_cache_entry_unhash(ce);
4489 + __mb_cache_entry_release_unlock(ce);
4494 + * mb_cache_entry_dup()
4496 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4497 + * itself). After the call, both the old and the new handle must be released.
4499 +struct mb_cache_entry *
4500 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4502 + atomic_inc(&ce->e_used);
4508 + * mb_cache_entry_get()
4510 + * Get a cache entry by device / block number. (There can only be one entry
4511 + * in the cache per device and block.) Returns NULL if no such cache entry
4514 +struct mb_cache_entry *
4515 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4517 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4518 + struct list_head *l;
4519 + struct mb_cache_entry *ce;
4521 + spin_lock(&mb_cache_spinlock);
4522 + list_for_each(l, &cache->c_block_hash[bucket]) {
4523 + ce = list_entry(l, struct mb_cache_entry, e_block_list);
4524 + if (ce->e_dev == dev && ce->e_block == block) {
4525 + if (!list_empty(&ce->e_lru_list))
4526 + list_del_init(&ce->e_lru_list);
4527 + atomic_inc(&ce->e_used);
4534 + spin_unlock(&mb_cache_spinlock);
4538 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4540 +static struct mb_cache_entry *
4541 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4542 + int index, kdev_t dev, unsigned int key)
4544 + while (l != head) {
4545 + struct mb_cache_entry *ce =
4546 + list_entry(l, struct mb_cache_entry,
4547 + e_indexes[index].o_list);
4548 + if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4549 + if (!list_empty(&ce->e_lru_list))
4550 + list_del_init(&ce->e_lru_list);
4551 + atomic_inc(&ce->e_used);
4561 + * mb_cache_entry_find_first()
4563 + * Find the first cache entry on a given device with a certain key in
4564 + * an additional index. Additonal matches can be found with
4565 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4567 + * @cache: the cache to search
4568 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4569 + * @dev: the device the cache entry should belong to
4570 + * @key: the key in the index
4572 +struct mb_cache_entry *
4573 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4576 + unsigned int bucket = key % cache->c_bucket_count;
4577 + struct list_head *l;
4578 + struct mb_cache_entry *ce;
4580 + mb_assert(index < mb_cache_indexes(cache));
4581 + spin_lock(&mb_cache_spinlock);
4582 + l = cache->c_indexes_hash[index][bucket].next;
4583 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4585 + spin_unlock(&mb_cache_spinlock);
4591 + * mb_cache_entry_find_next()
4593 + * Find the next cache entry on a given device with a certain key in an
4594 + * additional index. Returns NULL if no match could be found. The previous
4595 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4596 + * be called like this:
4598 + * entry = mb_cache_entry_find_first();
4601 + * entry = mb_cache_entry_find_next(entry, ...);
4604 + * @prev: The previous match
4605 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4606 + * @dev: the device the cache entry should belong to
4607 + * @key: the key in the index
4609 +struct mb_cache_entry *
4610 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4613 + struct mb_cache *cache = prev->e_cache;
4614 + unsigned int bucket = key % cache->c_bucket_count;
4615 + struct list_head *l;
4616 + struct mb_cache_entry *ce;
4618 + mb_assert(index < mb_cache_indexes(cache));
4619 + spin_lock(&mb_cache_spinlock);
4620 + l = prev->e_indexes[index].o_list.next;
4621 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4623 + __mb_cache_entry_release_unlock(prev);
4627 +#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4629 +static int __init init_mbcache(void)
4631 + register_cache(&mb_cache_definition);
4635 +static void __exit exit_mbcache(void)
4637 + unregister_cache(&mb_cache_definition);
4640 +module_init(init_mbcache)
4641 +module_exit(exit_mbcache)
4643 --- kernel-2.4.20-6chaos_18_7/include/asm-arm/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:14:42.000000000 -0600
4644 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-arm/unistd.h 2003-07-12 15:34:44.000000000 -0600
4646 #define __NR_security (__NR_SYSCALL_BASE+223)
4647 #define __NR_gettid (__NR_SYSCALL_BASE+224)
4648 #define __NR_readahead (__NR_SYSCALL_BASE+225)
4649 -#if 0 /* allocated in 2.5 */
4650 #define __NR_setxattr (__NR_SYSCALL_BASE+226)
4651 #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
4652 #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
4654 #define __NR_removexattr (__NR_SYSCALL_BASE+235)
4655 #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
4656 #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
4658 #define __NR_tkill (__NR_SYSCALL_BASE+238)
4660 * Please check 2.5 _before_ adding calls here,
4661 --- kernel-2.4.20-6chaos_18_7/include/asm-ppc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:42.000000000 -0600
4662 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-ppc64/unistd.h 2003-07-12 15:34:44.000000000 -0600
4664 #define __NR_gettid 207
4665 #if 0 /* Reserved syscalls */
4666 #define __NR_tkill 208
4668 #define __NR_setxattr 209
4669 #define __NR_lsetxattr 210
4670 #define __NR_fsetxattr 211
4672 #define __NR_removexattr 218
4673 #define __NR_lremovexattr 219
4674 #define __NR_fremovexattr 220
4675 +#if 0 /* Reserved syscalls */
4676 #define __NR_futex 221
4679 --- kernel-2.4.20-6chaos_18_7/include/asm-s390/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:44.000000000 -0600
4680 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390/unistd.h 2003-07-12 15:34:44.000000000 -0600
4681 @@ -212,9 +212,18 @@
4682 #define __NR_madvise 219
4683 #define __NR_getdents64 220
4684 #define __NR_fcntl64 221
4686 - * Numbers 224-235 are reserved for posix acl
4688 +#define __NR_setxattr 224
4689 +#define __NR_lsetxattr 225
4690 +#define __NR_fsetxattr 226
4691 +#define __NR_getxattr 227
4692 +#define __NR_lgetxattr 228
4693 +#define __NR_fgetxattr 229
4694 +#define __NR_listxattr 230
4695 +#define __NR_llistxattr 231
4696 +#define __NR_flistxattr 232
4697 +#define __NR_removexattr 233
4698 +#define __NR_lremovexattr 234
4699 +#define __NR_fremovexattr 235
4700 #define __NR_gettid 236
4701 #define __NR_tkill 237
4703 --- kernel-2.4.20-6chaos_18_7/include/asm-s390x/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:45.000000000 -0600
4704 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-s390x/unistd.h 2003-07-12 15:34:44.000000000 -0600
4705 @@ -180,9 +180,18 @@
4706 #define __NR_pivot_root 217
4707 #define __NR_mincore 218
4708 #define __NR_madvise 219
4710 - * Numbers 224-235 are reserved for posix acl
4712 +#define __NR_setxattr 224
4713 +#define __NR_lsetxattr 225
4714 +#define __NR_fsetxattr 226
4715 +#define __NR_getxattr 227
4716 +#define __NR_lgetxattr 228
4717 +#define __NR_fgetxattr 229
4718 +#define __NR_listxattr 230
4719 +#define __NR_llistxattr 231
4720 +#define __NR_flistxattr 232
4721 +#define __NR_removexattr 233
4722 +#define __NR_lremovexattr 234
4723 +#define __NR_fremovexattr 235
4724 #define __NR_gettid 236
4725 #define __NR_tkill 237
4727 --- kernel-2.4.20-6chaos_18_7/include/asm-sparc/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:46.000000000 -0600
4728 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc/unistd.h 2003-07-12 15:34:44.000000000 -0600
4729 @@ -184,24 +184,24 @@
4730 /* #define __NR_exportfs 166 SunOS Specific */
4731 #define __NR_mount 167 /* Common */
4732 #define __NR_ustat 168 /* Common */
4733 -/* #define __NR_semsys 169 SunOS Specific */
4734 -/* #define __NR_msgsys 170 SunOS Specific */
4735 -/* #define __NR_shmsys 171 SunOS Specific */
4736 -/* #define __NR_auditsys 172 SunOS Specific */
4737 -/* #define __NR_rfssys 173 SunOS Specific */
4738 +#define __NR_setxattr 169 /* SunOS: semsys */
4739 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4740 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4741 +#define __NR_getxattr 172 /* SunOS: auditsys */
4742 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4743 #define __NR_getdents 174 /* Common */
4744 #define __NR_setsid 175 /* Common */
4745 #define __NR_fchdir 176 /* Common */
4746 -/* #define __NR_fchroot 177 SunOS Specific */
4747 -/* #define __NR_vpixsys 178 SunOS Specific */
4748 -/* #define __NR_aioread 179 SunOS Specific */
4749 -/* #define __NR_aiowrite 180 SunOS Specific */
4750 -/* #define __NR_aiowait 181 SunOS Specific */
4751 -/* #define __NR_aiocancel 182 SunOS Specific */
4752 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4753 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4754 +#define __NR_llistxattr 179 /* SunOS: aioread */
4755 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4756 +#define __NR_removexattr 181 /* SunOS: aiowait */
4757 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4758 #define __NR_sigpending 183 /* Common */
4759 #define __NR_query_module 184 /* Linux Specific */
4760 #define __NR_setpgid 185 /* Common */
4761 -/* #define __NR_pathconf 186 SunOS Specific */
4762 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4763 #define __NR_tkill 187 /* SunOS: fpathconf */
4764 /* #define __NR_sysconf 188 SunOS Specific */
4765 #define __NR_uname 189 /* Linux Specific */
4766 --- kernel-2.4.20-6chaos_18_7/include/asm-sparc64/unistd.h~linux-2.4.20-xattr-0.8.54-chaos 2002-09-25 11:13:48.000000000 -0600
4767 +++ kernel-2.4.20-6chaos_18_7-braam/include/asm-sparc64/unistd.h 2003-07-12 15:34:44.000000000 -0600
4768 @@ -184,24 +184,24 @@
4769 /* #define __NR_exportfs 166 SunOS Specific */
4770 #define __NR_mount 167 /* Common */
4771 #define __NR_ustat 168 /* Common */
4772 -/* #define __NR_semsys 169 SunOS Specific */
4773 -/* #define __NR_msgsys 170 SunOS Specific */
4774 -/* #define __NR_shmsys 171 SunOS Specific */
4775 -/* #define __NR_auditsys 172 SunOS Specific */
4776 -/* #define __NR_rfssys 173 SunOS Specific */
4777 +#define __NR_setxattr 169 /* SunOS: semsys */
4778 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4779 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4780 +#define __NR_getxattr 172 /* SunOS: auditsys */
4781 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4782 #define __NR_getdents 174 /* Common */
4783 #define __NR_setsid 175 /* Common */
4784 #define __NR_fchdir 176 /* Common */
4785 -/* #define __NR_fchroot 177 SunOS Specific */
4786 -/* #define __NR_vpixsys 178 SunOS Specific */
4787 -/* #define __NR_aioread 179 SunOS Specific */
4788 -/* #define __NR_aiowrite 180 SunOS Specific */
4789 -/* #define __NR_aiowait 181 SunOS Specific */
4790 -/* #define __NR_aiocancel 182 SunOS Specific */
4791 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4792 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4793 +#define __NR_llistxattr 179 /* SunOS: aioread */
4794 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4795 +#define __NR_removexattr 181 /* SunOS: aiowait */
4796 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4797 #define __NR_sigpending 183 /* Common */
4798 #define __NR_query_module 184 /* Linux Specific */
4799 #define __NR_setpgid 185 /* Common */
4800 -/* #define __NR_pathconf 186 SunOS Specific */
4801 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4802 #define __NR_tkill 187 /* SunOS: fpathconf */
4803 /* #define __NR_sysconf 188 SunOS Specific */
4804 #define __NR_uname 189 /* Linux Specific */
4805 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
4806 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/cache_def.h 2003-07-12 15:34:44.000000000 -0600
4809 + * linux/cache_def.h
4810 + * Handling of caches defined in drivers, filesystems, ...
4812 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
4815 +struct cache_definition {
4817 + void (*shrink)(int, unsigned int);
4818 + struct list_head link;
4821 +extern void register_cache(struct cache_definition *);
4822 +extern void unregister_cache(struct cache_definition *);
4823 --- kernel-2.4.20-6chaos_18_7/include/linux/errno.h~linux-2.4.20-xattr-0.8.54-chaos 2003-05-15 21:15:06.000000000 -0600
4824 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/errno.h 2003-07-12 15:34:44.000000000 -0600
4829 +/* Defined for extended attributes */
4830 +#define ENOATTR ENODATA /* No such attribute */
4831 +#define ENOTSUP EOPNOTSUPP /* Operation not supported */
4834 --- kernel-2.4.20-6chaos_18_7/include/linux/ext2_fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-06-24 11:31:16.000000000 -0600
4835 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_fs.h 2003-07-12 15:34:44.000000000 -0600
4838 #define EXT2_BAD_INO 1 /* Bad blocks inode */
4839 #define EXT2_ROOT_INO 2 /* Root inode */
4840 -#define EXT2_ACL_IDX_INO 3 /* ACL inode */
4841 -#define EXT2_ACL_DATA_INO 4 /* ACL inode */
4842 #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
4843 #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
4847 # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
4849 -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
4850 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
4852 # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
4853 @@ -121,28 +118,6 @@
4859 -struct ext2_acl_header /* Header of Access Control Lists */
4862 - __u32 aclh_file_count;
4863 - __u32 aclh_acle_count;
4864 - __u32 aclh_first_acle;
4867 -struct ext2_acl_entry /* Access Control List Entry */
4870 - __u16 acle_perms; /* Access permissions */
4871 - __u16 acle_type; /* Type of entry */
4872 - __u16 acle_tag; /* User or group identity */
4874 - __u32 acle_next; /* Pointer on next entry for the */
4875 - /* same inode or on next free entry */
4879 * Structure of a blocks group descriptor
4881 struct ext2_group_desc
4882 @@ -314,6 +289,7 @@ struct ext2_inode {
4883 #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
4884 #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
4885 #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
4886 +#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
4888 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
4889 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
4890 @@ -397,6 +373,7 @@ struct ext2_super_block {
4893 #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
4894 +#define EXT2_I(inode) (&((inode)->u.ext2_i))
4896 /* Assume that user mode programs are passing in an ext2fs superblock, not
4897 * a kernel struct super_block. This will allow us to call the feature-test
4898 @@ -466,7 +443,7 @@ struct ext2_super_block {
4899 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
4900 #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
4902 -#define EXT2_FEATURE_COMPAT_SUPP 0
4903 +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
4904 #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
4905 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
4906 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
4907 @@ -624,8 +601,10 @@ extern struct address_space_operations e
4910 extern struct inode_operations ext2_dir_inode_operations;
4911 +extern struct inode_operations ext2_special_inode_operations;
4914 +extern struct inode_operations ext2_symlink_inode_operations;
4915 extern struct inode_operations ext2_fast_symlink_inode_operations;
4917 #endif /* __KERNEL__ */
4918 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
4919 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext2_xattr.h 2003-07-12 15:34:44.000000000 -0600
4922 + File: linux/ext2_xattr.h
4924 + On-disk format of extended attributes for the ext2 filesystem.
4926 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4929 +#include <linux/config.h>
4930 +#include <linux/init.h>
4931 +#include <linux/xattr.h>
4933 +/* Magic value in attribute blocks */
4934 +#define EXT2_XATTR_MAGIC 0xEA020000
4936 +/* Maximum number of references to one attribute block */
4937 +#define EXT2_XATTR_REFCOUNT_MAX 1024
4940 +#define EXT2_XATTR_INDEX_MAX 10
4941 +#define EXT2_XATTR_INDEX_USER 1
4942 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
4943 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
4945 +struct ext2_xattr_header {
4946 + __u32 h_magic; /* magic number for identification */
4947 + __u32 h_refcount; /* reference count */
4948 + __u32 h_blocks; /* number of disk blocks used */
4949 + __u32 h_hash; /* hash value of all attributes */
4950 + __u32 h_reserved[4]; /* zero right now */
4953 +struct ext2_xattr_entry {
4954 + __u8 e_name_len; /* length of name */
4955 + __u8 e_name_index; /* attribute name index */
4956 + __u16 e_value_offs; /* offset in disk block of value */
4957 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
4958 + __u32 e_value_size; /* size of attribute value */
4959 + __u32 e_hash; /* hash value of name and value */
4960 + char e_name[0]; /* attribute name */
4963 +#define EXT2_XATTR_PAD_BITS 2
4964 +#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
4965 +#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
4966 +#define EXT2_XATTR_LEN(name_len) \
4967 + (((name_len) + EXT2_XATTR_ROUND + \
4968 + sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
4969 +#define EXT2_XATTR_NEXT(entry) \
4970 + ( (struct ext2_xattr_entry *)( \
4971 + (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
4972 +#define EXT2_XATTR_SIZE(size) \
4973 + (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
4977 +# ifdef CONFIG_EXT2_FS_XATTR
4979 +struct ext2_xattr_handler {
4981 + size_t (*list)(char *list, struct inode *inode, const char *name,
4983 + int (*get)(struct inode *inode, const char *name, void *buffer,
4985 + int (*set)(struct inode *inode, const char *name, const void *buffer,
4986 + size_t size, int flags);
4989 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
4990 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
4992 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
4993 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
4994 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
4995 +extern int ext2_removexattr(struct dentry *, const char *);
4997 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
4998 +extern int ext2_xattr_list(struct inode *, char *, size_t);
4999 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
5001 +extern void ext2_xattr_delete_inode(struct inode *);
5002 +extern void ext2_xattr_put_super(struct super_block *);
5004 +extern int init_ext2_xattr(void) __init;
5005 +extern void exit_ext2_xattr(void);
5007 +# else /* CONFIG_EXT2_FS_XATTR */
5008 +# define ext2_setxattr NULL
5009 +# define ext2_getxattr NULL
5010 +# define ext2_listxattr NULL
5011 +# define ext2_removexattr NULL
5014 +ext2_xattr_get(struct inode *inode, int name_index,
5015 + const char *name, void *buffer, size_t size)
5021 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
5027 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
5028 + const void *value, size_t size, int flags)
5034 +ext2_xattr_delete_inode(struct inode *inode)
5039 +ext2_xattr_put_super(struct super_block *sb)
5044 +init_ext2_xattr(void)
5050 +exit_ext2_xattr(void)
5054 +# endif /* CONFIG_EXT2_FS_XATTR */
5056 +# ifdef CONFIG_EXT2_FS_XATTR_USER
5058 +extern int init_ext2_xattr_user(void) __init;
5059 +extern void exit_ext2_xattr_user(void);
5061 +# else /* CONFIG_EXT2_FS_XATTR_USER */
5064 +init_ext2_xattr_user(void)
5070 +exit_ext2_xattr_user(void)
5074 +# endif /* CONFIG_EXT2_FS_XATTR_USER */
5076 +#endif /* __KERNEL__ */
5078 --- kernel-2.4.20-6chaos_18_7/include/linux/ext3_fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:41.000000000 -0600
5079 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_fs.h 2003-07-12 15:34:44.000000000 -0600
5082 #define EXT3_BAD_INO 1 /* Bad blocks inode */
5083 #define EXT3_ROOT_INO 2 /* Root inode */
5084 -#define EXT3_ACL_IDX_INO 3 /* ACL inode */
5085 -#define EXT3_ACL_DATA_INO 4 /* ACL inode */
5086 #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
5087 #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
5088 #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
5091 # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5093 -#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
5094 #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
5096 # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5097 @@ -129,28 +126,6 @@
5103 -struct ext3_acl_header /* Header of Access Control Lists */
5106 - __u32 aclh_file_count;
5107 - __u32 aclh_acle_count;
5108 - __u32 aclh_first_acle;
5111 -struct ext3_acl_entry /* Access Control List Entry */
5114 - __u16 acle_perms; /* Access permissions */
5115 - __u16 acle_type; /* Type of entry */
5116 - __u16 acle_tag; /* User or group identity */
5118 - __u32 acle_next; /* Pointer on next entry for the */
5119 - /* same inode or on next free entry */
5123 * Structure of a blocks group descriptor
5125 struct ext3_group_desc
5126 @@ -344,6 +319,7 @@ struct ext3_inode {
5127 #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
5128 #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
5129 #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
5130 +#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5132 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
5133 #ifndef _LINUX_EXT2_FS_H
5134 @@ -521,7 +497,7 @@ struct ext3_super_block {
5135 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
5136 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
5138 -#define EXT3_FEATURE_COMPAT_SUPP 0
5139 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5140 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
5141 EXT3_FEATURE_INCOMPAT_RECOVER)
5142 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5143 @@ -704,6 +680,7 @@ extern void ext3_check_inodes_bitmap (st
5144 extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
5147 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
5148 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
5149 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
5151 @@ -773,8 +750,10 @@ extern struct address_space_operations e
5154 extern struct inode_operations ext3_dir_inode_operations;
5155 +extern struct inode_operations ext3_special_inode_operations;
5158 +extern struct inode_operations ext3_symlink_inode_operations;
5159 extern struct inode_operations ext3_fast_symlink_inode_operations;
5162 --- kernel-2.4.20-6chaos_18_7/include/linux/ext3_jbd.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:38.000000000 -0600
5163 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_jbd.h 2003-07-12 15:34:44.000000000 -0600
5166 #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U
5168 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5169 + * and two group and summaries. */
5171 +#define EXT3_XATTR_TRANS_BLOCKS 8
5173 /* Define the minimum size for a transaction which modifies data. This
5174 * needs to take into account the fact that we may end up modifying two
5175 * quota files too (one for the group, one for the user quota). The
5176 * superblock only gets updated once, of course, so don't bother
5177 * counting that again for the quota updates. */
5179 -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5180 +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5181 + EXT3_XATTR_TRANS_BLOCKS - 2)
5183 extern int ext3_writepage_trans_blocks(struct inode *inode);
5185 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
5186 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/ext3_xattr.h 2003-07-12 15:34:44.000000000 -0600
5189 + File: linux/ext3_xattr.h
5191 + On-disk format of extended attributes for the ext3 filesystem.
5193 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5196 +#include <linux/config.h>
5197 +#include <linux/init.h>
5198 +#include <linux/xattr.h>
5200 +/* Magic value in attribute blocks */
5201 +#define EXT3_XATTR_MAGIC 0xEA020000
5203 +/* Maximum number of references to one attribute block */
5204 +#define EXT3_XATTR_REFCOUNT_MAX 1024
5207 +#define EXT3_XATTR_INDEX_MAX 10
5208 +#define EXT3_XATTR_INDEX_USER 1
5209 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
5210 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5212 +struct ext3_xattr_header {
5213 + __u32 h_magic; /* magic number for identification */
5214 + __u32 h_refcount; /* reference count */
5215 + __u32 h_blocks; /* number of disk blocks used */
5216 + __u32 h_hash; /* hash value of all attributes */
5217 + __u32 h_reserved[4]; /* zero right now */
5220 +struct ext3_xattr_entry {
5221 + __u8 e_name_len; /* length of name */
5222 + __u8 e_name_index; /* attribute name index */
5223 + __u16 e_value_offs; /* offset in disk block of value */
5224 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5225 + __u32 e_value_size; /* size of attribute value */
5226 + __u32 e_hash; /* hash value of name and value */
5227 + char e_name[0]; /* attribute name */
5230 +#define EXT3_XATTR_PAD_BITS 2
5231 +#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
5232 +#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
5233 +#define EXT3_XATTR_LEN(name_len) \
5234 + (((name_len) + EXT3_XATTR_ROUND + \
5235 + sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5236 +#define EXT3_XATTR_NEXT(entry) \
5237 + ( (struct ext3_xattr_entry *)( \
5238 + (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5239 +#define EXT3_XATTR_SIZE(size) \
5240 + (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5244 +# ifdef CONFIG_EXT3_FS_XATTR
5246 +struct ext3_xattr_handler {
5248 + size_t (*list)(char *list, struct inode *inode, const char *name,
5250 + int (*get)(struct inode *inode, const char *name, void *buffer,
5252 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5253 + size_t size, int flags);
5256 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5257 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5259 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5260 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5261 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5262 +extern int ext3_removexattr(struct dentry *, const char *);
5264 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5265 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5266 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5268 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5269 +extern void ext3_xattr_put_super(struct super_block *);
5271 +extern int init_ext3_xattr(void) __init;
5272 +extern void exit_ext3_xattr(void);
5274 +# else /* CONFIG_EXT3_FS_XATTR */
5275 +# define ext3_setxattr NULL
5276 +# define ext3_getxattr NULL
5277 +# define ext3_listxattr NULL
5278 +# define ext3_removexattr NULL
5281 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5282 + void *buffer, size_t size)
5288 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5294 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5295 + const char *name, const void *value, size_t size, int flags)
5301 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5306 +ext3_xattr_put_super(struct super_block *sb)
5311 +init_ext3_xattr(void)
5317 +exit_ext3_xattr(void)
5321 +# endif /* CONFIG_EXT3_FS_XATTR */
5323 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5325 +extern int init_ext3_xattr_user(void) __init;
5326 +extern void exit_ext3_xattr_user(void);
5328 +# else /* CONFIG_EXT3_FS_XATTR_USER */
5331 +init_ext3_xattr_user(void)
5337 +exit_ext3_xattr_user(void)
5341 +#endif /* CONFIG_EXT3_FS_XATTR_USER */
5343 +#endif /* __KERNEL__ */
5345 --- kernel-2.4.20-6chaos_18_7/include/linux/fs.h~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:31:35.000000000 -0600
5346 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/fs.h 2003-07-12 15:34:44.000000000 -0600
5347 @@ -914,7 +914,7 @@ struct inode_operations {
5348 int (*setattr) (struct dentry *, struct iattr *);
5349 int (*setattr_raw) (struct inode *, struct iattr *);
5350 int (*getattr) (struct dentry *, struct iattr *);
5351 - int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
5352 + int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5353 ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5354 ssize_t (*listxattr) (struct dentry *, char *, size_t);
5355 int (*removexattr) (struct dentry *, const char *);
5356 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
5357 +++ kernel-2.4.20-6chaos_18_7-braam/include/linux/mbcache.h 2003-07-12 15:34:44.000000000 -0600
5360 + File: linux/mbcache.h
5362 + (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5365 +/* Hardwire the number of additional indexes */
5366 +#define MB_CACHE_INDEXES_COUNT 1
5368 +struct mb_cache_entry;
5370 +struct mb_cache_op {
5371 + int (*free)(struct mb_cache_entry *, int);
5375 + struct list_head c_cache_list;
5376 + const char *c_name;
5377 + struct mb_cache_op c_op;
5378 + atomic_t c_entry_count;
5379 + int c_bucket_count;
5380 +#ifndef MB_CACHE_INDEXES_COUNT
5381 + int c_indexes_count;
5383 + kmem_cache_t *c_entry_cache;
5384 + struct list_head *c_block_hash;
5385 + struct list_head *c_indexes_hash[0];
5388 +struct mb_cache_entry_index {
5389 + struct list_head o_list;
5390 + unsigned int o_key;
5393 +struct mb_cache_entry {
5394 + struct list_head e_lru_list;
5395 + struct mb_cache *e_cache;
5398 + unsigned long e_block;
5399 + struct list_head e_block_list;
5400 + struct mb_cache_entry_index e_indexes[0];
5403 +/* Functions on caches */
5405 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5407 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5408 +void mb_cache_destroy(struct mb_cache *);
5410 +/* Functions on cache entries */
5412 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5413 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5415 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5416 +void mb_cache_entry_release(struct mb_cache_entry *);
5417 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5418 +void mb_cache_entry_free(struct mb_cache_entry *);
5419 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5420 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5422 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5423 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5424 + kdev_t, unsigned int);
5425 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5426 + kdev_t, unsigned int);
5428 --- kernel-2.4.20-6chaos_18_7/kernel/ksyms.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:14:02.000000000 -0600
5429 +++ kernel-2.4.20-6chaos_18_7-braam/kernel/ksyms.c 2003-07-12 15:35:19.000000000 -0600
5431 #define __KERNEL_SYSCALLS__
5432 #include <linux/config.h>
5433 #include <linux/slab.h>
5434 +#include <linux/cache_def.h>
5435 #include <linux/smp.h>
5436 #include <linux/module.h>
5437 #include <linux/blkdev.h>
5438 @@ -106,6 +107,7 @@ EXPORT_SYMBOL(do_brk);
5439 EXPORT_SYMBOL(exit_mm);
5440 EXPORT_SYMBOL(exit_files);
5441 EXPORT_SYMBOL(exit_fs);
5442 +EXPORT_SYMBOL(copy_fs_struct);
5443 EXPORT_SYMBOL(exit_sighand);
5444 EXPORT_SYMBOL_GPL(make_pages_present);
5446 @@ -126,6 +128,8 @@ EXPORT_SYMBOL(kmem_cache_alloc);
5447 EXPORT_SYMBOL(kmem_cache_free);
5448 EXPORT_SYMBOL(kmem_cache_validate);
5449 EXPORT_SYMBOL(kmem_cache_size);
5450 +EXPORT_SYMBOL(register_cache);
5451 +EXPORT_SYMBOL(unregister_cache);
5452 EXPORT_SYMBOL(kmalloc);
5453 EXPORT_SYMBOL(kfree);
5454 EXPORT_SYMBOL(vfree);
5455 --- kernel-2.4.20-6chaos_18_7/mm/vmscan.c~linux-2.4.20-xattr-0.8.54-chaos 2003-07-12 15:33:34.000000000 -0600
5456 +++ kernel-2.4.20-6chaos_18_7-braam/mm/vmscan.c 2003-07-12 15:34:44.000000000 -0600
5458 #include <linux/kernel_stat.h>
5459 #include <linux/swap.h>
5460 #include <linux/swapctl.h>
5461 +#include <linux/cache_def.h>
5462 #include <linux/smp_lock.h>
5463 #include <linux/pagemap.h>
5464 #include <linux/init.h>
5465 @@ -444,6 +445,39 @@ static inline void kachunk_cache(struct
5467 #define BATCH_WORK_AMOUNT 64
5469 +static DECLARE_MUTEX(other_caches_sem);
5470 +static LIST_HEAD(cache_definitions);
5472 +void register_cache(struct cache_definition *cache)
5474 + down(&other_caches_sem);
5475 + list_add(&cache->link, &cache_definitions);
5476 + up(&other_caches_sem);
5479 +void unregister_cache(struct cache_definition *cache)
5481 + down(&other_caches_sem);
5482 + list_del(&cache->link);
5483 + up(&other_caches_sem);
5486 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
5488 + struct list_head *p;
5490 + if (down_trylock(&other_caches_sem))
5493 + list_for_each_prev(p, &cache_definitions) {
5494 + struct cache_definition *cache =
5495 + list_entry(p, struct cache_definition, link);
5497 + cache->shrink(priority, gfp_mask);
5499 + up(&other_caches_sem);
5503 * returns the active cache ratio relative to the total active list
5504 * times 10 (eg. 30% cache returns 3)
5505 @@ -887,7 +921,7 @@ static int do_try_to_free_pages_kswapd(u
5507 ret += shrink_dcache_memory(DEF_PRIORITY, gfp_mask);
5508 ret += shrink_icache_memory(DEF_PRIORITY, gfp_mask);
5509 - // ret += shrink_other_caches(DEF_PRIORITY, gfp_mask);
5510 + shrink_other_caches(DEF_PRIORITY, gfp_mask);
5512 ret += shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
5514 --- /dev/null 2003-01-30 03:24:37.000000000 -0700
5515 +++ kernel-2.4.20-6chaos_18_7-braam/fs/ext3/ext3-exports.c 2003-07-12 15:34:44.000000000 -0600
5517 +#include <linux/config.h>
5518 +#include <linux/module.h>
5519 +#include <linux/ext3_fs.h>
5520 +#include <linux/ext3_jbd.h>
5521 +#include <linux/ext3_xattr.h>
5523 +EXPORT_SYMBOL(ext3_force_commit);
5524 +EXPORT_SYMBOL(ext3_bread);
5525 +EXPORT_SYMBOL(ext3_xattr_register);
5526 +EXPORT_SYMBOL(ext3_xattr_unregister);
5527 +EXPORT_SYMBOL(ext3_xattr_get);
5528 +EXPORT_SYMBOL(ext3_xattr_list);
5529 +EXPORT_SYMBOL(ext3_xattr_set);