1 Index: linux-2.4.29/Documentation/Configure.help
2 ===================================================================
3 --- linux-2.4.29.orig/Documentation/Configure.help 2005-04-07 18:55:00.000000000 +0300
4 +++ linux-2.4.29/Documentation/Configure.help 2005-05-03 17:59:40.363127040 +0300
5 @@ -16679,6 +16679,39 @@
6 be compiled as a module, and so this could be dangerous. Most
7 everyone wants to say Y here.
9 +Ext2 extended attributes
11 + Extended attributes are name:value pairs associated with inodes by
12 + the kernel or by users (see the attr(5) manual page, or visit
13 + <http://acl.bestbits.at/> for details).
17 +Ext2 extended attribute block sharing
18 +CONFIG_EXT2_FS_XATTR_SHARING
19 + This options enables code for sharing identical extended attribute
20 + blocks among multiple inodes.
24 +Ext2 extended user attributes
25 +CONFIG_EXT2_FS_XATTR_USER
26 + This option enables extended user attributes on ext2. Processes can
27 + associate extended user attributes with inodes to store additional
28 + information such as the character encoding of files, etc. (see the
29 + attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
33 +Ext2 trusted extended attributes
34 +CONFIG_EXT2_FS_XATTR_TRUSTED
35 + This option enables extended attributes on ext2 that are accessible
36 + (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
37 + is only the super user. Trusted extended attributes are meant for
38 + implementing system/security services.
42 Ext3 journalling file system support (EXPERIMENTAL)
44 This is the journalling version of the Second extended file system
45 @@ -16711,6 +16744,39 @@
46 of your root partition (the one containing the directory /) cannot
47 be compiled as a module, and so this may be dangerous.
49 +Ext3 extended attributes
51 + Extended attributes are name:value pairs associated with inodes by
52 + the kernel or by users (see the attr(5) manual page, or visit
53 + <http://acl.bestbits.at/> for details).
57 +Ext3 extended attribute block sharing
58 +CONFIG_EXT3_FS_XATTR_SHARING
59 + This options enables code for sharing identical extended attribute
60 + blocks among multiple inodes.
64 +Ext3 extended user attributes
65 +CONFIG_EXT3_FS_XATTR_USER
66 + This option enables extended user attributes on ext3. Processes can
67 + associate extended user attributes with inodes to store additional
68 + information such as the character encoding of files, etc. (see the
69 + attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
73 +Ext3 trusted extended attributes
74 +CONFIG_EXT3_FS_XATTR_TRUSTED
75 + This option enables extended attributes on ext3 that are accessible
76 + (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
77 + is only the super user. Trusted extended attributes are meant for
78 + implementing system/security services.
82 Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
84 This is a generic journalling layer for block devices. It is
85 Index: linux-2.4.29/arch/alpha/defconfig
86 ===================================================================
87 --- linux-2.4.29.orig/arch/alpha/defconfig 2005-04-07 18:53:42.000000000 +0300
88 +++ linux-2.4.29/arch/alpha/defconfig 2005-05-03 17:59:40.365126736 +0300
91 # Automatically generated make config: don't edit
93 +CONFIG_EXT3_FS_XATTR=y
94 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
95 +# CONFIG_EXT3_FS_XATTR_USER is not set
96 +# CONFIG_EXT2_FS_XATTR is not set
97 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
98 +# CONFIG_EXT2_FS_XATTR_USER is not set
99 +# CONFIG_FS_MBCACHE is not set
101 # CONFIG_UID16 is not set
102 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
103 Index: linux-2.4.29/arch/alpha/kernel/entry.S
104 ===================================================================
105 --- linux-2.4.29.orig/arch/alpha/kernel/entry.S 2005-04-07 18:52:17.000000000 +0300
106 +++ linux-2.4.29/arch/alpha/kernel/entry.S 2005-05-03 17:59:40.367126432 +0300
107 @@ -1154,6 +1154,18 @@
109 .quad sys_ni_syscall /* 380, sys_security */
112 + .quad sys_lsetxattr
113 + .quad sys_fsetxattr
114 + .quad sys_getxattr /* 385 */
115 + .quad sys_lgetxattr
116 + .quad sys_fgetxattr
117 + .quad sys_listxattr
118 + .quad sys_llistxattr
119 + .quad sys_flistxattr /* 390 */
120 + .quad sys_removexattr
121 + .quad sys_lremovexattr
122 + .quad sys_fremovexattr
124 /* Remember to update everything, kids. */
125 .ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
126 Index: linux-2.4.29/arch/arm/defconfig
127 ===================================================================
128 --- linux-2.4.29.orig/arch/arm/defconfig 2005-04-07 18:53:03.000000000 +0300
129 +++ linux-2.4.29/arch/arm/defconfig 2005-05-03 17:59:40.369126128 +0300
132 # Automatically generated make config: don't edit
134 +CONFIG_EXT3_FS_XATTR=y
135 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
136 +# CONFIG_EXT3_FS_XATTR_USER is not set
137 +# CONFIG_EXT2_FS_XATTR is not set
138 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
139 +# CONFIG_EXT2_FS_XATTR_USER is not set
140 +# CONFIG_FS_MBCACHE is not set
142 # CONFIG_EISA is not set
143 # CONFIG_SBUS is not set
144 Index: linux-2.4.29/arch/arm/kernel/calls.S
145 ===================================================================
146 --- linux-2.4.29.orig/arch/arm/kernel/calls.S 2005-04-07 18:55:23.000000000 +0300
147 +++ linux-2.4.29/arch/arm/kernel/calls.S 2005-05-03 17:59:40.371125824 +0300
148 @@ -240,18 +240,18 @@
149 .long SYMBOL_NAME(sys_ni_syscall) /* Security */
150 .long SYMBOL_NAME(sys_gettid)
151 /* 225 */ .long SYMBOL_NAME(sys_readahead)
152 - .long SYMBOL_NAME(sys_ni_syscall) /* setxattr */
153 - .long SYMBOL_NAME(sys_ni_syscall) /* lsetxattr */
154 - .long SYMBOL_NAME(sys_ni_syscall) /* fsetxattr */
155 - .long SYMBOL_NAME(sys_ni_syscall) /* getxattr */
156 -/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* lgetxattr */
157 - .long SYMBOL_NAME(sys_ni_syscall) /* fgetxattr */
158 - .long SYMBOL_NAME(sys_ni_syscall) /* listxattr */
159 - .long SYMBOL_NAME(sys_ni_syscall) /* llistxattr */
160 - .long SYMBOL_NAME(sys_ni_syscall) /* flistxattr */
161 -/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* removexattr */
162 - .long SYMBOL_NAME(sys_ni_syscall) /* lremovexattr */
163 - .long SYMBOL_NAME(sys_ni_syscall) /* fremovexattr */
164 + .long SYMBOL_NAME(sys_setxattr)
165 + .long SYMBOL_NAME(sys_lsetxattr)
166 + .long SYMBOL_NAME(sys_fsetxattr)
167 + .long SYMBOL_NAME(sys_getxattr)
168 +/* 230 */ .long SYMBOL_NAME(sys_lgetxattr)
169 + .long SYMBOL_NAME(sys_fgetxattr)
170 + .long SYMBOL_NAME(sys_listxattr)
171 + .long SYMBOL_NAME(sys_llistxattr)
172 + .long SYMBOL_NAME(sys_flistxattr)
173 +/* 235 */ .long SYMBOL_NAME(sys_removexattr)
174 + .long SYMBOL_NAME(sys_lremovexattr)
175 + .long SYMBOL_NAME(sys_fremovexattr)
176 .long SYMBOL_NAME(sys_tkill)
177 .long SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */
178 /* 240 */ .long SYMBOL_NAME(sys_ni_syscall) /* futex */
179 Index: linux-2.4.29/arch/i386/defconfig
180 ===================================================================
181 --- linux-2.4.29.orig/arch/i386/defconfig 2005-04-07 18:52:37.000000000 +0300
182 +++ linux-2.4.29/arch/i386/defconfig 2005-05-03 17:59:40.372125672 +0300
185 # Automatically generated make config: don't edit
187 +CONFIG_EXT3_FS_XATTR=y
188 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
189 +# CONFIG_EXT3_FS_XATTR_USER is not set
190 +# CONFIG_EXT2_FS_XATTR is not set
191 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
192 +# CONFIG_EXT2_FS_XATTR_USER is not set
193 +# CONFIG_FS_MBCACHE is not set
195 # CONFIG_SBUS is not set
197 Index: linux-2.4.29/arch/ia64/defconfig
198 ===================================================================
199 --- linux-2.4.29.orig/arch/ia64/defconfig 2005-04-07 18:52:32.000000000 +0300
200 +++ linux-2.4.29/arch/ia64/defconfig 2005-05-03 17:59:40.374125368 +0300
203 # Automatically generated make config: don't edit
205 +CONFIG_EXT3_FS_XATTR=y
206 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
207 +# CONFIG_EXT3_FS_XATTR_USER is not set
208 +# CONFIG_EXT2_FS_XATTR is not set
209 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
210 +# CONFIG_EXT2_FS_XATTR_USER is not set
211 +# CONFIG_FS_MBCACHE is not set
214 # Code maturity level options
215 Index: linux-2.4.29/arch/m68k/defconfig
216 ===================================================================
217 --- linux-2.4.29.orig/arch/m68k/defconfig 2005-04-07 18:52:26.000000000 +0300
218 +++ linux-2.4.29/arch/m68k/defconfig 2005-05-03 17:59:40.375125216 +0300
221 # Automatically generated make config: don't edit
223 +CONFIG_EXT3_FS_XATTR=y
224 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
225 +# CONFIG_EXT3_FS_XATTR_USER is not set
226 +# CONFIG_EXT2_FS_XATTR is not set
227 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
228 +# CONFIG_EXT2_FS_XATTR_USER is not set
229 +# CONFIG_FS_MBCACHE is not set
233 Index: linux-2.4.29/arch/mips/defconfig
234 ===================================================================
235 --- linux-2.4.29.orig/arch/mips/defconfig 2005-04-07 18:52:42.000000000 +0300
236 +++ linux-2.4.29/arch/mips/defconfig 2005-05-03 17:59:40.376125064 +0300
239 # Automatically generated make config: don't edit
241 +CONFIG_EXT3_FS_XATTR=y
242 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
243 +# CONFIG_EXT3_FS_XATTR_USER is not set
244 +# CONFIG_EXT2_FS_XATTR is not set
245 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
246 +# CONFIG_EXT2_FS_XATTR_USER is not set
247 +# CONFIG_FS_MBCACHE is not set
250 # CONFIG_MIPS64 is not set
251 Index: linux-2.4.29/arch/mips64/defconfig
252 ===================================================================
253 --- linux-2.4.29.orig/arch/mips64/defconfig 2005-04-07 18:52:47.000000000 +0300
254 +++ linux-2.4.29/arch/mips64/defconfig 2005-05-03 17:59:40.378124760 +0300
257 # Automatically generated make config: don't edit
259 +CONFIG_EXT3_FS_XATTR=y
260 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
261 +# CONFIG_EXT3_FS_XATTR_USER is not set
262 +# CONFIG_EXT2_FS_XATTR is not set
263 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
264 +# CONFIG_EXT2_FS_XATTR_USER is not set
265 +# CONFIG_FS_MBCACHE is not set
267 # CONFIG_MIPS32 is not set
269 Index: linux-2.4.29/arch/s390/defconfig
270 ===================================================================
271 --- linux-2.4.29.orig/arch/s390/defconfig 2005-04-07 18:54:49.000000000 +0300
272 +++ linux-2.4.29/arch/s390/defconfig 2005-05-03 17:59:40.379124608 +0300
275 # Automatically generated make config: don't edit
277 +CONFIG_EXT3_FS_XATTR=y
278 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
279 +# CONFIG_EXT3_FS_XATTR_USER is not set
280 +# CONFIG_EXT2_FS_XATTR is not set
281 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
282 +# CONFIG_EXT2_FS_XATTR_USER is not set
283 +# CONFIG_FS_MBCACHE is not set
284 # CONFIG_ISA is not set
285 # CONFIG_EISA is not set
286 # CONFIG_MCA is not set
287 Index: linux-2.4.29/arch/s390/kernel/entry.S
288 ===================================================================
289 --- linux-2.4.29.orig/arch/s390/kernel/entry.S 2005-04-07 18:52:47.000000000 +0300
290 +++ linux-2.4.29/arch/s390/kernel/entry.S 2005-05-03 17:59:40.381124304 +0300
291 @@ -558,18 +558,18 @@
295 - .long sys_ni_syscall /* 224 - reserved for setxattr */
296 - .long sys_ni_syscall /* 225 - reserved for lsetxattr */
297 - .long sys_ni_syscall /* 226 - reserved for fsetxattr */
298 - .long sys_ni_syscall /* 227 - reserved for getxattr */
299 - .long sys_ni_syscall /* 228 - reserved for lgetxattr */
300 - .long sys_ni_syscall /* 229 - reserved for fgetxattr */
301 - .long sys_ni_syscall /* 230 - reserved for listxattr */
302 - .long sys_ni_syscall /* 231 - reserved for llistxattr */
303 - .long sys_ni_syscall /* 232 - reserved for flistxattr */
304 - .long sys_ni_syscall /* 233 - reserved for removexattr */
305 - .long sys_ni_syscall /* 234 - reserved for lremovexattr */
306 - .long sys_ni_syscall /* 235 - reserved for fremovexattr */
308 + .long sys_lsetxattr /* 225 */
309 + .long sys_fsetxattr
311 + .long sys_lgetxattr
312 + .long sys_fgetxattr
313 + .long sys_listxattr /* 230 */
314 + .long sys_llistxattr
315 + .long sys_flistxattr
316 + .long sys_removexattr
317 + .long sys_lremovexattr
318 + .long sys_fremovexattr /* 235 */
322 Index: linux-2.4.29/arch/s390x/defconfig
323 ===================================================================
324 --- linux-2.4.29.orig/arch/s390x/defconfig 2005-04-07 18:52:17.000000000 +0300
325 +++ linux-2.4.29/arch/s390x/defconfig 2005-05-03 17:59:40.382124152 +0300
328 # Automatically generated make config: don't edit
330 +CONFIG_EXT3_FS_XATTR=y
331 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
332 +# CONFIG_EXT3_FS_XATTR_USER is not set
333 +# CONFIG_EXT2_FS_XATTR is not set
334 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
335 +# CONFIG_EXT2_FS_XATTR_USER is not set
336 +# CONFIG_FS_MBCACHE is not set
337 # CONFIG_ISA is not set
338 # CONFIG_EISA is not set
339 # CONFIG_MCA is not set
340 Index: linux-2.4.29/arch/s390x/kernel/entry.S
341 ===================================================================
342 --- linux-2.4.29.orig/arch/s390x/kernel/entry.S 2005-04-07 18:52:58.000000000 +0300
343 +++ linux-2.4.29/arch/s390x/kernel/entry.S 2005-05-03 17:59:40.384123848 +0300
344 @@ -591,18 +591,18 @@
345 .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
346 .long SYSCALL(sys_readahead,sys32_readahead)
347 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
348 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
349 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
350 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
351 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
352 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
353 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
354 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
355 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
356 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
357 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
358 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
359 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
360 + .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
361 + .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
362 + .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
363 + .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
364 + .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
365 + .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
366 + .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
367 + .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
368 + .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
369 + .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
370 + .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
371 + .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
372 .long SYSCALL(sys_gettid,sys_gettid)
373 .long SYSCALL(sys_tkill,sys_tkill)
375 Index: linux-2.4.29/arch/s390x/kernel/wrapper32.S
376 ===================================================================
377 --- linux-2.4.29.orig/arch/s390x/kernel/wrapper32.S 2005-04-07 18:55:12.000000000 +0300
378 +++ linux-2.4.29/arch/s390x/kernel/wrapper32.S 2005-05-03 17:59:40.386123544 +0300
379 @@ -1098,6 +1098,98 @@
381 jg sys32_fstat64 # branch to system call
383 + .globl sys32_setxattr_wrapper
384 +sys32_setxattr_wrapper:
385 + llgtr %r2,%r2 # char *
386 + llgtr %r3,%r3 # char *
387 + llgtr %r4,%r4 # void *
388 + llgfr %r5,%r5 # size_t
392 + .globl sys32_lsetxattr_wrapper
393 +sys32_lsetxattr_wrapper:
394 + llgtr %r2,%r2 # char *
395 + llgtr %r3,%r3 # char *
396 + llgtr %r4,%r4 # void *
397 + llgfr %r5,%r5 # size_t
401 + .globl sys32_fsetxattr_wrapper
402 +sys32_fsetxattr_wrapper:
404 + llgtr %r3,%r3 # char *
405 + llgtr %r4,%r4 # void *
406 + llgfr %r5,%r5 # size_t
410 + .globl sys32_getxattr_wrapper
411 +sys32_getxattr_wrapper:
412 + llgtr %r2,%r2 # char *
413 + llgtr %r3,%r3 # char *
414 + llgtr %r4,%r4 # void *
415 + llgfr %r5,%r5 # size_t
418 + .globl sys32_lgetxattr_wrapper
419 +sys32_lgetxattr_wrapper:
420 + llgtr %r2,%r2 # char *
421 + llgtr %r3,%r3 # char *
422 + llgtr %r4,%r4 # void *
423 + llgfr %r5,%r5 # size_t
426 + .globl sys32_fgetxattr_wrapper
427 +sys32_fgetxattr_wrapper:
429 + llgtr %r3,%r3 # char *
430 + llgtr %r4,%r4 # void *
431 + llgfr %r5,%r5 # size_t
434 + .globl sys32_listxattr_wrapper
435 +sys32_listxattr_wrapper:
436 + llgtr %r2,%r2 # char *
437 + llgtr %r3,%r3 # char *
438 + llgfr %r4,%r4 # size_t
441 + .globl sys32_llistxattr_wrapper
442 +sys32_llistxattr_wrapper:
443 + llgtr %r2,%r2 # char *
444 + llgtr %r3,%r3 # char *
445 + llgfr %r4,%r4 # size_t
448 + .globl sys32_flistxattr_wrapper
449 +sys32_flistxattr_wrapper:
451 + llgtr %r3,%r3 # char *
452 + llgfr %r4,%r4 # size_t
455 + .globl sys32_removexattr_wrapper
456 +sys32_removexattr_wrapper:
457 + llgtr %r2,%r2 # char *
458 + llgtr %r3,%r3 # char *
461 + .globl sys32_lremovexattr_wrapper
462 +sys32_lremovexattr_wrapper:
463 + llgtr %r2,%r2 # char *
464 + llgtr %r3,%r3 # char *
465 + jg sys_lremovexattr
467 + .globl sys32_fremovexattr_wrapper
468 +sys32_fremovexattr_wrapper:
470 + llgtr %r3,%r3 # char *
471 + jg sys_fremovexattr
475 .globl sys32_stime_wrapper
477 llgtr %r2,%r2 # int *
478 Index: linux-2.4.29/arch/sparc64/defconfig
479 ===================================================================
480 --- linux-2.4.29.orig/arch/sparc64/defconfig 2005-04-07 18:53:09.000000000 +0300
481 +++ linux-2.4.29/arch/sparc64/defconfig 2005-05-03 17:59:40.388123240 +0300
484 # Automatically generated make config: don't edit
486 +CONFIG_EXT3_FS_XATTR=y
487 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
488 +# CONFIG_EXT3_FS_XATTR_USER is not set
489 +# CONFIG_EXT2_FS_XATTR is not set
490 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
491 +# CONFIG_EXT2_FS_XATTR_USER is not set
492 +# CONFIG_FS_MBCACHE is not set
495 # Code maturity level options
496 Index: linux-2.4.29/fs/Config.in
497 ===================================================================
498 --- linux-2.4.29.orig/fs/Config.in 2005-04-07 18:54:16.000000000 +0300
499 +++ linux-2.4.29/fs/Config.in 2005-05-03 17:59:40.389123088 +0300
501 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
503 tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
504 +dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
505 +dep_bool ' Ext3 extended attribute block sharing' \
506 + CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
507 +dep_bool ' Ext3 extended user attributes' \
508 + CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
509 # CONFIG_JBD could be its own option (even modular), but until there are
510 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
511 # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
513 tristate 'ROM file system support' CONFIG_ROMFS_FS
515 tristate 'Second extended fs support' CONFIG_EXT2_FS
516 +dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
517 +dep_bool ' Ext2 extended attribute block sharing' \
518 + CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
519 +dep_bool ' Ext2 extended user attributes' \
520 + CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
522 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
525 define_tristate CONFIG_ZISOFS_FS n
528 +# Meta block cache for Extended Attributes (ext2/ext3)
529 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
530 +define_tristate CONFIG_FS_MBCACHE y
532 mainmenu_option next_comment
533 comment 'Partition Types'
534 source fs/partitions/Config.in
535 Index: linux-2.4.29/fs/Makefile
536 ===================================================================
537 --- linux-2.4.29.orig/fs/Makefile 2005-05-03 17:23:53.969428480 +0300
538 +++ linux-2.4.29/fs/Makefile 2005-05-03 17:59:40.390122936 +0300
541 obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
543 +export-objs += mbcache.o
544 +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
546 # persistent filesystems
547 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
549 Index: linux-2.4.29/fs/ext2/Makefile
550 ===================================================================
551 --- linux-2.4.29.orig/fs/ext2/Makefile 2005-04-07 18:54:32.000000000 +0300
552 +++ linux-2.4.29/fs/ext2/Makefile 2005-05-03 17:59:40.391122784 +0300
554 ioctl.o namei.o super.o symlink.o
557 +export-objs += xattr.o
558 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
559 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
561 include $(TOPDIR)/Rules.make
562 Index: linux-2.4.29/fs/ext2/file.c
563 ===================================================================
564 --- linux-2.4.29.orig/fs/ext2/file.c 2005-04-07 18:53:14.000000000 +0300
565 +++ linux-2.4.29/fs/ext2/file.c 2005-05-03 17:59:40.392122632 +0300
568 #include <linux/fs.h>
569 #include <linux/ext2_fs.h>
570 +#include <linux/ext2_xattr.h>
571 #include <linux/sched.h>
576 struct inode_operations ext2_file_inode_operations = {
577 truncate: ext2_truncate,
578 + setxattr: ext2_setxattr,
579 + getxattr: ext2_getxattr,
580 + listxattr: ext2_listxattr,
581 + removexattr: ext2_removexattr,
583 Index: linux-2.4.29/fs/ext2/ialloc.c
584 ===================================================================
585 --- linux-2.4.29.orig/fs/ext2/ialloc.c 2005-04-07 18:53:47.000000000 +0300
586 +++ linux-2.4.29/fs/ext2/ialloc.c 2005-05-03 17:59:40.393122480 +0300
588 #include <linux/config.h>
589 #include <linux/fs.h>
590 #include <linux/ext2_fs.h>
591 +#include <linux/ext2_xattr.h>
592 #include <linux/locks.h>
593 #include <linux/quotaops.h>
597 if (!is_bad_inode(inode)) {
598 /* Quota is already initialized in iput() */
599 + ext2_xattr_delete_inode(inode);
600 DQUOT_FREE_INODE(inode);
603 Index: linux-2.4.29/fs/ext2/inode.c
604 ===================================================================
605 --- linux-2.4.29.orig/fs/ext2/inode.c 2005-04-07 18:52:32.000000000 +0300
606 +++ linux-2.4.29/fs/ext2/inode.c 2005-05-03 17:59:40.396122024 +0300
611 - if (is_bad_inode(inode) ||
612 - inode->i_ino == EXT2_ACL_IDX_INO ||
613 - inode->i_ino == EXT2_ACL_DATA_INO)
614 + if (is_bad_inode(inode))
616 inode->u.ext2_i.i_dtime = CURRENT_TIME;
617 mark_inode_dirty(inode);
620 if (ext2_inode_is_fast_symlink(inode))
622 + if (ext2_inode_is_fast_symlink(inode))
624 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
628 unsigned long offset;
629 struct ext2_group_desc * gdp;
631 - if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
632 - inode->i_ino != EXT2_ACL_DATA_INO &&
633 + if ((inode->i_ino != EXT2_ROOT_INO &&
634 inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
635 inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
636 ext2_error (inode->i_sb, "ext2_read_inode",
637 @@ -1004,10 +1003,7 @@
638 for (block = 0; block < EXT2_N_BLOCKS; block++)
639 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
641 - if (inode->i_ino == EXT2_ACL_IDX_INO ||
642 - inode->i_ino == EXT2_ACL_DATA_INO)
643 - /* Nothing to do */ ;
644 - else if (S_ISREG(inode->i_mode)) {
645 + if (S_ISREG(inode->i_mode)) {
646 inode->i_op = &ext2_file_inode_operations;
647 inode->i_fop = &ext2_file_operations;
648 inode->i_mapping->a_ops = &ext2_aops;
649 @@ -1019,12 +1015,14 @@
650 if (ext2_inode_is_fast_symlink(inode))
651 inode->i_op = &ext2_fast_symlink_inode_operations;
653 - inode->i_op = &page_symlink_inode_operations;
654 + inode->i_op = &ext2_symlink_inode_operations;
655 inode->i_mapping->a_ops = &ext2_aops;
659 + inode->i_op = &ext2_special_inode_operations;
660 init_special_inode(inode, inode->i_mode,
661 le32_to_cpu(raw_inode->i_block[0]));
664 inode->i_attr_flags = 0;
665 ext2_set_inode_flags(inode);
666 Index: linux-2.4.29/fs/ext2/namei.c
667 ===================================================================
668 --- linux-2.4.29.orig/fs/ext2/namei.c 2005-04-07 18:54:50.000000000 +0300
669 +++ linux-2.4.29/fs/ext2/namei.c 2005-05-03 17:59:40.397121872 +0300
672 #include <linux/fs.h>
673 #include <linux/ext2_fs.h>
674 +#include <linux/ext2_xattr.h>
675 #include <linux/pagemap.h>
680 if (l > sizeof (inode->u.ext2_i.i_data)) {
682 - inode->i_op = &page_symlink_inode_operations;
683 + inode->i_op = &ext2_symlink_inode_operations;
684 inode->i_mapping->a_ops = &ext2_aops;
685 err = block_symlink(inode, symname, l);
691 + setxattr: ext2_setxattr,
692 + getxattr: ext2_getxattr,
693 + listxattr: ext2_listxattr,
694 + removexattr: ext2_removexattr,
697 +struct inode_operations ext2_special_inode_operations = {
698 + setxattr: ext2_setxattr,
699 + getxattr: ext2_getxattr,
700 + listxattr: ext2_listxattr,
701 + removexattr: ext2_removexattr,
703 Index: linux-2.4.29/fs/ext2/super.c
704 ===================================================================
705 --- linux-2.4.29.orig/fs/ext2/super.c 2005-04-07 18:54:16.000000000 +0300
706 +++ linux-2.4.29/fs/ext2/super.c 2005-05-03 17:59:40.400121416 +0300
708 #include <linux/string.h>
709 #include <linux/fs.h>
710 #include <linux/ext2_fs.h>
711 +#include <linux/ext2_xattr.h>
712 #include <linux/slab.h>
713 #include <linux/init.h>
714 #include <linux/locks.h>
719 + ext2_xattr_put_super(sb);
720 if (!(sb->s_flags & MS_RDONLY)) {
721 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
724 this_char = strtok (NULL, ",")) {
725 if ((value = strchr (this_char, '=')) != NULL)
727 +#ifdef CONFIG_EXT2_FS_XATTR_USER
728 + if (!strcmp (this_char, "user_xattr"))
729 + set_opt (*mount_options, XATTR_USER);
730 + else if (!strcmp (this_char, "nouser_xattr"))
731 + clear_opt (*mount_options, XATTR_USER);
734 if (!strcmp (this_char, "bsddf"))
735 clear_opt (*mount_options, MINIX_DF);
736 else if (!strcmp (this_char, "nouid32")) {
738 blocksize = BLOCK_SIZE;
740 sb->u.ext2_sb.s_mount_opt = 0;
741 +#ifdef CONFIG_EXT2_FS_XATTR_USER
742 + /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
744 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
745 &sb->u.ext2_sb.s_mount_opt)) {
747 @@ -840,12 +852,27 @@
749 static int __init init_ext2_fs(void)
751 - return register_filesystem(&ext2_fs_type);
752 + int error = init_ext2_xattr();
755 + error = init_ext2_xattr_user();
758 + error = register_filesystem(&ext2_fs_type);
762 + exit_ext2_xattr_user();
768 static void __exit exit_ext2_fs(void)
770 unregister_filesystem(&ext2_fs_type);
771 + exit_ext2_xattr_user();
776 Index: linux-2.4.29/fs/ext2/symlink.c
777 ===================================================================
778 --- linux-2.4.29.orig/fs/ext2/symlink.c 2005-04-07 18:52:53.000000000 +0300
779 +++ linux-2.4.29/fs/ext2/symlink.c 2005-05-03 17:59:40.400121416 +0300
782 #include <linux/fs.h>
783 #include <linux/ext2_fs.h>
784 +#include <linux/ext2_xattr.h>
786 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
789 return vfs_follow_link(nd, s);
792 +struct inode_operations ext2_symlink_inode_operations = {
793 + readlink: page_readlink,
794 + follow_link: page_follow_link,
795 + setxattr: ext2_setxattr,
796 + getxattr: ext2_getxattr,
797 + listxattr: ext2_listxattr,
798 + removexattr: ext2_removexattr,
801 struct inode_operations ext2_fast_symlink_inode_operations = {
802 readlink: ext2_readlink,
803 follow_link: ext2_follow_link,
804 + setxattr: ext2_setxattr,
805 + getxattr: ext2_getxattr,
806 + listxattr: ext2_listxattr,
807 + removexattr: ext2_removexattr,
809 Index: linux-2.4.29/fs/ext2/xattr.c
810 ===================================================================
811 --- linux-2.4.29.orig/fs/ext2/xattr.c 2005-05-03 17:59:40.233146800 +0300
812 +++ linux-2.4.29/fs/ext2/xattr.c 2005-05-03 17:59:40.405120656 +0300
815 + * linux/fs/ext2/xattr.c
817 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
819 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
820 + * Extended attributes for symlinks and special files added per
821 + * suggestion of Luka Renko <luka.renko@hermes.si>.
825 + * Extended attributes are stored on disk blocks allocated outside of
826 + * any inode. The i_file_acl field is then made to point to this allocated
827 + * block. If all extended attributes of an inode are identical, these
828 + * inodes may share the same extended attribute block. Such situations
829 + * are automatically detected by keeping a cache of recent attribute block
830 + * numbers and hashes over the block's contents in memory.
833 + * Extended attribute block layout:
835 + * +------------------+
838 + * | entry 2 | | growing downwards
840 + * | four null bytes |
843 + * | value 3 | | growing upwards
845 + * +------------------+
847 + * The block header is followed by multiple entry descriptors. These entry
848 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
849 + * byte boundaries. The entry descriptors are sorted by attribute name,
850 + * so that two extended attribute blocks can be compared efficiently.
852 + * Attribute values are aligned to the end of the block, stored in
853 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
854 + * boundaries. No additional gaps are left between them.
858 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
859 + * the xattr inode operations are called, so we are guaranteed that only one
860 + * processes accesses extended attributes of an inode at any time.
862 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
863 + * only a single process is modifying an extended attribute block, even
864 + * if the block is shared among inodes.
866 + * Note for porting to 2.5
867 + * -----------------------
868 + * The BKL will no longer be held in the xattr inode operations.
871 +#include <linux/module.h>
872 +#include <linux/locks.h>
873 +#include <linux/slab.h>
874 +#include <linux/fs.h>
875 +#include <linux/ext2_fs.h>
876 +#include <linux/ext2_xattr.h>
877 +#include <linux/mbcache.h>
878 +#include <linux/quotaops.h>
879 +#include <asm/semaphore.h>
880 +#include <linux/compatmac.h>
882 +/* These symbols may be needed by a module. */
883 +EXPORT_SYMBOL(ext2_xattr_register);
884 +EXPORT_SYMBOL(ext2_xattr_unregister);
885 +EXPORT_SYMBOL(ext2_xattr_get);
886 +EXPORT_SYMBOL(ext2_xattr_list);
887 +EXPORT_SYMBOL(ext2_xattr_set);
889 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
890 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
893 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
894 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
895 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
896 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
898 +#ifdef EXT2_XATTR_DEBUG
899 +# define ea_idebug(inode, f...) do { \
900 + printk(KERN_DEBUG "inode %s:%ld: ", \
901 + kdevname(inode->i_dev), inode->i_ino); \
905 +# define ea_bdebug(bh, f...) do { \
906 + printk(KERN_DEBUG "block %s:%ld: ", \
907 + kdevname(bh->b_dev), bh->b_blocknr); \
912 +# define ea_idebug(f...)
913 +# define ea_bdebug(f...)
916 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
917 + struct ext2_xattr_header *);
919 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
921 +static int ext2_xattr_cache_insert(struct buffer_head *);
922 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
923 + struct ext2_xattr_header *);
924 +static void ext2_xattr_cache_remove(struct buffer_head *);
925 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
926 + struct ext2_xattr_entry *);
928 +static struct mb_cache *ext2_xattr_cache;
931 +# define ext2_xattr_cache_insert(bh) 0
932 +# define ext2_xattr_cache_find(inode, header) NULL
933 +# define ext2_xattr_cache_remove(bh) while(0) {}
934 +# define ext2_xattr_rehash(header, entry) while(0) {}
938 + * If a file system does not share extended attributes among inodes,
939 + * we should not need the ext2_xattr_sem semaphore. However, the
940 + * filesystem may still contain shared blocks, so we always take
944 +DECLARE_MUTEX(ext2_xattr_sem);
947 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
949 + struct super_block *sb = inode->i_sb;
950 + int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
951 + EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
953 + /* How can we enforce the allocation? */
954 + int block = ext2_new_block(inode, goal, 0, 0, errp);
957 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
963 +ext2_xattr_quota_alloc(struct inode *inode, int force)
965 + /* How can we enforce the allocation? */
967 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
969 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
971 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
979 +ext2_xattr_quota_free(struct inode *inode)
981 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
982 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
986 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
988 + ext2_free_blocks(inode, block, 1);
989 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
993 +# define ext2_xattr_quota_free(inode) \
994 + DQUOT_FREE_BLOCK(inode, 1)
995 +# define ext2_xattr_free_block(inode, block) \
996 + ext2_free_blocks(inode, block, 1)
999 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1001 +static inline struct buffer_head *
1002 +sb_bread(struct super_block *sb, int block)
1004 + return bread(sb->s_dev, block, sb->s_blocksize);
1007 +static inline struct buffer_head *
1008 +sb_getblk(struct super_block *sb, int block)
1010 + return getblk(sb->s_dev, block, sb->s_blocksize);
1015 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1016 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1019 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1021 + int error = -EINVAL;
1023 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1024 + write_lock(&ext2_handler_lock);
1025 + if (!ext2_xattr_handlers[name_index-1]) {
1026 + ext2_xattr_handlers[name_index-1] = handler;
1029 + write_unlock(&ext2_handler_lock);
1035 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1037 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1038 + write_lock(&ext2_handler_lock);
1039 + ext2_xattr_handlers[name_index-1] = NULL;
1040 + write_unlock(&ext2_handler_lock);
1044 +static inline const char *
1045 +strcmp_prefix(const char *a, const char *a_prefix)
1047 + while (*a_prefix && *a == *a_prefix) {
1051 + return *a_prefix ? NULL : a;
1055 + * Decode the extended attribute name, and translate it into
1056 + * the name_index and name suffix.
1058 +static struct ext2_xattr_handler *
1059 +ext2_xattr_resolve_name(const char **name)
1061 + struct ext2_xattr_handler *handler = NULL;
1066 + read_lock(&ext2_handler_lock);
1067 + for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1068 + if (ext2_xattr_handlers[i]) {
1069 + const char *n = strcmp_prefix(*name,
1070 + ext2_xattr_handlers[i]->prefix);
1072 + handler = ext2_xattr_handlers[i];
1078 + read_unlock(&ext2_handler_lock);
1082 +static inline struct ext2_xattr_handler *
1083 +ext2_xattr_handler(int name_index)
1085 + struct ext2_xattr_handler *handler = NULL;
1086 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1087 + read_lock(&ext2_handler_lock);
1088 + handler = ext2_xattr_handlers[name_index-1];
1089 + read_unlock(&ext2_handler_lock);
1095 + * Inode operation getxattr()
1097 + * dentry->d_inode->i_sem down
1098 + * BKL held [before 2.5.x]
1101 +ext2_getxattr(struct dentry *dentry, const char *name,
1102 + void *buffer, size_t size)
1104 + struct ext2_xattr_handler *handler;
1105 + struct inode *inode = dentry->d_inode;
1107 + handler = ext2_xattr_resolve_name(&name);
1110 + return handler->get(inode, name, buffer, size);
1114 + * Inode operation listxattr()
1116 + * dentry->d_inode->i_sem down
1117 + * BKL held [before 2.5.x]
1120 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1122 + return ext2_xattr_list(dentry->d_inode, buffer, size);
1126 + * Inode operation setxattr()
1128 + * dentry->d_inode->i_sem down
1129 + * BKL held [before 2.5.x]
1132 +ext2_setxattr(struct dentry *dentry, const char *name,
1133 + const void *value, size_t size, int flags)
1135 + struct ext2_xattr_handler *handler;
1136 + struct inode *inode = dentry->d_inode;
1139 + value = ""; /* empty EA, do not remove */
1140 + handler = ext2_xattr_resolve_name(&name);
1143 + return handler->set(inode, name, value, size, flags);
1147 + * Inode operation removexattr()
1149 + * dentry->d_inode->i_sem down
1150 + * BKL held [before 2.5.x]
1153 +ext2_removexattr(struct dentry *dentry, const char *name)
1155 + struct ext2_xattr_handler *handler;
1156 + struct inode *inode = dentry->d_inode;
1158 + handler = ext2_xattr_resolve_name(&name);
1161 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1165 + * ext2_xattr_get()
1167 + * Copy an extended attribute into the buffer
1168 + * provided, or compute the buffer size required.
1169 + * Buffer is NULL to compute the size of the buffer required.
1171 + * Returns a negative error number on failure, or the number of bytes
1172 + * used / required on success.
1175 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1176 + void *buffer, size_t buffer_size)
1178 + struct buffer_head *bh = NULL;
1179 + struct ext2_xattr_entry *entry;
1180 + unsigned int block, size;
1182 + int name_len, error;
1184 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1185 + name_index, name, buffer, (long)buffer_size);
1189 + if (!EXT2_I(inode)->i_file_acl)
1191 + block = EXT2_I(inode)->i_file_acl;
1192 + ea_idebug(inode, "reading block %d", block);
1193 + bh = sb_bread(inode->i_sb, block);
1196 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1197 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1198 + end = bh->b_data + bh->b_size;
1199 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1200 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1201 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
1202 + "inode %ld: bad block %d", inode->i_ino, block);
1206 + /* find named attribute */
1207 + name_len = strlen(name);
1210 + if (name_len > 255)
1212 + entry = FIRST_ENTRY(bh);
1213 + while (!IS_LAST_ENTRY(entry)) {
1214 + struct ext2_xattr_entry *next =
1215 + EXT2_XATTR_NEXT(entry);
1216 + if ((char *)next >= end)
1218 + if (name_index == entry->e_name_index &&
1219 + name_len == entry->e_name_len &&
1220 + memcmp(name, entry->e_name, name_len) == 0)
1224 + /* Check the remaining name entries */
1225 + while (!IS_LAST_ENTRY(entry)) {
1226 + struct ext2_xattr_entry *next =
1227 + EXT2_XATTR_NEXT(entry);
1228 + if ((char *)next >= end)
1232 + if (ext2_xattr_cache_insert(bh))
1233 + ea_idebug(inode, "cache insert failed");
1237 + /* check the buffer size */
1238 + if (entry->e_value_block != 0)
1240 + size = le32_to_cpu(entry->e_value_size);
1241 + if (size > inode->i_sb->s_blocksize ||
1242 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1245 + if (ext2_xattr_cache_insert(bh))
1246 + ea_idebug(inode, "cache insert failed");
1249 + if (size > buffer_size)
1251 + /* return value of attribute */
1252 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1264 + * ext2_xattr_list()
1266 + * Copy a list of attribute names into the buffer
1267 + * provided, or compute the buffer size required.
1268 + * Buffer is NULL to compute the size of the buffer required.
1270 + * Returns a negative error number on failure, or the number of bytes
1271 + * used / required on success.
1274 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1276 + struct buffer_head *bh = NULL;
1277 + struct ext2_xattr_entry *entry;
1278 + unsigned int block, size = 0;
1282 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1283 + buffer, (long)buffer_size);
1285 + if (!EXT2_I(inode)->i_file_acl)
1287 + block = EXT2_I(inode)->i_file_acl;
1288 + ea_idebug(inode, "reading block %d", block);
1289 + bh = sb_bread(inode->i_sb, block);
1292 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1293 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1294 + end = bh->b_data + bh->b_size;
1295 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1296 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1297 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
1298 + "inode %ld: bad block %d", inode->i_ino, block);
1302 + /* compute the size required for the list of attribute names */
1303 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1304 + entry = EXT2_XATTR_NEXT(entry)) {
1305 + struct ext2_xattr_handler *handler;
1306 + struct ext2_xattr_entry *next =
1307 + EXT2_XATTR_NEXT(entry);
1308 + if ((char *)next >= end)
1311 + handler = ext2_xattr_handler(entry->e_name_index);
1313 + size += handler->list(NULL, inode, entry->e_name,
1314 + entry->e_name_len);
1317 + if (ext2_xattr_cache_insert(bh))
1318 + ea_idebug(inode, "cache insert failed");
1324 + if (size > buffer_size)
1328 + /* list the attribute names */
1330 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1331 + entry = EXT2_XATTR_NEXT(entry)) {
1332 + struct ext2_xattr_handler *handler;
1334 + handler = ext2_xattr_handler(entry->e_name_index);
1336 + buf += handler->list(buf, inode, entry->e_name,
1337 + entry->e_name_len);
1348 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1349 + * not set, set it.
1351 +static void ext2_xattr_update_super_block(struct super_block *sb)
1353 + if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1357 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1358 + EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1360 + EXT2_SB(sb)->s_es->s_feature_compat |=
1361 + cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1363 + mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1368 + * ext2_xattr_set()
1370 + * Create, replace or remove an extended attribute for this inode. Buffer
1371 + * is NULL to remove an existing extended attribute, and non-NULL to
1372 + * either replace an existing extended attribute, or create a new extended
1373 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1374 + * specify that an extended attribute must exist and must not exist
1375 + * previous to the call, respectively.
1377 + * Returns 0, or a negative error number on failure.
1380 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1381 + const void *value, size_t value_len, int flags)
1383 + struct super_block *sb = inode->i_sb;
1384 + struct buffer_head *bh = NULL;
1385 + struct ext2_xattr_header *header = NULL;
1386 + struct ext2_xattr_entry *here, *last;
1387 + unsigned int name_len;
1388 + int block = EXT2_I(inode)->i_file_acl;
1389 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
1393 + * header -- Points either into bh, or to a temporarily
1394 + * allocated buffer.
1395 + * here -- The named entry found, or the place for inserting, within
1396 + * the block pointed to by header.
1397 + * last -- Points right after the last named entry within the block
1398 + * pointed to by header.
1399 + * min_offs -- The offset of the first value (values are aligned
1400 + * towards the end of the block).
1401 + * end -- Points right after the block pointed to by header.
1404 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1405 + name_index, name, value, (long)value_len);
1407 + if (IS_RDONLY(inode))
1409 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1411 + if (value == NULL)
1415 + name_len = strlen(name);
1416 + if (name_len > 255 || value_len > sb->s_blocksize)
1418 + down(&ext2_xattr_sem);
1421 + /* The inode already has an extended attribute block. */
1423 + bh = sb_bread(sb, block);
1427 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1428 + atomic_read(&(bh->b_count)),
1429 + le32_to_cpu(HDR(bh)->h_refcount));
1431 + end = bh->b_data + bh->b_size;
1432 + if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1433 + header->h_blocks != cpu_to_le32(1)) {
1434 +bad_block: ext2_error(sb, "ext2_xattr_set",
1435 + "inode %ld: bad block %d", inode->i_ino, block);
1439 + /* Find the named attribute. */
1440 + here = FIRST_ENTRY(bh);
1441 + while (!IS_LAST_ENTRY(here)) {
1442 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1443 + if ((char *)next >= end)
1445 + if (!here->e_value_block && here->e_value_size) {
1446 + int offs = le16_to_cpu(here->e_value_offs);
1447 + if (offs < min_offs)
1450 + not_found = name_index - here->e_name_index;
1452 + not_found = name_len - here->e_name_len;
1454 + not_found = memcmp(name, here->e_name,name_len);
1455 + if (not_found <= 0)
1460 + /* We still need to compute min_offs and last. */
1461 + while (!IS_LAST_ENTRY(last)) {
1462 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1463 + if ((char *)next >= end)
1465 + if (!last->e_value_block && last->e_value_size) {
1466 + int offs = le16_to_cpu(last->e_value_offs);
1467 + if (offs < min_offs)
1473 + /* Check whether we have enough space left. */
1474 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1476 + /* We will use a new extended attribute block. */
1477 + free = sb->s_blocksize -
1478 + sizeof(struct ext2_xattr_header) - sizeof(__u32);
1479 + here = last = NULL; /* avoid gcc uninitialized warning. */
1483 + /* Request to remove a nonexistent attribute? */
1485 + if (flags & XATTR_REPLACE)
1488 + if (value == NULL)
1491 + free -= EXT2_XATTR_LEN(name_len);
1493 + /* Request to create an existing attribute? */
1495 + if (flags & XATTR_CREATE)
1497 + if (!here->e_value_block && here->e_value_size) {
1498 + unsigned int size = le32_to_cpu(here->e_value_size);
1500 + if (le16_to_cpu(here->e_value_offs) + size >
1501 + sb->s_blocksize || size > sb->s_blocksize)
1503 + free += EXT2_XATTR_SIZE(size);
1506 + free -= EXT2_XATTR_SIZE(value_len);
1511 + /* Here we know that we can set the new attribute. */
1514 + if (header->h_refcount == cpu_to_le32(1)) {
1515 + ea_bdebug(bh, "modifying in-place");
1516 + ext2_xattr_cache_remove(bh);
1520 + ea_bdebug(bh, "cloning");
1521 + header = kmalloc(bh->b_size, GFP_KERNEL);
1523 + if (header == NULL)
1525 + memcpy(header, HDR(bh), bh->b_size);
1526 + header->h_refcount = cpu_to_le32(1);
1527 + offset = (char *)header - bh->b_data;
1528 + here = ENTRY((char *)here + offset);
1529 + last = ENTRY((char *)last + offset);
1532 + /* Allocate a buffer where we construct the new block. */
1533 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1535 + if (header == NULL)
1537 + memset(header, 0, sb->s_blocksize);
1538 + end = (char *)header + sb->s_blocksize;
1539 + header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1540 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
1541 + last = here = ENTRY(header+1);
1545 + /* Insert the new name. */
1546 + int size = EXT2_XATTR_LEN(name_len);
1547 + int rest = (char *)last - (char *)here;
1548 + memmove((char *)here + size, here, rest);
1549 + memset(here, 0, size);
1550 + here->e_name_index = name_index;
1551 + here->e_name_len = name_len;
1552 + memcpy(here->e_name, name, name_len);
1554 + /* Remove the old value. */
1555 + if (!here->e_value_block && here->e_value_size) {
1556 + char *first_val = (char *)header + min_offs;
1557 + int offs = le16_to_cpu(here->e_value_offs);
1558 + char *val = (char *)header + offs;
1559 + size_t size = EXT2_XATTR_SIZE(
1560 + le32_to_cpu(here->e_value_size));
1561 + memmove(first_val + size, first_val, val - first_val);
1562 + memset(first_val, 0, size);
1563 + here->e_value_offs = 0;
1566 + /* Adjust all value offsets. */
1567 + last = ENTRY(header+1);
1568 + while (!IS_LAST_ENTRY(last)) {
1569 + int o = le16_to_cpu(last->e_value_offs);
1570 + if (!last->e_value_block && o < offs)
1571 + last->e_value_offs =
1572 + cpu_to_le16(o + size);
1573 + last = EXT2_XATTR_NEXT(last);
1576 + if (value == NULL) {
1577 + /* Remove this attribute. */
1578 + if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1579 + /* This block is now empty. */
1580 + error = ext2_xattr_set2(inode, bh, NULL);
1583 + /* Remove the old name. */
1584 + int size = EXT2_XATTR_LEN(name_len);
1585 + last = ENTRY((char *)last - size);
1586 + memmove(here, (char*)here + size,
1587 + (char*)last - (char*)here);
1588 + memset(last, 0, size);
1593 + if (value != NULL) {
1594 + /* Insert the new value. */
1595 + here->e_value_size = cpu_to_le32(value_len);
1597 + size_t size = EXT2_XATTR_SIZE(value_len);
1598 + char *val = (char *)header + min_offs - size;
1599 + here->e_value_offs =
1600 + cpu_to_le16((char *)val - (char *)header);
1601 + memset(val + size - EXT2_XATTR_PAD, 0,
1602 + EXT2_XATTR_PAD); /* Clear the pad bytes. */
1603 + memcpy(val, value, value_len);
1606 + ext2_xattr_rehash(header, here);
1608 + error = ext2_xattr_set2(inode, bh, header);
1612 + if (!(bh && header == HDR(bh)))
1614 + up(&ext2_xattr_sem);
1620 + * Second half of ext2_xattr_set(): Update the file system.
1623 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1624 + struct ext2_xattr_header *header)
1626 + struct super_block *sb = inode->i_sb;
1627 + struct buffer_head *new_bh = NULL;
1631 + new_bh = ext2_xattr_cache_find(inode, header);
1634 + * We found an identical block in the cache.
1635 + * The old block will be released after updating
1638 + ea_bdebug(old_bh, "reusing block %ld",
1639 + new_bh->b_blocknr);
1642 + if (ext2_xattr_quota_alloc(inode, 1))
1645 + HDR(new_bh)->h_refcount = cpu_to_le32(
1646 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1647 + ea_bdebug(new_bh, "refcount now=%d",
1648 + le32_to_cpu(HDR(new_bh)->h_refcount));
1649 + } else if (old_bh && header == HDR(old_bh)) {
1650 + /* Keep this block. */
1652 + (void)ext2_xattr_cache_insert(new_bh);
1654 + /* We need to allocate a new block */
1655 + int force = EXT2_I(inode)->i_file_acl != 0;
1656 + int block = ext2_xattr_new_block(inode, &error, force);
1659 + ea_idebug(inode, "creating block %d", block);
1661 + new_bh = sb_getblk(sb, block);
1663 + ext2_xattr_free_block(inode, block);
1667 + lock_buffer(new_bh);
1668 + memcpy(new_bh->b_data, header, new_bh->b_size);
1669 + mark_buffer_uptodate(new_bh, 1);
1670 + unlock_buffer(new_bh);
1671 + (void)ext2_xattr_cache_insert(new_bh);
1673 + ext2_xattr_update_super_block(sb);
1675 + mark_buffer_dirty(new_bh);
1676 + if (IS_SYNC(inode)) {
1677 + ll_rw_block(WRITE, 1, &new_bh);
1678 + wait_on_buffer(new_bh);
1680 + if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1685 + /* Update the inode. */
1686 + EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1687 + inode->i_ctime = CURRENT_TIME;
1688 + if (IS_SYNC(inode)) {
1689 + error = ext2_sync_inode (inode);
1693 + mark_inode_dirty(inode);
1696 + if (old_bh && old_bh != new_bh) {
1698 + * If there was an old block, and we are not still using it,
1699 + * we now release the old block.
1701 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1703 + if (refcount == 1) {
1704 + /* Free the old block. */
1705 + ea_bdebug(old_bh, "freeing");
1706 + ext2_xattr_free_block(inode, old_bh->b_blocknr);
1707 + mark_buffer_clean(old_bh);
1709 + /* Decrement the refcount only. */
1711 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1712 + ext2_xattr_quota_free(inode);
1713 + mark_buffer_dirty(old_bh);
1714 + ea_bdebug(old_bh, "refcount now=%d", refcount);
1719 + if (old_bh != new_bh)
1726 + * ext2_xattr_delete_inode()
1728 + * Free extended attribute resources associated with this inode. This
1729 + * is called immediately before an inode is freed.
1732 +ext2_xattr_delete_inode(struct inode *inode)
1734 + struct buffer_head *bh;
1735 + unsigned int block = EXT2_I(inode)->i_file_acl;
1739 + down(&ext2_xattr_sem);
1741 + bh = sb_bread(inode->i_sb, block);
1743 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1744 + "inode %ld: block %d read error", inode->i_ino, block);
1747 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1748 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1749 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1750 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1751 + "inode %ld: bad block %d", inode->i_ino, block);
1754 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1755 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1756 + ext2_xattr_cache_remove(bh);
1757 + ext2_xattr_free_block(inode, block);
1761 + HDR(bh)->h_refcount = cpu_to_le32(
1762 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
1763 + mark_buffer_dirty(bh);
1764 + if (IS_SYNC(inode)) {
1765 + ll_rw_block(WRITE, 1, &bh);
1766 + wait_on_buffer(bh);
1768 + ext2_xattr_quota_free(inode);
1770 + EXT2_I(inode)->i_file_acl = 0;
1774 + up(&ext2_xattr_sem);
1778 + * ext2_xattr_put_super()
1780 + * This is called when a file system is unmounted.
1783 +ext2_xattr_put_super(struct super_block *sb)
1785 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1786 + mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
1790 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1793 + * ext2_xattr_cache_insert()
1795 + * Create a new entry in the extended attribute cache, and insert
1796 + * it unless such an entry is already in the cache.
1798 + * Returns 0, or a negative error number on failure.
1801 +ext2_xattr_cache_insert(struct buffer_head *bh)
1803 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
1804 + struct mb_cache_entry *ce;
1807 + ce = mb_cache_entry_alloc(ext2_xattr_cache);
1810 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
1812 + mb_cache_entry_free(ce);
1813 + if (error == -EBUSY) {
1814 + ea_bdebug(bh, "already in cache (%d cache entries)",
1815 + atomic_read(&ext2_xattr_cache->c_entry_count));
1819 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
1820 + atomic_read(&ext2_xattr_cache->c_entry_count));
1821 + mb_cache_entry_release(ce);
1827 + * ext2_xattr_cmp()
1829 + * Compare two extended attribute blocks for equality.
1831 + * Returns 0 if the blocks are equal, 1 if they differ, and
1832 + * a negative error number on errors.
1835 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
1836 + struct ext2_xattr_header *header2)
1838 + struct ext2_xattr_entry *entry1, *entry2;
1840 + entry1 = ENTRY(header1+1);
1841 + entry2 = ENTRY(header2+1);
1842 + while (!IS_LAST_ENTRY(entry1)) {
1843 + if (IS_LAST_ENTRY(entry2))
1845 + if (entry1->e_hash != entry2->e_hash ||
1846 + entry1->e_name_len != entry2->e_name_len ||
1847 + entry1->e_value_size != entry2->e_value_size ||
1848 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
1850 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
1852 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
1853 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
1854 + le32_to_cpu(entry1->e_value_size)))
1857 + entry1 = EXT2_XATTR_NEXT(entry1);
1858 + entry2 = EXT2_XATTR_NEXT(entry2);
1860 + if (!IS_LAST_ENTRY(entry2))
1866 + * ext2_xattr_cache_find()
1868 + * Find an identical extended attribute block.
1870 + * Returns a pointer to the block found, or NULL if such a block was
1871 + * not found or an error occurred.
1873 +static struct buffer_head *
1874 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
1876 + __u32 hash = le32_to_cpu(header->h_hash);
1877 + struct mb_cache_entry *ce;
1879 + if (!header->h_hash)
1880 + return NULL; /* never share */
1881 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
1882 + ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
1884 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
1887 + ext2_error(inode->i_sb, "ext2_xattr_cache_find",
1888 + "inode %ld: block %ld read error",
1889 + inode->i_ino, ce->e_block);
1890 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
1891 + EXT2_XATTR_REFCOUNT_MAX) {
1892 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
1893 + le32_to_cpu(HDR(bh)->h_refcount),
1894 + EXT2_XATTR_REFCOUNT_MAX);
1895 + } else if (!ext2_xattr_cmp(header, HDR(bh))) {
1896 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
1897 + mb_cache_entry_release(ce);
1901 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
1907 + * ext2_xattr_cache_remove()
1909 + * Remove the cache entry of a block from the cache. Called when a
1910 + * block becomes invalid.
1913 +ext2_xattr_cache_remove(struct buffer_head *bh)
1915 + struct mb_cache_entry *ce;
1917 + ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
1919 + ea_bdebug(bh, "removing (%d cache entries remaining)",
1920 + atomic_read(&ext2_xattr_cache->c_entry_count)-1);
1921 + mb_cache_entry_free(ce);
1923 + ea_bdebug(bh, "no cache entry");
1926 +#define NAME_HASH_SHIFT 5
1927 +#define VALUE_HASH_SHIFT 16
1930 + * ext2_xattr_hash_entry()
1932 + * Compute the hash of an extended attribute.
1934 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
1935 + struct ext2_xattr_entry *entry)
1938 + char *name = entry->e_name;
1941 + for (n=0; n < entry->e_name_len; n++) {
1942 + hash = (hash << NAME_HASH_SHIFT) ^
1943 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
1947 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
1948 + __u32 *value = (__u32 *)((char *)header +
1949 + le16_to_cpu(entry->e_value_offs));
1950 + for (n = (le32_to_cpu(entry->e_value_size) +
1951 + EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
1952 + hash = (hash << VALUE_HASH_SHIFT) ^
1953 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
1954 + le32_to_cpu(*value++);
1957 + entry->e_hash = cpu_to_le32(hash);
1960 +#undef NAME_HASH_SHIFT
1961 +#undef VALUE_HASH_SHIFT
1963 +#define BLOCK_HASH_SHIFT 16
1966 + * ext2_xattr_rehash()
1968 + * Re-compute the extended attribute hash value after an entry has changed.
1970 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
1971 + struct ext2_xattr_entry *entry)
1973 + struct ext2_xattr_entry *here;
1976 + ext2_xattr_hash_entry(header, entry);
1977 + here = ENTRY(header+1);
1978 + while (!IS_LAST_ENTRY(here)) {
1979 + if (!here->e_hash) {
1980 + /* Block is not shared if an entry's hash value == 0 */
1984 + hash = (hash << BLOCK_HASH_SHIFT) ^
1985 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
1986 + le32_to_cpu(here->e_hash);
1987 + here = EXT2_XATTR_NEXT(here);
1989 + header->h_hash = cpu_to_le32(hash);
1992 +#undef BLOCK_HASH_SHIFT
1995 +init_ext2_xattr(void)
1997 + ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
1998 + sizeof(struct mb_cache_entry) +
1999 + sizeof(struct mb_cache_entry_index), 1, 61);
2000 + if (!ext2_xattr_cache)
2007 +exit_ext2_xattr(void)
2009 + mb_cache_destroy(ext2_xattr_cache);
2012 +#else /* CONFIG_EXT2_FS_XATTR_SHARING */
2015 +init_ext2_xattr(void)
2021 +exit_ext2_xattr(void)
2025 +#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
2026 Index: linux-2.4.29/fs/ext2/xattr_user.c
2027 ===================================================================
2028 --- linux-2.4.29.orig/fs/ext2/xattr_user.c 2005-05-03 17:59:40.233146800 +0300
2029 +++ linux-2.4.29/fs/ext2/xattr_user.c 2005-05-03 17:59:40.407120352 +0300
2032 + * linux/fs/ext2/xattr_user.c
2033 + * Handler for extended user attributes.
2035 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2038 +#include <linux/module.h>
2039 +#include <linux/string.h>
2040 +#include <linux/fs.h>
2041 +#include <linux/ext2_fs.h>
2042 +#include <linux/ext2_xattr.h>
2044 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2045 +# include <linux/ext2_acl.h>
2048 +#define XATTR_USER_PREFIX "user."
2051 +ext2_xattr_user_list(char *list, struct inode *inode,
2052 + const char *name, int name_len)
2054 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2056 + if (!test_opt(inode->i_sb, XATTR_USER))
2060 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
2061 + memcpy(list+prefix_len, name, name_len);
2062 + list[prefix_len + name_len] = '\0';
2064 + return prefix_len + name_len + 1;
2068 +ext2_xattr_user_get(struct inode *inode, const char *name,
2069 + void *buffer, size_t size)
2073 + if (strcmp(name, "") == 0)
2075 + if (!test_opt(inode->i_sb, XATTR_USER))
2077 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2078 + error = ext2_permission_locked(inode, MAY_READ);
2080 + error = permission(inode, MAY_READ);
2085 + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2090 +ext2_xattr_user_set(struct inode *inode, const char *name,
2091 + const void *value, size_t size, int flags)
2095 + if (strcmp(name, "") == 0)
2097 + if (!test_opt(inode->i_sb, XATTR_USER))
2099 + if ( !S_ISREG(inode->i_mode) &&
2100 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2102 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2103 + error = ext2_permission_locked(inode, MAY_WRITE);
2105 + error = permission(inode, MAY_WRITE);
2110 + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2111 + value, size, flags);
2114 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2115 + prefix: XATTR_USER_PREFIX,
2116 + list: ext2_xattr_user_list,
2117 + get: ext2_xattr_user_get,
2118 + set: ext2_xattr_user_set,
2122 +init_ext2_xattr_user(void)
2124 + return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2125 + &ext2_xattr_user_handler);
2129 +exit_ext2_xattr_user(void)
2131 + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2132 + &ext2_xattr_user_handler);
2134 Index: linux-2.4.29/fs/ext3/Makefile
2135 ===================================================================
2136 --- linux-2.4.29.orig/fs/ext3/Makefile 2005-05-03 17:23:54.093409632 +0300
2137 +++ linux-2.4.29/fs/ext3/Makefile 2005-05-03 17:59:40.408120200 +0300
2140 -# Makefile for the linux ext2-filesystem routines.
2141 +# Makefile for the linux ext3-filesystem routines.
2143 # Note! Dependencies are done automagically by 'make dep', which also
2144 # removes any old dependencies. DON'T put your own dependencies here
2149 -export-objs := super.o inode.o
2150 +export-objs := ext3-exports.o
2152 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2153 - ioctl.o namei.o super.o symlink.o hash.o
2154 + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2155 obj-m := $(O_TARGET)
2157 +export-objs += xattr.o
2158 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2159 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2161 include $(TOPDIR)/Rules.make
2162 Index: linux-2.4.29/fs/ext3/file.c
2163 ===================================================================
2164 --- linux-2.4.29.orig/fs/ext3/file.c 2005-05-03 17:23:54.091409936 +0300
2165 +++ linux-2.4.29/fs/ext3/file.c 2005-05-03 17:59:40.410119896 +0300
2167 #include <linux/locks.h>
2168 #include <linux/jbd.h>
2169 #include <linux/ext3_fs.h>
2170 +#include <linux/ext3_xattr.h>
2171 #include <linux/ext3_jbd.h>
2172 #include <linux/smp_lock.h>
2175 struct inode_operations ext3_file_inode_operations = {
2176 truncate: ext3_truncate, /* BKL held */
2177 setattr: ext3_setattr, /* BKL held */
2178 + setxattr: ext3_setxattr, /* BKL held */
2179 + getxattr: ext3_getxattr, /* BKL held */
2180 + listxattr: ext3_listxattr, /* BKL held */
2181 + removexattr: ext3_removexattr, /* BKL held */
2184 Index: linux-2.4.29/fs/ext3/ialloc.c
2185 ===================================================================
2186 --- linux-2.4.29.orig/fs/ext3/ialloc.c 2005-04-07 18:53:42.000000000 +0300
2187 +++ linux-2.4.29/fs/ext3/ialloc.c 2005-05-03 17:59:40.411119744 +0300
2189 #include <linux/jbd.h>
2190 #include <linux/ext3_fs.h>
2191 #include <linux/ext3_jbd.h>
2192 +#include <linux/ext3_xattr.h>
2193 #include <linux/stat.h>
2194 #include <linux/string.h>
2195 #include <linux/locks.h>
2197 * as writing the quota to disk may need the lock as well.
2200 + ext3_xattr_delete_inode(handle, inode);
2201 DQUOT_FREE_INODE(inode);
2204 Index: linux-2.4.29/fs/ext3/inode.c
2205 ===================================================================
2206 --- linux-2.4.29.orig/fs/ext3/inode.c 2005-04-07 18:54:16.000000000 +0300
2207 +++ linux-2.4.29/fs/ext3/inode.c 2005-05-03 17:59:40.415119136 +0300
2209 * still needs to be revoked.
2212 -static int ext3_forget(handle_t *handle, int is_metadata,
2213 +int ext3_forget(handle_t *handle, int is_metadata,
2214 struct inode *inode, struct buffer_head *bh,
2221 - if (is_bad_inode(inode) ||
2222 - inode->i_ino == EXT3_ACL_IDX_INO ||
2223 - inode->i_ino == EXT3_ACL_DATA_INO)
2224 + if (is_bad_inode(inode))
2228 @@ -1885,6 +1883,8 @@
2230 if (ext3_inode_is_fast_symlink(inode))
2232 + if (ext3_inode_is_fast_symlink(inode))
2234 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2237 @@ -2032,8 +2032,6 @@
2238 struct ext3_group_desc * gdp;
2240 if ((inode->i_ino != EXT3_ROOT_INO &&
2241 - inode->i_ino != EXT3_ACL_IDX_INO &&
2242 - inode->i_ino != EXT3_ACL_DATA_INO &&
2243 inode->i_ino != EXT3_JOURNAL_INO &&
2244 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2245 inode->i_ino > le32_to_cpu(
2246 @@ -2174,10 +2172,7 @@
2247 inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
2248 INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
2250 - if (inode->i_ino == EXT3_ACL_IDX_INO ||
2251 - inode->i_ino == EXT3_ACL_DATA_INO)
2252 - /* Nothing to do */ ;
2253 - else if (S_ISREG(inode->i_mode)) {
2254 + if (S_ISREG(inode->i_mode)) {
2255 inode->i_op = &ext3_file_inode_operations;
2256 inode->i_fop = &ext3_file_operations;
2257 inode->i_mapping->a_ops = &ext3_aops;
2258 @@ -2188,12 +2183,14 @@
2259 if (ext3_inode_is_fast_symlink(inode))
2260 inode->i_op = &ext3_fast_symlink_inode_operations;
2262 - inode->i_op = &page_symlink_inode_operations;
2263 + inode->i_op = &ext3_symlink_inode_operations;
2264 inode->i_mapping->a_ops = &ext3_aops;
2268 + inode->i_op = &ext3_special_inode_operations;
2269 init_special_inode(inode, inode->i_mode,
2270 le32_to_cpu(iloc.raw_inode->i_block[0]));
2273 ext3_set_inode_flags(inode);
2275 Index: linux-2.4.29/fs/ext3/namei.c
2276 ===================================================================
2277 --- linux-2.4.29.orig/fs/ext3/namei.c 2005-05-03 17:23:54.101408416 +0300
2278 +++ linux-2.4.29/fs/ext3/namei.c 2005-05-03 17:59:40.419118528 +0300
2280 #include <linux/sched.h>
2281 #include <linux/ext3_fs.h>
2282 #include <linux/ext3_jbd.h>
2283 +#include <linux/ext3_xattr.h>
2284 #include <linux/fcntl.h>
2285 #include <linux/stat.h>
2286 #include <linux/string.h>
2287 @@ -1613,7 +1614,7 @@
2291 - inode = ext3_new_inode (handle, dir, S_IFDIR);
2292 + inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2293 err = PTR_ERR(inode);
2296 @@ -1621,7 +1622,6 @@
2297 inode->i_op = &ext3_dir_inode_operations;
2298 inode->i_fop = &ext3_dir_operations;
2299 inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2300 - inode->i_blocks = 0;
2301 dir_block = ext3_bread (handle, inode, 0, 1, &err);
2303 inode->i_nlink--; /* is this nlink == 0? */
2304 @@ -1648,9 +1648,6 @@
2305 BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2306 ext3_journal_dirty_metadata(handle, dir_block);
2308 - inode->i_mode = S_IFDIR | mode;
2309 - if (dir->i_mode & S_ISGID)
2310 - inode->i_mode |= S_ISGID;
2311 ext3_mark_inode_dirty(handle, inode);
2312 err = ext3_add_entry (handle, dentry, inode);
2314 @@ -2019,7 +2016,7 @@
2317 if (l > sizeof (EXT3_I(inode)->i_data)) {
2318 - inode->i_op = &page_symlink_inode_operations;
2319 + inode->i_op = &ext3_symlink_inode_operations;
2320 inode->i_mapping->a_ops = &ext3_aops;
2322 * block_symlink() calls back into ext3_prepare/commit_write.
2323 @@ -2248,4 +2245,16 @@
2324 rmdir: ext3_rmdir, /* BKL held */
2325 mknod: ext3_mknod, /* BKL held */
2326 rename: ext3_rename, /* BKL held */
2327 + setxattr: ext3_setxattr, /* BKL held */
2328 + getxattr: ext3_getxattr, /* BKL held */
2329 + listxattr: ext3_listxattr, /* BKL held */
2330 + removexattr: ext3_removexattr, /* BKL held */
2333 +struct inode_operations ext3_special_inode_operations = {
2334 + setxattr: ext3_setxattr, /* BKL held */
2335 + getxattr: ext3_getxattr, /* BKL held */
2336 + listxattr: ext3_listxattr, /* BKL held */
2337 + removexattr: ext3_removexattr, /* BKL held */
2340 Index: linux-2.4.29/fs/ext3/super.c
2341 ===================================================================
2342 --- linux-2.4.29.orig/fs/ext3/super.c 2005-05-03 17:23:54.104407960 +0300
2343 +++ linux-2.4.29/fs/ext3/super.c 2005-05-03 18:00:16.805586944 +0300
2345 #include <linux/jbd.h>
2346 #include <linux/ext3_fs.h>
2347 #include <linux/ext3_jbd.h>
2348 +#include <linux/ext3_xattr.h>
2349 #include <linux/slab.h>
2350 #include <linux/init.h>
2351 #include <linux/locks.h>
2353 kdev_t j_dev = sbi->s_journal->j_dev;
2356 + ext3_xattr_put_super(sb);
2357 journal_destroy(sbi->s_journal);
2358 if (!(sb->s_flags & MS_RDONLY)) {
2359 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2363 unsigned long *mount_options = &sbi->s_mount_opt;
2365 uid_t *resuid = &sbi->s_resuid;
2366 gid_t *resgid = &sbi->s_resgid;
2368 @@ -516,6 +519,13 @@
2369 this_char = strtok (NULL, ",")) {
2370 if ((value = strchr (this_char, '=')) != NULL)
2372 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2373 + if (!strcmp (this_char, "user_xattr"))
2374 + set_opt (*mount_options, XATTR_USER);
2375 + else if (!strcmp (this_char, "nouser_xattr"))
2376 + clear_opt (*mount_options, XATTR_USER);
2379 if (!strcmp (this_char, "bsddf"))
2380 clear_opt (*mount_options, MINIX_DF);
2381 else if (!strcmp (this_char, "nouid32")) {
2382 @@ -954,6 +964,12 @@
2383 sbi->s_mount_opt = 0;
2384 sbi->s_resuid = EXT3_DEF_RESUID;
2385 sbi->s_resgid = EXT3_DEF_RESGID;
2387 + /* Default extended attribute flags */
2388 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2389 + /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2392 if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2395 @@ -1838,22 +1854,35 @@
2397 static int __init init_ext3_fs(void)
2401 init_dquot_operations(&ext3_qops);
2402 old_write_dquot = ext3_qops.write_dquot;
2403 ext3_qops.write_dquot = ext3_write_dquot;
2405 - return register_filesystem(&ext3_fs_type);
2406 + error = init_ext3_xattr();
2409 + error = init_ext3_xattr_user();
2412 + error = register_filesystem(&ext3_fs_type);
2416 + exit_ext3_xattr_user();
2418 + exit_ext3_xattr();
2422 static void __exit exit_ext3_fs(void)
2424 unregister_filesystem(&ext3_fs_type);
2425 + exit_ext3_xattr_user();
2426 + exit_ext3_xattr();
2429 -EXPORT_SYMBOL(ext3_force_commit);
2430 -EXPORT_SYMBOL(ext3_bread);
2432 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2433 MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2434 MODULE_LICENSE("GPL");
2435 Index: linux-2.4.29/fs/ext3/symlink.c
2436 ===================================================================
2437 --- linux-2.4.29.orig/fs/ext3/symlink.c 2005-04-07 18:53:53.000000000 +0300
2438 +++ linux-2.4.29/fs/ext3/symlink.c 2005-05-03 17:59:40.423117920 +0300
2440 #include <linux/fs.h>
2441 #include <linux/jbd.h>
2442 #include <linux/ext3_fs.h>
2443 +#include <linux/ext3_xattr.h>
2445 static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2448 return vfs_follow_link(nd, s);
2451 +struct inode_operations ext3_symlink_inode_operations = {
2452 + readlink: page_readlink, /* BKL not held. Don't need */
2453 + follow_link: page_follow_link, /* BKL not held. Don't need */
2454 + setxattr: ext3_setxattr, /* BKL held */
2455 + getxattr: ext3_getxattr, /* BKL held */
2456 + listxattr: ext3_listxattr, /* BKL held */
2457 + removexattr: ext3_removexattr, /* BKL held */
2460 struct inode_operations ext3_fast_symlink_inode_operations = {
2461 readlink: ext3_readlink, /* BKL not held. Don't need */
2462 follow_link: ext3_follow_link, /* BKL not held. Don't need */
2463 + setxattr: ext3_setxattr, /* BKL held */
2464 + getxattr: ext3_getxattr, /* BKL held */
2465 + listxattr: ext3_listxattr, /* BKL held */
2466 + removexattr: ext3_removexattr, /* BKL held */
2468 Index: linux-2.4.29/fs/ext3/xattr.c
2469 ===================================================================
2470 --- linux-2.4.29.orig/fs/ext3/xattr.c 2005-05-03 17:59:40.234146648 +0300
2471 +++ linux-2.4.29/fs/ext3/xattr.c 2005-05-03 17:59:40.428117160 +0300
2474 + * linux/fs/ext3/xattr.c
2476 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2478 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2479 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2480 + * Extended attributes for symlinks and special files added per
2481 + * suggestion of Luka Renko <luka.renko@hermes.si>.
2485 + * Extended attributes are stored on disk blocks allocated outside of
2486 + * any inode. The i_file_acl field is then made to point to this allocated
2487 + * block. If all extended attributes of an inode are identical, these
2488 + * inodes may share the same extended attribute block. Such situations
2489 + * are automatically detected by keeping a cache of recent attribute block
2490 + * numbers and hashes over the block's contents in memory.
2493 + * Extended attribute block layout:
2495 + * +------------------+
2498 + * | entry 2 | | growing downwards
2500 + * | four null bytes |
2503 + * | value 3 | | growing upwards
2505 + * +------------------+
2507 + * The block header is followed by multiple entry descriptors. These entry
2508 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2509 + * byte boundaries. The entry descriptors are sorted by attribute name,
2510 + * so that two extended attribute blocks can be compared efficiently.
2512 + * Attribute values are aligned to the end of the block, stored in
2513 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2514 + * boundaries. No additional gaps are left between them.
2516 + * Locking strategy
2517 + * ----------------
2518 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2519 + * the xattr inode operations are called, so we are guaranteed that only one
2520 + * processes accesses extended attributes of an inode at any time.
2522 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2523 + * only a single process is modifying an extended attribute block, even
2524 + * if the block is shared among inodes.
2526 + * Note for porting to 2.5
2527 + * -----------------------
2528 + * The BKL will no longer be held in the xattr inode operations.
2531 +#include <linux/module.h>
2532 +#include <linux/fs.h>
2533 +#include <linux/locks.h>
2534 +#include <linux/slab.h>
2535 +#include <linux/ext3_jbd.h>
2536 +#include <linux/ext3_fs.h>
2537 +#include <linux/ext3_xattr.h>
2538 +#include <linux/mbcache.h>
2539 +#include <linux/quotaops.h>
2540 +#include <asm/semaphore.h>
2541 +#include <linux/compatmac.h>
2543 +#define EXT3_EA_USER "user."
2545 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2546 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2549 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2550 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2551 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2552 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2554 +#ifdef EXT3_XATTR_DEBUG
2555 +# define ea_idebug(inode, f...) do { \
2556 + printk(KERN_DEBUG "inode %s:%ld: ", \
2557 + kdevname(inode->i_dev), inode->i_ino); \
2561 +# define ea_bdebug(bh, f...) do { \
2562 + printk(KERN_DEBUG "block %s:%ld: ", \
2563 + kdevname(bh->b_dev), bh->b_blocknr); \
2568 +# define ea_idebug(f...)
2569 +# define ea_bdebug(f...)
2572 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2573 + struct ext3_xattr_header *);
2575 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2577 +static int ext3_xattr_cache_insert(struct buffer_head *);
2578 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2579 + struct ext3_xattr_header *);
2580 +static void ext3_xattr_cache_remove(struct buffer_head *);
2581 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2582 + struct ext3_xattr_entry *);
2584 +static struct mb_cache *ext3_xattr_cache;
2587 +# define ext3_xattr_cache_insert(bh) 0
2588 +# define ext3_xattr_cache_find(inode, header) NULL
2589 +# define ext3_xattr_cache_remove(bh) while(0) {}
2590 +# define ext3_xattr_rehash(header, entry) while(0) {}
2594 + * If a file system does not share extended attributes among inodes,
2595 + * we should not need the ext3_xattr_sem semaphore. However, the
2596 + * filesystem may still contain shared blocks, so we always take
2600 +DECLARE_MUTEX(ext3_xattr_sem);
2603 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2604 + int * errp, int force)
2606 + struct super_block *sb = inode->i_sb;
2607 + int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2608 + EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2610 + /* How can we enforce the allocation? */
2611 + int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2614 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2620 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2622 + /* How can we enforce the allocation? */
2624 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2626 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2628 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
2636 +ext3_xattr_quota_free(struct inode *inode)
2638 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2639 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2643 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2644 + unsigned long block)
2646 + ext3_free_blocks(handle, inode, block, 1);
2647 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2651 +# define ext3_xattr_quota_free(inode) \
2652 + DQUOT_FREE_BLOCK(inode, 1)
2653 +# define ext3_xattr_free_block(handle, inode, block) \
2654 + ext3_free_blocks(handle, inode, block, 1)
2657 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2659 +static inline struct buffer_head *
2660 +sb_bread(struct super_block *sb, int block)
2662 + return bread(sb->s_dev, block, sb->s_blocksize);
2665 +static inline struct buffer_head *
2666 +sb_getblk(struct super_block *sb, int block)
2668 + return getblk(sb->s_dev, block, sb->s_blocksize);
2673 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2674 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2677 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2679 + int error = -EINVAL;
2681 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2682 + write_lock(&ext3_handler_lock);
2683 + if (!ext3_xattr_handlers[name_index-1]) {
2684 + ext3_xattr_handlers[name_index-1] = handler;
2687 + write_unlock(&ext3_handler_lock);
2693 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2695 + if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2696 + write_lock(&ext3_handler_lock);
2697 + ext3_xattr_handlers[name_index-1] = NULL;
2698 + write_unlock(&ext3_handler_lock);
2702 +static inline const char *
2703 +strcmp_prefix(const char *a, const char *a_prefix)
2705 + while (*a_prefix && *a == *a_prefix) {
2709 + return *a_prefix ? NULL : a;
2713 + * Decode the extended attribute name, and translate it into
2714 + * the name_index and name suffix.
2716 +static inline struct ext3_xattr_handler *
2717 +ext3_xattr_resolve_name(const char **name)
2719 + struct ext3_xattr_handler *handler = NULL;
2724 + read_lock(&ext3_handler_lock);
2725 + for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2726 + if (ext3_xattr_handlers[i]) {
2727 + const char *n = strcmp_prefix(*name,
2728 + ext3_xattr_handlers[i]->prefix);
2730 + handler = ext3_xattr_handlers[i];
2736 + read_unlock(&ext3_handler_lock);
2740 +static inline struct ext3_xattr_handler *
2741 +ext3_xattr_handler(int name_index)
2743 + struct ext3_xattr_handler *handler = NULL;
2744 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2745 + read_lock(&ext3_handler_lock);
2746 + handler = ext3_xattr_handlers[name_index-1];
2747 + read_unlock(&ext3_handler_lock);
2753 + * Inode operation getxattr()
2755 + * dentry->d_inode->i_sem down
2756 + * BKL held [before 2.5.x]
2759 +ext3_getxattr(struct dentry *dentry, const char *name,
2760 + void *buffer, size_t size)
2762 + struct ext3_xattr_handler *handler;
2763 + struct inode *inode = dentry->d_inode;
2765 + handler = ext3_xattr_resolve_name(&name);
2768 + return handler->get(inode, name, buffer, size);
2772 + * Inode operation listxattr()
2774 + * dentry->d_inode->i_sem down
2775 + * BKL held [before 2.5.x]
2778 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
2780 + return ext3_xattr_list(dentry->d_inode, buffer, size);
2784 + * Inode operation setxattr()
2786 + * dentry->d_inode->i_sem down
2787 + * BKL held [before 2.5.x]
2790 +ext3_setxattr(struct dentry *dentry, const char *name,
2791 + const void *value, size_t size, int flags)
2793 + struct ext3_xattr_handler *handler;
2794 + struct inode *inode = dentry->d_inode;
2797 + value = ""; /* empty EA, do not remove */
2798 + handler = ext3_xattr_resolve_name(&name);
2801 + return handler->set(inode, name, value, size, flags);
2805 + * Inode operation removexattr()
2807 + * dentry->d_inode->i_sem down
2808 + * BKL held [before 2.5.x]
2811 +ext3_removexattr(struct dentry *dentry, const char *name)
2813 + struct ext3_xattr_handler *handler;
2814 + struct inode *inode = dentry->d_inode;
2816 + handler = ext3_xattr_resolve_name(&name);
2819 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
2823 + * ext3_xattr_get()
2825 + * Copy an extended attribute into the buffer
2826 + * provided, or compute the buffer size required.
2827 + * Buffer is NULL to compute the size of the buffer required.
2829 + * Returns a negative error number on failure, or the number of bytes
2830 + * used / required on success.
2833 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
2834 + void *buffer, size_t buffer_size)
2836 + struct buffer_head *bh = NULL;
2837 + struct ext3_xattr_entry *entry;
2838 + unsigned int block, size;
2840 + int name_len, error;
2842 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
2843 + name_index, name, buffer, (long)buffer_size);
2847 + if (!EXT3_I(inode)->i_file_acl)
2849 + block = EXT3_I(inode)->i_file_acl;
2850 + ea_idebug(inode, "reading block %d", block);
2851 + bh = sb_bread(inode->i_sb, block);
2854 + ea_bdebug(bh, "b_count=%d, refcount=%d",
2855 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
2856 + end = bh->b_data + bh->b_size;
2857 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
2858 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
2859 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
2860 + "inode %ld: bad block %d", inode->i_ino, block);
2864 + /* find named attribute */
2865 + name_len = strlen(name);
2868 + if (name_len > 255)
2870 + entry = FIRST_ENTRY(bh);
2871 + while (!IS_LAST_ENTRY(entry)) {
2872 + struct ext3_xattr_entry *next =
2873 + EXT3_XATTR_NEXT(entry);
2874 + if ((char *)next >= end)
2876 + if (name_index == entry->e_name_index &&
2877 + name_len == entry->e_name_len &&
2878 + memcmp(name, entry->e_name, name_len) == 0)
2882 + /* Check the remaining name entries */
2883 + while (!IS_LAST_ENTRY(entry)) {
2884 + struct ext3_xattr_entry *next =
2885 + EXT3_XATTR_NEXT(entry);
2886 + if ((char *)next >= end)
2890 + if (ext3_xattr_cache_insert(bh))
2891 + ea_idebug(inode, "cache insert failed");
2895 + /* check the buffer size */
2896 + if (entry->e_value_block != 0)
2898 + size = le32_to_cpu(entry->e_value_size);
2899 + if (size > inode->i_sb->s_blocksize ||
2900 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
2903 + if (ext3_xattr_cache_insert(bh))
2904 + ea_idebug(inode, "cache insert failed");
2907 + if (size > buffer_size)
2909 + /* return value of attribute */
2910 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
2922 + * ext3_xattr_list()
2924 + * Copy a list of attribute names into the buffer
2925 + * provided, or compute the buffer size required.
2926 + * Buffer is NULL to compute the size of the buffer required.
2928 + * Returns a negative error number on failure, or the number of bytes
2929 + * used / required on success.
2932 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
2934 + struct buffer_head *bh = NULL;
2935 + struct ext3_xattr_entry *entry;
2936 + unsigned int block, size = 0;
2940 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
2941 + buffer, (long)buffer_size);
2943 + if (!EXT3_I(inode)->i_file_acl)
2945 + block = EXT3_I(inode)->i_file_acl;
2946 + ea_idebug(inode, "reading block %d", block);
2947 + bh = sb_bread(inode->i_sb, block);
2950 + ea_bdebug(bh, "b_count=%d, refcount=%d",
2951 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
2952 + end = bh->b_data + bh->b_size;
2953 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
2954 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
2955 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
2956 + "inode %ld: bad block %d", inode->i_ino, block);
2960 + /* compute the size required for the list of attribute names */
2961 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
2962 + entry = EXT3_XATTR_NEXT(entry)) {
2963 + struct ext3_xattr_handler *handler;
2964 + struct ext3_xattr_entry *next =
2965 + EXT3_XATTR_NEXT(entry);
2966 + if ((char *)next >= end)
2969 + handler = ext3_xattr_handler(entry->e_name_index);
2971 + size += handler->list(NULL, inode, entry->e_name,
2972 + entry->e_name_len);
2975 + if (ext3_xattr_cache_insert(bh))
2976 + ea_idebug(inode, "cache insert failed");
2982 + if (size > buffer_size)
2986 + /* list the attribute names */
2988 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
2989 + entry = EXT3_XATTR_NEXT(entry)) {
2990 + struct ext3_xattr_handler *handler;
2992 + handler = ext3_xattr_handler(entry->e_name_index);
2994 + buf += handler->list(buf, inode, entry->e_name,
2995 + entry->e_name_len);
3006 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3007 + * not set, set it.
3009 +static void ext3_xattr_update_super_block(handle_t *handle,
3010 + struct super_block *sb)
3012 + if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3016 + ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3017 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3018 + EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3020 + EXT3_SB(sb)->s_es->s_feature_compat |=
3021 + cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3023 + ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3028 + * ext3_xattr_set()
3030 + * Create, replace or remove an extended attribute for this inode. Buffer
3031 + * is NULL to remove an existing extended attribute, and non-NULL to
3032 + * either replace an existing extended attribute, or create a new extended
3033 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3034 + * specify that an extended attribute must exist and must not exist
3035 + * previous to the call, respectively.
3037 + * Returns 0, or a negative error number on failure.
3040 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3041 + const char *name, const void *value, size_t value_len, int flags)
3043 + struct super_block *sb = inode->i_sb;
3044 + struct buffer_head *bh = NULL;
3045 + struct ext3_xattr_header *header = NULL;
3046 + struct ext3_xattr_entry *here, *last;
3047 + unsigned int name_len;
3048 + int block = EXT3_I(inode)->i_file_acl;
3049 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
3053 + * header -- Points either into bh, or to a temporarily
3054 + * allocated buffer.
3055 + * here -- The named entry found, or the place for inserting, within
3056 + * the block pointed to by header.
3057 + * last -- Points right after the last named entry within the block
3058 + * pointed to by header.
3059 + * min_offs -- The offset of the first value (values are aligned
3060 + * towards the end of the block).
3061 + * end -- Points right after the block pointed to by header.
3064 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3065 + name_index, name, value, (long)value_len);
3067 + if (IS_RDONLY(inode))
3069 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3071 + if (value == NULL)
3075 + name_len = strlen(name);
3076 + if (name_len > 255 || value_len > sb->s_blocksize)
3078 + down(&ext3_xattr_sem);
3081 + /* The inode already has an extended attribute block. */
3082 + bh = sb_bread(sb, block);
3086 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3087 + atomic_read(&(bh->b_count)),
3088 + le32_to_cpu(HDR(bh)->h_refcount));
3090 + end = bh->b_data + bh->b_size;
3091 + if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3092 + header->h_blocks != cpu_to_le32(1)) {
3093 +bad_block: ext3_error(sb, "ext3_xattr_set",
3094 + "inode %ld: bad block %d", inode->i_ino, block);
3098 + /* Find the named attribute. */
3099 + here = FIRST_ENTRY(bh);
3100 + while (!IS_LAST_ENTRY(here)) {
3101 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3102 + if ((char *)next >= end)
3104 + if (!here->e_value_block && here->e_value_size) {
3105 + int offs = le16_to_cpu(here->e_value_offs);
3106 + if (offs < min_offs)
3109 + not_found = name_index - here->e_name_index;
3111 + not_found = name_len - here->e_name_len;
3113 + not_found = memcmp(name, here->e_name,name_len);
3114 + if (not_found <= 0)
3119 + /* We still need to compute min_offs and last. */
3120 + while (!IS_LAST_ENTRY(last)) {
3121 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3122 + if ((char *)next >= end)
3124 + if (!last->e_value_block && last->e_value_size) {
3125 + int offs = le16_to_cpu(last->e_value_offs);
3126 + if (offs < min_offs)
3132 + /* Check whether we have enough space left. */
3133 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3135 + /* We will use a new extended attribute block. */
3136 + free = sb->s_blocksize -
3137 + sizeof(struct ext3_xattr_header) - sizeof(__u32);
3138 + here = last = NULL; /* avoid gcc uninitialized warning. */
3142 + /* Request to remove a nonexistent attribute? */
3144 + if (flags & XATTR_REPLACE)
3147 + if (value == NULL)
3150 + free -= EXT3_XATTR_LEN(name_len);
3152 + /* Request to create an existing attribute? */
3154 + if (flags & XATTR_CREATE)
3156 + if (!here->e_value_block && here->e_value_size) {
3157 + unsigned int size = le32_to_cpu(here->e_value_size);
3159 + if (le16_to_cpu(here->e_value_offs) + size >
3160 + sb->s_blocksize || size > sb->s_blocksize)
3162 + free += EXT3_XATTR_SIZE(size);
3165 + free -= EXT3_XATTR_SIZE(value_len);
3170 + /* Here we know that we can set the new attribute. */
3173 + if (header->h_refcount == cpu_to_le32(1)) {
3174 + ea_bdebug(bh, "modifying in-place");
3175 + ext3_xattr_cache_remove(bh);
3176 + error = ext3_journal_get_write_access(handle, bh);
3182 + ea_bdebug(bh, "cloning");
3183 + header = kmalloc(bh->b_size, GFP_KERNEL);
3185 + if (header == NULL)
3187 + memcpy(header, HDR(bh), bh->b_size);
3188 + header->h_refcount = cpu_to_le32(1);
3189 + offset = (char *)header - bh->b_data;
3190 + here = ENTRY((char *)here + offset);
3191 + last = ENTRY((char *)last + offset);
3194 + /* Allocate a buffer where we construct the new block. */
3195 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3197 + if (header == NULL)
3199 + memset(header, 0, sb->s_blocksize);
3200 + end = (char *)header + sb->s_blocksize;
3201 + header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3202 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
3203 + last = here = ENTRY(header+1);
3207 + /* Insert the new name. */
3208 + int size = EXT3_XATTR_LEN(name_len);
3209 + int rest = (char *)last - (char *)here;
3210 + memmove((char *)here + size, here, rest);
3211 + memset(here, 0, size);
3212 + here->e_name_index = name_index;
3213 + here->e_name_len = name_len;
3214 + memcpy(here->e_name, name, name_len);
3216 + /* Remove the old value. */
3217 + if (!here->e_value_block && here->e_value_size) {
3218 + char *first_val = (char *)header + min_offs;
3219 + int offs = le16_to_cpu(here->e_value_offs);
3220 + char *val = (char *)header + offs;
3221 + size_t size = EXT3_XATTR_SIZE(
3222 + le32_to_cpu(here->e_value_size));
3223 + memmove(first_val + size, first_val, val - first_val);
3224 + memset(first_val, 0, size);
3225 + here->e_value_offs = 0;
3228 + /* Adjust all value offsets. */
3229 + last = ENTRY(header+1);
3230 + while (!IS_LAST_ENTRY(last)) {
3231 + int o = le16_to_cpu(last->e_value_offs);
3232 + if (!last->e_value_block && o < offs)
3233 + last->e_value_offs =
3234 + cpu_to_le16(o + size);
3235 + last = EXT3_XATTR_NEXT(last);
3238 + if (value == NULL) {
3239 + /* Remove this attribute. */
3240 + if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3241 + /* This block is now empty. */
3242 + error = ext3_xattr_set2(handle, inode, bh,NULL);
3245 + /* Remove the old name. */
3246 + int size = EXT3_XATTR_LEN(name_len);
3247 + last = ENTRY((char *)last - size);
3248 + memmove(here, (char*)here + size,
3249 + (char*)last - (char*)here);
3250 + memset(last, 0, size);
3255 + if (value != NULL) {
3256 + /* Insert the new value. */
3257 + here->e_value_size = cpu_to_le32(value_len);
3259 + size_t size = EXT3_XATTR_SIZE(value_len);
3260 + char *val = (char *)header + min_offs - size;
3261 + here->e_value_offs =
3262 + cpu_to_le16((char *)val - (char *)header);
3263 + memset(val + size - EXT3_XATTR_PAD, 0,
3264 + EXT3_XATTR_PAD); /* Clear the pad bytes. */
3265 + memcpy(val, value, value_len);
3268 + ext3_xattr_rehash(header, here);
3270 + error = ext3_xattr_set2(handle, inode, bh, header);
3274 + if (!(bh && header == HDR(bh)))
3276 + up(&ext3_xattr_sem);
3282 + * Second half of ext3_xattr_set(): Update the file system.
3285 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3286 + struct buffer_head *old_bh, struct ext3_xattr_header *header)
3288 + struct super_block *sb = inode->i_sb;
3289 + struct buffer_head *new_bh = NULL;
3293 + new_bh = ext3_xattr_cache_find(inode, header);
3296 + * We found an identical block in the cache.
3297 + * The old block will be released after updating
3300 + ea_bdebug(old_bh, "reusing block %ld",
3301 + new_bh->b_blocknr);
3304 + if (ext3_xattr_quota_alloc(inode, 1))
3307 + error = ext3_journal_get_write_access(handle, new_bh);
3310 + HDR(new_bh)->h_refcount = cpu_to_le32(
3311 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3312 + ea_bdebug(new_bh, "refcount now=%d",
3313 + le32_to_cpu(HDR(new_bh)->h_refcount));
3314 + } else if (old_bh && header == HDR(old_bh)) {
3315 + /* Keep this block. */
3317 + (void)ext3_xattr_cache_insert(new_bh);
3319 + /* We need to allocate a new block */
3320 + int force = EXT3_I(inode)->i_file_acl != 0;
3321 + int block = ext3_xattr_new_block(handle, inode,
3325 + ea_idebug(inode, "creating block %d", block);
3327 + new_bh = sb_getblk(sb, block);
3329 +getblk_failed: ext3_xattr_free_block(handle, inode, block);
3333 + lock_buffer(new_bh);
3334 + error = ext3_journal_get_create_access(handle, new_bh);
3336 + unlock_buffer(new_bh);
3337 + goto getblk_failed;
3339 + memcpy(new_bh->b_data, header, new_bh->b_size);
3340 + mark_buffer_uptodate(new_bh, 1);
3341 + unlock_buffer(new_bh);
3342 + (void)ext3_xattr_cache_insert(new_bh);
3344 + ext3_xattr_update_super_block(handle, sb);
3346 + error = ext3_journal_dirty_metadata(handle, new_bh);
3351 + /* Update the inode. */
3352 + EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3353 + inode->i_ctime = CURRENT_TIME;
3354 + ext3_mark_inode_dirty(handle, inode);
3355 + if (IS_SYNC(inode))
3356 + handle->h_sync = 1;
3359 + if (old_bh && old_bh != new_bh) {
3361 + * If there was an old block, and we are not still using it,
3362 + * we now release the old block.
3364 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3366 + error = ext3_journal_get_write_access(handle, old_bh);
3369 + if (refcount == 1) {
3370 + /* Free the old block. */
3371 + ea_bdebug(old_bh, "freeing");
3372 + ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3374 + /* ext3_forget() calls bforget() for us, but we
3375 + let our caller release old_bh, so we need to
3376 + duplicate the handle before. */
3378 + ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3380 + /* Decrement the refcount only. */
3382 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3383 + ext3_xattr_quota_free(inode);
3384 + ext3_journal_dirty_metadata(handle, old_bh);
3385 + ea_bdebug(old_bh, "refcount now=%d", refcount);
3390 + if (old_bh != new_bh)
3397 + * ext3_xattr_delete_inode()
3399 + * Free extended attribute resources associated with this inode. This
3400 + * is called immediately before an inode is freed.
3403 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3405 + struct buffer_head *bh;
3406 + unsigned int block = EXT3_I(inode)->i_file_acl;
3410 + down(&ext3_xattr_sem);
3412 + bh = sb_bread(inode->i_sb, block);
3414 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3415 + "inode %ld: block %d read error", inode->i_ino, block);
3418 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3419 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3420 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3421 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3422 + "inode %ld: bad block %d", inode->i_ino, block);
3425 + ext3_journal_get_write_access(handle, bh);
3426 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3427 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3428 + ext3_xattr_cache_remove(bh);
3429 + ext3_xattr_free_block(handle, inode, block);
3430 + ext3_forget(handle, 1, inode, bh, block);
3433 + HDR(bh)->h_refcount = cpu_to_le32(
3434 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
3435 + ext3_journal_dirty_metadata(handle, bh);
3436 + if (IS_SYNC(inode))
3437 + handle->h_sync = 1;
3438 + ext3_xattr_quota_free(inode);
3440 + EXT3_I(inode)->i_file_acl = 0;
3444 + up(&ext3_xattr_sem);
3448 + * ext3_xattr_put_super()
3450 + * This is called when a file system is unmounted.
3453 +ext3_xattr_put_super(struct super_block *sb)
3455 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3456 + mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3460 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3463 + * ext3_xattr_cache_insert()
3465 + * Create a new entry in the extended attribute cache, and insert
3466 + * it unless such an entry is already in the cache.
3468 + * Returns 0, or a negative error number on failure.
3471 +ext3_xattr_cache_insert(struct buffer_head *bh)
3473 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3474 + struct mb_cache_entry *ce;
3477 + ce = mb_cache_entry_alloc(ext3_xattr_cache);
3480 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3482 + mb_cache_entry_free(ce);
3483 + if (error == -EBUSY) {
3484 + ea_bdebug(bh, "already in cache (%d cache entries)",
3485 + atomic_read(&ext3_xattr_cache->c_entry_count));
3489 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3490 + atomic_read(&ext3_xattr_cache->c_entry_count));
3491 + mb_cache_entry_release(ce);
3497 + * ext3_xattr_cmp()
3499 + * Compare two extended attribute blocks for equality.
3501 + * Returns 0 if the blocks are equal, 1 if they differ, and
3502 + * a negative error number on errors.
3505 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3506 + struct ext3_xattr_header *header2)
3508 + struct ext3_xattr_entry *entry1, *entry2;
3510 + entry1 = ENTRY(header1+1);
3511 + entry2 = ENTRY(header2+1);
3512 + while (!IS_LAST_ENTRY(entry1)) {
3513 + if (IS_LAST_ENTRY(entry2))
3515 + if (entry1->e_hash != entry2->e_hash ||
3516 + entry1->e_name_len != entry2->e_name_len ||
3517 + entry1->e_value_size != entry2->e_value_size ||
3518 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3520 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3522 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3523 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3524 + le32_to_cpu(entry1->e_value_size)))
3527 + entry1 = EXT3_XATTR_NEXT(entry1);
3528 + entry2 = EXT3_XATTR_NEXT(entry2);
3530 + if (!IS_LAST_ENTRY(entry2))
3536 + * ext3_xattr_cache_find()
3538 + * Find an identical extended attribute block.
3540 + * Returns a pointer to the block found, or NULL if such a block was
3541 + * not found or an error occurred.
3543 +static struct buffer_head *
3544 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3546 + __u32 hash = le32_to_cpu(header->h_hash);
3547 + struct mb_cache_entry *ce;
3549 + if (!header->h_hash)
3550 + return NULL; /* never share */
3551 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3552 + ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3554 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3557 + ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3558 + "inode %ld: block %ld read error",
3559 + inode->i_ino, ce->e_block);
3560 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3561 + EXT3_XATTR_REFCOUNT_MAX) {
3562 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3563 + le32_to_cpu(HDR(bh)->h_refcount),
3564 + EXT3_XATTR_REFCOUNT_MAX);
3565 + } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3566 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3567 + mb_cache_entry_release(ce);
3571 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3577 + * ext3_xattr_cache_remove()
3579 + * Remove the cache entry of a block from the cache. Called when a
3580 + * block becomes invalid.
3583 +ext3_xattr_cache_remove(struct buffer_head *bh)
3585 + struct mb_cache_entry *ce;
3587 + ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3589 + ea_bdebug(bh, "removing (%d cache entries remaining)",
3590 + atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3591 + mb_cache_entry_free(ce);
3593 + ea_bdebug(bh, "no cache entry");
3596 +#define NAME_HASH_SHIFT 5
3597 +#define VALUE_HASH_SHIFT 16
3600 + * ext3_xattr_hash_entry()
3602 + * Compute the hash of an extended attribute.
3604 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3605 + struct ext3_xattr_entry *entry)
3608 + char *name = entry->e_name;
3611 + for (n=0; n < entry->e_name_len; n++) {
3612 + hash = (hash << NAME_HASH_SHIFT) ^
3613 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3617 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3618 + __u32 *value = (__u32 *)((char *)header +
3619 + le16_to_cpu(entry->e_value_offs));
3620 + for (n = (le32_to_cpu(entry->e_value_size) +
3621 + EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3622 + hash = (hash << VALUE_HASH_SHIFT) ^
3623 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3624 + le32_to_cpu(*value++);
3627 + entry->e_hash = cpu_to_le32(hash);
3630 +#undef NAME_HASH_SHIFT
3631 +#undef VALUE_HASH_SHIFT
3633 +#define BLOCK_HASH_SHIFT 16
3636 + * ext3_xattr_rehash()
3638 + * Re-compute the extended attribute hash value after an entry has changed.
3640 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3641 + struct ext3_xattr_entry *entry)
3643 + struct ext3_xattr_entry *here;
3646 + ext3_xattr_hash_entry(header, entry);
3647 + here = ENTRY(header+1);
3648 + while (!IS_LAST_ENTRY(here)) {
3649 + if (!here->e_hash) {
3650 + /* Block is not shared if an entry's hash value == 0 */
3654 + hash = (hash << BLOCK_HASH_SHIFT) ^
3655 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3656 + le32_to_cpu(here->e_hash);
3657 + here = EXT3_XATTR_NEXT(here);
3659 + header->h_hash = cpu_to_le32(hash);
3662 +#undef BLOCK_HASH_SHIFT
3665 +init_ext3_xattr(void)
3667 + ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3668 + sizeof(struct mb_cache_entry) +
3669 + sizeof(struct mb_cache_entry_index), 1, 61);
3670 + if (!ext3_xattr_cache)
3677 +exit_ext3_xattr(void)
3679 + if (ext3_xattr_cache)
3680 + mb_cache_destroy(ext3_xattr_cache);
3681 + ext3_xattr_cache = NULL;
3684 +#else /* CONFIG_EXT3_FS_XATTR_SHARING */
3687 +init_ext3_xattr(void)
3693 +exit_ext3_xattr(void)
3697 +#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
3698 Index: linux-2.4.29/fs/ext3/xattr_user.c
3699 ===================================================================
3700 --- linux-2.4.29.orig/fs/ext3/xattr_user.c 2005-05-03 17:59:40.234146648 +0300
3701 +++ linux-2.4.29/fs/ext3/xattr_user.c 2005-05-03 17:59:40.429117008 +0300
3704 + * linux/fs/ext3/xattr_user.c
3705 + * Handler for extended user attributes.
3707 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3710 +#include <linux/module.h>
3711 +#include <linux/string.h>
3712 +#include <linux/fs.h>
3713 +#include <linux/ext3_jbd.h>
3714 +#include <linux/ext3_fs.h>
3715 +#include <linux/ext3_xattr.h>
3717 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3718 +# include <linux/ext3_acl.h>
3721 +#define XATTR_USER_PREFIX "user."
3724 +ext3_xattr_user_list(char *list, struct inode *inode,
3725 + const char *name, int name_len)
3727 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3729 + if (!test_opt(inode->i_sb, XATTR_USER))
3733 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
3734 + memcpy(list+prefix_len, name, name_len);
3735 + list[prefix_len + name_len] = '\0';
3737 + return prefix_len + name_len + 1;
3741 +ext3_xattr_user_get(struct inode *inode, const char *name,
3742 + void *buffer, size_t size)
3746 + if (strcmp(name, "") == 0)
3748 + if (!test_opt(inode->i_sb, XATTR_USER))
3750 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3751 + error = ext3_permission_locked(inode, MAY_READ);
3753 + error = permission(inode, MAY_READ);
3758 + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
3763 +ext3_xattr_user_set(struct inode *inode, const char *name,
3764 + const void *value, size_t size, int flags)
3769 + if (strcmp(name, "") == 0)
3771 + if (!test_opt(inode->i_sb, XATTR_USER))
3773 + if ( !S_ISREG(inode->i_mode) &&
3774 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
3776 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3777 + error = ext3_permission_locked(inode, MAY_WRITE);
3779 + error = permission(inode, MAY_WRITE);
3784 + handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
3785 + if (IS_ERR(handle))
3786 + return PTR_ERR(handle);
3787 + error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
3788 + value, size, flags);
3789 + ext3_journal_stop(handle, inode);
3794 +struct ext3_xattr_handler ext3_xattr_user_handler = {
3795 + prefix: XATTR_USER_PREFIX,
3796 + list: ext3_xattr_user_list,
3797 + get: ext3_xattr_user_get,
3798 + set: ext3_xattr_user_set,
3802 +init_ext3_xattr_user(void)
3804 + return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
3805 + &ext3_xattr_user_handler);
3809 +exit_ext3_xattr_user(void)
3811 + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
3812 + &ext3_xattr_user_handler);
3814 Index: linux-2.4.29/fs/ext3/ext3-exports.c
3815 ===================================================================
3816 --- linux-2.4.29.orig/fs/ext3/ext3-exports.c 2005-05-03 17:59:40.234146648 +0300
3817 +++ linux-2.4.29/fs/ext3/ext3-exports.c 2005-05-03 18:00:08.195895816 +0300
3819 +#include <linux/config.h>
3820 +#include <linux/module.h>
3821 +#include <linux/ext3_fs.h>
3822 +#include <linux/ext3_jbd.h>
3823 +#include <linux/ext3_xattr.h>
3825 +EXPORT_SYMBOL(ext3_force_commit);
3826 +EXPORT_SYMBOL(ext3_bread);
3827 +EXPORT_SYMBOL(ext3_xattr_register);
3828 +EXPORT_SYMBOL(ext3_xattr_unregister);
3829 +EXPORT_SYMBOL(ext3_xattr_get);
3830 +EXPORT_SYMBOL(ext3_xattr_list);
3831 +EXPORT_SYMBOL(ext3_xattr_set);
3832 Index: linux-2.4.29/fs/jfs/jfs_xattr.h
3833 ===================================================================
3834 --- linux-2.4.29.orig/fs/jfs/jfs_xattr.h 2005-04-07 18:53:29.000000000 +0300
3835 +++ linux-2.4.29/fs/jfs/jfs_xattr.h 2005-05-03 17:59:40.431116704 +0300
3837 #define END_EALIST(ealist) \
3838 ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
3840 -extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
3841 -extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
3842 +extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
3844 +extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
3846 extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
3847 extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
3848 extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
3849 Index: linux-2.4.29/fs/jfs/xattr.c
3850 ===================================================================
3851 --- linux-2.4.29.orig/fs/jfs/xattr.c 2005-04-07 18:52:32.000000000 +0300
3852 +++ linux-2.4.29/fs/jfs/xattr.c 2005-05-03 17:59:40.433116400 +0300
3856 static int can_set_xattr(struct inode *inode, const char *name,
3857 - void *value, size_t value_len)
3858 + const void *value, size_t value_len)
3860 if (IS_RDONLY(inode))
3863 return permission(inode, MAY_WRITE);
3866 -int __jfs_setxattr(struct inode *inode, const char *name, void *value,
3867 +int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
3868 size_t value_len, int flags)
3870 struct jfs_ea_list *ealist;
3875 -int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
3876 +int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
3877 size_t value_len, int flags)
3879 if (value == NULL) { /* empty EA, do not remove */
3880 Index: linux-2.4.29/fs/mbcache.c
3881 ===================================================================
3882 --- linux-2.4.29.orig/fs/mbcache.c 2005-05-03 17:59:40.235146496 +0300
3883 +++ linux-2.4.29/fs/mbcache.c 2005-05-03 17:59:40.436115944 +0300
3886 + * linux/fs/mbcache.c
3887 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
3891 + * Filesystem Meta Information Block Cache (mbcache)
3893 + * The mbcache caches blocks of block devices that need to be located
3894 + * by their device/block number, as well as by other criteria (such
3895 + * as the block's contents).
3897 + * There can only be one cache entry in a cache per device and block number.
3898 + * Additional indexes need not be unique in this sense. The number of
3899 + * additional indexes (=other criteria) can be hardwired at compile time
3900 + * or specified at cache create time.
3902 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
3903 + * in the cache. A valid entry is in the main hash tables of the cache,
3904 + * and may also be in the lru list. An invalid entry is not in any hashes
3907 + * A valid cache entry is only in the lru list if no handles refer to it.
3908 + * Invalid cache entries will be freed when the last handle to the cache
3909 + * entry is released. Entries that cannot be freed immediately are put
3910 + * back on the lru list.
3913 +#include <linux/kernel.h>
3914 +#include <linux/module.h>
3916 +#include <linux/fs.h>
3917 +#include <linux/slab.h>
3918 +#include <linux/sched.h>
3919 +#include <linux/cache_def.h>
3920 +#include <linux/version.h>
3921 +#include <linux/init.h>
3922 +#include <linux/mbcache.h>
3925 +#ifdef MB_CACHE_DEBUG
3926 +# define mb_debug(f...) do { \
3927 + printk(KERN_DEBUG f); \
3930 +#define mb_assert(c) do { if (!(c)) \
3931 + printk(KERN_ERR "assertion " #c " failed\n"); \
3934 +# define mb_debug(f...) do { } while(0)
3935 +# define mb_assert(c) do { } while(0)
3937 +#define mb_error(f...) do { \
3938 + printk(KERN_ERR f); \
3942 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
3943 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
3944 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3945 +MODULE_LICENSE("GPL");
3948 +EXPORT_SYMBOL(mb_cache_create);
3949 +EXPORT_SYMBOL(mb_cache_shrink);
3950 +EXPORT_SYMBOL(mb_cache_destroy);
3951 +EXPORT_SYMBOL(mb_cache_entry_alloc);
3952 +EXPORT_SYMBOL(mb_cache_entry_insert);
3953 +EXPORT_SYMBOL(mb_cache_entry_release);
3954 +EXPORT_SYMBOL(mb_cache_entry_takeout);
3955 +EXPORT_SYMBOL(mb_cache_entry_free);
3956 +EXPORT_SYMBOL(mb_cache_entry_dup);
3957 +EXPORT_SYMBOL(mb_cache_entry_get);
3958 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
3959 +EXPORT_SYMBOL(mb_cache_entry_find_first);
3960 +EXPORT_SYMBOL(mb_cache_entry_find_next);
3965 + * Global data: list of all mbcache's, lru list, and a spinlock for
3966 + * accessing cache data structures on SMP machines. The lru list is
3967 + * global across all mbcaches.
3970 +static LIST_HEAD(mb_cache_list);
3971 +static LIST_HEAD(mb_cache_lru_list);
3972 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
3975 +mb_cache_indexes(struct mb_cache *cache)
3977 +#ifdef MB_CACHE_INDEXES_COUNT
3978 + return MB_CACHE_INDEXES_COUNT;
3980 + return cache->c_indexes_count;
3985 + * What the mbcache registers as to get shrunk dynamically.
3989 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
3991 +static struct cache_definition mb_cache_definition = {
3993 + mb_cache_memory_pressure
3998 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4000 + return !list_empty(&ce->e_block_list);
4005 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4009 + if (__mb_cache_entry_is_hashed(ce)) {
4010 + list_del_init(&ce->e_block_list);
4011 + for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4012 + list_del(&ce->e_indexes[n].o_list);
4018 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4020 + struct mb_cache *cache = ce->e_cache;
4022 + mb_assert(atomic_read(&ce->e_used) == 0);
4023 + if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4024 + /* free failed -- put back on the lru list
4025 + for freeing later. */
4026 + spin_lock(&mb_cache_spinlock);
4027 + list_add(&ce->e_lru_list, &mb_cache_lru_list);
4028 + spin_unlock(&mb_cache_spinlock);
4030 + kmem_cache_free(cache->c_entry_cache, ce);
4031 + atomic_dec(&cache->c_entry_count);
4037 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4039 + if (atomic_dec_and_test(&ce->e_used)) {
4040 + if (__mb_cache_entry_is_hashed(ce))
4041 + list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4043 + spin_unlock(&mb_cache_spinlock);
4044 + __mb_cache_entry_forget(ce, GFP_KERNEL);
4048 + spin_unlock(&mb_cache_spinlock);
4053 + * mb_cache_memory_pressure() memory pressure callback
4055 + * This function is called by the kernel memory management when memory
4058 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4059 + * @gfp_mask: (ignored)
4062 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4064 + LIST_HEAD(free_list);
4065 + struct list_head *l, *ltmp;
4068 + spin_lock(&mb_cache_spinlock);
4069 + list_for_each(l, &mb_cache_list) {
4070 + struct mb_cache *cache =
4071 + list_entry(l, struct mb_cache, c_cache_list);
4072 + mb_debug("cache %s (%d)", cache->c_name,
4073 + atomic_read(&cache->c_entry_count));
4074 + count += atomic_read(&cache->c_entry_count);
4076 + mb_debug("trying to free %d of %d entries",
4077 + count / (priority ? priority : 1), count);
4079 + count /= priority;
4080 + while (count-- && !list_empty(&mb_cache_lru_list)) {
4081 + struct mb_cache_entry *ce =
4082 + list_entry(mb_cache_lru_list.next,
4083 + struct mb_cache_entry, e_lru_list);
4084 + list_del(&ce->e_lru_list);
4085 + __mb_cache_entry_unhash(ce);
4086 + list_add_tail(&ce->e_lru_list, &free_list);
4088 + spin_unlock(&mb_cache_spinlock);
4089 + list_for_each_safe(l, ltmp, &free_list) {
4090 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4091 + e_lru_list), gfp_mask);
4097 + * mb_cache_create() create a new cache
4099 + * All entries in one cache are equal size. Cache entries may be from
4100 + * multiple devices. If this is the first mbcache created, registers
4101 + * the cache with kernel memory management. Returns NULL if no more
4102 + * memory was available.
4104 + * @name: name of the cache (informal)
4105 + * @cache_op: contains the callback called when freeing a cache entry
4106 + * @entry_size: The size of a cache entry, including
4107 + * struct mb_cache_entry
4108 + * @indexes_count: number of additional indexes in the cache. Must equal
4109 + * MB_CACHE_INDEXES_COUNT if the number of indexes is
4111 + * @bucket_count: number of hash buckets
4114 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4115 + size_t entry_size, int indexes_count, int bucket_count)
4118 + struct mb_cache *cache = NULL;
4120 + if(entry_size < sizeof(struct mb_cache_entry) +
4121 + indexes_count * sizeof(struct mb_cache_entry_index))
4124 + MOD_INC_USE_COUNT;
4125 + cache = kmalloc(sizeof(struct mb_cache) +
4126 + indexes_count * sizeof(struct list_head), GFP_KERNEL);
4129 + cache->c_name = name;
4130 + cache->c_op.free = NULL;
4132 + cache->c_op.free = cache_op->free;
4133 + atomic_set(&cache->c_entry_count, 0);
4134 + cache->c_bucket_count = bucket_count;
4135 +#ifdef MB_CACHE_INDEXES_COUNT
4136 + mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4138 + cache->c_indexes_count = indexes_count;
4140 + cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4142 + if (!cache->c_block_hash)
4144 + for (n=0; n<bucket_count; n++)
4145 + INIT_LIST_HEAD(&cache->c_block_hash[n]);
4146 + for (m=0; m<indexes_count; m++) {
4147 + cache->c_indexes_hash[m] = kmalloc(bucket_count *
4148 + sizeof(struct list_head),
4150 + if (!cache->c_indexes_hash[m])
4152 + for (n=0; n<bucket_count; n++)
4153 + INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4155 + cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4156 + 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4157 + if (!cache->c_entry_cache)
4160 + spin_lock(&mb_cache_spinlock);
4161 + list_add(&cache->c_cache_list, &mb_cache_list);
4162 + spin_unlock(&mb_cache_spinlock);
4168 + kfree(cache->c_indexes_hash[m]);
4169 + if (cache->c_block_hash)
4170 + kfree(cache->c_block_hash);
4173 + MOD_DEC_USE_COUNT;
4179 + * mb_cache_shrink()
4181 + * Removes all cache entires of a device from the cache. All cache entries
4182 + * currently in use cannot be freed, and thus remain in the cache.
4184 + * @cache: which cache to shrink
4185 + * @dev: which device's cache entries to shrink
4188 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4190 + LIST_HEAD(free_list);
4191 + struct list_head *l, *ltmp;
4193 + spin_lock(&mb_cache_spinlock);
4194 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4195 + struct mb_cache_entry *ce =
4196 + list_entry(l, struct mb_cache_entry, e_lru_list);
4197 + if (ce->e_dev == dev) {
4198 + list_del(&ce->e_lru_list);
4199 + list_add_tail(&ce->e_lru_list, &free_list);
4200 + __mb_cache_entry_unhash(ce);
4203 + spin_unlock(&mb_cache_spinlock);
4204 + list_for_each_safe(l, ltmp, &free_list) {
4205 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4206 + e_lru_list), GFP_KERNEL);
4212 + * mb_cache_destroy()
4214 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4215 + * and then destroys it. If this was the last mbcache, un-registers the
4216 + * mbcache from kernel memory management.
4219 +mb_cache_destroy(struct mb_cache *cache)
4221 + LIST_HEAD(free_list);
4222 + struct list_head *l, *ltmp;
4225 + spin_lock(&mb_cache_spinlock);
4226 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4227 + struct mb_cache_entry *ce =
4228 + list_entry(l, struct mb_cache_entry, e_lru_list);
4229 + if (ce->e_cache == cache) {
4230 + list_del(&ce->e_lru_list);
4231 + list_add_tail(&ce->e_lru_list, &free_list);
4232 + __mb_cache_entry_unhash(ce);
4235 + list_del(&cache->c_cache_list);
4236 + spin_unlock(&mb_cache_spinlock);
4237 + list_for_each_safe(l, ltmp, &free_list) {
4238 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4239 + e_lru_list), GFP_KERNEL);
4242 + if (atomic_read(&cache->c_entry_count) > 0) {
4243 + mb_error("cache %s: %d orphaned entries",
4245 + atomic_read(&cache->c_entry_count));
4248 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4249 + /* We don't have kmem_cache_destroy() in 2.2.x */
4250 + kmem_cache_shrink(cache->c_entry_cache);
4252 + kmem_cache_destroy(cache->c_entry_cache);
4254 + for (n=0; n < mb_cache_indexes(cache); n++)
4255 + kfree(cache->c_indexes_hash[n]);
4256 + kfree(cache->c_block_hash);
4259 + MOD_DEC_USE_COUNT;
4264 + * mb_cache_entry_alloc()
4266 + * Allocates a new cache entry. The new entry will not be valid initially,
4267 + * and thus cannot be looked up yet. It should be filled with data, and
4268 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4269 + * if no more memory was available.
4271 +struct mb_cache_entry *
4272 +mb_cache_entry_alloc(struct mb_cache *cache)
4274 + struct mb_cache_entry *ce;
4276 + atomic_inc(&cache->c_entry_count);
4277 + ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4279 + INIT_LIST_HEAD(&ce->e_lru_list);
4280 + INIT_LIST_HEAD(&ce->e_block_list);
4281 + ce->e_cache = cache;
4282 + atomic_set(&ce->e_used, 1);
4289 + * mb_cache_entry_insert()
4291 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4292 + * the cache. After this, the cache entry can be looked up, but is not yet
4293 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4294 + * success, or -EBUSY if a cache entry for that device + inode exists
4295 + * already (this may happen after a failed lookup, if another process has
4296 + * inserted the same cache entry in the meantime).
4298 + * @dev: device the cache entry belongs to
4299 + * @block: block number
4300 + * @keys: array of additional keys. There must be indexes_count entries
4301 + * in the array (as specified when creating the cache).
4304 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4305 + unsigned long block, unsigned int keys[])
4307 + struct mb_cache *cache = ce->e_cache;
4308 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4309 + struct list_head *l;
4310 + int error = -EBUSY, n;
4312 + spin_lock(&mb_cache_spinlock);
4313 + list_for_each(l, &cache->c_block_hash[bucket]) {
4314 + struct mb_cache_entry *ce =
4315 + list_entry(l, struct mb_cache_entry, e_block_list);
4316 + if (ce->e_dev == dev && ce->e_block == block)
4319 + __mb_cache_entry_unhash(ce);
4321 + ce->e_block = block;
4322 + list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4323 + for (n=0; n<mb_cache_indexes(cache); n++) {
4324 + ce->e_indexes[n].o_key = keys[n];
4325 + bucket = keys[n] % cache->c_bucket_count;
4326 + list_add(&ce->e_indexes[n].o_list,
4327 + &cache->c_indexes_hash[n][bucket]);
4330 + spin_unlock(&mb_cache_spinlock);
4336 + * mb_cache_entry_release()
4338 + * Release a handle to a cache entry. When the last handle to a cache entry
4339 + * is released it is either freed (if it is invalid) or otherwise inserted
4340 + * in to the lru list.
4343 +mb_cache_entry_release(struct mb_cache_entry *ce)
4345 + spin_lock(&mb_cache_spinlock);
4346 + __mb_cache_entry_release_unlock(ce);
4351 + * mb_cache_entry_takeout()
4353 + * Take a cache entry out of the cache, making it invalid. The entry can later
4354 + * be re-inserted using mb_cache_entry_insert(), or released using
4355 + * mb_cache_entry_release().
4358 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4360 + spin_lock(&mb_cache_spinlock);
4361 + mb_assert(list_empty(&ce->e_lru_list));
4362 + __mb_cache_entry_unhash(ce);
4363 + spin_unlock(&mb_cache_spinlock);
4368 + * mb_cache_entry_free()
4370 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4371 + * mb_cache_entry_release().
4374 +mb_cache_entry_free(struct mb_cache_entry *ce)
4376 + spin_lock(&mb_cache_spinlock);
4377 + mb_assert(list_empty(&ce->e_lru_list));
4378 + __mb_cache_entry_unhash(ce);
4379 + __mb_cache_entry_release_unlock(ce);
4384 + * mb_cache_entry_dup()
4386 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4387 + * itself). After the call, both the old and the new handle must be released.
4389 +struct mb_cache_entry *
4390 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4392 + atomic_inc(&ce->e_used);
4398 + * mb_cache_entry_get()
4400 + * Get a cache entry by device / block number. (There can only be one entry
4401 + * in the cache per device and block.) Returns NULL if no such cache entry
4404 +struct mb_cache_entry *
4405 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4407 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4408 + struct list_head *l;
4409 + struct mb_cache_entry *ce;
4411 + spin_lock(&mb_cache_spinlock);
4412 + list_for_each(l, &cache->c_block_hash[bucket]) {
4413 + ce = list_entry(l, struct mb_cache_entry, e_block_list);
4414 + if (ce->e_dev == dev && ce->e_block == block) {
4415 + if (!list_empty(&ce->e_lru_list))
4416 + list_del_init(&ce->e_lru_list);
4417 + atomic_inc(&ce->e_used);
4424 + spin_unlock(&mb_cache_spinlock);
4428 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4430 +static struct mb_cache_entry *
4431 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4432 + int index, kdev_t dev, unsigned int key)
4434 + while (l != head) {
4435 + struct mb_cache_entry *ce =
4436 + list_entry(l, struct mb_cache_entry,
4437 + e_indexes[index].o_list);
4438 + if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4439 + if (!list_empty(&ce->e_lru_list))
4440 + list_del_init(&ce->e_lru_list);
4441 + atomic_inc(&ce->e_used);
4451 + * mb_cache_entry_find_first()
4453 + * Find the first cache entry on a given device with a certain key in
4454 + * an additional index. Additonal matches can be found with
4455 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4457 + * @cache: the cache to search
4458 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4459 + * @dev: the device the cache entry should belong to
4460 + * @key: the key in the index
4462 +struct mb_cache_entry *
4463 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4466 + unsigned int bucket = key % cache->c_bucket_count;
4467 + struct list_head *l;
4468 + struct mb_cache_entry *ce;
4470 + mb_assert(index < mb_cache_indexes(cache));
4471 + spin_lock(&mb_cache_spinlock);
4472 + l = cache->c_indexes_hash[index][bucket].next;
4473 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4475 + spin_unlock(&mb_cache_spinlock);
4481 + * mb_cache_entry_find_next()
4483 + * Find the next cache entry on a given device with a certain key in an
4484 + * additional index. Returns NULL if no match could be found. The previous
4485 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4486 + * be called like this:
4488 + * entry = mb_cache_entry_find_first();
4491 + * entry = mb_cache_entry_find_next(entry, ...);
4494 + * @prev: The previous match
4495 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4496 + * @dev: the device the cache entry should belong to
4497 + * @key: the key in the index
4499 +struct mb_cache_entry *
4500 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4503 + struct mb_cache *cache = prev->e_cache;
4504 + unsigned int bucket = key % cache->c_bucket_count;
4505 + struct list_head *l;
4506 + struct mb_cache_entry *ce;
4508 + mb_assert(index < mb_cache_indexes(cache));
4509 + spin_lock(&mb_cache_spinlock);
4510 + l = prev->e_indexes[index].o_list.next;
4511 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4513 + __mb_cache_entry_release_unlock(prev);
4517 +#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4519 +static int __init init_mbcache(void)
4521 + register_cache(&mb_cache_definition);
4525 +static void __exit exit_mbcache(void)
4527 + unregister_cache(&mb_cache_definition);
4530 +module_init(init_mbcache)
4531 +module_exit(exit_mbcache)
4533 Index: linux-2.4.29/include/asm-arm/unistd.h
4534 ===================================================================
4535 --- linux-2.4.29.orig/include/asm-arm/unistd.h 2005-04-07 18:55:01.000000000 +0300
4536 +++ linux-2.4.29/include/asm-arm/unistd.h 2005-05-03 17:59:40.438115640 +0300
4538 #define __NR_security (__NR_SYSCALL_BASE+223)
4539 #define __NR_gettid (__NR_SYSCALL_BASE+224)
4540 #define __NR_readahead (__NR_SYSCALL_BASE+225)
4541 -#if 0 /* allocated in 2.5 */
4542 #define __NR_setxattr (__NR_SYSCALL_BASE+226)
4543 #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
4544 #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
4546 #define __NR_removexattr (__NR_SYSCALL_BASE+235)
4547 #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
4548 #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
4550 #define __NR_tkill (__NR_SYSCALL_BASE+238)
4551 #if 0 /* allocated in 2.5 */
4552 #define __NR_sendfile64 (__NR_SYSCALL_BASE+239)
4553 Index: linux-2.4.29/include/asm-ppc64/unistd.h
4554 ===================================================================
4555 --- linux-2.4.29.orig/include/asm-ppc64/unistd.h 2005-04-07 18:52:47.000000000 +0300
4556 +++ linux-2.4.29/include/asm-ppc64/unistd.h 2005-05-03 17:59:40.439115488 +0300
4558 #define __NR_mincore 206
4559 #define __NR_gettid 207
4560 #define __NR_tkill 208
4562 #define __NR_setxattr 209
4563 #define __NR_lsetxattr 210
4564 #define __NR_fsetxattr 211
4566 #define __NR_removexattr 218
4567 #define __NR_lremovexattr 219
4568 #define __NR_fremovexattr 220
4569 +#if 0 /* Reserved syscalls */
4570 #define __NR_futex 221
4571 #define __NR_sched_setaffinity 222
4572 #define __NR_sched_getaffinity 223
4573 Index: linux-2.4.29/include/asm-s390/unistd.h
4574 ===================================================================
4575 --- linux-2.4.29.orig/include/asm-s390/unistd.h 2005-04-07 18:55:23.000000000 +0300
4576 +++ linux-2.4.29/include/asm-s390/unistd.h 2005-05-03 17:59:40.440115336 +0300
4577 @@ -213,9 +213,18 @@
4578 #define __NR_getdents64 220
4579 #define __NR_fcntl64 221
4580 #define __NR_readahead 222
4582 - * Numbers 224-235 are reserved for posix acl
4584 +#define __NR_setxattr 224
4585 +#define __NR_lsetxattr 225
4586 +#define __NR_fsetxattr 226
4587 +#define __NR_getxattr 227
4588 +#define __NR_lgetxattr 228
4589 +#define __NR_fgetxattr 229
4590 +#define __NR_listxattr 230
4591 +#define __NR_llistxattr 231
4592 +#define __NR_flistxattr 232
4593 +#define __NR_removexattr 233
4594 +#define __NR_lremovexattr 234
4595 +#define __NR_fremovexattr 235
4596 #define __NR_gettid 236
4597 #define __NR_tkill 237
4599 Index: linux-2.4.29/include/asm-s390x/unistd.h
4600 ===================================================================
4601 --- linux-2.4.29.orig/include/asm-s390x/unistd.h 2005-04-07 18:54:22.000000000 +0300
4602 +++ linux-2.4.29/include/asm-s390x/unistd.h 2005-05-03 17:59:40.441115184 +0300
4603 @@ -181,9 +181,18 @@
4604 #define __NR_mincore 218
4605 #define __NR_madvise 219
4606 #define __NR_readahead 222
4608 - * Numbers 224-235 are reserved for posix acl
4610 +#define __NR_setxattr 224
4611 +#define __NR_lsetxattr 225
4612 +#define __NR_fsetxattr 226
4613 +#define __NR_getxattr 227
4614 +#define __NR_lgetxattr 228
4615 +#define __NR_fgetxattr 229
4616 +#define __NR_listxattr 230
4617 +#define __NR_llistxattr 231
4618 +#define __NR_flistxattr 232
4619 +#define __NR_removexattr 233
4620 +#define __NR_lremovexattr 234
4621 +#define __NR_fremovexattr 235
4622 #define __NR_gettid 236
4623 #define __NR_tkill 237
4625 Index: linux-2.4.29/include/linux/cache_def.h
4626 ===================================================================
4627 --- linux-2.4.29.orig/include/linux/cache_def.h 2005-05-03 17:59:40.235146496 +0300
4628 +++ linux-2.4.29/include/linux/cache_def.h 2005-05-03 17:59:40.442115032 +0300
4631 + * linux/cache_def.h
4632 + * Handling of caches defined in drivers, filesystems, ...
4634 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
4637 +struct cache_definition {
4639 + void (*shrink)(int, unsigned int);
4640 + struct list_head link;
4643 +extern void register_cache(struct cache_definition *);
4644 +extern void unregister_cache(struct cache_definition *);
4645 Index: linux-2.4.29/include/linux/errno.h
4646 ===================================================================
4647 --- linux-2.4.29.orig/include/linux/errno.h 2005-04-07 18:54:43.000000000 +0300
4648 +++ linux-2.4.29/include/linux/errno.h 2005-05-03 17:59:40.443114880 +0300
4653 +/* Defined for extended attributes */
4654 +#define ENOATTR ENODATA /* No such attribute */
4655 +#define ENOTSUP EOPNOTSUPP /* Operation not supported */
4658 Index: linux-2.4.29/include/linux/ext2_fs.h
4659 ===================================================================
4660 --- linux-2.4.29.orig/include/linux/ext2_fs.h 2005-04-07 18:52:37.000000000 +0300
4661 +++ linux-2.4.29/include/linux/ext2_fs.h 2005-05-03 17:59:40.445114576 +0300
4664 #define EXT2_BAD_INO 1 /* Bad blocks inode */
4665 #define EXT2_ROOT_INO 2 /* Root inode */
4666 -#define EXT2_ACL_IDX_INO 3 /* ACL inode */
4667 -#define EXT2_ACL_DATA_INO 4 /* ACL inode */
4668 #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
4669 #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
4673 # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
4675 -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
4676 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
4678 # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
4679 @@ -121,28 +118,6 @@
4685 -struct ext2_acl_header /* Header of Access Control Lists */
4688 - __u32 aclh_file_count;
4689 - __u32 aclh_acle_count;
4690 - __u32 aclh_first_acle;
4693 -struct ext2_acl_entry /* Access Control List Entry */
4696 - __u16 acle_perms; /* Access permissions */
4697 - __u16 acle_type; /* Type of entry */
4698 - __u16 acle_tag; /* User or group identity */
4700 - __u32 acle_next; /* Pointer on next entry for the */
4701 - /* same inode or on next free entry */
4705 * Structure of a blocks group descriptor
4707 struct ext2_group_desc
4709 #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
4710 #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
4711 #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
4712 +#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
4714 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
4715 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
4719 #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
4720 +#define EXT2_I(inode) (&((inode)->u.ext2_i))
4722 /* Assume that user mode programs are passing in an ext2fs superblock, not
4723 * a kernel struct super_block. This will allow us to call the feature-test
4725 #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
4726 #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
4728 -#define EXT2_FEATURE_COMPAT_SUPP 0
4729 +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
4730 #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
4731 EXT2_FEATURE_INCOMPAT_META_BG)
4732 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
4733 @@ -650,8 +627,10 @@
4736 extern struct inode_operations ext2_dir_inode_operations;
4737 +extern struct inode_operations ext2_special_inode_operations;
4740 +extern struct inode_operations ext2_symlink_inode_operations;
4741 extern struct inode_operations ext2_fast_symlink_inode_operations;
4743 #endif /* __KERNEL__ */
4744 Index: linux-2.4.29/include/linux/ext2_xattr.h
4745 ===================================================================
4746 --- linux-2.4.29.orig/include/linux/ext2_xattr.h 2005-05-03 17:59:40.236146344 +0300
4747 +++ linux-2.4.29/include/linux/ext2_xattr.h 2005-05-03 17:59:40.446114424 +0300
4750 + File: linux/ext2_xattr.h
4752 + On-disk format of extended attributes for the ext2 filesystem.
4754 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4757 +#include <linux/config.h>
4758 +#include <linux/init.h>
4759 +#include <linux/xattr.h>
4761 +/* Magic value in attribute blocks */
4762 +#define EXT2_XATTR_MAGIC 0xEA020000
4764 +/* Maximum number of references to one attribute block */
4765 +#define EXT2_XATTR_REFCOUNT_MAX 1024
4768 +#define EXT2_XATTR_INDEX_MAX 10
4769 +#define EXT2_XATTR_INDEX_USER 1
4770 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
4771 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
4773 +struct ext2_xattr_header {
4774 + __u32 h_magic; /* magic number for identification */
4775 + __u32 h_refcount; /* reference count */
4776 + __u32 h_blocks; /* number of disk blocks used */
4777 + __u32 h_hash; /* hash value of all attributes */
4778 + __u32 h_reserved[4]; /* zero right now */
4781 +struct ext2_xattr_entry {
4782 + __u8 e_name_len; /* length of name */
4783 + __u8 e_name_index; /* attribute name index */
4784 + __u16 e_value_offs; /* offset in disk block of value */
4785 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
4786 + __u32 e_value_size; /* size of attribute value */
4787 + __u32 e_hash; /* hash value of name and value */
4788 + char e_name[0]; /* attribute name */
4791 +#define EXT2_XATTR_PAD_BITS 2
4792 +#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
4793 +#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
4794 +#define EXT2_XATTR_LEN(name_len) \
4795 + (((name_len) + EXT2_XATTR_ROUND + \
4796 + sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
4797 +#define EXT2_XATTR_NEXT(entry) \
4798 + ( (struct ext2_xattr_entry *)( \
4799 + (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
4800 +#define EXT2_XATTR_SIZE(size) \
4801 + (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
4805 +# ifdef CONFIG_EXT2_FS_XATTR
4807 +struct ext2_xattr_handler {
4809 + size_t (*list)(char *list, struct inode *inode, const char *name,
4811 + int (*get)(struct inode *inode, const char *name, void *buffer,
4813 + int (*set)(struct inode *inode, const char *name, const void *buffer,
4814 + size_t size, int flags);
4817 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
4818 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
4820 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
4821 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
4822 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
4823 +extern int ext2_removexattr(struct dentry *, const char *);
4825 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
4826 +extern int ext2_xattr_list(struct inode *, char *, size_t);
4827 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
4829 +extern void ext2_xattr_delete_inode(struct inode *);
4830 +extern void ext2_xattr_put_super(struct super_block *);
4832 +extern int init_ext2_xattr(void) __init;
4833 +extern void exit_ext2_xattr(void);
4835 +# else /* CONFIG_EXT2_FS_XATTR */
4836 +# define ext2_setxattr NULL
4837 +# define ext2_getxattr NULL
4838 +# define ext2_listxattr NULL
4839 +# define ext2_removexattr NULL
4842 +ext2_xattr_get(struct inode *inode, int name_index,
4843 + const char *name, void *buffer, size_t size)
4849 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
4855 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
4856 + const void *value, size_t size, int flags)
4862 +ext2_xattr_delete_inode(struct inode *inode)
4867 +ext2_xattr_put_super(struct super_block *sb)
4872 +init_ext2_xattr(void)
4878 +exit_ext2_xattr(void)
4882 +# endif /* CONFIG_EXT2_FS_XATTR */
4884 +# ifdef CONFIG_EXT2_FS_XATTR_USER
4886 +extern int init_ext2_xattr_user(void) __init;
4887 +extern void exit_ext2_xattr_user(void);
4889 +# else /* CONFIG_EXT2_FS_XATTR_USER */
4892 +init_ext2_xattr_user(void)
4898 +exit_ext2_xattr_user(void)
4902 +# endif /* CONFIG_EXT2_FS_XATTR_USER */
4904 +#endif /* __KERNEL__ */
4906 Index: linux-2.4.29/include/linux/ext3_fs.h
4907 ===================================================================
4908 --- linux-2.4.29.orig/include/linux/ext3_fs.h 2005-05-03 17:23:54.107407504 +0300
4909 +++ linux-2.4.29/include/linux/ext3_fs.h 2005-05-03 17:59:40.448114120 +0300
4912 #define EXT3_BAD_INO 1 /* Bad blocks inode */
4913 #define EXT3_ROOT_INO 2 /* Root inode */
4914 -#define EXT3_ACL_IDX_INO 3 /* ACL inode */
4915 -#define EXT3_ACL_DATA_INO 4 /* ACL inode */
4916 #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
4917 #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
4918 #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
4921 # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
4923 -#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
4924 #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
4926 # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
4927 @@ -129,28 +126,6 @@
4933 -struct ext3_acl_header /* Header of Access Control Lists */
4936 - __u32 aclh_file_count;
4937 - __u32 aclh_acle_count;
4938 - __u32 aclh_first_acle;
4941 -struct ext3_acl_entry /* Access Control List Entry */
4944 - __u16 acle_perms; /* Access permissions */
4945 - __u16 acle_type; /* Type of entry */
4946 - __u16 acle_tag; /* User or group identity */
4948 - __u32 acle_next; /* Pointer on next entry for the */
4949 - /* same inode or on next free entry */
4953 * Structure of a blocks group descriptor
4955 struct ext3_group_desc
4957 #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
4958 #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
4959 #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
4960 +#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
4962 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
4963 #ifndef _LINUX_EXT2_FS_H
4965 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
4966 #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010
4968 -#define EXT3_FEATURE_COMPAT_SUPP 0
4969 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
4970 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
4971 EXT3_FEATURE_INCOMPAT_RECOVER| \
4972 EXT3_FEATURE_INCOMPAT_META_BG)
4974 extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
4977 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
4978 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
4979 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
4981 @@ -787,8 +764,10 @@
4984 extern struct inode_operations ext3_dir_inode_operations;
4985 +extern struct inode_operations ext3_special_inode_operations;
4988 +extern struct inode_operations ext3_symlink_inode_operations;
4989 extern struct inode_operations ext3_fast_symlink_inode_operations;
4992 Index: linux-2.4.29/include/linux/ext3_jbd.h
4993 ===================================================================
4994 --- linux-2.4.29.orig/include/linux/ext3_jbd.h 2005-05-03 17:23:54.109407200 +0300
4995 +++ linux-2.4.29/include/linux/ext3_jbd.h 2005-05-03 17:59:40.449113968 +0300
4998 #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U
5000 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5001 + * and two group and summaries. */
5003 +#define EXT3_XATTR_TRANS_BLOCKS 8
5005 /* Define the minimum size for a transaction which modifies data. This
5006 * needs to take into account the fact that we may end up modifying two
5007 * quota files too (one for the group, one for the user quota). The
5008 * superblock only gets updated once, of course, so don't bother
5009 * counting that again for the quota updates. */
5011 -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5012 +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5013 + EXT3_XATTR_TRANS_BLOCKS - 2)
5015 extern int ext3_writepage_trans_blocks(struct inode *inode);
5017 Index: linux-2.4.29/include/linux/ext3_xattr.h
5018 ===================================================================
5019 --- linux-2.4.29.orig/include/linux/ext3_xattr.h 2005-05-03 17:59:40.236146344 +0300
5020 +++ linux-2.4.29/include/linux/ext3_xattr.h 2005-05-03 17:59:40.451113664 +0300
5023 + File: linux/ext3_xattr.h
5025 + On-disk format of extended attributes for the ext3 filesystem.
5027 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5030 +#include <linux/config.h>
5031 +#include <linux/init.h>
5032 +#include <linux/xattr.h>
5034 +/* Magic value in attribute blocks */
5035 +#define EXT3_XATTR_MAGIC 0xEA020000
5037 +/* Maximum number of references to one attribute block */
5038 +#define EXT3_XATTR_REFCOUNT_MAX 1024
5041 +#define EXT3_XATTR_INDEX_MAX 10
5042 +#define EXT3_XATTR_INDEX_USER 1
5043 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
5044 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5046 +struct ext3_xattr_header {
5047 + __u32 h_magic; /* magic number for identification */
5048 + __u32 h_refcount; /* reference count */
5049 + __u32 h_blocks; /* number of disk blocks used */
5050 + __u32 h_hash; /* hash value of all attributes */
5051 + __u32 h_reserved[4]; /* zero right now */
5054 +struct ext3_xattr_entry {
5055 + __u8 e_name_len; /* length of name */
5056 + __u8 e_name_index; /* attribute name index */
5057 + __u16 e_value_offs; /* offset in disk block of value */
5058 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5059 + __u32 e_value_size; /* size of attribute value */
5060 + __u32 e_hash; /* hash value of name and value */
5061 + char e_name[0]; /* attribute name */
5064 +#define EXT3_XATTR_PAD_BITS 2
5065 +#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
5066 +#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
5067 +#define EXT3_XATTR_LEN(name_len) \
5068 + (((name_len) + EXT3_XATTR_ROUND + \
5069 + sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5070 +#define EXT3_XATTR_NEXT(entry) \
5071 + ( (struct ext3_xattr_entry *)( \
5072 + (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5073 +#define EXT3_XATTR_SIZE(size) \
5074 + (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5078 +# ifdef CONFIG_EXT3_FS_XATTR
5080 +struct ext3_xattr_handler {
5082 + size_t (*list)(char *list, struct inode *inode, const char *name,
5084 + int (*get)(struct inode *inode, const char *name, void *buffer,
5086 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5087 + size_t size, int flags);
5090 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5091 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5093 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5094 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5095 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5096 +extern int ext3_removexattr(struct dentry *, const char *);
5098 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5099 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5100 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5102 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5103 +extern void ext3_xattr_put_super(struct super_block *);
5105 +extern int init_ext3_xattr(void) __init;
5106 +extern void exit_ext3_xattr(void);
5108 +# else /* CONFIG_EXT3_FS_XATTR */
5109 +# define ext3_setxattr NULL
5110 +# define ext3_getxattr NULL
5111 +# define ext3_listxattr NULL
5112 +# define ext3_removexattr NULL
5115 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5116 + void *buffer, size_t size)
5122 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5128 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5129 + const char *name, const void *value, size_t size, int flags)
5135 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5140 +ext3_xattr_put_super(struct super_block *sb)
5145 +init_ext3_xattr(void)
5151 +exit_ext3_xattr(void)
5155 +# endif /* CONFIG_EXT3_FS_XATTR */
5157 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5159 +extern int init_ext3_xattr_user(void) __init;
5160 +extern void exit_ext3_xattr_user(void);
5162 +# else /* CONFIG_EXT3_FS_XATTR_USER */
5165 +init_ext3_xattr_user(void)
5171 +exit_ext3_xattr_user(void)
5175 +#endif /* CONFIG_EXT3_FS_XATTR_USER */
5177 +#endif /* __KERNEL__ */
5179 Index: linux-2.4.29/include/linux/fs.h
5180 ===================================================================
5181 --- linux-2.4.29.orig/include/linux/fs.h 2005-05-03 17:23:53.736463896 +0300
5182 +++ linux-2.4.29/include/linux/fs.h 2005-05-03 17:59:40.453113360 +0300
5184 int (*setattr) (struct dentry *, struct iattr *);
5185 int (*setattr_raw) (struct inode *, struct iattr *);
5186 int (*getattr) (struct dentry *, struct iattr *);
5187 - int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
5188 + int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5189 ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5190 ssize_t (*listxattr) (struct dentry *, char *, size_t);
5191 int (*removexattr) (struct dentry *, const char *);
5192 Index: linux-2.4.29/include/linux/mbcache.h
5193 ===================================================================
5194 --- linux-2.4.29.orig/include/linux/mbcache.h 2005-05-03 17:59:40.236146344 +0300
5195 +++ linux-2.4.29/include/linux/mbcache.h 2005-05-03 17:59:40.454113208 +0300
5198 + File: linux/mbcache.h
5200 + (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5203 +/* Hardwire the number of additional indexes */
5204 +#define MB_CACHE_INDEXES_COUNT 1
5206 +struct mb_cache_entry;
5208 +struct mb_cache_op {
5209 + int (*free)(struct mb_cache_entry *, int);
5213 + struct list_head c_cache_list;
5214 + const char *c_name;
5215 + struct mb_cache_op c_op;
5216 + atomic_t c_entry_count;
5217 + int c_bucket_count;
5218 +#ifndef MB_CACHE_INDEXES_COUNT
5219 + int c_indexes_count;
5221 + kmem_cache_t *c_entry_cache;
5222 + struct list_head *c_block_hash;
5223 + struct list_head *c_indexes_hash[0];
5226 +struct mb_cache_entry_index {
5227 + struct list_head o_list;
5228 + unsigned int o_key;
5231 +struct mb_cache_entry {
5232 + struct list_head e_lru_list;
5233 + struct mb_cache *e_cache;
5236 + unsigned long e_block;
5237 + struct list_head e_block_list;
5238 + struct mb_cache_entry_index e_indexes[0];
5241 +/* Functions on caches */
5243 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5245 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5246 +void mb_cache_destroy(struct mb_cache *);
5248 +/* Functions on cache entries */
5250 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5251 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5253 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5254 +void mb_cache_entry_release(struct mb_cache_entry *);
5255 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5256 +void mb_cache_entry_free(struct mb_cache_entry *);
5257 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5258 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5260 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5261 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5262 + kdev_t, unsigned int);
5263 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5264 + kdev_t, unsigned int);
5266 Index: linux-2.4.29/kernel/ksyms.c
5267 ===================================================================
5268 --- linux-2.4.29.orig/kernel/ksyms.c 2005-04-07 19:14:06.000000000 +0300
5269 +++ linux-2.4.29/kernel/ksyms.c 2005-05-03 17:59:40.456112904 +0300
5272 #include <linux/config.h>
5273 #include <linux/slab.h>
5274 +#include <linux/cache_def.h>
5275 #include <linux/module.h>
5276 #include <linux/blkdev.h>
5277 #include <linux/cdrom.h>
5279 EXPORT_SYMBOL(exit_files);
5280 EXPORT_SYMBOL(exit_fs);
5281 EXPORT_SYMBOL(exit_sighand);
5282 +EXPORT_SYMBOL(copy_fs_struct);
5284 /* internal kernel memory management */
5285 EXPORT_SYMBOL(_alloc_pages);
5287 EXPORT_SYMBOL(kmem_cache_alloc);
5288 EXPORT_SYMBOL(kmem_cache_free);
5289 EXPORT_SYMBOL(kmem_cache_size);
5290 +EXPORT_SYMBOL(register_cache);
5291 +EXPORT_SYMBOL(unregister_cache);
5292 EXPORT_SYMBOL(kmalloc);
5293 EXPORT_SYMBOL(kfree);
5294 EXPORT_SYMBOL(vfree);
5295 Index: linux-2.4.29/mm/vmscan.c
5296 ===================================================================
5297 --- linux-2.4.29.orig/mm/vmscan.c 2005-04-07 18:52:37.000000000 +0300
5298 +++ linux-2.4.29/mm/vmscan.c 2005-05-03 17:59:40.458112600 +0300
5300 #include <linux/kernel_stat.h>
5301 #include <linux/swap.h>
5302 #include <linux/swapctl.h>
5303 +#include <linux/cache_def.h>
5304 #include <linux/smp_lock.h>
5305 #include <linux/pagemap.h>
5306 #include <linux/init.h>
5311 +static DECLARE_MUTEX(other_caches_sem);
5312 +static LIST_HEAD(cache_definitions);
5314 +void register_cache(struct cache_definition *cache)
5316 + down(&other_caches_sem);
5317 + list_add(&cache->link, &cache_definitions);
5318 + up(&other_caches_sem);
5321 +void unregister_cache(struct cache_definition *cache)
5323 + down(&other_caches_sem);
5324 + list_del(&cache->link);
5325 + up(&other_caches_sem);
5328 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
5330 + struct list_head *p;
5332 + if (down_trylock(&other_caches_sem))
5335 + list_for_each_prev(p, &cache_definitions) {
5336 + struct cache_definition *cache =
5337 + list_entry(p, struct cache_definition, link);
5339 + cache->shrink(priority, gfp_mask);
5341 + up(&other_caches_sem);
5345 * "vm_cache_scan_ratio" is how much of the inactive LRU queue we will scan
5346 * in one go. A value of 6 for vm_cache_scan_ratio implies that we'll
5349 shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask);
5351 + shrink_other_caches(vm_vfs_scan_ratio, gfp_mask);
5353 if (!*failed_swapout)
5354 *failed_swapout = !swap_out(classzone);
5357 shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask);
5359 + shrink_other_caches(vm_vfs_scan_ratio, gfp_mask);
5360 if (!failed_swapout)
5361 failed_swapout = !swap_out(classzone);