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 is not set
160 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
161 +# CONFIG_EXT3_FS_XATTR_USER is not set
162 +# CONFIG_EXT2_FS_XATTR is not set
163 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
164 +# CONFIG_EXT2_FS_XATTR_USER is not set
165 +# CONFIG_FS_MBCACHE is not set
167 # CONFIG_UID16 is not set
168 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
169 Index: linux-2.4.19-pre1/arch/alpha/kernel/entry.S
170 ===================================================================
171 --- linux-2.4.19-pre1.orig/arch/alpha/kernel/entry.S 2001-11-10 00:45:35.000000000 +0300
172 +++ linux-2.4.19-pre1/arch/alpha/kernel/entry.S 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 is not set
199 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
200 +# CONFIG_EXT3_FS_XATTR_USER is not set
201 +# CONFIG_EXT2_FS_XATTR is not set
202 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
203 +# CONFIG_EXT2_FS_XATTR_USER is not set
204 +# CONFIG_FS_MBCACHE is not set
206 # CONFIG_EISA is not set
207 # CONFIG_SBUS is not set
208 Index: linux-2.4.19-pre1/arch/arm/kernel/calls.S
209 ===================================================================
210 --- linux-2.4.19-pre1.orig/arch/arm/kernel/calls.S 2001-10-08 21:39:18.000000000 +0400
211 +++ linux-2.4.19-pre1/arch/arm/kernel/calls.S 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 is not set
244 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
245 +# CONFIG_EXT3_FS_XATTR_USER is not set
246 +# CONFIG_EXT2_FS_XATTR is not set
247 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
248 +# CONFIG_EXT2_FS_XATTR_USER is not set
249 +# CONFIG_FS_MBCACHE is not set
252 # CONFIG_SBUS is not set
253 Index: linux-2.4.19-pre1/arch/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 is not set
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 is not set
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 is not set
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 is not set
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 is not set
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_EXT3_FS_XATTR is not set
411 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
412 +# CONFIG_EXT3_FS_XATTR_USER is not set
413 +# CONFIG_EXT2_FS_XATTR is not set
414 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
415 +# CONFIG_EXT2_FS_XATTR_USER is not set
416 +# CONFIG_FS_MBCACHE is not set
417 # CONFIG_UID16 is not set
418 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
419 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
420 Index: linux-2.4.19-pre1/arch/s390/defconfig
421 ===================================================================
422 --- linux-2.4.19-pre1.orig/arch/s390/defconfig 2004-01-14 01:10:36.000000000 +0300
423 +++ linux-2.4.19-pre1/arch/s390/defconfig 2004-01-14 01:11:49.000000000 +0300
426 # Automatically generated make config: don't edit
428 +# CONFIG_EXT3_FS_XATTR is not set
429 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
430 +# CONFIG_EXT3_FS_XATTR_USER is not set
431 +# CONFIG_EXT2_FS_XATTR is not set
432 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
433 +# CONFIG_EXT2_FS_XATTR_USER is not set
434 +# CONFIG_FS_MBCACHE is not set
435 # CONFIG_ISA is not set
436 # CONFIG_EISA is not set
437 # CONFIG_MCA is not set
438 Index: linux-2.4.19-pre1/arch/s390/kernel/entry.S
439 ===================================================================
440 --- linux-2.4.19-pre1.orig/arch/s390/kernel/entry.S 2004-01-14 01:10:36.000000000 +0300
441 +++ linux-2.4.19-pre1/arch/s390/kernel/entry.S 2004-01-14 01:11:49.000000000 +0300
444 .long sys_ni_syscall /* 222 - reserved for posix_acl */
445 .long sys_ni_syscall /* 223 - reserved for posix_acl */
446 - .long sys_ni_syscall /* 224 - reserved for posix_acl */
449 + .long sys_lsetxattr /* 225 */
450 + .long sys_fsetxattr
452 + .long sys_lgetxattr
453 + .long sys_fgetxattr
454 + .long sys_listxattr /* 230 */
455 + .long sys_llistxattr
456 + .long sys_flistxattr
457 + .long sys_removexattr
458 + .long sys_lremovexattr
459 + .long sys_fremovexattr /* 235 */
464 Index: linux-2.4.19-pre1/arch/s390x/defconfig
465 ===================================================================
466 --- linux-2.4.19-pre1.orig/arch/s390x/defconfig 2004-01-14 01:10:36.000000000 +0300
467 +++ linux-2.4.19-pre1/arch/s390x/defconfig 2004-01-14 01:11:49.000000000 +0300
470 # Automatically generated make config: don't edit
472 +# CONFIG_EXT3_FS_XATTR is not set
473 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
474 +# CONFIG_EXT3_FS_XATTR_USER is not set
475 +# CONFIG_EXT2_FS_XATTR is not set
476 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
477 +# CONFIG_EXT2_FS_XATTR_USER is not set
478 +# CONFIG_FS_MBCACHE is not set
479 # CONFIG_ISA is not set
480 # CONFIG_EISA is not set
481 # CONFIG_MCA is not set
482 Index: linux-2.4.19-pre1/arch/s390x/kernel/entry.S
483 ===================================================================
484 --- linux-2.4.19-pre1.orig/arch/s390x/kernel/entry.S 2004-01-14 01:10:36.000000000 +0300
485 +++ linux-2.4.19-pre1/arch/s390x/kernel/entry.S 2004-01-14 01:11:49.000000000 +0300
487 .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
488 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 222 - reserved for posix_acl */
489 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 223 - reserved for posix_acl */
490 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for posix_acl */
492 + .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
493 + .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
494 + .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
495 + .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
496 + .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
497 + .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
498 + .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
499 + .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
500 + .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
501 + .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
502 + .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
503 + .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
505 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
508 Index: linux-2.4.19-pre1/arch/s390x/kernel/wrapper32.S
509 ===================================================================
510 --- linux-2.4.19-pre1.orig/arch/s390x/kernel/wrapper32.S 2004-01-14 01:10:36.000000000 +0300
511 +++ linux-2.4.19-pre1/arch/s390x/kernel/wrapper32.S 2004-01-14 01:11:49.000000000 +0300
512 @@ -1091,3 +1091,95 @@
513 llgtr %r3,%r3 # struct stat64 *
515 jg sys32_fstat64 # branch to system call
517 + .globl sys32_setxattr_wrapper
518 +sys32_setxattr_wrapper:
519 + llgtr %r2,%r2 # char *
520 + llgtr %r3,%r3 # char *
521 + llgtr %r4,%r4 # void *
522 + llgfr %r5,%r5 # size_t
526 + .globl sys32_lsetxattr_wrapper
527 +sys32_lsetxattr_wrapper:
528 + llgtr %r2,%r2 # char *
529 + llgtr %r3,%r3 # char *
530 + llgtr %r4,%r4 # void *
531 + llgfr %r5,%r5 # size_t
535 + .globl sys32_fsetxattr_wrapper
536 +sys32_fsetxattr_wrapper:
538 + llgtr %r3,%r3 # char *
539 + llgtr %r4,%r4 # void *
540 + llgfr %r5,%r5 # size_t
544 + .globl sys32_getxattr_wrapper
545 +sys32_getxattr_wrapper:
546 + llgtr %r2,%r2 # char *
547 + llgtr %r3,%r3 # char *
548 + llgtr %r4,%r4 # void *
549 + llgfr %r5,%r5 # size_t
552 + .globl sys32_lgetxattr_wrapper
553 +sys32_lgetxattr_wrapper:
554 + llgtr %r2,%r2 # char *
555 + llgtr %r3,%r3 # char *
556 + llgtr %r4,%r4 # void *
557 + llgfr %r5,%r5 # size_t
560 + .globl sys32_fgetxattr_wrapper
561 +sys32_fgetxattr_wrapper:
563 + llgtr %r3,%r3 # char *
564 + llgtr %r4,%r4 # void *
565 + llgfr %r5,%r5 # size_t
568 + .globl sys32_listxattr_wrapper
569 +sys32_listxattr_wrapper:
570 + llgtr %r2,%r2 # char *
571 + llgtr %r3,%r3 # char *
572 + llgfr %r4,%r4 # size_t
575 + .globl sys32_llistxattr_wrapper
576 +sys32_llistxattr_wrapper:
577 + llgtr %r2,%r2 # char *
578 + llgtr %r3,%r3 # char *
579 + llgfr %r4,%r4 # size_t
582 + .globl sys32_flistxattr_wrapper
583 +sys32_flistxattr_wrapper:
585 + llgtr %r3,%r3 # char *
586 + llgfr %r4,%r4 # size_t
589 + .globl sys32_removexattr_wrapper
590 +sys32_removexattr_wrapper:
591 + llgtr %r2,%r2 # char *
592 + llgtr %r3,%r3 # char *
595 + .globl sys32_lremovexattr_wrapper
596 +sys32_lremovexattr_wrapper:
597 + llgtr %r2,%r2 # char *
598 + llgtr %r3,%r3 # char *
599 + jg sys_lremovexattr
601 + .globl sys32_fremovexattr_wrapper
602 +sys32_fremovexattr_wrapper:
604 + llgtr %r3,%r3 # char *
605 + jg sys_fremovexattr
608 Index: linux-2.4.19-pre1/arch/sparc/defconfig
609 ===================================================================
610 --- linux-2.4.19-pre1.orig/arch/sparc/defconfig 2004-01-14 01:10:36.000000000 +0300
611 +++ linux-2.4.19-pre1/arch/sparc/defconfig 2004-01-14 01:11:49.000000000 +0300
614 # Automatically generated make config: don't edit
616 +# CONFIG_EXT3_FS_XATTR is not set
617 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
618 +# CONFIG_EXT3_FS_XATTR_USER is not set
619 +# CONFIG_EXT2_FS_XATTR is not set
620 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
621 +# CONFIG_EXT2_FS_XATTR_USER is not set
622 +# CONFIG_FS_MBCACHE is not set
626 Index: linux-2.4.19-pre1/arch/sparc/kernel/systbls.S
627 ===================================================================
628 --- linux-2.4.19-pre1.orig/arch/sparc/kernel/systbls.S 2001-10-21 21:36:54.000000000 +0400
629 +++ linux-2.4.19-pre1/arch/sparc/kernel/systbls.S 2004-01-14 01:11:49.000000000 +0300
631 /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
632 /*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
633 /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
634 -/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
635 -/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
636 -/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
637 -/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
638 -/*185*/ .long sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
639 +/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
640 +/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
641 +/*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
642 +/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
643 +/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
644 /*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
645 /*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
646 /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
647 Index: linux-2.4.19-pre1/arch/sparc64/defconfig
648 ===================================================================
649 --- linux-2.4.19-pre1.orig/arch/sparc64/defconfig 2004-01-14 01:10:36.000000000 +0300
650 +++ linux-2.4.19-pre1/arch/sparc64/defconfig 2004-01-14 01:11:49.000000000 +0300
653 # Automatically generated make config: don't edit
655 +# CONFIG_EXT3_FS_XATTR is not set
656 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
657 +# CONFIG_EXT3_FS_XATTR_USER is not set
658 +# CONFIG_EXT2_FS_XATTR is not set
659 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
660 +# CONFIG_EXT2_FS_XATTR_USER is not set
661 +# CONFIG_FS_MBCACHE is not set
664 # Code maturity level options
665 Index: linux-2.4.19-pre1/arch/sparc64/kernel/systbls.S
666 ===================================================================
667 --- linux-2.4.19-pre1.orig/arch/sparc64/kernel/systbls.S 2001-10-21 21:36:54.000000000 +0400
668 +++ linux-2.4.19-pre1/arch/sparc64/kernel/systbls.S 2004-01-14 01:11:49.000000000 +0300
670 /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
671 .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
672 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
673 - .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
674 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
675 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
676 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
677 - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
678 + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
679 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
680 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
681 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
682 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
683 /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
684 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
685 /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
686 @@ -111,11 +111,11 @@
687 /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
688 .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
689 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
690 - .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
691 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
692 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
693 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
694 - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
695 + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
696 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
697 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
698 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
699 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
700 /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
701 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
702 /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
703 Index: linux-2.4.19-pre1/fs/Config.in
704 ===================================================================
705 --- linux-2.4.19-pre1.orig/fs/Config.in 2004-01-14 01:10:37.000000000 +0300
706 +++ linux-2.4.19-pre1/fs/Config.in 2004-01-14 01:11:49.000000000 +0300
708 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
710 tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS
711 +dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
712 +dep_bool ' Ext3 extended attribute block sharing' \
713 + CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
714 +dep_bool ' Ext3 extended user attributes' \
715 + CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
716 # CONFIG_JBD could be its own option (even modular), but until there are
717 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
718 # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
720 tristate 'ROM file system support' CONFIG_ROMFS_FS
722 tristate 'Second extended fs support' CONFIG_EXT2_FS
723 +dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
724 +dep_bool ' Ext2 extended attribute block sharing' \
725 + CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
726 +dep_bool ' Ext2 extended user attributes' \
727 + CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
729 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
735 +# Meta block cache for Extended Attributes (ext2/ext3)
736 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
737 +define_tristate CONFIG_FS_MBCACHE y
739 mainmenu_option next_comment
740 comment 'Partition Types'
741 source fs/partitions/Config.in
742 Index: linux-2.4.19-pre1/fs/Makefile
743 ===================================================================
744 --- linux-2.4.19-pre1.orig/fs/Makefile 2004-01-14 01:11:49.000000000 +0300
745 +++ linux-2.4.19-pre1/fs/Makefile 2004-01-14 01:11:49.000000000 +0300
747 super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
748 fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
749 dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
750 - filesystems.o namespace.o seq_file.o
751 + filesystems.o namespace.o seq_file.o xattr.o
753 ifeq ($(CONFIG_QUOTA),y)
757 obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
759 +export-objs += mbcache.o
760 +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
762 # persistent filesystems
763 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
765 Index: linux-2.4.19-pre1/fs/ext2/Makefile
766 ===================================================================
767 --- linux-2.4.19-pre1.orig/fs/ext2/Makefile 2001-10-11 19:05:18.000000000 +0400
768 +++ linux-2.4.19-pre1/fs/ext2/Makefile 2004-01-14 01:11:49.000000000 +0300
770 ioctl.o namei.o super.o symlink.o
773 +export-objs += xattr.o
774 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
775 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
777 include $(TOPDIR)/Rules.make
778 Index: linux-2.4.19-pre1/fs/ext2/file.c
779 ===================================================================
780 --- linux-2.4.19-pre1.orig/fs/ext2/file.c 2001-10-11 19:05:18.000000000 +0400
781 +++ linux-2.4.19-pre1/fs/ext2/file.c 2004-01-14 01:11:49.000000000 +0300
784 #include <linux/fs.h>
785 #include <linux/ext2_fs.h>
786 +#include <linux/ext2_xattr.h>
787 #include <linux/sched.h>
792 struct inode_operations ext2_file_inode_operations = {
793 truncate: ext2_truncate,
794 + setxattr: ext2_setxattr,
795 + getxattr: ext2_getxattr,
796 + listxattr: ext2_listxattr,
797 + removexattr: ext2_removexattr,
799 Index: linux-2.4.19-pre1/fs/ext2/ialloc.c
800 ===================================================================
801 --- linux-2.4.19-pre1.orig/fs/ext2/ialloc.c 2004-01-14 01:10:37.000000000 +0300
802 +++ linux-2.4.19-pre1/fs/ext2/ialloc.c 2004-01-14 01:11:49.000000000 +0300
804 #include <linux/config.h>
805 #include <linux/fs.h>
806 #include <linux/ext2_fs.h>
807 +#include <linux/ext2_xattr.h>
808 #include <linux/locks.h>
809 #include <linux/quotaops.h>
813 if (!is_bad_inode(inode)) {
814 /* Quota is already initialized in iput() */
815 + ext2_xattr_delete_inode(inode);
816 DQUOT_FREE_INODE(inode);
819 Index: linux-2.4.19-pre1/fs/ext2/inode.c
820 ===================================================================
821 --- linux-2.4.19-pre1.orig/fs/ext2/inode.c 2004-01-14 01:10:37.000000000 +0300
822 +++ linux-2.4.19-pre1/fs/ext2/inode.c 2004-01-14 01:11:49.000000000 +0300
824 static int ext2_update_inode(struct inode * inode, int do_sync);
827 + * Test whether an inode is a fast symlink.
829 +static inline int ext2_inode_is_fast_symlink(struct inode *inode)
831 + int ea_blocks = inode->u.ext2_i.i_file_acl ?
832 + (inode->i_sb->s_blocksize >> 9) : 0;
834 + return (S_ISLNK(inode->i_mode) &&
835 + inode->i_blocks - ea_blocks == 0);
839 * Called at each iput()
841 void ext2_put_inode (struct inode * inode)
846 - if (is_bad_inode(inode) ||
847 - inode->i_ino == EXT2_ACL_IDX_INO ||
848 - inode->i_ino == EXT2_ACL_DATA_INO)
849 + if (is_bad_inode(inode))
851 inode->u.ext2_i.i_dtime = CURRENT_TIME;
852 mark_inode_dirty(inode);
854 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
855 S_ISLNK(inode->i_mode)))
857 + if (ext2_inode_is_fast_symlink(inode))
859 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
863 unsigned long offset;
864 struct ext2_group_desc * gdp;
866 - if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
867 - inode->i_ino != EXT2_ACL_DATA_INO &&
868 + if ((inode->i_ino != EXT2_ROOT_INO &&
869 inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
870 inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
871 ext2_error (inode->i_sb, "ext2_read_inode",
873 for (block = 0; block < EXT2_N_BLOCKS; block++)
874 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
876 - if (inode->i_ino == EXT2_ACL_IDX_INO ||
877 - inode->i_ino == EXT2_ACL_DATA_INO)
878 - /* Nothing to do */ ;
879 - else if (S_ISREG(inode->i_mode)) {
880 + if (S_ISREG(inode->i_mode)) {
881 inode->i_op = &ext2_file_inode_operations;
882 inode->i_fop = &ext2_file_operations;
883 inode->i_mapping->a_ops = &ext2_aops;
884 @@ -987,15 +995,17 @@
885 inode->i_fop = &ext2_dir_operations;
886 inode->i_mapping->a_ops = &ext2_aops;
887 } else if (S_ISLNK(inode->i_mode)) {
888 - if (!inode->i_blocks)
889 + if (ext2_inode_is_fast_symlink(inode))
890 inode->i_op = &ext2_fast_symlink_inode_operations;
892 - inode->i_op = &page_symlink_inode_operations;
893 + inode->i_op = &ext2_symlink_inode_operations;
894 inode->i_mapping->a_ops = &ext2_aops;
898 + inode->i_op = &ext2_special_inode_operations;
899 init_special_inode(inode, inode->i_mode,
900 le32_to_cpu(raw_inode->i_block[0]));
903 inode->i_attr_flags = 0;
904 if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
905 Index: linux-2.4.19-pre1/fs/ext2/namei.c
906 ===================================================================
907 --- linux-2.4.19-pre1.orig/fs/ext2/namei.c 2001-10-04 09:57:36.000000000 +0400
908 +++ linux-2.4.19-pre1/fs/ext2/namei.c 2004-01-14 01:11:49.000000000 +0300
911 #include <linux/fs.h>
912 #include <linux/ext2_fs.h>
913 +#include <linux/ext2_xattr.h>
914 #include <linux/pagemap.h>
919 if (l > sizeof (inode->u.ext2_i.i_data)) {
921 - inode->i_op = &page_symlink_inode_operations;
922 + inode->i_op = &ext2_symlink_inode_operations;
923 inode->i_mapping->a_ops = &ext2_aops;
924 err = block_symlink(inode, symname, l);
930 + setxattr: ext2_setxattr,
931 + getxattr: ext2_getxattr,
932 + listxattr: ext2_listxattr,
933 + removexattr: ext2_removexattr,
936 +struct inode_operations ext2_special_inode_operations = {
937 + setxattr: ext2_setxattr,
938 + getxattr: ext2_getxattr,
939 + listxattr: ext2_listxattr,
940 + removexattr: ext2_removexattr,
942 Index: linux-2.4.19-pre1/fs/ext2/super.c
943 ===================================================================
944 --- linux-2.4.19-pre1.orig/fs/ext2/super.c 2004-01-14 01:10:37.000000000 +0300
945 +++ linux-2.4.19-pre1/fs/ext2/super.c 2004-01-14 01:11:49.000000000 +0300
947 #include <linux/string.h>
948 #include <linux/fs.h>
949 #include <linux/ext2_fs.h>
950 +#include <linux/ext2_xattr.h>
951 #include <linux/slab.h>
952 #include <linux/init.h>
953 #include <linux/locks.h>
958 + ext2_xattr_put_super(sb);
959 if (!(sb->s_flags & MS_RDONLY)) {
960 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
963 this_char = strtok (NULL, ",")) {
964 if ((value = strchr (this_char, '=')) != NULL)
966 +#ifdef CONFIG_EXT2_FS_XATTR_USER
967 + if (!strcmp (this_char, "user_xattr"))
968 + set_opt (*mount_options, XATTR_USER);
969 + else if (!strcmp (this_char, "nouser_xattr"))
970 + clear_opt (*mount_options, XATTR_USER);
973 if (!strcmp (this_char, "bsddf"))
974 clear_opt (*mount_options, MINIX_DF);
975 else if (!strcmp (this_char, "nouid32")) {
977 blocksize = BLOCK_SIZE;
979 sb->u.ext2_sb.s_mount_opt = 0;
980 +#ifdef CONFIG_EXT2_FS_XATTR_USER
981 + /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
983 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
984 &sb->u.ext2_sb.s_mount_opt)) {
986 @@ -810,12 +822,27 @@
988 static int __init init_ext2_fs(void)
990 - return register_filesystem(&ext2_fs_type);
991 + int error = init_ext2_xattr();
994 + error = init_ext2_xattr_user();
997 + error = register_filesystem(&ext2_fs_type);
1001 + exit_ext2_xattr_user();
1003 + exit_ext2_xattr();
1007 static void __exit exit_ext2_fs(void)
1009 unregister_filesystem(&ext2_fs_type);
1010 + exit_ext2_xattr_user();
1011 + exit_ext2_xattr();
1015 Index: linux-2.4.19-pre1/fs/ext2/symlink.c
1016 ===================================================================
1017 --- linux-2.4.19-pre1.orig/fs/ext2/symlink.c 2000-09-28 00:41:33.000000000 +0400
1018 +++ linux-2.4.19-pre1/fs/ext2/symlink.c 2004-01-14 01:11:49.000000000 +0300
1021 #include <linux/fs.h>
1022 #include <linux/ext2_fs.h>
1023 +#include <linux/ext2_xattr.h>
1025 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
1028 return vfs_follow_link(nd, s);
1031 +struct inode_operations ext2_symlink_inode_operations = {
1032 + readlink: page_readlink,
1033 + follow_link: page_follow_link,
1034 + setxattr: ext2_setxattr,
1035 + getxattr: ext2_getxattr,
1036 + listxattr: ext2_listxattr,
1037 + removexattr: ext2_removexattr,
1040 struct inode_operations ext2_fast_symlink_inode_operations = {
1041 readlink: ext2_readlink,
1042 follow_link: ext2_follow_link,
1043 + setxattr: ext2_setxattr,
1044 + getxattr: ext2_getxattr,
1045 + listxattr: ext2_listxattr,
1046 + removexattr: ext2_removexattr,
1048 Index: linux-2.4.19-pre1/fs/ext2/xattr.c
1049 ===================================================================
1050 --- linux-2.4.19-pre1.orig/fs/ext2/xattr.c 2003-01-30 13:24:37.000000000 +0300
1051 +++ linux-2.4.19-pre1/fs/ext2/xattr.c 2004-01-14 01:11:49.000000000 +0300
1054 + * linux/fs/ext2/xattr.c
1056 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
1058 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
1059 + * Extended attributes for symlinks and special files added per
1060 + * suggestion of Luka Renko <luka.renko@hermes.si>.
1064 + * Extended attributes are stored on disk blocks allocated outside of
1065 + * any inode. The i_file_acl field is then made to point to this allocated
1066 + * block. If all extended attributes of an inode are identical, these
1067 + * inodes may share the same extended attribute block. Such situations
1068 + * are automatically detected by keeping a cache of recent attribute block
1069 + * numbers and hashes over the block's contents in memory.
1072 + * Extended attribute block layout:
1074 + * +------------------+
1077 + * | entry 2 | | growing downwards
1079 + * | four null bytes |
1082 + * | value 3 | | growing upwards
1084 + * +------------------+
1086 + * The block header is followed by multiple entry descriptors. These entry
1087 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
1088 + * byte boundaries. The entry descriptors are sorted by attribute name,
1089 + * so that two extended attribute blocks can be compared efficiently.
1091 + * Attribute values are aligned to the end of the block, stored in
1092 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
1093 + * boundaries. No additional gaps are left between them.
1095 + * Locking strategy
1096 + * ----------------
1097 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
1098 + * the xattr inode operations are called, so we are guaranteed that only one
1099 + * processes accesses extended attributes of an inode at any time.
1101 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
1102 + * only a single process is modifying an extended attribute block, even
1103 + * if the block is shared among inodes.
1105 + * Note for porting to 2.5
1106 + * -----------------------
1107 + * The BKL will no longer be held in the xattr inode operations.
1110 +#include <linux/module.h>
1111 +#include <linux/locks.h>
1112 +#include <linux/slab.h>
1113 +#include <linux/fs.h>
1114 +#include <linux/ext2_fs.h>
1115 +#include <linux/ext2_xattr.h>
1116 +#include <linux/mbcache.h>
1117 +#include <linux/quotaops.h>
1118 +#include <asm/semaphore.h>
1119 +#include <linux/compatmac.h>
1121 +/* These symbols may be needed by a module. */
1122 +EXPORT_SYMBOL(ext2_xattr_register);
1123 +EXPORT_SYMBOL(ext2_xattr_unregister);
1124 +EXPORT_SYMBOL(ext2_xattr_get);
1125 +EXPORT_SYMBOL(ext2_xattr_list);
1126 +EXPORT_SYMBOL(ext2_xattr_set);
1128 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1129 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
1132 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
1133 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
1134 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
1135 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
1137 +#ifdef EXT2_XATTR_DEBUG
1138 +# define ea_idebug(inode, f...) do { \
1139 + printk(KERN_DEBUG "inode %s:%ld: ", \
1140 + kdevname(inode->i_dev), inode->i_ino); \
1144 +# define ea_bdebug(bh, f...) do { \
1145 + printk(KERN_DEBUG "block %s:%ld: ", \
1146 + kdevname(bh->b_dev), bh->b_blocknr); \
1151 +# define ea_idebug(f...)
1152 +# define ea_bdebug(f...)
1155 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
1156 + struct ext2_xattr_header *);
1158 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1160 +static int ext2_xattr_cache_insert(struct buffer_head *);
1161 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
1162 + struct ext2_xattr_header *);
1163 +static void ext2_xattr_cache_remove(struct buffer_head *);
1164 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
1165 + struct ext2_xattr_entry *);
1167 +static struct mb_cache *ext2_xattr_cache;
1170 +# define ext2_xattr_cache_insert(bh) 0
1171 +# define ext2_xattr_cache_find(inode, header) NULL
1172 +# define ext2_xattr_cache_remove(bh) while(0) {}
1173 +# define ext2_xattr_rehash(header, entry) while(0) {}
1177 + * If a file system does not share extended attributes among inodes,
1178 + * we should not need the ext2_xattr_sem semaphore. However, the
1179 + * filesystem may still contain shared blocks, so we always take
1183 +DECLARE_MUTEX(ext2_xattr_sem);
1186 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
1188 + struct super_block *sb = inode->i_sb;
1189 + int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
1190 + EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
1192 + /* How can we enforce the allocation? */
1193 + int block = ext2_new_block(inode, goal, 0, 0, errp);
1196 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1202 +ext2_xattr_quota_alloc(struct inode *inode, int force)
1204 + /* How can we enforce the allocation? */
1206 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
1208 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1210 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
1218 +ext2_xattr_quota_free(struct inode *inode)
1220 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
1221 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1225 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
1227 + ext2_free_blocks(inode, block, 1);
1228 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1232 +# define ext2_xattr_quota_free(inode) \
1233 + DQUOT_FREE_BLOCK(inode, 1)
1234 +# define ext2_xattr_free_block(inode, block) \
1235 + ext2_free_blocks(inode, block, 1)
1238 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1240 +static inline struct buffer_head *
1241 +sb_bread(struct super_block *sb, int block)
1243 + return bread(sb->s_dev, block, sb->s_blocksize);
1246 +static inline struct buffer_head *
1247 +sb_getblk(struct super_block *sb, int block)
1249 + return getblk(sb->s_dev, block, sb->s_blocksize);
1254 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1255 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1258 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1260 + int error = -EINVAL;
1262 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1263 + write_lock(&ext2_handler_lock);
1264 + if (!ext2_xattr_handlers[name_index-1]) {
1265 + ext2_xattr_handlers[name_index-1] = handler;
1268 + write_unlock(&ext2_handler_lock);
1274 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1276 + if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
1277 + write_lock(&ext2_handler_lock);
1278 + ext2_xattr_handlers[name_index-1] = NULL;
1279 + write_unlock(&ext2_handler_lock);
1283 +static inline const char *
1284 +strcmp_prefix(const char *a, const char *a_prefix)
1286 + while (*a_prefix && *a == *a_prefix) {
1290 + return *a_prefix ? NULL : a;
1294 + * Decode the extended attribute name, and translate it into
1295 + * the name_index and name suffix.
1297 +static struct ext2_xattr_handler *
1298 +ext2_xattr_resolve_name(const char **name)
1300 + struct ext2_xattr_handler *handler = NULL;
1305 + read_lock(&ext2_handler_lock);
1306 + for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1307 + if (ext2_xattr_handlers[i]) {
1308 + const char *n = strcmp_prefix(*name,
1309 + ext2_xattr_handlers[i]->prefix);
1311 + handler = ext2_xattr_handlers[i];
1317 + read_unlock(&ext2_handler_lock);
1321 +static inline struct ext2_xattr_handler *
1322 +ext2_xattr_handler(int name_index)
1324 + struct ext2_xattr_handler *handler = NULL;
1325 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1326 + read_lock(&ext2_handler_lock);
1327 + handler = ext2_xattr_handlers[name_index-1];
1328 + read_unlock(&ext2_handler_lock);
1334 + * Inode operation getxattr()
1336 + * dentry->d_inode->i_sem down
1337 + * BKL held [before 2.5.x]
1340 +ext2_getxattr(struct dentry *dentry, const char *name,
1341 + void *buffer, size_t size)
1343 + struct ext2_xattr_handler *handler;
1344 + struct inode *inode = dentry->d_inode;
1346 + handler = ext2_xattr_resolve_name(&name);
1349 + return handler->get(inode, name, buffer, size);
1353 + * Inode operation listxattr()
1355 + * dentry->d_inode->i_sem down
1356 + * BKL held [before 2.5.x]
1359 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1361 + return ext2_xattr_list(dentry->d_inode, buffer, size);
1365 + * Inode operation setxattr()
1367 + * dentry->d_inode->i_sem down
1368 + * BKL held [before 2.5.x]
1371 +ext2_setxattr(struct dentry *dentry, const char *name,
1372 + const void *value, size_t size, int flags)
1374 + struct ext2_xattr_handler *handler;
1375 + struct inode *inode = dentry->d_inode;
1378 + value = ""; /* empty EA, do not remove */
1379 + handler = ext2_xattr_resolve_name(&name);
1382 + return handler->set(inode, name, value, size, flags);
1386 + * Inode operation removexattr()
1388 + * dentry->d_inode->i_sem down
1389 + * BKL held [before 2.5.x]
1392 +ext2_removexattr(struct dentry *dentry, const char *name)
1394 + struct ext2_xattr_handler *handler;
1395 + struct inode *inode = dentry->d_inode;
1397 + handler = ext2_xattr_resolve_name(&name);
1400 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1404 + * ext2_xattr_get()
1406 + * Copy an extended attribute into the buffer
1407 + * provided, or compute the buffer size required.
1408 + * Buffer is NULL to compute the size of the buffer required.
1410 + * Returns a negative error number on failure, or the number of bytes
1411 + * used / required on success.
1414 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1415 + void *buffer, size_t buffer_size)
1417 + struct buffer_head *bh = NULL;
1418 + struct ext2_xattr_entry *entry;
1419 + unsigned int block, size;
1421 + int name_len, error;
1423 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1424 + name_index, name, buffer, (long)buffer_size);
1428 + if (!EXT2_I(inode)->i_file_acl)
1430 + block = EXT2_I(inode)->i_file_acl;
1431 + ea_idebug(inode, "reading block %d", block);
1432 + bh = sb_bread(inode->i_sb, block);
1435 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1436 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1437 + end = bh->b_data + bh->b_size;
1438 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1439 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1440 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
1441 + "inode %ld: bad block %d", inode->i_ino, block);
1445 + /* find named attribute */
1446 + name_len = strlen(name);
1449 + if (name_len > 255)
1451 + entry = FIRST_ENTRY(bh);
1452 + while (!IS_LAST_ENTRY(entry)) {
1453 + struct ext2_xattr_entry *next =
1454 + EXT2_XATTR_NEXT(entry);
1455 + if ((char *)next >= end)
1457 + if (name_index == entry->e_name_index &&
1458 + name_len == entry->e_name_len &&
1459 + memcmp(name, entry->e_name, name_len) == 0)
1463 + /* Check the remaining name entries */
1464 + while (!IS_LAST_ENTRY(entry)) {
1465 + struct ext2_xattr_entry *next =
1466 + EXT2_XATTR_NEXT(entry);
1467 + if ((char *)next >= end)
1471 + if (ext2_xattr_cache_insert(bh))
1472 + ea_idebug(inode, "cache insert failed");
1476 + /* check the buffer size */
1477 + if (entry->e_value_block != 0)
1479 + size = le32_to_cpu(entry->e_value_size);
1480 + if (size > inode->i_sb->s_blocksize ||
1481 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1484 + if (ext2_xattr_cache_insert(bh))
1485 + ea_idebug(inode, "cache insert failed");
1488 + if (size > buffer_size)
1490 + /* return value of attribute */
1491 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1503 + * ext2_xattr_list()
1505 + * Copy a list of attribute names into the buffer
1506 + * provided, or compute the buffer size required.
1507 + * Buffer is NULL to compute the size of the buffer required.
1509 + * Returns a negative error number on failure, or the number of bytes
1510 + * used / required on success.
1513 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1515 + struct buffer_head *bh = NULL;
1516 + struct ext2_xattr_entry *entry;
1517 + unsigned int block, size = 0;
1521 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1522 + buffer, (long)buffer_size);
1524 + if (!EXT2_I(inode)->i_file_acl)
1526 + block = EXT2_I(inode)->i_file_acl;
1527 + ea_idebug(inode, "reading block %d", block);
1528 + bh = sb_bread(inode->i_sb, block);
1531 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1532 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1533 + end = bh->b_data + bh->b_size;
1534 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1535 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1536 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
1537 + "inode %ld: bad block %d", inode->i_ino, block);
1541 + /* compute the size required for the list of attribute names */
1542 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1543 + entry = EXT2_XATTR_NEXT(entry)) {
1544 + struct ext2_xattr_handler *handler;
1545 + struct ext2_xattr_entry *next =
1546 + EXT2_XATTR_NEXT(entry);
1547 + if ((char *)next >= end)
1550 + handler = ext2_xattr_handler(entry->e_name_index);
1552 + size += handler->list(NULL, inode, entry->e_name,
1553 + entry->e_name_len);
1556 + if (ext2_xattr_cache_insert(bh))
1557 + ea_idebug(inode, "cache insert failed");
1563 + if (size > buffer_size)
1567 + /* list the attribute names */
1569 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1570 + entry = EXT2_XATTR_NEXT(entry)) {
1571 + struct ext2_xattr_handler *handler;
1573 + handler = ext2_xattr_handler(entry->e_name_index);
1575 + buf += handler->list(buf, inode, entry->e_name,
1576 + entry->e_name_len);
1587 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1588 + * not set, set it.
1590 +static void ext2_xattr_update_super_block(struct super_block *sb)
1592 + if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1596 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1597 + EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1599 + EXT2_SB(sb)->s_es->s_feature_compat |=
1600 + cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1602 + mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1607 + * ext2_xattr_set()
1609 + * Create, replace or remove an extended attribute for this inode. Buffer
1610 + * is NULL to remove an existing extended attribute, and non-NULL to
1611 + * either replace an existing extended attribute, or create a new extended
1612 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1613 + * specify that an extended attribute must exist and must not exist
1614 + * previous to the call, respectively.
1616 + * Returns 0, or a negative error number on failure.
1619 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1620 + const void *value, size_t value_len, int flags)
1622 + struct super_block *sb = inode->i_sb;
1623 + struct buffer_head *bh = NULL;
1624 + struct ext2_xattr_header *header = NULL;
1625 + struct ext2_xattr_entry *here, *last;
1626 + unsigned int name_len;
1627 + int block = EXT2_I(inode)->i_file_acl;
1628 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
1632 + * header -- Points either into bh, or to a temporarily
1633 + * allocated buffer.
1634 + * here -- The named entry found, or the place for inserting, within
1635 + * the block pointed to by header.
1636 + * last -- Points right after the last named entry within the block
1637 + * pointed to by header.
1638 + * min_offs -- The offset of the first value (values are aligned
1639 + * towards the end of the block).
1640 + * end -- Points right after the block pointed to by header.
1643 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1644 + name_index, name, value, (long)value_len);
1646 + if (IS_RDONLY(inode))
1648 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1650 + if (value == NULL)
1654 + name_len = strlen(name);
1655 + if (name_len > 255 || value_len > sb->s_blocksize)
1657 + down(&ext2_xattr_sem);
1660 + /* The inode already has an extended attribute block. */
1662 + bh = sb_bread(sb, block);
1666 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1667 + atomic_read(&(bh->b_count)),
1668 + le32_to_cpu(HDR(bh)->h_refcount));
1670 + end = bh->b_data + bh->b_size;
1671 + if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1672 + header->h_blocks != cpu_to_le32(1)) {
1673 +bad_block: ext2_error(sb, "ext2_xattr_set",
1674 + "inode %ld: bad block %d", inode->i_ino, block);
1678 + /* Find the named attribute. */
1679 + here = FIRST_ENTRY(bh);
1680 + while (!IS_LAST_ENTRY(here)) {
1681 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1682 + if ((char *)next >= end)
1684 + if (!here->e_value_block && here->e_value_size) {
1685 + int offs = le16_to_cpu(here->e_value_offs);
1686 + if (offs < min_offs)
1689 + not_found = name_index - here->e_name_index;
1691 + not_found = name_len - here->e_name_len;
1693 + not_found = memcmp(name, here->e_name,name_len);
1694 + if (not_found <= 0)
1699 + /* We still need to compute min_offs and last. */
1700 + while (!IS_LAST_ENTRY(last)) {
1701 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1702 + if ((char *)next >= end)
1704 + if (!last->e_value_block && last->e_value_size) {
1705 + int offs = le16_to_cpu(last->e_value_offs);
1706 + if (offs < min_offs)
1712 + /* Check whether we have enough space left. */
1713 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1715 + /* We will use a new extended attribute block. */
1716 + free = sb->s_blocksize -
1717 + sizeof(struct ext2_xattr_header) - sizeof(__u32);
1718 + here = last = NULL; /* avoid gcc uninitialized warning. */
1722 + /* Request to remove a nonexistent attribute? */
1724 + if (flags & XATTR_REPLACE)
1727 + if (value == NULL)
1730 + free -= EXT2_XATTR_LEN(name_len);
1732 + /* Request to create an existing attribute? */
1734 + if (flags & XATTR_CREATE)
1736 + if (!here->e_value_block && here->e_value_size) {
1737 + unsigned int size = le32_to_cpu(here->e_value_size);
1739 + if (le16_to_cpu(here->e_value_offs) + size >
1740 + sb->s_blocksize || size > sb->s_blocksize)
1742 + free += EXT2_XATTR_SIZE(size);
1745 + free -= EXT2_XATTR_SIZE(value_len);
1750 + /* Here we know that we can set the new attribute. */
1753 + if (header->h_refcount == cpu_to_le32(1)) {
1754 + ea_bdebug(bh, "modifying in-place");
1755 + ext2_xattr_cache_remove(bh);
1759 + ea_bdebug(bh, "cloning");
1760 + header = kmalloc(bh->b_size, GFP_KERNEL);
1762 + if (header == NULL)
1764 + memcpy(header, HDR(bh), bh->b_size);
1765 + header->h_refcount = cpu_to_le32(1);
1766 + offset = (char *)header - bh->b_data;
1767 + here = ENTRY((char *)here + offset);
1768 + last = ENTRY((char *)last + offset);
1771 + /* Allocate a buffer where we construct the new block. */
1772 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1774 + if (header == NULL)
1776 + memset(header, 0, sb->s_blocksize);
1777 + end = (char *)header + sb->s_blocksize;
1778 + header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1779 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
1780 + last = here = ENTRY(header+1);
1784 + /* Insert the new name. */
1785 + int size = EXT2_XATTR_LEN(name_len);
1786 + int rest = (char *)last - (char *)here;
1787 + memmove((char *)here + size, here, rest);
1788 + memset(here, 0, size);
1789 + here->e_name_index = name_index;
1790 + here->e_name_len = name_len;
1791 + memcpy(here->e_name, name, name_len);
1793 + /* Remove the old value. */
1794 + if (!here->e_value_block && here->e_value_size) {
1795 + char *first_val = (char *)header + min_offs;
1796 + int offs = le16_to_cpu(here->e_value_offs);
1797 + char *val = (char *)header + offs;
1798 + size_t size = EXT2_XATTR_SIZE(
1799 + le32_to_cpu(here->e_value_size));
1800 + memmove(first_val + size, first_val, val - first_val);
1801 + memset(first_val, 0, size);
1802 + here->e_value_offs = 0;
1805 + /* Adjust all value offsets. */
1806 + last = ENTRY(header+1);
1807 + while (!IS_LAST_ENTRY(last)) {
1808 + int o = le16_to_cpu(last->e_value_offs);
1809 + if (!last->e_value_block && o < offs)
1810 + last->e_value_offs =
1811 + cpu_to_le16(o + size);
1812 + last = EXT2_XATTR_NEXT(last);
1815 + if (value == NULL) {
1816 + /* Remove this attribute. */
1817 + if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1818 + /* This block is now empty. */
1819 + error = ext2_xattr_set2(inode, bh, NULL);
1822 + /* Remove the old name. */
1823 + int size = EXT2_XATTR_LEN(name_len);
1824 + last = ENTRY((char *)last - size);
1825 + memmove(here, (char*)here + size,
1826 + (char*)last - (char*)here);
1827 + memset(last, 0, size);
1832 + if (value != NULL) {
1833 + /* Insert the new value. */
1834 + here->e_value_size = cpu_to_le32(value_len);
1836 + size_t size = EXT2_XATTR_SIZE(value_len);
1837 + char *val = (char *)header + min_offs - size;
1838 + here->e_value_offs =
1839 + cpu_to_le16((char *)val - (char *)header);
1840 + memset(val + size - EXT2_XATTR_PAD, 0,
1841 + EXT2_XATTR_PAD); /* Clear the pad bytes. */
1842 + memcpy(val, value, value_len);
1845 + ext2_xattr_rehash(header, here);
1847 + error = ext2_xattr_set2(inode, bh, header);
1851 + if (!(bh && header == HDR(bh)))
1853 + up(&ext2_xattr_sem);
1859 + * Second half of ext2_xattr_set(): Update the file system.
1862 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1863 + struct ext2_xattr_header *header)
1865 + struct super_block *sb = inode->i_sb;
1866 + struct buffer_head *new_bh = NULL;
1870 + new_bh = ext2_xattr_cache_find(inode, header);
1873 + * We found an identical block in the cache.
1874 + * The old block will be released after updating
1877 + ea_bdebug(old_bh, "reusing block %ld",
1878 + new_bh->b_blocknr);
1881 + if (ext2_xattr_quota_alloc(inode, 1))
1884 + HDR(new_bh)->h_refcount = cpu_to_le32(
1885 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1886 + ea_bdebug(new_bh, "refcount now=%d",
1887 + le32_to_cpu(HDR(new_bh)->h_refcount));
1888 + } else if (old_bh && header == HDR(old_bh)) {
1889 + /* Keep this block. */
1891 + ext2_xattr_cache_insert(new_bh);
1893 + /* We need to allocate a new block */
1894 + int force = EXT2_I(inode)->i_file_acl != 0;
1895 + int block = ext2_xattr_new_block(inode, &error, force);
1898 + ea_idebug(inode, "creating block %d", block);
1900 + new_bh = sb_getblk(sb, block);
1902 + ext2_xattr_free_block(inode, block);
1906 + lock_buffer(new_bh);
1907 + memcpy(new_bh->b_data, header, new_bh->b_size);
1908 + mark_buffer_uptodate(new_bh, 1);
1909 + unlock_buffer(new_bh);
1910 + ext2_xattr_cache_insert(new_bh);
1912 + ext2_xattr_update_super_block(sb);
1914 + mark_buffer_dirty(new_bh);
1915 + if (IS_SYNC(inode)) {
1916 + ll_rw_block(WRITE, 1, &new_bh);
1917 + wait_on_buffer(new_bh);
1919 + if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1924 + /* Update the inode. */
1925 + EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1926 + inode->i_ctime = CURRENT_TIME;
1927 + if (IS_SYNC(inode)) {
1928 + error = ext2_sync_inode (inode);
1932 + mark_inode_dirty(inode);
1935 + if (old_bh && old_bh != new_bh) {
1937 + * If there was an old block, and we are not still using it,
1938 + * we now release the old block.
1940 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1942 + if (refcount == 1) {
1943 + /* Free the old block. */
1944 + ea_bdebug(old_bh, "freeing");
1945 + ext2_xattr_free_block(inode, old_bh->b_blocknr);
1946 + mark_buffer_clean(old_bh);
1948 + /* Decrement the refcount only. */
1950 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1951 + ext2_xattr_quota_free(inode);
1952 + mark_buffer_dirty(old_bh);
1953 + ea_bdebug(old_bh, "refcount now=%d", refcount);
1958 + if (old_bh != new_bh)
1965 + * ext2_xattr_delete_inode()
1967 + * Free extended attribute resources associated with this inode. This
1968 + * is called immediately before an inode is freed.
1971 +ext2_xattr_delete_inode(struct inode *inode)
1973 + struct buffer_head *bh;
1974 + unsigned int block = EXT2_I(inode)->i_file_acl;
1978 + down(&ext2_xattr_sem);
1980 + bh = sb_bread(inode->i_sb, block);
1982 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1983 + "inode %ld: block %d read error", inode->i_ino, block);
1986 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1987 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1988 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1989 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1990 + "inode %ld: bad block %d", inode->i_ino, block);
1993 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1994 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1995 + ext2_xattr_cache_remove(bh);
1996 + ext2_xattr_free_block(inode, block);
2000 + HDR(bh)->h_refcount = cpu_to_le32(
2001 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
2002 + mark_buffer_dirty(bh);
2003 + if (IS_SYNC(inode)) {
2004 + ll_rw_block(WRITE, 1, &bh);
2005 + wait_on_buffer(bh);
2007 + ext2_xattr_quota_free(inode);
2009 + EXT2_I(inode)->i_file_acl = 0;
2013 + up(&ext2_xattr_sem);
2017 + * ext2_xattr_put_super()
2019 + * This is called when a file system is unmounted.
2022 +ext2_xattr_put_super(struct super_block *sb)
2024 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
2025 + mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
2029 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
2032 + * ext2_xattr_cache_insert()
2034 + * Create a new entry in the extended attribute cache, and insert
2035 + * it unless such an entry is already in the cache.
2037 + * Returns 0, or a negative error number on failure.
2040 +ext2_xattr_cache_insert(struct buffer_head *bh)
2042 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
2043 + struct mb_cache_entry *ce;
2046 + ce = mb_cache_entry_alloc(ext2_xattr_cache);
2049 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
2051 + mb_cache_entry_free(ce);
2052 + if (error == -EBUSY) {
2053 + ea_bdebug(bh, "already in cache (%d cache entries)",
2054 + atomic_read(&ext2_xattr_cache->c_entry_count));
2058 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
2059 + atomic_read(&ext2_xattr_cache->c_entry_count));
2060 + mb_cache_entry_release(ce);
2066 + * ext2_xattr_cmp()
2068 + * Compare two extended attribute blocks for equality.
2070 + * Returns 0 if the blocks are equal, 1 if they differ, and
2071 + * a negative error number on errors.
2074 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
2075 + struct ext2_xattr_header *header2)
2077 + struct ext2_xattr_entry *entry1, *entry2;
2079 + entry1 = ENTRY(header1+1);
2080 + entry2 = ENTRY(header2+1);
2081 + while (!IS_LAST_ENTRY(entry1)) {
2082 + if (IS_LAST_ENTRY(entry2))
2084 + if (entry1->e_hash != entry2->e_hash ||
2085 + entry1->e_name_len != entry2->e_name_len ||
2086 + entry1->e_value_size != entry2->e_value_size ||
2087 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
2089 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
2091 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
2092 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
2093 + le32_to_cpu(entry1->e_value_size)))
2096 + entry1 = EXT2_XATTR_NEXT(entry1);
2097 + entry2 = EXT2_XATTR_NEXT(entry2);
2099 + if (!IS_LAST_ENTRY(entry2))
2105 + * ext2_xattr_cache_find()
2107 + * Find an identical extended attribute block.
2109 + * Returns a pointer to the block found, or NULL if such a block was
2110 + * not found or an error occurred.
2112 +static struct buffer_head *
2113 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
2115 + __u32 hash = le32_to_cpu(header->h_hash);
2116 + struct mb_cache_entry *ce;
2118 + if (!header->h_hash)
2119 + return NULL; /* never share */
2120 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
2121 + ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
2123 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
2126 + ext2_error(inode->i_sb, "ext2_xattr_cache_find",
2127 + "inode %ld: block %ld read error",
2128 + inode->i_ino, ce->e_block);
2129 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
2130 + EXT2_XATTR_REFCOUNT_MAX) {
2131 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
2132 + le32_to_cpu(HDR(bh)->h_refcount),
2133 + EXT2_XATTR_REFCOUNT_MAX);
2134 + } else if (!ext2_xattr_cmp(header, HDR(bh))) {
2135 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
2136 + mb_cache_entry_release(ce);
2140 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
2146 + * ext2_xattr_cache_remove()
2148 + * Remove the cache entry of a block from the cache. Called when a
2149 + * block becomes invalid.
2152 +ext2_xattr_cache_remove(struct buffer_head *bh)
2154 + struct mb_cache_entry *ce;
2156 + ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
2158 + ea_bdebug(bh, "removing (%d cache entries remaining)",
2159 + atomic_read(&ext2_xattr_cache->c_entry_count)-1);
2160 + mb_cache_entry_free(ce);
2162 + ea_bdebug(bh, "no cache entry");
2165 +#define NAME_HASH_SHIFT 5
2166 +#define VALUE_HASH_SHIFT 16
2169 + * ext2_xattr_hash_entry()
2171 + * Compute the hash of an extended attribute.
2173 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
2174 + struct ext2_xattr_entry *entry)
2177 + char *name = entry->e_name;
2180 + for (n=0; n < entry->e_name_len; n++) {
2181 + hash = (hash << NAME_HASH_SHIFT) ^
2182 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
2186 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
2187 + __u32 *value = (__u32 *)((char *)header +
2188 + le16_to_cpu(entry->e_value_offs));
2189 + for (n = (le32_to_cpu(entry->e_value_size) +
2190 + EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
2191 + hash = (hash << VALUE_HASH_SHIFT) ^
2192 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
2193 + le32_to_cpu(*value++);
2196 + entry->e_hash = cpu_to_le32(hash);
2199 +#undef NAME_HASH_SHIFT
2200 +#undef VALUE_HASH_SHIFT
2202 +#define BLOCK_HASH_SHIFT 16
2205 + * ext2_xattr_rehash()
2207 + * Re-compute the extended attribute hash value after an entry has changed.
2209 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
2210 + struct ext2_xattr_entry *entry)
2212 + struct ext2_xattr_entry *here;
2215 + ext2_xattr_hash_entry(header, entry);
2216 + here = ENTRY(header+1);
2217 + while (!IS_LAST_ENTRY(here)) {
2218 + if (!here->e_hash) {
2219 + /* Block is not shared if an entry's hash value == 0 */
2223 + hash = (hash << BLOCK_HASH_SHIFT) ^
2224 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
2225 + le32_to_cpu(here->e_hash);
2226 + here = EXT2_XATTR_NEXT(here);
2228 + header->h_hash = cpu_to_le32(hash);
2231 +#undef BLOCK_HASH_SHIFT
2234 +init_ext2_xattr(void)
2236 + ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
2237 + sizeof(struct mb_cache_entry) +
2238 + sizeof(struct mb_cache_entry_index), 1, 61);
2239 + if (!ext2_xattr_cache)
2246 +exit_ext2_xattr(void)
2248 + mb_cache_destroy(ext2_xattr_cache);
2251 +#else /* CONFIG_EXT2_FS_XATTR_SHARING */
2254 +init_ext2_xattr(void)
2260 +exit_ext2_xattr(void)
2264 +#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
2265 Index: linux-2.4.19-pre1/fs/ext2/xattr_user.c
2266 ===================================================================
2267 --- linux-2.4.19-pre1.orig/fs/ext2/xattr_user.c 2003-01-30 13:24:37.000000000 +0300
2268 +++ linux-2.4.19-pre1/fs/ext2/xattr_user.c 2004-01-14 01:11:49.000000000 +0300
2271 + * linux/fs/ext2/xattr_user.c
2272 + * Handler for extended user attributes.
2274 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2277 +#include <linux/module.h>
2278 +#include <linux/string.h>
2279 +#include <linux/fs.h>
2280 +#include <linux/ext2_fs.h>
2281 +#include <linux/ext2_xattr.h>
2283 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2284 +# include <linux/ext2_acl.h>
2287 +#define XATTR_USER_PREFIX "user."
2290 +ext2_xattr_user_list(char *list, struct inode *inode,
2291 + const char *name, int name_len)
2293 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2295 + if (!test_opt(inode->i_sb, XATTR_USER))
2299 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
2300 + memcpy(list+prefix_len, name, name_len);
2301 + list[prefix_len + name_len] = '\0';
2303 + return prefix_len + name_len + 1;
2307 +ext2_xattr_user_get(struct inode *inode, const char *name,
2308 + void *buffer, size_t size)
2312 + if (strcmp(name, "") == 0)
2314 + if (!test_opt(inode->i_sb, XATTR_USER))
2316 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2317 + error = ext2_permission_locked(inode, MAY_READ);
2319 + error = permission(inode, MAY_READ);
2324 + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2329 +ext2_xattr_user_set(struct inode *inode, const char *name,
2330 + const void *value, size_t size, int flags)
2334 + if (strcmp(name, "") == 0)
2336 + if (!test_opt(inode->i_sb, XATTR_USER))
2338 + if ( !S_ISREG(inode->i_mode) &&
2339 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2341 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2342 + error = ext2_permission_locked(inode, MAY_WRITE);
2344 + error = permission(inode, MAY_WRITE);
2349 + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2350 + value, size, flags);
2353 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2354 + prefix: XATTR_USER_PREFIX,
2355 + list: ext2_xattr_user_list,
2356 + get: ext2_xattr_user_get,
2357 + set: ext2_xattr_user_set,
2361 +init_ext2_xattr_user(void)
2363 + return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2364 + &ext2_xattr_user_handler);
2368 +exit_ext2_xattr_user(void)
2370 + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2371 + &ext2_xattr_user_handler);
2373 Index: linux-2.4.19-pre1/fs/ext3/Makefile
2374 ===================================================================
2375 --- linux-2.4.19-pre1.orig/fs/ext3/Makefile 2004-01-14 01:11:49.000000000 +0300
2376 +++ linux-2.4.19-pre1/fs/ext3/Makefile 2004-01-14 01:11:49.000000000 +0300
2379 -# Makefile for the linux ext2-filesystem routines.
2380 +# Makefile for the linux ext3-filesystem routines.
2382 # Note! Dependencies are done automagically by 'make dep', which also
2383 # removes any old dependencies. DON'T put your own dependencies here
2388 -export-objs := super.o inode.o
2389 +export-objs := ext3-exports.o
2391 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2392 - ioctl.o namei.o super.o symlink.o hash.o
2393 + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2394 obj-m := $(O_TARGET)
2396 +export-objs += xattr.o
2397 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2398 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2400 include $(TOPDIR)/Rules.make
2401 Index: linux-2.4.19-pre1/fs/ext3/file.c
2402 ===================================================================
2403 --- linux-2.4.19-pre1.orig/fs/ext3/file.c 2004-01-14 01:11:49.000000000 +0300
2404 +++ linux-2.4.19-pre1/fs/ext3/file.c 2004-01-14 01:11:49.000000000 +0300
2406 #include <linux/locks.h>
2407 #include <linux/jbd.h>
2408 #include <linux/ext3_fs.h>
2409 +#include <linux/ext3_xattr.h>
2410 #include <linux/ext3_jbd.h>
2411 #include <linux/smp_lock.h>
2414 struct inode_operations ext3_file_inode_operations = {
2415 truncate: ext3_truncate, /* BKL held */
2416 setattr: ext3_setattr, /* BKL held */
2417 + setxattr: ext3_setxattr, /* BKL held */
2418 + getxattr: ext3_getxattr, /* BKL held */
2419 + listxattr: ext3_listxattr, /* BKL held */
2420 + removexattr: ext3_removexattr, /* BKL held */
2423 Index: linux-2.4.19-pre1/fs/ext3/ialloc.c
2424 ===================================================================
2425 --- linux-2.4.19-pre1.orig/fs/ext3/ialloc.c 2004-01-14 01:10:37.000000000 +0300
2426 +++ linux-2.4.19-pre1/fs/ext3/ialloc.c 2004-01-14 01:11:49.000000000 +0300
2428 #include <linux/jbd.h>
2429 #include <linux/ext3_fs.h>
2430 #include <linux/ext3_jbd.h>
2431 +#include <linux/ext3_xattr.h>
2432 #include <linux/stat.h>
2433 #include <linux/string.h>
2434 #include <linux/locks.h>
2436 * as writing the quota to disk may need the lock as well.
2439 + ext3_xattr_delete_inode(handle, inode);
2440 DQUOT_FREE_INODE(inode);
2443 Index: linux-2.4.19-pre1/fs/ext3/inode.c
2444 ===================================================================
2445 --- linux-2.4.19-pre1.orig/fs/ext3/inode.c 2004-01-14 01:10:37.000000000 +0300
2446 +++ linux-2.4.19-pre1/fs/ext3/inode.c 2004-01-14 01:11:49.000000000 +0300
2449 #undef SEARCH_FROM_ZERO
2452 + * Test whether an inode is a fast symlink.
2454 +static inline int ext3_inode_is_fast_symlink(struct inode *inode)
2456 + int ea_blocks = inode->u.ext3_i.i_file_acl ?
2457 + (inode->i_sb->s_blocksize >> 9) : 0;
2459 + return (S_ISLNK(inode->i_mode) &&
2460 + inode->i_blocks - ea_blocks == 0);
2463 /* The ext3 forget function must perform a revoke if we are freeing data
2464 * which has been journaled. Metadata (eg. indirect blocks) must be
2465 * revoked in all cases.
2467 * still needs to be revoked.
2470 -static int ext3_forget(handle_t *handle, int is_metadata,
2471 +int ext3_forget(handle_t *handle, int is_metadata,
2472 struct inode *inode, struct buffer_head *bh,
2479 - if (is_bad_inode(inode) ||
2480 - inode->i_ino == EXT3_ACL_IDX_INO ||
2481 - inode->i_ino == EXT3_ACL_DATA_INO)
2482 + if (is_bad_inode(inode))
2486 @@ -1845,6 +1855,8 @@
2487 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
2488 S_ISLNK(inode->i_mode)))
2490 + if (ext3_inode_is_fast_symlink(inode))
2492 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2495 @@ -1992,8 +2004,6 @@
2496 struct ext3_group_desc * gdp;
2498 if ((inode->i_ino != EXT3_ROOT_INO &&
2499 - inode->i_ino != EXT3_ACL_IDX_INO &&
2500 - inode->i_ino != EXT3_ACL_DATA_INO &&
2501 inode->i_ino != EXT3_JOURNAL_INO &&
2502 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2503 inode->i_ino > le32_to_cpu(
2504 @@ -2120,10 +2130,7 @@
2508 - if (inode->i_ino == EXT3_ACL_IDX_INO ||
2509 - inode->i_ino == EXT3_ACL_DATA_INO)
2510 - /* Nothing to do */ ;
2511 - else if (S_ISREG(inode->i_mode)) {
2512 + if (S_ISREG(inode->i_mode)) {
2513 inode->i_op = &ext3_file_inode_operations;
2514 inode->i_fop = &ext3_file_operations;
2515 inode->i_mapping->a_ops = &ext3_aops;
2516 @@ -2131,15 +2138,17 @@
2517 inode->i_op = &ext3_dir_inode_operations;
2518 inode->i_fop = &ext3_dir_operations;
2519 } else if (S_ISLNK(inode->i_mode)) {
2520 - if (!inode->i_blocks)
2521 + if (ext3_inode_is_fast_symlink(inode))
2522 inode->i_op = &ext3_fast_symlink_inode_operations;
2524 - inode->i_op = &page_symlink_inode_operations;
2525 + inode->i_op = &ext3_symlink_inode_operations;
2526 inode->i_mapping->a_ops = &ext3_aops;
2530 + inode->i_op = &ext3_special_inode_operations;
2531 init_special_inode(inode, inode->i_mode,
2532 le32_to_cpu(iloc.raw_inode->i_block[0]));
2534 /* inode->i_attr_flags = 0; unused */
2535 if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
2536 /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
2537 Index: linux-2.4.19-pre1/fs/ext3/namei.c
2538 ===================================================================
2539 --- linux-2.4.19-pre1.orig/fs/ext3/namei.c 2004-01-14 01:11:49.000000000 +0300
2540 +++ linux-2.4.19-pre1/fs/ext3/namei.c 2004-01-14 01:11:49.000000000 +0300
2542 #include <linux/sched.h>
2543 #include <linux/ext3_fs.h>
2544 #include <linux/ext3_jbd.h>
2545 +#include <linux/ext3_xattr.h>
2546 #include <linux/fcntl.h>
2547 #include <linux/stat.h>
2548 #include <linux/string.h>
2549 @@ -1612,7 +1613,7 @@
2553 - inode = ext3_new_inode (handle, dir, S_IFDIR);
2554 + inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2555 err = PTR_ERR(inode);
2558 @@ -1620,7 +1621,6 @@
2559 inode->i_op = &ext3_dir_inode_operations;
2560 inode->i_fop = &ext3_dir_operations;
2561 inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2562 - inode->i_blocks = 0;
2563 dir_block = ext3_bread (handle, inode, 0, 1, &err);
2565 inode->i_nlink--; /* is this nlink == 0? */
2566 @@ -1647,9 +1647,6 @@
2567 BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2568 ext3_journal_dirty_metadata(handle, dir_block);
2570 - inode->i_mode = S_IFDIR | mode;
2571 - if (dir->i_mode & S_ISGID)
2572 - inode->i_mode |= S_ISGID;
2573 ext3_mark_inode_dirty(handle, inode);
2574 err = ext3_add_entry (handle, dentry, inode);
2576 @@ -2018,7 +2015,7 @@
2579 if (l > sizeof (EXT3_I(inode)->i_data)) {
2580 - inode->i_op = &page_symlink_inode_operations;
2581 + inode->i_op = &ext3_symlink_inode_operations;
2582 inode->i_mapping->a_ops = &ext3_aops;
2584 * block_symlink() calls back into ext3_prepare/commit_write.
2585 @@ -2245,4 +2242,16 @@
2586 rmdir: ext3_rmdir, /* BKL held */
2587 mknod: ext3_mknod, /* BKL held */
2588 rename: ext3_rename, /* BKL held */
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 +struct inode_operations ext3_special_inode_operations = {
2596 + setxattr: ext3_setxattr, /* BKL held */
2597 + getxattr: ext3_getxattr, /* BKL held */
2598 + listxattr: ext3_listxattr, /* BKL held */
2599 + removexattr: ext3_removexattr, /* BKL held */
2602 Index: linux-2.4.19-pre1/fs/ext3/super.c
2603 ===================================================================
2604 --- linux-2.4.19-pre1.orig/fs/ext3/super.c 2004-01-14 01:11:49.000000000 +0300
2605 +++ linux-2.4.19-pre1/fs/ext3/super.c 2004-01-14 01:11:49.000000000 +0300
2607 #include <linux/jbd.h>
2608 #include <linux/ext3_fs.h>
2609 #include <linux/ext3_jbd.h>
2610 +#include <linux/ext3_xattr.h>
2611 #include <linux/slab.h>
2612 #include <linux/init.h>
2613 #include <linux/locks.h>
2615 kdev_t j_dev = sbi->s_journal->j_dev;
2618 + ext3_xattr_put_super(sb);
2619 journal_destroy(sbi->s_journal);
2620 if (!(sb->s_flags & MS_RDONLY)) {
2621 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2625 unsigned long *mount_options = &sbi->s_mount_opt;
2627 uid_t *resuid = &sbi->s_resuid;
2628 gid_t *resgid = &sbi->s_resgid;
2630 @@ -511,6 +514,13 @@
2631 this_char = strtok (NULL, ",")) {
2632 if ((value = strchr (this_char, '=')) != NULL)
2634 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2635 + if (!strcmp (this_char, "user_xattr"))
2636 + set_opt (*mount_options, XATTR_USER);
2637 + else if (!strcmp (this_char, "nouser_xattr"))
2638 + clear_opt (*mount_options, XATTR_USER);
2641 if (!strcmp (this_char, "bsddf"))
2642 clear_opt (*mount_options, MINIX_DF);
2643 else if (!strcmp (this_char, "nouid32")) {
2644 @@ -924,6 +934,12 @@
2645 sbi->s_mount_opt = 0;
2646 sbi->s_resuid = EXT3_DEF_RESUID;
2647 sbi->s_resgid = EXT3_DEF_RESGID;
2649 + /* Default extended attribute flags */
2650 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2651 + /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2654 if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2657 @@ -1742,17 +1758,29 @@
2659 static int __init init_ext3_fs(void)
2661 - return register_filesystem(&ext3_fs_type);
2662 + int error = init_ext3_xattr();
2665 + error = init_ext3_xattr_user();
2668 + error = register_filesystem(&ext3_fs_type);
2672 + exit_ext3_xattr_user();
2674 + exit_ext3_xattr();
2678 static void __exit exit_ext3_fs(void)
2680 unregister_filesystem(&ext3_fs_type);
2681 + exit_ext3_xattr_user();
2682 + exit_ext3_xattr();
2685 -EXPORT_SYMBOL(ext3_force_commit);
2686 -EXPORT_SYMBOL(ext3_bread);
2688 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2689 MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2690 MODULE_LICENSE("GPL");
2691 Index: linux-2.4.19-pre1/fs/ext3/symlink.c
2692 ===================================================================
2693 --- linux-2.4.19-pre1.orig/fs/ext3/symlink.c 2001-11-10 01:25:04.000000000 +0300
2694 +++ linux-2.4.19-pre1/fs/ext3/symlink.c 2004-01-14 01:11:49.000000000 +0300
2696 #include <linux/fs.h>
2697 #include <linux/jbd.h>
2698 #include <linux/ext3_fs.h>
2699 +#include <linux/ext3_xattr.h>
2701 static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2704 return vfs_follow_link(nd, s);
2707 +struct inode_operations ext3_symlink_inode_operations = {
2708 + readlink: page_readlink, /* BKL not held. Don't need */
2709 + follow_link: page_follow_link, /* BKL not held. Don't need */
2710 + setxattr: ext3_setxattr, /* BKL held */
2711 + getxattr: ext3_getxattr, /* BKL held */
2712 + listxattr: ext3_listxattr, /* BKL held */
2713 + removexattr: ext3_removexattr, /* BKL held */
2716 struct inode_operations ext3_fast_symlink_inode_operations = {
2717 readlink: ext3_readlink, /* BKL not held. Don't need */
2718 follow_link: ext3_follow_link, /* BKL not held. Don't need */
2719 + setxattr: ext3_setxattr, /* BKL held */
2720 + getxattr: ext3_getxattr, /* BKL held */
2721 + listxattr: ext3_listxattr, /* BKL held */
2722 + removexattr: ext3_removexattr, /* BKL held */
2724 Index: linux-2.4.19-pre1/fs/ext3/xattr.c
2725 ===================================================================
2726 --- linux-2.4.19-pre1.orig/fs/ext3/xattr.c 2003-01-30 13:24:37.000000000 +0300
2727 +++ linux-2.4.19-pre1/fs/ext3/xattr.c 2004-01-14 01:11:49.000000000 +0300
2730 + * linux/fs/ext3/xattr.c
2732 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2734 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2735 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2736 + * Extended attributes for symlinks and special files added per
2737 + * suggestion of Luka Renko <luka.renko@hermes.si>.
2741 + * Extended attributes are stored on disk blocks allocated outside of
2742 + * any inode. The i_file_acl field is then made to point to this allocated
2743 + * block. If all extended attributes of an inode are identical, these
2744 + * inodes may share the same extended attribute block. Such situations
2745 + * are automatically detected by keeping a cache of recent attribute block
2746 + * numbers and hashes over the block's contents in memory.
2749 + * Extended attribute block layout:
2751 + * +------------------+
2754 + * | entry 2 | | growing downwards
2756 + * | four null bytes |
2759 + * | value 3 | | growing upwards
2761 + * +------------------+
2763 + * The block header is followed by multiple entry descriptors. These entry
2764 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2765 + * byte boundaries. The entry descriptors are sorted by attribute name,
2766 + * so that two extended attribute blocks can be compared efficiently.
2768 + * Attribute values are aligned to the end of the block, stored in
2769 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2770 + * boundaries. No additional gaps are left between them.
2772 + * Locking strategy
2773 + * ----------------
2774 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2775 + * the xattr inode operations are called, so we are guaranteed that only one
2776 + * processes accesses extended attributes of an inode at any time.
2778 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2779 + * only a single process is modifying an extended attribute block, even
2780 + * if the block is shared among inodes.
2782 + * Note for porting to 2.5
2783 + * -----------------------
2784 + * The BKL will no longer be held in the xattr inode operations.
2787 +#include <linux/module.h>
2788 +#include <linux/fs.h>
2789 +#include <linux/locks.h>
2790 +#include <linux/slab.h>
2791 +#include <linux/ext3_jbd.h>
2792 +#include <linux/ext3_fs.h>
2793 +#include <linux/ext3_xattr.h>
2794 +#include <linux/mbcache.h>
2795 +#include <linux/quotaops.h>
2796 +#include <asm/semaphore.h>
2797 +#include <linux/compatmac.h>
2799 +#define EXT3_EA_USER "user."
2801 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2802 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2805 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2806 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2807 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2808 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2810 +#ifdef EXT3_XATTR_DEBUG
2811 +# define ea_idebug(inode, f...) do { \
2812 + printk(KERN_DEBUG "inode %s:%ld: ", \
2813 + kdevname(inode->i_dev), inode->i_ino); \
2817 +# define ea_bdebug(bh, f...) do { \
2818 + printk(KERN_DEBUG "block %s:%ld: ", \
2819 + kdevname(bh->b_dev), bh->b_blocknr); \
2824 +# define ea_idebug(f...)
2825 +# define ea_bdebug(f...)
2828 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2829 + struct ext3_xattr_header *);
2831 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2833 +static int ext3_xattr_cache_insert(struct buffer_head *);
2834 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2835 + struct ext3_xattr_header *);
2836 +static void ext3_xattr_cache_remove(struct buffer_head *);
2837 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2838 + struct ext3_xattr_entry *);
2840 +static struct mb_cache *ext3_xattr_cache;
2843 +# define ext3_xattr_cache_insert(bh) 0
2844 +# define ext3_xattr_cache_find(inode, header) NULL
2845 +# define ext3_xattr_cache_remove(bh) while(0) {}
2846 +# define ext3_xattr_rehash(header, entry) while(0) {}
2850 + * If a file system does not share extended attributes among inodes,
2851 + * we should not need the ext3_xattr_sem semaphore. However, the
2852 + * filesystem may still contain shared blocks, so we always take
2856 +DECLARE_MUTEX(ext3_xattr_sem);
2859 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2860 + int * errp, int force)
2862 + struct super_block *sb = inode->i_sb;
2863 + int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2864 + EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2866 + /* How can we enforce the allocation? */
2867 + int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2870 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2876 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2878 + /* How can we enforce the allocation? */
2880 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2882 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2884 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
2892 +ext3_xattr_quota_free(struct inode *inode)
2894 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2895 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2899 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2900 + unsigned long block)
2902 + ext3_free_blocks(handle, inode, block, 1);
2903 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2907 +# define ext3_xattr_quota_free(inode) \
2908 + DQUOT_FREE_BLOCK(inode, 1)
2909 +# define ext3_xattr_free_block(handle, inode, block) \
2910 + ext3_free_blocks(handle, inode, block, 1)
2913 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2915 +static inline struct buffer_head *
2916 +sb_bread(struct super_block *sb, int block)
2918 + return bread(sb->s_dev, block, sb->s_blocksize);
2921 +static inline struct buffer_head *
2922 +sb_getblk(struct super_block *sb, int block)
2924 + return getblk(sb->s_dev, block, sb->s_blocksize);
2929 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2930 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2933 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2935 + int error = -EINVAL;
2937 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2938 + write_lock(&ext3_handler_lock);
2939 + if (!ext3_xattr_handlers[name_index-1]) {
2940 + ext3_xattr_handlers[name_index-1] = handler;
2943 + write_unlock(&ext3_handler_lock);
2949 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2951 + if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2952 + write_lock(&ext3_handler_lock);
2953 + ext3_xattr_handlers[name_index-1] = NULL;
2954 + write_unlock(&ext3_handler_lock);
2958 +static inline const char *
2959 +strcmp_prefix(const char *a, const char *a_prefix)
2961 + while (*a_prefix && *a == *a_prefix) {
2965 + return *a_prefix ? NULL : a;
2969 + * Decode the extended attribute name, and translate it into
2970 + * the name_index and name suffix.
2972 +static inline struct ext3_xattr_handler *
2973 +ext3_xattr_resolve_name(const char **name)
2975 + struct ext3_xattr_handler *handler = NULL;
2980 + read_lock(&ext3_handler_lock);
2981 + for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2982 + if (ext3_xattr_handlers[i]) {
2983 + const char *n = strcmp_prefix(*name,
2984 + ext3_xattr_handlers[i]->prefix);
2986 + handler = ext3_xattr_handlers[i];
2992 + read_unlock(&ext3_handler_lock);
2996 +static inline struct ext3_xattr_handler *
2997 +ext3_xattr_handler(int name_index)
2999 + struct ext3_xattr_handler *handler = NULL;
3000 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
3001 + read_lock(&ext3_handler_lock);
3002 + handler = ext3_xattr_handlers[name_index-1];
3003 + read_unlock(&ext3_handler_lock);
3009 + * Inode operation getxattr()
3011 + * dentry->d_inode->i_sem down
3012 + * BKL held [before 2.5.x]
3015 +ext3_getxattr(struct dentry *dentry, const char *name,
3016 + void *buffer, size_t size)
3018 + struct ext3_xattr_handler *handler;
3019 + struct inode *inode = dentry->d_inode;
3021 + handler = ext3_xattr_resolve_name(&name);
3024 + return handler->get(inode, name, buffer, size);
3028 + * Inode operation listxattr()
3030 + * dentry->d_inode->i_sem down
3031 + * BKL held [before 2.5.x]
3034 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
3036 + return ext3_xattr_list(dentry->d_inode, buffer, size);
3040 + * Inode operation setxattr()
3042 + * dentry->d_inode->i_sem down
3043 + * BKL held [before 2.5.x]
3046 +ext3_setxattr(struct dentry *dentry, const char *name,
3047 + const void *value, size_t size, int flags)
3049 + struct ext3_xattr_handler *handler;
3050 + struct inode *inode = dentry->d_inode;
3053 + value = ""; /* empty EA, do not remove */
3054 + handler = ext3_xattr_resolve_name(&name);
3057 + return handler->set(inode, name, value, size, flags);
3061 + * Inode operation removexattr()
3063 + * dentry->d_inode->i_sem down
3064 + * BKL held [before 2.5.x]
3067 +ext3_removexattr(struct dentry *dentry, const char *name)
3069 + struct ext3_xattr_handler *handler;
3070 + struct inode *inode = dentry->d_inode;
3072 + handler = ext3_xattr_resolve_name(&name);
3075 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
3079 + * ext3_xattr_get()
3081 + * Copy an extended attribute into the buffer
3082 + * provided, or compute the buffer size required.
3083 + * Buffer is NULL to compute the size of the buffer required.
3085 + * Returns a negative error number on failure, or the number of bytes
3086 + * used / required on success.
3089 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
3090 + void *buffer, size_t buffer_size)
3092 + struct buffer_head *bh = NULL;
3093 + struct ext3_xattr_entry *entry;
3094 + unsigned int block, size;
3096 + int name_len, error;
3098 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
3099 + name_index, name, buffer, (long)buffer_size);
3103 + if (!EXT3_I(inode)->i_file_acl)
3105 + block = EXT3_I(inode)->i_file_acl;
3106 + ea_idebug(inode, "reading block %d", block);
3107 + bh = sb_bread(inode->i_sb, block);
3110 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3111 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3112 + end = bh->b_data + bh->b_size;
3113 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3114 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3115 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
3116 + "inode %ld: bad block %d", inode->i_ino, block);
3120 + /* find named attribute */
3121 + name_len = strlen(name);
3124 + if (name_len > 255)
3126 + entry = FIRST_ENTRY(bh);
3127 + while (!IS_LAST_ENTRY(entry)) {
3128 + struct ext3_xattr_entry *next =
3129 + EXT3_XATTR_NEXT(entry);
3130 + if ((char *)next >= end)
3132 + if (name_index == entry->e_name_index &&
3133 + name_len == entry->e_name_len &&
3134 + memcmp(name, entry->e_name, name_len) == 0)
3138 + /* Check the remaining name entries */
3139 + while (!IS_LAST_ENTRY(entry)) {
3140 + struct ext3_xattr_entry *next =
3141 + EXT3_XATTR_NEXT(entry);
3142 + if ((char *)next >= end)
3146 + if (ext3_xattr_cache_insert(bh))
3147 + ea_idebug(inode, "cache insert failed");
3151 + /* check the buffer size */
3152 + if (entry->e_value_block != 0)
3154 + size = le32_to_cpu(entry->e_value_size);
3155 + if (size > inode->i_sb->s_blocksize ||
3156 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
3159 + if (ext3_xattr_cache_insert(bh))
3160 + ea_idebug(inode, "cache insert failed");
3163 + if (size > buffer_size)
3165 + /* return value of attribute */
3166 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
3178 + * ext3_xattr_list()
3180 + * Copy a list of attribute names into the buffer
3181 + * provided, or compute the buffer size required.
3182 + * Buffer is NULL to compute the size of the buffer required.
3184 + * Returns a negative error number on failure, or the number of bytes
3185 + * used / required on success.
3188 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
3190 + struct buffer_head *bh = NULL;
3191 + struct ext3_xattr_entry *entry;
3192 + unsigned int block, size = 0;
3196 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
3197 + buffer, (long)buffer_size);
3199 + if (!EXT3_I(inode)->i_file_acl)
3201 + block = EXT3_I(inode)->i_file_acl;
3202 + ea_idebug(inode, "reading block %d", block);
3203 + bh = sb_bread(inode->i_sb, block);
3206 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3207 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3208 + end = bh->b_data + bh->b_size;
3209 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3210 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3211 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
3212 + "inode %ld: bad block %d", inode->i_ino, block);
3216 + /* compute the size required for the list of attribute names */
3217 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3218 + entry = EXT3_XATTR_NEXT(entry)) {
3219 + struct ext3_xattr_handler *handler;
3220 + struct ext3_xattr_entry *next =
3221 + EXT3_XATTR_NEXT(entry);
3222 + if ((char *)next >= end)
3225 + handler = ext3_xattr_handler(entry->e_name_index);
3227 + size += handler->list(NULL, inode, entry->e_name,
3228 + entry->e_name_len);
3231 + if (ext3_xattr_cache_insert(bh))
3232 + ea_idebug(inode, "cache insert failed");
3238 + if (size > buffer_size)
3242 + /* list the attribute names */
3244 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3245 + entry = EXT3_XATTR_NEXT(entry)) {
3246 + struct ext3_xattr_handler *handler;
3248 + handler = ext3_xattr_handler(entry->e_name_index);
3250 + buf += handler->list(buf, inode, entry->e_name,
3251 + entry->e_name_len);
3262 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3263 + * not set, set it.
3265 +static void ext3_xattr_update_super_block(handle_t *handle,
3266 + struct super_block *sb)
3268 + if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3272 + ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3273 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3274 + EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3276 + EXT3_SB(sb)->s_es->s_feature_compat |=
3277 + cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3279 + ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3284 + * ext3_xattr_set()
3286 + * Create, replace or remove an extended attribute for this inode. Buffer
3287 + * is NULL to remove an existing extended attribute, and non-NULL to
3288 + * either replace an existing extended attribute, or create a new extended
3289 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3290 + * specify that an extended attribute must exist and must not exist
3291 + * previous to the call, respectively.
3293 + * Returns 0, or a negative error number on failure.
3296 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3297 + const char *name, const void *value, size_t value_len, int flags)
3299 + struct super_block *sb = inode->i_sb;
3300 + struct buffer_head *bh = NULL;
3301 + struct ext3_xattr_header *header = NULL;
3302 + struct ext3_xattr_entry *here, *last;
3303 + unsigned int name_len;
3304 + int block = EXT3_I(inode)->i_file_acl;
3305 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
3309 + * header -- Points either into bh, or to a temporarily
3310 + * allocated buffer.
3311 + * here -- The named entry found, or the place for inserting, within
3312 + * the block pointed to by header.
3313 + * last -- Points right after the last named entry within the block
3314 + * pointed to by header.
3315 + * min_offs -- The offset of the first value (values are aligned
3316 + * towards the end of the block).
3317 + * end -- Points right after the block pointed to by header.
3320 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3321 + name_index, name, value, (long)value_len);
3323 + if (IS_RDONLY(inode))
3325 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3327 + if (value == NULL)
3331 + name_len = strlen(name);
3332 + if (name_len > 255 || value_len > sb->s_blocksize)
3334 + down(&ext3_xattr_sem);
3337 + /* The inode already has an extended attribute block. */
3338 + bh = sb_bread(sb, block);
3342 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3343 + atomic_read(&(bh->b_count)),
3344 + le32_to_cpu(HDR(bh)->h_refcount));
3346 + end = bh->b_data + bh->b_size;
3347 + if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3348 + header->h_blocks != cpu_to_le32(1)) {
3349 +bad_block: ext3_error(sb, "ext3_xattr_set",
3350 + "inode %ld: bad block %d", inode->i_ino, block);
3354 + /* Find the named attribute. */
3355 + here = FIRST_ENTRY(bh);
3356 + while (!IS_LAST_ENTRY(here)) {
3357 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3358 + if ((char *)next >= end)
3360 + if (!here->e_value_block && here->e_value_size) {
3361 + int offs = le16_to_cpu(here->e_value_offs);
3362 + if (offs < min_offs)
3365 + not_found = name_index - here->e_name_index;
3367 + not_found = name_len - here->e_name_len;
3369 + not_found = memcmp(name, here->e_name,name_len);
3370 + if (not_found <= 0)
3375 + /* We still need to compute min_offs and last. */
3376 + while (!IS_LAST_ENTRY(last)) {
3377 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3378 + if ((char *)next >= end)
3380 + if (!last->e_value_block && last->e_value_size) {
3381 + int offs = le16_to_cpu(last->e_value_offs);
3382 + if (offs < min_offs)
3388 + /* Check whether we have enough space left. */
3389 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3391 + /* We will use a new extended attribute block. */
3392 + free = sb->s_blocksize -
3393 + sizeof(struct ext3_xattr_header) - sizeof(__u32);
3394 + here = last = NULL; /* avoid gcc uninitialized warning. */
3398 + /* Request to remove a nonexistent attribute? */
3400 + if (flags & XATTR_REPLACE)
3403 + if (value == NULL)
3406 + free -= EXT3_XATTR_LEN(name_len);
3408 + /* Request to create an existing attribute? */
3410 + if (flags & XATTR_CREATE)
3412 + if (!here->e_value_block && here->e_value_size) {
3413 + unsigned int size = le32_to_cpu(here->e_value_size);
3415 + if (le16_to_cpu(here->e_value_offs) + size >
3416 + sb->s_blocksize || size > sb->s_blocksize)
3418 + free += EXT3_XATTR_SIZE(size);
3421 + free -= EXT3_XATTR_SIZE(value_len);
3426 + /* Here we know that we can set the new attribute. */
3429 + if (header->h_refcount == cpu_to_le32(1)) {
3430 + ea_bdebug(bh, "modifying in-place");
3431 + ext3_xattr_cache_remove(bh);
3432 + error = ext3_journal_get_write_access(handle, bh);
3438 + ea_bdebug(bh, "cloning");
3439 + header = kmalloc(bh->b_size, GFP_KERNEL);
3441 + if (header == NULL)
3443 + memcpy(header, HDR(bh), bh->b_size);
3444 + header->h_refcount = cpu_to_le32(1);
3445 + offset = (char *)header - bh->b_data;
3446 + here = ENTRY((char *)here + offset);
3447 + last = ENTRY((char *)last + offset);
3450 + /* Allocate a buffer where we construct the new block. */
3451 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3453 + if (header == NULL)
3455 + memset(header, 0, sb->s_blocksize);
3456 + end = (char *)header + sb->s_blocksize;
3457 + header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3458 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
3459 + last = here = ENTRY(header+1);
3463 + /* Insert the new name. */
3464 + int size = EXT3_XATTR_LEN(name_len);
3465 + int rest = (char *)last - (char *)here;
3466 + memmove((char *)here + size, here, rest);
3467 + memset(here, 0, size);
3468 + here->e_name_index = name_index;
3469 + here->e_name_len = name_len;
3470 + memcpy(here->e_name, name, name_len);
3472 + /* Remove the old value. */
3473 + if (!here->e_value_block && here->e_value_size) {
3474 + char *first_val = (char *)header + min_offs;
3475 + int offs = le16_to_cpu(here->e_value_offs);
3476 + char *val = (char *)header + offs;
3477 + size_t size = EXT3_XATTR_SIZE(
3478 + le32_to_cpu(here->e_value_size));
3479 + memmove(first_val + size, first_val, val - first_val);
3480 + memset(first_val, 0, size);
3481 + here->e_value_offs = 0;
3484 + /* Adjust all value offsets. */
3485 + last = ENTRY(header+1);
3486 + while (!IS_LAST_ENTRY(last)) {
3487 + int o = le16_to_cpu(last->e_value_offs);
3488 + if (!last->e_value_block && o < offs)
3489 + last->e_value_offs =
3490 + cpu_to_le16(o + size);
3491 + last = EXT3_XATTR_NEXT(last);
3494 + if (value == NULL) {
3495 + /* Remove this attribute. */
3496 + if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3497 + /* This block is now empty. */
3498 + error = ext3_xattr_set2(handle, inode, bh,NULL);
3501 + /* Remove the old name. */
3502 + int size = EXT3_XATTR_LEN(name_len);
3503 + last = ENTRY((char *)last - size);
3504 + memmove(here, (char*)here + size,
3505 + (char*)last - (char*)here);
3506 + memset(last, 0, size);
3511 + if (value != NULL) {
3512 + /* Insert the new value. */
3513 + here->e_value_size = cpu_to_le32(value_len);
3515 + size_t size = EXT3_XATTR_SIZE(value_len);
3516 + char *val = (char *)header + min_offs - size;
3517 + here->e_value_offs =
3518 + cpu_to_le16((char *)val - (char *)header);
3519 + memset(val + size - EXT3_XATTR_PAD, 0,
3520 + EXT3_XATTR_PAD); /* Clear the pad bytes. */
3521 + memcpy(val, value, value_len);
3524 + ext3_xattr_rehash(header, here);
3526 + error = ext3_xattr_set2(handle, inode, bh, header);
3530 + if (!(bh && header == HDR(bh)))
3532 + up(&ext3_xattr_sem);
3538 + * Second half of ext3_xattr_set(): Update the file system.
3541 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3542 + struct buffer_head *old_bh, struct ext3_xattr_header *header)
3544 + struct super_block *sb = inode->i_sb;
3545 + struct buffer_head *new_bh = NULL;
3549 + new_bh = ext3_xattr_cache_find(inode, header);
3552 + * We found an identical block in the cache.
3553 + * The old block will be released after updating
3556 + ea_bdebug(old_bh, "reusing block %ld",
3557 + new_bh->b_blocknr);
3560 + if (ext3_xattr_quota_alloc(inode, 1))
3563 + error = ext3_journal_get_write_access(handle, new_bh);
3566 + HDR(new_bh)->h_refcount = cpu_to_le32(
3567 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3568 + ea_bdebug(new_bh, "refcount now=%d",
3569 + le32_to_cpu(HDR(new_bh)->h_refcount));
3570 + } else if (old_bh && header == HDR(old_bh)) {
3571 + /* Keep this block. */
3573 + ext3_xattr_cache_insert(new_bh);
3575 + /* We need to allocate a new block */
3576 + int force = EXT3_I(inode)->i_file_acl != 0;
3577 + int block = ext3_xattr_new_block(handle, inode,
3581 + ea_idebug(inode, "creating block %d", block);
3583 + new_bh = sb_getblk(sb, block);
3585 +getblk_failed: ext3_xattr_free_block(handle, inode, block);
3589 + lock_buffer(new_bh);
3590 + error = ext3_journal_get_create_access(handle, new_bh);
3592 + unlock_buffer(new_bh);
3593 + goto getblk_failed;
3595 + memcpy(new_bh->b_data, header, new_bh->b_size);
3596 + mark_buffer_uptodate(new_bh, 1);
3597 + unlock_buffer(new_bh);
3598 + ext3_xattr_cache_insert(new_bh);
3600 + ext3_xattr_update_super_block(handle, sb);
3602 + error = ext3_journal_dirty_metadata(handle, new_bh);
3607 + /* Update the inode. */
3608 + EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3609 + inode->i_ctime = CURRENT_TIME;
3610 + ext3_mark_inode_dirty(handle, inode);
3611 + if (IS_SYNC(inode))
3612 + handle->h_sync = 1;
3615 + if (old_bh && old_bh != new_bh) {
3617 + * If there was an old block, and we are not still using it,
3618 + * we now release the old block.
3620 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3622 + error = ext3_journal_get_write_access(handle, old_bh);
3625 + if (refcount == 1) {
3626 + /* Free the old block. */
3627 + ea_bdebug(old_bh, "freeing");
3628 + ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3630 + /* ext3_forget() calls bforget() for us, but we
3631 + let our caller release old_bh, so we need to
3632 + duplicate the handle before. */
3634 + ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3636 + /* Decrement the refcount only. */
3638 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3639 + ext3_xattr_quota_free(inode);
3640 + ext3_journal_dirty_metadata(handle, old_bh);
3641 + ea_bdebug(old_bh, "refcount now=%d", refcount);
3646 + if (old_bh != new_bh)
3653 + * ext3_xattr_delete_inode()
3655 + * Free extended attribute resources associated with this inode. This
3656 + * is called immediately before an inode is freed.
3659 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3661 + struct buffer_head *bh;
3662 + unsigned int block = EXT3_I(inode)->i_file_acl;
3666 + down(&ext3_xattr_sem);
3668 + bh = sb_bread(inode->i_sb, block);
3670 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3671 + "inode %ld: block %d read error", inode->i_ino, block);
3674 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3675 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3676 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3677 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3678 + "inode %ld: bad block %d", inode->i_ino, block);
3681 + ext3_journal_get_write_access(handle, bh);
3682 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3683 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3684 + ext3_xattr_cache_remove(bh);
3685 + ext3_xattr_free_block(handle, inode, block);
3686 + ext3_forget(handle, 1, inode, bh, block);
3689 + HDR(bh)->h_refcount = cpu_to_le32(
3690 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
3691 + ext3_journal_dirty_metadata(handle, bh);
3692 + if (IS_SYNC(inode))
3693 + handle->h_sync = 1;
3694 + ext3_xattr_quota_free(inode);
3696 + EXT3_I(inode)->i_file_acl = 0;
3700 + up(&ext3_xattr_sem);
3704 + * ext3_xattr_put_super()
3706 + * This is called when a file system is unmounted.
3709 +ext3_xattr_put_super(struct super_block *sb)
3711 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3712 + mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3716 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3719 + * ext3_xattr_cache_insert()
3721 + * Create a new entry in the extended attribute cache, and insert
3722 + * it unless such an entry is already in the cache.
3724 + * Returns 0, or a negative error number on failure.
3727 +ext3_xattr_cache_insert(struct buffer_head *bh)
3729 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3730 + struct mb_cache_entry *ce;
3733 + ce = mb_cache_entry_alloc(ext3_xattr_cache);
3736 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3738 + mb_cache_entry_free(ce);
3739 + if (error == -EBUSY) {
3740 + ea_bdebug(bh, "already in cache (%d cache entries)",
3741 + atomic_read(&ext3_xattr_cache->c_entry_count));
3745 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3746 + atomic_read(&ext3_xattr_cache->c_entry_count));
3747 + mb_cache_entry_release(ce);
3753 + * ext3_xattr_cmp()
3755 + * Compare two extended attribute blocks for equality.
3757 + * Returns 0 if the blocks are equal, 1 if they differ, and
3758 + * a negative error number on errors.
3761 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3762 + struct ext3_xattr_header *header2)
3764 + struct ext3_xattr_entry *entry1, *entry2;
3766 + entry1 = ENTRY(header1+1);
3767 + entry2 = ENTRY(header2+1);
3768 + while (!IS_LAST_ENTRY(entry1)) {
3769 + if (IS_LAST_ENTRY(entry2))
3771 + if (entry1->e_hash != entry2->e_hash ||
3772 + entry1->e_name_len != entry2->e_name_len ||
3773 + entry1->e_value_size != entry2->e_value_size ||
3774 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3776 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3778 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3779 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3780 + le32_to_cpu(entry1->e_value_size)))
3783 + entry1 = EXT3_XATTR_NEXT(entry1);
3784 + entry2 = EXT3_XATTR_NEXT(entry2);
3786 + if (!IS_LAST_ENTRY(entry2))
3792 + * ext3_xattr_cache_find()
3794 + * Find an identical extended attribute block.
3796 + * Returns a pointer to the block found, or NULL if such a block was
3797 + * not found or an error occurred.
3799 +static struct buffer_head *
3800 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3802 + __u32 hash = le32_to_cpu(header->h_hash);
3803 + struct mb_cache_entry *ce;
3805 + if (!header->h_hash)
3806 + return NULL; /* never share */
3807 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3808 + ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3810 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3813 + ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3814 + "inode %ld: block %ld read error",
3815 + inode->i_ino, ce->e_block);
3816 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3817 + EXT3_XATTR_REFCOUNT_MAX) {
3818 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3819 + le32_to_cpu(HDR(bh)->h_refcount),
3820 + EXT3_XATTR_REFCOUNT_MAX);
3821 + } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3822 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3823 + mb_cache_entry_release(ce);
3827 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3833 + * ext3_xattr_cache_remove()
3835 + * Remove the cache entry of a block from the cache. Called when a
3836 + * block becomes invalid.
3839 +ext3_xattr_cache_remove(struct buffer_head *bh)
3841 + struct mb_cache_entry *ce;
3843 + ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3845 + ea_bdebug(bh, "removing (%d cache entries remaining)",
3846 + atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3847 + mb_cache_entry_free(ce);
3849 + ea_bdebug(bh, "no cache entry");
3852 +#define NAME_HASH_SHIFT 5
3853 +#define VALUE_HASH_SHIFT 16
3856 + * ext3_xattr_hash_entry()
3858 + * Compute the hash of an extended attribute.
3860 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3861 + struct ext3_xattr_entry *entry)
3864 + char *name = entry->e_name;
3867 + for (n=0; n < entry->e_name_len; n++) {
3868 + hash = (hash << NAME_HASH_SHIFT) ^
3869 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3873 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3874 + __u32 *value = (__u32 *)((char *)header +
3875 + le16_to_cpu(entry->e_value_offs));
3876 + for (n = (le32_to_cpu(entry->e_value_size) +
3877 + EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3878 + hash = (hash << VALUE_HASH_SHIFT) ^
3879 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3880 + le32_to_cpu(*value++);
3883 + entry->e_hash = cpu_to_le32(hash);
3886 +#undef NAME_HASH_SHIFT
3887 +#undef VALUE_HASH_SHIFT
3889 +#define BLOCK_HASH_SHIFT 16
3892 + * ext3_xattr_rehash()
3894 + * Re-compute the extended attribute hash value after an entry has changed.
3896 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3897 + struct ext3_xattr_entry *entry)
3899 + struct ext3_xattr_entry *here;
3902 + ext3_xattr_hash_entry(header, entry);
3903 + here = ENTRY(header+1);
3904 + while (!IS_LAST_ENTRY(here)) {
3905 + if (!here->e_hash) {
3906 + /* Block is not shared if an entry's hash value == 0 */
3910 + hash = (hash << BLOCK_HASH_SHIFT) ^
3911 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3912 + le32_to_cpu(here->e_hash);
3913 + here = EXT3_XATTR_NEXT(here);
3915 + header->h_hash = cpu_to_le32(hash);
3918 +#undef BLOCK_HASH_SHIFT
3921 +init_ext3_xattr(void)
3923 + ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3924 + sizeof(struct mb_cache_entry) +
3925 + sizeof(struct mb_cache_entry_index), 1, 61);
3926 + if (!ext3_xattr_cache)
3933 +exit_ext3_xattr(void)
3935 + if (ext3_xattr_cache)
3936 + mb_cache_destroy(ext3_xattr_cache);
3937 + ext3_xattr_cache = NULL;
3940 +#else /* CONFIG_EXT3_FS_XATTR_SHARING */
3943 +init_ext3_xattr(void)
3949 +exit_ext3_xattr(void)
3953 +#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
3954 Index: linux-2.4.19-pre1/fs/ext3/xattr_user.c
3955 ===================================================================
3956 --- linux-2.4.19-pre1.orig/fs/ext3/xattr_user.c 2003-01-30 13:24:37.000000000 +0300
3957 +++ linux-2.4.19-pre1/fs/ext3/xattr_user.c 2004-01-14 01:11:49.000000000 +0300
3960 + * linux/fs/ext3/xattr_user.c
3961 + * Handler for extended user attributes.
3963 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3966 +#include <linux/module.h>
3967 +#include <linux/string.h>
3968 +#include <linux/fs.h>
3969 +#include <linux/ext3_jbd.h>
3970 +#include <linux/ext3_fs.h>
3971 +#include <linux/ext3_xattr.h>
3973 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3974 +# include <linux/ext3_acl.h>
3977 +#define XATTR_USER_PREFIX "user."
3980 +ext3_xattr_user_list(char *list, struct inode *inode,
3981 + const char *name, int name_len)
3983 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3985 + if (!test_opt(inode->i_sb, XATTR_USER))
3989 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
3990 + memcpy(list+prefix_len, name, name_len);
3991 + list[prefix_len + name_len] = '\0';
3993 + return prefix_len + name_len + 1;
3997 +ext3_xattr_user_get(struct inode *inode, const char *name,
3998 + void *buffer, size_t size)
4002 + if (strcmp(name, "") == 0)
4004 + if (!test_opt(inode->i_sb, XATTR_USER))
4006 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
4007 + error = ext3_permission_locked(inode, MAY_READ);
4009 + error = permission(inode, MAY_READ);
4014 + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
4019 +ext3_xattr_user_set(struct inode *inode, const char *name,
4020 + const void *value, size_t size, int flags)
4025 + if (strcmp(name, "") == 0)
4027 + if (!test_opt(inode->i_sb, XATTR_USER))
4029 + if ( !S_ISREG(inode->i_mode) &&
4030 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
4032 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
4033 + error = ext3_permission_locked(inode, MAY_WRITE);
4035 + error = permission(inode, MAY_WRITE);
4040 + handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
4041 + if (IS_ERR(handle))
4042 + return PTR_ERR(handle);
4043 + error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
4044 + value, size, flags);
4045 + ext3_journal_stop(handle, inode);
4050 +struct ext3_xattr_handler ext3_xattr_user_handler = {
4051 + prefix: XATTR_USER_PREFIX,
4052 + list: ext3_xattr_user_list,
4053 + get: ext3_xattr_user_get,
4054 + set: ext3_xattr_user_set,
4058 +init_ext3_xattr_user(void)
4060 + return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
4061 + &ext3_xattr_user_handler);
4065 +exit_ext3_xattr_user(void)
4067 + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
4068 + &ext3_xattr_user_handler);
4070 Index: linux-2.4.19-pre1/fs/ext3/ext3-exports.c
4071 ===================================================================
4072 --- linux-2.4.19-pre1.orig/fs/ext3/ext3-exports.c 2003-01-30 13:24:37.000000000 +0300
4073 +++ linux-2.4.19-pre1/fs/ext3/ext3-exports.c 2004-01-14 01:11:49.000000000 +0300
4075 +#include <linux/config.h>
4076 +#include <linux/module.h>
4077 +#include <linux/ext3_fs.h>
4078 +#include <linux/ext3_jbd.h>
4079 +#include <linux/ext3_xattr.h>
4081 +EXPORT_SYMBOL(ext3_force_commit);
4082 +EXPORT_SYMBOL(ext3_bread);
4083 +EXPORT_SYMBOL(ext3_xattr_register);
4084 +EXPORT_SYMBOL(ext3_xattr_unregister);
4085 +EXPORT_SYMBOL(ext3_xattr_get);
4086 +EXPORT_SYMBOL(ext3_xattr_list);
4087 +EXPORT_SYMBOL(ext3_xattr_set);
4088 Index: linux-2.4.19-pre1/fs/mbcache.c
4089 ===================================================================
4090 --- linux-2.4.19-pre1.orig/fs/mbcache.c 2003-01-30 13:24:37.000000000 +0300
4091 +++ linux-2.4.19-pre1/fs/mbcache.c 2004-01-14 01:11:49.000000000 +0300
4094 + * linux/fs/mbcache.c
4095 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4099 + * Filesystem Meta Information Block Cache (mbcache)
4101 + * The mbcache caches blocks of block devices that need to be located
4102 + * by their device/block number, as well as by other criteria (such
4103 + * as the block's contents).
4105 + * There can only be one cache entry in a cache per device and block number.
4106 + * Additional indexes need not be unique in this sense. The number of
4107 + * additional indexes (=other criteria) can be hardwired at compile time
4108 + * or specified at cache create time.
4110 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
4111 + * in the cache. A valid entry is in the main hash tables of the cache,
4112 + * and may also be in the lru list. An invalid entry is not in any hashes
4115 + * A valid cache entry is only in the lru list if no handles refer to it.
4116 + * Invalid cache entries will be freed when the last handle to the cache
4117 + * entry is released. Entries that cannot be freed immediately are put
4118 + * back on the lru list.
4121 +#include <linux/kernel.h>
4122 +#include <linux/module.h>
4124 +#include <linux/fs.h>
4125 +#include <linux/slab.h>
4126 +#include <linux/sched.h>
4127 +#include <linux/cache_def.h>
4128 +#include <linux/version.h>
4129 +#include <linux/init.h>
4130 +#include <linux/mbcache.h>
4133 +#ifdef MB_CACHE_DEBUG
4134 +# define mb_debug(f...) do { \
4135 + printk(KERN_DEBUG f); \
4138 +#define mb_assert(c) do { if (!(c)) \
4139 + printk(KERN_ERR "assertion " #c " failed\n"); \
4142 +# define mb_debug(f...) do { } while(0)
4143 +# define mb_assert(c) do { } while(0)
4145 +#define mb_error(f...) do { \
4146 + printk(KERN_ERR f); \
4150 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
4151 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
4152 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4153 +MODULE_LICENSE("GPL");
4156 +EXPORT_SYMBOL(mb_cache_create);
4157 +EXPORT_SYMBOL(mb_cache_shrink);
4158 +EXPORT_SYMBOL(mb_cache_destroy);
4159 +EXPORT_SYMBOL(mb_cache_entry_alloc);
4160 +EXPORT_SYMBOL(mb_cache_entry_insert);
4161 +EXPORT_SYMBOL(mb_cache_entry_release);
4162 +EXPORT_SYMBOL(mb_cache_entry_takeout);
4163 +EXPORT_SYMBOL(mb_cache_entry_free);
4164 +EXPORT_SYMBOL(mb_cache_entry_dup);
4165 +EXPORT_SYMBOL(mb_cache_entry_get);
4166 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4167 +EXPORT_SYMBOL(mb_cache_entry_find_first);
4168 +EXPORT_SYMBOL(mb_cache_entry_find_next);
4173 + * Global data: list of all mbcache's, lru list, and a spinlock for
4174 + * accessing cache data structures on SMP machines. The lru list is
4175 + * global across all mbcaches.
4178 +static LIST_HEAD(mb_cache_list);
4179 +static LIST_HEAD(mb_cache_lru_list);
4180 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
4183 +mb_cache_indexes(struct mb_cache *cache)
4185 +#ifdef MB_CACHE_INDEXES_COUNT
4186 + return MB_CACHE_INDEXES_COUNT;
4188 + return cache->c_indexes_count;
4193 + * What the mbcache registers as to get shrunk dynamically.
4197 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
4199 +static struct cache_definition mb_cache_definition = {
4201 + mb_cache_memory_pressure
4206 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4208 + return !list_empty(&ce->e_block_list);
4213 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4217 + if (__mb_cache_entry_is_hashed(ce)) {
4218 + list_del_init(&ce->e_block_list);
4219 + for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4220 + list_del(&ce->e_indexes[n].o_list);
4226 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4228 + struct mb_cache *cache = ce->e_cache;
4230 + mb_assert(atomic_read(&ce->e_used) == 0);
4231 + if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4232 + /* free failed -- put back on the lru list
4233 + for freeing later. */
4234 + spin_lock(&mb_cache_spinlock);
4235 + list_add(&ce->e_lru_list, &mb_cache_lru_list);
4236 + spin_unlock(&mb_cache_spinlock);
4238 + kmem_cache_free(cache->c_entry_cache, ce);
4239 + atomic_dec(&cache->c_entry_count);
4245 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4247 + if (atomic_dec_and_test(&ce->e_used)) {
4248 + if (__mb_cache_entry_is_hashed(ce))
4249 + list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4251 + spin_unlock(&mb_cache_spinlock);
4252 + __mb_cache_entry_forget(ce, GFP_KERNEL);
4256 + spin_unlock(&mb_cache_spinlock);
4261 + * mb_cache_memory_pressure() memory pressure callback
4263 + * This function is called by the kernel memory management when memory
4266 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4267 + * @gfp_mask: (ignored)
4270 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4272 + LIST_HEAD(free_list);
4273 + struct list_head *l, *ltmp;
4276 + spin_lock(&mb_cache_spinlock);
4277 + list_for_each(l, &mb_cache_list) {
4278 + struct mb_cache *cache =
4279 + list_entry(l, struct mb_cache, c_cache_list);
4280 + mb_debug("cache %s (%d)", cache->c_name,
4281 + atomic_read(&cache->c_entry_count));
4282 + count += atomic_read(&cache->c_entry_count);
4284 + mb_debug("trying to free %d of %d entries",
4285 + count / (priority ? priority : 1), count);
4287 + count /= priority;
4288 + while (count-- && !list_empty(&mb_cache_lru_list)) {
4289 + struct mb_cache_entry *ce =
4290 + list_entry(mb_cache_lru_list.next,
4291 + struct mb_cache_entry, e_lru_list);
4292 + list_del(&ce->e_lru_list);
4293 + __mb_cache_entry_unhash(ce);
4294 + list_add_tail(&ce->e_lru_list, &free_list);
4296 + spin_unlock(&mb_cache_spinlock);
4297 + list_for_each_safe(l, ltmp, &free_list) {
4298 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4299 + e_lru_list), gfp_mask);
4305 + * mb_cache_create() create a new cache
4307 + * All entries in one cache are equal size. Cache entries may be from
4308 + * multiple devices. If this is the first mbcache created, registers
4309 + * the cache with kernel memory management. Returns NULL if no more
4310 + * memory was available.
4312 + * @name: name of the cache (informal)
4313 + * @cache_op: contains the callback called when freeing a cache entry
4314 + * @entry_size: The size of a cache entry, including
4315 + * struct mb_cache_entry
4316 + * @indexes_count: number of additional indexes in the cache. Must equal
4317 + * MB_CACHE_INDEXES_COUNT if the number of indexes is
4319 + * @bucket_count: number of hash buckets
4322 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4323 + size_t entry_size, int indexes_count, int bucket_count)
4326 + struct mb_cache *cache = NULL;
4328 + if(entry_size < sizeof(struct mb_cache_entry) +
4329 + indexes_count * sizeof(struct mb_cache_entry_index))
4332 + MOD_INC_USE_COUNT;
4333 + cache = kmalloc(sizeof(struct mb_cache) +
4334 + indexes_count * sizeof(struct list_head), GFP_KERNEL);
4337 + cache->c_name = name;
4338 + cache->c_op.free = NULL;
4340 + cache->c_op.free = cache_op->free;
4341 + atomic_set(&cache->c_entry_count, 0);
4342 + cache->c_bucket_count = bucket_count;
4343 +#ifdef MB_CACHE_INDEXES_COUNT
4344 + mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4346 + cache->c_indexes_count = indexes_count;
4348 + cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4350 + if (!cache->c_block_hash)
4352 + for (n=0; n<bucket_count; n++)
4353 + INIT_LIST_HEAD(&cache->c_block_hash[n]);
4354 + for (m=0; m<indexes_count; m++) {
4355 + cache->c_indexes_hash[m] = kmalloc(bucket_count *
4356 + sizeof(struct list_head),
4358 + if (!cache->c_indexes_hash[m])
4360 + for (n=0; n<bucket_count; n++)
4361 + INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4363 + cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4364 + 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4365 + if (!cache->c_entry_cache)
4368 + spin_lock(&mb_cache_spinlock);
4369 + list_add(&cache->c_cache_list, &mb_cache_list);
4370 + spin_unlock(&mb_cache_spinlock);
4376 + kfree(cache->c_indexes_hash[m]);
4377 + if (cache->c_block_hash)
4378 + kfree(cache->c_block_hash);
4381 + MOD_DEC_USE_COUNT;
4387 + * mb_cache_shrink()
4389 + * Removes all cache entires of a device from the cache. All cache entries
4390 + * currently in use cannot be freed, and thus remain in the cache.
4392 + * @cache: which cache to shrink
4393 + * @dev: which device's cache entries to shrink
4396 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4398 + LIST_HEAD(free_list);
4399 + struct list_head *l, *ltmp;
4401 + spin_lock(&mb_cache_spinlock);
4402 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4403 + struct mb_cache_entry *ce =
4404 + list_entry(l, struct mb_cache_entry, e_lru_list);
4405 + if (ce->e_dev == dev) {
4406 + list_del(&ce->e_lru_list);
4407 + list_add_tail(&ce->e_lru_list, &free_list);
4408 + __mb_cache_entry_unhash(ce);
4411 + spin_unlock(&mb_cache_spinlock);
4412 + list_for_each_safe(l, ltmp, &free_list) {
4413 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4414 + e_lru_list), GFP_KERNEL);
4420 + * mb_cache_destroy()
4422 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4423 + * and then destroys it. If this was the last mbcache, un-registers the
4424 + * mbcache from kernel memory management.
4427 +mb_cache_destroy(struct mb_cache *cache)
4429 + LIST_HEAD(free_list);
4430 + struct list_head *l, *ltmp;
4433 + spin_lock(&mb_cache_spinlock);
4434 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4435 + struct mb_cache_entry *ce =
4436 + list_entry(l, struct mb_cache_entry, e_lru_list);
4437 + if (ce->e_cache == cache) {
4438 + list_del(&ce->e_lru_list);
4439 + list_add_tail(&ce->e_lru_list, &free_list);
4440 + __mb_cache_entry_unhash(ce);
4443 + list_del(&cache->c_cache_list);
4444 + spin_unlock(&mb_cache_spinlock);
4445 + list_for_each_safe(l, ltmp, &free_list) {
4446 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4447 + e_lru_list), GFP_KERNEL);
4450 + if (atomic_read(&cache->c_entry_count) > 0) {
4451 + mb_error("cache %s: %d orphaned entries",
4453 + atomic_read(&cache->c_entry_count));
4456 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4457 + /* We don't have kmem_cache_destroy() in 2.2.x */
4458 + kmem_cache_shrink(cache->c_entry_cache);
4460 + kmem_cache_destroy(cache->c_entry_cache);
4462 + for (n=0; n < mb_cache_indexes(cache); n++)
4463 + kfree(cache->c_indexes_hash[n]);
4464 + kfree(cache->c_block_hash);
4467 + MOD_DEC_USE_COUNT;
4472 + * mb_cache_entry_alloc()
4474 + * Allocates a new cache entry. The new entry will not be valid initially,
4475 + * and thus cannot be looked up yet. It should be filled with data, and
4476 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4477 + * if no more memory was available.
4479 +struct mb_cache_entry *
4480 +mb_cache_entry_alloc(struct mb_cache *cache)
4482 + struct mb_cache_entry *ce;
4484 + atomic_inc(&cache->c_entry_count);
4485 + ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4487 + INIT_LIST_HEAD(&ce->e_lru_list);
4488 + INIT_LIST_HEAD(&ce->e_block_list);
4489 + ce->e_cache = cache;
4490 + atomic_set(&ce->e_used, 1);
4497 + * mb_cache_entry_insert()
4499 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4500 + * the cache. After this, the cache entry can be looked up, but is not yet
4501 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4502 + * success, or -EBUSY if a cache entry for that device + inode exists
4503 + * already (this may happen after a failed lookup, if another process has
4504 + * inserted the same cache entry in the meantime).
4506 + * @dev: device the cache entry belongs to
4507 + * @block: block number
4508 + * @keys: array of additional keys. There must be indexes_count entries
4509 + * in the array (as specified when creating the cache).
4512 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4513 + unsigned long block, unsigned int keys[])
4515 + struct mb_cache *cache = ce->e_cache;
4516 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4517 + struct list_head *l;
4518 + int error = -EBUSY, n;
4520 + spin_lock(&mb_cache_spinlock);
4521 + list_for_each(l, &cache->c_block_hash[bucket]) {
4522 + struct mb_cache_entry *ce =
4523 + list_entry(l, struct mb_cache_entry, e_block_list);
4524 + if (ce->e_dev == dev && ce->e_block == block)
4527 + __mb_cache_entry_unhash(ce);
4529 + ce->e_block = block;
4530 + list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4531 + for (n=0; n<mb_cache_indexes(cache); n++) {
4532 + ce->e_indexes[n].o_key = keys[n];
4533 + bucket = keys[n] % cache->c_bucket_count;
4534 + list_add(&ce->e_indexes[n].o_list,
4535 + &cache->c_indexes_hash[n][bucket]);
4538 + spin_unlock(&mb_cache_spinlock);
4544 + * mb_cache_entry_release()
4546 + * Release a handle to a cache entry. When the last handle to a cache entry
4547 + * is released it is either freed (if it is invalid) or otherwise inserted
4548 + * in to the lru list.
4551 +mb_cache_entry_release(struct mb_cache_entry *ce)
4553 + spin_lock(&mb_cache_spinlock);
4554 + __mb_cache_entry_release_unlock(ce);
4559 + * mb_cache_entry_takeout()
4561 + * Take a cache entry out of the cache, making it invalid. The entry can later
4562 + * be re-inserted using mb_cache_entry_insert(), or released using
4563 + * mb_cache_entry_release().
4566 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4568 + spin_lock(&mb_cache_spinlock);
4569 + mb_assert(list_empty(&ce->e_lru_list));
4570 + __mb_cache_entry_unhash(ce);
4571 + spin_unlock(&mb_cache_spinlock);
4576 + * mb_cache_entry_free()
4578 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4579 + * mb_cache_entry_release().
4582 +mb_cache_entry_free(struct mb_cache_entry *ce)
4584 + spin_lock(&mb_cache_spinlock);
4585 + mb_assert(list_empty(&ce->e_lru_list));
4586 + __mb_cache_entry_unhash(ce);
4587 + __mb_cache_entry_release_unlock(ce);
4592 + * mb_cache_entry_dup()
4594 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4595 + * itself). After the call, both the old and the new handle must be released.
4597 +struct mb_cache_entry *
4598 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4600 + atomic_inc(&ce->e_used);
4606 + * mb_cache_entry_get()
4608 + * Get a cache entry by device / block number. (There can only be one entry
4609 + * in the cache per device and block.) Returns NULL if no such cache entry
4612 +struct mb_cache_entry *
4613 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4615 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4616 + struct list_head *l;
4617 + struct mb_cache_entry *ce;
4619 + spin_lock(&mb_cache_spinlock);
4620 + list_for_each(l, &cache->c_block_hash[bucket]) {
4621 + ce = list_entry(l, struct mb_cache_entry, e_block_list);
4622 + if (ce->e_dev == dev && ce->e_block == block) {
4623 + if (!list_empty(&ce->e_lru_list))
4624 + list_del_init(&ce->e_lru_list);
4625 + atomic_inc(&ce->e_used);
4632 + spin_unlock(&mb_cache_spinlock);
4636 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4638 +static struct mb_cache_entry *
4639 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4640 + int index, kdev_t dev, unsigned int key)
4642 + while (l != head) {
4643 + struct mb_cache_entry *ce =
4644 + list_entry(l, struct mb_cache_entry,
4645 + e_indexes[index].o_list);
4646 + if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4647 + if (!list_empty(&ce->e_lru_list))
4648 + list_del_init(&ce->e_lru_list);
4649 + atomic_inc(&ce->e_used);
4659 + * mb_cache_entry_find_first()
4661 + * Find the first cache entry on a given device with a certain key in
4662 + * an additional index. Additonal matches can be found with
4663 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4665 + * @cache: the cache to search
4666 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4667 + * @dev: the device the cache entry should belong to
4668 + * @key: the key in the index
4670 +struct mb_cache_entry *
4671 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4674 + unsigned int bucket = key % cache->c_bucket_count;
4675 + struct list_head *l;
4676 + struct mb_cache_entry *ce;
4678 + mb_assert(index < mb_cache_indexes(cache));
4679 + spin_lock(&mb_cache_spinlock);
4680 + l = cache->c_indexes_hash[index][bucket].next;
4681 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4683 + spin_unlock(&mb_cache_spinlock);
4689 + * mb_cache_entry_find_next()
4691 + * Find the next cache entry on a given device with a certain key in an
4692 + * additional index. Returns NULL if no match could be found. The previous
4693 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4694 + * be called like this:
4696 + * entry = mb_cache_entry_find_first();
4699 + * entry = mb_cache_entry_find_next(entry, ...);
4702 + * @prev: The previous match
4703 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4704 + * @dev: the device the cache entry should belong to
4705 + * @key: the key in the index
4707 +struct mb_cache_entry *
4708 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4711 + struct mb_cache *cache = prev->e_cache;
4712 + unsigned int bucket = key % cache->c_bucket_count;
4713 + struct list_head *l;
4714 + struct mb_cache_entry *ce;
4716 + mb_assert(index < mb_cache_indexes(cache));
4717 + spin_lock(&mb_cache_spinlock);
4718 + l = prev->e_indexes[index].o_list.next;
4719 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4721 + __mb_cache_entry_release_unlock(prev);
4725 +#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4727 +static int __init init_mbcache(void)
4729 + register_cache(&mb_cache_definition);
4733 +static void __exit exit_mbcache(void)
4735 + unregister_cache(&mb_cache_definition);
4738 +module_init(init_mbcache)
4739 +module_exit(exit_mbcache)
4741 Index: linux-2.4.19-pre1/fs/xattr.c
4742 ===================================================================
4743 --- linux-2.4.19-pre1.orig/fs/xattr.c 2003-01-30 13:24:37.000000000 +0300
4744 +++ linux-2.4.19-pre1/fs/xattr.c 2004-01-14 01:11:49.000000000 +0300
4749 + Extended attribute handling.
4751 + Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
4752 + Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
4754 +#include <linux/fs.h>
4755 +#include <linux/slab.h>
4756 +#include <linux/vmalloc.h>
4757 +#include <linux/smp_lock.h>
4758 +#include <linux/file.h>
4759 +#include <linux/xattr.h>
4760 +#include <asm/uaccess.h>
4763 + * Extended attribute memory allocation wrappers, originally
4764 + * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
4765 + * The vmalloc use here is very uncommon - extended attributes
4766 + * are supposed to be small chunks of metadata, and it is quite
4767 + * unusual to have very many extended attributes, so lists tend
4768 + * to be quite short as well. The 64K upper limit is derived
4769 + * from the extended attribute size limit used by XFS.
4770 + * Intentionally allow zero @size for value/list size requests.
4773 +xattr_alloc(size_t size, size_t limit)
4778 + return ERR_PTR(-E2BIG);
4780 + if (!size) /* size request, no buffer is needed */
4782 + else if (size <= PAGE_SIZE)
4783 + ptr = kmalloc((unsigned long) size, GFP_KERNEL);
4785 + ptr = vmalloc((unsigned long) size);
4787 + return ERR_PTR(-ENOMEM);
4792 +xattr_free(void *ptr, size_t size)
4794 + if (!size) /* size request, no buffer was needed */
4796 + else if (size <= PAGE_SIZE)
4803 + * Extended attribute SET operations
4806 +setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
4810 + char kname[XATTR_NAME_MAX + 1];
4812 + if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
4815 + error = strncpy_from_user(kname, name, sizeof(kname));
4816 + if (error == 0 || error == sizeof(kname))
4821 + kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
4822 + if (IS_ERR(kvalue))
4823 + return PTR_ERR(kvalue);
4825 + if (size > 0 && copy_from_user(kvalue, value, size)) {
4826 + xattr_free(kvalue, size);
4830 + error = -EOPNOTSUPP;
4831 + if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
4832 + down(&d->d_inode->i_sem);
4834 + error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
4836 + up(&d->d_inode->i_sem);
4839 + xattr_free(kvalue, size);
4844 +sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
4846 + struct nameidata nd;
4849 + error = user_path_walk(path, &nd);
4852 + error = setxattr(nd.dentry, name, value, size, flags);
4853 + path_release(&nd);
4858 +sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
4860 + struct nameidata nd;
4863 + error = user_path_walk_link(path, &nd);
4866 + error = setxattr(nd.dentry, name, value, size, flags);
4867 + path_release(&nd);
4872 +sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
4875 + int error = -EBADF;
4880 + error = setxattr(f->f_dentry, name, value, size, flags);
4886 + * Extended attribute GET operations
4889 +getxattr(struct dentry *d, char *name, void *value, size_t size)
4893 + char kname[XATTR_NAME_MAX + 1];
4895 + error = strncpy_from_user(kname, name, sizeof(kname));
4896 + if (error == 0 || error == sizeof(kname))
4901 + kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
4902 + if (IS_ERR(kvalue))
4903 + return PTR_ERR(kvalue);
4905 + error = -EOPNOTSUPP;
4906 + if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
4907 + down(&d->d_inode->i_sem);
4909 + error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
4911 + up(&d->d_inode->i_sem);
4914 + if (kvalue && error > 0)
4915 + if (copy_to_user(value, kvalue, error))
4917 + xattr_free(kvalue, size);
4922 +sys_getxattr(char *path, char *name, void *value, size_t size)
4924 + struct nameidata nd;
4927 + error = user_path_walk(path, &nd);
4930 + error = getxattr(nd.dentry, name, value, size);
4931 + path_release(&nd);
4936 +sys_lgetxattr(char *path, char *name, void *value, size_t size)
4938 + struct nameidata nd;
4941 + error = user_path_walk_link(path, &nd);
4944 + error = getxattr(nd.dentry, name, value, size);
4945 + path_release(&nd);
4950 +sys_fgetxattr(int fd, char *name, void *value, size_t size)
4953 + ssize_t error = -EBADF;
4958 + error = getxattr(f->f_dentry, name, value, size);
4964 + * Extended attribute LIST operations
4967 +listxattr(struct dentry *d, char *list, size_t size)
4972 + klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
4973 + if (IS_ERR(klist))
4974 + return PTR_ERR(klist);
4976 + error = -EOPNOTSUPP;
4977 + if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
4978 + down(&d->d_inode->i_sem);
4980 + error = d->d_inode->i_op->listxattr(d, klist, size);
4982 + up(&d->d_inode->i_sem);
4985 + if (klist && error > 0)
4986 + if (copy_to_user(list, klist, error))
4988 + xattr_free(klist, size);
4993 +sys_listxattr(char *path, char *list, size_t size)
4995 + struct nameidata nd;
4998 + error = user_path_walk(path, &nd);
5001 + error = listxattr(nd.dentry, list, size);
5002 + path_release(&nd);
5007 +sys_llistxattr(char *path, char *list, size_t size)
5009 + struct nameidata nd;
5012 + error = user_path_walk_link(path, &nd);
5015 + error = listxattr(nd.dentry, list, size);
5016 + path_release(&nd);
5021 +sys_flistxattr(int fd, char *list, size_t size)
5024 + ssize_t error = -EBADF;
5029 + error = listxattr(f->f_dentry, list, size);
5035 + * Extended attribute REMOVE operations
5038 +removexattr(struct dentry *d, char *name)
5041 + char kname[XATTR_NAME_MAX + 1];
5043 + error = strncpy_from_user(kname, name, sizeof(kname));
5044 + if (error == 0 || error == sizeof(kname))
5049 + error = -EOPNOTSUPP;
5050 + if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
5051 + down(&d->d_inode->i_sem);
5053 + error = d->d_inode->i_op->removexattr(d, kname);
5055 + up(&d->d_inode->i_sem);
5061 +sys_removexattr(char *path, char *name)
5063 + struct nameidata nd;
5066 + error = user_path_walk(path, &nd);
5069 + error = removexattr(nd.dentry, name);
5070 + path_release(&nd);
5075 +sys_lremovexattr(char *path, char *name)
5077 + struct nameidata nd;
5080 + error = user_path_walk_link(path, &nd);
5083 + error = removexattr(nd.dentry, name);
5084 + path_release(&nd);
5089 +sys_fremovexattr(int fd, char *name)
5092 + int error = -EBADF;
5097 + error = removexattr(f->f_dentry, name);
5101 Index: linux-2.4.19-pre1/include/asm-arm/unistd.h
5102 ===================================================================
5103 --- linux-2.4.19-pre1.orig/include/asm-arm/unistd.h 2001-08-12 22:14:00.000000000 +0400
5104 +++ linux-2.4.19-pre1/include/asm-arm/unistd.h 2004-01-14 01:11:49.000000000 +0300
5105 @@ -240,6 +240,18 @@
5106 #define __NR_mincore (__NR_SYSCALL_BASE+219)
5107 #define __NR_madvise (__NR_SYSCALL_BASE+220)
5108 #define __NR_fcntl64 (__NR_SYSCALL_BASE+221)
5109 +#define __NR_setxattr (__NR_SYSCALL_BASE+226)
5110 +#define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
5111 +#define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
5112 +#define __NR_getxattr (__NR_SYSCALL_BASE+229)
5113 +#define __NR_lgetxattr (__NR_SYSCALL_BASE+230)
5114 +#define __NR_fgetxattr (__NR_SYSCALL_BASE+231)
5115 +#define __NR_listxattr (__NR_SYSCALL_BASE+232)
5116 +#define __NR_llistxattr (__NR_SYSCALL_BASE+233)
5117 +#define __NR_flistxattr (__NR_SYSCALL_BASE+234)
5118 +#define __NR_removexattr (__NR_SYSCALL_BASE+235)
5119 +#define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
5120 +#define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
5123 * The following SWIs are ARM private.
5124 Index: linux-2.4.19-pre1/include/asm-ia64/unistd.h
5125 ===================================================================
5126 --- linux-2.4.19-pre1.orig/include/asm-ia64/unistd.h 2001-11-10 01:26:17.000000000 +0300
5127 +++ linux-2.4.19-pre1/include/asm-ia64/unistd.h 2004-01-14 01:11:49.000000000 +0300
5128 @@ -206,6 +206,18 @@
5129 #define __NR_getdents64 1214
5130 #define __NR_getunwind 1215
5131 #define __NR_readahead 1216
5132 +#define __NR_setxattr 1217
5133 +#define __NR_lsetxattr 1218
5134 +#define __NR_fsetxattr 1219
5135 +#define __NR_getxattr 1220
5136 +#define __NR_lgetxattr 1221
5137 +#define __NR_fgetxattr 1222
5138 +#define __NR_listxattr 1223
5139 +#define __NR_llistxattr 1224
5140 +#define __NR_flistxattr 1225
5141 +#define __NR_removexattr 1226
5142 +#define __NR_lremovexattr 1227
5143 +#define __NR_fremovexattr 1228
5145 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
5147 Index: linux-2.4.19-pre1/include/asm-s390/unistd.h
5148 ===================================================================
5149 --- linux-2.4.19-pre1.orig/include/asm-s390/unistd.h 2001-10-11 20:43:38.000000000 +0400
5150 +++ linux-2.4.19-pre1/include/asm-s390/unistd.h 2004-01-14 01:11:49.000000000 +0300
5151 @@ -211,6 +211,18 @@
5152 #define __NR_mincore 218
5153 #define __NR_madvise 219
5154 #define __NR_getdents64 220
5155 +#define __NR_setxattr 224
5156 +#define __NR_lsetxattr 225
5157 +#define __NR_fsetxattr 226
5158 +#define __NR_getxattr 227
5159 +#define __NR_lgetxattr 228
5160 +#define __NR_fgetxattr 229
5161 +#define __NR_listxattr 230
5162 +#define __NR_llistxattr 231
5163 +#define __NR_flistxattr 232
5164 +#define __NR_removexattr 233
5165 +#define __NR_lremovexattr 234
5166 +#define __NR_fremovexattr 235
5169 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
5170 Index: linux-2.4.19-pre1/include/asm-s390x/unistd.h
5171 ===================================================================
5172 --- linux-2.4.19-pre1.orig/include/asm-s390x/unistd.h 2001-10-11 20:43:38.000000000 +0400
5173 +++ linux-2.4.19-pre1/include/asm-s390x/unistd.h 2004-01-14 01:11:49.000000000 +0300
5174 @@ -181,6 +181,18 @@
5175 #define __NR_mincore 218
5176 #define __NR_madvise 219
5177 #define __NR_getdents64 220
5178 +#define __NR_setxattr 224
5179 +#define __NR_lsetxattr 225
5180 +#define __NR_fsetxattr 226
5181 +#define __NR_getxattr 227
5182 +#define __NR_lgetxattr 228
5183 +#define __NR_fgetxattr 229
5184 +#define __NR_listxattr 230
5185 +#define __NR_llistxattr 231
5186 +#define __NR_flistxattr 232
5187 +#define __NR_removexattr 233
5188 +#define __NR_lremovexattr 234
5189 +#define __NR_fremovexattr 235
5192 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
5193 Index: linux-2.4.19-pre1/include/asm-sparc/unistd.h
5194 ===================================================================
5195 --- linux-2.4.19-pre1.orig/include/asm-sparc/unistd.h 2001-10-21 21:36:54.000000000 +0400
5196 +++ linux-2.4.19-pre1/include/asm-sparc/unistd.h 2004-01-14 01:11:49.000000000 +0300
5197 @@ -184,24 +184,24 @@
5198 /* #define __NR_exportfs 166 SunOS Specific */
5199 #define __NR_mount 167 /* Common */
5200 #define __NR_ustat 168 /* Common */
5201 -/* #define __NR_semsys 169 SunOS Specific */
5202 -/* #define __NR_msgsys 170 SunOS Specific */
5203 -/* #define __NR_shmsys 171 SunOS Specific */
5204 -/* #define __NR_auditsys 172 SunOS Specific */
5205 -/* #define __NR_rfssys 173 SunOS Specific */
5206 +#define __NR_setxattr 169 /* SunOS: semsys */
5207 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
5208 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
5209 +#define __NR_getxattr 172 /* SunOS: auditsys */
5210 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
5211 #define __NR_getdents 174 /* Common */
5212 #define __NR_setsid 175 /* Common */
5213 #define __NR_fchdir 176 /* Common */
5214 -/* #define __NR_fchroot 177 SunOS Specific */
5215 -/* #define __NR_vpixsys 178 SunOS Specific */
5216 -/* #define __NR_aioread 179 SunOS Specific */
5217 -/* #define __NR_aiowrite 180 SunOS Specific */
5218 -/* #define __NR_aiowait 181 SunOS Specific */
5219 -/* #define __NR_aiocancel 182 SunOS Specific */
5220 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
5221 +#define __NR_listxattr 178 /* SunOS: vpixsys */
5222 +#define __NR_llistxattr 179 /* SunOS: aioread */
5223 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
5224 +#define __NR_removexattr 181 /* SunOS: aiowait */
5225 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
5226 #define __NR_sigpending 183 /* Common */
5227 #define __NR_query_module 184 /* Linux Specific */
5228 #define __NR_setpgid 185 /* Common */
5229 -/* #define __NR_pathconf 186 SunOS Specific */
5230 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
5231 /* #define __NR_fpathconf 187 SunOS Specific */
5232 /* #define __NR_sysconf 188 SunOS Specific */
5233 #define __NR_uname 189 /* Linux Specific */
5234 Index: linux-2.4.19-pre1/include/asm-sparc64/unistd.h
5235 ===================================================================
5236 --- linux-2.4.19-pre1.orig/include/asm-sparc64/unistd.h 2001-10-21 21:36:54.000000000 +0400
5237 +++ linux-2.4.19-pre1/include/asm-sparc64/unistd.h 2004-01-14 01:11:49.000000000 +0300
5238 @@ -184,24 +184,24 @@
5239 /* #define __NR_exportfs 166 SunOS Specific */
5240 #define __NR_mount 167 /* Common */
5241 #define __NR_ustat 168 /* Common */
5242 -/* #define __NR_semsys 169 SunOS Specific */
5243 -/* #define __NR_msgsys 170 SunOS Specific */
5244 -/* #define __NR_shmsys 171 SunOS Specific */
5245 -/* #define __NR_auditsys 172 SunOS Specific */
5246 -/* #define __NR_rfssys 173 SunOS Specific */
5247 +#define __NR_setxattr 169 /* SunOS: semsys */
5248 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
5249 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
5250 +#define __NR_getxattr 172 /* SunOS: auditsys */
5251 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
5252 #define __NR_getdents 174 /* Common */
5253 #define __NR_setsid 175 /* Common */
5254 #define __NR_fchdir 176 /* Common */
5255 -/* #define __NR_fchroot 177 SunOS Specific */
5256 -/* #define __NR_vpixsys 178 SunOS Specific */
5257 -/* #define __NR_aioread 179 SunOS Specific */
5258 -/* #define __NR_aiowrite 180 SunOS Specific */
5259 -/* #define __NR_aiowait 181 SunOS Specific */
5260 -/* #define __NR_aiocancel 182 SunOS Specific */
5261 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
5262 +#define __NR_listxattr 178 /* SunOS: vpixsys */
5263 +#define __NR_llistxattr 179 /* SunOS: aioread */
5264 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
5265 +#define __NR_removexattr 181 /* SunOS: aiowait */
5266 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
5267 #define __NR_sigpending 183 /* Common */
5268 #define __NR_query_module 184 /* Linux Specific */
5269 #define __NR_setpgid 185 /* Common */
5270 -/* #define __NR_pathconf 186 SunOS Specific */
5271 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
5272 /* #define __NR_fpathconf 187 SunOS Specific */
5273 /* #define __NR_sysconf 188 SunOS Specific */
5274 #define __NR_uname 189 /* Linux Specific */
5275 Index: linux-2.4.19-pre1/include/linux/cache_def.h
5276 ===================================================================
5277 --- linux-2.4.19-pre1.orig/include/linux/cache_def.h 2003-01-30 13:24:37.000000000 +0300
5278 +++ linux-2.4.19-pre1/include/linux/cache_def.h 2004-01-14 01:11:49.000000000 +0300
5281 + * linux/cache_def.h
5282 + * Handling of caches defined in drivers, filesystems, ...
5284 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5287 +struct cache_definition {
5289 + void (*shrink)(int, unsigned int);
5290 + struct list_head link;
5293 +extern void register_cache(struct cache_definition *);
5294 +extern void unregister_cache(struct cache_definition *);
5295 Index: linux-2.4.19-pre1/include/linux/errno.h
5296 ===================================================================
5297 --- linux-2.4.19-pre1.orig/include/linux/errno.h 2001-02-10 01:46:13.000000000 +0300
5298 +++ linux-2.4.19-pre1/include/linux/errno.h 2004-01-14 01:11:49.000000000 +0300
5303 +/* Defined for extended attributes */
5304 +#define ENOATTR ENODATA /* No such attribute */
5305 +#define ENOTSUP EOPNOTSUPP /* Operation not supported */
5308 Index: linux-2.4.19-pre1/include/linux/ext2_fs.h
5309 ===================================================================
5310 --- linux-2.4.19-pre1.orig/include/linux/ext2_fs.h 2001-11-22 22:46:52.000000000 +0300
5311 +++ linux-2.4.19-pre1/include/linux/ext2_fs.h 2004-01-14 01:18:00.000000000 +0300
5314 #define EXT2_BAD_INO 1 /* Bad blocks inode */
5315 #define EXT2_ROOT_INO 2 /* Root inode */
5316 -#define EXT2_ACL_IDX_INO 3 /* ACL inode */
5317 -#define EXT2_ACL_DATA_INO 4 /* ACL inode */
5318 #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
5319 #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
5323 # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5325 -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
5326 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
5328 # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5329 @@ -121,28 +118,6 @@
5335 -struct ext2_acl_header /* Header of Access Control Lists */
5338 - __u32 aclh_file_count;
5339 - __u32 aclh_acle_count;
5340 - __u32 aclh_first_acle;
5343 -struct ext2_acl_entry /* Access Control List Entry */
5346 - __u16 acle_perms; /* Access permissions */
5347 - __u16 acle_type; /* Type of entry */
5348 - __u16 acle_tag; /* User or group identity */
5350 - __u32 acle_next; /* Pointer on next entry for the */
5351 - /* same inode or on next free entry */
5355 * Structure of a blocks group descriptor
5357 struct ext2_group_desc
5359 #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
5360 #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
5361 #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
5362 +#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5364 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
5365 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
5369 #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
5370 +#define EXT2_I(inode) (&((inode)->u.ext2_i))
5372 /* Assume that user mode programs are passing in an ext2fs superblock, not
5373 * a kernel struct super_block. This will allow us to call the feature-test
5375 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
5376 #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
5378 -#define EXT2_FEATURE_COMPAT_SUPP 0
5379 +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5380 #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
5381 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5382 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
5383 @@ -623,8 +600,10 @@
5386 extern struct inode_operations ext2_dir_inode_operations;
5387 +extern struct inode_operations ext2_special_inode_operations;
5390 +extern struct inode_operations ext2_symlink_inode_operations;
5391 extern struct inode_operations ext2_fast_symlink_inode_operations;
5393 #endif /* __KERNEL__ */
5394 Index: linux-2.4.19-pre1/include/linux/ext2_xattr.h
5395 ===================================================================
5396 --- linux-2.4.19-pre1.orig/include/linux/ext2_xattr.h 2003-01-30 13:24:37.000000000 +0300
5397 +++ linux-2.4.19-pre1/include/linux/ext2_xattr.h 2004-01-14 01:18:01.000000000 +0300
5400 + File: linux/ext2_xattr.h
5402 + On-disk format of extended attributes for the ext2 filesystem.
5404 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5407 +#include <linux/config.h>
5408 +#include <linux/init.h>
5409 +#include <linux/xattr.h>
5411 +/* Magic value in attribute blocks */
5412 +#define EXT2_XATTR_MAGIC 0xEA020000
5414 +/* Maximum number of references to one attribute block */
5415 +#define EXT2_XATTR_REFCOUNT_MAX 1024
5418 +#define EXT2_XATTR_INDEX_MAX 10
5419 +#define EXT2_XATTR_INDEX_USER 1
5420 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
5421 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5423 +struct ext2_xattr_header {
5424 + __u32 h_magic; /* magic number for identification */
5425 + __u32 h_refcount; /* reference count */
5426 + __u32 h_blocks; /* number of disk blocks used */
5427 + __u32 h_hash; /* hash value of all attributes */
5428 + __u32 h_reserved[4]; /* zero right now */
5431 +struct ext2_xattr_entry {
5432 + __u8 e_name_len; /* length of name */
5433 + __u8 e_name_index; /* attribute name index */
5434 + __u16 e_value_offs; /* offset in disk block of value */
5435 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5436 + __u32 e_value_size; /* size of attribute value */
5437 + __u32 e_hash; /* hash value of name and value */
5438 + char e_name[0]; /* attribute name */
5441 +#define EXT2_XATTR_PAD_BITS 2
5442 +#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
5443 +#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
5444 +#define EXT2_XATTR_LEN(name_len) \
5445 + (((name_len) + EXT2_XATTR_ROUND + \
5446 + sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
5447 +#define EXT2_XATTR_NEXT(entry) \
5448 + ( (struct ext2_xattr_entry *)( \
5449 + (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
5450 +#define EXT2_XATTR_SIZE(size) \
5451 + (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
5455 +# ifdef CONFIG_EXT2_FS_XATTR
5457 +struct ext2_xattr_handler {
5459 + size_t (*list)(char *list, struct inode *inode, const char *name,
5461 + int (*get)(struct inode *inode, const char *name, void *buffer,
5463 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5464 + size_t size, int flags);
5467 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
5468 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
5470 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
5471 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
5472 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
5473 +extern int ext2_removexattr(struct dentry *, const char *);
5475 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
5476 +extern int ext2_xattr_list(struct inode *, char *, size_t);
5477 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
5479 +extern void ext2_xattr_delete_inode(struct inode *);
5480 +extern void ext2_xattr_put_super(struct super_block *);
5482 +extern int init_ext2_xattr(void) __init;
5483 +extern void exit_ext2_xattr(void);
5485 +# else /* CONFIG_EXT2_FS_XATTR */
5486 +# define ext2_setxattr NULL
5487 +# define ext2_getxattr NULL
5488 +# define ext2_listxattr NULL
5489 +# define ext2_removexattr NULL
5492 +ext2_xattr_get(struct inode *inode, int name_index,
5493 + const char *name, void *buffer, size_t size)
5499 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
5505 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
5506 + const void *value, size_t size, int flags)
5512 +ext2_xattr_delete_inode(struct inode *inode)
5517 +ext2_xattr_put_super(struct super_block *sb)
5522 +init_ext2_xattr(void)
5528 +exit_ext2_xattr(void)
5532 +# endif /* CONFIG_EXT2_FS_XATTR */
5534 +# ifdef CONFIG_EXT2_FS_XATTR_USER
5536 +extern int init_ext2_xattr_user(void) __init;
5537 +extern void exit_ext2_xattr_user(void);
5539 +# else /* CONFIG_EXT2_FS_XATTR_USER */
5542 +init_ext2_xattr_user(void)
5548 +exit_ext2_xattr_user(void)
5552 +# endif /* CONFIG_EXT2_FS_XATTR_USER */
5554 +#endif /* __KERNEL__ */
5556 Index: linux-2.4.19-pre1/include/linux/ext3_fs.h
5557 ===================================================================
5558 --- linux-2.4.19-pre1.orig/include/linux/ext3_fs.h 2004-01-14 01:11:49.000000000 +0300
5559 +++ linux-2.4.19-pre1/include/linux/ext3_fs.h 2004-01-14 01:11:49.000000000 +0300
5562 #define EXT3_BAD_INO 1 /* Bad blocks inode */
5563 #define EXT3_ROOT_INO 2 /* Root inode */
5564 -#define EXT3_ACL_IDX_INO 3 /* ACL inode */
5565 -#define EXT3_ACL_DATA_INO 4 /* ACL inode */
5566 #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
5567 #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
5568 #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
5571 # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5573 -#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
5574 #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
5576 # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5577 @@ -129,28 +126,6 @@
5583 -struct ext3_acl_header /* Header of Access Control Lists */
5586 - __u32 aclh_file_count;
5587 - __u32 aclh_acle_count;
5588 - __u32 aclh_first_acle;
5591 -struct ext3_acl_entry /* Access Control List Entry */
5594 - __u16 acle_perms; /* Access permissions */
5595 - __u16 acle_type; /* Type of entry */
5596 - __u16 acle_tag; /* User or group identity */
5598 - __u32 acle_next; /* Pointer on next entry for the */
5599 - /* same inode or on next free entry */
5603 * Structure of a blocks group descriptor
5605 struct ext3_group_desc
5607 #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
5608 #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
5609 #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
5610 +#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5612 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
5613 #ifndef _LINUX_EXT2_FS_H
5615 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
5616 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
5618 -#define EXT3_FEATURE_COMPAT_SUPP 0
5619 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5620 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
5621 EXT3_FEATURE_INCOMPAT_RECOVER)
5622 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5624 extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
5627 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
5628 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
5629 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
5631 @@ -771,8 +748,10 @@
5634 extern struct inode_operations ext3_dir_inode_operations;
5635 +extern struct inode_operations ext3_special_inode_operations;
5638 +extern struct inode_operations ext3_symlink_inode_operations;
5639 extern struct inode_operations ext3_fast_symlink_inode_operations;
5642 Index: linux-2.4.19-pre1/include/linux/ext3_jbd.h
5643 ===================================================================
5644 --- linux-2.4.19-pre1.orig/include/linux/ext3_jbd.h 2004-01-14 01:11:49.000000000 +0300
5645 +++ linux-2.4.19-pre1/include/linux/ext3_jbd.h 2004-01-14 01:18:04.000000000 +0300
5648 #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
5650 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5651 + * and two group and summaries. */
5653 +#define EXT3_XATTR_TRANS_BLOCKS 8
5655 /* Define the minimum size for a transaction which modifies data. This
5656 * needs to take into account the fact that we may end up modifying two
5657 * quota files too (one for the group, one for the user quota). The
5658 * superblock only gets updated once, of course, so don't bother
5659 * counting that again for the quota updates. */
5661 -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5662 +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5663 + EXT3_XATTR_TRANS_BLOCKS - 2)
5665 extern int ext3_writepage_trans_blocks(struct inode *inode);
5667 Index: linux-2.4.19-pre1/include/linux/ext3_xattr.h
5668 ===================================================================
5669 --- linux-2.4.19-pre1.orig/include/linux/ext3_xattr.h 2003-01-30 13:24:37.000000000 +0300
5670 +++ linux-2.4.19-pre1/include/linux/ext3_xattr.h 2004-01-14 01:11:49.000000000 +0300
5673 + File: linux/ext3_xattr.h
5675 + On-disk format of extended attributes for the ext3 filesystem.
5677 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5680 +#include <linux/config.h>
5681 +#include <linux/init.h>
5682 +#include <linux/xattr.h>
5684 +/* Magic value in attribute blocks */
5685 +#define EXT3_XATTR_MAGIC 0xEA020000
5687 +/* Maximum number of references to one attribute block */
5688 +#define EXT3_XATTR_REFCOUNT_MAX 1024
5691 +#define EXT3_XATTR_INDEX_MAX 10
5692 +#define EXT3_XATTR_INDEX_USER 1
5693 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
5694 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5696 +struct ext3_xattr_header {
5697 + __u32 h_magic; /* magic number for identification */
5698 + __u32 h_refcount; /* reference count */
5699 + __u32 h_blocks; /* number of disk blocks used */
5700 + __u32 h_hash; /* hash value of all attributes */
5701 + __u32 h_reserved[4]; /* zero right now */
5704 +struct ext3_xattr_entry {
5705 + __u8 e_name_len; /* length of name */
5706 + __u8 e_name_index; /* attribute name index */
5707 + __u16 e_value_offs; /* offset in disk block of value */
5708 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5709 + __u32 e_value_size; /* size of attribute value */
5710 + __u32 e_hash; /* hash value of name and value */
5711 + char e_name[0]; /* attribute name */
5714 +#define EXT3_XATTR_PAD_BITS 2
5715 +#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
5716 +#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
5717 +#define EXT3_XATTR_LEN(name_len) \
5718 + (((name_len) + EXT3_XATTR_ROUND + \
5719 + sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5720 +#define EXT3_XATTR_NEXT(entry) \
5721 + ( (struct ext3_xattr_entry *)( \
5722 + (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5723 +#define EXT3_XATTR_SIZE(size) \
5724 + (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5728 +# ifdef CONFIG_EXT3_FS_XATTR
5730 +struct ext3_xattr_handler {
5732 + size_t (*list)(char *list, struct inode *inode, const char *name,
5734 + int (*get)(struct inode *inode, const char *name, void *buffer,
5736 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5737 + size_t size, int flags);
5740 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5741 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5743 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5744 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5745 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5746 +extern int ext3_removexattr(struct dentry *, const char *);
5748 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5749 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5750 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5752 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5753 +extern void ext3_xattr_put_super(struct super_block *);
5755 +extern int init_ext3_xattr(void) __init;
5756 +extern void exit_ext3_xattr(void);
5758 +# else /* CONFIG_EXT3_FS_XATTR */
5759 +# define ext3_setxattr NULL
5760 +# define ext3_getxattr NULL
5761 +# define ext3_listxattr NULL
5762 +# define ext3_removexattr NULL
5765 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5766 + void *buffer, size_t size)
5772 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5778 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5779 + const char *name, const void *value, size_t size, int flags)
5785 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5790 +ext3_xattr_put_super(struct super_block *sb)
5795 +init_ext3_xattr(void)
5801 +exit_ext3_xattr(void)
5805 +# endif /* CONFIG_EXT3_FS_XATTR */
5807 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5809 +extern int init_ext3_xattr_user(void) __init;
5810 +extern void exit_ext3_xattr_user(void);
5812 +# else /* CONFIG_EXT3_FS_XATTR_USER */
5815 +init_ext3_xattr_user(void)
5821 +exit_ext3_xattr_user(void)
5825 +#endif /* CONFIG_EXT3_FS_XATTR_USER */
5827 +#endif /* __KERNEL__ */
5829 Index: linux-2.4.19-pre1/include/linux/fs.h
5830 ===================================================================
5831 --- linux-2.4.19-pre1.orig/include/linux/fs.h 2004-01-14 01:11:48.000000000 +0300
5832 +++ linux-2.4.19-pre1/include/linux/fs.h 2004-01-14 01:11:49.000000000 +0300
5833 @@ -872,6 +872,10 @@
5834 int (*setattr) (struct dentry *, struct iattr *);
5835 int (*setattr_raw) (struct inode *, struct iattr *);
5836 int (*getattr) (struct dentry *, struct iattr *);
5837 + int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5838 + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5839 + ssize_t (*listxattr) (struct dentry *, char *, size_t);
5840 + int (*removexattr) (struct dentry *, const char *);
5844 Index: linux-2.4.19-pre1/include/linux/mbcache.h
5845 ===================================================================
5846 --- linux-2.4.19-pre1.orig/include/linux/mbcache.h 2003-01-30 13:24:37.000000000 +0300
5847 +++ linux-2.4.19-pre1/include/linux/mbcache.h 2004-01-14 01:11:49.000000000 +0300
5850 + File: linux/mbcache.h
5852 + (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5855 +/* Hardwire the number of additional indexes */
5856 +#define MB_CACHE_INDEXES_COUNT 1
5858 +struct mb_cache_entry;
5860 +struct mb_cache_op {
5861 + int (*free)(struct mb_cache_entry *, int);
5865 + struct list_head c_cache_list;
5866 + const char *c_name;
5867 + struct mb_cache_op c_op;
5868 + atomic_t c_entry_count;
5869 + int c_bucket_count;
5870 +#ifndef MB_CACHE_INDEXES_COUNT
5871 + int c_indexes_count;
5873 + kmem_cache_t *c_entry_cache;
5874 + struct list_head *c_block_hash;
5875 + struct list_head *c_indexes_hash[0];
5878 +struct mb_cache_entry_index {
5879 + struct list_head o_list;
5880 + unsigned int o_key;
5883 +struct mb_cache_entry {
5884 + struct list_head e_lru_list;
5885 + struct mb_cache *e_cache;
5888 + unsigned long e_block;
5889 + struct list_head e_block_list;
5890 + struct mb_cache_entry_index e_indexes[0];
5893 +/* Functions on caches */
5895 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5897 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5898 +void mb_cache_destroy(struct mb_cache *);
5900 +/* Functions on cache entries */
5902 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5903 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5905 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5906 +void mb_cache_entry_release(struct mb_cache_entry *);
5907 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5908 +void mb_cache_entry_free(struct mb_cache_entry *);
5909 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5910 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5912 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5913 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5914 + kdev_t, unsigned int);
5915 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5916 + kdev_t, unsigned int);
5918 Index: linux-2.4.19-pre1/include/linux/xattr.h
5919 ===================================================================
5920 --- linux-2.4.19-pre1.orig/include/linux/xattr.h 2003-01-30 13:24:37.000000000 +0300
5921 +++ linux-2.4.19-pre1/include/linux/xattr.h 2004-01-14 01:11:49.000000000 +0300
5924 + File: linux/xattr.h
5926 + Extended attributes handling.
5928 + Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
5929 + Copyright (c) 2001-2002 Silicon Graphics, Inc. All Rights Reserved.
5931 +#ifndef _LINUX_XATTR_H
5932 +#define _LINUX_XATTR_H
5934 +#define XATTR_CREATE 0x1 /* set the value, fail if attr already exists */
5935 +#define XATTR_REPLACE 0x2 /* set the value, fail if attr does not exist */
5937 +#endif /* _LINUX_XATTR_H */
5938 Index: linux-2.4.19-pre1/include/linux/kernel.h
5939 ===================================================================
5940 --- linux-2.4.19-pre1.orig/include/linux/kernel.h 2004-01-14 01:10:37.000000000 +0300
5941 +++ linux-2.4.19-pre1/include/linux/kernel.h 2004-01-14 01:16:51.000000000 +0300
5943 #include <linux/linkage.h>
5944 #include <linux/stddef.h>
5945 #include <linux/types.h>
5946 +#include <linux/compiler.h>
5948 /* Optimization barrier */
5949 /* The "volatile" is due to gcc bugs */
5950 Index: linux-2.4.19-pre1/include/linux/limits.h
5951 ===================================================================
5952 --- linux-2.4.19-pre1.orig/include/linux/limits.h 2004-01-14 01:10:37.000000000 +0300
5953 +++ linux-2.4.19-pre1/include/linux/limits.h 2004-01-14 01:22:08.000000000 +0300
5955 #define NAME_MAX 255 /* # chars in a file name */
5956 #define PATH_MAX 4096 /* # chars in a path name including nul */
5957 #define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
5958 +#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
5959 +#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
5960 +#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
5962 #define RTSIG_MAX 32
5964 Index: linux-2.4.19-pre1/kernel/ksyms.c
5965 ===================================================================
5966 --- linux-2.4.19-pre1.orig/kernel/ksyms.c 2004-01-14 01:11:48.000000000 +0300
5967 +++ linux-2.4.19-pre1/kernel/ksyms.c 2004-01-14 01:11:49.000000000 +0300
5970 #include <linux/config.h>
5971 #include <linux/slab.h>
5972 +#include <linux/cache_def.h>
5973 #include <linux/module.h>
5974 #include <linux/blkdev.h>
5975 #include <linux/cdrom.h>
5977 EXPORT_SYMBOL(exit_files);
5978 EXPORT_SYMBOL(exit_fs);
5979 EXPORT_SYMBOL(exit_sighand);
5980 +EXPORT_SYMBOL(copy_fs_struct);
5982 /* internal kernel memory management */
5983 EXPORT_SYMBOL(_alloc_pages);
5985 EXPORT_SYMBOL(kmem_cache_shrink);
5986 EXPORT_SYMBOL(kmem_cache_alloc);
5987 EXPORT_SYMBOL(kmem_cache_free);
5988 +EXPORT_SYMBOL(register_cache);
5989 +EXPORT_SYMBOL(unregister_cache);
5990 EXPORT_SYMBOL(kmalloc);
5991 EXPORT_SYMBOL(kfree);
5992 EXPORT_SYMBOL(vfree);
5993 Index: linux-2.4.19-pre1/mm/vmscan.c
5994 ===================================================================
5995 --- linux-2.4.19-pre1.orig/mm/vmscan.c 2004-01-14 01:10:37.000000000 +0300
5996 +++ linux-2.4.19-pre1/mm/vmscan.c 2004-01-14 01:11:49.000000000 +0300
5998 #include <linux/kernel_stat.h>
5999 #include <linux/swap.h>
6000 #include <linux/swapctl.h>
6001 +#include <linux/cache_def.h>
6002 #include <linux/smp_lock.h>
6003 #include <linux/pagemap.h>
6004 #include <linux/init.h>
6007 #define DEF_PRIORITY (6)
6009 +static DECLARE_MUTEX(other_caches_sem);
6010 +static LIST_HEAD(cache_definitions);
6012 +void register_cache(struct cache_definition *cache)
6014 + down(&other_caches_sem);
6015 + list_add(&cache->link, &cache_definitions);
6016 + up(&other_caches_sem);
6019 +void unregister_cache(struct cache_definition *cache)
6021 + down(&other_caches_sem);
6022 + list_del(&cache->link);
6023 + up(&other_caches_sem);
6026 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
6028 + struct list_head *p;
6030 + if (down_trylock(&other_caches_sem))
6033 + list_for_each_prev(p, &cache_definitions) {
6034 + struct cache_definition *cache =
6035 + list_entry(p, struct cache_definition, link);
6037 + cache->shrink(priority, gfp_mask);
6039 + up(&other_caches_sem);
6043 * The swap-out function returns 1 if it successfully
6044 * scanned all the pages it was asked to (`count').
6047 shrink_dcache_memory(priority, gfp_mask);
6048 shrink_icache_memory(priority, gfp_mask);
6049 + shrink_other_caches(priority, gfp_mask);
6051 shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);