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 2004-01-14 01:11:29.000000000 +0300
70 +++ linux-2.4.19-pre1/Documentation/Configure.help 2004-01-14 01:11:49.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 2004-01-14 01:11:49.000000000 +0300
157 # Automatically generated make config: don't edit
159 +CONFIG_EXT3_FS_XATTR=y
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 2004-01-14 01:11:49.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 2004-01-14 01:11:49.000000000 +0300
196 # Automatically generated make config: don't edit
198 +CONFIG_EXT3_FS_XATTR=y
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 2004-01-14 01:11:49.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 2004-01-14 01:10:36.000000000 +0300
238 +++ linux-2.4.19-pre1/arch/i386/defconfig 2004-01-14 01:11:49.000000000 +0300
241 # Automatically generated make config: don't edit
243 +CONFIG_EXT3_FS_XATTR=y
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/i386/kernel/entry.S
254 ===================================================================
255 --- linux-2.4.19-pre1.orig/arch/i386/kernel/entry.S 2004-01-14 01:11:46.000000000 +0300
256 +++ linux-2.4.19-pre1/arch/i386/kernel/entry.S 2004-01-14 01:11:49.000000000 +0300
257 @@ -619,18 +619,18 @@
258 .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */
259 .long SYMBOL_NAME(sys_gettid)
260 .long SYMBOL_NAME(sys_readahead) /* 225 */
261 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for setxattr */
262 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for lsetxattr */
263 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fsetxattr */
264 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for getxattr */
265 - .long SYMBOL_NAME(sys_ni_syscall) /* 230 reserved for lgetxattr */
266 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fgetxattr */
267 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for listxattr */
268 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for llistxattr */
269 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for flistxattr */
270 - .long SYMBOL_NAME(sys_ni_syscall) /* 235 reserved for removexattr */
271 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for lremovexattr */
272 - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fremovexattr */
273 + .long SYMBOL_NAME(sys_setxattr)
274 + .long SYMBOL_NAME(sys_lsetxattr)
275 + .long SYMBOL_NAME(sys_fsetxattr)
276 + .long SYMBOL_NAME(sys_getxattr)
277 + .long SYMBOL_NAME(sys_lgetxattr) /* 230 */
278 + .long SYMBOL_NAME(sys_fgetxattr)
279 + .long SYMBOL_NAME(sys_listxattr)
280 + .long SYMBOL_NAME(sys_llistxattr)
281 + .long SYMBOL_NAME(sys_flistxattr)
282 + .long SYMBOL_NAME(sys_removexattr) /* 235 */
283 + .long SYMBOL_NAME(sys_lremovexattr)
284 + .long SYMBOL_NAME(sys_fremovexattr)
286 .rept NR_syscalls-(.-sys_call_table)/4
287 .long SYMBOL_NAME(sys_ni_syscall)
288 Index: linux-2.4.19-pre1/arch/ia64/defconfig
289 ===================================================================
290 --- linux-2.4.19-pre1.orig/arch/ia64/defconfig 2001-11-10 01:26:17.000000000 +0300
291 +++ linux-2.4.19-pre1/arch/ia64/defconfig 2004-01-14 01:11:49.000000000 +0300
294 # Automatically generated make config: don't edit
296 +CONFIG_EXT3_FS_XATTR=y
297 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
298 +# CONFIG_EXT3_FS_XATTR_USER is not set
299 +# CONFIG_EXT2_FS_XATTR is not set
300 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
301 +# CONFIG_EXT2_FS_XATTR_USER is not set
302 +# CONFIG_FS_MBCACHE is not set
305 # Code maturity level options
306 Index: linux-2.4.19-pre1/arch/ia64/kernel/entry.S
307 ===================================================================
308 --- linux-2.4.19-pre1.orig/arch/ia64/kernel/entry.S 2001-11-10 01:26:17.000000000 +0300
309 +++ linux-2.4.19-pre1/arch/ia64/kernel/entry.S 2004-01-14 01:11:49.000000000 +0300
310 @@ -1130,18 +1130,18 @@
312 data8 sys_getunwind // 1215
314 - data8 ia64_ni_syscall
315 - data8 ia64_ni_syscall
316 - data8 ia64_ni_syscall
317 - data8 ia64_ni_syscall // 1220
318 - data8 ia64_ni_syscall
319 - data8 ia64_ni_syscall
320 - data8 ia64_ni_syscall
321 - data8 ia64_ni_syscall
322 - data8 ia64_ni_syscall // 1225
323 - data8 ia64_ni_syscall
324 - data8 ia64_ni_syscall
325 - data8 ia64_ni_syscall
327 + data8 sys_lsetxattr
328 + data8 sys_fsetxattr
329 + data8 sys_getxattr // 1220
330 + data8 sys_lgetxattr
331 + data8 sys_fgetxattr
332 + data8 sys_listxattr
333 + data8 sys_llistxattr
334 + data8 sys_flistxattr // 1225
335 + data8 sys_removexattr
336 + data8 sys_lremovexattr
337 + data8 sys_fremovexattr
338 data8 ia64_ni_syscall
339 data8 ia64_ni_syscall // 1230
340 data8 ia64_ni_syscall
341 Index: linux-2.4.19-pre1/arch/m68k/defconfig
342 ===================================================================
343 --- linux-2.4.19-pre1.orig/arch/m68k/defconfig 2000-06-19 23:56:08.000000000 +0400
344 +++ linux-2.4.19-pre1/arch/m68k/defconfig 2004-01-14 01:11:49.000000000 +0300
347 # Automatically generated make config: don't edit
349 +CONFIG_EXT3_FS_XATTR=y
350 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
351 +# CONFIG_EXT3_FS_XATTR_USER is not set
352 +# CONFIG_EXT2_FS_XATTR is not set
353 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
354 +# CONFIG_EXT2_FS_XATTR_USER is not set
355 +# CONFIG_FS_MBCACHE is not set
359 Index: linux-2.4.19-pre1/arch/mips/defconfig
360 ===================================================================
361 --- linux-2.4.19-pre1.orig/arch/mips/defconfig 2001-09-09 21:43:02.000000000 +0400
362 +++ linux-2.4.19-pre1/arch/mips/defconfig 2004-01-14 01:11:49.000000000 +0300
365 # Automatically generated make config: don't edit
367 +CONFIG_EXT3_FS_XATTR=y
368 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
369 +# CONFIG_EXT3_FS_XATTR_USER is not set
370 +# CONFIG_EXT2_FS_XATTR is not set
371 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
372 +# CONFIG_EXT2_FS_XATTR_USER is not set
373 +# CONFIG_FS_MBCACHE is not set
375 # CONFIG_SMP is not set
377 Index: linux-2.4.19-pre1/arch/mips64/defconfig
378 ===================================================================
379 --- linux-2.4.19-pre1.orig/arch/mips64/defconfig 2001-09-09 21:43:02.000000000 +0400
380 +++ linux-2.4.19-pre1/arch/mips64/defconfig 2004-01-14 01:11:49.000000000 +0300
383 # Automatically generated make config: don't edit
385 +CONFIG_EXT3_FS_XATTR=y
386 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
387 +# CONFIG_EXT3_FS_XATTR_USER is not set
388 +# CONFIG_EXT2_FS_XATTR is not set
389 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
390 +# CONFIG_EXT2_FS_XATTR_USER is not set
391 +# CONFIG_FS_MBCACHE is not set
394 # Code maturity level options
395 Index: linux-2.4.19-pre1/arch/ppc/defconfig
396 ===================================================================
397 --- linux-2.4.19-pre1.orig/arch/ppc/defconfig 2004-01-14 01:10:36.000000000 +0300
398 +++ linux-2.4.19-pre1/arch/ppc/defconfig 2004-01-14 01:11:49.000000000 +0300
401 # Automatically generated make config: don't edit
403 +CONFIG_EXT3_FS_XATTR=y
404 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
405 +# CONFIG_EXT3_FS_XATTR_USER is not set
406 +# CONFIG_EXT2_FS_XATTR is not set
407 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
408 +# CONFIG_EXT2_FS_XATTR_USER is not set
409 +# CONFIG_FS_MBCACHE is not set
410 # CONFIG_UID16 is not set
411 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
412 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
413 Index: linux-2.4.19-pre1/arch/s390/defconfig
414 ===================================================================
415 --- linux-2.4.19-pre1.orig/arch/s390/defconfig 2004-01-14 01:10:36.000000000 +0300
416 +++ linux-2.4.19-pre1/arch/s390/defconfig 2004-01-14 01:11:49.000000000 +0300
419 # Automatically generated make config: don't edit
421 +CONFIG_EXT3_FS_XATTR=y
422 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
423 +# CONFIG_EXT3_FS_XATTR_USER is not set
424 +# CONFIG_EXT2_FS_XATTR is not set
425 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
426 +# CONFIG_EXT2_FS_XATTR_USER is not set
427 +# CONFIG_FS_MBCACHE is not set
428 # CONFIG_ISA is not set
429 # CONFIG_EISA is not set
430 # CONFIG_MCA is not set
431 Index: linux-2.4.19-pre1/arch/s390/kernel/entry.S
432 ===================================================================
433 --- linux-2.4.19-pre1.orig/arch/s390/kernel/entry.S 2004-01-14 01:10:36.000000000 +0300
434 +++ linux-2.4.19-pre1/arch/s390/kernel/entry.S 2004-01-14 01:11:49.000000000 +0300
437 .long sys_ni_syscall /* 222 - reserved for posix_acl */
438 .long sys_ni_syscall /* 223 - reserved for posix_acl */
439 - .long sys_ni_syscall /* 224 - reserved for posix_acl */
442 + .long sys_lsetxattr /* 225 */
443 + .long sys_fsetxattr
445 + .long sys_lgetxattr
446 + .long sys_fgetxattr
447 + .long sys_listxattr /* 230 */
448 + .long sys_llistxattr
449 + .long sys_flistxattr
450 + .long sys_removexattr
451 + .long sys_lremovexattr
452 + .long sys_fremovexattr /* 235 */
457 Index: linux-2.4.19-pre1/arch/s390x/defconfig
458 ===================================================================
459 --- linux-2.4.19-pre1.orig/arch/s390x/defconfig 2004-01-14 01:10:36.000000000 +0300
460 +++ linux-2.4.19-pre1/arch/s390x/defconfig 2004-01-14 01:11:49.000000000 +0300
463 # Automatically generated make config: don't edit
465 +CONFIG_EXT3_FS_XATTR=y
466 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
467 +# CONFIG_EXT3_FS_XATTR_USER is not set
468 +# CONFIG_EXT2_FS_XATTR is not set
469 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
470 +# CONFIG_EXT2_FS_XATTR_USER is not set
471 +# CONFIG_FS_MBCACHE is not set
472 # CONFIG_ISA is not set
473 # CONFIG_EISA is not set
474 # CONFIG_MCA is not set
475 Index: linux-2.4.19-pre1/arch/s390x/kernel/entry.S
476 ===================================================================
477 --- linux-2.4.19-pre1.orig/arch/s390x/kernel/entry.S 2004-01-14 01:10:36.000000000 +0300
478 +++ linux-2.4.19-pre1/arch/s390x/kernel/entry.S 2004-01-14 01:11:49.000000000 +0300
480 .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
481 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 222 - reserved for posix_acl */
482 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 223 - reserved for posix_acl */
483 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for posix_acl */
485 + .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
486 + .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
487 + .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
488 + .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
489 + .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
490 + .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
491 + .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
492 + .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
493 + .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
494 + .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
495 + .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
496 + .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
498 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
501 Index: linux-2.4.19-pre1/arch/s390x/kernel/wrapper32.S
502 ===================================================================
503 --- linux-2.4.19-pre1.orig/arch/s390x/kernel/wrapper32.S 2004-01-14 01:10:36.000000000 +0300
504 +++ linux-2.4.19-pre1/arch/s390x/kernel/wrapper32.S 2004-01-14 01:11:49.000000000 +0300
505 @@ -1091,3 +1091,95 @@
506 llgtr %r3,%r3 # struct stat64 *
508 jg sys32_fstat64 # branch to system call
510 + .globl sys32_setxattr_wrapper
511 +sys32_setxattr_wrapper:
512 + llgtr %r2,%r2 # char *
513 + llgtr %r3,%r3 # char *
514 + llgtr %r4,%r4 # void *
515 + llgfr %r5,%r5 # size_t
519 + .globl sys32_lsetxattr_wrapper
520 +sys32_lsetxattr_wrapper:
521 + llgtr %r2,%r2 # char *
522 + llgtr %r3,%r3 # char *
523 + llgtr %r4,%r4 # void *
524 + llgfr %r5,%r5 # size_t
528 + .globl sys32_fsetxattr_wrapper
529 +sys32_fsetxattr_wrapper:
531 + llgtr %r3,%r3 # char *
532 + llgtr %r4,%r4 # void *
533 + llgfr %r5,%r5 # size_t
537 + .globl sys32_getxattr_wrapper
538 +sys32_getxattr_wrapper:
539 + llgtr %r2,%r2 # char *
540 + llgtr %r3,%r3 # char *
541 + llgtr %r4,%r4 # void *
542 + llgfr %r5,%r5 # size_t
545 + .globl sys32_lgetxattr_wrapper
546 +sys32_lgetxattr_wrapper:
547 + llgtr %r2,%r2 # char *
548 + llgtr %r3,%r3 # char *
549 + llgtr %r4,%r4 # void *
550 + llgfr %r5,%r5 # size_t
553 + .globl sys32_fgetxattr_wrapper
554 +sys32_fgetxattr_wrapper:
556 + llgtr %r3,%r3 # char *
557 + llgtr %r4,%r4 # void *
558 + llgfr %r5,%r5 # size_t
561 + .globl sys32_listxattr_wrapper
562 +sys32_listxattr_wrapper:
563 + llgtr %r2,%r2 # char *
564 + llgtr %r3,%r3 # char *
565 + llgfr %r4,%r4 # size_t
568 + .globl sys32_llistxattr_wrapper
569 +sys32_llistxattr_wrapper:
570 + llgtr %r2,%r2 # char *
571 + llgtr %r3,%r3 # char *
572 + llgfr %r4,%r4 # size_t
575 + .globl sys32_flistxattr_wrapper
576 +sys32_flistxattr_wrapper:
578 + llgtr %r3,%r3 # char *
579 + llgfr %r4,%r4 # size_t
582 + .globl sys32_removexattr_wrapper
583 +sys32_removexattr_wrapper:
584 + llgtr %r2,%r2 # char *
585 + llgtr %r3,%r3 # char *
588 + .globl sys32_lremovexattr_wrapper
589 +sys32_lremovexattr_wrapper:
590 + llgtr %r2,%r2 # char *
591 + llgtr %r3,%r3 # char *
592 + jg sys_lremovexattr
594 + .globl sys32_fremovexattr_wrapper
595 +sys32_fremovexattr_wrapper:
597 + llgtr %r3,%r3 # char *
598 + jg sys_fremovexattr
601 Index: linux-2.4.19-pre1/arch/sparc/defconfig
602 ===================================================================
603 --- linux-2.4.19-pre1.orig/arch/sparc/defconfig 2004-01-14 01:10:36.000000000 +0300
604 +++ linux-2.4.19-pre1/arch/sparc/defconfig 2004-01-14 01:11:49.000000000 +0300
607 # Automatically generated make config: don't edit
609 +CONFIG_EXT3_FS_XATTR=y
610 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
611 +# CONFIG_EXT3_FS_XATTR_USER is not set
612 +# CONFIG_EXT2_FS_XATTR is not set
613 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
614 +# CONFIG_EXT2_FS_XATTR_USER is not set
615 +# CONFIG_FS_MBCACHE is not set
619 Index: linux-2.4.19-pre1/arch/sparc/kernel/systbls.S
620 ===================================================================
621 --- linux-2.4.19-pre1.orig/arch/sparc/kernel/systbls.S 2001-10-21 21:36:54.000000000 +0400
622 +++ linux-2.4.19-pre1/arch/sparc/kernel/systbls.S 2004-01-14 01:11:49.000000000 +0300
624 /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
625 /*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
626 /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
627 -/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
628 -/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
629 -/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
630 -/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
631 -/*185*/ .long sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
632 +/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
633 +/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
634 +/*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
635 +/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
636 +/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
637 /*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
638 /*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
639 /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
640 Index: linux-2.4.19-pre1/arch/sparc64/defconfig
641 ===================================================================
642 --- linux-2.4.19-pre1.orig/arch/sparc64/defconfig 2004-01-14 01:10:36.000000000 +0300
643 +++ linux-2.4.19-pre1/arch/sparc64/defconfig 2004-01-14 01:11:49.000000000 +0300
646 # Automatically generated make config: don't edit
648 +CONFIG_EXT3_FS_XATTR=y
649 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
650 +# CONFIG_EXT3_FS_XATTR_USER is not set
651 +# CONFIG_EXT2_FS_XATTR is not set
652 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
653 +# CONFIG_EXT2_FS_XATTR_USER is not set
654 +# CONFIG_FS_MBCACHE is not set
657 # Code maturity level options
658 Index: linux-2.4.19-pre1/arch/sparc64/kernel/systbls.S
659 ===================================================================
660 --- linux-2.4.19-pre1.orig/arch/sparc64/kernel/systbls.S 2001-10-21 21:36:54.000000000 +0400
661 +++ linux-2.4.19-pre1/arch/sparc64/kernel/systbls.S 2004-01-14 01:11:49.000000000 +0300
663 /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
664 .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
665 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
666 - .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
667 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
668 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
669 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
670 - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
671 + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
672 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
673 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
674 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
675 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
676 /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
677 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
678 /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
679 @@ -111,11 +111,11 @@
680 /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
681 .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
682 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
683 - .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
684 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
685 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
686 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
687 - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
688 + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
689 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
690 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
691 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
692 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
693 /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
694 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
695 /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
696 Index: linux-2.4.19-pre1/fs/Config.in
697 ===================================================================
698 --- linux-2.4.19-pre1.orig/fs/Config.in 2004-01-14 01:10:37.000000000 +0300
699 +++ linux-2.4.19-pre1/fs/Config.in 2004-01-14 01:11:49.000000000 +0300
701 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
703 tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS
704 +dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
705 +dep_bool ' Ext3 extended attribute block sharing' \
706 + CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
707 +dep_bool ' Ext3 extended user attributes' \
708 + CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
709 # CONFIG_JBD could be its own option (even modular), but until there are
710 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
711 # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
713 tristate 'ROM file system support' CONFIG_ROMFS_FS
715 tristate 'Second extended fs support' CONFIG_EXT2_FS
716 +dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
717 +dep_bool ' Ext2 extended attribute block sharing' \
718 + CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
719 +dep_bool ' Ext2 extended user attributes' \
720 + CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
722 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
728 +# Meta block cache for Extended Attributes (ext2/ext3)
729 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
730 +define_tristate CONFIG_FS_MBCACHE y
732 mainmenu_option next_comment
733 comment 'Partition Types'
734 source fs/partitions/Config.in
735 Index: linux-2.4.19-pre1/fs/Makefile
736 ===================================================================
737 --- linux-2.4.19-pre1.orig/fs/Makefile 2004-01-14 01:11:49.000000000 +0300
738 +++ linux-2.4.19-pre1/fs/Makefile 2004-01-14 01:11:49.000000000 +0300
740 super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
741 fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
742 dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
743 - filesystems.o namespace.o seq_file.o
744 + filesystems.o namespace.o seq_file.o xattr.o
746 ifeq ($(CONFIG_QUOTA),y)
750 obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
752 +export-objs += mbcache.o
753 +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
755 # persistent filesystems
756 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
758 Index: linux-2.4.19-pre1/fs/ext2/Makefile
759 ===================================================================
760 --- linux-2.4.19-pre1.orig/fs/ext2/Makefile 2001-10-11 19:05:18.000000000 +0400
761 +++ linux-2.4.19-pre1/fs/ext2/Makefile 2004-01-14 01:11:49.000000000 +0300
763 ioctl.o namei.o super.o symlink.o
766 +export-objs += xattr.o
767 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
768 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
770 include $(TOPDIR)/Rules.make
771 Index: linux-2.4.19-pre1/fs/ext2/file.c
772 ===================================================================
773 --- linux-2.4.19-pre1.orig/fs/ext2/file.c 2001-10-11 19:05:18.000000000 +0400
774 +++ linux-2.4.19-pre1/fs/ext2/file.c 2004-01-14 01:11:49.000000000 +0300
777 #include <linux/fs.h>
778 #include <linux/ext2_fs.h>
779 +#include <linux/ext2_xattr.h>
780 #include <linux/sched.h>
785 struct inode_operations ext2_file_inode_operations = {
786 truncate: ext2_truncate,
787 + setxattr: ext2_setxattr,
788 + getxattr: ext2_getxattr,
789 + listxattr: ext2_listxattr,
790 + removexattr: ext2_removexattr,
792 Index: linux-2.4.19-pre1/fs/ext2/ialloc.c
793 ===================================================================
794 --- linux-2.4.19-pre1.orig/fs/ext2/ialloc.c 2004-01-14 01:10:37.000000000 +0300
795 +++ linux-2.4.19-pre1/fs/ext2/ialloc.c 2004-01-14 01:11:49.000000000 +0300
797 #include <linux/config.h>
798 #include <linux/fs.h>
799 #include <linux/ext2_fs.h>
800 +#include <linux/ext2_xattr.h>
801 #include <linux/locks.h>
802 #include <linux/quotaops.h>
806 if (!is_bad_inode(inode)) {
807 /* Quota is already initialized in iput() */
808 + ext2_xattr_delete_inode(inode);
809 DQUOT_FREE_INODE(inode);
812 Index: linux-2.4.19-pre1/fs/ext2/inode.c
813 ===================================================================
814 --- linux-2.4.19-pre1.orig/fs/ext2/inode.c 2004-01-14 01:10:37.000000000 +0300
815 +++ linux-2.4.19-pre1/fs/ext2/inode.c 2004-01-14 01:11:49.000000000 +0300
817 static int ext2_update_inode(struct inode * inode, int do_sync);
820 + * Test whether an inode is a fast symlink.
822 +static inline int ext2_inode_is_fast_symlink(struct inode *inode)
824 + int ea_blocks = inode->u.ext2_i.i_file_acl ?
825 + (inode->i_sb->s_blocksize >> 9) : 0;
827 + return (S_ISLNK(inode->i_mode) &&
828 + inode->i_blocks - ea_blocks == 0);
832 * Called at each iput()
834 void ext2_put_inode (struct inode * inode)
839 - if (is_bad_inode(inode) ||
840 - inode->i_ino == EXT2_ACL_IDX_INO ||
841 - inode->i_ino == EXT2_ACL_DATA_INO)
842 + if (is_bad_inode(inode))
844 inode->u.ext2_i.i_dtime = CURRENT_TIME;
845 mark_inode_dirty(inode);
847 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
848 S_ISLNK(inode->i_mode)))
850 + if (ext2_inode_is_fast_symlink(inode))
852 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
856 unsigned long offset;
857 struct ext2_group_desc * gdp;
859 - if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
860 - inode->i_ino != EXT2_ACL_DATA_INO &&
861 + if ((inode->i_ino != EXT2_ROOT_INO &&
862 inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
863 inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
864 ext2_error (inode->i_sb, "ext2_read_inode",
866 for (block = 0; block < EXT2_N_BLOCKS; block++)
867 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
869 - if (inode->i_ino == EXT2_ACL_IDX_INO ||
870 - inode->i_ino == EXT2_ACL_DATA_INO)
871 - /* Nothing to do */ ;
872 - else if (S_ISREG(inode->i_mode)) {
873 + if (S_ISREG(inode->i_mode)) {
874 inode->i_op = &ext2_file_inode_operations;
875 inode->i_fop = &ext2_file_operations;
876 inode->i_mapping->a_ops = &ext2_aops;
877 @@ -987,15 +995,17 @@
878 inode->i_fop = &ext2_dir_operations;
879 inode->i_mapping->a_ops = &ext2_aops;
880 } else if (S_ISLNK(inode->i_mode)) {
881 - if (!inode->i_blocks)
882 + if (ext2_inode_is_fast_symlink(inode))
883 inode->i_op = &ext2_fast_symlink_inode_operations;
885 - inode->i_op = &page_symlink_inode_operations;
886 + inode->i_op = &ext2_symlink_inode_operations;
887 inode->i_mapping->a_ops = &ext2_aops;
891 + inode->i_op = &ext2_special_inode_operations;
892 init_special_inode(inode, inode->i_mode,
893 le32_to_cpu(raw_inode->i_block[0]));
896 inode->i_attr_flags = 0;
897 if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
898 Index: linux-2.4.19-pre1/fs/ext2/namei.c
899 ===================================================================
900 --- linux-2.4.19-pre1.orig/fs/ext2/namei.c 2001-10-04 09:57:36.000000000 +0400
901 +++ linux-2.4.19-pre1/fs/ext2/namei.c 2004-01-14 01:11:49.000000000 +0300
904 #include <linux/fs.h>
905 #include <linux/ext2_fs.h>
906 +#include <linux/ext2_xattr.h>
907 #include <linux/pagemap.h>
912 if (l > sizeof (inode->u.ext2_i.i_data)) {
914 - inode->i_op = &page_symlink_inode_operations;
915 + inode->i_op = &ext2_symlink_inode_operations;
916 inode->i_mapping->a_ops = &ext2_aops;
917 err = block_symlink(inode, symname, l);
923 + setxattr: ext2_setxattr,
924 + getxattr: ext2_getxattr,
925 + listxattr: ext2_listxattr,
926 + removexattr: ext2_removexattr,
929 +struct inode_operations ext2_special_inode_operations = {
930 + setxattr: ext2_setxattr,
931 + getxattr: ext2_getxattr,
932 + listxattr: ext2_listxattr,
933 + removexattr: ext2_removexattr,
935 Index: linux-2.4.19-pre1/fs/ext2/super.c
936 ===================================================================
937 --- linux-2.4.19-pre1.orig/fs/ext2/super.c 2004-01-14 01:10:37.000000000 +0300
938 +++ linux-2.4.19-pre1/fs/ext2/super.c 2004-01-14 01:11:49.000000000 +0300
940 #include <linux/string.h>
941 #include <linux/fs.h>
942 #include <linux/ext2_fs.h>
943 +#include <linux/ext2_xattr.h>
944 #include <linux/slab.h>
945 #include <linux/init.h>
946 #include <linux/locks.h>
951 + ext2_xattr_put_super(sb);
952 if (!(sb->s_flags & MS_RDONLY)) {
953 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
956 this_char = strtok (NULL, ",")) {
957 if ((value = strchr (this_char, '=')) != NULL)
959 +#ifdef CONFIG_EXT2_FS_XATTR_USER
960 + if (!strcmp (this_char, "user_xattr"))
961 + set_opt (*mount_options, XATTR_USER);
962 + else if (!strcmp (this_char, "nouser_xattr"))
963 + clear_opt (*mount_options, XATTR_USER);
966 if (!strcmp (this_char, "bsddf"))
967 clear_opt (*mount_options, MINIX_DF);
968 else if (!strcmp (this_char, "nouid32")) {
970 blocksize = BLOCK_SIZE;
972 sb->u.ext2_sb.s_mount_opt = 0;
973 +#ifdef CONFIG_EXT2_FS_XATTR_USER
974 + /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
976 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
977 &sb->u.ext2_sb.s_mount_opt)) {
979 @@ -810,12 +822,27 @@
981 static int __init init_ext2_fs(void)
983 - return register_filesystem(&ext2_fs_type);
984 + int error = init_ext2_xattr();
987 + error = init_ext2_xattr_user();
990 + error = register_filesystem(&ext2_fs_type);
994 + exit_ext2_xattr_user();
1000 static void __exit exit_ext2_fs(void)
1002 unregister_filesystem(&ext2_fs_type);
1003 + exit_ext2_xattr_user();
1004 + exit_ext2_xattr();
1008 Index: linux-2.4.19-pre1/fs/ext2/symlink.c
1009 ===================================================================
1010 --- linux-2.4.19-pre1.orig/fs/ext2/symlink.c 2000-09-28 00:41:33.000000000 +0400
1011 +++ linux-2.4.19-pre1/fs/ext2/symlink.c 2004-01-14 01:11:49.000000000 +0300
1014 #include <linux/fs.h>
1015 #include <linux/ext2_fs.h>
1016 +#include <linux/ext2_xattr.h>
1018 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
1021 return vfs_follow_link(nd, s);
1024 +struct inode_operations ext2_symlink_inode_operations = {
1025 + readlink: page_readlink,
1026 + follow_link: page_follow_link,
1027 + setxattr: ext2_setxattr,
1028 + getxattr: ext2_getxattr,
1029 + listxattr: ext2_listxattr,
1030 + removexattr: ext2_removexattr,
1033 struct inode_operations ext2_fast_symlink_inode_operations = {
1034 readlink: ext2_readlink,
1035 follow_link: ext2_follow_link,
1036 + setxattr: ext2_setxattr,
1037 + getxattr: ext2_getxattr,
1038 + listxattr: ext2_listxattr,
1039 + removexattr: ext2_removexattr,
1041 Index: linux-2.4.19-pre1/fs/ext2/xattr.c
1042 ===================================================================
1043 --- linux-2.4.19-pre1.orig/fs/ext2/xattr.c 2003-01-30 13:24:37.000000000 +0300
1044 +++ linux-2.4.19-pre1/fs/ext2/xattr.c 2004-01-14 01:11:49.000000000 +0300
1047 + * linux/fs/ext2/xattr.c
1049 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
1051 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
1052 + * Extended attributes for symlinks and special files added per
1053 + * suggestion of Luka Renko <luka.renko@hermes.si>.
1057 + * Extended attributes are stored on disk blocks allocated outside of
1058 + * any inode. The i_file_acl field is then made to point to this allocated
1059 + * block. If all extended attributes of an inode are identical, these
1060 + * inodes may share the same extended attribute block. Such situations
1061 + * are automatically detected by keeping a cache of recent attribute block
1062 + * numbers and hashes over the block's contents in memory.
1065 + * Extended attribute block layout:
1067 + * +------------------+
1070 + * | entry 2 | | growing downwards
1072 + * | four null bytes |
1075 + * | value 3 | | growing upwards
1077 + * +------------------+
1079 + * The block header is followed by multiple entry descriptors. These entry
1080 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
1081 + * byte boundaries. The entry descriptors are sorted by attribute name,
1082 + * so that two extended attribute blocks can be compared efficiently.
1084 + * Attribute values are aligned to the end of the block, stored in
1085 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
1086 + * boundaries. No additional gaps are left between them.
1088 + * Locking strategy
1089 + * ----------------
1090 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
1091 + * the xattr inode operations are called, so we are guaranteed that only one
1092 + * processes accesses extended attributes of an inode at any time.
1094 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
1095 + * only a single process is modifying an extended attribute block, even
1096 + * if the block is shared among inodes.
1098 + * Note for porting to 2.5
1099 + * -----------------------
1100 + * The BKL will no longer be held in the xattr inode operations.
1103 +#include <linux/module.h>
1104 +#include <linux/locks.h>
1105 +#include <linux/slab.h>
1106 +#include <linux/fs.h>
1107 +#include <linux/ext2_fs.h>
1108 +#include <linux/ext2_xattr.h>
1109 +#include <linux/mbcache.h>
1110 +#include <linux/quotaops.h>
1111 +#include <asm/semaphore.h>
1112 +#include <linux/compatmac.h>
1114 +/* These symbols may be needed by a module. */
1115 +EXPORT_SYMBOL(ext2_xattr_register);
1116 +EXPORT_SYMBOL(ext2_xattr_unregister);
1117 +EXPORT_SYMBOL(ext2_xattr_get);
1118 +EXPORT_SYMBOL(ext2_xattr_list);
1119 +EXPORT_SYMBOL(ext2_xattr_set);
1121 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1122 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
1125 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
1126 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
1127 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
1128 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
1130 +#ifdef EXT2_XATTR_DEBUG
1131 +# define ea_idebug(inode, f...) do { \
1132 + printk(KERN_DEBUG "inode %s:%ld: ", \
1133 + kdevname(inode->i_dev), inode->i_ino); \
1137 +# define ea_bdebug(bh, f...) do { \
1138 + printk(KERN_DEBUG "block %s:%ld: ", \
1139 + kdevname(bh->b_dev), bh->b_blocknr); \
1144 +# define ea_idebug(f...)
1145 +# define ea_bdebug(f...)
1148 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
1149 + struct ext2_xattr_header *);
1151 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1153 +static int ext2_xattr_cache_insert(struct buffer_head *);
1154 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
1155 + struct ext2_xattr_header *);
1156 +static void ext2_xattr_cache_remove(struct buffer_head *);
1157 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
1158 + struct ext2_xattr_entry *);
1160 +static struct mb_cache *ext2_xattr_cache;
1163 +# define ext2_xattr_cache_insert(bh) 0
1164 +# define ext2_xattr_cache_find(inode, header) NULL
1165 +# define ext2_xattr_cache_remove(bh) while(0) {}
1166 +# define ext2_xattr_rehash(header, entry) while(0) {}
1170 + * If a file system does not share extended attributes among inodes,
1171 + * we should not need the ext2_xattr_sem semaphore. However, the
1172 + * filesystem may still contain shared blocks, so we always take
1176 +DECLARE_MUTEX(ext2_xattr_sem);
1179 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
1181 + struct super_block *sb = inode->i_sb;
1182 + int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
1183 + EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
1185 + /* How can we enforce the allocation? */
1186 + int block = ext2_new_block(inode, goal, 0, 0, errp);
1189 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1195 +ext2_xattr_quota_alloc(struct inode *inode, int force)
1197 + /* How can we enforce the allocation? */
1199 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
1201 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1203 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
1211 +ext2_xattr_quota_free(struct inode *inode)
1213 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
1214 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1218 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
1220 + ext2_free_blocks(inode, block, 1);
1221 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1225 +# define ext2_xattr_quota_free(inode) \
1226 + DQUOT_FREE_BLOCK(inode, 1)
1227 +# define ext2_xattr_free_block(inode, block) \
1228 + ext2_free_blocks(inode, block, 1)
1231 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1233 +static inline struct buffer_head *
1234 +sb_bread(struct super_block *sb, int block)
1236 + return bread(sb->s_dev, block, sb->s_blocksize);
1239 +static inline struct buffer_head *
1240 +sb_getblk(struct super_block *sb, int block)
1242 + return getblk(sb->s_dev, block, sb->s_blocksize);
1247 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1248 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1251 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1253 + int error = -EINVAL;
1255 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1256 + write_lock(&ext2_handler_lock);
1257 + if (!ext2_xattr_handlers[name_index-1]) {
1258 + ext2_xattr_handlers[name_index-1] = handler;
1261 + write_unlock(&ext2_handler_lock);
1267 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1269 + if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
1270 + write_lock(&ext2_handler_lock);
1271 + ext2_xattr_handlers[name_index-1] = NULL;
1272 + write_unlock(&ext2_handler_lock);
1276 +static inline const char *
1277 +strcmp_prefix(const char *a, const char *a_prefix)
1279 + while (*a_prefix && *a == *a_prefix) {
1283 + return *a_prefix ? NULL : a;
1287 + * Decode the extended attribute name, and translate it into
1288 + * the name_index and name suffix.
1290 +static struct ext2_xattr_handler *
1291 +ext2_xattr_resolve_name(const char **name)
1293 + struct ext2_xattr_handler *handler = NULL;
1298 + read_lock(&ext2_handler_lock);
1299 + for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1300 + if (ext2_xattr_handlers[i]) {
1301 + const char *n = strcmp_prefix(*name,
1302 + ext2_xattr_handlers[i]->prefix);
1304 + handler = ext2_xattr_handlers[i];
1310 + read_unlock(&ext2_handler_lock);
1314 +static inline struct ext2_xattr_handler *
1315 +ext2_xattr_handler(int name_index)
1317 + struct ext2_xattr_handler *handler = NULL;
1318 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1319 + read_lock(&ext2_handler_lock);
1320 + handler = ext2_xattr_handlers[name_index-1];
1321 + read_unlock(&ext2_handler_lock);
1327 + * Inode operation getxattr()
1329 + * dentry->d_inode->i_sem down
1330 + * BKL held [before 2.5.x]
1333 +ext2_getxattr(struct dentry *dentry, const char *name,
1334 + void *buffer, size_t size)
1336 + struct ext2_xattr_handler *handler;
1337 + struct inode *inode = dentry->d_inode;
1339 + handler = ext2_xattr_resolve_name(&name);
1342 + return handler->get(inode, name, buffer, size);
1346 + * Inode operation listxattr()
1348 + * dentry->d_inode->i_sem down
1349 + * BKL held [before 2.5.x]
1352 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1354 + return ext2_xattr_list(dentry->d_inode, buffer, size);
1358 + * Inode operation setxattr()
1360 + * dentry->d_inode->i_sem down
1361 + * BKL held [before 2.5.x]
1364 +ext2_setxattr(struct dentry *dentry, const char *name,
1365 + const void *value, size_t size, int flags)
1367 + struct ext2_xattr_handler *handler;
1368 + struct inode *inode = dentry->d_inode;
1371 + value = ""; /* empty EA, do not remove */
1372 + handler = ext2_xattr_resolve_name(&name);
1375 + return handler->set(inode, name, value, size, flags);
1379 + * Inode operation removexattr()
1381 + * dentry->d_inode->i_sem down
1382 + * BKL held [before 2.5.x]
1385 +ext2_removexattr(struct dentry *dentry, const char *name)
1387 + struct ext2_xattr_handler *handler;
1388 + struct inode *inode = dentry->d_inode;
1390 + handler = ext2_xattr_resolve_name(&name);
1393 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1397 + * ext2_xattr_get()
1399 + * Copy an extended attribute into the buffer
1400 + * provided, or compute the buffer size required.
1401 + * Buffer is NULL to compute the size of the buffer required.
1403 + * Returns a negative error number on failure, or the number of bytes
1404 + * used / required on success.
1407 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1408 + void *buffer, size_t buffer_size)
1410 + struct buffer_head *bh = NULL;
1411 + struct ext2_xattr_entry *entry;
1412 + unsigned int block, size;
1414 + int name_len, error;
1416 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1417 + name_index, name, buffer, (long)buffer_size);
1421 + if (!EXT2_I(inode)->i_file_acl)
1423 + block = EXT2_I(inode)->i_file_acl;
1424 + ea_idebug(inode, "reading block %d", block);
1425 + bh = sb_bread(inode->i_sb, block);
1428 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1429 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1430 + end = bh->b_data + bh->b_size;
1431 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1432 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1433 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
1434 + "inode %ld: bad block %d", inode->i_ino, block);
1438 + /* find named attribute */
1439 + name_len = strlen(name);
1442 + if (name_len > 255)
1444 + entry = FIRST_ENTRY(bh);
1445 + while (!IS_LAST_ENTRY(entry)) {
1446 + struct ext2_xattr_entry *next =
1447 + EXT2_XATTR_NEXT(entry);
1448 + if ((char *)next >= end)
1450 + if (name_index == entry->e_name_index &&
1451 + name_len == entry->e_name_len &&
1452 + memcmp(name, entry->e_name, name_len) == 0)
1456 + /* Check the remaining name entries */
1457 + while (!IS_LAST_ENTRY(entry)) {
1458 + struct ext2_xattr_entry *next =
1459 + EXT2_XATTR_NEXT(entry);
1460 + if ((char *)next >= end)
1464 + if (ext2_xattr_cache_insert(bh))
1465 + ea_idebug(inode, "cache insert failed");
1469 + /* check the buffer size */
1470 + if (entry->e_value_block != 0)
1472 + size = le32_to_cpu(entry->e_value_size);
1473 + if (size > inode->i_sb->s_blocksize ||
1474 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1477 + if (ext2_xattr_cache_insert(bh))
1478 + ea_idebug(inode, "cache insert failed");
1481 + if (size > buffer_size)
1483 + /* return value of attribute */
1484 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1496 + * ext2_xattr_list()
1498 + * Copy a list of attribute names into the buffer
1499 + * provided, or compute the buffer size required.
1500 + * Buffer is NULL to compute the size of the buffer required.
1502 + * Returns a negative error number on failure, or the number of bytes
1503 + * used / required on success.
1506 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1508 + struct buffer_head *bh = NULL;
1509 + struct ext2_xattr_entry *entry;
1510 + unsigned int block, size = 0;
1514 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1515 + buffer, (long)buffer_size);
1517 + if (!EXT2_I(inode)->i_file_acl)
1519 + block = EXT2_I(inode)->i_file_acl;
1520 + ea_idebug(inode, "reading block %d", block);
1521 + bh = sb_bread(inode->i_sb, block);
1524 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1525 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1526 + end = bh->b_data + bh->b_size;
1527 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1528 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1529 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
1530 + "inode %ld: bad block %d", inode->i_ino, block);
1534 + /* compute the size required for the list of attribute names */
1535 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1536 + entry = EXT2_XATTR_NEXT(entry)) {
1537 + struct ext2_xattr_handler *handler;
1538 + struct ext2_xattr_entry *next =
1539 + EXT2_XATTR_NEXT(entry);
1540 + if ((char *)next >= end)
1543 + handler = ext2_xattr_handler(entry->e_name_index);
1545 + size += handler->list(NULL, inode, entry->e_name,
1546 + entry->e_name_len);
1549 + if (ext2_xattr_cache_insert(bh))
1550 + ea_idebug(inode, "cache insert failed");
1556 + if (size > buffer_size)
1560 + /* list the attribute names */
1562 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1563 + entry = EXT2_XATTR_NEXT(entry)) {
1564 + struct ext2_xattr_handler *handler;
1566 + handler = ext2_xattr_handler(entry->e_name_index);
1568 + buf += handler->list(buf, inode, entry->e_name,
1569 + entry->e_name_len);
1580 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1581 + * not set, set it.
1583 +static void ext2_xattr_update_super_block(struct super_block *sb)
1585 + if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1589 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1590 + EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1592 + EXT2_SB(sb)->s_es->s_feature_compat |=
1593 + cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1595 + mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1600 + * ext2_xattr_set()
1602 + * Create, replace or remove an extended attribute for this inode. Buffer
1603 + * is NULL to remove an existing extended attribute, and non-NULL to
1604 + * either replace an existing extended attribute, or create a new extended
1605 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1606 + * specify that an extended attribute must exist and must not exist
1607 + * previous to the call, respectively.
1609 + * Returns 0, or a negative error number on failure.
1612 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1613 + const void *value, size_t value_len, int flags)
1615 + struct super_block *sb = inode->i_sb;
1616 + struct buffer_head *bh = NULL;
1617 + struct ext2_xattr_header *header = NULL;
1618 + struct ext2_xattr_entry *here, *last;
1619 + unsigned int name_len;
1620 + int block = EXT2_I(inode)->i_file_acl;
1621 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
1625 + * header -- Points either into bh, or to a temporarily
1626 + * allocated buffer.
1627 + * here -- The named entry found, or the place for inserting, within
1628 + * the block pointed to by header.
1629 + * last -- Points right after the last named entry within the block
1630 + * pointed to by header.
1631 + * min_offs -- The offset of the first value (values are aligned
1632 + * towards the end of the block).
1633 + * end -- Points right after the block pointed to by header.
1636 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1637 + name_index, name, value, (long)value_len);
1639 + if (IS_RDONLY(inode))
1641 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1643 + if (value == NULL)
1647 + name_len = strlen(name);
1648 + if (name_len > 255 || value_len > sb->s_blocksize)
1650 + down(&ext2_xattr_sem);
1653 + /* The inode already has an extended attribute block. */
1655 + bh = sb_bread(sb, block);
1659 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1660 + atomic_read(&(bh->b_count)),
1661 + le32_to_cpu(HDR(bh)->h_refcount));
1663 + end = bh->b_data + bh->b_size;
1664 + if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1665 + header->h_blocks != cpu_to_le32(1)) {
1666 +bad_block: ext2_error(sb, "ext2_xattr_set",
1667 + "inode %ld: bad block %d", inode->i_ino, block);
1671 + /* Find the named attribute. */
1672 + here = FIRST_ENTRY(bh);
1673 + while (!IS_LAST_ENTRY(here)) {
1674 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1675 + if ((char *)next >= end)
1677 + if (!here->e_value_block && here->e_value_size) {
1678 + int offs = le16_to_cpu(here->e_value_offs);
1679 + if (offs < min_offs)
1682 + not_found = name_index - here->e_name_index;
1684 + not_found = name_len - here->e_name_len;
1686 + not_found = memcmp(name, here->e_name,name_len);
1687 + if (not_found <= 0)
1692 + /* We still need to compute min_offs and last. */
1693 + while (!IS_LAST_ENTRY(last)) {
1694 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1695 + if ((char *)next >= end)
1697 + if (!last->e_value_block && last->e_value_size) {
1698 + int offs = le16_to_cpu(last->e_value_offs);
1699 + if (offs < min_offs)
1705 + /* Check whether we have enough space left. */
1706 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1708 + /* We will use a new extended attribute block. */
1709 + free = sb->s_blocksize -
1710 + sizeof(struct ext2_xattr_header) - sizeof(__u32);
1711 + here = last = NULL; /* avoid gcc uninitialized warning. */
1715 + /* Request to remove a nonexistent attribute? */
1717 + if (flags & XATTR_REPLACE)
1720 + if (value == NULL)
1723 + free -= EXT2_XATTR_LEN(name_len);
1725 + /* Request to create an existing attribute? */
1727 + if (flags & XATTR_CREATE)
1729 + if (!here->e_value_block && here->e_value_size) {
1730 + unsigned int size = le32_to_cpu(here->e_value_size);
1732 + if (le16_to_cpu(here->e_value_offs) + size >
1733 + sb->s_blocksize || size > sb->s_blocksize)
1735 + free += EXT2_XATTR_SIZE(size);
1738 + free -= EXT2_XATTR_SIZE(value_len);
1743 + /* Here we know that we can set the new attribute. */
1746 + if (header->h_refcount == cpu_to_le32(1)) {
1747 + ea_bdebug(bh, "modifying in-place");
1748 + ext2_xattr_cache_remove(bh);
1752 + ea_bdebug(bh, "cloning");
1753 + header = kmalloc(bh->b_size, GFP_KERNEL);
1755 + if (header == NULL)
1757 + memcpy(header, HDR(bh), bh->b_size);
1758 + header->h_refcount = cpu_to_le32(1);
1759 + offset = (char *)header - bh->b_data;
1760 + here = ENTRY((char *)here + offset);
1761 + last = ENTRY((char *)last + offset);
1764 + /* Allocate a buffer where we construct the new block. */
1765 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1767 + if (header == NULL)
1769 + memset(header, 0, sb->s_blocksize);
1770 + end = (char *)header + sb->s_blocksize;
1771 + header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1772 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
1773 + last = here = ENTRY(header+1);
1777 + /* Insert the new name. */
1778 + int size = EXT2_XATTR_LEN(name_len);
1779 + int rest = (char *)last - (char *)here;
1780 + memmove((char *)here + size, here, rest);
1781 + memset(here, 0, size);
1782 + here->e_name_index = name_index;
1783 + here->e_name_len = name_len;
1784 + memcpy(here->e_name, name, name_len);
1786 + /* Remove the old value. */
1787 + if (!here->e_value_block && here->e_value_size) {
1788 + char *first_val = (char *)header + min_offs;
1789 + int offs = le16_to_cpu(here->e_value_offs);
1790 + char *val = (char *)header + offs;
1791 + size_t size = EXT2_XATTR_SIZE(
1792 + le32_to_cpu(here->e_value_size));
1793 + memmove(first_val + size, first_val, val - first_val);
1794 + memset(first_val, 0, size);
1795 + here->e_value_offs = 0;
1798 + /* Adjust all value offsets. */
1799 + last = ENTRY(header+1);
1800 + while (!IS_LAST_ENTRY(last)) {
1801 + int o = le16_to_cpu(last->e_value_offs);
1802 + if (!last->e_value_block && o < offs)
1803 + last->e_value_offs =
1804 + cpu_to_le16(o + size);
1805 + last = EXT2_XATTR_NEXT(last);
1808 + if (value == NULL) {
1809 + /* Remove this attribute. */
1810 + if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1811 + /* This block is now empty. */
1812 + error = ext2_xattr_set2(inode, bh, NULL);
1815 + /* Remove the old name. */
1816 + int size = EXT2_XATTR_LEN(name_len);
1817 + last = ENTRY((char *)last - size);
1818 + memmove(here, (char*)here + size,
1819 + (char*)last - (char*)here);
1820 + memset(last, 0, size);
1825 + if (value != NULL) {
1826 + /* Insert the new value. */
1827 + here->e_value_size = cpu_to_le32(value_len);
1829 + size_t size = EXT2_XATTR_SIZE(value_len);
1830 + char *val = (char *)header + min_offs - size;
1831 + here->e_value_offs =
1832 + cpu_to_le16((char *)val - (char *)header);
1833 + memset(val + size - EXT2_XATTR_PAD, 0,
1834 + EXT2_XATTR_PAD); /* Clear the pad bytes. */
1835 + memcpy(val, value, value_len);
1838 + ext2_xattr_rehash(header, here);
1840 + error = ext2_xattr_set2(inode, bh, header);
1844 + if (!(bh && header == HDR(bh)))
1846 + up(&ext2_xattr_sem);
1852 + * Second half of ext2_xattr_set(): Update the file system.
1855 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1856 + struct ext2_xattr_header *header)
1858 + struct super_block *sb = inode->i_sb;
1859 + struct buffer_head *new_bh = NULL;
1863 + new_bh = ext2_xattr_cache_find(inode, header);
1866 + * We found an identical block in the cache.
1867 + * The old block will be released after updating
1870 + ea_bdebug(old_bh, "reusing block %ld",
1871 + new_bh->b_blocknr);
1874 + if (ext2_xattr_quota_alloc(inode, 1))
1877 + HDR(new_bh)->h_refcount = cpu_to_le32(
1878 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1879 + ea_bdebug(new_bh, "refcount now=%d",
1880 + le32_to_cpu(HDR(new_bh)->h_refcount));
1881 + } else if (old_bh && header == HDR(old_bh)) {
1882 + /* Keep this block. */
1884 + (void)ext2_xattr_cache_insert(new_bh);
1886 + /* We need to allocate a new block */
1887 + int force = EXT2_I(inode)->i_file_acl != 0;
1888 + int block = ext2_xattr_new_block(inode, &error, force);
1891 + ea_idebug(inode, "creating block %d", block);
1893 + new_bh = sb_getblk(sb, block);
1895 + ext2_xattr_free_block(inode, block);
1899 + lock_buffer(new_bh);
1900 + memcpy(new_bh->b_data, header, new_bh->b_size);
1901 + mark_buffer_uptodate(new_bh, 1);
1902 + unlock_buffer(new_bh);
1903 + (void)ext2_xattr_cache_insert(new_bh);
1905 + ext2_xattr_update_super_block(sb);
1907 + mark_buffer_dirty(new_bh);
1908 + if (IS_SYNC(inode)) {
1909 + ll_rw_block(WRITE, 1, &new_bh);
1910 + wait_on_buffer(new_bh);
1912 + if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1917 + /* Update the inode. */
1918 + EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1919 + inode->i_ctime = CURRENT_TIME;
1920 + if (IS_SYNC(inode)) {
1921 + error = ext2_sync_inode (inode);
1925 + mark_inode_dirty(inode);
1928 + if (old_bh && old_bh != new_bh) {
1930 + * If there was an old block, and we are not still using it,
1931 + * we now release the old block.
1933 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1935 + if (refcount == 1) {
1936 + /* Free the old block. */
1937 + ea_bdebug(old_bh, "freeing");
1938 + ext2_xattr_free_block(inode, old_bh->b_blocknr);
1939 + mark_buffer_clean(old_bh);
1941 + /* Decrement the refcount only. */
1943 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1944 + ext2_xattr_quota_free(inode);
1945 + mark_buffer_dirty(old_bh);
1946 + ea_bdebug(old_bh, "refcount now=%d", refcount);
1951 + if (old_bh != new_bh)
1958 + * ext2_xattr_delete_inode()
1960 + * Free extended attribute resources associated with this inode. This
1961 + * is called immediately before an inode is freed.
1964 +ext2_xattr_delete_inode(struct inode *inode)
1966 + struct buffer_head *bh;
1967 + unsigned int block = EXT2_I(inode)->i_file_acl;
1971 + down(&ext2_xattr_sem);
1973 + bh = sb_bread(inode->i_sb, block);
1975 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1976 + "inode %ld: block %d read error", inode->i_ino, block);
1979 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1980 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1981 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1982 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1983 + "inode %ld: bad block %d", inode->i_ino, block);
1986 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1987 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1988 + ext2_xattr_cache_remove(bh);
1989 + ext2_xattr_free_block(inode, block);
1993 + HDR(bh)->h_refcount = cpu_to_le32(
1994 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
1995 + mark_buffer_dirty(bh);
1996 + if (IS_SYNC(inode)) {
1997 + ll_rw_block(WRITE, 1, &bh);
1998 + wait_on_buffer(bh);
2000 + ext2_xattr_quota_free(inode);
2002 + EXT2_I(inode)->i_file_acl = 0;
2006 + up(&ext2_xattr_sem);
2010 + * ext2_xattr_put_super()
2012 + * This is called when a file system is unmounted.
2015 +ext2_xattr_put_super(struct super_block *sb)
2017 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
2018 + mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
2022 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
2025 + * ext2_xattr_cache_insert()
2027 + * Create a new entry in the extended attribute cache, and insert
2028 + * it unless such an entry is already in the cache.
2030 + * Returns 0, or a negative error number on failure.
2033 +ext2_xattr_cache_insert(struct buffer_head *bh)
2035 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
2036 + struct mb_cache_entry *ce;
2039 + ce = mb_cache_entry_alloc(ext2_xattr_cache);
2042 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
2044 + mb_cache_entry_free(ce);
2045 + if (error == -EBUSY) {
2046 + ea_bdebug(bh, "already in cache (%d cache entries)",
2047 + atomic_read(&ext2_xattr_cache->c_entry_count));
2051 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
2052 + atomic_read(&ext2_xattr_cache->c_entry_count));
2053 + mb_cache_entry_release(ce);
2059 + * ext2_xattr_cmp()
2061 + * Compare two extended attribute blocks for equality.
2063 + * Returns 0 if the blocks are equal, 1 if they differ, and
2064 + * a negative error number on errors.
2067 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
2068 + struct ext2_xattr_header *header2)
2070 + struct ext2_xattr_entry *entry1, *entry2;
2072 + entry1 = ENTRY(header1+1);
2073 + entry2 = ENTRY(header2+1);
2074 + while (!IS_LAST_ENTRY(entry1)) {
2075 + if (IS_LAST_ENTRY(entry2))
2077 + if (entry1->e_hash != entry2->e_hash ||
2078 + entry1->e_name_len != entry2->e_name_len ||
2079 + entry1->e_value_size != entry2->e_value_size ||
2080 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
2082 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
2084 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
2085 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
2086 + le32_to_cpu(entry1->e_value_size)))
2089 + entry1 = EXT2_XATTR_NEXT(entry1);
2090 + entry2 = EXT2_XATTR_NEXT(entry2);
2092 + if (!IS_LAST_ENTRY(entry2))
2098 + * ext2_xattr_cache_find()
2100 + * Find an identical extended attribute block.
2102 + * Returns a pointer to the block found, or NULL if such a block was
2103 + * not found or an error occurred.
2105 +static struct buffer_head *
2106 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
2108 + __u32 hash = le32_to_cpu(header->h_hash);
2109 + struct mb_cache_entry *ce;
2111 + if (!header->h_hash)
2112 + return NULL; /* never share */
2113 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
2114 + ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
2116 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
2119 + ext2_error(inode->i_sb, "ext2_xattr_cache_find",
2120 + "inode %ld: block %ld read error",
2121 + inode->i_ino, ce->e_block);
2122 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
2123 + EXT2_XATTR_REFCOUNT_MAX) {
2124 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
2125 + le32_to_cpu(HDR(bh)->h_refcount),
2126 + EXT2_XATTR_REFCOUNT_MAX);
2127 + } else if (!ext2_xattr_cmp(header, HDR(bh))) {
2128 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
2129 + mb_cache_entry_release(ce);
2133 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
2139 + * ext2_xattr_cache_remove()
2141 + * Remove the cache entry of a block from the cache. Called when a
2142 + * block becomes invalid.
2145 +ext2_xattr_cache_remove(struct buffer_head *bh)
2147 + struct mb_cache_entry *ce;
2149 + ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
2151 + ea_bdebug(bh, "removing (%d cache entries remaining)",
2152 + atomic_read(&ext2_xattr_cache->c_entry_count)-1);
2153 + mb_cache_entry_free(ce);
2155 + ea_bdebug(bh, "no cache entry");
2158 +#define NAME_HASH_SHIFT 5
2159 +#define VALUE_HASH_SHIFT 16
2162 + * ext2_xattr_hash_entry()
2164 + * Compute the hash of an extended attribute.
2166 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
2167 + struct ext2_xattr_entry *entry)
2170 + char *name = entry->e_name;
2173 + for (n=0; n < entry->e_name_len; n++) {
2174 + hash = (hash << NAME_HASH_SHIFT) ^
2175 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
2179 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
2180 + __u32 *value = (__u32 *)((char *)header +
2181 + le16_to_cpu(entry->e_value_offs));
2182 + for (n = (le32_to_cpu(entry->e_value_size) +
2183 + EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
2184 + hash = (hash << VALUE_HASH_SHIFT) ^
2185 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
2186 + le32_to_cpu(*value++);
2189 + entry->e_hash = cpu_to_le32(hash);
2192 +#undef NAME_HASH_SHIFT
2193 +#undef VALUE_HASH_SHIFT
2195 +#define BLOCK_HASH_SHIFT 16
2198 + * ext2_xattr_rehash()
2200 + * Re-compute the extended attribute hash value after an entry has changed.
2202 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
2203 + struct ext2_xattr_entry *entry)
2205 + struct ext2_xattr_entry *here;
2208 + ext2_xattr_hash_entry(header, entry);
2209 + here = ENTRY(header+1);
2210 + while (!IS_LAST_ENTRY(here)) {
2211 + if (!here->e_hash) {
2212 + /* Block is not shared if an entry's hash value == 0 */
2216 + hash = (hash << BLOCK_HASH_SHIFT) ^
2217 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
2218 + le32_to_cpu(here->e_hash);
2219 + here = EXT2_XATTR_NEXT(here);
2221 + header->h_hash = cpu_to_le32(hash);
2224 +#undef BLOCK_HASH_SHIFT
2227 +init_ext2_xattr(void)
2229 + ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
2230 + sizeof(struct mb_cache_entry) +
2231 + sizeof(struct mb_cache_entry_index), 1, 61);
2232 + if (!ext2_xattr_cache)
2239 +exit_ext2_xattr(void)
2241 + mb_cache_destroy(ext2_xattr_cache);
2244 +#else /* CONFIG_EXT2_FS_XATTR_SHARING */
2247 +init_ext2_xattr(void)
2253 +exit_ext2_xattr(void)
2257 +#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
2258 Index: linux-2.4.19-pre1/fs/ext2/xattr_user.c
2259 ===================================================================
2260 --- linux-2.4.19-pre1.orig/fs/ext2/xattr_user.c 2003-01-30 13:24:37.000000000 +0300
2261 +++ linux-2.4.19-pre1/fs/ext2/xattr_user.c 2004-01-14 01:11:49.000000000 +0300
2264 + * linux/fs/ext2/xattr_user.c
2265 + * Handler for extended user attributes.
2267 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2270 +#include <linux/module.h>
2271 +#include <linux/string.h>
2272 +#include <linux/fs.h>
2273 +#include <linux/ext2_fs.h>
2274 +#include <linux/ext2_xattr.h>
2276 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2277 +# include <linux/ext2_acl.h>
2280 +#define XATTR_USER_PREFIX "user."
2283 +ext2_xattr_user_list(char *list, struct inode *inode,
2284 + const char *name, int name_len)
2286 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2288 + if (!test_opt(inode->i_sb, XATTR_USER))
2292 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
2293 + memcpy(list+prefix_len, name, name_len);
2294 + list[prefix_len + name_len] = '\0';
2296 + return prefix_len + name_len + 1;
2300 +ext2_xattr_user_get(struct inode *inode, const char *name,
2301 + void *buffer, size_t size)
2305 + if (strcmp(name, "") == 0)
2307 + if (!test_opt(inode->i_sb, XATTR_USER))
2309 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2310 + error = ext2_permission_locked(inode, MAY_READ);
2312 + error = permission(inode, MAY_READ);
2317 + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2322 +ext2_xattr_user_set(struct inode *inode, const char *name,
2323 + const void *value, size_t size, int flags)
2327 + if (strcmp(name, "") == 0)
2329 + if (!test_opt(inode->i_sb, XATTR_USER))
2331 + if ( !S_ISREG(inode->i_mode) &&
2332 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2334 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2335 + error = ext2_permission_locked(inode, MAY_WRITE);
2337 + error = permission(inode, MAY_WRITE);
2342 + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2343 + value, size, flags);
2346 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2347 + prefix: XATTR_USER_PREFIX,
2348 + list: ext2_xattr_user_list,
2349 + get: ext2_xattr_user_get,
2350 + set: ext2_xattr_user_set,
2354 +init_ext2_xattr_user(void)
2356 + return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2357 + &ext2_xattr_user_handler);
2361 +exit_ext2_xattr_user(void)
2363 + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2364 + &ext2_xattr_user_handler);
2366 Index: linux-2.4.19-pre1/fs/ext3/Makefile
2367 ===================================================================
2368 --- linux-2.4.19-pre1.orig/fs/ext3/Makefile 2004-01-14 01:11:49.000000000 +0300
2369 +++ linux-2.4.19-pre1/fs/ext3/Makefile 2004-01-14 01:11:49.000000000 +0300
2372 -# Makefile for the linux ext2-filesystem routines.
2373 +# Makefile for the linux ext3-filesystem routines.
2375 # Note! Dependencies are done automagically by 'make dep', which also
2376 # removes any old dependencies. DON'T put your own dependencies here
2381 -export-objs := super.o inode.o
2382 +export-objs := ext3-exports.o
2384 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2385 - ioctl.o namei.o super.o symlink.o hash.o
2386 + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2387 obj-m := $(O_TARGET)
2389 +export-objs += xattr.o
2390 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2391 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2393 include $(TOPDIR)/Rules.make
2394 Index: linux-2.4.19-pre1/fs/ext3/file.c
2395 ===================================================================
2396 --- linux-2.4.19-pre1.orig/fs/ext3/file.c 2004-01-14 01:11:49.000000000 +0300
2397 +++ linux-2.4.19-pre1/fs/ext3/file.c 2004-01-14 01:11:49.000000000 +0300
2399 #include <linux/locks.h>
2400 #include <linux/jbd.h>
2401 #include <linux/ext3_fs.h>
2402 +#include <linux/ext3_xattr.h>
2403 #include <linux/ext3_jbd.h>
2404 #include <linux/smp_lock.h>
2407 struct inode_operations ext3_file_inode_operations = {
2408 truncate: ext3_truncate, /* BKL held */
2409 setattr: ext3_setattr, /* BKL held */
2410 + setxattr: ext3_setxattr, /* BKL held */
2411 + getxattr: ext3_getxattr, /* BKL held */
2412 + listxattr: ext3_listxattr, /* BKL held */
2413 + removexattr: ext3_removexattr, /* BKL held */
2416 Index: linux-2.4.19-pre1/fs/ext3/ialloc.c
2417 ===================================================================
2418 --- linux-2.4.19-pre1.orig/fs/ext3/ialloc.c 2004-01-14 01:10:37.000000000 +0300
2419 +++ linux-2.4.19-pre1/fs/ext3/ialloc.c 2004-01-14 01:11:49.000000000 +0300
2421 #include <linux/jbd.h>
2422 #include <linux/ext3_fs.h>
2423 #include <linux/ext3_jbd.h>
2424 +#include <linux/ext3_xattr.h>
2425 #include <linux/stat.h>
2426 #include <linux/string.h>
2427 #include <linux/locks.h>
2429 * as writing the quota to disk may need the lock as well.
2432 + ext3_xattr_delete_inode(handle, inode);
2433 DQUOT_FREE_INODE(inode);
2436 Index: linux-2.4.19-pre1/fs/ext3/inode.c
2437 ===================================================================
2438 --- linux-2.4.19-pre1.orig/fs/ext3/inode.c 2004-01-14 01:10:37.000000000 +0300
2439 +++ linux-2.4.19-pre1/fs/ext3/inode.c 2004-01-14 01:11:49.000000000 +0300
2442 #undef SEARCH_FROM_ZERO
2445 + * Test whether an inode is a fast symlink.
2447 +static inline int ext3_inode_is_fast_symlink(struct inode *inode)
2449 + int ea_blocks = inode->u.ext3_i.i_file_acl ?
2450 + (inode->i_sb->s_blocksize >> 9) : 0;
2452 + return (S_ISLNK(inode->i_mode) &&
2453 + inode->i_blocks - ea_blocks == 0);
2456 /* The ext3 forget function must perform a revoke if we are freeing data
2457 * which has been journaled. Metadata (eg. indirect blocks) must be
2458 * revoked in all cases.
2460 * still needs to be revoked.
2463 -static int ext3_forget(handle_t *handle, int is_metadata,
2464 +int ext3_forget(handle_t *handle, int is_metadata,
2465 struct inode *inode, struct buffer_head *bh,
2472 - if (is_bad_inode(inode) ||
2473 - inode->i_ino == EXT3_ACL_IDX_INO ||
2474 - inode->i_ino == EXT3_ACL_DATA_INO)
2475 + if (is_bad_inode(inode))
2479 @@ -1845,6 +1855,8 @@
2480 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
2481 S_ISLNK(inode->i_mode)))
2483 + if (ext3_inode_is_fast_symlink(inode))
2485 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2488 @@ -1992,8 +2004,6 @@
2489 struct ext3_group_desc * gdp;
2491 if ((inode->i_ino != EXT3_ROOT_INO &&
2492 - inode->i_ino != EXT3_ACL_IDX_INO &&
2493 - inode->i_ino != EXT3_ACL_DATA_INO &&
2494 inode->i_ino != EXT3_JOURNAL_INO &&
2495 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2496 inode->i_ino > le32_to_cpu(
2497 @@ -2120,10 +2130,7 @@
2501 - if (inode->i_ino == EXT3_ACL_IDX_INO ||
2502 - inode->i_ino == EXT3_ACL_DATA_INO)
2503 - /* Nothing to do */ ;
2504 - else if (S_ISREG(inode->i_mode)) {
2505 + if (S_ISREG(inode->i_mode)) {
2506 inode->i_op = &ext3_file_inode_operations;
2507 inode->i_fop = &ext3_file_operations;
2508 inode->i_mapping->a_ops = &ext3_aops;
2509 @@ -2131,15 +2138,17 @@
2510 inode->i_op = &ext3_dir_inode_operations;
2511 inode->i_fop = &ext3_dir_operations;
2512 } else if (S_ISLNK(inode->i_mode)) {
2513 - if (!inode->i_blocks)
2514 + if (ext3_inode_is_fast_symlink(inode))
2515 inode->i_op = &ext3_fast_symlink_inode_operations;
2517 - inode->i_op = &page_symlink_inode_operations;
2518 + inode->i_op = &ext3_symlink_inode_operations;
2519 inode->i_mapping->a_ops = &ext3_aops;
2523 + inode->i_op = &ext3_special_inode_operations;
2524 init_special_inode(inode, inode->i_mode,
2525 le32_to_cpu(iloc.raw_inode->i_block[0]));
2527 /* inode->i_attr_flags = 0; unused */
2528 if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
2529 /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
2530 Index: linux-2.4.19-pre1/fs/ext3/namei.c
2531 ===================================================================
2532 --- linux-2.4.19-pre1.orig/fs/ext3/namei.c 2004-01-14 01:11:49.000000000 +0300
2533 +++ linux-2.4.19-pre1/fs/ext3/namei.c 2004-01-14 01:11:49.000000000 +0300
2535 #include <linux/sched.h>
2536 #include <linux/ext3_fs.h>
2537 #include <linux/ext3_jbd.h>
2538 +#include <linux/ext3_xattr.h>
2539 #include <linux/fcntl.h>
2540 #include <linux/stat.h>
2541 #include <linux/string.h>
2542 @@ -1612,7 +1613,7 @@
2546 - inode = ext3_new_inode (handle, dir, S_IFDIR);
2547 + inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2548 err = PTR_ERR(inode);
2551 @@ -1620,7 +1621,6 @@
2552 inode->i_op = &ext3_dir_inode_operations;
2553 inode->i_fop = &ext3_dir_operations;
2554 inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2555 - inode->i_blocks = 0;
2556 dir_block = ext3_bread (handle, inode, 0, 1, &err);
2558 inode->i_nlink--; /* is this nlink == 0? */
2559 @@ -1647,9 +1647,6 @@
2560 BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2561 ext3_journal_dirty_metadata(handle, dir_block);
2563 - inode->i_mode = S_IFDIR | mode;
2564 - if (dir->i_mode & S_ISGID)
2565 - inode->i_mode |= S_ISGID;
2566 ext3_mark_inode_dirty(handle, inode);
2567 err = ext3_add_entry (handle, dentry, inode);
2569 @@ -2018,7 +2015,7 @@
2572 if (l > sizeof (EXT3_I(inode)->i_data)) {
2573 - inode->i_op = &page_symlink_inode_operations;
2574 + inode->i_op = &ext3_symlink_inode_operations;
2575 inode->i_mapping->a_ops = &ext3_aops;
2577 * block_symlink() calls back into ext3_prepare/commit_write.
2578 @@ -2245,4 +2242,16 @@
2579 rmdir: ext3_rmdir, /* BKL held */
2580 mknod: ext3_mknod, /* BKL held */
2581 rename: ext3_rename, /* BKL held */
2582 + setxattr: ext3_setxattr, /* BKL held */
2583 + getxattr: ext3_getxattr, /* BKL held */
2584 + listxattr: ext3_listxattr, /* BKL held */
2585 + removexattr: ext3_removexattr, /* BKL held */
2588 +struct inode_operations ext3_special_inode_operations = {
2589 + setxattr: ext3_setxattr, /* BKL held */
2590 + getxattr: ext3_getxattr, /* BKL held */
2591 + listxattr: ext3_listxattr, /* BKL held */
2592 + removexattr: ext3_removexattr, /* BKL held */
2595 Index: linux-2.4.19-pre1/fs/ext3/super.c
2596 ===================================================================
2597 --- linux-2.4.19-pre1.orig/fs/ext3/super.c 2004-01-14 01:11:49.000000000 +0300
2598 +++ linux-2.4.19-pre1/fs/ext3/super.c 2004-01-14 01:11:49.000000000 +0300
2600 #include <linux/jbd.h>
2601 #include <linux/ext3_fs.h>
2602 #include <linux/ext3_jbd.h>
2603 +#include <linux/ext3_xattr.h>
2604 #include <linux/slab.h>
2605 #include <linux/init.h>
2606 #include <linux/locks.h>
2608 kdev_t j_dev = sbi->s_journal->j_dev;
2611 + ext3_xattr_put_super(sb);
2612 journal_destroy(sbi->s_journal);
2613 if (!(sb->s_flags & MS_RDONLY)) {
2614 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2618 unsigned long *mount_options = &sbi->s_mount_opt;
2620 uid_t *resuid = &sbi->s_resuid;
2621 gid_t *resgid = &sbi->s_resgid;
2623 @@ -511,6 +514,13 @@
2624 this_char = strtok (NULL, ",")) {
2625 if ((value = strchr (this_char, '=')) != NULL)
2627 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2628 + if (!strcmp (this_char, "user_xattr"))
2629 + set_opt (*mount_options, XATTR_USER);
2630 + else if (!strcmp (this_char, "nouser_xattr"))
2631 + clear_opt (*mount_options, XATTR_USER);
2634 if (!strcmp (this_char, "bsddf"))
2635 clear_opt (*mount_options, MINIX_DF);
2636 else if (!strcmp (this_char, "nouid32")) {
2637 @@ -924,6 +934,12 @@
2638 sbi->s_mount_opt = 0;
2639 sbi->s_resuid = EXT3_DEF_RESUID;
2640 sbi->s_resgid = EXT3_DEF_RESGID;
2642 + /* Default extended attribute flags */
2643 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2644 + /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2647 if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2650 @@ -1742,17 +1758,29 @@
2652 static int __init init_ext3_fs(void)
2654 - return register_filesystem(&ext3_fs_type);
2655 + int error = init_ext3_xattr();
2658 + error = init_ext3_xattr_user();
2661 + error = register_filesystem(&ext3_fs_type);
2665 + exit_ext3_xattr_user();
2667 + exit_ext3_xattr();
2671 static void __exit exit_ext3_fs(void)
2673 unregister_filesystem(&ext3_fs_type);
2674 + exit_ext3_xattr_user();
2675 + exit_ext3_xattr();
2678 -EXPORT_SYMBOL(ext3_force_commit);
2679 -EXPORT_SYMBOL(ext3_bread);
2681 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2682 MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2683 MODULE_LICENSE("GPL");
2684 Index: linux-2.4.19-pre1/fs/ext3/symlink.c
2685 ===================================================================
2686 --- linux-2.4.19-pre1.orig/fs/ext3/symlink.c 2001-11-10 01:25:04.000000000 +0300
2687 +++ linux-2.4.19-pre1/fs/ext3/symlink.c 2004-01-14 01:11:49.000000000 +0300
2689 #include <linux/fs.h>
2690 #include <linux/jbd.h>
2691 #include <linux/ext3_fs.h>
2692 +#include <linux/ext3_xattr.h>
2694 static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2697 return vfs_follow_link(nd, s);
2700 +struct inode_operations ext3_symlink_inode_operations = {
2701 + readlink: page_readlink, /* BKL not held. Don't need */
2702 + follow_link: page_follow_link, /* BKL not held. Don't need */
2703 + setxattr: ext3_setxattr, /* BKL held */
2704 + getxattr: ext3_getxattr, /* BKL held */
2705 + listxattr: ext3_listxattr, /* BKL held */
2706 + removexattr: ext3_removexattr, /* BKL held */
2709 struct inode_operations ext3_fast_symlink_inode_operations = {
2710 readlink: ext3_readlink, /* BKL not held. Don't need */
2711 follow_link: ext3_follow_link, /* BKL not held. Don't need */
2712 + setxattr: ext3_setxattr, /* BKL held */
2713 + getxattr: ext3_getxattr, /* BKL held */
2714 + listxattr: ext3_listxattr, /* BKL held */
2715 + removexattr: ext3_removexattr, /* BKL held */
2717 Index: linux-2.4.19-pre1/fs/ext3/xattr.c
2718 ===================================================================
2719 --- linux-2.4.19-pre1.orig/fs/ext3/xattr.c 2003-01-30 13:24:37.000000000 +0300
2720 +++ linux-2.4.19-pre1/fs/ext3/xattr.c 2004-01-14 01:11:49.000000000 +0300
2723 + * linux/fs/ext3/xattr.c
2725 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2727 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2728 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2729 + * Extended attributes for symlinks and special files added per
2730 + * suggestion of Luka Renko <luka.renko@hermes.si>.
2734 + * Extended attributes are stored on disk blocks allocated outside of
2735 + * any inode. The i_file_acl field is then made to point to this allocated
2736 + * block. If all extended attributes of an inode are identical, these
2737 + * inodes may share the same extended attribute block. Such situations
2738 + * are automatically detected by keeping a cache of recent attribute block
2739 + * numbers and hashes over the block's contents in memory.
2742 + * Extended attribute block layout:
2744 + * +------------------+
2747 + * | entry 2 | | growing downwards
2749 + * | four null bytes |
2752 + * | value 3 | | growing upwards
2754 + * +------------------+
2756 + * The block header is followed by multiple entry descriptors. These entry
2757 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2758 + * byte boundaries. The entry descriptors are sorted by attribute name,
2759 + * so that two extended attribute blocks can be compared efficiently.
2761 + * Attribute values are aligned to the end of the block, stored in
2762 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2763 + * boundaries. No additional gaps are left between them.
2765 + * Locking strategy
2766 + * ----------------
2767 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2768 + * the xattr inode operations are called, so we are guaranteed that only one
2769 + * processes accesses extended attributes of an inode at any time.
2771 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2772 + * only a single process is modifying an extended attribute block, even
2773 + * if the block is shared among inodes.
2775 + * Note for porting to 2.5
2776 + * -----------------------
2777 + * The BKL will no longer be held in the xattr inode operations.
2780 +#include <linux/module.h>
2781 +#include <linux/fs.h>
2782 +#include <linux/locks.h>
2783 +#include <linux/slab.h>
2784 +#include <linux/ext3_jbd.h>
2785 +#include <linux/ext3_fs.h>
2786 +#include <linux/ext3_xattr.h>
2787 +#include <linux/mbcache.h>
2788 +#include <linux/quotaops.h>
2789 +#include <asm/semaphore.h>
2790 +#include <linux/compatmac.h>
2792 +#define EXT3_EA_USER "user."
2794 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2795 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2798 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2799 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2800 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2801 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2803 +#ifdef EXT3_XATTR_DEBUG
2804 +# define ea_idebug(inode, f...) do { \
2805 + printk(KERN_DEBUG "inode %s:%ld: ", \
2806 + kdevname(inode->i_dev), inode->i_ino); \
2810 +# define ea_bdebug(bh, f...) do { \
2811 + printk(KERN_DEBUG "block %s:%ld: ", \
2812 + kdevname(bh->b_dev), bh->b_blocknr); \
2817 +# define ea_idebug(f...)
2818 +# define ea_bdebug(f...)
2821 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2822 + struct ext3_xattr_header *);
2824 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2826 +static int ext3_xattr_cache_insert(struct buffer_head *);
2827 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2828 + struct ext3_xattr_header *);
2829 +static void ext3_xattr_cache_remove(struct buffer_head *);
2830 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2831 + struct ext3_xattr_entry *);
2833 +static struct mb_cache *ext3_xattr_cache;
2836 +# define ext3_xattr_cache_insert(bh) 0
2837 +# define ext3_xattr_cache_find(inode, header) NULL
2838 +# define ext3_xattr_cache_remove(bh) while(0) {}
2839 +# define ext3_xattr_rehash(header, entry) while(0) {}
2843 + * If a file system does not share extended attributes among inodes,
2844 + * we should not need the ext3_xattr_sem semaphore. However, the
2845 + * filesystem may still contain shared blocks, so we always take
2849 +DECLARE_MUTEX(ext3_xattr_sem);
2852 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2853 + int * errp, int force)
2855 + struct super_block *sb = inode->i_sb;
2856 + int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2857 + EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2859 + /* How can we enforce the allocation? */
2860 + int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2863 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2869 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2871 + /* How can we enforce the allocation? */
2873 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2875 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2877 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
2885 +ext3_xattr_quota_free(struct inode *inode)
2887 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2888 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2892 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2893 + unsigned long block)
2895 + ext3_free_blocks(handle, inode, block, 1);
2896 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2900 +# define ext3_xattr_quota_free(inode) \
2901 + DQUOT_FREE_BLOCK(inode, 1)
2902 +# define ext3_xattr_free_block(handle, inode, block) \
2903 + ext3_free_blocks(handle, inode, block, 1)
2906 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2908 +static inline struct buffer_head *
2909 +sb_bread(struct super_block *sb, int block)
2911 + return bread(sb->s_dev, block, sb->s_blocksize);
2914 +static inline struct buffer_head *
2915 +sb_getblk(struct super_block *sb, int block)
2917 + return getblk(sb->s_dev, block, sb->s_blocksize);
2922 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2923 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2926 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2928 + int error = -EINVAL;
2930 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2931 + write_lock(&ext3_handler_lock);
2932 + if (!ext3_xattr_handlers[name_index-1]) {
2933 + ext3_xattr_handlers[name_index-1] = handler;
2936 + write_unlock(&ext3_handler_lock);
2942 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2944 + if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2945 + write_lock(&ext3_handler_lock);
2946 + ext3_xattr_handlers[name_index-1] = NULL;
2947 + write_unlock(&ext3_handler_lock);
2951 +static inline const char *
2952 +strcmp_prefix(const char *a, const char *a_prefix)
2954 + while (*a_prefix && *a == *a_prefix) {
2958 + return *a_prefix ? NULL : a;
2962 + * Decode the extended attribute name, and translate it into
2963 + * the name_index and name suffix.
2965 +static inline struct ext3_xattr_handler *
2966 +ext3_xattr_resolve_name(const char **name)
2968 + struct ext3_xattr_handler *handler = NULL;
2973 + read_lock(&ext3_handler_lock);
2974 + for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2975 + if (ext3_xattr_handlers[i]) {
2976 + const char *n = strcmp_prefix(*name,
2977 + ext3_xattr_handlers[i]->prefix);
2979 + handler = ext3_xattr_handlers[i];
2985 + read_unlock(&ext3_handler_lock);
2989 +static inline struct ext3_xattr_handler *
2990 +ext3_xattr_handler(int name_index)
2992 + struct ext3_xattr_handler *handler = NULL;
2993 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2994 + read_lock(&ext3_handler_lock);
2995 + handler = ext3_xattr_handlers[name_index-1];
2996 + read_unlock(&ext3_handler_lock);
3002 + * Inode operation getxattr()
3004 + * dentry->d_inode->i_sem down
3005 + * BKL held [before 2.5.x]
3008 +ext3_getxattr(struct dentry *dentry, const char *name,
3009 + void *buffer, size_t size)
3011 + struct ext3_xattr_handler *handler;
3012 + struct inode *inode = dentry->d_inode;
3014 + handler = ext3_xattr_resolve_name(&name);
3017 + return handler->get(inode, name, buffer, size);
3021 + * Inode operation listxattr()
3023 + * dentry->d_inode->i_sem down
3024 + * BKL held [before 2.5.x]
3027 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
3029 + return ext3_xattr_list(dentry->d_inode, buffer, size);
3033 + * Inode operation setxattr()
3035 + * dentry->d_inode->i_sem down
3036 + * BKL held [before 2.5.x]
3039 +ext3_setxattr(struct dentry *dentry, const char *name,
3040 + const void *value, size_t size, int flags)
3042 + struct ext3_xattr_handler *handler;
3043 + struct inode *inode = dentry->d_inode;
3046 + value = ""; /* empty EA, do not remove */
3047 + handler = ext3_xattr_resolve_name(&name);
3050 + return handler->set(inode, name, value, size, flags);
3054 + * Inode operation removexattr()
3056 + * dentry->d_inode->i_sem down
3057 + * BKL held [before 2.5.x]
3060 +ext3_removexattr(struct dentry *dentry, const char *name)
3062 + struct ext3_xattr_handler *handler;
3063 + struct inode *inode = dentry->d_inode;
3065 + handler = ext3_xattr_resolve_name(&name);
3068 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
3072 + * ext3_xattr_get()
3074 + * Copy an extended attribute into the buffer
3075 + * provided, or compute the buffer size required.
3076 + * Buffer is NULL to compute the size of the buffer required.
3078 + * Returns a negative error number on failure, or the number of bytes
3079 + * used / required on success.
3082 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
3083 + void *buffer, size_t buffer_size)
3085 + struct buffer_head *bh = NULL;
3086 + struct ext3_xattr_entry *entry;
3087 + unsigned int block, size;
3089 + int name_len, error;
3091 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
3092 + name_index, name, buffer, (long)buffer_size);
3096 + if (!EXT3_I(inode)->i_file_acl)
3098 + block = EXT3_I(inode)->i_file_acl;
3099 + ea_idebug(inode, "reading block %d", block);
3100 + bh = sb_bread(inode->i_sb, block);
3103 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3104 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3105 + end = bh->b_data + bh->b_size;
3106 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3107 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3108 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
3109 + "inode %ld: bad block %d", inode->i_ino, block);
3113 + /* find named attribute */
3114 + name_len = strlen(name);
3117 + if (name_len > 255)
3119 + entry = FIRST_ENTRY(bh);
3120 + while (!IS_LAST_ENTRY(entry)) {
3121 + struct ext3_xattr_entry *next =
3122 + EXT3_XATTR_NEXT(entry);
3123 + if ((char *)next >= end)
3125 + if (name_index == entry->e_name_index &&
3126 + name_len == entry->e_name_len &&
3127 + memcmp(name, entry->e_name, name_len) == 0)
3131 + /* Check the remaining name entries */
3132 + while (!IS_LAST_ENTRY(entry)) {
3133 + struct ext3_xattr_entry *next =
3134 + EXT3_XATTR_NEXT(entry);
3135 + if ((char *)next >= end)
3139 + if (ext3_xattr_cache_insert(bh))
3140 + ea_idebug(inode, "cache insert failed");
3144 + /* check the buffer size */
3145 + if (entry->e_value_block != 0)
3147 + size = le32_to_cpu(entry->e_value_size);
3148 + if (size > inode->i_sb->s_blocksize ||
3149 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
3152 + if (ext3_xattr_cache_insert(bh))
3153 + ea_idebug(inode, "cache insert failed");
3156 + if (size > buffer_size)
3158 + /* return value of attribute */
3159 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
3171 + * ext3_xattr_list()
3173 + * Copy a list of attribute names into the buffer
3174 + * provided, or compute the buffer size required.
3175 + * Buffer is NULL to compute the size of the buffer required.
3177 + * Returns a negative error number on failure, or the number of bytes
3178 + * used / required on success.
3181 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
3183 + struct buffer_head *bh = NULL;
3184 + struct ext3_xattr_entry *entry;
3185 + unsigned int block, size = 0;
3189 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
3190 + buffer, (long)buffer_size);
3192 + if (!EXT3_I(inode)->i_file_acl)
3194 + block = EXT3_I(inode)->i_file_acl;
3195 + ea_idebug(inode, "reading block %d", block);
3196 + bh = sb_bread(inode->i_sb, block);
3199 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3200 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3201 + end = bh->b_data + bh->b_size;
3202 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3203 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3204 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
3205 + "inode %ld: bad block %d", inode->i_ino, block);
3209 + /* compute the size required for the list of attribute names */
3210 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3211 + entry = EXT3_XATTR_NEXT(entry)) {
3212 + struct ext3_xattr_handler *handler;
3213 + struct ext3_xattr_entry *next =
3214 + EXT3_XATTR_NEXT(entry);
3215 + if ((char *)next >= end)
3218 + handler = ext3_xattr_handler(entry->e_name_index);
3220 + size += handler->list(NULL, inode, entry->e_name,
3221 + entry->e_name_len);
3224 + if (ext3_xattr_cache_insert(bh))
3225 + ea_idebug(inode, "cache insert failed");
3231 + if (size > buffer_size)
3235 + /* list the attribute names */
3237 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3238 + entry = EXT3_XATTR_NEXT(entry)) {
3239 + struct ext3_xattr_handler *handler;
3241 + handler = ext3_xattr_handler(entry->e_name_index);
3243 + buf += handler->list(buf, inode, entry->e_name,
3244 + entry->e_name_len);
3255 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3256 + * not set, set it.
3258 +static void ext3_xattr_update_super_block(handle_t *handle,
3259 + struct super_block *sb)
3261 + if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3265 + ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3266 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3267 + EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3269 + EXT3_SB(sb)->s_es->s_feature_compat |=
3270 + cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3272 + ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3277 + * ext3_xattr_set()
3279 + * Create, replace or remove an extended attribute for this inode. Buffer
3280 + * is NULL to remove an existing extended attribute, and non-NULL to
3281 + * either replace an existing extended attribute, or create a new extended
3282 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3283 + * specify that an extended attribute must exist and must not exist
3284 + * previous to the call, respectively.
3286 + * Returns 0, or a negative error number on failure.
3289 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3290 + const char *name, const void *value, size_t value_len, int flags)
3292 + struct super_block *sb = inode->i_sb;
3293 + struct buffer_head *bh = NULL;
3294 + struct ext3_xattr_header *header = NULL;
3295 + struct ext3_xattr_entry *here, *last;
3296 + unsigned int name_len;
3297 + int block = EXT3_I(inode)->i_file_acl;
3298 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
3302 + * header -- Points either into bh, or to a temporarily
3303 + * allocated buffer.
3304 + * here -- The named entry found, or the place for inserting, within
3305 + * the block pointed to by header.
3306 + * last -- Points right after the last named entry within the block
3307 + * pointed to by header.
3308 + * min_offs -- The offset of the first value (values are aligned
3309 + * towards the end of the block).
3310 + * end -- Points right after the block pointed to by header.
3313 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3314 + name_index, name, value, (long)value_len);
3316 + if (IS_RDONLY(inode))
3318 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3320 + if (value == NULL)
3324 + name_len = strlen(name);
3325 + if (name_len > 255 || value_len > sb->s_blocksize)
3327 + down(&ext3_xattr_sem);
3330 + /* The inode already has an extended attribute block. */
3331 + bh = sb_bread(sb, block);
3335 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3336 + atomic_read(&(bh->b_count)),
3337 + le32_to_cpu(HDR(bh)->h_refcount));
3339 + end = bh->b_data + bh->b_size;
3340 + if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3341 + header->h_blocks != cpu_to_le32(1)) {
3342 +bad_block: ext3_error(sb, "ext3_xattr_set",
3343 + "inode %ld: bad block %d", inode->i_ino, block);
3347 + /* Find the named attribute. */
3348 + here = FIRST_ENTRY(bh);
3349 + while (!IS_LAST_ENTRY(here)) {
3350 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3351 + if ((char *)next >= end)
3353 + if (!here->e_value_block && here->e_value_size) {
3354 + int offs = le16_to_cpu(here->e_value_offs);
3355 + if (offs < min_offs)
3358 + not_found = name_index - here->e_name_index;
3360 + not_found = name_len - here->e_name_len;
3362 + not_found = memcmp(name, here->e_name,name_len);
3363 + if (not_found <= 0)
3368 + /* We still need to compute min_offs and last. */
3369 + while (!IS_LAST_ENTRY(last)) {
3370 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3371 + if ((char *)next >= end)
3373 + if (!last->e_value_block && last->e_value_size) {
3374 + int offs = le16_to_cpu(last->e_value_offs);
3375 + if (offs < min_offs)
3381 + /* Check whether we have enough space left. */
3382 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3384 + /* We will use a new extended attribute block. */
3385 + free = sb->s_blocksize -
3386 + sizeof(struct ext3_xattr_header) - sizeof(__u32);
3387 + here = last = NULL; /* avoid gcc uninitialized warning. */
3391 + /* Request to remove a nonexistent attribute? */
3393 + if (flags & XATTR_REPLACE)
3396 + if (value == NULL)
3399 + free -= EXT3_XATTR_LEN(name_len);
3401 + /* Request to create an existing attribute? */
3403 + if (flags & XATTR_CREATE)
3405 + if (!here->e_value_block && here->e_value_size) {
3406 + unsigned int size = le32_to_cpu(here->e_value_size);
3408 + if (le16_to_cpu(here->e_value_offs) + size >
3409 + sb->s_blocksize || size > sb->s_blocksize)
3411 + free += EXT3_XATTR_SIZE(size);
3414 + free -= EXT3_XATTR_SIZE(value_len);
3419 + /* Here we know that we can set the new attribute. */
3422 + if (header->h_refcount == cpu_to_le32(1)) {
3423 + ea_bdebug(bh, "modifying in-place");
3424 + ext3_xattr_cache_remove(bh);
3425 + error = ext3_journal_get_write_access(handle, bh);
3431 + ea_bdebug(bh, "cloning");
3432 + header = kmalloc(bh->b_size, GFP_KERNEL);
3434 + if (header == NULL)
3436 + memcpy(header, HDR(bh), bh->b_size);
3437 + header->h_refcount = cpu_to_le32(1);
3438 + offset = (char *)header - bh->b_data;
3439 + here = ENTRY((char *)here + offset);
3440 + last = ENTRY((char *)last + offset);
3443 + /* Allocate a buffer where we construct the new block. */
3444 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3446 + if (header == NULL)
3448 + memset(header, 0, sb->s_blocksize);
3449 + end = (char *)header + sb->s_blocksize;
3450 + header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3451 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
3452 + last = here = ENTRY(header+1);
3456 + /* Insert the new name. */
3457 + int size = EXT3_XATTR_LEN(name_len);
3458 + int rest = (char *)last - (char *)here;
3459 + memmove((char *)here + size, here, rest);
3460 + memset(here, 0, size);
3461 + here->e_name_index = name_index;
3462 + here->e_name_len = name_len;
3463 + memcpy(here->e_name, name, name_len);
3465 + /* Remove the old value. */
3466 + if (!here->e_value_block && here->e_value_size) {
3467 + char *first_val = (char *)header + min_offs;
3468 + int offs = le16_to_cpu(here->e_value_offs);
3469 + char *val = (char *)header + offs;
3470 + size_t size = EXT3_XATTR_SIZE(
3471 + le32_to_cpu(here->e_value_size));
3472 + memmove(first_val + size, first_val, val - first_val);
3473 + memset(first_val, 0, size);
3474 + here->e_value_offs = 0;
3477 + /* Adjust all value offsets. */
3478 + last = ENTRY(header+1);
3479 + while (!IS_LAST_ENTRY(last)) {
3480 + int o = le16_to_cpu(last->e_value_offs);
3481 + if (!last->e_value_block && o < offs)
3482 + last->e_value_offs =
3483 + cpu_to_le16(o + size);
3484 + last = EXT3_XATTR_NEXT(last);
3487 + if (value == NULL) {
3488 + /* Remove this attribute. */
3489 + if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3490 + /* This block is now empty. */
3491 + error = ext3_xattr_set2(handle, inode, bh,NULL);
3494 + /* Remove the old name. */
3495 + int size = EXT3_XATTR_LEN(name_len);
3496 + last = ENTRY((char *)last - size);
3497 + memmove(here, (char*)here + size,
3498 + (char*)last - (char*)here);
3499 + memset(last, 0, size);
3504 + if (value != NULL) {
3505 + /* Insert the new value. */
3506 + here->e_value_size = cpu_to_le32(value_len);
3508 + size_t size = EXT3_XATTR_SIZE(value_len);
3509 + char *val = (char *)header + min_offs - size;
3510 + here->e_value_offs =
3511 + cpu_to_le16((char *)val - (char *)header);
3512 + memset(val + size - EXT3_XATTR_PAD, 0,
3513 + EXT3_XATTR_PAD); /* Clear the pad bytes. */
3514 + memcpy(val, value, value_len);
3517 + ext3_xattr_rehash(header, here);
3519 + error = ext3_xattr_set2(handle, inode, bh, header);
3523 + if (!(bh && header == HDR(bh)))
3525 + up(&ext3_xattr_sem);
3531 + * Second half of ext3_xattr_set(): Update the file system.
3534 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3535 + struct buffer_head *old_bh, struct ext3_xattr_header *header)
3537 + struct super_block *sb = inode->i_sb;
3538 + struct buffer_head *new_bh = NULL;
3542 + new_bh = ext3_xattr_cache_find(inode, header);
3545 + * We found an identical block in the cache.
3546 + * The old block will be released after updating
3549 + ea_bdebug(old_bh, "reusing block %ld",
3550 + new_bh->b_blocknr);
3553 + if (ext3_xattr_quota_alloc(inode, 1))
3556 + error = ext3_journal_get_write_access(handle, new_bh);
3559 + HDR(new_bh)->h_refcount = cpu_to_le32(
3560 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3561 + ea_bdebug(new_bh, "refcount now=%d",
3562 + le32_to_cpu(HDR(new_bh)->h_refcount));
3563 + } else if (old_bh && header == HDR(old_bh)) {
3564 + /* Keep this block. */
3566 + (void)ext3_xattr_cache_insert(new_bh);
3568 + /* We need to allocate a new block */
3569 + int force = EXT3_I(inode)->i_file_acl != 0;
3570 + int block = ext3_xattr_new_block(handle, inode,
3574 + ea_idebug(inode, "creating block %d", block);
3576 + new_bh = sb_getblk(sb, block);
3578 +getblk_failed: ext3_xattr_free_block(handle, inode, block);
3582 + lock_buffer(new_bh);
3583 + error = ext3_journal_get_create_access(handle, new_bh);
3585 + unlock_buffer(new_bh);
3586 + goto getblk_failed;
3588 + memcpy(new_bh->b_data, header, new_bh->b_size);
3589 + mark_buffer_uptodate(new_bh, 1);
3590 + unlock_buffer(new_bh);
3591 + (void)ext3_xattr_cache_insert(new_bh);
3593 + ext3_xattr_update_super_block(handle, sb);
3595 + error = ext3_journal_dirty_metadata(handle, new_bh);
3600 + /* Update the inode. */
3601 + EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3602 + inode->i_ctime = CURRENT_TIME;
3603 + ext3_mark_inode_dirty(handle, inode);
3604 + if (IS_SYNC(inode))
3605 + handle->h_sync = 1;
3608 + if (old_bh && old_bh != new_bh) {
3610 + * If there was an old block, and we are not still using it,
3611 + * we now release the old block.
3613 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3615 + error = ext3_journal_get_write_access(handle, old_bh);
3618 + if (refcount == 1) {
3619 + /* Free the old block. */
3620 + ea_bdebug(old_bh, "freeing");
3621 + ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3623 + /* ext3_forget() calls bforget() for us, but we
3624 + let our caller release old_bh, so we need to
3625 + duplicate the handle before. */
3627 + ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3629 + /* Decrement the refcount only. */
3631 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3632 + ext3_xattr_quota_free(inode);
3633 + ext3_journal_dirty_metadata(handle, old_bh);
3634 + ea_bdebug(old_bh, "refcount now=%d", refcount);
3639 + if (old_bh != new_bh)
3646 + * ext3_xattr_delete_inode()
3648 + * Free extended attribute resources associated with this inode. This
3649 + * is called immediately before an inode is freed.
3652 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3654 + struct buffer_head *bh;
3655 + unsigned int block = EXT3_I(inode)->i_file_acl;
3659 + down(&ext3_xattr_sem);
3661 + bh = sb_bread(inode->i_sb, block);
3663 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3664 + "inode %ld: block %d read error", inode->i_ino, block);
3667 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3668 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3669 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3670 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3671 + "inode %ld: bad block %d", inode->i_ino, block);
3674 + ext3_journal_get_write_access(handle, bh);
3675 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3676 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3677 + ext3_xattr_cache_remove(bh);
3678 + ext3_xattr_free_block(handle, inode, block);
3679 + ext3_forget(handle, 1, inode, bh, block);
3682 + HDR(bh)->h_refcount = cpu_to_le32(
3683 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
3684 + ext3_journal_dirty_metadata(handle, bh);
3685 + if (IS_SYNC(inode))
3686 + handle->h_sync = 1;
3687 + ext3_xattr_quota_free(inode);
3689 + EXT3_I(inode)->i_file_acl = 0;
3693 + up(&ext3_xattr_sem);
3697 + * ext3_xattr_put_super()
3699 + * This is called when a file system is unmounted.
3702 +ext3_xattr_put_super(struct super_block *sb)
3704 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3705 + mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3709 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3712 + * ext3_xattr_cache_insert()
3714 + * Create a new entry in the extended attribute cache, and insert
3715 + * it unless such an entry is already in the cache.
3717 + * Returns 0, or a negative error number on failure.
3720 +ext3_xattr_cache_insert(struct buffer_head *bh)
3722 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3723 + struct mb_cache_entry *ce;
3726 + ce = mb_cache_entry_alloc(ext3_xattr_cache);
3729 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3731 + mb_cache_entry_free(ce);
3732 + if (error == -EBUSY) {
3733 + ea_bdebug(bh, "already in cache (%d cache entries)",
3734 + atomic_read(&ext3_xattr_cache->c_entry_count));
3738 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3739 + atomic_read(&ext3_xattr_cache->c_entry_count));
3740 + mb_cache_entry_release(ce);
3746 + * ext3_xattr_cmp()
3748 + * Compare two extended attribute blocks for equality.
3750 + * Returns 0 if the blocks are equal, 1 if they differ, and
3751 + * a negative error number on errors.
3754 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3755 + struct ext3_xattr_header *header2)
3757 + struct ext3_xattr_entry *entry1, *entry2;
3759 + entry1 = ENTRY(header1+1);
3760 + entry2 = ENTRY(header2+1);
3761 + while (!IS_LAST_ENTRY(entry1)) {
3762 + if (IS_LAST_ENTRY(entry2))
3764 + if (entry1->e_hash != entry2->e_hash ||
3765 + entry1->e_name_len != entry2->e_name_len ||
3766 + entry1->e_value_size != entry2->e_value_size ||
3767 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3769 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3771 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3772 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3773 + le32_to_cpu(entry1->e_value_size)))
3776 + entry1 = EXT3_XATTR_NEXT(entry1);
3777 + entry2 = EXT3_XATTR_NEXT(entry2);
3779 + if (!IS_LAST_ENTRY(entry2))
3785 + * ext3_xattr_cache_find()
3787 + * Find an identical extended attribute block.
3789 + * Returns a pointer to the block found, or NULL if such a block was
3790 + * not found or an error occurred.
3792 +static struct buffer_head *
3793 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3795 + __u32 hash = le32_to_cpu(header->h_hash);
3796 + struct mb_cache_entry *ce;
3798 + if (!header->h_hash)
3799 + return NULL; /* never share */
3800 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3801 + ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3803 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3806 + ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3807 + "inode %ld: block %ld read error",
3808 + inode->i_ino, ce->e_block);
3809 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3810 + EXT3_XATTR_REFCOUNT_MAX) {
3811 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3812 + le32_to_cpu(HDR(bh)->h_refcount),
3813 + EXT3_XATTR_REFCOUNT_MAX);
3814 + } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3815 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3816 + mb_cache_entry_release(ce);
3820 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3826 + * ext3_xattr_cache_remove()
3828 + * Remove the cache entry of a block from the cache. Called when a
3829 + * block becomes invalid.
3832 +ext3_xattr_cache_remove(struct buffer_head *bh)
3834 + struct mb_cache_entry *ce;
3836 + ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3838 + ea_bdebug(bh, "removing (%d cache entries remaining)",
3839 + atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3840 + mb_cache_entry_free(ce);
3842 + ea_bdebug(bh, "no cache entry");
3845 +#define NAME_HASH_SHIFT 5
3846 +#define VALUE_HASH_SHIFT 16
3849 + * ext3_xattr_hash_entry()
3851 + * Compute the hash of an extended attribute.
3853 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3854 + struct ext3_xattr_entry *entry)
3857 + char *name = entry->e_name;
3860 + for (n=0; n < entry->e_name_len; n++) {
3861 + hash = (hash << NAME_HASH_SHIFT) ^
3862 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3866 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3867 + __u32 *value = (__u32 *)((char *)header +
3868 + le16_to_cpu(entry->e_value_offs));
3869 + for (n = (le32_to_cpu(entry->e_value_size) +
3870 + EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3871 + hash = (hash << VALUE_HASH_SHIFT) ^
3872 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3873 + le32_to_cpu(*value++);
3876 + entry->e_hash = cpu_to_le32(hash);
3879 +#undef NAME_HASH_SHIFT
3880 +#undef VALUE_HASH_SHIFT
3882 +#define BLOCK_HASH_SHIFT 16
3885 + * ext3_xattr_rehash()
3887 + * Re-compute the extended attribute hash value after an entry has changed.
3889 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3890 + struct ext3_xattr_entry *entry)
3892 + struct ext3_xattr_entry *here;
3895 + ext3_xattr_hash_entry(header, entry);
3896 + here = ENTRY(header+1);
3897 + while (!IS_LAST_ENTRY(here)) {
3898 + if (!here->e_hash) {
3899 + /* Block is not shared if an entry's hash value == 0 */
3903 + hash = (hash << BLOCK_HASH_SHIFT) ^
3904 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3905 + le32_to_cpu(here->e_hash);
3906 + here = EXT3_XATTR_NEXT(here);
3908 + header->h_hash = cpu_to_le32(hash);
3911 +#undef BLOCK_HASH_SHIFT
3914 +init_ext3_xattr(void)
3916 + ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3917 + sizeof(struct mb_cache_entry) +
3918 + sizeof(struct mb_cache_entry_index), 1, 61);
3919 + if (!ext3_xattr_cache)
3926 +exit_ext3_xattr(void)
3928 + if (ext3_xattr_cache)
3929 + mb_cache_destroy(ext3_xattr_cache);
3930 + ext3_xattr_cache = NULL;
3933 +#else /* CONFIG_EXT3_FS_XATTR_SHARING */
3936 +init_ext3_xattr(void)
3942 +exit_ext3_xattr(void)
3946 +#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
3947 Index: linux-2.4.19-pre1/fs/ext3/xattr_user.c
3948 ===================================================================
3949 --- linux-2.4.19-pre1.orig/fs/ext3/xattr_user.c 2003-01-30 13:24:37.000000000 +0300
3950 +++ linux-2.4.19-pre1/fs/ext3/xattr_user.c 2004-01-14 01:11:49.000000000 +0300
3953 + * linux/fs/ext3/xattr_user.c
3954 + * Handler for extended user attributes.
3956 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3959 +#include <linux/module.h>
3960 +#include <linux/string.h>
3961 +#include <linux/fs.h>
3962 +#include <linux/ext3_jbd.h>
3963 +#include <linux/ext3_fs.h>
3964 +#include <linux/ext3_xattr.h>
3966 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3967 +# include <linux/ext3_acl.h>
3970 +#define XATTR_USER_PREFIX "user."
3973 +ext3_xattr_user_list(char *list, struct inode *inode,
3974 + const char *name, int name_len)
3976 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3978 + if (!test_opt(inode->i_sb, XATTR_USER))
3982 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
3983 + memcpy(list+prefix_len, name, name_len);
3984 + list[prefix_len + name_len] = '\0';
3986 + return prefix_len + name_len + 1;
3990 +ext3_xattr_user_get(struct inode *inode, const char *name,
3991 + void *buffer, size_t size)
3995 + if (strcmp(name, "") == 0)
3997 + if (!test_opt(inode->i_sb, XATTR_USER))
3999 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
4000 + error = ext3_permission_locked(inode, MAY_READ);
4002 + error = permission(inode, MAY_READ);
4007 + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
4012 +ext3_xattr_user_set(struct inode *inode, const char *name,
4013 + const void *value, size_t size, int flags)
4018 + if (strcmp(name, "") == 0)
4020 + if (!test_opt(inode->i_sb, XATTR_USER))
4022 + if ( !S_ISREG(inode->i_mode) &&
4023 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
4025 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
4026 + error = ext3_permission_locked(inode, MAY_WRITE);
4028 + error = permission(inode, MAY_WRITE);
4033 + handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
4034 + if (IS_ERR(handle))
4035 + return PTR_ERR(handle);
4036 + error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
4037 + value, size, flags);
4038 + ext3_journal_stop(handle, inode);
4043 +struct ext3_xattr_handler ext3_xattr_user_handler = {
4044 + prefix: XATTR_USER_PREFIX,
4045 + list: ext3_xattr_user_list,
4046 + get: ext3_xattr_user_get,
4047 + set: ext3_xattr_user_set,
4051 +init_ext3_xattr_user(void)
4053 + return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
4054 + &ext3_xattr_user_handler);
4058 +exit_ext3_xattr_user(void)
4060 + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
4061 + &ext3_xattr_user_handler);
4063 Index: linux-2.4.19-pre1/fs/ext3/ext3-exports.c
4064 ===================================================================
4065 --- linux-2.4.19-pre1.orig/fs/ext3/ext3-exports.c 2003-01-30 13:24:37.000000000 +0300
4066 +++ linux-2.4.19-pre1/fs/ext3/ext3-exports.c 2004-01-14 01:11:49.000000000 +0300
4068 +#include <linux/config.h>
4069 +#include <linux/module.h>
4070 +#include <linux/ext3_fs.h>
4071 +#include <linux/ext3_jbd.h>
4072 +#include <linux/ext3_xattr.h>
4074 +EXPORT_SYMBOL(ext3_force_commit);
4075 +EXPORT_SYMBOL(ext3_bread);
4076 +EXPORT_SYMBOL(ext3_xattr_register);
4077 +EXPORT_SYMBOL(ext3_xattr_unregister);
4078 +EXPORT_SYMBOL(ext3_xattr_get);
4079 +EXPORT_SYMBOL(ext3_xattr_list);
4080 +EXPORT_SYMBOL(ext3_xattr_set);
4081 Index: linux-2.4.19-pre1/fs/mbcache.c
4082 ===================================================================
4083 --- linux-2.4.19-pre1.orig/fs/mbcache.c 2003-01-30 13:24:37.000000000 +0300
4084 +++ linux-2.4.19-pre1/fs/mbcache.c 2004-01-14 01:11:49.000000000 +0300
4087 + * linux/fs/mbcache.c
4088 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4092 + * Filesystem Meta Information Block Cache (mbcache)
4094 + * The mbcache caches blocks of block devices that need to be located
4095 + * by their device/block number, as well as by other criteria (such
4096 + * as the block's contents).
4098 + * There can only be one cache entry in a cache per device and block number.
4099 + * Additional indexes need not be unique in this sense. The number of
4100 + * additional indexes (=other criteria) can be hardwired at compile time
4101 + * or specified at cache create time.
4103 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
4104 + * in the cache. A valid entry is in the main hash tables of the cache,
4105 + * and may also be in the lru list. An invalid entry is not in any hashes
4108 + * A valid cache entry is only in the lru list if no handles refer to it.
4109 + * Invalid cache entries will be freed when the last handle to the cache
4110 + * entry is released. Entries that cannot be freed immediately are put
4111 + * back on the lru list.
4114 +#include <linux/kernel.h>
4115 +#include <linux/module.h>
4117 +#include <linux/fs.h>
4118 +#include <linux/slab.h>
4119 +#include <linux/sched.h>
4120 +#include <linux/cache_def.h>
4121 +#include <linux/version.h>
4122 +#include <linux/init.h>
4123 +#include <linux/mbcache.h>
4126 +#ifdef MB_CACHE_DEBUG
4127 +# define mb_debug(f...) do { \
4128 + printk(KERN_DEBUG f); \
4131 +#define mb_assert(c) do { if (!(c)) \
4132 + printk(KERN_ERR "assertion " #c " failed\n"); \
4135 +# define mb_debug(f...) do { } while(0)
4136 +# define mb_assert(c) do { } while(0)
4138 +#define mb_error(f...) do { \
4139 + printk(KERN_ERR f); \
4143 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
4144 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
4145 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4146 +MODULE_LICENSE("GPL");
4149 +EXPORT_SYMBOL(mb_cache_create);
4150 +EXPORT_SYMBOL(mb_cache_shrink);
4151 +EXPORT_SYMBOL(mb_cache_destroy);
4152 +EXPORT_SYMBOL(mb_cache_entry_alloc);
4153 +EXPORT_SYMBOL(mb_cache_entry_insert);
4154 +EXPORT_SYMBOL(mb_cache_entry_release);
4155 +EXPORT_SYMBOL(mb_cache_entry_takeout);
4156 +EXPORT_SYMBOL(mb_cache_entry_free);
4157 +EXPORT_SYMBOL(mb_cache_entry_dup);
4158 +EXPORT_SYMBOL(mb_cache_entry_get);
4159 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4160 +EXPORT_SYMBOL(mb_cache_entry_find_first);
4161 +EXPORT_SYMBOL(mb_cache_entry_find_next);
4166 + * Global data: list of all mbcache's, lru list, and a spinlock for
4167 + * accessing cache data structures on SMP machines. The lru list is
4168 + * global across all mbcaches.
4171 +static LIST_HEAD(mb_cache_list);
4172 +static LIST_HEAD(mb_cache_lru_list);
4173 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
4176 +mb_cache_indexes(struct mb_cache *cache)
4178 +#ifdef MB_CACHE_INDEXES_COUNT
4179 + return MB_CACHE_INDEXES_COUNT;
4181 + return cache->c_indexes_count;
4186 + * What the mbcache registers as to get shrunk dynamically.
4190 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
4192 +static struct cache_definition mb_cache_definition = {
4194 + mb_cache_memory_pressure
4199 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4201 + return !list_empty(&ce->e_block_list);
4206 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4210 + if (__mb_cache_entry_is_hashed(ce)) {
4211 + list_del_init(&ce->e_block_list);
4212 + for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4213 + list_del(&ce->e_indexes[n].o_list);
4219 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4221 + struct mb_cache *cache = ce->e_cache;
4223 + mb_assert(atomic_read(&ce->e_used) == 0);
4224 + if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4225 + /* free failed -- put back on the lru list
4226 + for freeing later. */
4227 + spin_lock(&mb_cache_spinlock);
4228 + list_add(&ce->e_lru_list, &mb_cache_lru_list);
4229 + spin_unlock(&mb_cache_spinlock);
4231 + kmem_cache_free(cache->c_entry_cache, ce);
4232 + atomic_dec(&cache->c_entry_count);
4238 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4240 + if (atomic_dec_and_test(&ce->e_used)) {
4241 + if (__mb_cache_entry_is_hashed(ce))
4242 + list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4244 + spin_unlock(&mb_cache_spinlock);
4245 + __mb_cache_entry_forget(ce, GFP_KERNEL);
4249 + spin_unlock(&mb_cache_spinlock);
4254 + * mb_cache_memory_pressure() memory pressure callback
4256 + * This function is called by the kernel memory management when memory
4259 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4260 + * @gfp_mask: (ignored)
4263 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4265 + LIST_HEAD(free_list);
4266 + struct list_head *l, *ltmp;
4269 + spin_lock(&mb_cache_spinlock);
4270 + list_for_each(l, &mb_cache_list) {
4271 + struct mb_cache *cache =
4272 + list_entry(l, struct mb_cache, c_cache_list);
4273 + mb_debug("cache %s (%d)", cache->c_name,
4274 + atomic_read(&cache->c_entry_count));
4275 + count += atomic_read(&cache->c_entry_count);
4277 + mb_debug("trying to free %d of %d entries",
4278 + count / (priority ? priority : 1), count);
4280 + count /= priority;
4281 + while (count-- && !list_empty(&mb_cache_lru_list)) {
4282 + struct mb_cache_entry *ce =
4283 + list_entry(mb_cache_lru_list.next,
4284 + struct mb_cache_entry, e_lru_list);
4285 + list_del(&ce->e_lru_list);
4286 + __mb_cache_entry_unhash(ce);
4287 + list_add_tail(&ce->e_lru_list, &free_list);
4289 + spin_unlock(&mb_cache_spinlock);
4290 + list_for_each_safe(l, ltmp, &free_list) {
4291 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4292 + e_lru_list), gfp_mask);
4298 + * mb_cache_create() create a new cache
4300 + * All entries in one cache are equal size. Cache entries may be from
4301 + * multiple devices. If this is the first mbcache created, registers
4302 + * the cache with kernel memory management. Returns NULL if no more
4303 + * memory was available.
4305 + * @name: name of the cache (informal)
4306 + * @cache_op: contains the callback called when freeing a cache entry
4307 + * @entry_size: The size of a cache entry, including
4308 + * struct mb_cache_entry
4309 + * @indexes_count: number of additional indexes in the cache. Must equal
4310 + * MB_CACHE_INDEXES_COUNT if the number of indexes is
4312 + * @bucket_count: number of hash buckets
4315 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4316 + size_t entry_size, int indexes_count, int bucket_count)
4319 + struct mb_cache *cache = NULL;
4321 + if(entry_size < sizeof(struct mb_cache_entry) +
4322 + indexes_count * sizeof(struct mb_cache_entry_index))
4325 + MOD_INC_USE_COUNT;
4326 + cache = kmalloc(sizeof(struct mb_cache) +
4327 + indexes_count * sizeof(struct list_head), GFP_KERNEL);
4330 + cache->c_name = name;
4331 + cache->c_op.free = NULL;
4333 + cache->c_op.free = cache_op->free;
4334 + atomic_set(&cache->c_entry_count, 0);
4335 + cache->c_bucket_count = bucket_count;
4336 +#ifdef MB_CACHE_INDEXES_COUNT
4337 + mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4339 + cache->c_indexes_count = indexes_count;
4341 + cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4343 + if (!cache->c_block_hash)
4345 + for (n=0; n<bucket_count; n++)
4346 + INIT_LIST_HEAD(&cache->c_block_hash[n]);
4347 + for (m=0; m<indexes_count; m++) {
4348 + cache->c_indexes_hash[m] = kmalloc(bucket_count *
4349 + sizeof(struct list_head),
4351 + if (!cache->c_indexes_hash[m])
4353 + for (n=0; n<bucket_count; n++)
4354 + INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4356 + cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4357 + 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4358 + if (!cache->c_entry_cache)
4361 + spin_lock(&mb_cache_spinlock);
4362 + list_add(&cache->c_cache_list, &mb_cache_list);
4363 + spin_unlock(&mb_cache_spinlock);
4369 + kfree(cache->c_indexes_hash[m]);
4370 + if (cache->c_block_hash)
4371 + kfree(cache->c_block_hash);
4374 + MOD_DEC_USE_COUNT;
4380 + * mb_cache_shrink()
4382 + * Removes all cache entires of a device from the cache. All cache entries
4383 + * currently in use cannot be freed, and thus remain in the cache.
4385 + * @cache: which cache to shrink
4386 + * @dev: which device's cache entries to shrink
4389 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4391 + LIST_HEAD(free_list);
4392 + struct list_head *l, *ltmp;
4394 + spin_lock(&mb_cache_spinlock);
4395 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4396 + struct mb_cache_entry *ce =
4397 + list_entry(l, struct mb_cache_entry, e_lru_list);
4398 + if (ce->e_dev == dev) {
4399 + list_del(&ce->e_lru_list);
4400 + list_add_tail(&ce->e_lru_list, &free_list);
4401 + __mb_cache_entry_unhash(ce);
4404 + spin_unlock(&mb_cache_spinlock);
4405 + list_for_each_safe(l, ltmp, &free_list) {
4406 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4407 + e_lru_list), GFP_KERNEL);
4413 + * mb_cache_destroy()
4415 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4416 + * and then destroys it. If this was the last mbcache, un-registers the
4417 + * mbcache from kernel memory management.
4420 +mb_cache_destroy(struct mb_cache *cache)
4422 + LIST_HEAD(free_list);
4423 + struct list_head *l, *ltmp;
4426 + spin_lock(&mb_cache_spinlock);
4427 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4428 + struct mb_cache_entry *ce =
4429 + list_entry(l, struct mb_cache_entry, e_lru_list);
4430 + if (ce->e_cache == cache) {
4431 + list_del(&ce->e_lru_list);
4432 + list_add_tail(&ce->e_lru_list, &free_list);
4433 + __mb_cache_entry_unhash(ce);
4436 + list_del(&cache->c_cache_list);
4437 + spin_unlock(&mb_cache_spinlock);
4438 + list_for_each_safe(l, ltmp, &free_list) {
4439 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4440 + e_lru_list), GFP_KERNEL);
4443 + if (atomic_read(&cache->c_entry_count) > 0) {
4444 + mb_error("cache %s: %d orphaned entries",
4446 + atomic_read(&cache->c_entry_count));
4449 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4450 + /* We don't have kmem_cache_destroy() in 2.2.x */
4451 + kmem_cache_shrink(cache->c_entry_cache);
4453 + kmem_cache_destroy(cache->c_entry_cache);
4455 + for (n=0; n < mb_cache_indexes(cache); n++)
4456 + kfree(cache->c_indexes_hash[n]);
4457 + kfree(cache->c_block_hash);
4460 + MOD_DEC_USE_COUNT;
4465 + * mb_cache_entry_alloc()
4467 + * Allocates a new cache entry. The new entry will not be valid initially,
4468 + * and thus cannot be looked up yet. It should be filled with data, and
4469 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4470 + * if no more memory was available.
4472 +struct mb_cache_entry *
4473 +mb_cache_entry_alloc(struct mb_cache *cache)
4475 + struct mb_cache_entry *ce;
4477 + atomic_inc(&cache->c_entry_count);
4478 + ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4480 + INIT_LIST_HEAD(&ce->e_lru_list);
4481 + INIT_LIST_HEAD(&ce->e_block_list);
4482 + ce->e_cache = cache;
4483 + atomic_set(&ce->e_used, 1);
4490 + * mb_cache_entry_insert()
4492 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4493 + * the cache. After this, the cache entry can be looked up, but is not yet
4494 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4495 + * success, or -EBUSY if a cache entry for that device + inode exists
4496 + * already (this may happen after a failed lookup, if another process has
4497 + * inserted the same cache entry in the meantime).
4499 + * @dev: device the cache entry belongs to
4500 + * @block: block number
4501 + * @keys: array of additional keys. There must be indexes_count entries
4502 + * in the array (as specified when creating the cache).
4505 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4506 + unsigned long block, unsigned int keys[])
4508 + struct mb_cache *cache = ce->e_cache;
4509 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4510 + struct list_head *l;
4511 + int error = -EBUSY, n;
4513 + spin_lock(&mb_cache_spinlock);
4514 + list_for_each(l, &cache->c_block_hash[bucket]) {
4515 + struct mb_cache_entry *ce =
4516 + list_entry(l, struct mb_cache_entry, e_block_list);
4517 + if (ce->e_dev == dev && ce->e_block == block)
4520 + __mb_cache_entry_unhash(ce);
4522 + ce->e_block = block;
4523 + list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4524 + for (n=0; n<mb_cache_indexes(cache); n++) {
4525 + ce->e_indexes[n].o_key = keys[n];
4526 + bucket = keys[n] % cache->c_bucket_count;
4527 + list_add(&ce->e_indexes[n].o_list,
4528 + &cache->c_indexes_hash[n][bucket]);
4531 + spin_unlock(&mb_cache_spinlock);
4537 + * mb_cache_entry_release()
4539 + * Release a handle to a cache entry. When the last handle to a cache entry
4540 + * is released it is either freed (if it is invalid) or otherwise inserted
4541 + * in to the lru list.
4544 +mb_cache_entry_release(struct mb_cache_entry *ce)
4546 + spin_lock(&mb_cache_spinlock);
4547 + __mb_cache_entry_release_unlock(ce);
4552 + * mb_cache_entry_takeout()
4554 + * Take a cache entry out of the cache, making it invalid. The entry can later
4555 + * be re-inserted using mb_cache_entry_insert(), or released using
4556 + * mb_cache_entry_release().
4559 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4561 + spin_lock(&mb_cache_spinlock);
4562 + mb_assert(list_empty(&ce->e_lru_list));
4563 + __mb_cache_entry_unhash(ce);
4564 + spin_unlock(&mb_cache_spinlock);
4569 + * mb_cache_entry_free()
4571 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4572 + * mb_cache_entry_release().
4575 +mb_cache_entry_free(struct mb_cache_entry *ce)
4577 + spin_lock(&mb_cache_spinlock);
4578 + mb_assert(list_empty(&ce->e_lru_list));
4579 + __mb_cache_entry_unhash(ce);
4580 + __mb_cache_entry_release_unlock(ce);
4585 + * mb_cache_entry_dup()
4587 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4588 + * itself). After the call, both the old and the new handle must be released.
4590 +struct mb_cache_entry *
4591 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4593 + atomic_inc(&ce->e_used);
4599 + * mb_cache_entry_get()
4601 + * Get a cache entry by device / block number. (There can only be one entry
4602 + * in the cache per device and block.) Returns NULL if no such cache entry
4605 +struct mb_cache_entry *
4606 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4608 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4609 + struct list_head *l;
4610 + struct mb_cache_entry *ce;
4612 + spin_lock(&mb_cache_spinlock);
4613 + list_for_each(l, &cache->c_block_hash[bucket]) {
4614 + ce = list_entry(l, struct mb_cache_entry, e_block_list);
4615 + if (ce->e_dev == dev && ce->e_block == block) {
4616 + if (!list_empty(&ce->e_lru_list))
4617 + list_del_init(&ce->e_lru_list);
4618 + atomic_inc(&ce->e_used);
4625 + spin_unlock(&mb_cache_spinlock);
4629 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4631 +static struct mb_cache_entry *
4632 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4633 + int index, kdev_t dev, unsigned int key)
4635 + while (l != head) {
4636 + struct mb_cache_entry *ce =
4637 + list_entry(l, struct mb_cache_entry,
4638 + e_indexes[index].o_list);
4639 + if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4640 + if (!list_empty(&ce->e_lru_list))
4641 + list_del_init(&ce->e_lru_list);
4642 + atomic_inc(&ce->e_used);
4652 + * mb_cache_entry_find_first()
4654 + * Find the first cache entry on a given device with a certain key in
4655 + * an additional index. Additonal matches can be found with
4656 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4658 + * @cache: the cache to search
4659 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4660 + * @dev: the device the cache entry should belong to
4661 + * @key: the key in the index
4663 +struct mb_cache_entry *
4664 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4667 + unsigned int bucket = key % cache->c_bucket_count;
4668 + struct list_head *l;
4669 + struct mb_cache_entry *ce;
4671 + mb_assert(index < mb_cache_indexes(cache));
4672 + spin_lock(&mb_cache_spinlock);
4673 + l = cache->c_indexes_hash[index][bucket].next;
4674 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4676 + spin_unlock(&mb_cache_spinlock);
4682 + * mb_cache_entry_find_next()
4684 + * Find the next cache entry on a given device with a certain key in an
4685 + * additional index. Returns NULL if no match could be found. The previous
4686 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4687 + * be called like this:
4689 + * entry = mb_cache_entry_find_first();
4692 + * entry = mb_cache_entry_find_next(entry, ...);
4695 + * @prev: The previous match
4696 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4697 + * @dev: the device the cache entry should belong to
4698 + * @key: the key in the index
4700 +struct mb_cache_entry *
4701 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4704 + struct mb_cache *cache = prev->e_cache;
4705 + unsigned int bucket = key % cache->c_bucket_count;
4706 + struct list_head *l;
4707 + struct mb_cache_entry *ce;
4709 + mb_assert(index < mb_cache_indexes(cache));
4710 + spin_lock(&mb_cache_spinlock);
4711 + l = prev->e_indexes[index].o_list.next;
4712 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4714 + __mb_cache_entry_release_unlock(prev);
4718 +#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4720 +static int __init init_mbcache(void)
4722 + register_cache(&mb_cache_definition);
4726 +static void __exit exit_mbcache(void)
4728 + unregister_cache(&mb_cache_definition);
4731 +module_init(init_mbcache)
4732 +module_exit(exit_mbcache)
4734 Index: linux-2.4.19-pre1/fs/xattr.c
4735 ===================================================================
4736 --- linux-2.4.19-pre1.orig/fs/xattr.c 2003-01-30 13:24:37.000000000 +0300
4737 +++ linux-2.4.19-pre1/fs/xattr.c 2004-01-14 01:11:49.000000000 +0300
4742 + Extended attribute handling.
4744 + Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
4745 + Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
4747 +#include <linux/fs.h>
4748 +#include <linux/slab.h>
4749 +#include <linux/vmalloc.h>
4750 +#include <linux/smp_lock.h>
4751 +#include <linux/file.h>
4752 +#include <linux/xattr.h>
4753 +#include <asm/uaccess.h>
4756 + * Extended attribute memory allocation wrappers, originally
4757 + * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
4758 + * The vmalloc use here is very uncommon - extended attributes
4759 + * are supposed to be small chunks of metadata, and it is quite
4760 + * unusual to have very many extended attributes, so lists tend
4761 + * to be quite short as well. The 64K upper limit is derived
4762 + * from the extended attribute size limit used by XFS.
4763 + * Intentionally allow zero @size for value/list size requests.
4766 +xattr_alloc(size_t size, size_t limit)
4771 + return ERR_PTR(-E2BIG);
4773 + if (!size) /* size request, no buffer is needed */
4775 + else if (size <= PAGE_SIZE)
4776 + ptr = kmalloc((unsigned long) size, GFP_KERNEL);
4778 + ptr = vmalloc((unsigned long) size);
4780 + return ERR_PTR(-ENOMEM);
4785 +xattr_free(void *ptr, size_t size)
4787 + if (!size) /* size request, no buffer was needed */
4789 + else if (size <= PAGE_SIZE)
4796 + * Extended attribute SET operations
4799 +setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
4803 + char kname[XATTR_NAME_MAX + 1];
4805 + if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
4808 + error = strncpy_from_user(kname, name, sizeof(kname));
4809 + if (error == 0 || error == sizeof(kname))
4814 + kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
4815 + if (IS_ERR(kvalue))
4816 + return PTR_ERR(kvalue);
4818 + if (size > 0 && copy_from_user(kvalue, value, size)) {
4819 + xattr_free(kvalue, size);
4823 + error = -EOPNOTSUPP;
4824 + if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
4825 + down(&d->d_inode->i_sem);
4827 + error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
4829 + up(&d->d_inode->i_sem);
4832 + xattr_free(kvalue, size);
4837 +sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
4839 + struct nameidata nd;
4842 + error = user_path_walk(path, &nd);
4845 + error = setxattr(nd.dentry, name, value, size, flags);
4846 + path_release(&nd);
4851 +sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
4853 + struct nameidata nd;
4856 + error = user_path_walk_link(path, &nd);
4859 + error = setxattr(nd.dentry, name, value, size, flags);
4860 + path_release(&nd);
4865 +sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
4868 + int error = -EBADF;
4873 + error = setxattr(f->f_dentry, name, value, size, flags);
4879 + * Extended attribute GET operations
4882 +getxattr(struct dentry *d, char *name, void *value, size_t size)
4886 + char kname[XATTR_NAME_MAX + 1];
4888 + error = strncpy_from_user(kname, name, sizeof(kname));
4889 + if (error == 0 || error == sizeof(kname))
4894 + kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
4895 + if (IS_ERR(kvalue))
4896 + return PTR_ERR(kvalue);
4898 + error = -EOPNOTSUPP;
4899 + if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
4900 + down(&d->d_inode->i_sem);
4902 + error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
4904 + up(&d->d_inode->i_sem);
4907 + if (kvalue && error > 0)
4908 + if (copy_to_user(value, kvalue, error))
4910 + xattr_free(kvalue, size);
4915 +sys_getxattr(char *path, char *name, void *value, size_t size)
4917 + struct nameidata nd;
4920 + error = user_path_walk(path, &nd);
4923 + error = getxattr(nd.dentry, name, value, size);
4924 + path_release(&nd);
4929 +sys_lgetxattr(char *path, char *name, void *value, size_t size)
4931 + struct nameidata nd;
4934 + error = user_path_walk_link(path, &nd);
4937 + error = getxattr(nd.dentry, name, value, size);
4938 + path_release(&nd);
4943 +sys_fgetxattr(int fd, char *name, void *value, size_t size)
4946 + ssize_t error = -EBADF;
4951 + error = getxattr(f->f_dentry, name, value, size);
4957 + * Extended attribute LIST operations
4960 +listxattr(struct dentry *d, char *list, size_t size)
4965 + klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
4966 + if (IS_ERR(klist))
4967 + return PTR_ERR(klist);
4969 + error = -EOPNOTSUPP;
4970 + if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
4971 + down(&d->d_inode->i_sem);
4973 + error = d->d_inode->i_op->listxattr(d, klist, size);
4975 + up(&d->d_inode->i_sem);
4978 + if (klist && error > 0)
4979 + if (copy_to_user(list, klist, error))
4981 + xattr_free(klist, size);
4986 +sys_listxattr(char *path, char *list, size_t size)
4988 + struct nameidata nd;
4991 + error = user_path_walk(path, &nd);
4994 + error = listxattr(nd.dentry, list, size);
4995 + path_release(&nd);
5000 +sys_llistxattr(char *path, char *list, size_t size)
5002 + struct nameidata nd;
5005 + error = user_path_walk_link(path, &nd);
5008 + error = listxattr(nd.dentry, list, size);
5009 + path_release(&nd);
5014 +sys_flistxattr(int fd, char *list, size_t size)
5017 + ssize_t error = -EBADF;
5022 + error = listxattr(f->f_dentry, list, size);
5028 + * Extended attribute REMOVE operations
5031 +removexattr(struct dentry *d, char *name)
5034 + char kname[XATTR_NAME_MAX + 1];
5036 + error = strncpy_from_user(kname, name, sizeof(kname));
5037 + if (error == 0 || error == sizeof(kname))
5042 + error = -EOPNOTSUPP;
5043 + if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
5044 + down(&d->d_inode->i_sem);
5046 + error = d->d_inode->i_op->removexattr(d, kname);
5048 + up(&d->d_inode->i_sem);
5054 +sys_removexattr(char *path, char *name)
5056 + struct nameidata nd;
5059 + error = user_path_walk(path, &nd);
5062 + error = removexattr(nd.dentry, name);
5063 + path_release(&nd);
5068 +sys_lremovexattr(char *path, char *name)
5070 + struct nameidata nd;
5073 + error = user_path_walk_link(path, &nd);
5076 + error = removexattr(nd.dentry, name);
5077 + path_release(&nd);
5082 +sys_fremovexattr(int fd, char *name)
5085 + int error = -EBADF;
5090 + error = removexattr(f->f_dentry, name);
5094 Index: linux-2.4.19-pre1/include/asm-arm/unistd.h
5095 ===================================================================
5096 --- linux-2.4.19-pre1.orig/include/asm-arm/unistd.h 2001-08-12 22:14:00.000000000 +0400
5097 +++ linux-2.4.19-pre1/include/asm-arm/unistd.h 2004-01-14 01:11:49.000000000 +0300
5098 @@ -240,6 +240,18 @@
5099 #define __NR_mincore (__NR_SYSCALL_BASE+219)
5100 #define __NR_madvise (__NR_SYSCALL_BASE+220)
5101 #define __NR_fcntl64 (__NR_SYSCALL_BASE+221)
5102 +#define __NR_setxattr (__NR_SYSCALL_BASE+226)
5103 +#define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
5104 +#define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
5105 +#define __NR_getxattr (__NR_SYSCALL_BASE+229)
5106 +#define __NR_lgetxattr (__NR_SYSCALL_BASE+230)
5107 +#define __NR_fgetxattr (__NR_SYSCALL_BASE+231)
5108 +#define __NR_listxattr (__NR_SYSCALL_BASE+232)
5109 +#define __NR_llistxattr (__NR_SYSCALL_BASE+233)
5110 +#define __NR_flistxattr (__NR_SYSCALL_BASE+234)
5111 +#define __NR_removexattr (__NR_SYSCALL_BASE+235)
5112 +#define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
5113 +#define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
5116 * The following SWIs are ARM private.
5117 Index: linux-2.4.19-pre1/include/asm-ia64/unistd.h
5118 ===================================================================
5119 --- linux-2.4.19-pre1.orig/include/asm-ia64/unistd.h 2001-11-10 01:26:17.000000000 +0300
5120 +++ linux-2.4.19-pre1/include/asm-ia64/unistd.h 2004-01-14 01:11:49.000000000 +0300
5121 @@ -206,6 +206,18 @@
5122 #define __NR_getdents64 1214
5123 #define __NR_getunwind 1215
5124 #define __NR_readahead 1216
5125 +#define __NR_setxattr 1217
5126 +#define __NR_lsetxattr 1218
5127 +#define __NR_fsetxattr 1219
5128 +#define __NR_getxattr 1220
5129 +#define __NR_lgetxattr 1221
5130 +#define __NR_fgetxattr 1222
5131 +#define __NR_listxattr 1223
5132 +#define __NR_llistxattr 1224
5133 +#define __NR_flistxattr 1225
5134 +#define __NR_removexattr 1226
5135 +#define __NR_lremovexattr 1227
5136 +#define __NR_fremovexattr 1228
5138 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
5140 Index: linux-2.4.19-pre1/include/asm-s390/unistd.h
5141 ===================================================================
5142 --- linux-2.4.19-pre1.orig/include/asm-s390/unistd.h 2001-10-11 20:43:38.000000000 +0400
5143 +++ linux-2.4.19-pre1/include/asm-s390/unistd.h 2004-01-14 01:11:49.000000000 +0300
5144 @@ -211,6 +211,18 @@
5145 #define __NR_mincore 218
5146 #define __NR_madvise 219
5147 #define __NR_getdents64 220
5148 +#define __NR_setxattr 224
5149 +#define __NR_lsetxattr 225
5150 +#define __NR_fsetxattr 226
5151 +#define __NR_getxattr 227
5152 +#define __NR_lgetxattr 228
5153 +#define __NR_fgetxattr 229
5154 +#define __NR_listxattr 230
5155 +#define __NR_llistxattr 231
5156 +#define __NR_flistxattr 232
5157 +#define __NR_removexattr 233
5158 +#define __NR_lremovexattr 234
5159 +#define __NR_fremovexattr 235
5162 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
5163 Index: linux-2.4.19-pre1/include/asm-s390x/unistd.h
5164 ===================================================================
5165 --- linux-2.4.19-pre1.orig/include/asm-s390x/unistd.h 2001-10-11 20:43:38.000000000 +0400
5166 +++ linux-2.4.19-pre1/include/asm-s390x/unistd.h 2004-01-14 01:11:49.000000000 +0300
5167 @@ -181,6 +181,18 @@
5168 #define __NR_mincore 218
5169 #define __NR_madvise 219
5170 #define __NR_getdents64 220
5171 +#define __NR_setxattr 224
5172 +#define __NR_lsetxattr 225
5173 +#define __NR_fsetxattr 226
5174 +#define __NR_getxattr 227
5175 +#define __NR_lgetxattr 228
5176 +#define __NR_fgetxattr 229
5177 +#define __NR_listxattr 230
5178 +#define __NR_llistxattr 231
5179 +#define __NR_flistxattr 232
5180 +#define __NR_removexattr 233
5181 +#define __NR_lremovexattr 234
5182 +#define __NR_fremovexattr 235
5185 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
5186 Index: linux-2.4.19-pre1/include/asm-sparc/unistd.h
5187 ===================================================================
5188 --- linux-2.4.19-pre1.orig/include/asm-sparc/unistd.h 2001-10-21 21:36:54.000000000 +0400
5189 +++ linux-2.4.19-pre1/include/asm-sparc/unistd.h 2004-01-14 01:11:49.000000000 +0300
5190 @@ -184,24 +184,24 @@
5191 /* #define __NR_exportfs 166 SunOS Specific */
5192 #define __NR_mount 167 /* Common */
5193 #define __NR_ustat 168 /* Common */
5194 -/* #define __NR_semsys 169 SunOS Specific */
5195 -/* #define __NR_msgsys 170 SunOS Specific */
5196 -/* #define __NR_shmsys 171 SunOS Specific */
5197 -/* #define __NR_auditsys 172 SunOS Specific */
5198 -/* #define __NR_rfssys 173 SunOS Specific */
5199 +#define __NR_setxattr 169 /* SunOS: semsys */
5200 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
5201 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
5202 +#define __NR_getxattr 172 /* SunOS: auditsys */
5203 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
5204 #define __NR_getdents 174 /* Common */
5205 #define __NR_setsid 175 /* Common */
5206 #define __NR_fchdir 176 /* Common */
5207 -/* #define __NR_fchroot 177 SunOS Specific */
5208 -/* #define __NR_vpixsys 178 SunOS Specific */
5209 -/* #define __NR_aioread 179 SunOS Specific */
5210 -/* #define __NR_aiowrite 180 SunOS Specific */
5211 -/* #define __NR_aiowait 181 SunOS Specific */
5212 -/* #define __NR_aiocancel 182 SunOS Specific */
5213 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
5214 +#define __NR_listxattr 178 /* SunOS: vpixsys */
5215 +#define __NR_llistxattr 179 /* SunOS: aioread */
5216 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
5217 +#define __NR_removexattr 181 /* SunOS: aiowait */
5218 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
5219 #define __NR_sigpending 183 /* Common */
5220 #define __NR_query_module 184 /* Linux Specific */
5221 #define __NR_setpgid 185 /* Common */
5222 -/* #define __NR_pathconf 186 SunOS Specific */
5223 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
5224 /* #define __NR_fpathconf 187 SunOS Specific */
5225 /* #define __NR_sysconf 188 SunOS Specific */
5226 #define __NR_uname 189 /* Linux Specific */
5227 Index: linux-2.4.19-pre1/include/asm-sparc64/unistd.h
5228 ===================================================================
5229 --- linux-2.4.19-pre1.orig/include/asm-sparc64/unistd.h 2001-10-21 21:36:54.000000000 +0400
5230 +++ linux-2.4.19-pre1/include/asm-sparc64/unistd.h 2004-01-14 01:11:49.000000000 +0300
5231 @@ -184,24 +184,24 @@
5232 /* #define __NR_exportfs 166 SunOS Specific */
5233 #define __NR_mount 167 /* Common */
5234 #define __NR_ustat 168 /* Common */
5235 -/* #define __NR_semsys 169 SunOS Specific */
5236 -/* #define __NR_msgsys 170 SunOS Specific */
5237 -/* #define __NR_shmsys 171 SunOS Specific */
5238 -/* #define __NR_auditsys 172 SunOS Specific */
5239 -/* #define __NR_rfssys 173 SunOS Specific */
5240 +#define __NR_setxattr 169 /* SunOS: semsys */
5241 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
5242 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
5243 +#define __NR_getxattr 172 /* SunOS: auditsys */
5244 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
5245 #define __NR_getdents 174 /* Common */
5246 #define __NR_setsid 175 /* Common */
5247 #define __NR_fchdir 176 /* Common */
5248 -/* #define __NR_fchroot 177 SunOS Specific */
5249 -/* #define __NR_vpixsys 178 SunOS Specific */
5250 -/* #define __NR_aioread 179 SunOS Specific */
5251 -/* #define __NR_aiowrite 180 SunOS Specific */
5252 -/* #define __NR_aiowait 181 SunOS Specific */
5253 -/* #define __NR_aiocancel 182 SunOS Specific */
5254 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
5255 +#define __NR_listxattr 178 /* SunOS: vpixsys */
5256 +#define __NR_llistxattr 179 /* SunOS: aioread */
5257 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
5258 +#define __NR_removexattr 181 /* SunOS: aiowait */
5259 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
5260 #define __NR_sigpending 183 /* Common */
5261 #define __NR_query_module 184 /* Linux Specific */
5262 #define __NR_setpgid 185 /* Common */
5263 -/* #define __NR_pathconf 186 SunOS Specific */
5264 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
5265 /* #define __NR_fpathconf 187 SunOS Specific */
5266 /* #define __NR_sysconf 188 SunOS Specific */
5267 #define __NR_uname 189 /* Linux Specific */
5268 Index: linux-2.4.19-pre1/include/linux/cache_def.h
5269 ===================================================================
5270 --- linux-2.4.19-pre1.orig/include/linux/cache_def.h 2003-01-30 13:24:37.000000000 +0300
5271 +++ linux-2.4.19-pre1/include/linux/cache_def.h 2004-01-14 01:11:49.000000000 +0300
5274 + * linux/cache_def.h
5275 + * Handling of caches defined in drivers, filesystems, ...
5277 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5280 +struct cache_definition {
5282 + void (*shrink)(int, unsigned int);
5283 + struct list_head link;
5286 +extern void register_cache(struct cache_definition *);
5287 +extern void unregister_cache(struct cache_definition *);
5288 Index: linux-2.4.19-pre1/include/linux/errno.h
5289 ===================================================================
5290 --- linux-2.4.19-pre1.orig/include/linux/errno.h 2001-02-10 01:46:13.000000000 +0300
5291 +++ linux-2.4.19-pre1/include/linux/errno.h 2004-01-14 01:11:49.000000000 +0300
5296 +/* Defined for extended attributes */
5297 +#define ENOATTR ENODATA /* No such attribute */
5298 +#define ENOTSUP EOPNOTSUPP /* Operation not supported */
5301 Index: linux-2.4.19-pre1/include/linux/ext2_fs.h
5302 ===================================================================
5303 --- linux-2.4.19-pre1.orig/include/linux/ext2_fs.h 2001-11-22 22:46:52.000000000 +0300
5304 +++ linux-2.4.19-pre1/include/linux/ext2_fs.h 2004-01-14 01:18:00.000000000 +0300
5307 #define EXT2_BAD_INO 1 /* Bad blocks inode */
5308 #define EXT2_ROOT_INO 2 /* Root inode */
5309 -#define EXT2_ACL_IDX_INO 3 /* ACL inode */
5310 -#define EXT2_ACL_DATA_INO 4 /* ACL inode */
5311 #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
5312 #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
5316 # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5318 -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
5319 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
5321 # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5322 @@ -121,28 +118,6 @@
5328 -struct ext2_acl_header /* Header of Access Control Lists */
5331 - __u32 aclh_file_count;
5332 - __u32 aclh_acle_count;
5333 - __u32 aclh_first_acle;
5336 -struct ext2_acl_entry /* Access Control List Entry */
5339 - __u16 acle_perms; /* Access permissions */
5340 - __u16 acle_type; /* Type of entry */
5341 - __u16 acle_tag; /* User or group identity */
5343 - __u32 acle_next; /* Pointer on next entry for the */
5344 - /* same inode or on next free entry */
5348 * Structure of a blocks group descriptor
5350 struct ext2_group_desc
5352 #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
5353 #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
5354 #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
5355 +#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5357 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
5358 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
5362 #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
5363 +#define EXT2_I(inode) (&((inode)->u.ext2_i))
5365 /* Assume that user mode programs are passing in an ext2fs superblock, not
5366 * a kernel struct super_block. This will allow us to call the feature-test
5368 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
5369 #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
5371 -#define EXT2_FEATURE_COMPAT_SUPP 0
5372 +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5373 #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
5374 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5375 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
5376 @@ -623,8 +600,10 @@
5379 extern struct inode_operations ext2_dir_inode_operations;
5380 +extern struct inode_operations ext2_special_inode_operations;
5383 +extern struct inode_operations ext2_symlink_inode_operations;
5384 extern struct inode_operations ext2_fast_symlink_inode_operations;
5386 #endif /* __KERNEL__ */
5387 Index: linux-2.4.19-pre1/include/linux/ext2_xattr.h
5388 ===================================================================
5389 --- linux-2.4.19-pre1.orig/include/linux/ext2_xattr.h 2003-01-30 13:24:37.000000000 +0300
5390 +++ linux-2.4.19-pre1/include/linux/ext2_xattr.h 2004-01-14 01:18:01.000000000 +0300
5393 + File: linux/ext2_xattr.h
5395 + On-disk format of extended attributes for the ext2 filesystem.
5397 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5400 +#include <linux/config.h>
5401 +#include <linux/init.h>
5402 +#include <linux/xattr.h>
5404 +/* Magic value in attribute blocks */
5405 +#define EXT2_XATTR_MAGIC 0xEA020000
5407 +/* Maximum number of references to one attribute block */
5408 +#define EXT2_XATTR_REFCOUNT_MAX 1024
5411 +#define EXT2_XATTR_INDEX_MAX 10
5412 +#define EXT2_XATTR_INDEX_USER 1
5413 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
5414 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5416 +struct ext2_xattr_header {
5417 + __u32 h_magic; /* magic number for identification */
5418 + __u32 h_refcount; /* reference count */
5419 + __u32 h_blocks; /* number of disk blocks used */
5420 + __u32 h_hash; /* hash value of all attributes */
5421 + __u32 h_reserved[4]; /* zero right now */
5424 +struct ext2_xattr_entry {
5425 + __u8 e_name_len; /* length of name */
5426 + __u8 e_name_index; /* attribute name index */
5427 + __u16 e_value_offs; /* offset in disk block of value */
5428 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5429 + __u32 e_value_size; /* size of attribute value */
5430 + __u32 e_hash; /* hash value of name and value */
5431 + char e_name[0]; /* attribute name */
5434 +#define EXT2_XATTR_PAD_BITS 2
5435 +#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
5436 +#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
5437 +#define EXT2_XATTR_LEN(name_len) \
5438 + (((name_len) + EXT2_XATTR_ROUND + \
5439 + sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
5440 +#define EXT2_XATTR_NEXT(entry) \
5441 + ( (struct ext2_xattr_entry *)( \
5442 + (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
5443 +#define EXT2_XATTR_SIZE(size) \
5444 + (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
5448 +# ifdef CONFIG_EXT2_FS_XATTR
5450 +struct ext2_xattr_handler {
5452 + size_t (*list)(char *list, struct inode *inode, const char *name,
5454 + int (*get)(struct inode *inode, const char *name, void *buffer,
5456 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5457 + size_t size, int flags);
5460 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
5461 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
5463 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
5464 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
5465 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
5466 +extern int ext2_removexattr(struct dentry *, const char *);
5468 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
5469 +extern int ext2_xattr_list(struct inode *, char *, size_t);
5470 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
5472 +extern void ext2_xattr_delete_inode(struct inode *);
5473 +extern void ext2_xattr_put_super(struct super_block *);
5475 +extern int init_ext2_xattr(void) __init;
5476 +extern void exit_ext2_xattr(void);
5478 +# else /* CONFIG_EXT2_FS_XATTR */
5479 +# define ext2_setxattr NULL
5480 +# define ext2_getxattr NULL
5481 +# define ext2_listxattr NULL
5482 +# define ext2_removexattr NULL
5485 +ext2_xattr_get(struct inode *inode, int name_index,
5486 + const char *name, void *buffer, size_t size)
5492 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
5498 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
5499 + const void *value, size_t size, int flags)
5505 +ext2_xattr_delete_inode(struct inode *inode)
5510 +ext2_xattr_put_super(struct super_block *sb)
5515 +init_ext2_xattr(void)
5521 +exit_ext2_xattr(void)
5525 +# endif /* CONFIG_EXT2_FS_XATTR */
5527 +# ifdef CONFIG_EXT2_FS_XATTR_USER
5529 +extern int init_ext2_xattr_user(void) __init;
5530 +extern void exit_ext2_xattr_user(void);
5532 +# else /* CONFIG_EXT2_FS_XATTR_USER */
5535 +init_ext2_xattr_user(void)
5541 +exit_ext2_xattr_user(void)
5545 +# endif /* CONFIG_EXT2_FS_XATTR_USER */
5547 +#endif /* __KERNEL__ */
5549 Index: linux-2.4.19-pre1/include/linux/ext3_fs.h
5550 ===================================================================
5551 --- linux-2.4.19-pre1.orig/include/linux/ext3_fs.h 2004-01-14 01:11:49.000000000 +0300
5552 +++ linux-2.4.19-pre1/include/linux/ext3_fs.h 2004-01-14 01:11:49.000000000 +0300
5555 #define EXT3_BAD_INO 1 /* Bad blocks inode */
5556 #define EXT3_ROOT_INO 2 /* Root inode */
5557 -#define EXT3_ACL_IDX_INO 3 /* ACL inode */
5558 -#define EXT3_ACL_DATA_INO 4 /* ACL inode */
5559 #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
5560 #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
5561 #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
5564 # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5566 -#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
5567 #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
5569 # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5570 @@ -129,28 +126,6 @@
5576 -struct ext3_acl_header /* Header of Access Control Lists */
5579 - __u32 aclh_file_count;
5580 - __u32 aclh_acle_count;
5581 - __u32 aclh_first_acle;
5584 -struct ext3_acl_entry /* Access Control List Entry */
5587 - __u16 acle_perms; /* Access permissions */
5588 - __u16 acle_type; /* Type of entry */
5589 - __u16 acle_tag; /* User or group identity */
5591 - __u32 acle_next; /* Pointer on next entry for the */
5592 - /* same inode or on next free entry */
5596 * Structure of a blocks group descriptor
5598 struct ext3_group_desc
5600 #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
5601 #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
5602 #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
5603 +#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5605 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
5606 #ifndef _LINUX_EXT2_FS_H
5608 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
5609 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
5611 -#define EXT3_FEATURE_COMPAT_SUPP 0
5612 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5613 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
5614 EXT3_FEATURE_INCOMPAT_RECOVER)
5615 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5617 extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
5620 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
5621 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
5622 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
5624 @@ -771,8 +748,10 @@
5627 extern struct inode_operations ext3_dir_inode_operations;
5628 +extern struct inode_operations ext3_special_inode_operations;
5631 +extern struct inode_operations ext3_symlink_inode_operations;
5632 extern struct inode_operations ext3_fast_symlink_inode_operations;
5635 Index: linux-2.4.19-pre1/include/linux/ext3_jbd.h
5636 ===================================================================
5637 --- linux-2.4.19-pre1.orig/include/linux/ext3_jbd.h 2004-01-14 01:11:49.000000000 +0300
5638 +++ linux-2.4.19-pre1/include/linux/ext3_jbd.h 2004-01-14 01:18:04.000000000 +0300
5641 #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
5643 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5644 + * and two group and summaries. */
5646 +#define EXT3_XATTR_TRANS_BLOCKS 8
5648 /* Define the minimum size for a transaction which modifies data. This
5649 * needs to take into account the fact that we may end up modifying two
5650 * quota files too (one for the group, one for the user quota). The
5651 * superblock only gets updated once, of course, so don't bother
5652 * counting that again for the quota updates. */
5654 -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5655 +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5656 + EXT3_XATTR_TRANS_BLOCKS - 2)
5658 extern int ext3_writepage_trans_blocks(struct inode *inode);
5660 Index: linux-2.4.19-pre1/include/linux/ext3_xattr.h
5661 ===================================================================
5662 --- linux-2.4.19-pre1.orig/include/linux/ext3_xattr.h 2003-01-30 13:24:37.000000000 +0300
5663 +++ linux-2.4.19-pre1/include/linux/ext3_xattr.h 2004-01-14 01:11:49.000000000 +0300
5666 + File: linux/ext3_xattr.h
5668 + On-disk format of extended attributes for the ext3 filesystem.
5670 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5673 +#include <linux/config.h>
5674 +#include <linux/init.h>
5675 +#include <linux/xattr.h>
5677 +/* Magic value in attribute blocks */
5678 +#define EXT3_XATTR_MAGIC 0xEA020000
5680 +/* Maximum number of references to one attribute block */
5681 +#define EXT3_XATTR_REFCOUNT_MAX 1024
5684 +#define EXT3_XATTR_INDEX_MAX 10
5685 +#define EXT3_XATTR_INDEX_USER 1
5686 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
5687 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5689 +struct ext3_xattr_header {
5690 + __u32 h_magic; /* magic number for identification */
5691 + __u32 h_refcount; /* reference count */
5692 + __u32 h_blocks; /* number of disk blocks used */
5693 + __u32 h_hash; /* hash value of all attributes */
5694 + __u32 h_reserved[4]; /* zero right now */
5697 +struct ext3_xattr_entry {
5698 + __u8 e_name_len; /* length of name */
5699 + __u8 e_name_index; /* attribute name index */
5700 + __u16 e_value_offs; /* offset in disk block of value */
5701 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5702 + __u32 e_value_size; /* size of attribute value */
5703 + __u32 e_hash; /* hash value of name and value */
5704 + char e_name[0]; /* attribute name */
5707 +#define EXT3_XATTR_PAD_BITS 2
5708 +#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
5709 +#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
5710 +#define EXT3_XATTR_LEN(name_len) \
5711 + (((name_len) + EXT3_XATTR_ROUND + \
5712 + sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5713 +#define EXT3_XATTR_NEXT(entry) \
5714 + ( (struct ext3_xattr_entry *)( \
5715 + (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5716 +#define EXT3_XATTR_SIZE(size) \
5717 + (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5721 +# ifdef CONFIG_EXT3_FS_XATTR
5723 +struct ext3_xattr_handler {
5725 + size_t (*list)(char *list, struct inode *inode, const char *name,
5727 + int (*get)(struct inode *inode, const char *name, void *buffer,
5729 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5730 + size_t size, int flags);
5733 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5734 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5736 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5737 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5738 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5739 +extern int ext3_removexattr(struct dentry *, const char *);
5741 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5742 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5743 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5745 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5746 +extern void ext3_xattr_put_super(struct super_block *);
5748 +extern int init_ext3_xattr(void) __init;
5749 +extern void exit_ext3_xattr(void);
5751 +# else /* CONFIG_EXT3_FS_XATTR */
5752 +# define ext3_setxattr NULL
5753 +# define ext3_getxattr NULL
5754 +# define ext3_listxattr NULL
5755 +# define ext3_removexattr NULL
5758 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5759 + void *buffer, size_t size)
5765 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5771 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5772 + const char *name, const void *value, size_t size, int flags)
5778 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5783 +ext3_xattr_put_super(struct super_block *sb)
5788 +init_ext3_xattr(void)
5794 +exit_ext3_xattr(void)
5798 +# endif /* CONFIG_EXT3_FS_XATTR */
5800 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5802 +extern int init_ext3_xattr_user(void) __init;
5803 +extern void exit_ext3_xattr_user(void);
5805 +# else /* CONFIG_EXT3_FS_XATTR_USER */
5808 +init_ext3_xattr_user(void)
5814 +exit_ext3_xattr_user(void)
5818 +#endif /* CONFIG_EXT3_FS_XATTR_USER */
5820 +#endif /* __KERNEL__ */
5822 Index: linux-2.4.19-pre1/include/linux/fs.h
5823 ===================================================================
5824 --- linux-2.4.19-pre1.orig/include/linux/fs.h 2004-01-14 01:11:48.000000000 +0300
5825 +++ linux-2.4.19-pre1/include/linux/fs.h 2004-01-14 01:11:49.000000000 +0300
5826 @@ -872,6 +872,10 @@
5827 int (*setattr) (struct dentry *, struct iattr *);
5828 int (*setattr_raw) (struct inode *, struct iattr *);
5829 int (*getattr) (struct dentry *, struct iattr *);
5830 + int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5831 + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5832 + ssize_t (*listxattr) (struct dentry *, char *, size_t);
5833 + int (*removexattr) (struct dentry *, const char *);
5837 Index: linux-2.4.19-pre1/include/linux/mbcache.h
5838 ===================================================================
5839 --- linux-2.4.19-pre1.orig/include/linux/mbcache.h 2003-01-30 13:24:37.000000000 +0300
5840 +++ linux-2.4.19-pre1/include/linux/mbcache.h 2004-01-14 01:11:49.000000000 +0300
5843 + File: linux/mbcache.h
5845 + (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5848 +/* Hardwire the number of additional indexes */
5849 +#define MB_CACHE_INDEXES_COUNT 1
5851 +struct mb_cache_entry;
5853 +struct mb_cache_op {
5854 + int (*free)(struct mb_cache_entry *, int);
5858 + struct list_head c_cache_list;
5859 + const char *c_name;
5860 + struct mb_cache_op c_op;
5861 + atomic_t c_entry_count;
5862 + int c_bucket_count;
5863 +#ifndef MB_CACHE_INDEXES_COUNT
5864 + int c_indexes_count;
5866 + kmem_cache_t *c_entry_cache;
5867 + struct list_head *c_block_hash;
5868 + struct list_head *c_indexes_hash[0];
5871 +struct mb_cache_entry_index {
5872 + struct list_head o_list;
5873 + unsigned int o_key;
5876 +struct mb_cache_entry {
5877 + struct list_head e_lru_list;
5878 + struct mb_cache *e_cache;
5881 + unsigned long e_block;
5882 + struct list_head e_block_list;
5883 + struct mb_cache_entry_index e_indexes[0];
5886 +/* Functions on caches */
5888 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5890 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5891 +void mb_cache_destroy(struct mb_cache *);
5893 +/* Functions on cache entries */
5895 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5896 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5898 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5899 +void mb_cache_entry_release(struct mb_cache_entry *);
5900 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5901 +void mb_cache_entry_free(struct mb_cache_entry *);
5902 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5903 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5905 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5906 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5907 + kdev_t, unsigned int);
5908 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5909 + kdev_t, unsigned int);
5911 Index: linux-2.4.19-pre1/include/linux/xattr.h
5912 ===================================================================
5913 --- linux-2.4.19-pre1.orig/include/linux/xattr.h 2003-01-30 13:24:37.000000000 +0300
5914 +++ linux-2.4.19-pre1/include/linux/xattr.h 2004-01-14 01:11:49.000000000 +0300
5917 + File: linux/xattr.h
5919 + Extended attributes handling.
5921 + Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
5922 + Copyright (c) 2001-2002 Silicon Graphics, Inc. All Rights Reserved.
5924 +#ifndef _LINUX_XATTR_H
5925 +#define _LINUX_XATTR_H
5927 +#define XATTR_CREATE 0x1 /* set the value, fail if attr already exists */
5928 +#define XATTR_REPLACE 0x2 /* set the value, fail if attr does not exist */
5930 +#endif /* _LINUX_XATTR_H */
5931 Index: linux-2.4.19-pre1/include/linux/kernel.h
5932 ===================================================================
5933 --- linux-2.4.19-pre1.orig/include/linux/kernel.h 2004-01-14 01:10:37.000000000 +0300
5934 +++ linux-2.4.19-pre1/include/linux/kernel.h 2004-01-14 01:16:51.000000000 +0300
5936 #include <linux/linkage.h>
5937 #include <linux/stddef.h>
5938 #include <linux/types.h>
5939 +#include <linux/compiler.h>
5941 /* Optimization barrier */
5942 /* The "volatile" is due to gcc bugs */
5943 Index: linux-2.4.19-pre1/include/linux/limits.h
5944 ===================================================================
5945 --- linux-2.4.19-pre1.orig/include/linux/limits.h 2004-01-14 01:10:37.000000000 +0300
5946 +++ linux-2.4.19-pre1/include/linux/limits.h 2004-01-14 01:22:08.000000000 +0300
5948 #define NAME_MAX 255 /* # chars in a file name */
5949 #define PATH_MAX 4096 /* # chars in a path name including nul */
5950 #define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
5951 +#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
5952 +#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
5953 +#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
5955 #define RTSIG_MAX 32
5957 Index: linux-2.4.19-pre1/kernel/ksyms.c
5958 ===================================================================
5959 --- linux-2.4.19-pre1.orig/kernel/ksyms.c 2004-01-14 01:11:48.000000000 +0300
5960 +++ linux-2.4.19-pre1/kernel/ksyms.c 2004-01-14 01:11:49.000000000 +0300
5963 #include <linux/config.h>
5964 #include <linux/slab.h>
5965 +#include <linux/cache_def.h>
5966 #include <linux/module.h>
5967 #include <linux/blkdev.h>
5968 #include <linux/cdrom.h>
5970 EXPORT_SYMBOL(exit_files);
5971 EXPORT_SYMBOL(exit_fs);
5972 EXPORT_SYMBOL(exit_sighand);
5973 +EXPORT_SYMBOL(copy_fs_struct);
5975 /* internal kernel memory management */
5976 EXPORT_SYMBOL(_alloc_pages);
5978 EXPORT_SYMBOL(kmem_cache_shrink);
5979 EXPORT_SYMBOL(kmem_cache_alloc);
5980 EXPORT_SYMBOL(kmem_cache_free);
5981 +EXPORT_SYMBOL(register_cache);
5982 +EXPORT_SYMBOL(unregister_cache);
5983 EXPORT_SYMBOL(kmalloc);
5984 EXPORT_SYMBOL(kfree);
5985 EXPORT_SYMBOL(vfree);
5986 Index: linux-2.4.19-pre1/mm/vmscan.c
5987 ===================================================================
5988 --- linux-2.4.19-pre1.orig/mm/vmscan.c 2004-01-14 01:10:37.000000000 +0300
5989 +++ linux-2.4.19-pre1/mm/vmscan.c 2004-01-14 01:11:49.000000000 +0300
5991 #include <linux/kernel_stat.h>
5992 #include <linux/swap.h>
5993 #include <linux/swapctl.h>
5994 +#include <linux/cache_def.h>
5995 #include <linux/smp_lock.h>
5996 #include <linux/pagemap.h>
5997 #include <linux/init.h>
6000 #define DEF_PRIORITY (6)
6002 +static DECLARE_MUTEX(other_caches_sem);
6003 +static LIST_HEAD(cache_definitions);
6005 +void register_cache(struct cache_definition *cache)
6007 + down(&other_caches_sem);
6008 + list_add(&cache->link, &cache_definitions);
6009 + up(&other_caches_sem);
6012 +void unregister_cache(struct cache_definition *cache)
6014 + down(&other_caches_sem);
6015 + list_del(&cache->link);
6016 + up(&other_caches_sem);
6019 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
6021 + struct list_head *p;
6023 + if (down_trylock(&other_caches_sem))
6026 + list_for_each_prev(p, &cache_definitions) {
6027 + struct cache_definition *cache =
6028 + list_entry(p, struct cache_definition, link);
6030 + cache->shrink(priority, gfp_mask);
6032 + up(&other_caches_sem);
6036 * The swap-out function returns 1 if it successfully
6037 * scanned all the pages it was asked to (`count').
6040 shrink_dcache_memory(priority, gfp_mask);
6041 shrink_icache_memory(priority, gfp_mask);
6042 + shrink_other_caches(priority, gfp_mask);
6044 shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);