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/ia64/kernel/entry.S | 24
9 arch/m68k/defconfig | 7
10 arch/mips/defconfig | 7
11 arch/mips64/defconfig | 7
12 arch/ppc/defconfig | 14
13 arch/ppc64/kernel/misc.S | 2
14 arch/s390/defconfig | 7
15 arch/s390/kernel/entry.S | 24
16 arch/s390x/defconfig | 7
17 arch/s390x/kernel/entry.S | 24
18 arch/s390x/kernel/wrapper32.S | 92 +++
19 arch/sparc/defconfig | 7
20 arch/sparc/kernel/systbls.S | 10
21 arch/sparc64/defconfig | 7
22 arch/sparc64/kernel/systbls.S | 20
28 fs/ext2/inode.c | 34 -
31 fs/ext2/symlink.c | 14
32 fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++
33 fs/ext2/xattr_user.c | 103 +++
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-ia64/unistd.h | 13
48 include/asm-ppc64/unistd.h | 2
49 include/asm-s390/unistd.h | 15
50 include/asm-s390x/unistd.h | 15
51 include/asm-sparc/unistd.h | 24
52 include/asm-sparc64/unistd.h | 24
53 include/linux/cache_def.h | 15
54 include/linux/errno.h | 4
55 include/linux/ext2_fs.h | 31 -
56 include/linux/ext2_xattr.h | 157 +++++
57 include/linux/ext3_fs.h | 31 -
58 include/linux/ext3_jbd.h | 8
59 include/linux/ext3_xattr.h | 157 +++++
60 include/linux/fs.h | 2
61 include/linux/mbcache.h | 69 ++
64 fs/ext3/ext3-exports.c | 14 +
65 64 files changed, 4355 insertions(+), 195 deletions(-)
67 Index: linux-2.4.19-pre1/Documentation/Configure.help
68 ===================================================================
69 --- linux-2.4.19-pre1.orig/Documentation/Configure.help 2003-11-20 19:01:44.000000000 +0300
70 +++ linux-2.4.19-pre1/Documentation/Configure.help 2003-11-21 03:51:05.000000000 +0300
71 @@ -14035,6 +14035,39 @@
72 be compiled as a module, and so this could be dangerous. Most
73 everyone wants to say Y here.
75 +Ext2 extended attributes
77 + Extended attributes are name:value pairs associated with inodes by
78 + the kernel or by users (see the attr(5) manual page, or visit
79 + <http://acl.bestbits.at/> for details).
83 +Ext2 extended attribute block sharing
84 +CONFIG_EXT2_FS_XATTR_SHARING
85 + This options enables code for sharing identical extended attribute
86 + blocks among multiple inodes.
90 +Ext2 extended user attributes
91 +CONFIG_EXT2_FS_XATTR_USER
92 + This option enables extended user attributes on ext2. Processes can
93 + associate extended user attributes with inodes to store additional
94 + information such as the character encoding of files, etc. (see the
95 + attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
99 +Ext2 trusted extended attributes
100 +CONFIG_EXT2_FS_XATTR_TRUSTED
101 + This option enables extended attributes on ext2 that are accessible
102 + (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
103 + is only the super user. Trusted extended attributes are meant for
104 + implementing system/security services.
108 Ext3 journalling file system support (EXPERIMENTAL)
110 This is the journalling version of the Second extended file system
111 @@ -14067,6 +14100,39 @@
112 of your root partition (the one containing the directory /) cannot
113 be compiled as a module, and so this may be dangerous.
115 +Ext3 extended attributes
116 +CONFIG_EXT3_FS_XATTR
117 + Extended attributes are name:value pairs associated with inodes by
118 + the kernel or by users (see the attr(5) manual page, or visit
119 + <http://acl.bestbits.at/> for details).
123 +Ext3 extended attribute block sharing
124 +CONFIG_EXT3_FS_XATTR_SHARING
125 + This options enables code for sharing identical extended attribute
126 + blocks among multiple inodes.
130 +Ext3 extended user attributes
131 +CONFIG_EXT3_FS_XATTR_USER
132 + This option enables extended user attributes on ext3. Processes can
133 + associate extended user attributes with inodes to store additional
134 + information such as the character encoding of files, etc. (see the
135 + attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
139 +Ext3 trusted extended attributes
140 +CONFIG_EXT3_FS_XATTR_TRUSTED
141 + This option enables extended attributes on ext3 that are accessible
142 + (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
143 + is only the super user. Trusted extended attributes are meant for
144 + implementing system/security services.
148 Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
150 This is a generic journalling layer for block devices. It is
151 Index: linux-2.4.19-pre1/arch/alpha/defconfig
152 ===================================================================
153 --- linux-2.4.19-pre1.orig/arch/alpha/defconfig 2001-11-20 02:19:42.000000000 +0300
154 +++ linux-2.4.19-pre1/arch/alpha/defconfig 2003-11-21 03:51:05.000000000 +0300
157 # Automatically generated make config: don't edit
159 +# CONFIG_EXT3_FS_XATTR is not set
160 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
161 +# CONFIG_EXT3_FS_XATTR_USER is not set
162 +# CONFIG_EXT2_FS_XATTR is not set
163 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
164 +# CONFIG_EXT2_FS_XATTR_USER is not set
165 +# CONFIG_FS_MBCACHE is not set
167 # CONFIG_UID16 is not set
168 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
169 Index: linux-2.4.19-pre1/arch/alpha/kernel/entry.S
170 ===================================================================
171 --- linux-2.4.19-pre1.orig/arch/alpha/kernel/entry.S 2001-11-10 00:45:35.000000000 +0300
172 +++ linux-2.4.19-pre1/arch/alpha/kernel/entry.S 2003-11-21 03:51:05.000000000 +0300
173 @@ -1148,3 +1148,16 @@
176 .quad sys_ni_syscall /* 380, sys_security */
177 + .quad sys_ni_syscall /* 381, sys_tkill */
179 + .quad sys_lsetxattr
180 + .quad sys_fsetxattr
181 + .quad sys_getxattr /* 385 */
182 + .quad sys_lgetxattr
183 + .quad sys_fgetxattr
184 + .quad sys_listxattr
185 + .quad sys_llistxattr
186 + .quad sys_flistxattr /* 390 */
187 + .quad sys_removexattr
188 + .quad sys_lremovexattr
189 + .quad sys_fremovexattr
190 Index: linux-2.4.19-pre1/arch/arm/defconfig
191 ===================================================================
192 --- linux-2.4.19-pre1.orig/arch/arm/defconfig 2001-05-20 04:43:05.000000000 +0400
193 +++ linux-2.4.19-pre1/arch/arm/defconfig 2003-11-21 03:51:05.000000000 +0300
196 # Automatically generated make config: don't edit
198 +# CONFIG_EXT3_FS_XATTR is not set
199 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
200 +# CONFIG_EXT3_FS_XATTR_USER is not set
201 +# CONFIG_EXT2_FS_XATTR is not set
202 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
203 +# CONFIG_EXT2_FS_XATTR_USER is not set
204 +# CONFIG_FS_MBCACHE is not set
206 # CONFIG_EISA is not set
207 # CONFIG_SBUS is not set
208 Index: linux-2.4.19-pre1/arch/arm/kernel/calls.S
209 ===================================================================
210 --- linux-2.4.19-pre1.orig/arch/arm/kernel/calls.S 2001-10-08 21:39:18.000000000 +0400
211 +++ linux-2.4.19-pre1/arch/arm/kernel/calls.S 2003-11-21 03:51:05.000000000 +0300
213 .long SYMBOL_NAME(sys_mincore)
214 /* 220 */ .long SYMBOL_NAME(sys_madvise)
215 .long SYMBOL_NAME(sys_fcntl64)
216 + .long SYMBOL_NAME(sys_ni_syscall) /* TUX */
217 + .long SYMBOL_NAME(sys_ni_syscall) /* Security */
218 + .long SYMBOL_NAME(sys_gettid)
219 + /* 225 */ .long SYMBOL_NAME(sys_readahead)
220 + .long SYMBOL_NAME(sys_setxattr)
221 + .long SYMBOL_NAME(sys_lsetxattr)
222 + .long SYMBOL_NAME(sys_fsetxattr)
223 + .long SYMBOL_NAME(sys_getxattr)
224 +/* 230 */ .long SYMBOL_NAME(sys_lgetxattr)
225 + .long SYMBOL_NAME(sys_fgetxattr)
226 + .long SYMBOL_NAME(sys_listxattr)
227 + .long SYMBOL_NAME(sys_llistxattr)
228 + .long SYMBOL_NAME(sys_flistxattr)
229 +/* 235 */ .long SYMBOL_NAME(sys_removexattr)
230 + .long SYMBOL_NAME(sys_lremovexattr)
231 + .long SYMBOL_NAME(sys_fremovexattr)
234 .rept NR_syscalls - (__syscall_end - __syscall_start) / 4
235 Index: linux-2.4.19-pre1/arch/i386/defconfig
236 ===================================================================
237 --- linux-2.4.19-pre1.orig/arch/i386/defconfig 2003-11-20 19:01:35.000000000 +0300
238 +++ linux-2.4.19-pre1/arch/i386/defconfig 2003-11-21 03:51:05.000000000 +0300
241 # Automatically generated make config: don't edit
243 +# CONFIG_EXT3_FS_XATTR is not set
244 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
245 +# CONFIG_EXT3_FS_XATTR_USER is not set
246 +# CONFIG_EXT2_FS_XATTR is not set
247 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
248 +# CONFIG_EXT2_FS_XATTR_USER is not set
249 +# CONFIG_FS_MBCACHE is not set
252 # CONFIG_SBUS is not set
253 Index: linux-2.4.19-pre1/arch/ia64/defconfig
254 ===================================================================
255 --- linux-2.4.19-pre1.orig/arch/ia64/defconfig 2001-11-10 01:26:17.000000000 +0300
256 +++ linux-2.4.19-pre1/arch/ia64/defconfig 2003-11-21 03:51:05.000000000 +0300
259 # Automatically generated make config: don't edit
261 +# CONFIG_EXT3_FS_XATTR is not set
262 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
263 +# CONFIG_EXT3_FS_XATTR_USER is not set
264 +# CONFIG_EXT2_FS_XATTR is not set
265 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
266 +# CONFIG_EXT2_FS_XATTR_USER is not set
267 +# CONFIG_FS_MBCACHE is not set
270 # Code maturity level options
271 Index: linux-2.4.19-pre1/arch/ia64/kernel/entry.S
272 ===================================================================
273 --- linux-2.4.19-pre1.orig/arch/ia64/kernel/entry.S 2001-11-10 01:26:17.000000000 +0300
274 +++ linux-2.4.19-pre1/arch/ia64/kernel/entry.S 2003-11-21 03:51:05.000000000 +0300
275 @@ -1130,18 +1130,18 @@
277 data8 sys_getunwind // 1215
279 - data8 ia64_ni_syscall
280 - data8 ia64_ni_syscall
281 - data8 ia64_ni_syscall
282 - data8 ia64_ni_syscall // 1220
283 - data8 ia64_ni_syscall
284 - data8 ia64_ni_syscall
285 - data8 ia64_ni_syscall
286 - data8 ia64_ni_syscall
287 - data8 ia64_ni_syscall // 1225
288 - data8 ia64_ni_syscall
289 - data8 ia64_ni_syscall
290 - data8 ia64_ni_syscall
292 + data8 sys_lsetxattr
293 + data8 sys_fsetxattr
294 + data8 sys_getxattr // 1220
295 + data8 sys_lgetxattr
296 + data8 sys_fgetxattr
297 + data8 sys_listxattr
298 + data8 sys_llistxattr
299 + data8 sys_flistxattr // 1225
300 + data8 sys_removexattr
301 + data8 sys_lremovexattr
302 + data8 sys_fremovexattr
303 data8 ia64_ni_syscall
304 data8 ia64_ni_syscall // 1230
305 data8 ia64_ni_syscall
306 Index: linux-2.4.19-pre1/arch/m68k/defconfig
307 ===================================================================
308 --- linux-2.4.19-pre1.orig/arch/m68k/defconfig 2000-06-19 23:56:08.000000000 +0400
309 +++ linux-2.4.19-pre1/arch/m68k/defconfig 2003-11-21 03:51:05.000000000 +0300
312 # Automatically generated make config: don't edit
314 +# CONFIG_EXT3_FS_XATTR is not set
315 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
316 +# CONFIG_EXT3_FS_XATTR_USER is not set
317 +# CONFIG_EXT2_FS_XATTR is not set
318 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
319 +# CONFIG_EXT2_FS_XATTR_USER is not set
320 +# CONFIG_FS_MBCACHE is not set
324 Index: linux-2.4.19-pre1/arch/mips/defconfig
325 ===================================================================
326 --- linux-2.4.19-pre1.orig/arch/mips/defconfig 2001-09-09 21:43:02.000000000 +0400
327 +++ linux-2.4.19-pre1/arch/mips/defconfig 2003-11-21 03:51:05.000000000 +0300
330 # Automatically generated make config: don't edit
332 +# CONFIG_EXT3_FS_XATTR is not set
333 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
334 +# CONFIG_EXT3_FS_XATTR_USER is not set
335 +# CONFIG_EXT2_FS_XATTR is not set
336 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
337 +# CONFIG_EXT2_FS_XATTR_USER is not set
338 +# CONFIG_FS_MBCACHE is not set
340 # CONFIG_SMP is not set
342 Index: linux-2.4.19-pre1/arch/mips64/defconfig
343 ===================================================================
344 --- linux-2.4.19-pre1.orig/arch/mips64/defconfig 2001-09-09 21:43:02.000000000 +0400
345 +++ linux-2.4.19-pre1/arch/mips64/defconfig 2003-11-21 03:51:05.000000000 +0300
348 # Automatically generated make config: don't edit
350 +# CONFIG_EXT3_FS_XATTR is not set
351 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
352 +# CONFIG_EXT3_FS_XATTR_USER is not set
353 +# CONFIG_EXT2_FS_XATTR is not set
354 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
355 +# CONFIG_EXT2_FS_XATTR_USER is not set
356 +# CONFIG_FS_MBCACHE is not set
359 # Code maturity level options
360 Index: linux-2.4.19-pre1/arch/ppc/defconfig
361 ===================================================================
362 --- linux-2.4.19-pre1.orig/arch/ppc/defconfig 2003-11-20 19:01:35.000000000 +0300
363 +++ linux-2.4.19-pre1/arch/ppc/defconfig 2003-11-21 03:51:05.000000000 +0300
366 # Automatically generated make config: don't edit
368 +# CONFIG_EXT3_FS_XATTR is not set
369 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
370 +# CONFIG_EXT3_FS_XATTR_USER is not set
371 +# CONFIG_EXT2_FS_XATTR is not set
372 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
373 +# CONFIG_EXT2_FS_XATTR_USER is not set
374 +# CONFIG_FS_MBCACHE is not set
375 +# CONFIG_EXT3_FS_XATTR is not set
376 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
377 +# CONFIG_EXT3_FS_XATTR_USER is not set
378 +# CONFIG_EXT2_FS_XATTR is not set
379 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
380 +# CONFIG_EXT2_FS_XATTR_USER is not set
381 +# CONFIG_FS_MBCACHE is not set
382 # CONFIG_UID16 is not set
383 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
384 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
385 Index: linux-2.4.19-pre1/arch/s390/defconfig
386 ===================================================================
387 --- linux-2.4.19-pre1.orig/arch/s390/defconfig 2003-11-20 19:01:35.000000000 +0300
388 +++ linux-2.4.19-pre1/arch/s390/defconfig 2003-11-21 03:51:05.000000000 +0300
391 # Automatically generated make config: don't edit
393 +# CONFIG_EXT3_FS_XATTR is not set
394 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
395 +# CONFIG_EXT3_FS_XATTR_USER is not set
396 +# CONFIG_EXT2_FS_XATTR is not set
397 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
398 +# CONFIG_EXT2_FS_XATTR_USER is not set
399 +# CONFIG_FS_MBCACHE is not set
400 # CONFIG_ISA is not set
401 # CONFIG_EISA is not set
402 # CONFIG_MCA is not set
403 Index: linux-2.4.19-pre1/arch/s390/kernel/entry.S
404 ===================================================================
405 --- linux-2.4.19-pre1.orig/arch/s390/kernel/entry.S 2003-11-20 19:01:35.000000000 +0300
406 +++ linux-2.4.19-pre1/arch/s390/kernel/entry.S 2003-11-21 03:51:05.000000000 +0300
409 .long sys_ni_syscall /* 222 - reserved for posix_acl */
410 .long sys_ni_syscall /* 223 - reserved for posix_acl */
411 - .long sys_ni_syscall /* 224 - reserved for posix_acl */
414 + .long sys_lsetxattr /* 225 */
415 + .long sys_fsetxattr
417 + .long sys_lgetxattr
418 + .long sys_fgetxattr
419 + .long sys_listxattr /* 230 */
420 + .long sys_llistxattr
421 + .long sys_flistxattr
422 + .long sys_removexattr
423 + .long sys_lremovexattr
424 + .long sys_fremovexattr /* 235 */
429 Index: linux-2.4.19-pre1/arch/s390x/defconfig
430 ===================================================================
431 --- linux-2.4.19-pre1.orig/arch/s390x/defconfig 2003-11-20 19:01:35.000000000 +0300
432 +++ linux-2.4.19-pre1/arch/s390x/defconfig 2003-11-21 03:51:05.000000000 +0300
435 # Automatically generated make config: don't edit
437 +# CONFIG_EXT3_FS_XATTR is not set
438 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
439 +# CONFIG_EXT3_FS_XATTR_USER is not set
440 +# CONFIG_EXT2_FS_XATTR is not set
441 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
442 +# CONFIG_EXT2_FS_XATTR_USER is not set
443 +# CONFIG_FS_MBCACHE is not set
444 # CONFIG_ISA is not set
445 # CONFIG_EISA is not set
446 # CONFIG_MCA is not set
447 Index: linux-2.4.19-pre1/arch/s390x/kernel/entry.S
448 ===================================================================
449 --- linux-2.4.19-pre1.orig/arch/s390x/kernel/entry.S 2003-11-20 19:01:35.000000000 +0300
450 +++ linux-2.4.19-pre1/arch/s390x/kernel/entry.S 2003-11-21 03:51:05.000000000 +0300
452 .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
453 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 222 - reserved for posix_acl */
454 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 223 - reserved for posix_acl */
455 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for posix_acl */
457 + .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
458 + .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
459 + .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
460 + .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
461 + .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
462 + .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
463 + .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
464 + .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
465 + .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
466 + .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
467 + .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
468 + .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
470 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
473 Index: linux-2.4.19-pre1/arch/s390x/kernel/wrapper32.S
474 ===================================================================
475 --- linux-2.4.19-pre1.orig/arch/s390x/kernel/wrapper32.S 2003-11-20 19:01:35.000000000 +0300
476 +++ linux-2.4.19-pre1/arch/s390x/kernel/wrapper32.S 2003-11-21 03:51:05.000000000 +0300
477 @@ -1091,3 +1091,95 @@
478 llgtr %r3,%r3 # struct stat64 *
480 jg sys32_fstat64 # branch to system call
482 + .globl sys32_setxattr_wrapper
483 +sys32_setxattr_wrapper:
484 + llgtr %r2,%r2 # char *
485 + llgtr %r3,%r3 # char *
486 + llgtr %r4,%r4 # void *
487 + llgfr %r5,%r5 # size_t
491 + .globl sys32_lsetxattr_wrapper
492 +sys32_lsetxattr_wrapper:
493 + llgtr %r2,%r2 # char *
494 + llgtr %r3,%r3 # char *
495 + llgtr %r4,%r4 # void *
496 + llgfr %r5,%r5 # size_t
500 + .globl sys32_fsetxattr_wrapper
501 +sys32_fsetxattr_wrapper:
503 + llgtr %r3,%r3 # char *
504 + llgtr %r4,%r4 # void *
505 + llgfr %r5,%r5 # size_t
509 + .globl sys32_getxattr_wrapper
510 +sys32_getxattr_wrapper:
511 + llgtr %r2,%r2 # char *
512 + llgtr %r3,%r3 # char *
513 + llgtr %r4,%r4 # void *
514 + llgfr %r5,%r5 # size_t
517 + .globl sys32_lgetxattr_wrapper
518 +sys32_lgetxattr_wrapper:
519 + llgtr %r2,%r2 # char *
520 + llgtr %r3,%r3 # char *
521 + llgtr %r4,%r4 # void *
522 + llgfr %r5,%r5 # size_t
525 + .globl sys32_fgetxattr_wrapper
526 +sys32_fgetxattr_wrapper:
528 + llgtr %r3,%r3 # char *
529 + llgtr %r4,%r4 # void *
530 + llgfr %r5,%r5 # size_t
533 + .globl sys32_listxattr_wrapper
534 +sys32_listxattr_wrapper:
535 + llgtr %r2,%r2 # char *
536 + llgtr %r3,%r3 # char *
537 + llgfr %r4,%r4 # size_t
540 + .globl sys32_llistxattr_wrapper
541 +sys32_llistxattr_wrapper:
542 + llgtr %r2,%r2 # char *
543 + llgtr %r3,%r3 # char *
544 + llgfr %r4,%r4 # size_t
547 + .globl sys32_flistxattr_wrapper
548 +sys32_flistxattr_wrapper:
550 + llgtr %r3,%r3 # char *
551 + llgfr %r4,%r4 # size_t
554 + .globl sys32_removexattr_wrapper
555 +sys32_removexattr_wrapper:
556 + llgtr %r2,%r2 # char *
557 + llgtr %r3,%r3 # char *
560 + .globl sys32_lremovexattr_wrapper
561 +sys32_lremovexattr_wrapper:
562 + llgtr %r2,%r2 # char *
563 + llgtr %r3,%r3 # char *
564 + jg sys_lremovexattr
566 + .globl sys32_fremovexattr_wrapper
567 +sys32_fremovexattr_wrapper:
569 + llgtr %r3,%r3 # char *
570 + jg sys_fremovexattr
573 Index: linux-2.4.19-pre1/arch/sparc/defconfig
574 ===================================================================
575 --- linux-2.4.19-pre1.orig/arch/sparc/defconfig 2003-11-20 19:01:35.000000000 +0300
576 +++ linux-2.4.19-pre1/arch/sparc/defconfig 2003-11-21 03:51:05.000000000 +0300
579 # Automatically generated make config: don't edit
581 +# CONFIG_EXT3_FS_XATTR is not set
582 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
583 +# CONFIG_EXT3_FS_XATTR_USER is not set
584 +# CONFIG_EXT2_FS_XATTR is not set
585 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
586 +# CONFIG_EXT2_FS_XATTR_USER is not set
587 +# CONFIG_FS_MBCACHE is not set
591 Index: linux-2.4.19-pre1/arch/sparc/kernel/systbls.S
592 ===================================================================
593 --- linux-2.4.19-pre1.orig/arch/sparc/kernel/systbls.S 2001-10-21 21:36:54.000000000 +0400
594 +++ linux-2.4.19-pre1/arch/sparc/kernel/systbls.S 2003-11-21 03:51:05.000000000 +0300
596 /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
597 /*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
598 /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
599 -/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
600 -/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
601 -/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
602 -/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
603 -/*185*/ .long sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
604 +/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
605 +/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
606 +/*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
607 +/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
608 +/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
609 /*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
610 /*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
611 /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
612 Index: linux-2.4.19-pre1/arch/sparc64/defconfig
613 ===================================================================
614 --- linux-2.4.19-pre1.orig/arch/sparc64/defconfig 2003-11-20 19:01:35.000000000 +0300
615 +++ linux-2.4.19-pre1/arch/sparc64/defconfig 2003-11-21 03:51:05.000000000 +0300
618 # Automatically generated make config: don't edit
620 +# CONFIG_EXT3_FS_XATTR is not set
621 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
622 +# CONFIG_EXT3_FS_XATTR_USER is not set
623 +# CONFIG_EXT2_FS_XATTR is not set
624 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
625 +# CONFIG_EXT2_FS_XATTR_USER is not set
626 +# CONFIG_FS_MBCACHE is not set
629 # Code maturity level options
630 Index: linux-2.4.19-pre1/arch/sparc64/kernel/systbls.S
631 ===================================================================
632 --- linux-2.4.19-pre1.orig/arch/sparc64/kernel/systbls.S 2001-10-21 21:36:54.000000000 +0400
633 +++ linux-2.4.19-pre1/arch/sparc64/kernel/systbls.S 2003-11-21 03:51:05.000000000 +0300
635 /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
636 .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
637 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
638 - .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
639 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
640 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
641 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
642 - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
643 + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
644 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
645 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
646 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
647 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
648 /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
649 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
650 /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
651 @@ -111,11 +111,11 @@
652 /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
653 .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
654 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
655 - .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
656 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
657 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
658 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
659 - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
660 + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
661 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
662 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
663 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
664 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
665 /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
666 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
667 /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
668 Index: linux-2.4.19-pre1/fs/Config.in
669 ===================================================================
670 --- linux-2.4.19-pre1.orig/fs/Config.in 2003-11-20 19:01:36.000000000 +0300
671 +++ linux-2.4.19-pre1/fs/Config.in 2003-11-21 03:51:05.000000000 +0300
673 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
675 tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS
676 +dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
677 +dep_bool ' Ext3 extended attribute block sharing' \
678 + CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
679 +dep_bool ' Ext3 extended user attributes' \
680 + CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
681 # CONFIG_JBD could be its own option (even modular), but until there are
682 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
683 # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
685 tristate 'ROM file system support' CONFIG_ROMFS_FS
687 tristate 'Second extended fs support' CONFIG_EXT2_FS
688 +dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
689 +dep_bool ' Ext2 extended attribute block sharing' \
690 + CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
691 +dep_bool ' Ext2 extended user attributes' \
692 + CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
694 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
700 +# Meta block cache for Extended Attributes (ext2/ext3)
701 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
702 +define_tristate CONFIG_FS_MBCACHE y
704 mainmenu_option next_comment
705 comment 'Partition Types'
706 source fs/partitions/Config.in
707 Index: linux-2.4.19-pre1/fs/Makefile
708 ===================================================================
709 --- linux-2.4.19-pre1.orig/fs/Makefile 2003-11-21 03:51:01.000000000 +0300
710 +++ linux-2.4.19-pre1/fs/Makefile 2003-11-21 03:51:05.000000000 +0300
712 super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
713 fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
714 dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
715 - filesystems.o namespace.o seq_file.o
716 + filesystems.o namespace.o seq_file.o xattr.o
718 ifeq ($(CONFIG_QUOTA),y)
722 obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
724 +export-objs += mbcache.o
725 +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
727 # persistent filesystems
728 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
730 Index: linux-2.4.19-pre1/fs/ext2/Makefile
731 ===================================================================
732 --- linux-2.4.19-pre1.orig/fs/ext2/Makefile 2001-10-11 19:05:18.000000000 +0400
733 +++ linux-2.4.19-pre1/fs/ext2/Makefile 2003-11-21 03:51:05.000000000 +0300
735 ioctl.o namei.o super.o symlink.o
738 +export-objs += xattr.o
739 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
740 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
742 include $(TOPDIR)/Rules.make
743 Index: linux-2.4.19-pre1/fs/ext2/file.c
744 ===================================================================
745 --- linux-2.4.19-pre1.orig/fs/ext2/file.c 2001-10-11 19:05:18.000000000 +0400
746 +++ linux-2.4.19-pre1/fs/ext2/file.c 2003-11-21 03:51:05.000000000 +0300
749 #include <linux/fs.h>
750 #include <linux/ext2_fs.h>
751 +#include <linux/ext2_xattr.h>
752 #include <linux/sched.h>
757 struct inode_operations ext2_file_inode_operations = {
758 truncate: ext2_truncate,
759 + setxattr: ext2_setxattr,
760 + getxattr: ext2_getxattr,
761 + listxattr: ext2_listxattr,
762 + removexattr: ext2_removexattr,
764 Index: linux-2.4.19-pre1/fs/ext2/ialloc.c
765 ===================================================================
766 --- linux-2.4.19-pre1.orig/fs/ext2/ialloc.c 2003-11-20 19:01:36.000000000 +0300
767 +++ linux-2.4.19-pre1/fs/ext2/ialloc.c 2003-11-21 03:51:05.000000000 +0300
769 #include <linux/config.h>
770 #include <linux/fs.h>
771 #include <linux/ext2_fs.h>
772 +#include <linux/ext2_xattr.h>
773 #include <linux/locks.h>
774 #include <linux/quotaops.h>
778 if (!is_bad_inode(inode)) {
779 /* Quota is already initialized in iput() */
780 + ext2_xattr_delete_inode(inode);
781 DQUOT_FREE_INODE(inode);
784 Index: linux-2.4.19-pre1/fs/ext2/inode.c
785 ===================================================================
786 --- linux-2.4.19-pre1.orig/fs/ext2/inode.c 2003-11-20 19:01:36.000000000 +0300
787 +++ linux-2.4.19-pre1/fs/ext2/inode.c 2003-11-21 03:51:05.000000000 +0300
789 static int ext2_update_inode(struct inode * inode, int do_sync);
792 + * Test whether an inode is a fast symlink.
794 +static inline int ext2_inode_is_fast_symlink(struct inode *inode)
796 + int ea_blocks = inode->u.ext2_i.i_file_acl ?
797 + (inode->i_sb->s_blocksize >> 9) : 0;
799 + return (S_ISLNK(inode->i_mode) &&
800 + inode->i_blocks - ea_blocks == 0);
804 * Called at each iput()
806 void ext2_put_inode (struct inode * inode)
811 - if (is_bad_inode(inode) ||
812 - inode->i_ino == EXT2_ACL_IDX_INO ||
813 - inode->i_ino == EXT2_ACL_DATA_INO)
814 + if (is_bad_inode(inode))
816 inode->u.ext2_i.i_dtime = CURRENT_TIME;
817 mark_inode_dirty(inode);
819 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
820 S_ISLNK(inode->i_mode)))
822 + if (ext2_inode_is_fast_symlink(inode))
824 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
828 unsigned long offset;
829 struct ext2_group_desc * gdp;
831 - if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
832 - inode->i_ino != EXT2_ACL_DATA_INO &&
833 + if ((inode->i_ino != EXT2_ROOT_INO &&
834 inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
835 inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
836 ext2_error (inode->i_sb, "ext2_read_inode",
838 for (block = 0; block < EXT2_N_BLOCKS; block++)
839 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
841 - if (inode->i_ino == EXT2_ACL_IDX_INO ||
842 - inode->i_ino == EXT2_ACL_DATA_INO)
843 - /* Nothing to do */ ;
844 - else if (S_ISREG(inode->i_mode)) {
845 + if (S_ISREG(inode->i_mode)) {
846 inode->i_op = &ext2_file_inode_operations;
847 inode->i_fop = &ext2_file_operations;
848 inode->i_mapping->a_ops = &ext2_aops;
849 @@ -987,15 +995,17 @@
850 inode->i_fop = &ext2_dir_operations;
851 inode->i_mapping->a_ops = &ext2_aops;
852 } else if (S_ISLNK(inode->i_mode)) {
853 - if (!inode->i_blocks)
854 + if (ext2_inode_is_fast_symlink(inode))
855 inode->i_op = &ext2_fast_symlink_inode_operations;
857 - inode->i_op = &page_symlink_inode_operations;
858 + inode->i_op = &ext2_symlink_inode_operations;
859 inode->i_mapping->a_ops = &ext2_aops;
863 + inode->i_op = &ext2_special_inode_operations;
864 init_special_inode(inode, inode->i_mode,
865 le32_to_cpu(raw_inode->i_block[0]));
868 inode->i_attr_flags = 0;
869 if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
870 Index: linux-2.4.19-pre1/fs/ext2/namei.c
871 ===================================================================
872 --- linux-2.4.19-pre1.orig/fs/ext2/namei.c 2001-10-04 09:57:36.000000000 +0400
873 +++ linux-2.4.19-pre1/fs/ext2/namei.c 2003-11-21 03:51:05.000000000 +0300
876 #include <linux/fs.h>
877 #include <linux/ext2_fs.h>
878 +#include <linux/ext2_xattr.h>
879 #include <linux/pagemap.h>
884 if (l > sizeof (inode->u.ext2_i.i_data)) {
886 - inode->i_op = &page_symlink_inode_operations;
887 + inode->i_op = &ext2_symlink_inode_operations;
888 inode->i_mapping->a_ops = &ext2_aops;
889 err = block_symlink(inode, symname, l);
895 + setxattr: ext2_setxattr,
896 + getxattr: ext2_getxattr,
897 + listxattr: ext2_listxattr,
898 + removexattr: ext2_removexattr,
901 +struct inode_operations ext2_special_inode_operations = {
902 + setxattr: ext2_setxattr,
903 + getxattr: ext2_getxattr,
904 + listxattr: ext2_listxattr,
905 + removexattr: ext2_removexattr,
907 Index: linux-2.4.19-pre1/fs/ext2/super.c
908 ===================================================================
909 --- linux-2.4.19-pre1.orig/fs/ext2/super.c 2003-11-20 19:01:36.000000000 +0300
910 +++ linux-2.4.19-pre1/fs/ext2/super.c 2003-11-21 03:51:05.000000000 +0300
912 #include <linux/string.h>
913 #include <linux/fs.h>
914 #include <linux/ext2_fs.h>
915 +#include <linux/ext2_xattr.h>
916 #include <linux/slab.h>
917 #include <linux/init.h>
918 #include <linux/locks.h>
923 + ext2_xattr_put_super(sb);
924 if (!(sb->s_flags & MS_RDONLY)) {
925 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
928 this_char = strtok (NULL, ",")) {
929 if ((value = strchr (this_char, '=')) != NULL)
931 +#ifdef CONFIG_EXT2_FS_XATTR_USER
932 + if (!strcmp (this_char, "user_xattr"))
933 + set_opt (*mount_options, XATTR_USER);
934 + else if (!strcmp (this_char, "nouser_xattr"))
935 + clear_opt (*mount_options, XATTR_USER);
938 if (!strcmp (this_char, "bsddf"))
939 clear_opt (*mount_options, MINIX_DF);
940 else if (!strcmp (this_char, "nouid32")) {
942 blocksize = BLOCK_SIZE;
944 sb->u.ext2_sb.s_mount_opt = 0;
945 +#ifdef CONFIG_EXT2_FS_XATTR_USER
946 + /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
948 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
949 &sb->u.ext2_sb.s_mount_opt)) {
951 @@ -810,12 +822,27 @@
953 static int __init init_ext2_fs(void)
955 - return register_filesystem(&ext2_fs_type);
956 + int error = init_ext2_xattr();
959 + error = init_ext2_xattr_user();
962 + error = register_filesystem(&ext2_fs_type);
966 + exit_ext2_xattr_user();
972 static void __exit exit_ext2_fs(void)
974 unregister_filesystem(&ext2_fs_type);
975 + exit_ext2_xattr_user();
980 Index: linux-2.4.19-pre1/fs/ext2/symlink.c
981 ===================================================================
982 --- linux-2.4.19-pre1.orig/fs/ext2/symlink.c 2000-09-28 00:41:33.000000000 +0400
983 +++ linux-2.4.19-pre1/fs/ext2/symlink.c 2003-11-21 03:51:05.000000000 +0300
986 #include <linux/fs.h>
987 #include <linux/ext2_fs.h>
988 +#include <linux/ext2_xattr.h>
990 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
993 return vfs_follow_link(nd, s);
996 +struct inode_operations ext2_symlink_inode_operations = {
997 + readlink: page_readlink,
998 + follow_link: page_follow_link,
999 + setxattr: ext2_setxattr,
1000 + getxattr: ext2_getxattr,
1001 + listxattr: ext2_listxattr,
1002 + removexattr: ext2_removexattr,
1005 struct inode_operations ext2_fast_symlink_inode_operations = {
1006 readlink: ext2_readlink,
1007 follow_link: ext2_follow_link,
1008 + setxattr: ext2_setxattr,
1009 + getxattr: ext2_getxattr,
1010 + listxattr: ext2_listxattr,
1011 + removexattr: ext2_removexattr,
1013 Index: linux-2.4.19-pre1/fs/ext2/xattr.c
1014 ===================================================================
1015 --- linux-2.4.19-pre1.orig/fs/ext2/xattr.c 2003-11-21 03:51:05.000000000 +0300
1016 +++ linux-2.4.19-pre1/fs/ext2/xattr.c 2003-11-21 03:51:05.000000000 +0300
1019 + * linux/fs/ext2/xattr.c
1021 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
1023 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
1024 + * Extended attributes for symlinks and special files added per
1025 + * suggestion of Luka Renko <luka.renko@hermes.si>.
1029 + * Extended attributes are stored on disk blocks allocated outside of
1030 + * any inode. The i_file_acl field is then made to point to this allocated
1031 + * block. If all extended attributes of an inode are identical, these
1032 + * inodes may share the same extended attribute block. Such situations
1033 + * are automatically detected by keeping a cache of recent attribute block
1034 + * numbers and hashes over the block's contents in memory.
1037 + * Extended attribute block layout:
1039 + * +------------------+
1042 + * | entry 2 | | growing downwards
1044 + * | four null bytes |
1047 + * | value 3 | | growing upwards
1049 + * +------------------+
1051 + * The block header is followed by multiple entry descriptors. These entry
1052 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
1053 + * byte boundaries. The entry descriptors are sorted by attribute name,
1054 + * so that two extended attribute blocks can be compared efficiently.
1056 + * Attribute values are aligned to the end of the block, stored in
1057 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
1058 + * boundaries. No additional gaps are left between them.
1060 + * Locking strategy
1061 + * ----------------
1062 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
1063 + * the xattr inode operations are called, so we are guaranteed that only one
1064 + * processes accesses extended attributes of an inode at any time.
1066 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
1067 + * only a single process is modifying an extended attribute block, even
1068 + * if the block is shared among inodes.
1070 + * Note for porting to 2.5
1071 + * -----------------------
1072 + * The BKL will no longer be held in the xattr inode operations.
1075 +#include <linux/module.h>
1076 +#include <linux/locks.h>
1077 +#include <linux/slab.h>
1078 +#include <linux/fs.h>
1079 +#include <linux/ext2_fs.h>
1080 +#include <linux/ext2_xattr.h>
1081 +#include <linux/mbcache.h>
1082 +#include <linux/quotaops.h>
1083 +#include <asm/semaphore.h>
1084 +#include <linux/compatmac.h>
1086 +/* These symbols may be needed by a module. */
1087 +EXPORT_SYMBOL(ext2_xattr_register);
1088 +EXPORT_SYMBOL(ext2_xattr_unregister);
1089 +EXPORT_SYMBOL(ext2_xattr_get);
1090 +EXPORT_SYMBOL(ext2_xattr_list);
1091 +EXPORT_SYMBOL(ext2_xattr_set);
1093 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1094 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
1097 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
1098 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
1099 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
1100 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
1102 +#ifdef EXT2_XATTR_DEBUG
1103 +# define ea_idebug(inode, f...) do { \
1104 + printk(KERN_DEBUG "inode %s:%ld: ", \
1105 + kdevname(inode->i_dev), inode->i_ino); \
1109 +# define ea_bdebug(bh, f...) do { \
1110 + printk(KERN_DEBUG "block %s:%ld: ", \
1111 + kdevname(bh->b_dev), bh->b_blocknr); \
1116 +# define ea_idebug(f...)
1117 +# define ea_bdebug(f...)
1120 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
1121 + struct ext2_xattr_header *);
1123 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1125 +static int ext2_xattr_cache_insert(struct buffer_head *);
1126 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
1127 + struct ext2_xattr_header *);
1128 +static void ext2_xattr_cache_remove(struct buffer_head *);
1129 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
1130 + struct ext2_xattr_entry *);
1132 +static struct mb_cache *ext2_xattr_cache;
1135 +# define ext2_xattr_cache_insert(bh) 0
1136 +# define ext2_xattr_cache_find(inode, header) NULL
1137 +# define ext2_xattr_cache_remove(bh) while(0) {}
1138 +# define ext2_xattr_rehash(header, entry) while(0) {}
1142 + * If a file system does not share extended attributes among inodes,
1143 + * we should not need the ext2_xattr_sem semaphore. However, the
1144 + * filesystem may still contain shared blocks, so we always take
1148 +DECLARE_MUTEX(ext2_xattr_sem);
1151 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
1153 + struct super_block *sb = inode->i_sb;
1154 + int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
1155 + EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
1157 + /* How can we enforce the allocation? */
1158 + int block = ext2_new_block(inode, goal, 0, 0, errp);
1161 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1167 +ext2_xattr_quota_alloc(struct inode *inode, int force)
1169 + /* How can we enforce the allocation? */
1171 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
1173 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1175 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
1183 +ext2_xattr_quota_free(struct inode *inode)
1185 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
1186 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1190 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
1192 + ext2_free_blocks(inode, block, 1);
1193 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1197 +# define ext2_xattr_quota_free(inode) \
1198 + DQUOT_FREE_BLOCK(inode, 1)
1199 +# define ext2_xattr_free_block(inode, block) \
1200 + ext2_free_blocks(inode, block, 1)
1203 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1205 +static inline struct buffer_head *
1206 +sb_bread(struct super_block *sb, int block)
1208 + return bread(sb->s_dev, block, sb->s_blocksize);
1211 +static inline struct buffer_head *
1212 +sb_getblk(struct super_block *sb, int block)
1214 + return getblk(sb->s_dev, block, sb->s_blocksize);
1219 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1220 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1223 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1225 + int error = -EINVAL;
1227 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1228 + write_lock(&ext2_handler_lock);
1229 + if (!ext2_xattr_handlers[name_index-1]) {
1230 + ext2_xattr_handlers[name_index-1] = handler;
1233 + write_unlock(&ext2_handler_lock);
1239 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1241 + if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
1242 + write_lock(&ext2_handler_lock);
1243 + ext2_xattr_handlers[name_index-1] = NULL;
1244 + write_unlock(&ext2_handler_lock);
1248 +static inline const char *
1249 +strcmp_prefix(const char *a, const char *a_prefix)
1251 + while (*a_prefix && *a == *a_prefix) {
1255 + return *a_prefix ? NULL : a;
1259 + * Decode the extended attribute name, and translate it into
1260 + * the name_index and name suffix.
1262 +static struct ext2_xattr_handler *
1263 +ext2_xattr_resolve_name(const char **name)
1265 + struct ext2_xattr_handler *handler = NULL;
1270 + read_lock(&ext2_handler_lock);
1271 + for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1272 + if (ext2_xattr_handlers[i]) {
1273 + const char *n = strcmp_prefix(*name,
1274 + ext2_xattr_handlers[i]->prefix);
1276 + handler = ext2_xattr_handlers[i];
1282 + read_unlock(&ext2_handler_lock);
1286 +static inline struct ext2_xattr_handler *
1287 +ext2_xattr_handler(int name_index)
1289 + struct ext2_xattr_handler *handler = NULL;
1290 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1291 + read_lock(&ext2_handler_lock);
1292 + handler = ext2_xattr_handlers[name_index-1];
1293 + read_unlock(&ext2_handler_lock);
1299 + * Inode operation getxattr()
1301 + * dentry->d_inode->i_sem down
1302 + * BKL held [before 2.5.x]
1305 +ext2_getxattr(struct dentry *dentry, const char *name,
1306 + void *buffer, size_t size)
1308 + struct ext2_xattr_handler *handler;
1309 + struct inode *inode = dentry->d_inode;
1311 + handler = ext2_xattr_resolve_name(&name);
1314 + return handler->get(inode, name, buffer, size);
1318 + * Inode operation listxattr()
1320 + * dentry->d_inode->i_sem down
1321 + * BKL held [before 2.5.x]
1324 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1326 + return ext2_xattr_list(dentry->d_inode, buffer, size);
1330 + * Inode operation setxattr()
1332 + * dentry->d_inode->i_sem down
1333 + * BKL held [before 2.5.x]
1336 +ext2_setxattr(struct dentry *dentry, const char *name,
1337 + const void *value, size_t size, int flags)
1339 + struct ext2_xattr_handler *handler;
1340 + struct inode *inode = dentry->d_inode;
1343 + value = ""; /* empty EA, do not remove */
1344 + handler = ext2_xattr_resolve_name(&name);
1347 + return handler->set(inode, name, value, size, flags);
1351 + * Inode operation removexattr()
1353 + * dentry->d_inode->i_sem down
1354 + * BKL held [before 2.5.x]
1357 +ext2_removexattr(struct dentry *dentry, const char *name)
1359 + struct ext2_xattr_handler *handler;
1360 + struct inode *inode = dentry->d_inode;
1362 + handler = ext2_xattr_resolve_name(&name);
1365 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1369 + * ext2_xattr_get()
1371 + * Copy an extended attribute into the buffer
1372 + * provided, or compute the buffer size required.
1373 + * Buffer is NULL to compute the size of the buffer required.
1375 + * Returns a negative error number on failure, or the number of bytes
1376 + * used / required on success.
1379 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1380 + void *buffer, size_t buffer_size)
1382 + struct buffer_head *bh = NULL;
1383 + struct ext2_xattr_entry *entry;
1384 + unsigned int block, size;
1386 + int name_len, error;
1388 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1389 + name_index, name, buffer, (long)buffer_size);
1393 + if (!EXT2_I(inode)->i_file_acl)
1395 + block = EXT2_I(inode)->i_file_acl;
1396 + ea_idebug(inode, "reading block %d", block);
1397 + bh = sb_bread(inode->i_sb, block);
1400 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1401 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1402 + end = bh->b_data + bh->b_size;
1403 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1404 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1405 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
1406 + "inode %ld: bad block %d", inode->i_ino, block);
1410 + /* find named attribute */
1411 + name_len = strlen(name);
1414 + if (name_len > 255)
1416 + entry = FIRST_ENTRY(bh);
1417 + while (!IS_LAST_ENTRY(entry)) {
1418 + struct ext2_xattr_entry *next =
1419 + EXT2_XATTR_NEXT(entry);
1420 + if ((char *)next >= end)
1422 + if (name_index == entry->e_name_index &&
1423 + name_len == entry->e_name_len &&
1424 + memcmp(name, entry->e_name, name_len) == 0)
1428 + /* Check the remaining name entries */
1429 + while (!IS_LAST_ENTRY(entry)) {
1430 + struct ext2_xattr_entry *next =
1431 + EXT2_XATTR_NEXT(entry);
1432 + if ((char *)next >= end)
1436 + if (ext2_xattr_cache_insert(bh))
1437 + ea_idebug(inode, "cache insert failed");
1441 + /* check the buffer size */
1442 + if (entry->e_value_block != 0)
1444 + size = le32_to_cpu(entry->e_value_size);
1445 + if (size > inode->i_sb->s_blocksize ||
1446 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1449 + if (ext2_xattr_cache_insert(bh))
1450 + ea_idebug(inode, "cache insert failed");
1453 + if (size > buffer_size)
1455 + /* return value of attribute */
1456 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1468 + * ext2_xattr_list()
1470 + * Copy a list of attribute names into the buffer
1471 + * provided, or compute the buffer size required.
1472 + * Buffer is NULL to compute the size of the buffer required.
1474 + * Returns a negative error number on failure, or the number of bytes
1475 + * used / required on success.
1478 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1480 + struct buffer_head *bh = NULL;
1481 + struct ext2_xattr_entry *entry;
1482 + unsigned int block, size = 0;
1486 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1487 + buffer, (long)buffer_size);
1489 + if (!EXT2_I(inode)->i_file_acl)
1491 + block = EXT2_I(inode)->i_file_acl;
1492 + ea_idebug(inode, "reading block %d", block);
1493 + bh = sb_bread(inode->i_sb, block);
1496 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1497 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1498 + end = bh->b_data + bh->b_size;
1499 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1500 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1501 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
1502 + "inode %ld: bad block %d", inode->i_ino, block);
1506 + /* compute the size required for the list of attribute names */
1507 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1508 + entry = EXT2_XATTR_NEXT(entry)) {
1509 + struct ext2_xattr_handler *handler;
1510 + struct ext2_xattr_entry *next =
1511 + EXT2_XATTR_NEXT(entry);
1512 + if ((char *)next >= end)
1515 + handler = ext2_xattr_handler(entry->e_name_index);
1517 + size += handler->list(NULL, inode, entry->e_name,
1518 + entry->e_name_len);
1521 + if (ext2_xattr_cache_insert(bh))
1522 + ea_idebug(inode, "cache insert failed");
1528 + if (size > buffer_size)
1532 + /* list the attribute names */
1534 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1535 + entry = EXT2_XATTR_NEXT(entry)) {
1536 + struct ext2_xattr_handler *handler;
1538 + handler = ext2_xattr_handler(entry->e_name_index);
1540 + buf += handler->list(buf, inode, entry->e_name,
1541 + entry->e_name_len);
1552 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1553 + * not set, set it.
1555 +static void ext2_xattr_update_super_block(struct super_block *sb)
1557 + if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1561 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1562 + EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1564 + EXT2_SB(sb)->s_es->s_feature_compat |=
1565 + cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1567 + mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1572 + * ext2_xattr_set()
1574 + * Create, replace or remove an extended attribute for this inode. Buffer
1575 + * is NULL to remove an existing extended attribute, and non-NULL to
1576 + * either replace an existing extended attribute, or create a new extended
1577 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1578 + * specify that an extended attribute must exist and must not exist
1579 + * previous to the call, respectively.
1581 + * Returns 0, or a negative error number on failure.
1584 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1585 + const void *value, size_t value_len, int flags)
1587 + struct super_block *sb = inode->i_sb;
1588 + struct buffer_head *bh = NULL;
1589 + struct ext2_xattr_header *header = NULL;
1590 + struct ext2_xattr_entry *here, *last;
1591 + unsigned int name_len;
1592 + int block = EXT2_I(inode)->i_file_acl;
1593 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
1597 + * header -- Points either into bh, or to a temporarily
1598 + * allocated buffer.
1599 + * here -- The named entry found, or the place for inserting, within
1600 + * the block pointed to by header.
1601 + * last -- Points right after the last named entry within the block
1602 + * pointed to by header.
1603 + * min_offs -- The offset of the first value (values are aligned
1604 + * towards the end of the block).
1605 + * end -- Points right after the block pointed to by header.
1608 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1609 + name_index, name, value, (long)value_len);
1611 + if (IS_RDONLY(inode))
1613 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1615 + if (value == NULL)
1619 + name_len = strlen(name);
1620 + if (name_len > 255 || value_len > sb->s_blocksize)
1622 + down(&ext2_xattr_sem);
1625 + /* The inode already has an extended attribute block. */
1627 + bh = sb_bread(sb, block);
1631 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1632 + atomic_read(&(bh->b_count)),
1633 + le32_to_cpu(HDR(bh)->h_refcount));
1635 + end = bh->b_data + bh->b_size;
1636 + if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1637 + header->h_blocks != cpu_to_le32(1)) {
1638 +bad_block: ext2_error(sb, "ext2_xattr_set",
1639 + "inode %ld: bad block %d", inode->i_ino, block);
1643 + /* Find the named attribute. */
1644 + here = FIRST_ENTRY(bh);
1645 + while (!IS_LAST_ENTRY(here)) {
1646 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1647 + if ((char *)next >= end)
1649 + if (!here->e_value_block && here->e_value_size) {
1650 + int offs = le16_to_cpu(here->e_value_offs);
1651 + if (offs < min_offs)
1654 + not_found = name_index - here->e_name_index;
1656 + not_found = name_len - here->e_name_len;
1658 + not_found = memcmp(name, here->e_name,name_len);
1659 + if (not_found <= 0)
1664 + /* We still need to compute min_offs and last. */
1665 + while (!IS_LAST_ENTRY(last)) {
1666 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1667 + if ((char *)next >= end)
1669 + if (!last->e_value_block && last->e_value_size) {
1670 + int offs = le16_to_cpu(last->e_value_offs);
1671 + if (offs < min_offs)
1677 + /* Check whether we have enough space left. */
1678 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1680 + /* We will use a new extended attribute block. */
1681 + free = sb->s_blocksize -
1682 + sizeof(struct ext2_xattr_header) - sizeof(__u32);
1683 + here = last = NULL; /* avoid gcc uninitialized warning. */
1687 + /* Request to remove a nonexistent attribute? */
1689 + if (flags & XATTR_REPLACE)
1692 + if (value == NULL)
1695 + free -= EXT2_XATTR_LEN(name_len);
1697 + /* Request to create an existing attribute? */
1699 + if (flags & XATTR_CREATE)
1701 + if (!here->e_value_block && here->e_value_size) {
1702 + unsigned int size = le32_to_cpu(here->e_value_size);
1704 + if (le16_to_cpu(here->e_value_offs) + size >
1705 + sb->s_blocksize || size > sb->s_blocksize)
1707 + free += EXT2_XATTR_SIZE(size);
1710 + free -= EXT2_XATTR_SIZE(value_len);
1715 + /* Here we know that we can set the new attribute. */
1718 + if (header->h_refcount == cpu_to_le32(1)) {
1719 + ea_bdebug(bh, "modifying in-place");
1720 + ext2_xattr_cache_remove(bh);
1724 + ea_bdebug(bh, "cloning");
1725 + header = kmalloc(bh->b_size, GFP_KERNEL);
1727 + if (header == NULL)
1729 + memcpy(header, HDR(bh), bh->b_size);
1730 + header->h_refcount = cpu_to_le32(1);
1731 + offset = (char *)header - bh->b_data;
1732 + here = ENTRY((char *)here + offset);
1733 + last = ENTRY((char *)last + offset);
1736 + /* Allocate a buffer where we construct the new block. */
1737 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1739 + if (header == NULL)
1741 + memset(header, 0, sb->s_blocksize);
1742 + end = (char *)header + sb->s_blocksize;
1743 + header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1744 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
1745 + last = here = ENTRY(header+1);
1749 + /* Insert the new name. */
1750 + int size = EXT2_XATTR_LEN(name_len);
1751 + int rest = (char *)last - (char *)here;
1752 + memmove((char *)here + size, here, rest);
1753 + memset(here, 0, size);
1754 + here->e_name_index = name_index;
1755 + here->e_name_len = name_len;
1756 + memcpy(here->e_name, name, name_len);
1758 + /* Remove the old value. */
1759 + if (!here->e_value_block && here->e_value_size) {
1760 + char *first_val = (char *)header + min_offs;
1761 + int offs = le16_to_cpu(here->e_value_offs);
1762 + char *val = (char *)header + offs;
1763 + size_t size = EXT2_XATTR_SIZE(
1764 + le32_to_cpu(here->e_value_size));
1765 + memmove(first_val + size, first_val, val - first_val);
1766 + memset(first_val, 0, size);
1767 + here->e_value_offs = 0;
1770 + /* Adjust all value offsets. */
1771 + last = ENTRY(header+1);
1772 + while (!IS_LAST_ENTRY(last)) {
1773 + int o = le16_to_cpu(last->e_value_offs);
1774 + if (!last->e_value_block && o < offs)
1775 + last->e_value_offs =
1776 + cpu_to_le16(o + size);
1777 + last = EXT2_XATTR_NEXT(last);
1780 + if (value == NULL) {
1781 + /* Remove this attribute. */
1782 + if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1783 + /* This block is now empty. */
1784 + error = ext2_xattr_set2(inode, bh, NULL);
1787 + /* Remove the old name. */
1788 + int size = EXT2_XATTR_LEN(name_len);
1789 + last = ENTRY((char *)last - size);
1790 + memmove(here, (char*)here + size,
1791 + (char*)last - (char*)here);
1792 + memset(last, 0, size);
1797 + if (value != NULL) {
1798 + /* Insert the new value. */
1799 + here->e_value_size = cpu_to_le32(value_len);
1801 + size_t size = EXT2_XATTR_SIZE(value_len);
1802 + char *val = (char *)header + min_offs - size;
1803 + here->e_value_offs =
1804 + cpu_to_le16((char *)val - (char *)header);
1805 + memset(val + size - EXT2_XATTR_PAD, 0,
1806 + EXT2_XATTR_PAD); /* Clear the pad bytes. */
1807 + memcpy(val, value, value_len);
1810 + ext2_xattr_rehash(header, here);
1812 + error = ext2_xattr_set2(inode, bh, header);
1816 + if (!(bh && header == HDR(bh)))
1818 + up(&ext2_xattr_sem);
1824 + * Second half of ext2_xattr_set(): Update the file system.
1827 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1828 + struct ext2_xattr_header *header)
1830 + struct super_block *sb = inode->i_sb;
1831 + struct buffer_head *new_bh = NULL;
1835 + new_bh = ext2_xattr_cache_find(inode, header);
1838 + * We found an identical block in the cache.
1839 + * The old block will be released after updating
1842 + ea_bdebug(old_bh, "reusing block %ld",
1843 + new_bh->b_blocknr);
1846 + if (ext2_xattr_quota_alloc(inode, 1))
1849 + HDR(new_bh)->h_refcount = cpu_to_le32(
1850 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1851 + ea_bdebug(new_bh, "refcount now=%d",
1852 + le32_to_cpu(HDR(new_bh)->h_refcount));
1853 + } else if (old_bh && header == HDR(old_bh)) {
1854 + /* Keep this block. */
1856 + ext2_xattr_cache_insert(new_bh);
1858 + /* We need to allocate a new block */
1859 + int force = EXT2_I(inode)->i_file_acl != 0;
1860 + int block = ext2_xattr_new_block(inode, &error, force);
1863 + ea_idebug(inode, "creating block %d", block);
1865 + new_bh = sb_getblk(sb, block);
1867 + ext2_xattr_free_block(inode, block);
1871 + lock_buffer(new_bh);
1872 + memcpy(new_bh->b_data, header, new_bh->b_size);
1873 + mark_buffer_uptodate(new_bh, 1);
1874 + unlock_buffer(new_bh);
1875 + ext2_xattr_cache_insert(new_bh);
1877 + ext2_xattr_update_super_block(sb);
1879 + mark_buffer_dirty(new_bh);
1880 + if (IS_SYNC(inode)) {
1881 + ll_rw_block(WRITE, 1, &new_bh);
1882 + wait_on_buffer(new_bh);
1884 + if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1889 + /* Update the inode. */
1890 + EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1891 + inode->i_ctime = CURRENT_TIME;
1892 + if (IS_SYNC(inode)) {
1893 + error = ext2_sync_inode (inode);
1897 + mark_inode_dirty(inode);
1900 + if (old_bh && old_bh != new_bh) {
1902 + * If there was an old block, and we are not still using it,
1903 + * we now release the old block.
1905 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1907 + if (refcount == 1) {
1908 + /* Free the old block. */
1909 + ea_bdebug(old_bh, "freeing");
1910 + ext2_xattr_free_block(inode, old_bh->b_blocknr);
1911 + mark_buffer_clean(old_bh);
1913 + /* Decrement the refcount only. */
1915 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1916 + ext2_xattr_quota_free(inode);
1917 + mark_buffer_dirty(old_bh);
1918 + ea_bdebug(old_bh, "refcount now=%d", refcount);
1923 + if (old_bh != new_bh)
1930 + * ext2_xattr_delete_inode()
1932 + * Free extended attribute resources associated with this inode. This
1933 + * is called immediately before an inode is freed.
1936 +ext2_xattr_delete_inode(struct inode *inode)
1938 + struct buffer_head *bh;
1939 + unsigned int block = EXT2_I(inode)->i_file_acl;
1943 + down(&ext2_xattr_sem);
1945 + bh = sb_bread(inode->i_sb, block);
1947 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1948 + "inode %ld: block %d read error", inode->i_ino, block);
1951 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1952 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1953 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1954 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1955 + "inode %ld: bad block %d", inode->i_ino, block);
1958 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1959 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1960 + ext2_xattr_cache_remove(bh);
1961 + ext2_xattr_free_block(inode, block);
1965 + HDR(bh)->h_refcount = cpu_to_le32(
1966 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
1967 + mark_buffer_dirty(bh);
1968 + if (IS_SYNC(inode)) {
1969 + ll_rw_block(WRITE, 1, &bh);
1970 + wait_on_buffer(bh);
1972 + ext2_xattr_quota_free(inode);
1974 + EXT2_I(inode)->i_file_acl = 0;
1978 + up(&ext2_xattr_sem);
1982 + * ext2_xattr_put_super()
1984 + * This is called when a file system is unmounted.
1987 +ext2_xattr_put_super(struct super_block *sb)
1989 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1990 + mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
1994 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1997 + * ext2_xattr_cache_insert()
1999 + * Create a new entry in the extended attribute cache, and insert
2000 + * it unless such an entry is already in the cache.
2002 + * Returns 0, or a negative error number on failure.
2005 +ext2_xattr_cache_insert(struct buffer_head *bh)
2007 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
2008 + struct mb_cache_entry *ce;
2011 + ce = mb_cache_entry_alloc(ext2_xattr_cache);
2014 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
2016 + mb_cache_entry_free(ce);
2017 + if (error == -EBUSY) {
2018 + ea_bdebug(bh, "already in cache (%d cache entries)",
2019 + atomic_read(&ext2_xattr_cache->c_entry_count));
2023 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
2024 + atomic_read(&ext2_xattr_cache->c_entry_count));
2025 + mb_cache_entry_release(ce);
2031 + * ext2_xattr_cmp()
2033 + * Compare two extended attribute blocks for equality.
2035 + * Returns 0 if the blocks are equal, 1 if they differ, and
2036 + * a negative error number on errors.
2039 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
2040 + struct ext2_xattr_header *header2)
2042 + struct ext2_xattr_entry *entry1, *entry2;
2044 + entry1 = ENTRY(header1+1);
2045 + entry2 = ENTRY(header2+1);
2046 + while (!IS_LAST_ENTRY(entry1)) {
2047 + if (IS_LAST_ENTRY(entry2))
2049 + if (entry1->e_hash != entry2->e_hash ||
2050 + entry1->e_name_len != entry2->e_name_len ||
2051 + entry1->e_value_size != entry2->e_value_size ||
2052 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
2054 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
2056 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
2057 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
2058 + le32_to_cpu(entry1->e_value_size)))
2061 + entry1 = EXT2_XATTR_NEXT(entry1);
2062 + entry2 = EXT2_XATTR_NEXT(entry2);
2064 + if (!IS_LAST_ENTRY(entry2))
2070 + * ext2_xattr_cache_find()
2072 + * Find an identical extended attribute block.
2074 + * Returns a pointer to the block found, or NULL if such a block was
2075 + * not found or an error occurred.
2077 +static struct buffer_head *
2078 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
2080 + __u32 hash = le32_to_cpu(header->h_hash);
2081 + struct mb_cache_entry *ce;
2083 + if (!header->h_hash)
2084 + return NULL; /* never share */
2085 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
2086 + ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
2088 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
2091 + ext2_error(inode->i_sb, "ext2_xattr_cache_find",
2092 + "inode %ld: block %ld read error",
2093 + inode->i_ino, ce->e_block);
2094 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
2095 + EXT2_XATTR_REFCOUNT_MAX) {
2096 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
2097 + le32_to_cpu(HDR(bh)->h_refcount),
2098 + EXT2_XATTR_REFCOUNT_MAX);
2099 + } else if (!ext2_xattr_cmp(header, HDR(bh))) {
2100 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
2101 + mb_cache_entry_release(ce);
2105 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
2111 + * ext2_xattr_cache_remove()
2113 + * Remove the cache entry of a block from the cache. Called when a
2114 + * block becomes invalid.
2117 +ext2_xattr_cache_remove(struct buffer_head *bh)
2119 + struct mb_cache_entry *ce;
2121 + ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
2123 + ea_bdebug(bh, "removing (%d cache entries remaining)",
2124 + atomic_read(&ext2_xattr_cache->c_entry_count)-1);
2125 + mb_cache_entry_free(ce);
2127 + ea_bdebug(bh, "no cache entry");
2130 +#define NAME_HASH_SHIFT 5
2131 +#define VALUE_HASH_SHIFT 16
2134 + * ext2_xattr_hash_entry()
2136 + * Compute the hash of an extended attribute.
2138 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
2139 + struct ext2_xattr_entry *entry)
2142 + char *name = entry->e_name;
2145 + for (n=0; n < entry->e_name_len; n++) {
2146 + hash = (hash << NAME_HASH_SHIFT) ^
2147 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
2151 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
2152 + __u32 *value = (__u32 *)((char *)header +
2153 + le16_to_cpu(entry->e_value_offs));
2154 + for (n = (le32_to_cpu(entry->e_value_size) +
2155 + EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
2156 + hash = (hash << VALUE_HASH_SHIFT) ^
2157 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
2158 + le32_to_cpu(*value++);
2161 + entry->e_hash = cpu_to_le32(hash);
2164 +#undef NAME_HASH_SHIFT
2165 +#undef VALUE_HASH_SHIFT
2167 +#define BLOCK_HASH_SHIFT 16
2170 + * ext2_xattr_rehash()
2172 + * Re-compute the extended attribute hash value after an entry has changed.
2174 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
2175 + struct ext2_xattr_entry *entry)
2177 + struct ext2_xattr_entry *here;
2180 + ext2_xattr_hash_entry(header, entry);
2181 + here = ENTRY(header+1);
2182 + while (!IS_LAST_ENTRY(here)) {
2183 + if (!here->e_hash) {
2184 + /* Block is not shared if an entry's hash value == 0 */
2188 + hash = (hash << BLOCK_HASH_SHIFT) ^
2189 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
2190 + le32_to_cpu(here->e_hash);
2191 + here = EXT2_XATTR_NEXT(here);
2193 + header->h_hash = cpu_to_le32(hash);
2196 +#undef BLOCK_HASH_SHIFT
2199 +init_ext2_xattr(void)
2201 + ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
2202 + sizeof(struct mb_cache_entry) +
2203 + sizeof(struct mb_cache_entry_index), 1, 61);
2204 + if (!ext2_xattr_cache)
2211 +exit_ext2_xattr(void)
2213 + mb_cache_destroy(ext2_xattr_cache);
2216 +#else /* CONFIG_EXT2_FS_XATTR_SHARING */
2219 +init_ext2_xattr(void)
2225 +exit_ext2_xattr(void)
2229 +#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
2230 Index: linux-2.4.19-pre1/fs/ext2/xattr_user.c
2231 ===================================================================
2232 --- linux-2.4.19-pre1.orig/fs/ext2/xattr_user.c 2003-11-21 03:51:05.000000000 +0300
2233 +++ linux-2.4.19-pre1/fs/ext2/xattr_user.c 2003-11-21 03:51:05.000000000 +0300
2236 + * linux/fs/ext2/xattr_user.c
2237 + * Handler for extended user attributes.
2239 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2242 +#include <linux/module.h>
2243 +#include <linux/string.h>
2244 +#include <linux/fs.h>
2245 +#include <linux/ext2_fs.h>
2246 +#include <linux/ext2_xattr.h>
2248 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2249 +# include <linux/ext2_acl.h>
2252 +#define XATTR_USER_PREFIX "user."
2255 +ext2_xattr_user_list(char *list, struct inode *inode,
2256 + const char *name, int name_len)
2258 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2260 + if (!test_opt(inode->i_sb, XATTR_USER))
2264 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
2265 + memcpy(list+prefix_len, name, name_len);
2266 + list[prefix_len + name_len] = '\0';
2268 + return prefix_len + name_len + 1;
2272 +ext2_xattr_user_get(struct inode *inode, const char *name,
2273 + void *buffer, size_t size)
2277 + if (strcmp(name, "") == 0)
2279 + if (!test_opt(inode->i_sb, XATTR_USER))
2281 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2282 + error = ext2_permission_locked(inode, MAY_READ);
2284 + error = permission(inode, MAY_READ);
2289 + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2294 +ext2_xattr_user_set(struct inode *inode, const char *name,
2295 + const void *value, size_t size, int flags)
2299 + if (strcmp(name, "") == 0)
2301 + if (!test_opt(inode->i_sb, XATTR_USER))
2303 + if ( !S_ISREG(inode->i_mode) &&
2304 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2306 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2307 + error = ext2_permission_locked(inode, MAY_WRITE);
2309 + error = permission(inode, MAY_WRITE);
2314 + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2315 + value, size, flags);
2318 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2319 + prefix: XATTR_USER_PREFIX,
2320 + list: ext2_xattr_user_list,
2321 + get: ext2_xattr_user_get,
2322 + set: ext2_xattr_user_set,
2326 +init_ext2_xattr_user(void)
2328 + return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2329 + &ext2_xattr_user_handler);
2333 +exit_ext2_xattr_user(void)
2335 + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2336 + &ext2_xattr_user_handler);
2338 Index: linux-2.4.19-pre1/fs/ext3/Makefile
2339 ===================================================================
2340 --- linux-2.4.19-pre1.orig/fs/ext3/Makefile 2003-11-21 03:51:02.000000000 +0300
2341 +++ linux-2.4.19-pre1/fs/ext3/Makefile 2003-11-21 03:51:05.000000000 +0300
2344 -# Makefile for the linux ext2-filesystem routines.
2345 +# Makefile for the linux ext3-filesystem routines.
2347 # Note! Dependencies are done automagically by 'make dep', which also
2348 # removes any old dependencies. DON'T put your own dependencies here
2353 -export-objs := super.o inode.o
2354 +export-objs := ext3-exports.o
2356 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2357 - ioctl.o namei.o super.o symlink.o hash.o
2358 + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2359 obj-m := $(O_TARGET)
2361 +export-objs += xattr.o
2362 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2363 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2365 include $(TOPDIR)/Rules.make
2366 Index: linux-2.4.19-pre1/fs/ext3/file.c
2367 ===================================================================
2368 --- linux-2.4.19-pre1.orig/fs/ext3/file.c 2003-11-21 03:51:02.000000000 +0300
2369 +++ linux-2.4.19-pre1/fs/ext3/file.c 2003-11-21 03:51:05.000000000 +0300
2371 #include <linux/locks.h>
2372 #include <linux/jbd.h>
2373 #include <linux/ext3_fs.h>
2374 +#include <linux/ext3_xattr.h>
2375 #include <linux/ext3_jbd.h>
2376 #include <linux/smp_lock.h>
2379 struct inode_operations ext3_file_inode_operations = {
2380 truncate: ext3_truncate, /* BKL held */
2381 setattr: ext3_setattr, /* BKL held */
2382 + setxattr: ext3_setxattr, /* BKL held */
2383 + getxattr: ext3_getxattr, /* BKL held */
2384 + listxattr: ext3_listxattr, /* BKL held */
2385 + removexattr: ext3_removexattr, /* BKL held */
2388 Index: linux-2.4.19-pre1/fs/ext3/ialloc.c
2389 ===================================================================
2390 --- linux-2.4.19-pre1.orig/fs/ext3/ialloc.c 2003-11-20 19:01:36.000000000 +0300
2391 +++ linux-2.4.19-pre1/fs/ext3/ialloc.c 2003-11-21 03:51:05.000000000 +0300
2393 #include <linux/jbd.h>
2394 #include <linux/ext3_fs.h>
2395 #include <linux/ext3_jbd.h>
2396 +#include <linux/ext3_xattr.h>
2397 #include <linux/stat.h>
2398 #include <linux/string.h>
2399 #include <linux/locks.h>
2401 * as writing the quota to disk may need the lock as well.
2404 + ext3_xattr_delete_inode(handle, inode);
2405 DQUOT_FREE_INODE(inode);
2408 Index: linux-2.4.19-pre1/fs/ext3/inode.c
2409 ===================================================================
2410 --- linux-2.4.19-pre1.orig/fs/ext3/inode.c 2003-11-20 19:01:36.000000000 +0300
2411 +++ linux-2.4.19-pre1/fs/ext3/inode.c 2003-11-21 03:51:05.000000000 +0300
2414 #undef SEARCH_FROM_ZERO
2417 + * Test whether an inode is a fast symlink.
2419 +static inline int ext3_inode_is_fast_symlink(struct inode *inode)
2421 + int ea_blocks = inode->u.ext3_i.i_file_acl ?
2422 + (inode->i_sb->s_blocksize >> 9) : 0;
2424 + return (S_ISLNK(inode->i_mode) &&
2425 + inode->i_blocks - ea_blocks == 0);
2428 /* The ext3 forget function must perform a revoke if we are freeing data
2429 * which has been journaled. Metadata (eg. indirect blocks) must be
2430 * revoked in all cases.
2432 * still needs to be revoked.
2435 -static int ext3_forget(handle_t *handle, int is_metadata,
2436 +int ext3_forget(handle_t *handle, int is_metadata,
2437 struct inode *inode, struct buffer_head *bh,
2444 - if (is_bad_inode(inode) ||
2445 - inode->i_ino == EXT3_ACL_IDX_INO ||
2446 - inode->i_ino == EXT3_ACL_DATA_INO)
2447 + if (is_bad_inode(inode))
2451 @@ -1845,6 +1855,8 @@
2452 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
2453 S_ISLNK(inode->i_mode)))
2455 + if (ext3_inode_is_fast_symlink(inode))
2457 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2460 @@ -1992,8 +2004,6 @@
2461 struct ext3_group_desc * gdp;
2463 if ((inode->i_ino != EXT3_ROOT_INO &&
2464 - inode->i_ino != EXT3_ACL_IDX_INO &&
2465 - inode->i_ino != EXT3_ACL_DATA_INO &&
2466 inode->i_ino != EXT3_JOURNAL_INO &&
2467 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2468 inode->i_ino > le32_to_cpu(
2469 @@ -2120,10 +2130,7 @@
2473 - if (inode->i_ino == EXT3_ACL_IDX_INO ||
2474 - inode->i_ino == EXT3_ACL_DATA_INO)
2475 - /* Nothing to do */ ;
2476 - else if (S_ISREG(inode->i_mode)) {
2477 + if (S_ISREG(inode->i_mode)) {
2478 inode->i_op = &ext3_file_inode_operations;
2479 inode->i_fop = &ext3_file_operations;
2480 inode->i_mapping->a_ops = &ext3_aops;
2481 @@ -2131,15 +2138,17 @@
2482 inode->i_op = &ext3_dir_inode_operations;
2483 inode->i_fop = &ext3_dir_operations;
2484 } else if (S_ISLNK(inode->i_mode)) {
2485 - if (!inode->i_blocks)
2486 + if (ext3_inode_is_fast_symlink(inode))
2487 inode->i_op = &ext3_fast_symlink_inode_operations;
2489 - inode->i_op = &page_symlink_inode_operations;
2490 + inode->i_op = &ext3_symlink_inode_operations;
2491 inode->i_mapping->a_ops = &ext3_aops;
2495 + inode->i_op = &ext3_special_inode_operations;
2496 init_special_inode(inode, inode->i_mode,
2497 le32_to_cpu(iloc.raw_inode->i_block[0]));
2499 /* inode->i_attr_flags = 0; unused */
2500 if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
2501 /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
2502 Index: linux-2.4.19-pre1/fs/ext3/namei.c
2503 ===================================================================
2504 --- linux-2.4.19-pre1.orig/fs/ext3/namei.c 2003-11-21 03:51:02.000000000 +0300
2505 +++ linux-2.4.19-pre1/fs/ext3/namei.c 2003-11-21 03:51:05.000000000 +0300
2507 #include <linux/sched.h>
2508 #include <linux/ext3_fs.h>
2509 #include <linux/ext3_jbd.h>
2510 +#include <linux/ext3_xattr.h>
2511 #include <linux/fcntl.h>
2512 #include <linux/stat.h>
2513 #include <linux/string.h>
2514 @@ -1612,7 +1613,7 @@
2518 - inode = ext3_new_inode (handle, dir, S_IFDIR);
2519 + inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2520 err = PTR_ERR(inode);
2523 @@ -1620,7 +1621,6 @@
2524 inode->i_op = &ext3_dir_inode_operations;
2525 inode->i_fop = &ext3_dir_operations;
2526 inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2527 - inode->i_blocks = 0;
2528 dir_block = ext3_bread (handle, inode, 0, 1, &err);
2530 inode->i_nlink--; /* is this nlink == 0? */
2531 @@ -1647,9 +1647,6 @@
2532 BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2533 ext3_journal_dirty_metadata(handle, dir_block);
2535 - inode->i_mode = S_IFDIR | mode;
2536 - if (dir->i_mode & S_ISGID)
2537 - inode->i_mode |= S_ISGID;
2538 ext3_mark_inode_dirty(handle, inode);
2539 err = ext3_add_entry (handle, dentry, inode);
2541 @@ -2018,7 +2015,7 @@
2544 if (l > sizeof (EXT3_I(inode)->i_data)) {
2545 - inode->i_op = &page_symlink_inode_operations;
2546 + inode->i_op = &ext3_symlink_inode_operations;
2547 inode->i_mapping->a_ops = &ext3_aops;
2549 * block_symlink() calls back into ext3_prepare/commit_write.
2550 @@ -2245,4 +2242,16 @@
2551 rmdir: ext3_rmdir, /* BKL held */
2552 mknod: ext3_mknod, /* BKL held */
2553 rename: ext3_rename, /* BKL held */
2554 + setxattr: ext3_setxattr, /* BKL held */
2555 + getxattr: ext3_getxattr, /* BKL held */
2556 + listxattr: ext3_listxattr, /* BKL held */
2557 + removexattr: ext3_removexattr, /* BKL held */
2560 +struct inode_operations ext3_special_inode_operations = {
2561 + setxattr: ext3_setxattr, /* BKL held */
2562 + getxattr: ext3_getxattr, /* BKL held */
2563 + listxattr: ext3_listxattr, /* BKL held */
2564 + removexattr: ext3_removexattr, /* BKL held */
2567 Index: linux-2.4.19-pre1/fs/ext3/super.c
2568 ===================================================================
2569 --- linux-2.4.19-pre1.orig/fs/ext3/super.c 2003-11-21 03:51:02.000000000 +0300
2570 +++ linux-2.4.19-pre1/fs/ext3/super.c 2003-11-21 03:51:05.000000000 +0300
2572 #include <linux/jbd.h>
2573 #include <linux/ext3_fs.h>
2574 #include <linux/ext3_jbd.h>
2575 +#include <linux/ext3_xattr.h>
2576 #include <linux/slab.h>
2577 #include <linux/init.h>
2578 #include <linux/locks.h>
2580 kdev_t j_dev = sbi->s_journal->j_dev;
2583 + ext3_xattr_put_super(sb);
2584 journal_destroy(sbi->s_journal);
2585 if (!(sb->s_flags & MS_RDONLY)) {
2586 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2590 unsigned long *mount_options = &sbi->s_mount_opt;
2592 uid_t *resuid = &sbi->s_resuid;
2593 gid_t *resgid = &sbi->s_resgid;
2595 @@ -511,6 +514,13 @@
2596 this_char = strtok (NULL, ",")) {
2597 if ((value = strchr (this_char, '=')) != NULL)
2599 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2600 + if (!strcmp (this_char, "user_xattr"))
2601 + set_opt (*mount_options, XATTR_USER);
2602 + else if (!strcmp (this_char, "nouser_xattr"))
2603 + clear_opt (*mount_options, XATTR_USER);
2606 if (!strcmp (this_char, "bsddf"))
2607 clear_opt (*mount_options, MINIX_DF);
2608 else if (!strcmp (this_char, "nouid32")) {
2609 @@ -924,6 +934,12 @@
2610 sbi->s_mount_opt = 0;
2611 sbi->s_resuid = EXT3_DEF_RESUID;
2612 sbi->s_resgid = EXT3_DEF_RESGID;
2614 + /* Default extended attribute flags */
2615 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2616 + /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2619 if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2622 @@ -1742,17 +1758,29 @@
2624 static int __init init_ext3_fs(void)
2626 - return register_filesystem(&ext3_fs_type);
2627 + int error = init_ext3_xattr();
2630 + error = init_ext3_xattr_user();
2633 + error = register_filesystem(&ext3_fs_type);
2637 + exit_ext3_xattr_user();
2639 + exit_ext3_xattr();
2643 static void __exit exit_ext3_fs(void)
2645 unregister_filesystem(&ext3_fs_type);
2646 + exit_ext3_xattr_user();
2647 + exit_ext3_xattr();
2650 -EXPORT_SYMBOL(ext3_force_commit);
2651 -EXPORT_SYMBOL(ext3_bread);
2653 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2654 MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2655 MODULE_LICENSE("GPL");
2656 Index: linux-2.4.19-pre1/fs/ext3/symlink.c
2657 ===================================================================
2658 --- linux-2.4.19-pre1.orig/fs/ext3/symlink.c 2001-11-10 01:25:04.000000000 +0300
2659 +++ linux-2.4.19-pre1/fs/ext3/symlink.c 2003-11-21 03:51:05.000000000 +0300
2661 #include <linux/fs.h>
2662 #include <linux/jbd.h>
2663 #include <linux/ext3_fs.h>
2664 +#include <linux/ext3_xattr.h>
2666 static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2669 return vfs_follow_link(nd, s);
2672 +struct inode_operations ext3_symlink_inode_operations = {
2673 + readlink: page_readlink, /* BKL not held. Don't need */
2674 + follow_link: page_follow_link, /* BKL not held. Don't need */
2675 + setxattr: ext3_setxattr, /* BKL held */
2676 + getxattr: ext3_getxattr, /* BKL held */
2677 + listxattr: ext3_listxattr, /* BKL held */
2678 + removexattr: ext3_removexattr, /* BKL held */
2681 struct inode_operations ext3_fast_symlink_inode_operations = {
2682 readlink: ext3_readlink, /* BKL not held. Don't need */
2683 follow_link: ext3_follow_link, /* BKL not held. Don't need */
2684 + setxattr: ext3_setxattr, /* BKL held */
2685 + getxattr: ext3_getxattr, /* BKL held */
2686 + listxattr: ext3_listxattr, /* BKL held */
2687 + removexattr: ext3_removexattr, /* BKL held */
2689 Index: linux-2.4.19-pre1/fs/ext3/xattr.c
2690 ===================================================================
2691 --- linux-2.4.19-pre1.orig/fs/ext3/xattr.c 2003-11-21 03:51:05.000000000 +0300
2692 +++ linux-2.4.19-pre1/fs/ext3/xattr.c 2003-11-21 03:51:05.000000000 +0300
2695 + * linux/fs/ext3/xattr.c
2697 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2699 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2700 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2701 + * Extended attributes for symlinks and special files added per
2702 + * suggestion of Luka Renko <luka.renko@hermes.si>.
2706 + * Extended attributes are stored on disk blocks allocated outside of
2707 + * any inode. The i_file_acl field is then made to point to this allocated
2708 + * block. If all extended attributes of an inode are identical, these
2709 + * inodes may share the same extended attribute block. Such situations
2710 + * are automatically detected by keeping a cache of recent attribute block
2711 + * numbers and hashes over the block's contents in memory.
2714 + * Extended attribute block layout:
2716 + * +------------------+
2719 + * | entry 2 | | growing downwards
2721 + * | four null bytes |
2724 + * | value 3 | | growing upwards
2726 + * +------------------+
2728 + * The block header is followed by multiple entry descriptors. These entry
2729 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2730 + * byte boundaries. The entry descriptors are sorted by attribute name,
2731 + * so that two extended attribute blocks can be compared efficiently.
2733 + * Attribute values are aligned to the end of the block, stored in
2734 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2735 + * boundaries. No additional gaps are left between them.
2737 + * Locking strategy
2738 + * ----------------
2739 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2740 + * the xattr inode operations are called, so we are guaranteed that only one
2741 + * processes accesses extended attributes of an inode at any time.
2743 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2744 + * only a single process is modifying an extended attribute block, even
2745 + * if the block is shared among inodes.
2747 + * Note for porting to 2.5
2748 + * -----------------------
2749 + * The BKL will no longer be held in the xattr inode operations.
2752 +#include <linux/module.h>
2753 +#include <linux/fs.h>
2754 +#include <linux/locks.h>
2755 +#include <linux/slab.h>
2756 +#include <linux/ext3_jbd.h>
2757 +#include <linux/ext3_fs.h>
2758 +#include <linux/ext3_xattr.h>
2759 +#include <linux/mbcache.h>
2760 +#include <linux/quotaops.h>
2761 +#include <asm/semaphore.h>
2762 +#include <linux/compatmac.h>
2764 +#define EXT3_EA_USER "user."
2766 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2767 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2770 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2771 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2772 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2773 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2775 +#ifdef EXT3_XATTR_DEBUG
2776 +# define ea_idebug(inode, f...) do { \
2777 + printk(KERN_DEBUG "inode %s:%ld: ", \
2778 + kdevname(inode->i_dev), inode->i_ino); \
2782 +# define ea_bdebug(bh, f...) do { \
2783 + printk(KERN_DEBUG "block %s:%ld: ", \
2784 + kdevname(bh->b_dev), bh->b_blocknr); \
2789 +# define ea_idebug(f...)
2790 +# define ea_bdebug(f...)
2793 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2794 + struct ext3_xattr_header *);
2796 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2798 +static int ext3_xattr_cache_insert(struct buffer_head *);
2799 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2800 + struct ext3_xattr_header *);
2801 +static void ext3_xattr_cache_remove(struct buffer_head *);
2802 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2803 + struct ext3_xattr_entry *);
2805 +static struct mb_cache *ext3_xattr_cache;
2808 +# define ext3_xattr_cache_insert(bh) 0
2809 +# define ext3_xattr_cache_find(inode, header) NULL
2810 +# define ext3_xattr_cache_remove(bh) while(0) {}
2811 +# define ext3_xattr_rehash(header, entry) while(0) {}
2815 + * If a file system does not share extended attributes among inodes,
2816 + * we should not need the ext3_xattr_sem semaphore. However, the
2817 + * filesystem may still contain shared blocks, so we always take
2821 +DECLARE_MUTEX(ext3_xattr_sem);
2824 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2825 + int * errp, int force)
2827 + struct super_block *sb = inode->i_sb;
2828 + int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2829 + EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2831 + /* How can we enforce the allocation? */
2832 + int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2835 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2841 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2843 + /* How can we enforce the allocation? */
2845 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2847 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2849 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
2857 +ext3_xattr_quota_free(struct inode *inode)
2859 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2860 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2864 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2865 + unsigned long block)
2867 + ext3_free_blocks(handle, inode, block, 1);
2868 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2872 +# define ext3_xattr_quota_free(inode) \
2873 + DQUOT_FREE_BLOCK(inode, 1)
2874 +# define ext3_xattr_free_block(handle, inode, block) \
2875 + ext3_free_blocks(handle, inode, block, 1)
2878 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2880 +static inline struct buffer_head *
2881 +sb_bread(struct super_block *sb, int block)
2883 + return bread(sb->s_dev, block, sb->s_blocksize);
2886 +static inline struct buffer_head *
2887 +sb_getblk(struct super_block *sb, int block)
2889 + return getblk(sb->s_dev, block, sb->s_blocksize);
2894 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2895 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2898 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2900 + int error = -EINVAL;
2902 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2903 + write_lock(&ext3_handler_lock);
2904 + if (!ext3_xattr_handlers[name_index-1]) {
2905 + ext3_xattr_handlers[name_index-1] = handler;
2908 + write_unlock(&ext3_handler_lock);
2914 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2916 + if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2917 + write_lock(&ext3_handler_lock);
2918 + ext3_xattr_handlers[name_index-1] = NULL;
2919 + write_unlock(&ext3_handler_lock);
2923 +static inline const char *
2924 +strcmp_prefix(const char *a, const char *a_prefix)
2926 + while (*a_prefix && *a == *a_prefix) {
2930 + return *a_prefix ? NULL : a;
2934 + * Decode the extended attribute name, and translate it into
2935 + * the name_index and name suffix.
2937 +static inline struct ext3_xattr_handler *
2938 +ext3_xattr_resolve_name(const char **name)
2940 + struct ext3_xattr_handler *handler = NULL;
2945 + read_lock(&ext3_handler_lock);
2946 + for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2947 + if (ext3_xattr_handlers[i]) {
2948 + const char *n = strcmp_prefix(*name,
2949 + ext3_xattr_handlers[i]->prefix);
2951 + handler = ext3_xattr_handlers[i];
2957 + read_unlock(&ext3_handler_lock);
2961 +static inline struct ext3_xattr_handler *
2962 +ext3_xattr_handler(int name_index)
2964 + struct ext3_xattr_handler *handler = NULL;
2965 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2966 + read_lock(&ext3_handler_lock);
2967 + handler = ext3_xattr_handlers[name_index-1];
2968 + read_unlock(&ext3_handler_lock);
2974 + * Inode operation getxattr()
2976 + * dentry->d_inode->i_sem down
2977 + * BKL held [before 2.5.x]
2980 +ext3_getxattr(struct dentry *dentry, const char *name,
2981 + void *buffer, size_t size)
2983 + struct ext3_xattr_handler *handler;
2984 + struct inode *inode = dentry->d_inode;
2986 + handler = ext3_xattr_resolve_name(&name);
2989 + return handler->get(inode, name, buffer, size);
2993 + * Inode operation listxattr()
2995 + * dentry->d_inode->i_sem down
2996 + * BKL held [before 2.5.x]
2999 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
3001 + return ext3_xattr_list(dentry->d_inode, buffer, size);
3005 + * Inode operation setxattr()
3007 + * dentry->d_inode->i_sem down
3008 + * BKL held [before 2.5.x]
3011 +ext3_setxattr(struct dentry *dentry, const char *name,
3012 + const void *value, size_t size, int flags)
3014 + struct ext3_xattr_handler *handler;
3015 + struct inode *inode = dentry->d_inode;
3018 + value = ""; /* empty EA, do not remove */
3019 + handler = ext3_xattr_resolve_name(&name);
3022 + return handler->set(inode, name, value, size, flags);
3026 + * Inode operation removexattr()
3028 + * dentry->d_inode->i_sem down
3029 + * BKL held [before 2.5.x]
3032 +ext3_removexattr(struct dentry *dentry, const char *name)
3034 + struct ext3_xattr_handler *handler;
3035 + struct inode *inode = dentry->d_inode;
3037 + handler = ext3_xattr_resolve_name(&name);
3040 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
3044 + * ext3_xattr_get()
3046 + * Copy an extended attribute into the buffer
3047 + * provided, or compute the buffer size required.
3048 + * Buffer is NULL to compute the size of the buffer required.
3050 + * Returns a negative error number on failure, or the number of bytes
3051 + * used / required on success.
3054 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
3055 + void *buffer, size_t buffer_size)
3057 + struct buffer_head *bh = NULL;
3058 + struct ext3_xattr_entry *entry;
3059 + unsigned int block, size;
3061 + int name_len, error;
3063 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
3064 + name_index, name, buffer, (long)buffer_size);
3068 + if (!EXT3_I(inode)->i_file_acl)
3070 + block = EXT3_I(inode)->i_file_acl;
3071 + ea_idebug(inode, "reading block %d", block);
3072 + bh = sb_bread(inode->i_sb, block);
3075 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3076 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3077 + end = bh->b_data + bh->b_size;
3078 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3079 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3080 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
3081 + "inode %ld: bad block %d", inode->i_ino, block);
3085 + /* find named attribute */
3086 + name_len = strlen(name);
3089 + if (name_len > 255)
3091 + entry = FIRST_ENTRY(bh);
3092 + while (!IS_LAST_ENTRY(entry)) {
3093 + struct ext3_xattr_entry *next =
3094 + EXT3_XATTR_NEXT(entry);
3095 + if ((char *)next >= end)
3097 + if (name_index == entry->e_name_index &&
3098 + name_len == entry->e_name_len &&
3099 + memcmp(name, entry->e_name, name_len) == 0)
3103 + /* Check the remaining name entries */
3104 + while (!IS_LAST_ENTRY(entry)) {
3105 + struct ext3_xattr_entry *next =
3106 + EXT3_XATTR_NEXT(entry);
3107 + if ((char *)next >= end)
3111 + if (ext3_xattr_cache_insert(bh))
3112 + ea_idebug(inode, "cache insert failed");
3116 + /* check the buffer size */
3117 + if (entry->e_value_block != 0)
3119 + size = le32_to_cpu(entry->e_value_size);
3120 + if (size > inode->i_sb->s_blocksize ||
3121 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
3124 + if (ext3_xattr_cache_insert(bh))
3125 + ea_idebug(inode, "cache insert failed");
3128 + if (size > buffer_size)
3130 + /* return value of attribute */
3131 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
3143 + * ext3_xattr_list()
3145 + * Copy a list of attribute names into the buffer
3146 + * provided, or compute the buffer size required.
3147 + * Buffer is NULL to compute the size of the buffer required.
3149 + * Returns a negative error number on failure, or the number of bytes
3150 + * used / required on success.
3153 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
3155 + struct buffer_head *bh = NULL;
3156 + struct ext3_xattr_entry *entry;
3157 + unsigned int block, size = 0;
3161 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
3162 + buffer, (long)buffer_size);
3164 + if (!EXT3_I(inode)->i_file_acl)
3166 + block = EXT3_I(inode)->i_file_acl;
3167 + ea_idebug(inode, "reading block %d", block);
3168 + bh = sb_bread(inode->i_sb, block);
3171 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3172 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3173 + end = bh->b_data + bh->b_size;
3174 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3175 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3176 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
3177 + "inode %ld: bad block %d", inode->i_ino, block);
3181 + /* compute the size required for the list of attribute names */
3182 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3183 + entry = EXT3_XATTR_NEXT(entry)) {
3184 + struct ext3_xattr_handler *handler;
3185 + struct ext3_xattr_entry *next =
3186 + EXT3_XATTR_NEXT(entry);
3187 + if ((char *)next >= end)
3190 + handler = ext3_xattr_handler(entry->e_name_index);
3192 + size += handler->list(NULL, inode, entry->e_name,
3193 + entry->e_name_len);
3196 + if (ext3_xattr_cache_insert(bh))
3197 + ea_idebug(inode, "cache insert failed");
3203 + if (size > buffer_size)
3207 + /* list the attribute names */
3209 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3210 + entry = EXT3_XATTR_NEXT(entry)) {
3211 + struct ext3_xattr_handler *handler;
3213 + handler = ext3_xattr_handler(entry->e_name_index);
3215 + buf += handler->list(buf, inode, entry->e_name,
3216 + entry->e_name_len);
3227 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3228 + * not set, set it.
3230 +static void ext3_xattr_update_super_block(handle_t *handle,
3231 + struct super_block *sb)
3233 + if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3237 + ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3238 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3239 + EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3241 + EXT3_SB(sb)->s_es->s_feature_compat |=
3242 + cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3244 + ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3249 + * ext3_xattr_set()
3251 + * Create, replace or remove an extended attribute for this inode. Buffer
3252 + * is NULL to remove an existing extended attribute, and non-NULL to
3253 + * either replace an existing extended attribute, or create a new extended
3254 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3255 + * specify that an extended attribute must exist and must not exist
3256 + * previous to the call, respectively.
3258 + * Returns 0, or a negative error number on failure.
3261 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3262 + const char *name, const void *value, size_t value_len, int flags)
3264 + struct super_block *sb = inode->i_sb;
3265 + struct buffer_head *bh = NULL;
3266 + struct ext3_xattr_header *header = NULL;
3267 + struct ext3_xattr_entry *here, *last;
3268 + unsigned int name_len;
3269 + int block = EXT3_I(inode)->i_file_acl;
3270 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
3274 + * header -- Points either into bh, or to a temporarily
3275 + * allocated buffer.
3276 + * here -- The named entry found, or the place for inserting, within
3277 + * the block pointed to by header.
3278 + * last -- Points right after the last named entry within the block
3279 + * pointed to by header.
3280 + * min_offs -- The offset of the first value (values are aligned
3281 + * towards the end of the block).
3282 + * end -- Points right after the block pointed to by header.
3285 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3286 + name_index, name, value, (long)value_len);
3288 + if (IS_RDONLY(inode))
3290 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3292 + if (value == NULL)
3296 + name_len = strlen(name);
3297 + if (name_len > 255 || value_len > sb->s_blocksize)
3299 + down(&ext3_xattr_sem);
3302 + /* The inode already has an extended attribute block. */
3303 + bh = sb_bread(sb, block);
3307 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3308 + atomic_read(&(bh->b_count)),
3309 + le32_to_cpu(HDR(bh)->h_refcount));
3311 + end = bh->b_data + bh->b_size;
3312 + if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3313 + header->h_blocks != cpu_to_le32(1)) {
3314 +bad_block: ext3_error(sb, "ext3_xattr_set",
3315 + "inode %ld: bad block %d", inode->i_ino, block);
3319 + /* Find the named attribute. */
3320 + here = FIRST_ENTRY(bh);
3321 + while (!IS_LAST_ENTRY(here)) {
3322 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3323 + if ((char *)next >= end)
3325 + if (!here->e_value_block && here->e_value_size) {
3326 + int offs = le16_to_cpu(here->e_value_offs);
3327 + if (offs < min_offs)
3330 + not_found = name_index - here->e_name_index;
3332 + not_found = name_len - here->e_name_len;
3334 + not_found = memcmp(name, here->e_name,name_len);
3335 + if (not_found <= 0)
3340 + /* We still need to compute min_offs and last. */
3341 + while (!IS_LAST_ENTRY(last)) {
3342 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3343 + if ((char *)next >= end)
3345 + if (!last->e_value_block && last->e_value_size) {
3346 + int offs = le16_to_cpu(last->e_value_offs);
3347 + if (offs < min_offs)
3353 + /* Check whether we have enough space left. */
3354 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3356 + /* We will use a new extended attribute block. */
3357 + free = sb->s_blocksize -
3358 + sizeof(struct ext3_xattr_header) - sizeof(__u32);
3359 + here = last = NULL; /* avoid gcc uninitialized warning. */
3363 + /* Request to remove a nonexistent attribute? */
3365 + if (flags & XATTR_REPLACE)
3368 + if (value == NULL)
3371 + free -= EXT3_XATTR_LEN(name_len);
3373 + /* Request to create an existing attribute? */
3375 + if (flags & XATTR_CREATE)
3377 + if (!here->e_value_block && here->e_value_size) {
3378 + unsigned int size = le32_to_cpu(here->e_value_size);
3380 + if (le16_to_cpu(here->e_value_offs) + size >
3381 + sb->s_blocksize || size > sb->s_blocksize)
3383 + free += EXT3_XATTR_SIZE(size);
3386 + free -= EXT3_XATTR_SIZE(value_len);
3391 + /* Here we know that we can set the new attribute. */
3394 + if (header->h_refcount == cpu_to_le32(1)) {
3395 + ea_bdebug(bh, "modifying in-place");
3396 + ext3_xattr_cache_remove(bh);
3397 + error = ext3_journal_get_write_access(handle, bh);
3403 + ea_bdebug(bh, "cloning");
3404 + header = kmalloc(bh->b_size, GFP_KERNEL);
3406 + if (header == NULL)
3408 + memcpy(header, HDR(bh), bh->b_size);
3409 + header->h_refcount = cpu_to_le32(1);
3410 + offset = (char *)header - bh->b_data;
3411 + here = ENTRY((char *)here + offset);
3412 + last = ENTRY((char *)last + offset);
3415 + /* Allocate a buffer where we construct the new block. */
3416 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3418 + if (header == NULL)
3420 + memset(header, 0, sb->s_blocksize);
3421 + end = (char *)header + sb->s_blocksize;
3422 + header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3423 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
3424 + last = here = ENTRY(header+1);
3428 + /* Insert the new name. */
3429 + int size = EXT3_XATTR_LEN(name_len);
3430 + int rest = (char *)last - (char *)here;
3431 + memmove((char *)here + size, here, rest);
3432 + memset(here, 0, size);
3433 + here->e_name_index = name_index;
3434 + here->e_name_len = name_len;
3435 + memcpy(here->e_name, name, name_len);
3437 + /* Remove the old value. */
3438 + if (!here->e_value_block && here->e_value_size) {
3439 + char *first_val = (char *)header + min_offs;
3440 + int offs = le16_to_cpu(here->e_value_offs);
3441 + char *val = (char *)header + offs;
3442 + size_t size = EXT3_XATTR_SIZE(
3443 + le32_to_cpu(here->e_value_size));
3444 + memmove(first_val + size, first_val, val - first_val);
3445 + memset(first_val, 0, size);
3446 + here->e_value_offs = 0;
3449 + /* Adjust all value offsets. */
3450 + last = ENTRY(header+1);
3451 + while (!IS_LAST_ENTRY(last)) {
3452 + int o = le16_to_cpu(last->e_value_offs);
3453 + if (!last->e_value_block && o < offs)
3454 + last->e_value_offs =
3455 + cpu_to_le16(o + size);
3456 + last = EXT3_XATTR_NEXT(last);
3459 + if (value == NULL) {
3460 + /* Remove this attribute. */
3461 + if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3462 + /* This block is now empty. */
3463 + error = ext3_xattr_set2(handle, inode, bh,NULL);
3466 + /* Remove the old name. */
3467 + int size = EXT3_XATTR_LEN(name_len);
3468 + last = ENTRY((char *)last - size);
3469 + memmove(here, (char*)here + size,
3470 + (char*)last - (char*)here);
3471 + memset(last, 0, size);
3476 + if (value != NULL) {
3477 + /* Insert the new value. */
3478 + here->e_value_size = cpu_to_le32(value_len);
3480 + size_t size = EXT3_XATTR_SIZE(value_len);
3481 + char *val = (char *)header + min_offs - size;
3482 + here->e_value_offs =
3483 + cpu_to_le16((char *)val - (char *)header);
3484 + memset(val + size - EXT3_XATTR_PAD, 0,
3485 + EXT3_XATTR_PAD); /* Clear the pad bytes. */
3486 + memcpy(val, value, value_len);
3489 + ext3_xattr_rehash(header, here);
3491 + error = ext3_xattr_set2(handle, inode, bh, header);
3495 + if (!(bh && header == HDR(bh)))
3497 + up(&ext3_xattr_sem);
3503 + * Second half of ext3_xattr_set(): Update the file system.
3506 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3507 + struct buffer_head *old_bh, struct ext3_xattr_header *header)
3509 + struct super_block *sb = inode->i_sb;
3510 + struct buffer_head *new_bh = NULL;
3514 + new_bh = ext3_xattr_cache_find(inode, header);
3517 + * We found an identical block in the cache.
3518 + * The old block will be released after updating
3521 + ea_bdebug(old_bh, "reusing block %ld",
3522 + new_bh->b_blocknr);
3525 + if (ext3_xattr_quota_alloc(inode, 1))
3528 + error = ext3_journal_get_write_access(handle, new_bh);
3531 + HDR(new_bh)->h_refcount = cpu_to_le32(
3532 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3533 + ea_bdebug(new_bh, "refcount now=%d",
3534 + le32_to_cpu(HDR(new_bh)->h_refcount));
3535 + } else if (old_bh && header == HDR(old_bh)) {
3536 + /* Keep this block. */
3538 + ext3_xattr_cache_insert(new_bh);
3540 + /* We need to allocate a new block */
3541 + int force = EXT3_I(inode)->i_file_acl != 0;
3542 + int block = ext3_xattr_new_block(handle, inode,
3546 + ea_idebug(inode, "creating block %d", block);
3548 + new_bh = sb_getblk(sb, block);
3550 +getblk_failed: ext3_xattr_free_block(handle, inode, block);
3554 + lock_buffer(new_bh);
3555 + error = ext3_journal_get_create_access(handle, new_bh);
3557 + unlock_buffer(new_bh);
3558 + goto getblk_failed;
3560 + memcpy(new_bh->b_data, header, new_bh->b_size);
3561 + mark_buffer_uptodate(new_bh, 1);
3562 + unlock_buffer(new_bh);
3563 + ext3_xattr_cache_insert(new_bh);
3565 + ext3_xattr_update_super_block(handle, sb);
3567 + error = ext3_journal_dirty_metadata(handle, new_bh);
3572 + /* Update the inode. */
3573 + EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3574 + inode->i_ctime = CURRENT_TIME;
3575 + ext3_mark_inode_dirty(handle, inode);
3576 + if (IS_SYNC(inode))
3577 + handle->h_sync = 1;
3580 + if (old_bh && old_bh != new_bh) {
3582 + * If there was an old block, and we are not still using it,
3583 + * we now release the old block.
3585 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3587 + error = ext3_journal_get_write_access(handle, old_bh);
3590 + if (refcount == 1) {
3591 + /* Free the old block. */
3592 + ea_bdebug(old_bh, "freeing");
3593 + ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3595 + /* ext3_forget() calls bforget() for us, but we
3596 + let our caller release old_bh, so we need to
3597 + duplicate the handle before. */
3599 + ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3601 + /* Decrement the refcount only. */
3603 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3604 + ext3_xattr_quota_free(inode);
3605 + ext3_journal_dirty_metadata(handle, old_bh);
3606 + ea_bdebug(old_bh, "refcount now=%d", refcount);
3611 + if (old_bh != new_bh)
3618 + * ext3_xattr_delete_inode()
3620 + * Free extended attribute resources associated with this inode. This
3621 + * is called immediately before an inode is freed.
3624 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3626 + struct buffer_head *bh;
3627 + unsigned int block = EXT3_I(inode)->i_file_acl;
3631 + down(&ext3_xattr_sem);
3633 + bh = sb_bread(inode->i_sb, block);
3635 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3636 + "inode %ld: block %d read error", inode->i_ino, block);
3639 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3640 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3641 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3642 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3643 + "inode %ld: bad block %d", inode->i_ino, block);
3646 + ext3_journal_get_write_access(handle, bh);
3647 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3648 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3649 + ext3_xattr_cache_remove(bh);
3650 + ext3_xattr_free_block(handle, inode, block);
3651 + ext3_forget(handle, 1, inode, bh, block);
3654 + HDR(bh)->h_refcount = cpu_to_le32(
3655 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
3656 + ext3_journal_dirty_metadata(handle, bh);
3657 + if (IS_SYNC(inode))
3658 + handle->h_sync = 1;
3659 + ext3_xattr_quota_free(inode);
3661 + EXT3_I(inode)->i_file_acl = 0;
3665 + up(&ext3_xattr_sem);
3669 + * ext3_xattr_put_super()
3671 + * This is called when a file system is unmounted.
3674 +ext3_xattr_put_super(struct super_block *sb)
3676 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3677 + mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3681 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3684 + * ext3_xattr_cache_insert()
3686 + * Create a new entry in the extended attribute cache, and insert
3687 + * it unless such an entry is already in the cache.
3689 + * Returns 0, or a negative error number on failure.
3692 +ext3_xattr_cache_insert(struct buffer_head *bh)
3694 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3695 + struct mb_cache_entry *ce;
3698 + ce = mb_cache_entry_alloc(ext3_xattr_cache);
3701 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3703 + mb_cache_entry_free(ce);
3704 + if (error == -EBUSY) {
3705 + ea_bdebug(bh, "already in cache (%d cache entries)",
3706 + atomic_read(&ext3_xattr_cache->c_entry_count));
3710 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3711 + atomic_read(&ext3_xattr_cache->c_entry_count));
3712 + mb_cache_entry_release(ce);
3718 + * ext3_xattr_cmp()
3720 + * Compare two extended attribute blocks for equality.
3722 + * Returns 0 if the blocks are equal, 1 if they differ, and
3723 + * a negative error number on errors.
3726 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3727 + struct ext3_xattr_header *header2)
3729 + struct ext3_xattr_entry *entry1, *entry2;
3731 + entry1 = ENTRY(header1+1);
3732 + entry2 = ENTRY(header2+1);
3733 + while (!IS_LAST_ENTRY(entry1)) {
3734 + if (IS_LAST_ENTRY(entry2))
3736 + if (entry1->e_hash != entry2->e_hash ||
3737 + entry1->e_name_len != entry2->e_name_len ||
3738 + entry1->e_value_size != entry2->e_value_size ||
3739 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3741 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3743 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3744 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3745 + le32_to_cpu(entry1->e_value_size)))
3748 + entry1 = EXT3_XATTR_NEXT(entry1);
3749 + entry2 = EXT3_XATTR_NEXT(entry2);
3751 + if (!IS_LAST_ENTRY(entry2))
3757 + * ext3_xattr_cache_find()
3759 + * Find an identical extended attribute block.
3761 + * Returns a pointer to the block found, or NULL if such a block was
3762 + * not found or an error occurred.
3764 +static struct buffer_head *
3765 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3767 + __u32 hash = le32_to_cpu(header->h_hash);
3768 + struct mb_cache_entry *ce;
3770 + if (!header->h_hash)
3771 + return NULL; /* never share */
3772 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3773 + ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3775 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3778 + ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3779 + "inode %ld: block %ld read error",
3780 + inode->i_ino, ce->e_block);
3781 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3782 + EXT3_XATTR_REFCOUNT_MAX) {
3783 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3784 + le32_to_cpu(HDR(bh)->h_refcount),
3785 + EXT3_XATTR_REFCOUNT_MAX);
3786 + } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3787 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3788 + mb_cache_entry_release(ce);
3792 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3798 + * ext3_xattr_cache_remove()
3800 + * Remove the cache entry of a block from the cache. Called when a
3801 + * block becomes invalid.
3804 +ext3_xattr_cache_remove(struct buffer_head *bh)
3806 + struct mb_cache_entry *ce;
3808 + ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3810 + ea_bdebug(bh, "removing (%d cache entries remaining)",
3811 + atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3812 + mb_cache_entry_free(ce);
3814 + ea_bdebug(bh, "no cache entry");
3817 +#define NAME_HASH_SHIFT 5
3818 +#define VALUE_HASH_SHIFT 16
3821 + * ext3_xattr_hash_entry()
3823 + * Compute the hash of an extended attribute.
3825 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3826 + struct ext3_xattr_entry *entry)
3829 + char *name = entry->e_name;
3832 + for (n=0; n < entry->e_name_len; n++) {
3833 + hash = (hash << NAME_HASH_SHIFT) ^
3834 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3838 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3839 + __u32 *value = (__u32 *)((char *)header +
3840 + le16_to_cpu(entry->e_value_offs));
3841 + for (n = (le32_to_cpu(entry->e_value_size) +
3842 + EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3843 + hash = (hash << VALUE_HASH_SHIFT) ^
3844 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3845 + le32_to_cpu(*value++);
3848 + entry->e_hash = cpu_to_le32(hash);
3851 +#undef NAME_HASH_SHIFT
3852 +#undef VALUE_HASH_SHIFT
3854 +#define BLOCK_HASH_SHIFT 16
3857 + * ext3_xattr_rehash()
3859 + * Re-compute the extended attribute hash value after an entry has changed.
3861 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3862 + struct ext3_xattr_entry *entry)
3864 + struct ext3_xattr_entry *here;
3867 + ext3_xattr_hash_entry(header, entry);
3868 + here = ENTRY(header+1);
3869 + while (!IS_LAST_ENTRY(here)) {
3870 + if (!here->e_hash) {
3871 + /* Block is not shared if an entry's hash value == 0 */
3875 + hash = (hash << BLOCK_HASH_SHIFT) ^
3876 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3877 + le32_to_cpu(here->e_hash);
3878 + here = EXT3_XATTR_NEXT(here);
3880 + header->h_hash = cpu_to_le32(hash);
3883 +#undef BLOCK_HASH_SHIFT
3886 +init_ext3_xattr(void)
3888 + ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3889 + sizeof(struct mb_cache_entry) +
3890 + sizeof(struct mb_cache_entry_index), 1, 61);
3891 + if (!ext3_xattr_cache)
3898 +exit_ext3_xattr(void)
3900 + if (ext3_xattr_cache)
3901 + mb_cache_destroy(ext3_xattr_cache);
3902 + ext3_xattr_cache = NULL;
3905 +#else /* CONFIG_EXT3_FS_XATTR_SHARING */
3908 +init_ext3_xattr(void)
3914 +exit_ext3_xattr(void)
3918 +#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
3919 Index: linux-2.4.19-pre1/fs/ext3/xattr_user.c
3920 ===================================================================
3921 --- linux-2.4.19-pre1.orig/fs/ext3/xattr_user.c 2003-11-21 03:51:05.000000000 +0300
3922 +++ linux-2.4.19-pre1/fs/ext3/xattr_user.c 2003-11-21 03:51:05.000000000 +0300
3925 + * linux/fs/ext3/xattr_user.c
3926 + * Handler for extended user attributes.
3928 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3931 +#include <linux/module.h>
3932 +#include <linux/string.h>
3933 +#include <linux/fs.h>
3934 +#include <linux/ext3_jbd.h>
3935 +#include <linux/ext3_fs.h>
3936 +#include <linux/ext3_xattr.h>
3938 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3939 +# include <linux/ext3_acl.h>
3942 +#define XATTR_USER_PREFIX "user."
3945 +ext3_xattr_user_list(char *list, struct inode *inode,
3946 + const char *name, int name_len)
3948 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3950 + if (!test_opt(inode->i_sb, XATTR_USER))
3954 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
3955 + memcpy(list+prefix_len, name, name_len);
3956 + list[prefix_len + name_len] = '\0';
3958 + return prefix_len + name_len + 1;
3962 +ext3_xattr_user_get(struct inode *inode, const char *name,
3963 + void *buffer, size_t size)
3967 + if (strcmp(name, "") == 0)
3969 + if (!test_opt(inode->i_sb, XATTR_USER))
3971 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3972 + error = ext3_permission_locked(inode, MAY_READ);
3974 + error = permission(inode, MAY_READ);
3979 + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
3984 +ext3_xattr_user_set(struct inode *inode, const char *name,
3985 + const void *value, size_t size, int flags)
3990 + if (strcmp(name, "") == 0)
3992 + if (!test_opt(inode->i_sb, XATTR_USER))
3994 + if ( !S_ISREG(inode->i_mode) &&
3995 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
3997 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3998 + error = ext3_permission_locked(inode, MAY_WRITE);
4000 + error = permission(inode, MAY_WRITE);
4005 + handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
4006 + if (IS_ERR(handle))
4007 + return PTR_ERR(handle);
4008 + error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
4009 + value, size, flags);
4010 + ext3_journal_stop(handle, inode);
4015 +struct ext3_xattr_handler ext3_xattr_user_handler = {
4016 + prefix: XATTR_USER_PREFIX,
4017 + list: ext3_xattr_user_list,
4018 + get: ext3_xattr_user_get,
4019 + set: ext3_xattr_user_set,
4023 +init_ext3_xattr_user(void)
4025 + return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
4026 + &ext3_xattr_user_handler);
4030 +exit_ext3_xattr_user(void)
4032 + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
4033 + &ext3_xattr_user_handler);
4035 Index: linux-2.4.19-pre1/fs/mbcache.c
4036 ===================================================================
4037 --- linux-2.4.19-pre1.orig/fs/mbcache.c 2003-11-21 03:51:05.000000000 +0300
4038 +++ linux-2.4.19-pre1/fs/mbcache.c 2003-11-21 03:51:05.000000000 +0300
4041 + * linux/fs/mbcache.c
4042 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4046 + * Filesystem Meta Information Block Cache (mbcache)
4048 + * The mbcache caches blocks of block devices that need to be located
4049 + * by their device/block number, as well as by other criteria (such
4050 + * as the block's contents).
4052 + * There can only be one cache entry in a cache per device and block number.
4053 + * Additional indexes need not be unique in this sense. The number of
4054 + * additional indexes (=other criteria) can be hardwired at compile time
4055 + * or specified at cache create time.
4057 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
4058 + * in the cache. A valid entry is in the main hash tables of the cache,
4059 + * and may also be in the lru list. An invalid entry is not in any hashes
4062 + * A valid cache entry is only in the lru list if no handles refer to it.
4063 + * Invalid cache entries will be freed when the last handle to the cache
4064 + * entry is released. Entries that cannot be freed immediately are put
4065 + * back on the lru list.
4068 +#include <linux/kernel.h>
4069 +#include <linux/module.h>
4071 +#include <linux/fs.h>
4072 +#include <linux/slab.h>
4073 +#include <linux/sched.h>
4074 +#include <linux/cache_def.h>
4075 +#include <linux/version.h>
4076 +#include <linux/init.h>
4077 +#include <linux/mbcache.h>
4080 +#ifdef MB_CACHE_DEBUG
4081 +# define mb_debug(f...) do { \
4082 + printk(KERN_DEBUG f); \
4085 +#define mb_assert(c) do { if (!(c)) \
4086 + printk(KERN_ERR "assertion " #c " failed\n"); \
4089 +# define mb_debug(f...) do { } while(0)
4090 +# define mb_assert(c) do { } while(0)
4092 +#define mb_error(f...) do { \
4093 + printk(KERN_ERR f); \
4097 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
4098 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
4099 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4100 +MODULE_LICENSE("GPL");
4103 +EXPORT_SYMBOL(mb_cache_create);
4104 +EXPORT_SYMBOL(mb_cache_shrink);
4105 +EXPORT_SYMBOL(mb_cache_destroy);
4106 +EXPORT_SYMBOL(mb_cache_entry_alloc);
4107 +EXPORT_SYMBOL(mb_cache_entry_insert);
4108 +EXPORT_SYMBOL(mb_cache_entry_release);
4109 +EXPORT_SYMBOL(mb_cache_entry_takeout);
4110 +EXPORT_SYMBOL(mb_cache_entry_free);
4111 +EXPORT_SYMBOL(mb_cache_entry_dup);
4112 +EXPORT_SYMBOL(mb_cache_entry_get);
4113 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4114 +EXPORT_SYMBOL(mb_cache_entry_find_first);
4115 +EXPORT_SYMBOL(mb_cache_entry_find_next);
4120 + * Global data: list of all mbcache's, lru list, and a spinlock for
4121 + * accessing cache data structures on SMP machines. The lru list is
4122 + * global across all mbcaches.
4125 +static LIST_HEAD(mb_cache_list);
4126 +static LIST_HEAD(mb_cache_lru_list);
4127 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
4130 +mb_cache_indexes(struct mb_cache *cache)
4132 +#ifdef MB_CACHE_INDEXES_COUNT
4133 + return MB_CACHE_INDEXES_COUNT;
4135 + return cache->c_indexes_count;
4140 + * What the mbcache registers as to get shrunk dynamically.
4144 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
4146 +static struct cache_definition mb_cache_definition = {
4148 + mb_cache_memory_pressure
4153 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4155 + return !list_empty(&ce->e_block_list);
4160 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4164 + if (__mb_cache_entry_is_hashed(ce)) {
4165 + list_del_init(&ce->e_block_list);
4166 + for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4167 + list_del(&ce->e_indexes[n].o_list);
4173 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4175 + struct mb_cache *cache = ce->e_cache;
4177 + mb_assert(atomic_read(&ce->e_used) == 0);
4178 + if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4179 + /* free failed -- put back on the lru list
4180 + for freeing later. */
4181 + spin_lock(&mb_cache_spinlock);
4182 + list_add(&ce->e_lru_list, &mb_cache_lru_list);
4183 + spin_unlock(&mb_cache_spinlock);
4185 + kmem_cache_free(cache->c_entry_cache, ce);
4186 + atomic_dec(&cache->c_entry_count);
4192 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4194 + if (atomic_dec_and_test(&ce->e_used)) {
4195 + if (__mb_cache_entry_is_hashed(ce))
4196 + list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4198 + spin_unlock(&mb_cache_spinlock);
4199 + __mb_cache_entry_forget(ce, GFP_KERNEL);
4203 + spin_unlock(&mb_cache_spinlock);
4208 + * mb_cache_memory_pressure() memory pressure callback
4210 + * This function is called by the kernel memory management when memory
4213 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4214 + * @gfp_mask: (ignored)
4217 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4219 + LIST_HEAD(free_list);
4220 + struct list_head *l, *ltmp;
4223 + spin_lock(&mb_cache_spinlock);
4224 + list_for_each(l, &mb_cache_list) {
4225 + struct mb_cache *cache =
4226 + list_entry(l, struct mb_cache, c_cache_list);
4227 + mb_debug("cache %s (%d)", cache->c_name,
4228 + atomic_read(&cache->c_entry_count));
4229 + count += atomic_read(&cache->c_entry_count);
4231 + mb_debug("trying to free %d of %d entries",
4232 + count / (priority ? priority : 1), count);
4234 + count /= priority;
4235 + while (count-- && !list_empty(&mb_cache_lru_list)) {
4236 + struct mb_cache_entry *ce =
4237 + list_entry(mb_cache_lru_list.next,
4238 + struct mb_cache_entry, e_lru_list);
4239 + list_del(&ce->e_lru_list);
4240 + __mb_cache_entry_unhash(ce);
4241 + list_add_tail(&ce->e_lru_list, &free_list);
4243 + spin_unlock(&mb_cache_spinlock);
4244 + list_for_each_safe(l, ltmp, &free_list) {
4245 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4246 + e_lru_list), gfp_mask);
4252 + * mb_cache_create() create a new cache
4254 + * All entries in one cache are equal size. Cache entries may be from
4255 + * multiple devices. If this is the first mbcache created, registers
4256 + * the cache with kernel memory management. Returns NULL if no more
4257 + * memory was available.
4259 + * @name: name of the cache (informal)
4260 + * @cache_op: contains the callback called when freeing a cache entry
4261 + * @entry_size: The size of a cache entry, including
4262 + * struct mb_cache_entry
4263 + * @indexes_count: number of additional indexes in the cache. Must equal
4264 + * MB_CACHE_INDEXES_COUNT if the number of indexes is
4266 + * @bucket_count: number of hash buckets
4269 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4270 + size_t entry_size, int indexes_count, int bucket_count)
4273 + struct mb_cache *cache = NULL;
4275 + if(entry_size < sizeof(struct mb_cache_entry) +
4276 + indexes_count * sizeof(struct mb_cache_entry_index))
4279 + MOD_INC_USE_COUNT;
4280 + cache = kmalloc(sizeof(struct mb_cache) +
4281 + indexes_count * sizeof(struct list_head), GFP_KERNEL);
4284 + cache->c_name = name;
4285 + cache->c_op.free = NULL;
4287 + cache->c_op.free = cache_op->free;
4288 + atomic_set(&cache->c_entry_count, 0);
4289 + cache->c_bucket_count = bucket_count;
4290 +#ifdef MB_CACHE_INDEXES_COUNT
4291 + mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4293 + cache->c_indexes_count = indexes_count;
4295 + cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4297 + if (!cache->c_block_hash)
4299 + for (n=0; n<bucket_count; n++)
4300 + INIT_LIST_HEAD(&cache->c_block_hash[n]);
4301 + for (m=0; m<indexes_count; m++) {
4302 + cache->c_indexes_hash[m] = kmalloc(bucket_count *
4303 + sizeof(struct list_head),
4305 + if (!cache->c_indexes_hash[m])
4307 + for (n=0; n<bucket_count; n++)
4308 + INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4310 + cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4311 + 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4312 + if (!cache->c_entry_cache)
4315 + spin_lock(&mb_cache_spinlock);
4316 + list_add(&cache->c_cache_list, &mb_cache_list);
4317 + spin_unlock(&mb_cache_spinlock);
4323 + kfree(cache->c_indexes_hash[m]);
4324 + if (cache->c_block_hash)
4325 + kfree(cache->c_block_hash);
4328 + MOD_DEC_USE_COUNT;
4334 + * mb_cache_shrink()
4336 + * Removes all cache entires of a device from the cache. All cache entries
4337 + * currently in use cannot be freed, and thus remain in the cache.
4339 + * @cache: which cache to shrink
4340 + * @dev: which device's cache entries to shrink
4343 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4345 + LIST_HEAD(free_list);
4346 + struct list_head *l, *ltmp;
4348 + spin_lock(&mb_cache_spinlock);
4349 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4350 + struct mb_cache_entry *ce =
4351 + list_entry(l, struct mb_cache_entry, e_lru_list);
4352 + if (ce->e_dev == dev) {
4353 + list_del(&ce->e_lru_list);
4354 + list_add_tail(&ce->e_lru_list, &free_list);
4355 + __mb_cache_entry_unhash(ce);
4358 + spin_unlock(&mb_cache_spinlock);
4359 + list_for_each_safe(l, ltmp, &free_list) {
4360 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4361 + e_lru_list), GFP_KERNEL);
4367 + * mb_cache_destroy()
4369 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4370 + * and then destroys it. If this was the last mbcache, un-registers the
4371 + * mbcache from kernel memory management.
4374 +mb_cache_destroy(struct mb_cache *cache)
4376 + LIST_HEAD(free_list);
4377 + struct list_head *l, *ltmp;
4380 + spin_lock(&mb_cache_spinlock);
4381 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4382 + struct mb_cache_entry *ce =
4383 + list_entry(l, struct mb_cache_entry, e_lru_list);
4384 + if (ce->e_cache == cache) {
4385 + list_del(&ce->e_lru_list);
4386 + list_add_tail(&ce->e_lru_list, &free_list);
4387 + __mb_cache_entry_unhash(ce);
4390 + list_del(&cache->c_cache_list);
4391 + spin_unlock(&mb_cache_spinlock);
4392 + list_for_each_safe(l, ltmp, &free_list) {
4393 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4394 + e_lru_list), GFP_KERNEL);
4397 + if (atomic_read(&cache->c_entry_count) > 0) {
4398 + mb_error("cache %s: %d orphaned entries",
4400 + atomic_read(&cache->c_entry_count));
4403 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4404 + /* We don't have kmem_cache_destroy() in 2.2.x */
4405 + kmem_cache_shrink(cache->c_entry_cache);
4407 + kmem_cache_destroy(cache->c_entry_cache);
4409 + for (n=0; n < mb_cache_indexes(cache); n++)
4410 + kfree(cache->c_indexes_hash[n]);
4411 + kfree(cache->c_block_hash);
4414 + MOD_DEC_USE_COUNT;
4419 + * mb_cache_entry_alloc()
4421 + * Allocates a new cache entry. The new entry will not be valid initially,
4422 + * and thus cannot be looked up yet. It should be filled with data, and
4423 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4424 + * if no more memory was available.
4426 +struct mb_cache_entry *
4427 +mb_cache_entry_alloc(struct mb_cache *cache)
4429 + struct mb_cache_entry *ce;
4431 + atomic_inc(&cache->c_entry_count);
4432 + ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4434 + INIT_LIST_HEAD(&ce->e_lru_list);
4435 + INIT_LIST_HEAD(&ce->e_block_list);
4436 + ce->e_cache = cache;
4437 + atomic_set(&ce->e_used, 1);
4444 + * mb_cache_entry_insert()
4446 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4447 + * the cache. After this, the cache entry can be looked up, but is not yet
4448 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4449 + * success, or -EBUSY if a cache entry for that device + inode exists
4450 + * already (this may happen after a failed lookup, if another process has
4451 + * inserted the same cache entry in the meantime).
4453 + * @dev: device the cache entry belongs to
4454 + * @block: block number
4455 + * @keys: array of additional keys. There must be indexes_count entries
4456 + * in the array (as specified when creating the cache).
4459 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4460 + unsigned long block, unsigned int keys[])
4462 + struct mb_cache *cache = ce->e_cache;
4463 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4464 + struct list_head *l;
4465 + int error = -EBUSY, n;
4467 + spin_lock(&mb_cache_spinlock);
4468 + list_for_each(l, &cache->c_block_hash[bucket]) {
4469 + struct mb_cache_entry *ce =
4470 + list_entry(l, struct mb_cache_entry, e_block_list);
4471 + if (ce->e_dev == dev && ce->e_block == block)
4474 + __mb_cache_entry_unhash(ce);
4476 + ce->e_block = block;
4477 + list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4478 + for (n=0; n<mb_cache_indexes(cache); n++) {
4479 + ce->e_indexes[n].o_key = keys[n];
4480 + bucket = keys[n] % cache->c_bucket_count;
4481 + list_add(&ce->e_indexes[n].o_list,
4482 + &cache->c_indexes_hash[n][bucket]);
4485 + spin_unlock(&mb_cache_spinlock);
4491 + * mb_cache_entry_release()
4493 + * Release a handle to a cache entry. When the last handle to a cache entry
4494 + * is released it is either freed (if it is invalid) or otherwise inserted
4495 + * in to the lru list.
4498 +mb_cache_entry_release(struct mb_cache_entry *ce)
4500 + spin_lock(&mb_cache_spinlock);
4501 + __mb_cache_entry_release_unlock(ce);
4506 + * mb_cache_entry_takeout()
4508 + * Take a cache entry out of the cache, making it invalid. The entry can later
4509 + * be re-inserted using mb_cache_entry_insert(), or released using
4510 + * mb_cache_entry_release().
4513 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4515 + spin_lock(&mb_cache_spinlock);
4516 + mb_assert(list_empty(&ce->e_lru_list));
4517 + __mb_cache_entry_unhash(ce);
4518 + spin_unlock(&mb_cache_spinlock);
4523 + * mb_cache_entry_free()
4525 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4526 + * mb_cache_entry_release().
4529 +mb_cache_entry_free(struct mb_cache_entry *ce)
4531 + spin_lock(&mb_cache_spinlock);
4532 + mb_assert(list_empty(&ce->e_lru_list));
4533 + __mb_cache_entry_unhash(ce);
4534 + __mb_cache_entry_release_unlock(ce);
4539 + * mb_cache_entry_dup()
4541 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4542 + * itself). After the call, both the old and the new handle must be released.
4544 +struct mb_cache_entry *
4545 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4547 + atomic_inc(&ce->e_used);
4553 + * mb_cache_entry_get()
4555 + * Get a cache entry by device / block number. (There can only be one entry
4556 + * in the cache per device and block.) Returns NULL if no such cache entry
4559 +struct mb_cache_entry *
4560 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4562 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4563 + struct list_head *l;
4564 + struct mb_cache_entry *ce;
4566 + spin_lock(&mb_cache_spinlock);
4567 + list_for_each(l, &cache->c_block_hash[bucket]) {
4568 + ce = list_entry(l, struct mb_cache_entry, e_block_list);
4569 + if (ce->e_dev == dev && ce->e_block == block) {
4570 + if (!list_empty(&ce->e_lru_list))
4571 + list_del_init(&ce->e_lru_list);
4572 + atomic_inc(&ce->e_used);
4579 + spin_unlock(&mb_cache_spinlock);
4583 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4585 +static struct mb_cache_entry *
4586 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4587 + int index, kdev_t dev, unsigned int key)
4589 + while (l != head) {
4590 + struct mb_cache_entry *ce =
4591 + list_entry(l, struct mb_cache_entry,
4592 + e_indexes[index].o_list);
4593 + if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4594 + if (!list_empty(&ce->e_lru_list))
4595 + list_del_init(&ce->e_lru_list);
4596 + atomic_inc(&ce->e_used);
4606 + * mb_cache_entry_find_first()
4608 + * Find the first cache entry on a given device with a certain key in
4609 + * an additional index. Additonal matches can be found with
4610 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4612 + * @cache: the cache to search
4613 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4614 + * @dev: the device the cache entry should belong to
4615 + * @key: the key in the index
4617 +struct mb_cache_entry *
4618 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4621 + unsigned int bucket = key % cache->c_bucket_count;
4622 + struct list_head *l;
4623 + struct mb_cache_entry *ce;
4625 + mb_assert(index < mb_cache_indexes(cache));
4626 + spin_lock(&mb_cache_spinlock);
4627 + l = cache->c_indexes_hash[index][bucket].next;
4628 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4630 + spin_unlock(&mb_cache_spinlock);
4636 + * mb_cache_entry_find_next()
4638 + * Find the next cache entry on a given device with a certain key in an
4639 + * additional index. Returns NULL if no match could be found. The previous
4640 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4641 + * be called like this:
4643 + * entry = mb_cache_entry_find_first();
4646 + * entry = mb_cache_entry_find_next(entry, ...);
4649 + * @prev: The previous match
4650 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4651 + * @dev: the device the cache entry should belong to
4652 + * @key: the key in the index
4654 +struct mb_cache_entry *
4655 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4658 + struct mb_cache *cache = prev->e_cache;
4659 + unsigned int bucket = key % cache->c_bucket_count;
4660 + struct list_head *l;
4661 + struct mb_cache_entry *ce;
4663 + mb_assert(index < mb_cache_indexes(cache));
4664 + spin_lock(&mb_cache_spinlock);
4665 + l = prev->e_indexes[index].o_list.next;
4666 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4668 + __mb_cache_entry_release_unlock(prev);
4672 +#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4674 +static int __init init_mbcache(void)
4676 + register_cache(&mb_cache_definition);
4680 +static void __exit exit_mbcache(void)
4682 + unregister_cache(&mb_cache_definition);
4685 +module_init(init_mbcache)
4686 +module_exit(exit_mbcache)
4688 Index: linux-2.4.19-pre1/include/asm-arm/unistd.h
4689 ===================================================================
4690 --- linux-2.4.19-pre1.orig/include/asm-arm/unistd.h 2001-08-12 22:14:00.000000000 +0400
4691 +++ linux-2.4.19-pre1/include/asm-arm/unistd.h 2003-11-21 03:51:05.000000000 +0300
4692 @@ -240,6 +240,18 @@
4693 #define __NR_mincore (__NR_SYSCALL_BASE+219)
4694 #define __NR_madvise (__NR_SYSCALL_BASE+220)
4695 #define __NR_fcntl64 (__NR_SYSCALL_BASE+221)
4696 +#define __NR_setxattr (__NR_SYSCALL_BASE+226)
4697 +#define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
4698 +#define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
4699 +#define __NR_getxattr (__NR_SYSCALL_BASE+229)
4700 +#define __NR_lgetxattr (__NR_SYSCALL_BASE+230)
4701 +#define __NR_fgetxattr (__NR_SYSCALL_BASE+231)
4702 +#define __NR_listxattr (__NR_SYSCALL_BASE+232)
4703 +#define __NR_llistxattr (__NR_SYSCALL_BASE+233)
4704 +#define __NR_flistxattr (__NR_SYSCALL_BASE+234)
4705 +#define __NR_removexattr (__NR_SYSCALL_BASE+235)
4706 +#define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
4707 +#define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
4710 * The following SWIs are ARM private.
4711 Index: linux-2.4.19-pre1/include/asm-ia64/unistd.h
4712 ===================================================================
4713 --- linux-2.4.19-pre1.orig/include/asm-ia64/unistd.h 2001-11-10 01:26:17.000000000 +0300
4714 +++ linux-2.4.19-pre1/include/asm-ia64/unistd.h 2003-11-21 03:51:05.000000000 +0300
4715 @@ -206,6 +206,18 @@
4716 #define __NR_getdents64 1214
4717 #define __NR_getunwind 1215
4718 #define __NR_readahead 1216
4719 +#define __NR_setxattr 1217
4720 +#define __NR_lsetxattr 1218
4721 +#define __NR_fsetxattr 1219
4722 +#define __NR_getxattr 1220
4723 +#define __NR_lgetxattr 1221
4724 +#define __NR_fgetxattr 1222
4725 +#define __NR_listxattr 1223
4726 +#define __NR_llistxattr 1224
4727 +#define __NR_flistxattr 1225
4728 +#define __NR_removexattr 1226
4729 +#define __NR_lremovexattr 1227
4730 +#define __NR_fremovexattr 1228
4732 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
4734 Index: linux-2.4.19-pre1/include/asm-s390/unistd.h
4735 ===================================================================
4736 --- linux-2.4.19-pre1.orig/include/asm-s390/unistd.h 2001-10-11 20:43:38.000000000 +0400
4737 +++ linux-2.4.19-pre1/include/asm-s390/unistd.h 2003-11-21 03:51:05.000000000 +0300
4738 @@ -211,6 +211,18 @@
4739 #define __NR_mincore 218
4740 #define __NR_madvise 219
4741 #define __NR_getdents64 220
4742 +#define __NR_setxattr 224
4743 +#define __NR_lsetxattr 225
4744 +#define __NR_fsetxattr 226
4745 +#define __NR_getxattr 227
4746 +#define __NR_lgetxattr 228
4747 +#define __NR_fgetxattr 229
4748 +#define __NR_listxattr 230
4749 +#define __NR_llistxattr 231
4750 +#define __NR_flistxattr 232
4751 +#define __NR_removexattr 233
4752 +#define __NR_lremovexattr 234
4753 +#define __NR_fremovexattr 235
4756 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
4757 Index: linux-2.4.19-pre1/include/asm-s390x/unistd.h
4758 ===================================================================
4759 --- linux-2.4.19-pre1.orig/include/asm-s390x/unistd.h 2001-10-11 20:43:38.000000000 +0400
4760 +++ linux-2.4.19-pre1/include/asm-s390x/unistd.h 2003-11-21 03:51:05.000000000 +0300
4761 @@ -181,6 +181,18 @@
4762 #define __NR_mincore 218
4763 #define __NR_madvise 219
4764 #define __NR_getdents64 220
4765 +#define __NR_setxattr 224
4766 +#define __NR_lsetxattr 225
4767 +#define __NR_fsetxattr 226
4768 +#define __NR_getxattr 227
4769 +#define __NR_lgetxattr 228
4770 +#define __NR_fgetxattr 229
4771 +#define __NR_listxattr 230
4772 +#define __NR_llistxattr 231
4773 +#define __NR_flistxattr 232
4774 +#define __NR_removexattr 233
4775 +#define __NR_lremovexattr 234
4776 +#define __NR_fremovexattr 235
4779 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
4780 Index: linux-2.4.19-pre1/include/asm-sparc/unistd.h
4781 ===================================================================
4782 --- linux-2.4.19-pre1.orig/include/asm-sparc/unistd.h 2001-10-21 21:36:54.000000000 +0400
4783 +++ linux-2.4.19-pre1/include/asm-sparc/unistd.h 2003-11-21 03:51:05.000000000 +0300
4784 @@ -184,24 +184,24 @@
4785 /* #define __NR_exportfs 166 SunOS Specific */
4786 #define __NR_mount 167 /* Common */
4787 #define __NR_ustat 168 /* Common */
4788 -/* #define __NR_semsys 169 SunOS Specific */
4789 -/* #define __NR_msgsys 170 SunOS Specific */
4790 -/* #define __NR_shmsys 171 SunOS Specific */
4791 -/* #define __NR_auditsys 172 SunOS Specific */
4792 -/* #define __NR_rfssys 173 SunOS Specific */
4793 +#define __NR_setxattr 169 /* SunOS: semsys */
4794 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4795 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4796 +#define __NR_getxattr 172 /* SunOS: auditsys */
4797 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4798 #define __NR_getdents 174 /* Common */
4799 #define __NR_setsid 175 /* Common */
4800 #define __NR_fchdir 176 /* Common */
4801 -/* #define __NR_fchroot 177 SunOS Specific */
4802 -/* #define __NR_vpixsys 178 SunOS Specific */
4803 -/* #define __NR_aioread 179 SunOS Specific */
4804 -/* #define __NR_aiowrite 180 SunOS Specific */
4805 -/* #define __NR_aiowait 181 SunOS Specific */
4806 -/* #define __NR_aiocancel 182 SunOS Specific */
4807 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4808 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4809 +#define __NR_llistxattr 179 /* SunOS: aioread */
4810 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4811 +#define __NR_removexattr 181 /* SunOS: aiowait */
4812 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4813 #define __NR_sigpending 183 /* Common */
4814 #define __NR_query_module 184 /* Linux Specific */
4815 #define __NR_setpgid 185 /* Common */
4816 -/* #define __NR_pathconf 186 SunOS Specific */
4817 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4818 /* #define __NR_fpathconf 187 SunOS Specific */
4819 /* #define __NR_sysconf 188 SunOS Specific */
4820 #define __NR_uname 189 /* Linux Specific */
4821 Index: linux-2.4.19-pre1/include/asm-sparc64/unistd.h
4822 ===================================================================
4823 --- linux-2.4.19-pre1.orig/include/asm-sparc64/unistd.h 2001-10-21 21:36:54.000000000 +0400
4824 +++ linux-2.4.19-pre1/include/asm-sparc64/unistd.h 2003-11-21 03:51:05.000000000 +0300
4825 @@ -184,24 +184,24 @@
4826 /* #define __NR_exportfs 166 SunOS Specific */
4827 #define __NR_mount 167 /* Common */
4828 #define __NR_ustat 168 /* Common */
4829 -/* #define __NR_semsys 169 SunOS Specific */
4830 -/* #define __NR_msgsys 170 SunOS Specific */
4831 -/* #define __NR_shmsys 171 SunOS Specific */
4832 -/* #define __NR_auditsys 172 SunOS Specific */
4833 -/* #define __NR_rfssys 173 SunOS Specific */
4834 +#define __NR_setxattr 169 /* SunOS: semsys */
4835 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4836 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4837 +#define __NR_getxattr 172 /* SunOS: auditsys */
4838 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4839 #define __NR_getdents 174 /* Common */
4840 #define __NR_setsid 175 /* Common */
4841 #define __NR_fchdir 176 /* Common */
4842 -/* #define __NR_fchroot 177 SunOS Specific */
4843 -/* #define __NR_vpixsys 178 SunOS Specific */
4844 -/* #define __NR_aioread 179 SunOS Specific */
4845 -/* #define __NR_aiowrite 180 SunOS Specific */
4846 -/* #define __NR_aiowait 181 SunOS Specific */
4847 -/* #define __NR_aiocancel 182 SunOS Specific */
4848 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4849 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4850 +#define __NR_llistxattr 179 /* SunOS: aioread */
4851 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4852 +#define __NR_removexattr 181 /* SunOS: aiowait */
4853 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4854 #define __NR_sigpending 183 /* Common */
4855 #define __NR_query_module 184 /* Linux Specific */
4856 #define __NR_setpgid 185 /* Common */
4857 -/* #define __NR_pathconf 186 SunOS Specific */
4858 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4859 /* #define __NR_fpathconf 187 SunOS Specific */
4860 /* #define __NR_sysconf 188 SunOS Specific */
4861 #define __NR_uname 189 /* Linux Specific */
4862 Index: linux-2.4.19-pre1/include/linux/cache_def.h
4863 ===================================================================
4864 --- linux-2.4.19-pre1.orig/include/linux/cache_def.h 2003-11-21 03:51:05.000000000 +0300
4865 +++ linux-2.4.19-pre1/include/linux/cache_def.h 2003-11-21 03:51:05.000000000 +0300
4868 + * linux/cache_def.h
4869 + * Handling of caches defined in drivers, filesystems, ...
4871 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
4874 +struct cache_definition {
4876 + void (*shrink)(int, unsigned int);
4877 + struct list_head link;
4880 +extern void register_cache(struct cache_definition *);
4881 +extern void unregister_cache(struct cache_definition *);
4882 Index: linux-2.4.19-pre1/include/linux/errno.h
4883 ===================================================================
4884 --- linux-2.4.19-pre1.orig/include/linux/errno.h 2001-02-10 01:46:13.000000000 +0300
4885 +++ linux-2.4.19-pre1/include/linux/errno.h 2003-11-21 03:51:05.000000000 +0300
4890 +/* Defined for extended attributes */
4891 +#define ENOATTR ENODATA /* No such attribute */
4892 +#define ENOTSUP EOPNOTSUPP /* Operation not supported */
4895 Index: linux-2.4.19-pre1/include/linux/ext2_fs.h
4896 ===================================================================
4897 --- linux-2.4.19-pre1.orig/include/linux/ext2_fs.h 2001-11-22 22:46:52.000000000 +0300
4898 +++ linux-2.4.19-pre1/include/linux/ext2_fs.h 2003-11-21 03:51:05.000000000 +0300
4901 #define EXT2_BAD_INO 1 /* Bad blocks inode */
4902 #define EXT2_ROOT_INO 2 /* Root inode */
4903 -#define EXT2_ACL_IDX_INO 3 /* ACL inode */
4904 -#define EXT2_ACL_DATA_INO 4 /* ACL inode */
4905 #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
4906 #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
4910 # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
4912 -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
4913 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
4915 # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
4916 @@ -121,28 +118,6 @@
4922 -struct ext2_acl_header /* Header of Access Control Lists */
4925 - __u32 aclh_file_count;
4926 - __u32 aclh_acle_count;
4927 - __u32 aclh_first_acle;
4930 -struct ext2_acl_entry /* Access Control List Entry */
4933 - __u16 acle_perms; /* Access permissions */
4934 - __u16 acle_type; /* Type of entry */
4935 - __u16 acle_tag; /* User or group identity */
4937 - __u32 acle_next; /* Pointer on next entry for the */
4938 - /* same inode or on next free entry */
4942 * Structure of a blocks group descriptor
4944 struct ext2_group_desc
4946 #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
4947 #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
4948 #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
4949 +#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
4951 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
4952 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
4956 #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
4957 +#define EXT2_I(inode) (&((inode)->u.ext2_i))
4959 /* Assume that user mode programs are passing in an ext2fs superblock, not
4960 * a kernel struct super_block. This will allow us to call the feature-test
4962 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
4963 #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
4965 -#define EXT2_FEATURE_COMPAT_SUPP 0
4966 +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
4967 #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
4968 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
4969 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
4970 @@ -623,8 +600,10 @@
4973 extern struct inode_operations ext2_dir_inode_operations;
4974 +extern struct inode_operations ext2_special_inode_operations;
4977 +extern struct inode_operations ext2_symlink_inode_operations;
4978 extern struct inode_operations ext2_fast_symlink_inode_operations;
4980 #endif /* __KERNEL__ */
4981 Index: linux-2.4.19-pre1/include/linux/ext2_xattr.h
4982 ===================================================================
4983 --- linux-2.4.19-pre1.orig/include/linux/ext2_xattr.h 2003-11-21 03:51:05.000000000 +0300
4984 +++ linux-2.4.19-pre1/include/linux/ext2_xattr.h 2003-11-21 03:51:05.000000000 +0300
4987 + File: linux/ext2_xattr.h
4989 + On-disk format of extended attributes for the ext2 filesystem.
4991 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4994 +#include <linux/config.h>
4995 +#include <linux/init.h>
4996 +#include <linux/xattr.h>
4998 +/* Magic value in attribute blocks */
4999 +#define EXT2_XATTR_MAGIC 0xEA020000
5001 +/* Maximum number of references to one attribute block */
5002 +#define EXT2_XATTR_REFCOUNT_MAX 1024
5005 +#define EXT2_XATTR_INDEX_MAX 10
5006 +#define EXT2_XATTR_INDEX_USER 1
5007 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
5008 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5010 +struct ext2_xattr_header {
5011 + __u32 h_magic; /* magic number for identification */
5012 + __u32 h_refcount; /* reference count */
5013 + __u32 h_blocks; /* number of disk blocks used */
5014 + __u32 h_hash; /* hash value of all attributes */
5015 + __u32 h_reserved[4]; /* zero right now */
5018 +struct ext2_xattr_entry {
5019 + __u8 e_name_len; /* length of name */
5020 + __u8 e_name_index; /* attribute name index */
5021 + __u16 e_value_offs; /* offset in disk block of value */
5022 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5023 + __u32 e_value_size; /* size of attribute value */
5024 + __u32 e_hash; /* hash value of name and value */
5025 + char e_name[0]; /* attribute name */
5028 +#define EXT2_XATTR_PAD_BITS 2
5029 +#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
5030 +#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
5031 +#define EXT2_XATTR_LEN(name_len) \
5032 + (((name_len) + EXT2_XATTR_ROUND + \
5033 + sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
5034 +#define EXT2_XATTR_NEXT(entry) \
5035 + ( (struct ext2_xattr_entry *)( \
5036 + (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
5037 +#define EXT2_XATTR_SIZE(size) \
5038 + (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
5042 +# ifdef CONFIG_EXT2_FS_XATTR
5044 +struct ext2_xattr_handler {
5046 + size_t (*list)(char *list, struct inode *inode, const char *name,
5048 + int (*get)(struct inode *inode, const char *name, void *buffer,
5050 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5051 + size_t size, int flags);
5054 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
5055 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
5057 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
5058 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
5059 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
5060 +extern int ext2_removexattr(struct dentry *, const char *);
5062 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
5063 +extern int ext2_xattr_list(struct inode *, char *, size_t);
5064 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
5066 +extern void ext2_xattr_delete_inode(struct inode *);
5067 +extern void ext2_xattr_put_super(struct super_block *);
5069 +extern int init_ext2_xattr(void) __init;
5070 +extern void exit_ext2_xattr(void);
5072 +# else /* CONFIG_EXT2_FS_XATTR */
5073 +# define ext2_setxattr NULL
5074 +# define ext2_getxattr NULL
5075 +# define ext2_listxattr NULL
5076 +# define ext2_removexattr NULL
5079 +ext2_xattr_get(struct inode *inode, int name_index,
5080 + const char *name, void *buffer, size_t size)
5086 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
5092 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
5093 + const void *value, size_t size, int flags)
5099 +ext2_xattr_delete_inode(struct inode *inode)
5104 +ext2_xattr_put_super(struct super_block *sb)
5109 +init_ext2_xattr(void)
5115 +exit_ext2_xattr(void)
5119 +# endif /* CONFIG_EXT2_FS_XATTR */
5121 +# ifdef CONFIG_EXT2_FS_XATTR_USER
5123 +extern int init_ext2_xattr_user(void) __init;
5124 +extern void exit_ext2_xattr_user(void);
5126 +# else /* CONFIG_EXT2_FS_XATTR_USER */
5129 +init_ext2_xattr_user(void)
5135 +exit_ext2_xattr_user(void)
5139 +# endif /* CONFIG_EXT2_FS_XATTR_USER */
5141 +#endif /* __KERNEL__ */
5143 Index: linux-2.4.19-pre1/include/linux/ext3_fs.h
5144 ===================================================================
5145 --- linux-2.4.19-pre1.orig/include/linux/ext3_fs.h 2003-11-21 03:51:02.000000000 +0300
5146 +++ linux-2.4.19-pre1/include/linux/ext3_fs.h 2003-11-21 03:51:05.000000000 +0300
5149 #define EXT3_BAD_INO 1 /* Bad blocks inode */
5150 #define EXT3_ROOT_INO 2 /* Root inode */
5151 -#define EXT3_ACL_IDX_INO 3 /* ACL inode */
5152 -#define EXT3_ACL_DATA_INO 4 /* ACL inode */
5153 #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
5154 #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
5155 #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
5158 # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5160 -#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
5161 #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
5163 # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5164 @@ -129,28 +126,6 @@
5170 -struct ext3_acl_header /* Header of Access Control Lists */
5173 - __u32 aclh_file_count;
5174 - __u32 aclh_acle_count;
5175 - __u32 aclh_first_acle;
5178 -struct ext3_acl_entry /* Access Control List Entry */
5181 - __u16 acle_perms; /* Access permissions */
5182 - __u16 acle_type; /* Type of entry */
5183 - __u16 acle_tag; /* User or group identity */
5185 - __u32 acle_next; /* Pointer on next entry for the */
5186 - /* same inode or on next free entry */
5190 * Structure of a blocks group descriptor
5192 struct ext3_group_desc
5194 #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
5195 #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
5196 #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
5197 +#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5199 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
5200 #ifndef _LINUX_EXT2_FS_H
5202 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
5203 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
5205 -#define EXT3_FEATURE_COMPAT_SUPP 0
5206 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5207 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
5208 EXT3_FEATURE_INCOMPAT_RECOVER)
5209 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5211 extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
5214 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
5215 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
5216 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
5218 @@ -771,8 +748,10 @@
5221 extern struct inode_operations ext3_dir_inode_operations;
5222 +extern struct inode_operations ext3_special_inode_operations;
5225 +extern struct inode_operations ext3_symlink_inode_operations;
5226 extern struct inode_operations ext3_fast_symlink_inode_operations;
5229 Index: linux-2.4.19-pre1/include/linux/ext3_jbd.h
5230 ===================================================================
5231 --- linux-2.4.19-pre1.orig/include/linux/ext3_jbd.h 2003-11-21 03:51:02.000000000 +0300
5232 +++ linux-2.4.19-pre1/include/linux/ext3_jbd.h 2003-11-21 03:51:05.000000000 +0300
5235 #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
5237 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5238 + * and two group and summaries. */
5240 +#define EXT3_XATTR_TRANS_BLOCKS 8
5242 /* Define the minimum size for a transaction which modifies data. This
5243 * needs to take into account the fact that we may end up modifying two
5244 * quota files too (one for the group, one for the user quota). The
5245 * superblock only gets updated once, of course, so don't bother
5246 * counting that again for the quota updates. */
5248 -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5249 +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5250 + EXT3_XATTR_TRANS_BLOCKS - 2)
5252 extern int ext3_writepage_trans_blocks(struct inode *inode);
5254 Index: linux-2.4.19-pre1/include/linux/ext3_xattr.h
5255 ===================================================================
5256 --- linux-2.4.19-pre1.orig/include/linux/ext3_xattr.h 2003-11-21 03:51:05.000000000 +0300
5257 +++ linux-2.4.19-pre1/include/linux/ext3_xattr.h 2003-11-21 03:51:05.000000000 +0300
5260 + File: linux/ext3_xattr.h
5262 + On-disk format of extended attributes for the ext3 filesystem.
5264 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5267 +#include <linux/config.h>
5268 +#include <linux/init.h>
5269 +#include <linux/xattr.h>
5271 +/* Magic value in attribute blocks */
5272 +#define EXT3_XATTR_MAGIC 0xEA020000
5274 +/* Maximum number of references to one attribute block */
5275 +#define EXT3_XATTR_REFCOUNT_MAX 1024
5278 +#define EXT3_XATTR_INDEX_MAX 10
5279 +#define EXT3_XATTR_INDEX_USER 1
5280 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
5281 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5283 +struct ext3_xattr_header {
5284 + __u32 h_magic; /* magic number for identification */
5285 + __u32 h_refcount; /* reference count */
5286 + __u32 h_blocks; /* number of disk blocks used */
5287 + __u32 h_hash; /* hash value of all attributes */
5288 + __u32 h_reserved[4]; /* zero right now */
5291 +struct ext3_xattr_entry {
5292 + __u8 e_name_len; /* length of name */
5293 + __u8 e_name_index; /* attribute name index */
5294 + __u16 e_value_offs; /* offset in disk block of value */
5295 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5296 + __u32 e_value_size; /* size of attribute value */
5297 + __u32 e_hash; /* hash value of name and value */
5298 + char e_name[0]; /* attribute name */
5301 +#define EXT3_XATTR_PAD_BITS 2
5302 +#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
5303 +#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
5304 +#define EXT3_XATTR_LEN(name_len) \
5305 + (((name_len) + EXT3_XATTR_ROUND + \
5306 + sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5307 +#define EXT3_XATTR_NEXT(entry) \
5308 + ( (struct ext3_xattr_entry *)( \
5309 + (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5310 +#define EXT3_XATTR_SIZE(size) \
5311 + (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5315 +# ifdef CONFIG_EXT3_FS_XATTR
5317 +struct ext3_xattr_handler {
5319 + size_t (*list)(char *list, struct inode *inode, const char *name,
5321 + int (*get)(struct inode *inode, const char *name, void *buffer,
5323 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5324 + size_t size, int flags);
5327 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5328 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5330 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5331 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5332 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5333 +extern int ext3_removexattr(struct dentry *, const char *);
5335 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5336 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5337 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5339 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5340 +extern void ext3_xattr_put_super(struct super_block *);
5342 +extern int init_ext3_xattr(void) __init;
5343 +extern void exit_ext3_xattr(void);
5345 +# else /* CONFIG_EXT3_FS_XATTR */
5346 +# define ext3_setxattr NULL
5347 +# define ext3_getxattr NULL
5348 +# define ext3_listxattr NULL
5349 +# define ext3_removexattr NULL
5352 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5353 + void *buffer, size_t size)
5359 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5365 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5366 + const char *name, const void *value, size_t size, int flags)
5372 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5377 +ext3_xattr_put_super(struct super_block *sb)
5382 +init_ext3_xattr(void)
5388 +exit_ext3_xattr(void)
5392 +# endif /* CONFIG_EXT3_FS_XATTR */
5394 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5396 +extern int init_ext3_xattr_user(void) __init;
5397 +extern void exit_ext3_xattr_user(void);
5399 +# else /* CONFIG_EXT3_FS_XATTR_USER */
5402 +init_ext3_xattr_user(void)
5408 +exit_ext3_xattr_user(void)
5412 +#endif /* CONFIG_EXT3_FS_XATTR_USER */
5414 +#endif /* __KERNEL__ */
5416 Index: linux-2.4.19-pre1/include/linux/fs.h
5417 ===================================================================
5418 --- linux-2.4.19-pre1.orig/include/linux/fs.h 2003-11-21 03:51:00.000000000 +0300
5419 +++ linux-2.4.19-pre1/include/linux/fs.h 2003-11-21 03:51:05.000000000 +0300
5420 @@ -872,6 +872,10 @@
5421 int (*setattr) (struct dentry *, struct iattr *);
5422 int (*setattr_raw) (struct inode *, struct iattr *);
5423 int (*getattr) (struct dentry *, struct iattr *);
5424 + int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5425 + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5426 + ssize_t (*listxattr) (struct dentry *, char *, size_t);
5427 + int (*removexattr) (struct dentry *, const char *);
5431 Index: linux-2.4.19-pre1/include/linux/mbcache.h
5432 ===================================================================
5433 --- linux-2.4.19-pre1.orig/include/linux/mbcache.h 2003-11-21 03:51:05.000000000 +0300
5434 +++ linux-2.4.19-pre1/include/linux/mbcache.h 2003-11-21 03:51:05.000000000 +0300
5437 + File: linux/mbcache.h
5439 + (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5442 +/* Hardwire the number of additional indexes */
5443 +#define MB_CACHE_INDEXES_COUNT 1
5445 +struct mb_cache_entry;
5447 +struct mb_cache_op {
5448 + int (*free)(struct mb_cache_entry *, int);
5452 + struct list_head c_cache_list;
5453 + const char *c_name;
5454 + struct mb_cache_op c_op;
5455 + atomic_t c_entry_count;
5456 + int c_bucket_count;
5457 +#ifndef MB_CACHE_INDEXES_COUNT
5458 + int c_indexes_count;
5460 + kmem_cache_t *c_entry_cache;
5461 + struct list_head *c_block_hash;
5462 + struct list_head *c_indexes_hash[0];
5465 +struct mb_cache_entry_index {
5466 + struct list_head o_list;
5467 + unsigned int o_key;
5470 +struct mb_cache_entry {
5471 + struct list_head e_lru_list;
5472 + struct mb_cache *e_cache;
5475 + unsigned long e_block;
5476 + struct list_head e_block_list;
5477 + struct mb_cache_entry_index e_indexes[0];
5480 +/* Functions on caches */
5482 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5484 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5485 +void mb_cache_destroy(struct mb_cache *);
5487 +/* Functions on cache entries */
5489 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5490 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5492 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5493 +void mb_cache_entry_release(struct mb_cache_entry *);
5494 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5495 +void mb_cache_entry_free(struct mb_cache_entry *);
5496 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5497 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5499 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5500 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5501 + kdev_t, unsigned int);
5502 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5503 + kdev_t, unsigned int);
5505 Index: linux-2.4.19-pre1/kernel/ksyms.c
5506 ===================================================================
5507 --- linux-2.4.19-pre1.orig/kernel/ksyms.c 2003-11-21 03:50:59.000000000 +0300
5508 +++ linux-2.4.19-pre1/kernel/ksyms.c 2003-11-21 03:51:05.000000000 +0300
5511 #include <linux/config.h>
5512 #include <linux/slab.h>
5513 +#include <linux/cache_def.h>
5514 #include <linux/module.h>
5515 #include <linux/blkdev.h>
5516 #include <linux/cdrom.h>
5518 EXPORT_SYMBOL(exit_files);
5519 EXPORT_SYMBOL(exit_fs);
5520 EXPORT_SYMBOL(exit_sighand);
5521 +EXPORT_SYMBOL(copy_fs_struct);
5523 /* internal kernel memory management */
5524 EXPORT_SYMBOL(_alloc_pages);
5526 EXPORT_SYMBOL(kmem_cache_shrink);
5527 EXPORT_SYMBOL(kmem_cache_alloc);
5528 EXPORT_SYMBOL(kmem_cache_free);
5529 +EXPORT_SYMBOL(register_cache);
5530 +EXPORT_SYMBOL(unregister_cache);
5531 EXPORT_SYMBOL(kmalloc);
5532 EXPORT_SYMBOL(kfree);
5533 EXPORT_SYMBOL(vfree);
5534 Index: linux-2.4.19-pre1/mm/vmscan.c
5535 ===================================================================
5536 --- linux-2.4.19-pre1.orig/mm/vmscan.c 2003-11-20 19:01:38.000000000 +0300
5537 +++ linux-2.4.19-pre1/mm/vmscan.c 2003-11-21 03:51:05.000000000 +0300
5539 #include <linux/kernel_stat.h>
5540 #include <linux/swap.h>
5541 #include <linux/swapctl.h>
5542 +#include <linux/cache_def.h>
5543 #include <linux/smp_lock.h>
5544 #include <linux/pagemap.h>
5545 #include <linux/init.h>
5548 #define DEF_PRIORITY (6)
5550 +static DECLARE_MUTEX(other_caches_sem);
5551 +static LIST_HEAD(cache_definitions);
5553 +void register_cache(struct cache_definition *cache)
5555 + down(&other_caches_sem);
5556 + list_add(&cache->link, &cache_definitions);
5557 + up(&other_caches_sem);
5560 +void unregister_cache(struct cache_definition *cache)
5562 + down(&other_caches_sem);
5563 + list_del(&cache->link);
5564 + up(&other_caches_sem);
5567 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
5569 + struct list_head *p;
5571 + if (down_trylock(&other_caches_sem))
5574 + list_for_each_prev(p, &cache_definitions) {
5575 + struct cache_definition *cache =
5576 + list_entry(p, struct cache_definition, link);
5578 + cache->shrink(priority, gfp_mask);
5580 + up(&other_caches_sem);
5584 * The swap-out function returns 1 if it successfully
5585 * scanned all the pages it was asked to (`count').
5588 shrink_dcache_memory(priority, gfp_mask);
5589 shrink_icache_memory(priority, gfp_mask);
5590 + shrink_other_caches(priority, gfp_mask);
5592 shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
5594 Index: linux-2.4.19-pre1/fs/ext3/ext3-exports.c
5595 ===================================================================
5596 --- linux-2.4.19-pre1.orig/fs/ext3/ext3-exports.c 2003-11-21 03:51:05.000000000 +0300
5597 +++ linux-2.4.19-pre1/fs/ext3/ext3-exports.c 2003-11-21 03:51:05.000000000 +0300
5599 +#include <linux/config.h>
5600 +#include <linux/module.h>
5601 +#include <linux/ext3_fs.h>
5602 +#include <linux/ext3_jbd.h>
5603 +#include <linux/ext3_xattr.h>
5605 +EXPORT_SYMBOL(ext3_force_commit);
5606 +EXPORT_SYMBOL(ext3_bread);
5607 +EXPORT_SYMBOL(ext3_xattr_register);
5608 +EXPORT_SYMBOL(ext3_xattr_unregister);
5609 +EXPORT_SYMBOL(ext3_xattr_get);
5610 +EXPORT_SYMBOL(ext3_xattr_list);
5611 +EXPORT_SYMBOL(ext3_xattr_set);
5612 Index: linux-2.4.19-pre1/include/linux/xattr.h
5613 ===================================================================
5614 --- linux-2.4.19-pre1.orig/include/linux/xattr.h 2003-11-21 03:51:05.000000000 +0300
5615 +++ linux-2.4.19-pre1/include/linux/xattr.h 2003-11-21 03:51:05.000000000 +0300
5618 + File: linux/xattr.h
5620 + Extended attributes handling.
5622 + Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
5623 + Copyright (c) 2001-2002 Silicon Graphics, Inc. All Rights Reserved.
5625 +#ifndef _LINUX_XATTR_H
5626 +#define _LINUX_XATTR_H
5628 +#define XATTR_CREATE 0x1 /* set the value, fail if attr already exists */
5629 +#define XATTR_REPLACE 0x2 /* set the value, fail if attr does not exist */
5631 +#endif /* _LINUX_XATTR_H */
5632 Index: linux-2.4.19-pre1/arch/i386/kernel/entry.S
5633 ===================================================================
5634 --- linux-2.4.19-pre1.orig/arch/i386/kernel/entry.S 2003-11-21 03:38:55.000000000 +0300
5635 +++ linux-2.4.19-pre1/arch/i386/kernel/entry.S 2003-11-21 03:51:05.000000000 +0300
5636 @@ -622,18 +622,18 @@
5637 .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */
5638 .long SYMBOL_NAME(sys_gettid)
5639 .long SYMBOL_NAME(sys_readahead) /* 225 */
5640 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for setxattr */
5641 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for lsetxattr */
5642 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fsetxattr */
5643 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for getxattr */
5644 - .long SYMBOL_NAME(sys_ni_syscall) /* 230 reserved for lgetxattr */
5645 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fgetxattr */
5646 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for listxattr */
5647 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for llistxattr */
5648 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for flistxattr */
5649 - .long SYMBOL_NAME(sys_ni_syscall) /* 235 reserved for removexattr */
5650 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for lremovexattr */
5651 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fremovexattr */
5652 + .long SYMBOL_NAME(sys_setxattr)
5653 + .long SYMBOL_NAME(sys_lsetxattr)
5654 + .long SYMBOL_NAME(sys_fsetxattr)
5655 + .long SYMBOL_NAME(sys_getxattr)
5656 + .long SYMBOL_NAME(sys_lgetxattr) /* 230 */
5657 + .long SYMBOL_NAME(sys_fgetxattr)
5658 + .long SYMBOL_NAME(sys_listxattr)
5659 + .long SYMBOL_NAME(sys_llistxattr)
5660 + .long SYMBOL_NAME(sys_flistxattr)
5661 + .long SYMBOL_NAME(sys_removexattr) /* 235 */
5662 + .long SYMBOL_NAME(sys_lremovexattr)
5663 + .long SYMBOL_NAME(sys_fremovexattr)
5665 .rept NR_syscalls-(.-sys_call_table)/4
5666 .long SYMBOL_NAME(sys_ni_syscall)
5667 Index: linux-2.4.19-pre1/fs/xattr.c
5668 ===================================================================
5669 --- linux-2.4.19-pre1.orig/fs/xattr.c 2003-11-21 03:51:05.000000000 +0300
5670 +++ linux-2.4.19-pre1/fs/xattr.c 2003-11-21 03:51:05.000000000 +0300
5675 + Extended attribute handling.
5677 + Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
5678 + Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
5680 +#include <linux/fs.h>
5681 +#include <linux/slab.h>
5682 +#include <linux/vmalloc.h>
5683 +#include <linux/smp_lock.h>
5684 +#include <linux/file.h>
5685 +#include <linux/xattr.h>
5686 +#include <asm/uaccess.h>
5689 + * Extended attribute memory allocation wrappers, originally
5690 + * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
5691 + * The vmalloc use here is very uncommon - extended attributes
5692 + * are supposed to be small chunks of metadata, and it is quite
5693 + * unusual to have very many extended attributes, so lists tend
5694 + * to be quite short as well. The 64K upper limit is derived
5695 + * from the extended attribute size limit used by XFS.
5696 + * Intentionally allow zero @size for value/list size requests.
5699 +xattr_alloc(size_t size, size_t limit)
5704 + return ERR_PTR(-E2BIG);
5706 + if (!size) /* size request, no buffer is needed */
5708 + else if (size <= PAGE_SIZE)
5709 + ptr = kmalloc((unsigned long) size, GFP_KERNEL);
5711 + ptr = vmalloc((unsigned long) size);
5713 + return ERR_PTR(-ENOMEM);
5718 +xattr_free(void *ptr, size_t size)
5720 + if (!size) /* size request, no buffer was needed */
5722 + else if (size <= PAGE_SIZE)
5729 + * Extended attribute SET operations
5732 +setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
5736 + char kname[XATTR_NAME_MAX + 1];
5738 + if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
5741 + error = strncpy_from_user(kname, name, sizeof(kname));
5742 + if (error == 0 || error == sizeof(kname))
5747 + kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
5748 + if (IS_ERR(kvalue))
5749 + return PTR_ERR(kvalue);
5751 + if (size > 0 && copy_from_user(kvalue, value, size)) {
5752 + xattr_free(kvalue, size);
5756 + error = -EOPNOTSUPP;
5757 + if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
5758 + down(&d->d_inode->i_sem);
5760 + error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
5762 + up(&d->d_inode->i_sem);
5765 + xattr_free(kvalue, size);
5770 +sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
5772 + struct nameidata nd;
5775 + error = user_path_walk(path, &nd);
5778 + error = setxattr(nd.dentry, name, value, size, flags);
5779 + path_release(&nd);
5784 +sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
5786 + struct nameidata nd;
5789 + error = user_path_walk_link(path, &nd);
5792 + error = setxattr(nd.dentry, name, value, size, flags);
5793 + path_release(&nd);
5798 +sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
5801 + int error = -EBADF;
5806 + error = setxattr(f->f_dentry, name, value, size, flags);
5812 + * Extended attribute GET operations
5815 +getxattr(struct dentry *d, char *name, void *value, size_t size)
5819 + char kname[XATTR_NAME_MAX + 1];
5821 + error = strncpy_from_user(kname, name, sizeof(kname));
5822 + if (error == 0 || error == sizeof(kname))
5827 + kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
5828 + if (IS_ERR(kvalue))
5829 + return PTR_ERR(kvalue);
5831 + error = -EOPNOTSUPP;
5832 + if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
5833 + down(&d->d_inode->i_sem);
5835 + error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
5837 + up(&d->d_inode->i_sem);
5840 + if (kvalue && error > 0)
5841 + if (copy_to_user(value, kvalue, error))
5843 + xattr_free(kvalue, size);
5848 +sys_getxattr(char *path, char *name, void *value, size_t size)
5850 + struct nameidata nd;
5853 + error = user_path_walk(path, &nd);
5856 + error = getxattr(nd.dentry, name, value, size);
5857 + path_release(&nd);
5862 +sys_lgetxattr(char *path, char *name, void *value, size_t size)
5864 + struct nameidata nd;
5867 + error = user_path_walk_link(path, &nd);
5870 + error = getxattr(nd.dentry, name, value, size);
5871 + path_release(&nd);
5876 +sys_fgetxattr(int fd, char *name, void *value, size_t size)
5879 + ssize_t error = -EBADF;
5884 + error = getxattr(f->f_dentry, name, value, size);
5890 + * Extended attribute LIST operations
5893 +listxattr(struct dentry *d, char *list, size_t size)
5898 + klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
5899 + if (IS_ERR(klist))
5900 + return PTR_ERR(klist);
5902 + error = -EOPNOTSUPP;
5903 + if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
5904 + down(&d->d_inode->i_sem);
5906 + error = d->d_inode->i_op->listxattr(d, klist, size);
5908 + up(&d->d_inode->i_sem);
5911 + if (klist && error > 0)
5912 + if (copy_to_user(list, klist, error))
5914 + xattr_free(klist, size);
5919 +sys_listxattr(char *path, char *list, size_t size)
5921 + struct nameidata nd;
5924 + error = user_path_walk(path, &nd);
5927 + error = listxattr(nd.dentry, list, size);
5928 + path_release(&nd);
5933 +sys_llistxattr(char *path, char *list, size_t size)
5935 + struct nameidata nd;
5938 + error = user_path_walk_link(path, &nd);
5941 + error = listxattr(nd.dentry, list, size);
5942 + path_release(&nd);
5947 +sys_flistxattr(int fd, char *list, size_t size)
5950 + ssize_t error = -EBADF;
5955 + error = listxattr(f->f_dentry, list, size);
5961 + * Extended attribute REMOVE operations
5964 +removexattr(struct dentry *d, char *name)
5967 + char kname[XATTR_NAME_MAX + 1];
5969 + error = strncpy_from_user(kname, name, sizeof(kname));
5970 + if (error == 0 || error == sizeof(kname))
5975 + error = -EOPNOTSUPP;
5976 + if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
5977 + down(&d->d_inode->i_sem);
5979 + error = d->d_inode->i_op->removexattr(d, kname);
5981 + up(&d->d_inode->i_sem);
5987 +sys_removexattr(char *path, char *name)
5989 + struct nameidata nd;
5992 + error = user_path_walk(path, &nd);
5995 + error = removexattr(nd.dentry, name);
5996 + path_release(&nd);
6001 +sys_lremovexattr(char *path, char *name)
6003 + struct nameidata nd;
6006 + error = user_path_walk_link(path, &nd);
6009 + error = removexattr(nd.dentry, name);
6010 + path_release(&nd);
6015 +sys_fremovexattr(int fd, char *name)
6018 + int error = -EBADF;
6023 + error = removexattr(f->f_dentry, name);
6027 Index: linux-2.4.19-pre1/include/linux/kernel.h
6028 ===================================================================
6029 --- linux-2.4.19-pre1.orig/include/linux/kernel.h 2003-11-21 02:25:34.000000000 +0300
6030 +++ linux-2.4.19-pre1/include/linux/kernel.h 2003-11-21 03:51:05.000000000 +0300
6032 #include <linux/linkage.h>
6033 #include <linux/stddef.h>
6034 #include <linux/types.h>
6035 +#include <linux/compiler.h>
6037 /* Optimization barrier */
6038 /* The "volatile" is due to gcc bugs */