1 Documentation/Configure.help | 66 ++
2 arch/alpha/defconfig | 7
3 arch/alpha/kernel/entry.S | 12
5 arch/arm/kernel/calls.S | 24
6 arch/i386/defconfig | 7
7 arch/ia64/defconfig | 7
8 arch/m68k/defconfig | 7
9 arch/mips/defconfig | 7
10 arch/mips64/defconfig | 7
11 arch/ppc/defconfig | 14
12 arch/ppc64/kernel/misc.S | 2
13 arch/s390/defconfig | 7
14 arch/s390/kernel/entry.S | 24
15 arch/s390x/defconfig | 7
16 arch/s390x/kernel/entry.S | 24
17 arch/s390x/kernel/wrapper32.S | 92 +++
18 arch/sparc/defconfig | 7
19 arch/sparc/kernel/systbls.S | 10
20 arch/sparc64/defconfig | 7
21 arch/sparc64/kernel/systbls.S | 20
27 fs/ext2/inode.c | 34 -
30 fs/ext2/symlink.c | 14
31 fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++
32 fs/ext2/xattr_user.c | 103 +++
34 fs/ext3/ext3-exports.c | 13
37 fs/ext3/inode.c | 35 -
39 fs/ext3/super.c | 36 +
40 fs/ext3/symlink.c | 14
41 fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++
42 fs/ext3/xattr_user.c | 111 +++
43 fs/jfs/jfs_xattr.h | 6
45 fs/mbcache.c | 648 ++++++++++++++++++++++
46 include/asm-arm/unistd.h | 2
47 include/asm-ppc64/unistd.h | 2
48 include/asm-s390/unistd.h | 15
49 include/asm-s390x/unistd.h | 15
50 include/asm-sparc/unistd.h | 24
51 include/asm-sparc64/unistd.h | 24
52 include/linux/cache_def.h | 15
53 include/linux/errno.h | 4
54 include/linux/ext2_fs.h | 31 -
55 include/linux/ext2_xattr.h | 157 +++++
56 include/linux/ext3_fs.h | 31 -
57 include/linux/ext3_jbd.h | 8
58 include/linux/ext3_xattr.h | 157 +++++
59 include/linux/fs.h | 2
60 include/linux/mbcache.h | 69 ++
63 62 files changed, 4343 insertions(+), 182 deletions(-)
65 --- linux/Documentation/Configure.help~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:23 2003
66 +++ linux-mmonroe/Documentation/Configure.help Fri May 16 08:43:00 2003
67 @@ -15309,6 +15309,39 @@ CONFIG_EXT2_FS
68 be compiled as a module, and so this could be dangerous. Most
69 everyone wants to say Y here.
71 +Ext2 extended attributes
73 + Extended attributes are name:value pairs associated with inodes by
74 + the kernel or by users (see the attr(5) manual page, or visit
75 + <http://acl.bestbits.at/> for details).
79 +Ext2 extended attribute block sharing
80 +CONFIG_EXT2_FS_XATTR_SHARING
81 + This options enables code for sharing identical extended attribute
82 + blocks among multiple inodes.
86 +Ext2 extended user attributes
87 +CONFIG_EXT2_FS_XATTR_USER
88 + This option enables extended user attributes on ext2. Processes can
89 + associate extended user attributes with inodes to store additional
90 + information such as the character encoding of files, etc. (see the
91 + attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
95 +Ext2 trusted extended attributes
96 +CONFIG_EXT2_FS_XATTR_TRUSTED
97 + This option enables extended attributes on ext2 that are accessible
98 + (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
99 + is only the super user. Trusted extended attributes are meant for
100 + implementing system/security services.
104 Ext3 journalling file system support (EXPERIMENTAL)
106 This is the journalling version of the Second extended file system
107 @@ -15341,6 +15374,39 @@ CONFIG_EXT3_FS
108 of your root partition (the one containing the directory /) cannot
109 be compiled as a module, and so this may be dangerous.
111 +Ext3 extended attributes
112 +CONFIG_EXT3_FS_XATTR
113 + Extended attributes are name:value pairs associated with inodes by
114 + the kernel or by users (see the attr(5) manual page, or visit
115 + <http://acl.bestbits.at/> for details).
119 +Ext3 extended attribute block sharing
120 +CONFIG_EXT3_FS_XATTR_SHARING
121 + This options enables code for sharing identical extended attribute
122 + blocks among multiple inodes.
126 +Ext3 extended user attributes
127 +CONFIG_EXT3_FS_XATTR_USER
128 + This option enables extended user attributes on ext3. Processes can
129 + associate extended user attributes with inodes to store additional
130 + information such as the character encoding of files, etc. (see the
131 + attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
135 +Ext3 trusted extended attributes
136 +CONFIG_EXT3_FS_XATTR_TRUSTED
137 + This option enables extended attributes on ext3 that are accessible
138 + (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
139 + is only the super user. Trusted extended attributes are meant for
140 + implementing system/security services.
144 Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
146 This is a generic journalling layer for block devices. It is
147 --- linux/arch/alpha/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
148 +++ linux-mmonroe/arch/alpha/defconfig Fri May 16 08:43:00 2003
151 # Automatically generated make config: don't edit
153 +# CONFIG_EXT3_FS_XATTR is not set
154 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
155 +# CONFIG_EXT3_FS_XATTR_USER is not set
156 +# CONFIG_EXT2_FS_XATTR is not set
157 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
158 +# CONFIG_EXT2_FS_XATTR_USER is not set
159 +# CONFIG_FS_MBCACHE is not set
161 # CONFIG_UID16 is not set
162 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
163 --- linux/arch/alpha/kernel/entry.S~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:42 2002
164 +++ linux-mmonroe/arch/alpha/kernel/entry.S Fri May 16 08:43:00 2003
165 @@ -1154,6 +1154,18 @@ sys_call_table:
167 .quad sys_ni_syscall /* 380, sys_security */
170 + .quad sys_lsetxattr
171 + .quad sys_fsetxattr
172 + .quad sys_getxattr /* 385 */
173 + .quad sys_lgetxattr
174 + .quad sys_fgetxattr
175 + .quad sys_listxattr
176 + .quad sys_llistxattr
177 + .quad sys_flistxattr /* 390 */
178 + .quad sys_removexattr
179 + .quad sys_lremovexattr
180 + .quad sys_fremovexattr
182 /* Remember to update everything, kids. */
183 .ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
184 --- linux/arch/arm/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
185 +++ linux-mmonroe/arch/arm/defconfig Fri May 16 08:43:00 2003
188 # Automatically generated make config: don't edit
190 +# CONFIG_EXT3_FS_XATTR is not set
191 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
192 +# CONFIG_EXT3_FS_XATTR_USER is not set
193 +# CONFIG_EXT2_FS_XATTR is not set
194 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
195 +# CONFIG_EXT2_FS_XATTR_USER is not set
196 +# CONFIG_FS_MBCACHE is not set
198 # CONFIG_EISA is not set
199 # CONFIG_SBUS is not set
200 --- linux/arch/arm/kernel/calls.S~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:42 2002
201 +++ linux-mmonroe/arch/arm/kernel/calls.S Fri May 16 08:43:00 2003
202 @@ -240,18 +240,18 @@ __syscall_start:
203 .long SYMBOL_NAME(sys_ni_syscall) /* Security */
204 .long SYMBOL_NAME(sys_gettid)
205 /* 225 */ .long SYMBOL_NAME(sys_readahead)
206 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_setxattr */
207 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_lsetxattr */
208 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_fsetxattr */
209 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_getxattr */
210 -/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_lgetxattr */
211 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_fgetxattr */
212 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_listxattr */
213 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_llistxattr */
214 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_flistxattr */
215 -/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_removexattr */
216 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_lremovexattr */
217 - .long SYMBOL_NAME(sys_ni_syscall) /* sys_fremovexattr */
218 + .long SYMBOL_NAME(sys_setxattr)
219 + .long SYMBOL_NAME(sys_lsetxattr)
220 + .long SYMBOL_NAME(sys_fsetxattr)
221 + .long SYMBOL_NAME(sys_getxattr)
222 +/* 230 */ .long SYMBOL_NAME(sys_lgetxattr)
223 + .long SYMBOL_NAME(sys_fgetxattr)
224 + .long SYMBOL_NAME(sys_listxattr)
225 + .long SYMBOL_NAME(sys_llistxattr)
226 + .long SYMBOL_NAME(sys_flistxattr)
227 +/* 235 */ .long SYMBOL_NAME(sys_removexattr)
228 + .long SYMBOL_NAME(sys_lremovexattr)
229 + .long SYMBOL_NAME(sys_fremovexattr)
230 .long SYMBOL_NAME(sys_tkill)
232 * Please check 2.5 _before_ adding calls here,
233 --- linux/arch/i386/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
234 +++ linux-mmonroe/arch/i386/defconfig Fri May 16 08:43:00 2003
237 # Automatically generated make config: don't edit
239 +# CONFIG_EXT3_FS_XATTR is not set
240 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
241 +# CONFIG_EXT3_FS_XATTR_USER is not set
242 +# CONFIG_EXT2_FS_XATTR is not set
243 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
244 +# CONFIG_EXT2_FS_XATTR_USER is not set
245 +# CONFIG_FS_MBCACHE is not set
248 # CONFIG_SBUS is not set
249 --- linux/arch/ia64/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
250 +++ linux-mmonroe/arch/ia64/defconfig Fri May 16 08:43:00 2003
253 # Automatically generated make config: don't edit
255 +# CONFIG_EXT3_FS_XATTR is not set
256 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
257 +# CONFIG_EXT3_FS_XATTR_USER is not set
258 +# CONFIG_EXT2_FS_XATTR is not set
259 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
260 +# CONFIG_EXT2_FS_XATTR_USER is not set
261 +# CONFIG_FS_MBCACHE is not set
264 # Code maturity level options
265 --- linux/arch/m68k/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
266 +++ linux-mmonroe/arch/m68k/defconfig Fri May 16 08:43:00 2003
269 # Automatically generated make config: don't edit
271 +# CONFIG_EXT3_FS_XATTR is not set
272 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
273 +# CONFIG_EXT3_FS_XATTR_USER is not set
274 +# CONFIG_EXT2_FS_XATTR is not set
275 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
276 +# CONFIG_EXT2_FS_XATTR_USER is not set
277 +# CONFIG_FS_MBCACHE is not set
281 --- linux/arch/mips/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
282 +++ linux-mmonroe/arch/mips/defconfig Fri May 16 08:43:01 2003
285 # Automatically generated make config: don't edit
287 +# CONFIG_EXT3_FS_XATTR is not set
288 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
289 +# CONFIG_EXT3_FS_XATTR_USER is not set
290 +# CONFIG_EXT2_FS_XATTR is not set
291 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
292 +# CONFIG_EXT2_FS_XATTR_USER is not set
293 +# CONFIG_FS_MBCACHE is not set
296 # CONFIG_MIPS64 is not set
297 --- linux/arch/mips64/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
298 +++ linux-mmonroe/arch/mips64/defconfig Fri May 16 08:43:01 2003
301 # Automatically generated make config: don't edit
303 +# CONFIG_EXT3_FS_XATTR is not set
304 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
305 +# CONFIG_EXT3_FS_XATTR_USER is not set
306 +# CONFIG_EXT2_FS_XATTR is not set
307 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
308 +# CONFIG_EXT2_FS_XATTR_USER is not set
309 +# CONFIG_FS_MBCACHE is not set
311 # CONFIG_MIPS32 is not set
313 --- linux/arch/ppc/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
314 +++ linux-mmonroe/arch/ppc/defconfig Fri May 16 08:43:01 2003
317 # Automatically generated make config: don't edit
319 +# CONFIG_EXT3_FS_XATTR is not set
320 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
321 +# CONFIG_EXT3_FS_XATTR_USER is not set
322 +# CONFIG_EXT2_FS_XATTR is not set
323 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
324 +# CONFIG_EXT2_FS_XATTR_USER is not set
325 +# CONFIG_FS_MBCACHE is not set
326 +# CONFIG_EXT3_FS_XATTR is not set
327 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
328 +# CONFIG_EXT3_FS_XATTR_USER is not set
329 +# CONFIG_EXT2_FS_XATTR is not set
330 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
331 +# CONFIG_EXT2_FS_XATTR_USER is not set
332 +# CONFIG_FS_MBCACHE is not set
333 # CONFIG_UID16 is not set
334 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
335 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
336 --- linux/arch/ppc64/kernel/misc.S~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:11 2002
337 +++ linux-mmonroe/arch/ppc64/kernel/misc.S Fri May 16 08:43:01 2003
338 @@ -731,6 +731,7 @@ _GLOBAL(sys_call_table32)
339 .llong .sys_gettid /* 207 */
340 #if 0 /* Reserved syscalls */
341 .llong .sys_tkill /* 208 */
344 .llong .sys_lsetxattr /* 210 */
345 .llong .sys_fsetxattr
346 @@ -743,6 +744,7 @@ _GLOBAL(sys_call_table32)
347 .llong .sys_removexattr
348 .llong .sys_lremovexattr
349 .llong .sys_fremovexattr /* 220 */
350 +#if 0 /* Reserved syscalls */
353 .llong .sys_perfmonctl /* Put this here for now ... */
354 --- linux/arch/s390/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
355 +++ linux-mmonroe/arch/s390/defconfig Fri May 16 08:43:01 2003
358 # Automatically generated make config: don't edit
360 +# CONFIG_EXT3_FS_XATTR is not set
361 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
362 +# CONFIG_EXT3_FS_XATTR_USER is not set
363 +# CONFIG_EXT2_FS_XATTR is not set
364 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
365 +# CONFIG_EXT2_FS_XATTR_USER is not set
366 +# CONFIG_FS_MBCACHE is not set
367 # CONFIG_ISA is not set
368 # CONFIG_EISA is not set
369 # CONFIG_MCA is not set
370 --- linux/arch/s390/kernel/entry.S~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:11 2002
371 +++ linux-mmonroe/arch/s390/kernel/entry.S Fri May 16 08:43:01 2003
372 @@ -558,18 +558,18 @@ sys_call_table:
376 - .long sys_ni_syscall /* 224 - reserved for setxattr */
377 - .long sys_ni_syscall /* 225 - reserved for lsetxattr */
378 - .long sys_ni_syscall /* 226 - reserved for fsetxattr */
379 - .long sys_ni_syscall /* 227 - reserved for getxattr */
380 - .long sys_ni_syscall /* 228 - reserved for lgetxattr */
381 - .long sys_ni_syscall /* 229 - reserved for fgetxattr */
382 - .long sys_ni_syscall /* 230 - reserved for listxattr */
383 - .long sys_ni_syscall /* 231 - reserved for llistxattr */
384 - .long sys_ni_syscall /* 232 - reserved for flistxattr */
385 - .long sys_ni_syscall /* 233 - reserved for removexattr */
386 - .long sys_ni_syscall /* 234 - reserved for lremovexattr */
387 - .long sys_ni_syscall /* 235 - reserved for fremovexattr */
389 + .long sys_lsetxattr /* 225 */
390 + .long sys_fsetxattr
392 + .long sys_lgetxattr
393 + .long sys_fgetxattr
394 + .long sys_listxattr /* 230 */
395 + .long sys_llistxattr
396 + .long sys_flistxattr
397 + .long sys_removexattr
398 + .long sys_lremovexattr
399 + .long sys_fremovexattr /* 235 */
403 --- linux/arch/s390x/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
404 +++ linux-mmonroe/arch/s390x/defconfig Fri May 16 08:43:01 2003
407 # Automatically generated make config: don't edit
409 +# CONFIG_EXT3_FS_XATTR is not set
410 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
411 +# CONFIG_EXT3_FS_XATTR_USER is not set
412 +# CONFIG_EXT2_FS_XATTR is not set
413 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
414 +# CONFIG_EXT2_FS_XATTR_USER is not set
415 +# CONFIG_FS_MBCACHE is not set
416 # CONFIG_ISA is not set
417 # CONFIG_EISA is not set
418 # CONFIG_MCA is not set
419 --- linux/arch/s390x/kernel/entry.S~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:11 2002
420 +++ linux-mmonroe/arch/s390x/kernel/entry.S Fri May 16 08:43:01 2003
421 @@ -591,18 +591,18 @@ sys_call_table:
422 .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
423 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
424 .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
425 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
426 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
427 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
428 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
429 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
430 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
431 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
432 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
433 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
434 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
435 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
436 - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
437 + .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
438 + .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
439 + .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
440 + .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
441 + .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
442 + .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
443 + .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
444 + .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
445 + .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
446 + .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
447 + .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
448 + .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
449 .long SYSCALL(sys_gettid,sys_gettid)
450 .long SYSCALL(sys_tkill,sys_tkill)
452 --- linux/arch/s390x/kernel/wrapper32.S~linux-2.4.20-xattr-0.8.54-hp Mon Feb 25 11:37:56 2002
453 +++ linux-mmonroe/arch/s390x/kernel/wrapper32.S Fri May 16 08:43:01 2003
454 @@ -1091,3 +1091,95 @@ sys32_fstat64_wrapper:
455 llgtr %r3,%r3 # struct stat64 *
457 jg sys32_fstat64 # branch to system call
459 + .globl sys32_setxattr_wrapper
460 +sys32_setxattr_wrapper:
461 + llgtr %r2,%r2 # char *
462 + llgtr %r3,%r3 # char *
463 + llgtr %r4,%r4 # void *
464 + llgfr %r5,%r5 # size_t
468 + .globl sys32_lsetxattr_wrapper
469 +sys32_lsetxattr_wrapper:
470 + llgtr %r2,%r2 # char *
471 + llgtr %r3,%r3 # char *
472 + llgtr %r4,%r4 # void *
473 + llgfr %r5,%r5 # size_t
477 + .globl sys32_fsetxattr_wrapper
478 +sys32_fsetxattr_wrapper:
480 + llgtr %r3,%r3 # char *
481 + llgtr %r4,%r4 # void *
482 + llgfr %r5,%r5 # size_t
486 + .globl sys32_getxattr_wrapper
487 +sys32_getxattr_wrapper:
488 + llgtr %r2,%r2 # char *
489 + llgtr %r3,%r3 # char *
490 + llgtr %r4,%r4 # void *
491 + llgfr %r5,%r5 # size_t
494 + .globl sys32_lgetxattr_wrapper
495 +sys32_lgetxattr_wrapper:
496 + llgtr %r2,%r2 # char *
497 + llgtr %r3,%r3 # char *
498 + llgtr %r4,%r4 # void *
499 + llgfr %r5,%r5 # size_t
502 + .globl sys32_fgetxattr_wrapper
503 +sys32_fgetxattr_wrapper:
505 + llgtr %r3,%r3 # char *
506 + llgtr %r4,%r4 # void *
507 + llgfr %r5,%r5 # size_t
510 + .globl sys32_listxattr_wrapper
511 +sys32_listxattr_wrapper:
512 + llgtr %r2,%r2 # char *
513 + llgtr %r3,%r3 # char *
514 + llgfr %r4,%r4 # size_t
517 + .globl sys32_llistxattr_wrapper
518 +sys32_llistxattr_wrapper:
519 + llgtr %r2,%r2 # char *
520 + llgtr %r3,%r3 # char *
521 + llgfr %r4,%r4 # size_t
524 + .globl sys32_flistxattr_wrapper
525 +sys32_flistxattr_wrapper:
527 + llgtr %r3,%r3 # char *
528 + llgfr %r4,%r4 # size_t
531 + .globl sys32_removexattr_wrapper
532 +sys32_removexattr_wrapper:
533 + llgtr %r2,%r2 # char *
534 + llgtr %r3,%r3 # char *
537 + .globl sys32_lremovexattr_wrapper
538 +sys32_lremovexattr_wrapper:
539 + llgtr %r2,%r2 # char *
540 + llgtr %r3,%r3 # char *
541 + jg sys_lremovexattr
543 + .globl sys32_fremovexattr_wrapper
544 +sys32_fremovexattr_wrapper:
546 + llgtr %r3,%r3 # char *
547 + jg sys_fremovexattr
550 --- linux/arch/sparc/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
551 +++ linux-mmonroe/arch/sparc/defconfig Fri May 16 08:43:01 2003
554 # Automatically generated make config: don't edit
556 +# CONFIG_EXT3_FS_XATTR is not set
557 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
558 +# CONFIG_EXT3_FS_XATTR_USER is not set
559 +# CONFIG_EXT2_FS_XATTR is not set
560 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
561 +# CONFIG_EXT2_FS_XATTR_USER is not set
562 +# CONFIG_FS_MBCACHE is not set
566 --- linux/arch/sparc/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:43 2002
567 +++ linux-mmonroe/arch/sparc/kernel/systbls.S Fri May 16 08:43:01 2003
568 @@ -51,11 +51,11 @@ sys_call_table:
569 /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
570 /*155*/ .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
571 /*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
572 -/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
573 -/*170*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
574 -/*175*/ .long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
575 -/*180*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
576 -/*185*/ .long sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sys_newuname
577 +/*165*/ .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
578 +/*170*/ .long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
579 +/*175*/ .long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
580 +/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_query_module
581 +/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sys_newuname
582 /*190*/ .long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
583 /*195*/ .long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
584 /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
585 --- linux/arch/sparc64/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
586 +++ linux-mmonroe/arch/sparc64/defconfig Fri May 16 08:43:01 2003
589 # Automatically generated make config: don't edit
591 +# CONFIG_EXT3_FS_XATTR is not set
592 +# CONFIG_EXT3_FS_XATTR_SHARING is not set
593 +# CONFIG_EXT3_FS_XATTR_USER is not set
594 +# CONFIG_EXT2_FS_XATTR is not set
595 +# CONFIG_EXT2_FS_XATTR_SHARING is not set
596 +# CONFIG_EXT2_FS_XATTR_USER is not set
597 +# CONFIG_FS_MBCACHE is not set
600 # Code maturity level options
601 --- linux/arch/sparc64/kernel/systbls.S~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
602 +++ linux-mmonroe/arch/sparc64/kernel/systbls.S Fri May 16 08:43:01 2003
603 @@ -52,11 +52,11 @@ sys_call_table32:
604 /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
605 .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
606 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
607 - .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
608 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
609 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
610 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
611 - .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
612 + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_setxattr
613 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
614 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
615 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys32_sigpending, sys32_query_module
616 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
617 /*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
618 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
619 /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
620 @@ -111,11 +111,11 @@ sys_call_table:
621 /*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
622 .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
623 /*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
624 - .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
625 -/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
626 - .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
627 -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
628 - .word sys_setpgid, sys_nis_syscall, sys_tkill, sys_nis_syscall, sparc64_newuname
629 + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_setxattr
630 +/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
631 + .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
632 +/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_query_module
633 + .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_nis_syscall, sparc64_newuname
634 /*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
635 .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
636 /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
637 --- linux/fs/Config.in~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003
638 +++ linux-mmonroe/fs/Config.in Fri May 16 08:43:01 2003
639 @@ -35,6 +35,11 @@ dep_mbool ' Debug Befs' CONFIG_BEFS_DEB
640 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
642 tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
643 +dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
644 +dep_bool ' Ext3 extended attribute block sharing' \
645 + CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
646 +dep_bool ' Ext3 extended user attributes' \
647 + CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
648 # CONFIG_JBD could be its own option (even modular), but until there are
649 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
650 # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
651 @@ -98,6 +103,11 @@ dep_mbool ' QNX4FS write support (DANGE
652 tristate 'ROM file system support' CONFIG_ROMFS_FS
654 tristate 'Second extended fs support' CONFIG_EXT2_FS
655 +dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
656 +dep_bool ' Ext2 extended attribute block sharing' \
657 + CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
658 +dep_bool ' Ext2 extended user attributes' \
659 + CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
661 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
663 @@ -176,6 +186,10 @@ else
664 define_tristate CONFIG_ZISOFS_FS n
667 +# Meta block cache for Extended Attributes (ext2/ext3)
668 +#tristate 'Meta block cache' CONFIG_FS_MBCACHE
669 +define_tristate CONFIG_FS_MBCACHE y
671 mainmenu_option next_comment
672 comment 'Partition Types'
673 source fs/partitions/Config.in
674 --- linux/fs/Makefile~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003
675 +++ linux-mmonroe/fs/Makefile Fri May 16 08:43:01 2003
676 @@ -80,6 +80,9 @@ obj-y += binfmt_script.o
678 obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
680 +export-objs += mbcache.o
681 +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
683 # persistent filesystems
684 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
686 --- linux/fs/ext2/Makefile~linux-2.4.20-xattr-0.8.54-hp Thu Oct 11 08:05:18 2001
687 +++ linux-mmonroe/fs/ext2/Makefile Fri May 16 08:43:01 2003
688 @@ -13,4 +13,8 @@ obj-y := balloc.o bitmap.o dir.o file
689 ioctl.o namei.o super.o symlink.o
692 +export-objs += xattr.o
693 +obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
694 +obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
696 include $(TOPDIR)/Rules.make
697 --- linux/fs/ext2/file.c~linux-2.4.20-xattr-0.8.54-hp Thu Oct 11 08:05:18 2001
698 +++ linux-mmonroe/fs/ext2/file.c Fri May 16 08:43:01 2003
701 #include <linux/fs.h>
702 #include <linux/ext2_fs.h>
703 +#include <linux/ext2_xattr.h>
704 #include <linux/sched.h>
707 @@ -51,4 +52,8 @@ struct file_operations ext2_file_operati
709 struct inode_operations ext2_file_inode_operations = {
710 truncate: ext2_truncate,
711 + setxattr: ext2_setxattr,
712 + getxattr: ext2_getxattr,
713 + listxattr: ext2_listxattr,
714 + removexattr: ext2_removexattr,
716 --- linux/fs/ext2/ialloc.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002
717 +++ linux-mmonroe/fs/ext2/ialloc.c Fri May 16 08:43:01 2003
719 #include <linux/config.h>
720 #include <linux/fs.h>
721 #include <linux/ext2_fs.h>
722 +#include <linux/ext2_xattr.h>
723 #include <linux/locks.h>
724 #include <linux/quotaops.h>
726 @@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino
728 if (!is_bad_inode(inode)) {
729 /* Quota is already initialized in iput() */
730 + ext2_xattr_delete_inode(inode);
731 DQUOT_FREE_INODE(inode);
734 --- linux/fs/ext2/inode.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002
735 +++ linux-mmonroe/fs/ext2/inode.c Fri May 16 08:43:01 2003
736 @@ -39,6 +39,18 @@ MODULE_LICENSE("GPL");
737 static int ext2_update_inode(struct inode * inode, int do_sync);
740 + * Test whether an inode is a fast symlink.
742 +static inline int ext2_inode_is_fast_symlink(struct inode *inode)
744 + int ea_blocks = inode->u.ext2_i.i_file_acl ?
745 + (inode->i_sb->s_blocksize >> 9) : 0;
747 + return (S_ISLNK(inode->i_mode) &&
748 + inode->i_blocks - ea_blocks == 0);
752 * Called at each iput()
754 void ext2_put_inode (struct inode * inode)
755 @@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i
759 - if (is_bad_inode(inode) ||
760 - inode->i_ino == EXT2_ACL_IDX_INO ||
761 - inode->i_ino == EXT2_ACL_DATA_INO)
762 + if (is_bad_inode(inode))
764 inode->u.ext2_i.i_dtime = CURRENT_TIME;
765 mark_inode_dirty(inode);
766 @@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode
767 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
768 S_ISLNK(inode->i_mode)))
770 + if (ext2_inode_is_fast_symlink(inode))
772 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
775 @@ -888,8 +900,7 @@ void ext2_read_inode (struct inode * ino
776 unsigned long offset;
777 struct ext2_group_desc * gdp;
779 - if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
780 - inode->i_ino != EXT2_ACL_DATA_INO &&
781 + if ((inode->i_ino != EXT2_ROOT_INO &&
782 inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
783 inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
784 ext2_error (inode->i_sb, "ext2_read_inode",
785 @@ -974,10 +985,7 @@ void ext2_read_inode (struct inode * ino
786 for (block = 0; block < EXT2_N_BLOCKS; block++)
787 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
789 - if (inode->i_ino == EXT2_ACL_IDX_INO ||
790 - inode->i_ino == EXT2_ACL_DATA_INO)
791 - /* Nothing to do */ ;
792 - else if (S_ISREG(inode->i_mode)) {
793 + if (S_ISREG(inode->i_mode)) {
794 inode->i_op = &ext2_file_inode_operations;
795 inode->i_fop = &ext2_file_operations;
796 inode->i_mapping->a_ops = &ext2_aops;
797 @@ -986,15 +994,17 @@ void ext2_read_inode (struct inode * ino
798 inode->i_fop = &ext2_dir_operations;
799 inode->i_mapping->a_ops = &ext2_aops;
800 } else if (S_ISLNK(inode->i_mode)) {
801 - if (!inode->i_blocks)
802 + if (ext2_inode_is_fast_symlink(inode))
803 inode->i_op = &ext2_fast_symlink_inode_operations;
805 - inode->i_op = &page_symlink_inode_operations;
806 + inode->i_op = &ext2_symlink_inode_operations;
807 inode->i_mapping->a_ops = &ext2_aops;
811 + inode->i_op = &ext2_special_inode_operations;
812 init_special_inode(inode, inode->i_mode,
813 le32_to_cpu(raw_inode->i_block[0]));
816 inode->i_attr_flags = 0;
817 if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
818 --- linux/fs/ext2/namei.c~linux-2.4.20-xattr-0.8.54-hp Wed Oct 3 22:57:36 2001
819 +++ linux-mmonroe/fs/ext2/namei.c Fri May 16 08:43:01 2003
822 #include <linux/fs.h>
823 #include <linux/ext2_fs.h>
824 +#include <linux/ext2_xattr.h>
825 #include <linux/pagemap.h>
828 @@ -136,7 +137,7 @@ static int ext2_symlink (struct inode *
830 if (l > sizeof (inode->u.ext2_i.i_data)) {
832 - inode->i_op = &page_symlink_inode_operations;
833 + inode->i_op = &ext2_symlink_inode_operations;
834 inode->i_mapping->a_ops = &ext2_aops;
835 err = block_symlink(inode, symname, l);
837 @@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o
841 + setxattr: ext2_setxattr,
842 + getxattr: ext2_getxattr,
843 + listxattr: ext2_listxattr,
844 + removexattr: ext2_removexattr,
847 +struct inode_operations ext2_special_inode_operations = {
848 + setxattr: ext2_setxattr,
849 + getxattr: ext2_getxattr,
850 + listxattr: ext2_listxattr,
851 + removexattr: ext2_removexattr,
853 --- linux/fs/ext2/super.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002
854 +++ linux-mmonroe/fs/ext2/super.c Fri May 16 08:43:01 2003
856 #include <linux/string.h>
857 #include <linux/fs.h>
858 #include <linux/ext2_fs.h>
859 +#include <linux/ext2_xattr.h>
860 #include <linux/slab.h>
861 #include <linux/init.h>
862 #include <linux/locks.h>
863 @@ -125,6 +126,7 @@ void ext2_put_super (struct super_block
867 + ext2_xattr_put_super(sb);
868 if (!(sb->s_flags & MS_RDONLY)) {
869 struct ext2_super_block *es = EXT2_SB(sb)->s_es;
871 @@ -175,6 +177,13 @@ static int parse_options (char * options
872 this_char = strtok (NULL, ",")) {
873 if ((value = strchr (this_char, '=')) != NULL)
875 +#ifdef CONFIG_EXT2_FS_XATTR_USER
876 + if (!strcmp (this_char, "user_xattr"))
877 + set_opt (*mount_options, XATTR_USER);
878 + else if (!strcmp (this_char, "nouser_xattr"))
879 + clear_opt (*mount_options, XATTR_USER);
882 if (!strcmp (this_char, "bsddf"))
883 clear_opt (*mount_options, MINIX_DF);
884 else if (!strcmp (this_char, "nouid32")) {
885 @@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st
886 blocksize = BLOCK_SIZE;
888 sb->u.ext2_sb.s_mount_opt = 0;
889 +#ifdef CONFIG_EXT2_FS_XATTR_USER
890 + /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
892 if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
893 &sb->u.ext2_sb.s_mount_opt)) {
895 @@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type,
897 static int __init init_ext2_fs(void)
899 - return register_filesystem(&ext2_fs_type);
900 + int error = init_ext2_xattr();
903 + error = init_ext2_xattr_user();
906 + error = register_filesystem(&ext2_fs_type);
910 + exit_ext2_xattr_user();
916 static void __exit exit_ext2_fs(void)
918 unregister_filesystem(&ext2_fs_type);
919 + exit_ext2_xattr_user();
924 --- linux/fs/ext2/symlink.c~linux-2.4.20-xattr-0.8.54-hp Wed Sep 27 13:41:33 2000
925 +++ linux-mmonroe/fs/ext2/symlink.c Fri May 16 08:43:01 2003
928 #include <linux/fs.h>
929 #include <linux/ext2_fs.h>
930 +#include <linux/ext2_xattr.h>
932 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
934 @@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr
935 return vfs_follow_link(nd, s);
938 +struct inode_operations ext2_symlink_inode_operations = {
939 + readlink: page_readlink,
940 + follow_link: page_follow_link,
941 + setxattr: ext2_setxattr,
942 + getxattr: ext2_getxattr,
943 + listxattr: ext2_listxattr,
944 + removexattr: ext2_removexattr,
947 struct inode_operations ext2_fast_symlink_inode_operations = {
948 readlink: ext2_readlink,
949 follow_link: ext2_follow_link,
950 + setxattr: ext2_setxattr,
951 + getxattr: ext2_getxattr,
952 + listxattr: ext2_listxattr,
953 + removexattr: ext2_removexattr,
955 --- /dev/null Mon May 20 21:11:23 2002
956 +++ linux-mmonroe/fs/ext2/xattr.c Fri May 16 08:43:01 2003
959 + * linux/fs/ext2/xattr.c
961 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
963 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
964 + * Extended attributes for symlinks and special files added per
965 + * suggestion of Luka Renko <luka.renko@hermes.si>.
969 + * Extended attributes are stored on disk blocks allocated outside of
970 + * any inode. The i_file_acl field is then made to point to this allocated
971 + * block. If all extended attributes of an inode are identical, these
972 + * inodes may share the same extended attribute block. Such situations
973 + * are automatically detected by keeping a cache of recent attribute block
974 + * numbers and hashes over the block's contents in memory.
977 + * Extended attribute block layout:
979 + * +------------------+
982 + * | entry 2 | | growing downwards
984 + * | four null bytes |
987 + * | value 3 | | growing upwards
989 + * +------------------+
991 + * The block header is followed by multiple entry descriptors. These entry
992 + * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
993 + * byte boundaries. The entry descriptors are sorted by attribute name,
994 + * so that two extended attribute blocks can be compared efficiently.
996 + * Attribute values are aligned to the end of the block, stored in
997 + * no specific order. They are also padded to EXT2_XATTR_PAD byte
998 + * boundaries. No additional gaps are left between them.
1000 + * Locking strategy
1001 + * ----------------
1002 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
1003 + * the xattr inode operations are called, so we are guaranteed that only one
1004 + * processes accesses extended attributes of an inode at any time.
1006 + * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
1007 + * only a single process is modifying an extended attribute block, even
1008 + * if the block is shared among inodes.
1010 + * Note for porting to 2.5
1011 + * -----------------------
1012 + * The BKL will no longer be held in the xattr inode operations.
1015 +#include <linux/module.h>
1016 +#include <linux/locks.h>
1017 +#include <linux/slab.h>
1018 +#include <linux/fs.h>
1019 +#include <linux/ext2_fs.h>
1020 +#include <linux/ext2_xattr.h>
1021 +#include <linux/mbcache.h>
1022 +#include <linux/quotaops.h>
1023 +#include <asm/semaphore.h>
1024 +#include <linux/compatmac.h>
1026 +/* These symbols may be needed by a module. */
1027 +EXPORT_SYMBOL(ext2_xattr_register);
1028 +EXPORT_SYMBOL(ext2_xattr_unregister);
1029 +EXPORT_SYMBOL(ext2_xattr_get);
1030 +EXPORT_SYMBOL(ext2_xattr_list);
1031 +EXPORT_SYMBOL(ext2_xattr_set);
1033 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1034 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
1037 +#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
1038 +#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
1039 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
1040 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
1042 +#ifdef EXT2_XATTR_DEBUG
1043 +# define ea_idebug(inode, f...) do { \
1044 + printk(KERN_DEBUG "inode %s:%ld: ", \
1045 + kdevname(inode->i_dev), inode->i_ino); \
1049 +# define ea_bdebug(bh, f...) do { \
1050 + printk(KERN_DEBUG "block %s:%ld: ", \
1051 + kdevname(bh->b_dev), bh->b_blocknr); \
1056 +# define ea_idebug(f...)
1057 +# define ea_bdebug(f...)
1060 +static int ext2_xattr_set2(struct inode *, struct buffer_head *,
1061 + struct ext2_xattr_header *);
1063 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1065 +static int ext2_xattr_cache_insert(struct buffer_head *);
1066 +static struct buffer_head *ext2_xattr_cache_find(struct inode *,
1067 + struct ext2_xattr_header *);
1068 +static void ext2_xattr_cache_remove(struct buffer_head *);
1069 +static void ext2_xattr_rehash(struct ext2_xattr_header *,
1070 + struct ext2_xattr_entry *);
1072 +static struct mb_cache *ext2_xattr_cache;
1075 +# define ext2_xattr_cache_insert(bh) 0
1076 +# define ext2_xattr_cache_find(inode, header) NULL
1077 +# define ext2_xattr_cache_remove(bh) while(0) {}
1078 +# define ext2_xattr_rehash(header, entry) while(0) {}
1082 + * If a file system does not share extended attributes among inodes,
1083 + * we should not need the ext2_xattr_sem semaphore. However, the
1084 + * filesystem may still contain shared blocks, so we always take
1088 +DECLARE_MUTEX(ext2_xattr_sem);
1091 +ext2_xattr_new_block(struct inode *inode, int * errp, int force)
1093 + struct super_block *sb = inode->i_sb;
1094 + int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
1095 + EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
1097 + /* How can we enforce the allocation? */
1098 + int block = ext2_new_block(inode, goal, 0, 0, errp);
1101 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1107 +ext2_xattr_quota_alloc(struct inode *inode, int force)
1109 + /* How can we enforce the allocation? */
1111 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
1113 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
1115 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
1123 +ext2_xattr_quota_free(struct inode *inode)
1125 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
1126 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1130 +ext2_xattr_free_block(struct inode * inode, unsigned long block)
1132 + ext2_free_blocks(inode, block, 1);
1133 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
1137 +# define ext2_xattr_quota_free(inode) \
1138 + DQUOT_FREE_BLOCK(inode, 1)
1139 +# define ext2_xattr_free_block(inode, block) \
1140 + ext2_free_blocks(inode, block, 1)
1143 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
1145 +static inline struct buffer_head *
1146 +sb_bread(struct super_block *sb, int block)
1148 + return bread(sb->s_dev, block, sb->s_blocksize);
1151 +static inline struct buffer_head *
1152 +sb_getblk(struct super_block *sb, int block)
1154 + return getblk(sb->s_dev, block, sb->s_blocksize);
1159 +struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
1160 +rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
1163 +ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
1165 + int error = -EINVAL;
1167 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1168 + write_lock(&ext2_handler_lock);
1169 + if (!ext2_xattr_handlers[name_index-1]) {
1170 + ext2_xattr_handlers[name_index-1] = handler;
1173 + write_unlock(&ext2_handler_lock);
1179 +ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
1181 + if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
1182 + write_lock(&ext2_handler_lock);
1183 + ext2_xattr_handlers[name_index-1] = NULL;
1184 + write_unlock(&ext2_handler_lock);
1188 +static inline const char *
1189 +strcmp_prefix(const char *a, const char *a_prefix)
1191 + while (*a_prefix && *a == *a_prefix) {
1195 + return *a_prefix ? NULL : a;
1199 + * Decode the extended attribute name, and translate it into
1200 + * the name_index and name suffix.
1202 +static struct ext2_xattr_handler *
1203 +ext2_xattr_resolve_name(const char **name)
1205 + struct ext2_xattr_handler *handler = NULL;
1210 + read_lock(&ext2_handler_lock);
1211 + for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
1212 + if (ext2_xattr_handlers[i]) {
1213 + const char *n = strcmp_prefix(*name,
1214 + ext2_xattr_handlers[i]->prefix);
1216 + handler = ext2_xattr_handlers[i];
1222 + read_unlock(&ext2_handler_lock);
1226 +static inline struct ext2_xattr_handler *
1227 +ext2_xattr_handler(int name_index)
1229 + struct ext2_xattr_handler *handler = NULL;
1230 + if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
1231 + read_lock(&ext2_handler_lock);
1232 + handler = ext2_xattr_handlers[name_index-1];
1233 + read_unlock(&ext2_handler_lock);
1239 + * Inode operation getxattr()
1241 + * dentry->d_inode->i_sem down
1242 + * BKL held [before 2.5.x]
1245 +ext2_getxattr(struct dentry *dentry, const char *name,
1246 + void *buffer, size_t size)
1248 + struct ext2_xattr_handler *handler;
1249 + struct inode *inode = dentry->d_inode;
1251 + handler = ext2_xattr_resolve_name(&name);
1254 + return handler->get(inode, name, buffer, size);
1258 + * Inode operation listxattr()
1260 + * dentry->d_inode->i_sem down
1261 + * BKL held [before 2.5.x]
1264 +ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
1266 + return ext2_xattr_list(dentry->d_inode, buffer, size);
1270 + * Inode operation setxattr()
1272 + * dentry->d_inode->i_sem down
1273 + * BKL held [before 2.5.x]
1276 +ext2_setxattr(struct dentry *dentry, const char *name,
1277 + const void *value, size_t size, int flags)
1279 + struct ext2_xattr_handler *handler;
1280 + struct inode *inode = dentry->d_inode;
1283 + value = ""; /* empty EA, do not remove */
1284 + handler = ext2_xattr_resolve_name(&name);
1287 + return handler->set(inode, name, value, size, flags);
1291 + * Inode operation removexattr()
1293 + * dentry->d_inode->i_sem down
1294 + * BKL held [before 2.5.x]
1297 +ext2_removexattr(struct dentry *dentry, const char *name)
1299 + struct ext2_xattr_handler *handler;
1300 + struct inode *inode = dentry->d_inode;
1302 + handler = ext2_xattr_resolve_name(&name);
1305 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
1309 + * ext2_xattr_get()
1311 + * Copy an extended attribute into the buffer
1312 + * provided, or compute the buffer size required.
1313 + * Buffer is NULL to compute the size of the buffer required.
1315 + * Returns a negative error number on failure, or the number of bytes
1316 + * used / required on success.
1319 +ext2_xattr_get(struct inode *inode, int name_index, const char *name,
1320 + void *buffer, size_t buffer_size)
1322 + struct buffer_head *bh = NULL;
1323 + struct ext2_xattr_entry *entry;
1324 + unsigned int block, size;
1326 + int name_len, error;
1328 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
1329 + name_index, name, buffer, (long)buffer_size);
1333 + if (!EXT2_I(inode)->i_file_acl)
1335 + block = EXT2_I(inode)->i_file_acl;
1336 + ea_idebug(inode, "reading block %d", block);
1337 + bh = sb_bread(inode->i_sb, block);
1340 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1341 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1342 + end = bh->b_data + bh->b_size;
1343 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1344 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1345 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
1346 + "inode %ld: bad block %d", inode->i_ino, block);
1350 + /* find named attribute */
1351 + name_len = strlen(name);
1354 + if (name_len > 255)
1356 + entry = FIRST_ENTRY(bh);
1357 + while (!IS_LAST_ENTRY(entry)) {
1358 + struct ext2_xattr_entry *next =
1359 + EXT2_XATTR_NEXT(entry);
1360 + if ((char *)next >= end)
1362 + if (name_index == entry->e_name_index &&
1363 + name_len == entry->e_name_len &&
1364 + memcmp(name, entry->e_name, name_len) == 0)
1368 + /* Check the remaining name entries */
1369 + while (!IS_LAST_ENTRY(entry)) {
1370 + struct ext2_xattr_entry *next =
1371 + EXT2_XATTR_NEXT(entry);
1372 + if ((char *)next >= end)
1376 + if (ext2_xattr_cache_insert(bh))
1377 + ea_idebug(inode, "cache insert failed");
1381 + /* check the buffer size */
1382 + if (entry->e_value_block != 0)
1384 + size = le32_to_cpu(entry->e_value_size);
1385 + if (size > inode->i_sb->s_blocksize ||
1386 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
1389 + if (ext2_xattr_cache_insert(bh))
1390 + ea_idebug(inode, "cache insert failed");
1393 + if (size > buffer_size)
1395 + /* return value of attribute */
1396 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
1408 + * ext2_xattr_list()
1410 + * Copy a list of attribute names into the buffer
1411 + * provided, or compute the buffer size required.
1412 + * Buffer is NULL to compute the size of the buffer required.
1414 + * Returns a negative error number on failure, or the number of bytes
1415 + * used / required on success.
1418 +ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
1420 + struct buffer_head *bh = NULL;
1421 + struct ext2_xattr_entry *entry;
1422 + unsigned int block, size = 0;
1426 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
1427 + buffer, (long)buffer_size);
1429 + if (!EXT2_I(inode)->i_file_acl)
1431 + block = EXT2_I(inode)->i_file_acl;
1432 + ea_idebug(inode, "reading block %d", block);
1433 + bh = sb_bread(inode->i_sb, block);
1436 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1437 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
1438 + end = bh->b_data + bh->b_size;
1439 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1440 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1441 +bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
1442 + "inode %ld: bad block %d", inode->i_ino, block);
1446 + /* compute the size required for the list of attribute names */
1447 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1448 + entry = EXT2_XATTR_NEXT(entry)) {
1449 + struct ext2_xattr_handler *handler;
1450 + struct ext2_xattr_entry *next =
1451 + EXT2_XATTR_NEXT(entry);
1452 + if ((char *)next >= end)
1455 + handler = ext2_xattr_handler(entry->e_name_index);
1457 + size += handler->list(NULL, inode, entry->e_name,
1458 + entry->e_name_len);
1461 + if (ext2_xattr_cache_insert(bh))
1462 + ea_idebug(inode, "cache insert failed");
1468 + if (size > buffer_size)
1472 + /* list the attribute names */
1474 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
1475 + entry = EXT2_XATTR_NEXT(entry)) {
1476 + struct ext2_xattr_handler *handler;
1478 + handler = ext2_xattr_handler(entry->e_name_index);
1480 + buf += handler->list(buf, inode, entry->e_name,
1481 + entry->e_name_len);
1492 + * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
1493 + * not set, set it.
1495 +static void ext2_xattr_update_super_block(struct super_block *sb)
1497 + if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
1501 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
1502 + EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
1504 + EXT2_SB(sb)->s_es->s_feature_compat |=
1505 + cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
1507 + mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
1512 + * ext2_xattr_set()
1514 + * Create, replace or remove an extended attribute for this inode. Buffer
1515 + * is NULL to remove an existing extended attribute, and non-NULL to
1516 + * either replace an existing extended attribute, or create a new extended
1517 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
1518 + * specify that an extended attribute must exist and must not exist
1519 + * previous to the call, respectively.
1521 + * Returns 0, or a negative error number on failure.
1524 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
1525 + const void *value, size_t value_len, int flags)
1527 + struct super_block *sb = inode->i_sb;
1528 + struct buffer_head *bh = NULL;
1529 + struct ext2_xattr_header *header = NULL;
1530 + struct ext2_xattr_entry *here, *last;
1531 + unsigned int name_len;
1532 + int block = EXT2_I(inode)->i_file_acl;
1533 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
1537 + * header -- Points either into bh, or to a temporarily
1538 + * allocated buffer.
1539 + * here -- The named entry found, or the place for inserting, within
1540 + * the block pointed to by header.
1541 + * last -- Points right after the last named entry within the block
1542 + * pointed to by header.
1543 + * min_offs -- The offset of the first value (values are aligned
1544 + * towards the end of the block).
1545 + * end -- Points right after the block pointed to by header.
1548 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
1549 + name_index, name, value, (long)value_len);
1551 + if (IS_RDONLY(inode))
1553 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1555 + if (value == NULL)
1559 + name_len = strlen(name);
1560 + if (name_len > 255 || value_len > sb->s_blocksize)
1562 + down(&ext2_xattr_sem);
1565 + /* The inode already has an extended attribute block. */
1567 + bh = sb_bread(sb, block);
1571 + ea_bdebug(bh, "b_count=%d, refcount=%d",
1572 + atomic_read(&(bh->b_count)),
1573 + le32_to_cpu(HDR(bh)->h_refcount));
1575 + end = bh->b_data + bh->b_size;
1576 + if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1577 + header->h_blocks != cpu_to_le32(1)) {
1578 +bad_block: ext2_error(sb, "ext2_xattr_set",
1579 + "inode %ld: bad block %d", inode->i_ino, block);
1583 + /* Find the named attribute. */
1584 + here = FIRST_ENTRY(bh);
1585 + while (!IS_LAST_ENTRY(here)) {
1586 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
1587 + if ((char *)next >= end)
1589 + if (!here->e_value_block && here->e_value_size) {
1590 + int offs = le16_to_cpu(here->e_value_offs);
1591 + if (offs < min_offs)
1594 + not_found = name_index - here->e_name_index;
1596 + not_found = name_len - here->e_name_len;
1598 + not_found = memcmp(name, here->e_name,name_len);
1599 + if (not_found <= 0)
1604 + /* We still need to compute min_offs and last. */
1605 + while (!IS_LAST_ENTRY(last)) {
1606 + struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
1607 + if ((char *)next >= end)
1609 + if (!last->e_value_block && last->e_value_size) {
1610 + int offs = le16_to_cpu(last->e_value_offs);
1611 + if (offs < min_offs)
1617 + /* Check whether we have enough space left. */
1618 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
1620 + /* We will use a new extended attribute block. */
1621 + free = sb->s_blocksize -
1622 + sizeof(struct ext2_xattr_header) - sizeof(__u32);
1623 + here = last = NULL; /* avoid gcc uninitialized warning. */
1627 + /* Request to remove a nonexistent attribute? */
1629 + if (flags & XATTR_REPLACE)
1632 + if (value == NULL)
1635 + free -= EXT2_XATTR_LEN(name_len);
1637 + /* Request to create an existing attribute? */
1639 + if (flags & XATTR_CREATE)
1641 + if (!here->e_value_block && here->e_value_size) {
1642 + unsigned int size = le32_to_cpu(here->e_value_size);
1644 + if (le16_to_cpu(here->e_value_offs) + size >
1645 + sb->s_blocksize || size > sb->s_blocksize)
1647 + free += EXT2_XATTR_SIZE(size);
1650 + free -= EXT2_XATTR_SIZE(value_len);
1655 + /* Here we know that we can set the new attribute. */
1658 + if (header->h_refcount == cpu_to_le32(1)) {
1659 + ea_bdebug(bh, "modifying in-place");
1660 + ext2_xattr_cache_remove(bh);
1664 + ea_bdebug(bh, "cloning");
1665 + header = kmalloc(bh->b_size, GFP_KERNEL);
1667 + if (header == NULL)
1669 + memcpy(header, HDR(bh), bh->b_size);
1670 + header->h_refcount = cpu_to_le32(1);
1671 + offset = (char *)header - bh->b_data;
1672 + here = ENTRY((char *)here + offset);
1673 + last = ENTRY((char *)last + offset);
1676 + /* Allocate a buffer where we construct the new block. */
1677 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
1679 + if (header == NULL)
1681 + memset(header, 0, sb->s_blocksize);
1682 + end = (char *)header + sb->s_blocksize;
1683 + header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
1684 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
1685 + last = here = ENTRY(header+1);
1689 + /* Insert the new name. */
1690 + int size = EXT2_XATTR_LEN(name_len);
1691 + int rest = (char *)last - (char *)here;
1692 + memmove((char *)here + size, here, rest);
1693 + memset(here, 0, size);
1694 + here->e_name_index = name_index;
1695 + here->e_name_len = name_len;
1696 + memcpy(here->e_name, name, name_len);
1698 + /* Remove the old value. */
1699 + if (!here->e_value_block && here->e_value_size) {
1700 + char *first_val = (char *)header + min_offs;
1701 + int offs = le16_to_cpu(here->e_value_offs);
1702 + char *val = (char *)header + offs;
1703 + size_t size = EXT2_XATTR_SIZE(
1704 + le32_to_cpu(here->e_value_size));
1705 + memmove(first_val + size, first_val, val - first_val);
1706 + memset(first_val, 0, size);
1707 + here->e_value_offs = 0;
1710 + /* Adjust all value offsets. */
1711 + last = ENTRY(header+1);
1712 + while (!IS_LAST_ENTRY(last)) {
1713 + int o = le16_to_cpu(last->e_value_offs);
1714 + if (!last->e_value_block && o < offs)
1715 + last->e_value_offs =
1716 + cpu_to_le16(o + size);
1717 + last = EXT2_XATTR_NEXT(last);
1720 + if (value == NULL) {
1721 + /* Remove this attribute. */
1722 + if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
1723 + /* This block is now empty. */
1724 + error = ext2_xattr_set2(inode, bh, NULL);
1727 + /* Remove the old name. */
1728 + int size = EXT2_XATTR_LEN(name_len);
1729 + last = ENTRY((char *)last - size);
1730 + memmove(here, (char*)here + size,
1731 + (char*)last - (char*)here);
1732 + memset(last, 0, size);
1737 + if (value != NULL) {
1738 + /* Insert the new value. */
1739 + here->e_value_size = cpu_to_le32(value_len);
1741 + size_t size = EXT2_XATTR_SIZE(value_len);
1742 + char *val = (char *)header + min_offs - size;
1743 + here->e_value_offs =
1744 + cpu_to_le16((char *)val - (char *)header);
1745 + memset(val + size - EXT2_XATTR_PAD, 0,
1746 + EXT2_XATTR_PAD); /* Clear the pad bytes. */
1747 + memcpy(val, value, value_len);
1750 + ext2_xattr_rehash(header, here);
1752 + error = ext2_xattr_set2(inode, bh, header);
1756 + if (!(bh && header == HDR(bh)))
1758 + up(&ext2_xattr_sem);
1764 + * Second half of ext2_xattr_set(): Update the file system.
1767 +ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
1768 + struct ext2_xattr_header *header)
1770 + struct super_block *sb = inode->i_sb;
1771 + struct buffer_head *new_bh = NULL;
1775 + new_bh = ext2_xattr_cache_find(inode, header);
1778 + * We found an identical block in the cache.
1779 + * The old block will be released after updating
1782 + ea_bdebug(old_bh, "reusing block %ld",
1783 + new_bh->b_blocknr);
1786 + if (ext2_xattr_quota_alloc(inode, 1))
1789 + HDR(new_bh)->h_refcount = cpu_to_le32(
1790 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
1791 + ea_bdebug(new_bh, "refcount now=%d",
1792 + le32_to_cpu(HDR(new_bh)->h_refcount));
1793 + } else if (old_bh && header == HDR(old_bh)) {
1794 + /* Keep this block. */
1796 + ext2_xattr_cache_insert(new_bh);
1798 + /* We need to allocate a new block */
1799 + int force = EXT2_I(inode)->i_file_acl != 0;
1800 + int block = ext2_xattr_new_block(inode, &error, force);
1803 + ea_idebug(inode, "creating block %d", block);
1805 + new_bh = sb_getblk(sb, block);
1807 + ext2_xattr_free_block(inode, block);
1811 + lock_buffer(new_bh);
1812 + memcpy(new_bh->b_data, header, new_bh->b_size);
1813 + mark_buffer_uptodate(new_bh, 1);
1814 + unlock_buffer(new_bh);
1815 + ext2_xattr_cache_insert(new_bh);
1817 + ext2_xattr_update_super_block(sb);
1819 + mark_buffer_dirty(new_bh);
1820 + if (IS_SYNC(inode)) {
1821 + ll_rw_block(WRITE, 1, &new_bh);
1822 + wait_on_buffer(new_bh);
1824 + if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
1829 + /* Update the inode. */
1830 + EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
1831 + inode->i_ctime = CURRENT_TIME;
1832 + if (IS_SYNC(inode)) {
1833 + error = ext2_sync_inode (inode);
1837 + mark_inode_dirty(inode);
1840 + if (old_bh && old_bh != new_bh) {
1842 + * If there was an old block, and we are not still using it,
1843 + * we now release the old block.
1845 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
1847 + if (refcount == 1) {
1848 + /* Free the old block. */
1849 + ea_bdebug(old_bh, "freeing");
1850 + ext2_xattr_free_block(inode, old_bh->b_blocknr);
1851 + mark_buffer_clean(old_bh);
1853 + /* Decrement the refcount only. */
1855 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
1856 + ext2_xattr_quota_free(inode);
1857 + mark_buffer_dirty(old_bh);
1858 + ea_bdebug(old_bh, "refcount now=%d", refcount);
1863 + if (old_bh != new_bh)
1870 + * ext2_xattr_delete_inode()
1872 + * Free extended attribute resources associated with this inode. This
1873 + * is called immediately before an inode is freed.
1876 +ext2_xattr_delete_inode(struct inode *inode)
1878 + struct buffer_head *bh;
1879 + unsigned int block = EXT2_I(inode)->i_file_acl;
1883 + down(&ext2_xattr_sem);
1885 + bh = sb_bread(inode->i_sb, block);
1887 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1888 + "inode %ld: block %d read error", inode->i_ino, block);
1891 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
1892 + if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
1893 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
1894 + ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
1895 + "inode %ld: bad block %d", inode->i_ino, block);
1898 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
1899 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
1900 + ext2_xattr_cache_remove(bh);
1901 + ext2_xattr_free_block(inode, block);
1905 + HDR(bh)->h_refcount = cpu_to_le32(
1906 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
1907 + mark_buffer_dirty(bh);
1908 + if (IS_SYNC(inode)) {
1909 + ll_rw_block(WRITE, 1, &bh);
1910 + wait_on_buffer(bh);
1912 + ext2_xattr_quota_free(inode);
1914 + EXT2_I(inode)->i_file_acl = 0;
1918 + up(&ext2_xattr_sem);
1922 + * ext2_xattr_put_super()
1924 + * This is called when a file system is unmounted.
1927 +ext2_xattr_put_super(struct super_block *sb)
1929 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1930 + mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
1934 +#ifdef CONFIG_EXT2_FS_XATTR_SHARING
1937 + * ext2_xattr_cache_insert()
1939 + * Create a new entry in the extended attribute cache, and insert
1940 + * it unless such an entry is already in the cache.
1942 + * Returns 0, or a negative error number on failure.
1945 +ext2_xattr_cache_insert(struct buffer_head *bh)
1947 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
1948 + struct mb_cache_entry *ce;
1951 + ce = mb_cache_entry_alloc(ext2_xattr_cache);
1954 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
1956 + mb_cache_entry_free(ce);
1957 + if (error == -EBUSY) {
1958 + ea_bdebug(bh, "already in cache (%d cache entries)",
1959 + atomic_read(&ext2_xattr_cache->c_entry_count));
1963 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
1964 + atomic_read(&ext2_xattr_cache->c_entry_count));
1965 + mb_cache_entry_release(ce);
1971 + * ext2_xattr_cmp()
1973 + * Compare two extended attribute blocks for equality.
1975 + * Returns 0 if the blocks are equal, 1 if they differ, and
1976 + * a negative error number on errors.
1979 +ext2_xattr_cmp(struct ext2_xattr_header *header1,
1980 + struct ext2_xattr_header *header2)
1982 + struct ext2_xattr_entry *entry1, *entry2;
1984 + entry1 = ENTRY(header1+1);
1985 + entry2 = ENTRY(header2+1);
1986 + while (!IS_LAST_ENTRY(entry1)) {
1987 + if (IS_LAST_ENTRY(entry2))
1989 + if (entry1->e_hash != entry2->e_hash ||
1990 + entry1->e_name_len != entry2->e_name_len ||
1991 + entry1->e_value_size != entry2->e_value_size ||
1992 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
1994 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
1996 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
1997 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
1998 + le32_to_cpu(entry1->e_value_size)))
2001 + entry1 = EXT2_XATTR_NEXT(entry1);
2002 + entry2 = EXT2_XATTR_NEXT(entry2);
2004 + if (!IS_LAST_ENTRY(entry2))
2010 + * ext2_xattr_cache_find()
2012 + * Find an identical extended attribute block.
2014 + * Returns a pointer to the block found, or NULL if such a block was
2015 + * not found or an error occurred.
2017 +static struct buffer_head *
2018 +ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
2020 + __u32 hash = le32_to_cpu(header->h_hash);
2021 + struct mb_cache_entry *ce;
2023 + if (!header->h_hash)
2024 + return NULL; /* never share */
2025 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
2026 + ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
2028 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
2031 + ext2_error(inode->i_sb, "ext2_xattr_cache_find",
2032 + "inode %ld: block %ld read error",
2033 + inode->i_ino, ce->e_block);
2034 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
2035 + EXT2_XATTR_REFCOUNT_MAX) {
2036 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
2037 + le32_to_cpu(HDR(bh)->h_refcount),
2038 + EXT2_XATTR_REFCOUNT_MAX);
2039 + } else if (!ext2_xattr_cmp(header, HDR(bh))) {
2040 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
2041 + mb_cache_entry_release(ce);
2045 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
2051 + * ext2_xattr_cache_remove()
2053 + * Remove the cache entry of a block from the cache. Called when a
2054 + * block becomes invalid.
2057 +ext2_xattr_cache_remove(struct buffer_head *bh)
2059 + struct mb_cache_entry *ce;
2061 + ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
2063 + ea_bdebug(bh, "removing (%d cache entries remaining)",
2064 + atomic_read(&ext2_xattr_cache->c_entry_count)-1);
2065 + mb_cache_entry_free(ce);
2067 + ea_bdebug(bh, "no cache entry");
2070 +#define NAME_HASH_SHIFT 5
2071 +#define VALUE_HASH_SHIFT 16
2074 + * ext2_xattr_hash_entry()
2076 + * Compute the hash of an extended attribute.
2078 +static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
2079 + struct ext2_xattr_entry *entry)
2082 + char *name = entry->e_name;
2085 + for (n=0; n < entry->e_name_len; n++) {
2086 + hash = (hash << NAME_HASH_SHIFT) ^
2087 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
2091 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
2092 + __u32 *value = (__u32 *)((char *)header +
2093 + le16_to_cpu(entry->e_value_offs));
2094 + for (n = (le32_to_cpu(entry->e_value_size) +
2095 + EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
2096 + hash = (hash << VALUE_HASH_SHIFT) ^
2097 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
2098 + le32_to_cpu(*value++);
2101 + entry->e_hash = cpu_to_le32(hash);
2104 +#undef NAME_HASH_SHIFT
2105 +#undef VALUE_HASH_SHIFT
2107 +#define BLOCK_HASH_SHIFT 16
2110 + * ext2_xattr_rehash()
2112 + * Re-compute the extended attribute hash value after an entry has changed.
2114 +static void ext2_xattr_rehash(struct ext2_xattr_header *header,
2115 + struct ext2_xattr_entry *entry)
2117 + struct ext2_xattr_entry *here;
2120 + ext2_xattr_hash_entry(header, entry);
2121 + here = ENTRY(header+1);
2122 + while (!IS_LAST_ENTRY(here)) {
2123 + if (!here->e_hash) {
2124 + /* Block is not shared if an entry's hash value == 0 */
2128 + hash = (hash << BLOCK_HASH_SHIFT) ^
2129 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
2130 + le32_to_cpu(here->e_hash);
2131 + here = EXT2_XATTR_NEXT(here);
2133 + header->h_hash = cpu_to_le32(hash);
2136 +#undef BLOCK_HASH_SHIFT
2139 +init_ext2_xattr(void)
2141 + ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
2142 + sizeof(struct mb_cache_entry) +
2143 + sizeof(struct mb_cache_entry_index), 1, 61);
2144 + if (!ext2_xattr_cache)
2151 +exit_ext2_xattr(void)
2153 + mb_cache_destroy(ext2_xattr_cache);
2156 +#else /* CONFIG_EXT2_FS_XATTR_SHARING */
2159 +init_ext2_xattr(void)
2165 +exit_ext2_xattr(void)
2169 +#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
2170 --- /dev/null Mon May 20 21:11:23 2002
2171 +++ linux-mmonroe/fs/ext2/xattr_user.c Fri May 16 08:43:01 2003
2174 + * linux/fs/ext2/xattr_user.c
2175 + * Handler for extended user attributes.
2177 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2180 +#include <linux/module.h>
2181 +#include <linux/string.h>
2182 +#include <linux/fs.h>
2183 +#include <linux/ext2_fs.h>
2184 +#include <linux/ext2_xattr.h>
2186 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2187 +# include <linux/ext2_acl.h>
2190 +#define XATTR_USER_PREFIX "user."
2193 +ext2_xattr_user_list(char *list, struct inode *inode,
2194 + const char *name, int name_len)
2196 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
2198 + if (!test_opt(inode->i_sb, XATTR_USER))
2202 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
2203 + memcpy(list+prefix_len, name, name_len);
2204 + list[prefix_len + name_len] = '\0';
2206 + return prefix_len + name_len + 1;
2210 +ext2_xattr_user_get(struct inode *inode, const char *name,
2211 + void *buffer, size_t size)
2215 + if (strcmp(name, "") == 0)
2217 + if (!test_opt(inode->i_sb, XATTR_USER))
2219 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2220 + error = ext2_permission_locked(inode, MAY_READ);
2222 + error = permission(inode, MAY_READ);
2227 + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
2232 +ext2_xattr_user_set(struct inode *inode, const char *name,
2233 + const void *value, size_t size, int flags)
2237 + if (strcmp(name, "") == 0)
2239 + if (!test_opt(inode->i_sb, XATTR_USER))
2241 + if ( !S_ISREG(inode->i_mode) &&
2242 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2244 +#ifdef CONFIG_EXT2_FS_POSIX_ACL
2245 + error = ext2_permission_locked(inode, MAY_WRITE);
2247 + error = permission(inode, MAY_WRITE);
2252 + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
2253 + value, size, flags);
2256 +struct ext2_xattr_handler ext2_xattr_user_handler = {
2257 + prefix: XATTR_USER_PREFIX,
2258 + list: ext2_xattr_user_list,
2259 + get: ext2_xattr_user_get,
2260 + set: ext2_xattr_user_set,
2264 +init_ext2_xattr_user(void)
2266 + return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
2267 + &ext2_xattr_user_handler);
2271 +exit_ext2_xattr_user(void)
2273 + ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
2274 + &ext2_xattr_user_handler);
2276 --- linux/fs/ext3/Makefile~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003
2277 +++ linux-mmonroe/fs/ext3/Makefile Fri May 16 08:43:01 2003
2280 -# Makefile for the linux ext2-filesystem routines.
2281 +# Makefile for the linux ext3-filesystem routines.
2283 # Note! Dependencies are done automagically by 'make dep', which also
2284 # removes any old dependencies. DON'T put your own dependencies here
2289 -export-objs := super.o inode.o
2290 +export-objs := ext3-exports.o
2292 obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
2293 - ioctl.o namei.o super.o symlink.o hash.o
2294 + ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
2295 obj-m := $(O_TARGET)
2297 +obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
2298 +obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
2300 include $(TOPDIR)/Rules.make
2301 --- linux/fs/ext3/file.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003
2302 +++ linux-mmonroe/fs/ext3/file.c Fri May 16 08:43:01 2003
2304 #include <linux/locks.h>
2305 #include <linux/jbd.h>
2306 #include <linux/ext3_fs.h>
2307 +#include <linux/ext3_xattr.h>
2308 #include <linux/ext3_jbd.h>
2309 #include <linux/smp_lock.h>
2311 @@ -126,5 +127,9 @@ struct file_operations ext3_file_operati
2312 struct inode_operations ext3_file_inode_operations = {
2313 truncate: ext3_truncate, /* BKL held */
2314 setattr: ext3_setattr, /* BKL held */
2315 + setxattr: ext3_setxattr, /* BKL held */
2316 + getxattr: ext3_getxattr, /* BKL held */
2317 + listxattr: ext3_listxattr, /* BKL held */
2318 + removexattr: ext3_removexattr, /* BKL held */
2321 --- linux/fs/ext3/ialloc.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002
2322 +++ linux-mmonroe/fs/ext3/ialloc.c Fri May 16 08:43:01 2003
2324 #include <linux/jbd.h>
2325 #include <linux/ext3_fs.h>
2326 #include <linux/ext3_jbd.h>
2327 +#include <linux/ext3_xattr.h>
2328 #include <linux/stat.h>
2329 #include <linux/string.h>
2330 #include <linux/locks.h>
2331 @@ -216,6 +217,7 @@ void ext3_free_inode (handle_t *handle,
2332 * as writing the quota to disk may need the lock as well.
2335 + ext3_xattr_delete_inode(handle, inode);
2336 DQUOT_FREE_INODE(inode);
2339 --- linux/fs/ext3/inode.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002
2340 +++ linux-mmonroe/fs/ext3/inode.c Fri May 16 08:43:01 2003
2343 #undef SEARCH_FROM_ZERO
2346 + * Test whether an inode is a fast symlink.
2348 +static inline int ext3_inode_is_fast_symlink(struct inode *inode)
2350 + int ea_blocks = inode->u.ext3_i.i_file_acl ?
2351 + (inode->i_sb->s_blocksize >> 9) : 0;
2353 + return (S_ISLNK(inode->i_mode) &&
2354 + inode->i_blocks - ea_blocks == 0);
2357 /* The ext3 forget function must perform a revoke if we are freeing data
2358 * which has been journaled. Metadata (eg. indirect blocks) must be
2359 * revoked in all cases.
2361 * still needs to be revoked.
2364 -static int ext3_forget(handle_t *handle, int is_metadata,
2365 +int ext3_forget(handle_t *handle, int is_metadata,
2366 struct inode *inode, struct buffer_head *bh,
2369 @@ -164,9 +176,7 @@ void ext3_delete_inode (struct inode * i
2373 - if (is_bad_inode(inode) ||
2374 - inode->i_ino == EXT3_ACL_IDX_INO ||
2375 - inode->i_ino == EXT3_ACL_DATA_INO)
2376 + if (is_bad_inode(inode))
2380 @@ -1855,6 +1865,8 @@ void ext3_truncate(struct inode * inode)
2381 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
2382 S_ISLNK(inode->i_mode)))
2384 + if (ext3_inode_is_fast_symlink(inode))
2386 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2389 @@ -2002,8 +2014,6 @@ int ext3_get_inode_loc (struct inode *in
2390 struct ext3_group_desc * gdp;
2392 if ((inode->i_ino != EXT3_ROOT_INO &&
2393 - inode->i_ino != EXT3_ACL_IDX_INO &&
2394 - inode->i_ino != EXT3_ACL_DATA_INO &&
2395 inode->i_ino != EXT3_JOURNAL_INO &&
2396 inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2397 inode->i_ino > le32_to_cpu(
2398 @@ -2130,10 +2140,7 @@ void ext3_read_inode(struct inode * inod
2402 - if (inode->i_ino == EXT3_ACL_IDX_INO ||
2403 - inode->i_ino == EXT3_ACL_DATA_INO)
2404 - /* Nothing to do */ ;
2405 - else if (S_ISREG(inode->i_mode)) {
2406 + if (S_ISREG(inode->i_mode)) {
2407 inode->i_op = &ext3_file_inode_operations;
2408 inode->i_fop = &ext3_file_operations;
2409 inode->i_mapping->a_ops = &ext3_aops;
2410 @@ -2141,15 +2148,17 @@ void ext3_read_inode(struct inode * inod
2411 inode->i_op = &ext3_dir_inode_operations;
2412 inode->i_fop = &ext3_dir_operations;
2413 } else if (S_ISLNK(inode->i_mode)) {
2414 - if (!inode->i_blocks)
2415 + if (ext3_inode_is_fast_symlink(inode))
2416 inode->i_op = &ext3_fast_symlink_inode_operations;
2418 - inode->i_op = &page_symlink_inode_operations;
2419 + inode->i_op = &ext3_symlink_inode_operations;
2420 inode->i_mapping->a_ops = &ext3_aops;
2424 + inode->i_op = &ext3_special_inode_operations;
2425 init_special_inode(inode, inode->i_mode,
2426 le32_to_cpu(iloc.raw_inode->i_block[0]));
2428 /* inode->i_attr_flags = 0; unused */
2429 if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
2430 /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
2431 --- linux/fs/ext3/namei.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:47 2003
2432 +++ linux-mmonroe/fs/ext3/namei.c Fri May 16 08:43:01 2003
2434 #include <linux/sched.h>
2435 #include <linux/ext3_fs.h>
2436 #include <linux/ext3_jbd.h>
2437 +#include <linux/ext3_xattr.h>
2438 #include <linux/fcntl.h>
2439 #include <linux/stat.h>
2440 #include <linux/string.h>
2441 @@ -1611,7 +1612,7 @@ static int ext3_mkdir(struct inode * dir
2445 - inode = ext3_new_inode (handle, dir, S_IFDIR);
2446 + inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
2447 err = PTR_ERR(inode);
2450 @@ -1619,7 +1620,6 @@ static int ext3_mkdir(struct inode * dir
2451 inode->i_op = &ext3_dir_inode_operations;
2452 inode->i_fop = &ext3_dir_operations;
2453 inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
2454 - inode->i_blocks = 0;
2455 dir_block = ext3_bread (handle, inode, 0, 1, &err);
2457 inode->i_nlink--; /* is this nlink == 0? */
2458 @@ -1646,9 +1646,6 @@ static int ext3_mkdir(struct inode * dir
2459 BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
2460 ext3_journal_dirty_metadata(handle, dir_block);
2462 - inode->i_mode = S_IFDIR | mode;
2463 - if (dir->i_mode & S_ISGID)
2464 - inode->i_mode |= S_ISGID;
2465 ext3_mark_inode_dirty(handle, inode);
2466 err = ext3_add_entry (handle, dentry, inode);
2468 @@ -2017,7 +2014,7 @@ static int ext3_symlink (struct inode *
2471 if (l > sizeof (EXT3_I(inode)->i_data)) {
2472 - inode->i_op = &page_symlink_inode_operations;
2473 + inode->i_op = &ext3_symlink_inode_operations;
2474 inode->i_mapping->a_ops = &ext3_aops;
2476 * block_symlink() calls back into ext3_prepare/commit_write.
2477 @@ -2244,4 +2241,16 @@ struct inode_operations ext3_dir_inode_o
2478 rmdir: ext3_rmdir, /* BKL held */
2479 mknod: ext3_mknod, /* BKL held */
2480 rename: ext3_rename, /* BKL held */
2481 + setxattr: ext3_setxattr, /* BKL held */
2482 + getxattr: ext3_getxattr, /* BKL held */
2483 + listxattr: ext3_listxattr, /* BKL held */
2484 + removexattr: ext3_removexattr, /* BKL held */
2487 +struct inode_operations ext3_special_inode_operations = {
2488 + setxattr: ext3_setxattr, /* BKL held */
2489 + getxattr: ext3_getxattr, /* BKL held */
2490 + listxattr: ext3_listxattr, /* BKL held */
2491 + removexattr: ext3_removexattr, /* BKL held */
2494 --- linux/fs/ext3/super.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003
2495 +++ linux-mmonroe/fs/ext3/super.c Fri May 16 08:43:01 2003
2497 #include <linux/jbd.h>
2498 #include <linux/ext3_fs.h>
2499 #include <linux/ext3_jbd.h>
2500 +#include <linux/ext3_xattr.h>
2501 #include <linux/slab.h>
2502 #include <linux/init.h>
2503 #include <linux/locks.h>
2504 @@ -406,6 +407,7 @@ void ext3_put_super (struct super_block
2505 kdev_t j_dev = sbi->s_journal->j_dev;
2508 + ext3_xattr_put_super(sb);
2509 journal_destroy(sbi->s_journal);
2510 if (!(sb->s_flags & MS_RDONLY)) {
2511 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
2512 @@ -502,6 +504,7 @@ static int parse_options (char * options
2515 unsigned long *mount_options = &sbi->s_mount_opt;
2517 uid_t *resuid = &sbi->s_resuid;
2518 gid_t *resgid = &sbi->s_resgid;
2520 @@ -514,6 +517,13 @@ static int parse_options (char * options
2521 this_char = strtok (NULL, ",")) {
2522 if ((value = strchr (this_char, '=')) != NULL)
2524 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2525 + if (!strcmp (this_char, "user_xattr"))
2526 + set_opt (*mount_options, XATTR_USER);
2527 + else if (!strcmp (this_char, "nouser_xattr"))
2528 + clear_opt (*mount_options, XATTR_USER);
2531 if (!strcmp (this_char, "bsddf"))
2532 clear_opt (*mount_options, MINIX_DF);
2533 else if (!strcmp (this_char, "nouid32")) {
2534 @@ -931,6 +941,12 @@ struct super_block * ext3_read_super (st
2535 sbi->s_mount_opt = 0;
2536 sbi->s_resuid = EXT3_DEF_RESUID;
2537 sbi->s_resgid = EXT3_DEF_RESGID;
2539 + /* Default extended attribute flags */
2540 +#ifdef CONFIG_EXT3_FS_XATTR_USER
2541 + /* set_opt(sbi->s_mount_opt, XATTR_USER); */
2544 if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
2547 @@ -1768,17 +1784,29 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type,
2549 static int __init init_ext3_fs(void)
2551 - return register_filesystem(&ext3_fs_type);
2552 + int error = init_ext3_xattr();
2555 + error = init_ext3_xattr_user();
2558 + error = register_filesystem(&ext3_fs_type);
2562 + exit_ext3_xattr_user();
2564 + exit_ext3_xattr();
2568 static void __exit exit_ext3_fs(void)
2570 unregister_filesystem(&ext3_fs_type);
2571 + exit_ext3_xattr_user();
2572 + exit_ext3_xattr();
2575 -EXPORT_SYMBOL(ext3_force_commit);
2576 -EXPORT_SYMBOL(ext3_bread);
2578 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
2579 MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
2580 MODULE_LICENSE("GPL");
2581 --- linux/fs/ext3/symlink.c~linux-2.4.20-xattr-0.8.54-hp Fri Nov 9 14:25:04 2001
2582 +++ linux-mmonroe/fs/ext3/symlink.c Fri May 16 08:43:01 2003
2584 #include <linux/fs.h>
2585 #include <linux/jbd.h>
2586 #include <linux/ext3_fs.h>
2587 +#include <linux/ext3_xattr.h>
2589 static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
2591 @@ -33,7 +34,20 @@ static int ext3_follow_link(struct dentr
2592 return vfs_follow_link(nd, s);
2595 +struct inode_operations ext3_symlink_inode_operations = {
2596 + readlink: page_readlink, /* BKL not held. Don't need */
2597 + follow_link: page_follow_link, /* BKL not held. Don't need */
2598 + setxattr: ext3_setxattr, /* BKL held */
2599 + getxattr: ext3_getxattr, /* BKL held */
2600 + listxattr: ext3_listxattr, /* BKL held */
2601 + removexattr: ext3_removexattr, /* BKL held */
2604 struct inode_operations ext3_fast_symlink_inode_operations = {
2605 readlink: ext3_readlink, /* BKL not held. Don't need */
2606 follow_link: ext3_follow_link, /* BKL not held. Don't need */
2607 + setxattr: ext3_setxattr, /* BKL held */
2608 + getxattr: ext3_getxattr, /* BKL held */
2609 + listxattr: ext3_listxattr, /* BKL held */
2610 + removexattr: ext3_removexattr, /* BKL held */
2612 --- /dev/null Mon May 20 21:11:23 2002
2613 +++ linux-mmonroe/fs/ext3/xattr.c Fri May 16 08:43:01 2003
2616 + * linux/fs/ext3/xattr.c
2618 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
2620 + * Fix by Harrison Xing <harrison@mountainviewdata.com>.
2621 + * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
2622 + * Extended attributes for symlinks and special files added per
2623 + * suggestion of Luka Renko <luka.renko@hermes.si>.
2627 + * Extended attributes are stored on disk blocks allocated outside of
2628 + * any inode. The i_file_acl field is then made to point to this allocated
2629 + * block. If all extended attributes of an inode are identical, these
2630 + * inodes may share the same extended attribute block. Such situations
2631 + * are automatically detected by keeping a cache of recent attribute block
2632 + * numbers and hashes over the block's contents in memory.
2635 + * Extended attribute block layout:
2637 + * +------------------+
2640 + * | entry 2 | | growing downwards
2642 + * | four null bytes |
2645 + * | value 3 | | growing upwards
2647 + * +------------------+
2649 + * The block header is followed by multiple entry descriptors. These entry
2650 + * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
2651 + * byte boundaries. The entry descriptors are sorted by attribute name,
2652 + * so that two extended attribute blocks can be compared efficiently.
2654 + * Attribute values are aligned to the end of the block, stored in
2655 + * no specific order. They are also padded to EXT3_XATTR_PAD byte
2656 + * boundaries. No additional gaps are left between them.
2658 + * Locking strategy
2659 + * ----------------
2660 + * The VFS already holds the BKL and the inode->i_sem semaphore when any of
2661 + * the xattr inode operations are called, so we are guaranteed that only one
2662 + * processes accesses extended attributes of an inode at any time.
2664 + * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
2665 + * only a single process is modifying an extended attribute block, even
2666 + * if the block is shared among inodes.
2668 + * Note for porting to 2.5
2669 + * -----------------------
2670 + * The BKL will no longer be held in the xattr inode operations.
2673 +#include <linux/module.h>
2674 +#include <linux/fs.h>
2675 +#include <linux/locks.h>
2676 +#include <linux/slab.h>
2677 +#include <linux/ext3_jbd.h>
2678 +#include <linux/ext3_fs.h>
2679 +#include <linux/ext3_xattr.h>
2680 +#include <linux/mbcache.h>
2681 +#include <linux/quotaops.h>
2682 +#include <asm/semaphore.h>
2683 +#include <linux/compatmac.h>
2685 +#define EXT3_EA_USER "user."
2687 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2688 +# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
2691 +#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
2692 +#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
2693 +#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
2694 +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
2696 +#ifdef EXT3_XATTR_DEBUG
2697 +# define ea_idebug(inode, f...) do { \
2698 + printk(KERN_DEBUG "inode %s:%ld: ", \
2699 + kdevname(inode->i_dev), inode->i_ino); \
2703 +# define ea_bdebug(bh, f...) do { \
2704 + printk(KERN_DEBUG "block %s:%ld: ", \
2705 + kdevname(bh->b_dev), bh->b_blocknr); \
2710 +# define ea_idebug(f...)
2711 +# define ea_bdebug(f...)
2714 +static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
2715 + struct ext3_xattr_header *);
2717 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
2719 +static int ext3_xattr_cache_insert(struct buffer_head *);
2720 +static struct buffer_head *ext3_xattr_cache_find(struct inode *,
2721 + struct ext3_xattr_header *);
2722 +static void ext3_xattr_cache_remove(struct buffer_head *);
2723 +static void ext3_xattr_rehash(struct ext3_xattr_header *,
2724 + struct ext3_xattr_entry *);
2726 +static struct mb_cache *ext3_xattr_cache;
2729 +# define ext3_xattr_cache_insert(bh) 0
2730 +# define ext3_xattr_cache_find(inode, header) NULL
2731 +# define ext3_xattr_cache_remove(bh) while(0) {}
2732 +# define ext3_xattr_rehash(header, entry) while(0) {}
2736 + * If a file system does not share extended attributes among inodes,
2737 + * we should not need the ext3_xattr_sem semaphore. However, the
2738 + * filesystem may still contain shared blocks, so we always take
2742 +DECLARE_MUTEX(ext3_xattr_sem);
2745 +ext3_xattr_new_block(handle_t *handle, struct inode *inode,
2746 + int * errp, int force)
2748 + struct super_block *sb = inode->i_sb;
2749 + int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
2750 + EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
2752 + /* How can we enforce the allocation? */
2753 + int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
2756 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2762 +ext3_xattr_quota_alloc(struct inode *inode, int force)
2764 + /* How can we enforce the allocation? */
2766 + int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
2768 + inode->i_blocks += inode->i_sb->s_blocksize >> 9;
2770 + int error = DQUOT_ALLOC_BLOCK(inode, 1);
2778 +ext3_xattr_quota_free(struct inode *inode)
2780 + DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
2781 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2785 +ext3_xattr_free_block(handle_t *handle, struct inode * inode,
2786 + unsigned long block)
2788 + ext3_free_blocks(handle, inode, block, 1);
2789 + inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
2793 +# define ext3_xattr_quota_free(inode) \
2794 + DQUOT_FREE_BLOCK(inode, 1)
2795 +# define ext3_xattr_free_block(handle, inode, block) \
2796 + ext3_free_blocks(handle, inode, block, 1)
2799 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
2801 +static inline struct buffer_head *
2802 +sb_bread(struct super_block *sb, int block)
2804 + return bread(sb->s_dev, block, sb->s_blocksize);
2807 +static inline struct buffer_head *
2808 +sb_getblk(struct super_block *sb, int block)
2810 + return getblk(sb->s_dev, block, sb->s_blocksize);
2815 +struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
2816 +rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
2819 +ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
2821 + int error = -EINVAL;
2823 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2824 + write_lock(&ext3_handler_lock);
2825 + if (!ext3_xattr_handlers[name_index-1]) {
2826 + ext3_xattr_handlers[name_index-1] = handler;
2829 + write_unlock(&ext3_handler_lock);
2835 +ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
2837 + if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
2838 + write_lock(&ext3_handler_lock);
2839 + ext3_xattr_handlers[name_index-1] = NULL;
2840 + write_unlock(&ext3_handler_lock);
2844 +static inline const char *
2845 +strcmp_prefix(const char *a, const char *a_prefix)
2847 + while (*a_prefix && *a == *a_prefix) {
2851 + return *a_prefix ? NULL : a;
2855 + * Decode the extended attribute name, and translate it into
2856 + * the name_index and name suffix.
2858 +static inline struct ext3_xattr_handler *
2859 +ext3_xattr_resolve_name(const char **name)
2861 + struct ext3_xattr_handler *handler = NULL;
2866 + read_lock(&ext3_handler_lock);
2867 + for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
2868 + if (ext3_xattr_handlers[i]) {
2869 + const char *n = strcmp_prefix(*name,
2870 + ext3_xattr_handlers[i]->prefix);
2872 + handler = ext3_xattr_handlers[i];
2878 + read_unlock(&ext3_handler_lock);
2882 +static inline struct ext3_xattr_handler *
2883 +ext3_xattr_handler(int name_index)
2885 + struct ext3_xattr_handler *handler = NULL;
2886 + if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
2887 + read_lock(&ext3_handler_lock);
2888 + handler = ext3_xattr_handlers[name_index-1];
2889 + read_unlock(&ext3_handler_lock);
2895 + * Inode operation getxattr()
2897 + * dentry->d_inode->i_sem down
2898 + * BKL held [before 2.5.x]
2901 +ext3_getxattr(struct dentry *dentry, const char *name,
2902 + void *buffer, size_t size)
2904 + struct ext3_xattr_handler *handler;
2905 + struct inode *inode = dentry->d_inode;
2907 + handler = ext3_xattr_resolve_name(&name);
2910 + return handler->get(inode, name, buffer, size);
2914 + * Inode operation listxattr()
2916 + * dentry->d_inode->i_sem down
2917 + * BKL held [before 2.5.x]
2920 +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
2922 + return ext3_xattr_list(dentry->d_inode, buffer, size);
2926 + * Inode operation setxattr()
2928 + * dentry->d_inode->i_sem down
2929 + * BKL held [before 2.5.x]
2932 +ext3_setxattr(struct dentry *dentry, const char *name,
2933 + const void *value, size_t size, int flags)
2935 + struct ext3_xattr_handler *handler;
2936 + struct inode *inode = dentry->d_inode;
2939 + value = ""; /* empty EA, do not remove */
2940 + handler = ext3_xattr_resolve_name(&name);
2943 + return handler->set(inode, name, value, size, flags);
2947 + * Inode operation removexattr()
2949 + * dentry->d_inode->i_sem down
2950 + * BKL held [before 2.5.x]
2953 +ext3_removexattr(struct dentry *dentry, const char *name)
2955 + struct ext3_xattr_handler *handler;
2956 + struct inode *inode = dentry->d_inode;
2958 + handler = ext3_xattr_resolve_name(&name);
2961 + return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
2965 + * ext3_xattr_get()
2967 + * Copy an extended attribute into the buffer
2968 + * provided, or compute the buffer size required.
2969 + * Buffer is NULL to compute the size of the buffer required.
2971 + * Returns a negative error number on failure, or the number of bytes
2972 + * used / required on success.
2975 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
2976 + void *buffer, size_t buffer_size)
2978 + struct buffer_head *bh = NULL;
2979 + struct ext3_xattr_entry *entry;
2980 + unsigned int block, size;
2982 + int name_len, error;
2984 + ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
2985 + name_index, name, buffer, (long)buffer_size);
2989 + if (!EXT3_I(inode)->i_file_acl)
2991 + block = EXT3_I(inode)->i_file_acl;
2992 + ea_idebug(inode, "reading block %d", block);
2993 + bh = sb_bread(inode->i_sb, block);
2996 + ea_bdebug(bh, "b_count=%d, refcount=%d",
2997 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
2998 + end = bh->b_data + bh->b_size;
2999 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3000 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3001 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
3002 + "inode %ld: bad block %d", inode->i_ino, block);
3006 + /* find named attribute */
3007 + name_len = strlen(name);
3010 + if (name_len > 255)
3012 + entry = FIRST_ENTRY(bh);
3013 + while (!IS_LAST_ENTRY(entry)) {
3014 + struct ext3_xattr_entry *next =
3015 + EXT3_XATTR_NEXT(entry);
3016 + if ((char *)next >= end)
3018 + if (name_index == entry->e_name_index &&
3019 + name_len == entry->e_name_len &&
3020 + memcmp(name, entry->e_name, name_len) == 0)
3024 + /* Check the remaining name entries */
3025 + while (!IS_LAST_ENTRY(entry)) {
3026 + struct ext3_xattr_entry *next =
3027 + EXT3_XATTR_NEXT(entry);
3028 + if ((char *)next >= end)
3032 + if (ext3_xattr_cache_insert(bh))
3033 + ea_idebug(inode, "cache insert failed");
3037 + /* check the buffer size */
3038 + if (entry->e_value_block != 0)
3040 + size = le32_to_cpu(entry->e_value_size);
3041 + if (size > inode->i_sb->s_blocksize ||
3042 + le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
3045 + if (ext3_xattr_cache_insert(bh))
3046 + ea_idebug(inode, "cache insert failed");
3049 + if (size > buffer_size)
3051 + /* return value of attribute */
3052 + memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
3064 + * ext3_xattr_list()
3066 + * Copy a list of attribute names into the buffer
3067 + * provided, or compute the buffer size required.
3068 + * Buffer is NULL to compute the size of the buffer required.
3070 + * Returns a negative error number on failure, or the number of bytes
3071 + * used / required on success.
3074 +ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
3076 + struct buffer_head *bh = NULL;
3077 + struct ext3_xattr_entry *entry;
3078 + unsigned int block, size = 0;
3082 + ea_idebug(inode, "buffer=%p, buffer_size=%ld",
3083 + buffer, (long)buffer_size);
3085 + if (!EXT3_I(inode)->i_file_acl)
3087 + block = EXT3_I(inode)->i_file_acl;
3088 + ea_idebug(inode, "reading block %d", block);
3089 + bh = sb_bread(inode->i_sb, block);
3092 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3093 + atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
3094 + end = bh->b_data + bh->b_size;
3095 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3096 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3097 +bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
3098 + "inode %ld: bad block %d", inode->i_ino, block);
3102 + /* compute the size required for the list of attribute names */
3103 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3104 + entry = EXT3_XATTR_NEXT(entry)) {
3105 + struct ext3_xattr_handler *handler;
3106 + struct ext3_xattr_entry *next =
3107 + EXT3_XATTR_NEXT(entry);
3108 + if ((char *)next >= end)
3111 + handler = ext3_xattr_handler(entry->e_name_index);
3113 + size += handler->list(NULL, inode, entry->e_name,
3114 + entry->e_name_len);
3117 + if (ext3_xattr_cache_insert(bh))
3118 + ea_idebug(inode, "cache insert failed");
3124 + if (size > buffer_size)
3128 + /* list the attribute names */
3130 + for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
3131 + entry = EXT3_XATTR_NEXT(entry)) {
3132 + struct ext3_xattr_handler *handler;
3134 + handler = ext3_xattr_handler(entry->e_name_index);
3136 + buf += handler->list(buf, inode, entry->e_name,
3137 + entry->e_name_len);
3148 + * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
3149 + * not set, set it.
3151 +static void ext3_xattr_update_super_block(handle_t *handle,
3152 + struct super_block *sb)
3154 + if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
3158 + ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
3159 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3160 + EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
3162 + EXT3_SB(sb)->s_es->s_feature_compat |=
3163 + cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
3165 + ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
3170 + * ext3_xattr_set()
3172 + * Create, replace or remove an extended attribute for this inode. Buffer
3173 + * is NULL to remove an existing extended attribute, and non-NULL to
3174 + * either replace an existing extended attribute, or create a new extended
3175 + * attribute. The flags XATTR_REPLACE and XATTR_CREATE
3176 + * specify that an extended attribute must exist and must not exist
3177 + * previous to the call, respectively.
3179 + * Returns 0, or a negative error number on failure.
3182 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
3183 + const char *name, const void *value, size_t value_len, int flags)
3185 + struct super_block *sb = inode->i_sb;
3186 + struct buffer_head *bh = NULL;
3187 + struct ext3_xattr_header *header = NULL;
3188 + struct ext3_xattr_entry *here, *last;
3189 + unsigned int name_len;
3190 + int block = EXT3_I(inode)->i_file_acl;
3191 + int min_offs = sb->s_blocksize, not_found = 1, free, error;
3195 + * header -- Points either into bh, or to a temporarily
3196 + * allocated buffer.
3197 + * here -- The named entry found, or the place for inserting, within
3198 + * the block pointed to by header.
3199 + * last -- Points right after the last named entry within the block
3200 + * pointed to by header.
3201 + * min_offs -- The offset of the first value (values are aligned
3202 + * towards the end of the block).
3203 + * end -- Points right after the block pointed to by header.
3206 + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
3207 + name_index, name, value, (long)value_len);
3209 + if (IS_RDONLY(inode))
3211 + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
3213 + if (value == NULL)
3217 + name_len = strlen(name);
3218 + if (name_len > 255 || value_len > sb->s_blocksize)
3220 + down(&ext3_xattr_sem);
3223 + /* The inode already has an extended attribute block. */
3224 + bh = sb_bread(sb, block);
3228 + ea_bdebug(bh, "b_count=%d, refcount=%d",
3229 + atomic_read(&(bh->b_count)),
3230 + le32_to_cpu(HDR(bh)->h_refcount));
3232 + end = bh->b_data + bh->b_size;
3233 + if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3234 + header->h_blocks != cpu_to_le32(1)) {
3235 +bad_block: ext3_error(sb, "ext3_xattr_set",
3236 + "inode %ld: bad block %d", inode->i_ino, block);
3240 + /* Find the named attribute. */
3241 + here = FIRST_ENTRY(bh);
3242 + while (!IS_LAST_ENTRY(here)) {
3243 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
3244 + if ((char *)next >= end)
3246 + if (!here->e_value_block && here->e_value_size) {
3247 + int offs = le16_to_cpu(here->e_value_offs);
3248 + if (offs < min_offs)
3251 + not_found = name_index - here->e_name_index;
3253 + not_found = name_len - here->e_name_len;
3255 + not_found = memcmp(name, here->e_name,name_len);
3256 + if (not_found <= 0)
3261 + /* We still need to compute min_offs and last. */
3262 + while (!IS_LAST_ENTRY(last)) {
3263 + struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
3264 + if ((char *)next >= end)
3266 + if (!last->e_value_block && last->e_value_size) {
3267 + int offs = le16_to_cpu(last->e_value_offs);
3268 + if (offs < min_offs)
3274 + /* Check whether we have enough space left. */
3275 + free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
3277 + /* We will use a new extended attribute block. */
3278 + free = sb->s_blocksize -
3279 + sizeof(struct ext3_xattr_header) - sizeof(__u32);
3280 + here = last = NULL; /* avoid gcc uninitialized warning. */
3284 + /* Request to remove a nonexistent attribute? */
3286 + if (flags & XATTR_REPLACE)
3289 + if (value == NULL)
3292 + free -= EXT3_XATTR_LEN(name_len);
3294 + /* Request to create an existing attribute? */
3296 + if (flags & XATTR_CREATE)
3298 + if (!here->e_value_block && here->e_value_size) {
3299 + unsigned int size = le32_to_cpu(here->e_value_size);
3301 + if (le16_to_cpu(here->e_value_offs) + size >
3302 + sb->s_blocksize || size > sb->s_blocksize)
3304 + free += EXT3_XATTR_SIZE(size);
3307 + free -= EXT3_XATTR_SIZE(value_len);
3312 + /* Here we know that we can set the new attribute. */
3315 + if (header->h_refcount == cpu_to_le32(1)) {
3316 + ea_bdebug(bh, "modifying in-place");
3317 + ext3_xattr_cache_remove(bh);
3318 + error = ext3_journal_get_write_access(handle, bh);
3324 + ea_bdebug(bh, "cloning");
3325 + header = kmalloc(bh->b_size, GFP_KERNEL);
3327 + if (header == NULL)
3329 + memcpy(header, HDR(bh), bh->b_size);
3330 + header->h_refcount = cpu_to_le32(1);
3331 + offset = (char *)header - bh->b_data;
3332 + here = ENTRY((char *)here + offset);
3333 + last = ENTRY((char *)last + offset);
3336 + /* Allocate a buffer where we construct the new block. */
3337 + header = kmalloc(sb->s_blocksize, GFP_KERNEL);
3339 + if (header == NULL)
3341 + memset(header, 0, sb->s_blocksize);
3342 + end = (char *)header + sb->s_blocksize;
3343 + header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
3344 + header->h_blocks = header->h_refcount = cpu_to_le32(1);
3345 + last = here = ENTRY(header+1);
3349 + /* Insert the new name. */
3350 + int size = EXT3_XATTR_LEN(name_len);
3351 + int rest = (char *)last - (char *)here;
3352 + memmove((char *)here + size, here, rest);
3353 + memset(here, 0, size);
3354 + here->e_name_index = name_index;
3355 + here->e_name_len = name_len;
3356 + memcpy(here->e_name, name, name_len);
3358 + /* Remove the old value. */
3359 + if (!here->e_value_block && here->e_value_size) {
3360 + char *first_val = (char *)header + min_offs;
3361 + int offs = le16_to_cpu(here->e_value_offs);
3362 + char *val = (char *)header + offs;
3363 + size_t size = EXT3_XATTR_SIZE(
3364 + le32_to_cpu(here->e_value_size));
3365 + memmove(first_val + size, first_val, val - first_val);
3366 + memset(first_val, 0, size);
3367 + here->e_value_offs = 0;
3370 + /* Adjust all value offsets. */
3371 + last = ENTRY(header+1);
3372 + while (!IS_LAST_ENTRY(last)) {
3373 + int o = le16_to_cpu(last->e_value_offs);
3374 + if (!last->e_value_block && o < offs)
3375 + last->e_value_offs =
3376 + cpu_to_le16(o + size);
3377 + last = EXT3_XATTR_NEXT(last);
3380 + if (value == NULL) {
3381 + /* Remove this attribute. */
3382 + if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
3383 + /* This block is now empty. */
3384 + error = ext3_xattr_set2(handle, inode, bh,NULL);
3387 + /* Remove the old name. */
3388 + int size = EXT3_XATTR_LEN(name_len);
3389 + last = ENTRY((char *)last - size);
3390 + memmove(here, (char*)here + size,
3391 + (char*)last - (char*)here);
3392 + memset(last, 0, size);
3397 + if (value != NULL) {
3398 + /* Insert the new value. */
3399 + here->e_value_size = cpu_to_le32(value_len);
3401 + size_t size = EXT3_XATTR_SIZE(value_len);
3402 + char *val = (char *)header + min_offs - size;
3403 + here->e_value_offs =
3404 + cpu_to_le16((char *)val - (char *)header);
3405 + memset(val + size - EXT3_XATTR_PAD, 0,
3406 + EXT3_XATTR_PAD); /* Clear the pad bytes. */
3407 + memcpy(val, value, value_len);
3410 + ext3_xattr_rehash(header, here);
3412 + error = ext3_xattr_set2(handle, inode, bh, header);
3416 + if (!(bh && header == HDR(bh)))
3418 + up(&ext3_xattr_sem);
3424 + * Second half of ext3_xattr_set(): Update the file system.
3427 +ext3_xattr_set2(handle_t *handle, struct inode *inode,
3428 + struct buffer_head *old_bh, struct ext3_xattr_header *header)
3430 + struct super_block *sb = inode->i_sb;
3431 + struct buffer_head *new_bh = NULL;
3435 + new_bh = ext3_xattr_cache_find(inode, header);
3438 + * We found an identical block in the cache.
3439 + * The old block will be released after updating
3442 + ea_bdebug(old_bh, "reusing block %ld",
3443 + new_bh->b_blocknr);
3446 + if (ext3_xattr_quota_alloc(inode, 1))
3449 + error = ext3_journal_get_write_access(handle, new_bh);
3452 + HDR(new_bh)->h_refcount = cpu_to_le32(
3453 + le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
3454 + ea_bdebug(new_bh, "refcount now=%d",
3455 + le32_to_cpu(HDR(new_bh)->h_refcount));
3456 + } else if (old_bh && header == HDR(old_bh)) {
3457 + /* Keep this block. */
3459 + ext3_xattr_cache_insert(new_bh);
3461 + /* We need to allocate a new block */
3462 + int force = EXT3_I(inode)->i_file_acl != 0;
3463 + int block = ext3_xattr_new_block(handle, inode,
3467 + ea_idebug(inode, "creating block %d", block);
3469 + new_bh = sb_getblk(sb, block);
3471 +getblk_failed: ext3_xattr_free_block(handle, inode, block);
3475 + lock_buffer(new_bh);
3476 + error = ext3_journal_get_create_access(handle, new_bh);
3478 + unlock_buffer(new_bh);
3479 + goto getblk_failed;
3481 + memcpy(new_bh->b_data, header, new_bh->b_size);
3482 + mark_buffer_uptodate(new_bh, 1);
3483 + unlock_buffer(new_bh);
3484 + ext3_xattr_cache_insert(new_bh);
3486 + ext3_xattr_update_super_block(handle, sb);
3488 + error = ext3_journal_dirty_metadata(handle, new_bh);
3493 + /* Update the inode. */
3494 + EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
3495 + inode->i_ctime = CURRENT_TIME;
3496 + ext3_mark_inode_dirty(handle, inode);
3497 + if (IS_SYNC(inode))
3498 + handle->h_sync = 1;
3501 + if (old_bh && old_bh != new_bh) {
3503 + * If there was an old block, and we are not still using it,
3504 + * we now release the old block.
3506 + unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
3508 + error = ext3_journal_get_write_access(handle, old_bh);
3511 + if (refcount == 1) {
3512 + /* Free the old block. */
3513 + ea_bdebug(old_bh, "freeing");
3514 + ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
3516 + /* ext3_forget() calls bforget() for us, but we
3517 + let our caller release old_bh, so we need to
3518 + duplicate the handle before. */
3520 + ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
3522 + /* Decrement the refcount only. */
3524 + HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
3525 + ext3_xattr_quota_free(inode);
3526 + ext3_journal_dirty_metadata(handle, old_bh);
3527 + ea_bdebug(old_bh, "refcount now=%d", refcount);
3532 + if (old_bh != new_bh)
3539 + * ext3_xattr_delete_inode()
3541 + * Free extended attribute resources associated with this inode. This
3542 + * is called immediately before an inode is freed.
3545 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
3547 + struct buffer_head *bh;
3548 + unsigned int block = EXT3_I(inode)->i_file_acl;
3552 + down(&ext3_xattr_sem);
3554 + bh = sb_bread(inode->i_sb, block);
3556 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3557 + "inode %ld: block %d read error", inode->i_ino, block);
3560 + ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
3561 + if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
3562 + HDR(bh)->h_blocks != cpu_to_le32(1)) {
3563 + ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
3564 + "inode %ld: bad block %d", inode->i_ino, block);
3567 + ext3_journal_get_write_access(handle, bh);
3568 + ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
3569 + if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
3570 + ext3_xattr_cache_remove(bh);
3571 + ext3_xattr_free_block(handle, inode, block);
3572 + ext3_forget(handle, 1, inode, bh, block);
3575 + HDR(bh)->h_refcount = cpu_to_le32(
3576 + le32_to_cpu(HDR(bh)->h_refcount) - 1);
3577 + ext3_journal_dirty_metadata(handle, bh);
3578 + if (IS_SYNC(inode))
3579 + handle->h_sync = 1;
3580 + ext3_xattr_quota_free(inode);
3582 + EXT3_I(inode)->i_file_acl = 0;
3586 + up(&ext3_xattr_sem);
3590 + * ext3_xattr_put_super()
3592 + * This is called when a file system is unmounted.
3595 +ext3_xattr_put_super(struct super_block *sb)
3597 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3598 + mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
3602 +#ifdef CONFIG_EXT3_FS_XATTR_SHARING
3605 + * ext3_xattr_cache_insert()
3607 + * Create a new entry in the extended attribute cache, and insert
3608 + * it unless such an entry is already in the cache.
3610 + * Returns 0, or a negative error number on failure.
3613 +ext3_xattr_cache_insert(struct buffer_head *bh)
3615 + __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
3616 + struct mb_cache_entry *ce;
3619 + ce = mb_cache_entry_alloc(ext3_xattr_cache);
3622 + error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
3624 + mb_cache_entry_free(ce);
3625 + if (error == -EBUSY) {
3626 + ea_bdebug(bh, "already in cache (%d cache entries)",
3627 + atomic_read(&ext3_xattr_cache->c_entry_count));
3631 + ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
3632 + atomic_read(&ext3_xattr_cache->c_entry_count));
3633 + mb_cache_entry_release(ce);
3639 + * ext3_xattr_cmp()
3641 + * Compare two extended attribute blocks for equality.
3643 + * Returns 0 if the blocks are equal, 1 if they differ, and
3644 + * a negative error number on errors.
3647 +ext3_xattr_cmp(struct ext3_xattr_header *header1,
3648 + struct ext3_xattr_header *header2)
3650 + struct ext3_xattr_entry *entry1, *entry2;
3652 + entry1 = ENTRY(header1+1);
3653 + entry2 = ENTRY(header2+1);
3654 + while (!IS_LAST_ENTRY(entry1)) {
3655 + if (IS_LAST_ENTRY(entry2))
3657 + if (entry1->e_hash != entry2->e_hash ||
3658 + entry1->e_name_len != entry2->e_name_len ||
3659 + entry1->e_value_size != entry2->e_value_size ||
3660 + memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
3662 + if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
3664 + if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
3665 + (char *)header2 + le16_to_cpu(entry2->e_value_offs),
3666 + le32_to_cpu(entry1->e_value_size)))
3669 + entry1 = EXT3_XATTR_NEXT(entry1);
3670 + entry2 = EXT3_XATTR_NEXT(entry2);
3672 + if (!IS_LAST_ENTRY(entry2))
3678 + * ext3_xattr_cache_find()
3680 + * Find an identical extended attribute block.
3682 + * Returns a pointer to the block found, or NULL if such a block was
3683 + * not found or an error occurred.
3685 +static struct buffer_head *
3686 +ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
3688 + __u32 hash = le32_to_cpu(header->h_hash);
3689 + struct mb_cache_entry *ce;
3691 + if (!header->h_hash)
3692 + return NULL; /* never share */
3693 + ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
3694 + ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
3696 + struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
3699 + ext3_error(inode->i_sb, "ext3_xattr_cache_find",
3700 + "inode %ld: block %ld read error",
3701 + inode->i_ino, ce->e_block);
3702 + } else if (le32_to_cpu(HDR(bh)->h_refcount) >
3703 + EXT3_XATTR_REFCOUNT_MAX) {
3704 + ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
3705 + le32_to_cpu(HDR(bh)->h_refcount),
3706 + EXT3_XATTR_REFCOUNT_MAX);
3707 + } else if (!ext3_xattr_cmp(header, HDR(bh))) {
3708 + ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
3709 + mb_cache_entry_release(ce);
3713 + ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
3719 + * ext3_xattr_cache_remove()
3721 + * Remove the cache entry of a block from the cache. Called when a
3722 + * block becomes invalid.
3725 +ext3_xattr_cache_remove(struct buffer_head *bh)
3727 + struct mb_cache_entry *ce;
3729 + ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
3731 + ea_bdebug(bh, "removing (%d cache entries remaining)",
3732 + atomic_read(&ext3_xattr_cache->c_entry_count)-1);
3733 + mb_cache_entry_free(ce);
3735 + ea_bdebug(bh, "no cache entry");
3738 +#define NAME_HASH_SHIFT 5
3739 +#define VALUE_HASH_SHIFT 16
3742 + * ext3_xattr_hash_entry()
3744 + * Compute the hash of an extended attribute.
3746 +static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
3747 + struct ext3_xattr_entry *entry)
3750 + char *name = entry->e_name;
3753 + for (n=0; n < entry->e_name_len; n++) {
3754 + hash = (hash << NAME_HASH_SHIFT) ^
3755 + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
3759 + if (entry->e_value_block == 0 && entry->e_value_size != 0) {
3760 + __u32 *value = (__u32 *)((char *)header +
3761 + le16_to_cpu(entry->e_value_offs));
3762 + for (n = (le32_to_cpu(entry->e_value_size) +
3763 + EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
3764 + hash = (hash << VALUE_HASH_SHIFT) ^
3765 + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
3766 + le32_to_cpu(*value++);
3769 + entry->e_hash = cpu_to_le32(hash);
3772 +#undef NAME_HASH_SHIFT
3773 +#undef VALUE_HASH_SHIFT
3775 +#define BLOCK_HASH_SHIFT 16
3778 + * ext3_xattr_rehash()
3780 + * Re-compute the extended attribute hash value after an entry has changed.
3782 +static void ext3_xattr_rehash(struct ext3_xattr_header *header,
3783 + struct ext3_xattr_entry *entry)
3785 + struct ext3_xattr_entry *here;
3788 + ext3_xattr_hash_entry(header, entry);
3789 + here = ENTRY(header+1);
3790 + while (!IS_LAST_ENTRY(here)) {
3791 + if (!here->e_hash) {
3792 + /* Block is not shared if an entry's hash value == 0 */
3796 + hash = (hash << BLOCK_HASH_SHIFT) ^
3797 + (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
3798 + le32_to_cpu(here->e_hash);
3799 + here = EXT3_XATTR_NEXT(here);
3801 + header->h_hash = cpu_to_le32(hash);
3804 +#undef BLOCK_HASH_SHIFT
3807 +init_ext3_xattr(void)
3809 + ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
3810 + sizeof(struct mb_cache_entry) +
3811 + sizeof(struct mb_cache_entry_index), 1, 61);
3812 + if (!ext3_xattr_cache)
3819 +exit_ext3_xattr(void)
3821 + if (ext3_xattr_cache)
3822 + mb_cache_destroy(ext3_xattr_cache);
3823 + ext3_xattr_cache = NULL;
3826 +#else /* CONFIG_EXT3_FS_XATTR_SHARING */
3829 +init_ext3_xattr(void)
3835 +exit_ext3_xattr(void)
3839 +#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
3840 --- /dev/null Mon May 20 21:11:23 2002
3841 +++ linux-mmonroe/fs/ext3/xattr_user.c Fri May 16 08:43:01 2003
3844 + * linux/fs/ext3/xattr_user.c
3845 + * Handler for extended user attributes.
3847 + * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
3850 +#include <linux/module.h>
3851 +#include <linux/string.h>
3852 +#include <linux/fs.h>
3853 +#include <linux/ext3_jbd.h>
3854 +#include <linux/ext3_fs.h>
3855 +#include <linux/ext3_xattr.h>
3857 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3858 +# include <linux/ext3_acl.h>
3861 +#define XATTR_USER_PREFIX "user."
3864 +ext3_xattr_user_list(char *list, struct inode *inode,
3865 + const char *name, int name_len)
3867 + const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
3869 + if (!test_opt(inode->i_sb, XATTR_USER))
3873 + memcpy(list, XATTR_USER_PREFIX, prefix_len);
3874 + memcpy(list+prefix_len, name, name_len);
3875 + list[prefix_len + name_len] = '\0';
3877 + return prefix_len + name_len + 1;
3881 +ext3_xattr_user_get(struct inode *inode, const char *name,
3882 + void *buffer, size_t size)
3886 + if (strcmp(name, "") == 0)
3888 + if (!test_opt(inode->i_sb, XATTR_USER))
3890 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3891 + error = ext3_permission_locked(inode, MAY_READ);
3893 + error = permission(inode, MAY_READ);
3898 + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
3903 +ext3_xattr_user_set(struct inode *inode, const char *name,
3904 + const void *value, size_t size, int flags)
3909 + if (strcmp(name, "") == 0)
3911 + if (!test_opt(inode->i_sb, XATTR_USER))
3913 + if ( !S_ISREG(inode->i_mode) &&
3914 + (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
3916 +#ifdef CONFIG_EXT3_FS_POSIX_ACL
3917 + error = ext3_permission_locked(inode, MAY_WRITE);
3919 + error = permission(inode, MAY_WRITE);
3924 + handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
3925 + if (IS_ERR(handle))
3926 + return PTR_ERR(handle);
3927 + error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
3928 + value, size, flags);
3929 + ext3_journal_stop(handle, inode);
3934 +struct ext3_xattr_handler ext3_xattr_user_handler = {
3935 + prefix: XATTR_USER_PREFIX,
3936 + list: ext3_xattr_user_list,
3937 + get: ext3_xattr_user_get,
3938 + set: ext3_xattr_user_set,
3942 +init_ext3_xattr_user(void)
3944 + return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
3945 + &ext3_xattr_user_handler);
3949 +exit_ext3_xattr_user(void)
3951 + ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
3952 + &ext3_xattr_user_handler);
3954 --- /dev/null Mon May 20 21:11:23 2002
3955 +++ linux-mmonroe/fs/ext3/ext3-exports.c Fri May 16 08:43:01 2003
3957 +#include <linux/config.h>
3958 +#include <linux/module.h>
3959 +#include <linux/ext3_fs.h>
3960 +#include <linux/ext3_jbd.h>
3961 +#include <linux/ext3_xattr.h>
3963 +EXPORT_SYMBOL(ext3_force_commit);
3964 +EXPORT_SYMBOL(ext3_bread);
3965 +EXPORT_SYMBOL(ext3_xattr_register);
3966 +EXPORT_SYMBOL(ext3_xattr_unregister);
3967 +EXPORT_SYMBOL(ext3_xattr_get);
3968 +EXPORT_SYMBOL(ext3_xattr_list);
3969 +EXPORT_SYMBOL(ext3_xattr_set);
3970 --- linux/fs/jfs/jfs_xattr.h~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002
3971 +++ linux-mmonroe/fs/jfs/jfs_xattr.h Fri May 16 08:43:01 2003
3972 @@ -52,8 +52,10 @@ struct jfs_ea_list {
3973 #define END_EALIST(ealist) \
3974 ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
3976 -extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
3977 -extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
3978 +extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
3980 +extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
3982 extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
3983 extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
3984 extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
3985 --- linux/fs/jfs/xattr.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002
3986 +++ linux-mmonroe/fs/jfs/xattr.c Fri May 16 08:43:01 2003
3987 @@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s
3990 static int can_set_xattr(struct inode *inode, const char *name,
3991 - void *value, size_t value_len)
3992 + const void *value, size_t value_len)
3994 if (IS_RDONLY(inode))
3996 @@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i
3997 return permission(inode, MAY_WRITE);
4000 -int __jfs_setxattr(struct inode *inode, const char *name, void *value,
4001 +int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
4002 size_t value_len, int flags)
4004 struct jfs_ea_list *ealist;
4005 @@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode,
4009 -int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
4010 +int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
4011 size_t value_len, int flags)
4013 if (value == NULL) { /* empty EA, do not remove */
4014 --- /dev/null Mon May 20 21:11:23 2002
4015 +++ linux-mmonroe/fs/mbcache.c Fri May 16 08:43:01 2003
4018 + * linux/fs/mbcache.c
4019 + * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4023 + * Filesystem Meta Information Block Cache (mbcache)
4025 + * The mbcache caches blocks of block devices that need to be located
4026 + * by their device/block number, as well as by other criteria (such
4027 + * as the block's contents).
4029 + * There can only be one cache entry in a cache per device and block number.
4030 + * Additional indexes need not be unique in this sense. The number of
4031 + * additional indexes (=other criteria) can be hardwired at compile time
4032 + * or specified at cache create time.
4034 + * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
4035 + * in the cache. A valid entry is in the main hash tables of the cache,
4036 + * and may also be in the lru list. An invalid entry is not in any hashes
4039 + * A valid cache entry is only in the lru list if no handles refer to it.
4040 + * Invalid cache entries will be freed when the last handle to the cache
4041 + * entry is released. Entries that cannot be freed immediately are put
4042 + * back on the lru list.
4045 +#include <linux/kernel.h>
4046 +#include <linux/module.h>
4048 +#include <linux/fs.h>
4049 +#include <linux/slab.h>
4050 +#include <linux/sched.h>
4051 +#include <linux/cache_def.h>
4052 +#include <linux/version.h>
4053 +#include <linux/init.h>
4054 +#include <linux/mbcache.h>
4057 +#ifdef MB_CACHE_DEBUG
4058 +# define mb_debug(f...) do { \
4059 + printk(KERN_DEBUG f); \
4062 +#define mb_assert(c) do { if (!(c)) \
4063 + printk(KERN_ERR "assertion " #c " failed\n"); \
4066 +# define mb_debug(f...) do { } while(0)
4067 +# define mb_assert(c) do { } while(0)
4069 +#define mb_error(f...) do { \
4070 + printk(KERN_ERR f); \
4074 +MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
4075 +MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
4076 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4077 +MODULE_LICENSE("GPL");
4080 +EXPORT_SYMBOL(mb_cache_create);
4081 +EXPORT_SYMBOL(mb_cache_shrink);
4082 +EXPORT_SYMBOL(mb_cache_destroy);
4083 +EXPORT_SYMBOL(mb_cache_entry_alloc);
4084 +EXPORT_SYMBOL(mb_cache_entry_insert);
4085 +EXPORT_SYMBOL(mb_cache_entry_release);
4086 +EXPORT_SYMBOL(mb_cache_entry_takeout);
4087 +EXPORT_SYMBOL(mb_cache_entry_free);
4088 +EXPORT_SYMBOL(mb_cache_entry_dup);
4089 +EXPORT_SYMBOL(mb_cache_entry_get);
4090 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4091 +EXPORT_SYMBOL(mb_cache_entry_find_first);
4092 +EXPORT_SYMBOL(mb_cache_entry_find_next);
4097 + * Global data: list of all mbcache's, lru list, and a spinlock for
4098 + * accessing cache data structures on SMP machines. The lru list is
4099 + * global across all mbcaches.
4102 +static LIST_HEAD(mb_cache_list);
4103 +static LIST_HEAD(mb_cache_lru_list);
4104 +static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
4107 +mb_cache_indexes(struct mb_cache *cache)
4109 +#ifdef MB_CACHE_INDEXES_COUNT
4110 + return MB_CACHE_INDEXES_COUNT;
4112 + return cache->c_indexes_count;
4117 + * What the mbcache registers as to get shrunk dynamically.
4121 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
4123 +static struct cache_definition mb_cache_definition = {
4125 + mb_cache_memory_pressure
4130 +__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
4132 + return !list_empty(&ce->e_block_list);
4137 +__mb_cache_entry_unhash(struct mb_cache_entry *ce)
4141 + if (__mb_cache_entry_is_hashed(ce)) {
4142 + list_del_init(&ce->e_block_list);
4143 + for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
4144 + list_del(&ce->e_indexes[n].o_list);
4150 +__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
4152 + struct mb_cache *cache = ce->e_cache;
4154 + mb_assert(atomic_read(&ce->e_used) == 0);
4155 + if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
4156 + /* free failed -- put back on the lru list
4157 + for freeing later. */
4158 + spin_lock(&mb_cache_spinlock);
4159 + list_add(&ce->e_lru_list, &mb_cache_lru_list);
4160 + spin_unlock(&mb_cache_spinlock);
4162 + kmem_cache_free(cache->c_entry_cache, ce);
4163 + atomic_dec(&cache->c_entry_count);
4169 +__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
4171 + if (atomic_dec_and_test(&ce->e_used)) {
4172 + if (__mb_cache_entry_is_hashed(ce))
4173 + list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
4175 + spin_unlock(&mb_cache_spinlock);
4176 + __mb_cache_entry_forget(ce, GFP_KERNEL);
4180 + spin_unlock(&mb_cache_spinlock);
4185 + * mb_cache_memory_pressure() memory pressure callback
4187 + * This function is called by the kernel memory management when memory
4190 + * @priority: Amount by which to shrink the cache (0 = highes priority)
4191 + * @gfp_mask: (ignored)
4194 +mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
4196 + LIST_HEAD(free_list);
4197 + struct list_head *l, *ltmp;
4200 + spin_lock(&mb_cache_spinlock);
4201 + list_for_each(l, &mb_cache_list) {
4202 + struct mb_cache *cache =
4203 + list_entry(l, struct mb_cache, c_cache_list);
4204 + mb_debug("cache %s (%d)", cache->c_name,
4205 + atomic_read(&cache->c_entry_count));
4206 + count += atomic_read(&cache->c_entry_count);
4208 + mb_debug("trying to free %d of %d entries",
4209 + count / (priority ? priority : 1), count);
4211 + count /= priority;
4212 + while (count-- && !list_empty(&mb_cache_lru_list)) {
4213 + struct mb_cache_entry *ce =
4214 + list_entry(mb_cache_lru_list.next,
4215 + struct mb_cache_entry, e_lru_list);
4216 + list_del(&ce->e_lru_list);
4217 + __mb_cache_entry_unhash(ce);
4218 + list_add_tail(&ce->e_lru_list, &free_list);
4220 + spin_unlock(&mb_cache_spinlock);
4221 + list_for_each_safe(l, ltmp, &free_list) {
4222 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4223 + e_lru_list), gfp_mask);
4229 + * mb_cache_create() create a new cache
4231 + * All entries in one cache are equal size. Cache entries may be from
4232 + * multiple devices. If this is the first mbcache created, registers
4233 + * the cache with kernel memory management. Returns NULL if no more
4234 + * memory was available.
4236 + * @name: name of the cache (informal)
4237 + * @cache_op: contains the callback called when freeing a cache entry
4238 + * @entry_size: The size of a cache entry, including
4239 + * struct mb_cache_entry
4240 + * @indexes_count: number of additional indexes in the cache. Must equal
4241 + * MB_CACHE_INDEXES_COUNT if the number of indexes is
4243 + * @bucket_count: number of hash buckets
4246 +mb_cache_create(const char *name, struct mb_cache_op *cache_op,
4247 + size_t entry_size, int indexes_count, int bucket_count)
4250 + struct mb_cache *cache = NULL;
4252 + if(entry_size < sizeof(struct mb_cache_entry) +
4253 + indexes_count * sizeof(struct mb_cache_entry_index))
4256 + MOD_INC_USE_COUNT;
4257 + cache = kmalloc(sizeof(struct mb_cache) +
4258 + indexes_count * sizeof(struct list_head), GFP_KERNEL);
4261 + cache->c_name = name;
4262 + cache->c_op.free = NULL;
4264 + cache->c_op.free = cache_op->free;
4265 + atomic_set(&cache->c_entry_count, 0);
4266 + cache->c_bucket_count = bucket_count;
4267 +#ifdef MB_CACHE_INDEXES_COUNT
4268 + mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
4270 + cache->c_indexes_count = indexes_count;
4272 + cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
4274 + if (!cache->c_block_hash)
4276 + for (n=0; n<bucket_count; n++)
4277 + INIT_LIST_HEAD(&cache->c_block_hash[n]);
4278 + for (m=0; m<indexes_count; m++) {
4279 + cache->c_indexes_hash[m] = kmalloc(bucket_count *
4280 + sizeof(struct list_head),
4282 + if (!cache->c_indexes_hash[m])
4284 + for (n=0; n<bucket_count; n++)
4285 + INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
4287 + cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
4288 + 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
4289 + if (!cache->c_entry_cache)
4292 + spin_lock(&mb_cache_spinlock);
4293 + list_add(&cache->c_cache_list, &mb_cache_list);
4294 + spin_unlock(&mb_cache_spinlock);
4300 + kfree(cache->c_indexes_hash[m]);
4301 + if (cache->c_block_hash)
4302 + kfree(cache->c_block_hash);
4305 + MOD_DEC_USE_COUNT;
4311 + * mb_cache_shrink()
4313 + * Removes all cache entires of a device from the cache. All cache entries
4314 + * currently in use cannot be freed, and thus remain in the cache.
4316 + * @cache: which cache to shrink
4317 + * @dev: which device's cache entries to shrink
4320 +mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
4322 + LIST_HEAD(free_list);
4323 + struct list_head *l, *ltmp;
4325 + spin_lock(&mb_cache_spinlock);
4326 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4327 + struct mb_cache_entry *ce =
4328 + list_entry(l, struct mb_cache_entry, e_lru_list);
4329 + if (ce->e_dev == dev) {
4330 + list_del(&ce->e_lru_list);
4331 + list_add_tail(&ce->e_lru_list, &free_list);
4332 + __mb_cache_entry_unhash(ce);
4335 + spin_unlock(&mb_cache_spinlock);
4336 + list_for_each_safe(l, ltmp, &free_list) {
4337 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4338 + e_lru_list), GFP_KERNEL);
4344 + * mb_cache_destroy()
4346 + * Shrinks the cache to its minimum possible size (hopefully 0 entries),
4347 + * and then destroys it. If this was the last mbcache, un-registers the
4348 + * mbcache from kernel memory management.
4351 +mb_cache_destroy(struct mb_cache *cache)
4353 + LIST_HEAD(free_list);
4354 + struct list_head *l, *ltmp;
4357 + spin_lock(&mb_cache_spinlock);
4358 + list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
4359 + struct mb_cache_entry *ce =
4360 + list_entry(l, struct mb_cache_entry, e_lru_list);
4361 + if (ce->e_cache == cache) {
4362 + list_del(&ce->e_lru_list);
4363 + list_add_tail(&ce->e_lru_list, &free_list);
4364 + __mb_cache_entry_unhash(ce);
4367 + list_del(&cache->c_cache_list);
4368 + spin_unlock(&mb_cache_spinlock);
4369 + list_for_each_safe(l, ltmp, &free_list) {
4370 + __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
4371 + e_lru_list), GFP_KERNEL);
4374 + if (atomic_read(&cache->c_entry_count) > 0) {
4375 + mb_error("cache %s: %d orphaned entries",
4377 + atomic_read(&cache->c_entry_count));
4380 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
4381 + /* We don't have kmem_cache_destroy() in 2.2.x */
4382 + kmem_cache_shrink(cache->c_entry_cache);
4384 + kmem_cache_destroy(cache->c_entry_cache);
4386 + for (n=0; n < mb_cache_indexes(cache); n++)
4387 + kfree(cache->c_indexes_hash[n]);
4388 + kfree(cache->c_block_hash);
4391 + MOD_DEC_USE_COUNT;
4396 + * mb_cache_entry_alloc()
4398 + * Allocates a new cache entry. The new entry will not be valid initially,
4399 + * and thus cannot be looked up yet. It should be filled with data, and
4400 + * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
4401 + * if no more memory was available.
4403 +struct mb_cache_entry *
4404 +mb_cache_entry_alloc(struct mb_cache *cache)
4406 + struct mb_cache_entry *ce;
4408 + atomic_inc(&cache->c_entry_count);
4409 + ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
4411 + INIT_LIST_HEAD(&ce->e_lru_list);
4412 + INIT_LIST_HEAD(&ce->e_block_list);
4413 + ce->e_cache = cache;
4414 + atomic_set(&ce->e_used, 1);
4421 + * mb_cache_entry_insert()
4423 + * Inserts an entry that was allocated using mb_cache_entry_alloc() into
4424 + * the cache. After this, the cache entry can be looked up, but is not yet
4425 + * in the lru list as the caller still holds a handle to it. Returns 0 on
4426 + * success, or -EBUSY if a cache entry for that device + inode exists
4427 + * already (this may happen after a failed lookup, if another process has
4428 + * inserted the same cache entry in the meantime).
4430 + * @dev: device the cache entry belongs to
4431 + * @block: block number
4432 + * @keys: array of additional keys. There must be indexes_count entries
4433 + * in the array (as specified when creating the cache).
4436 +mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
4437 + unsigned long block, unsigned int keys[])
4439 + struct mb_cache *cache = ce->e_cache;
4440 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4441 + struct list_head *l;
4442 + int error = -EBUSY, n;
4444 + spin_lock(&mb_cache_spinlock);
4445 + list_for_each(l, &cache->c_block_hash[bucket]) {
4446 + struct mb_cache_entry *ce =
4447 + list_entry(l, struct mb_cache_entry, e_block_list);
4448 + if (ce->e_dev == dev && ce->e_block == block)
4451 + __mb_cache_entry_unhash(ce);
4453 + ce->e_block = block;
4454 + list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
4455 + for (n=0; n<mb_cache_indexes(cache); n++) {
4456 + ce->e_indexes[n].o_key = keys[n];
4457 + bucket = keys[n] % cache->c_bucket_count;
4458 + list_add(&ce->e_indexes[n].o_list,
4459 + &cache->c_indexes_hash[n][bucket]);
4462 + spin_unlock(&mb_cache_spinlock);
4468 + * mb_cache_entry_release()
4470 + * Release a handle to a cache entry. When the last handle to a cache entry
4471 + * is released it is either freed (if it is invalid) or otherwise inserted
4472 + * in to the lru list.
4475 +mb_cache_entry_release(struct mb_cache_entry *ce)
4477 + spin_lock(&mb_cache_spinlock);
4478 + __mb_cache_entry_release_unlock(ce);
4483 + * mb_cache_entry_takeout()
4485 + * Take a cache entry out of the cache, making it invalid. The entry can later
4486 + * be re-inserted using mb_cache_entry_insert(), or released using
4487 + * mb_cache_entry_release().
4490 +mb_cache_entry_takeout(struct mb_cache_entry *ce)
4492 + spin_lock(&mb_cache_spinlock);
4493 + mb_assert(list_empty(&ce->e_lru_list));
4494 + __mb_cache_entry_unhash(ce);
4495 + spin_unlock(&mb_cache_spinlock);
4500 + * mb_cache_entry_free()
4502 + * This is equivalent to the sequence mb_cache_entry_takeout() --
4503 + * mb_cache_entry_release().
4506 +mb_cache_entry_free(struct mb_cache_entry *ce)
4508 + spin_lock(&mb_cache_spinlock);
4509 + mb_assert(list_empty(&ce->e_lru_list));
4510 + __mb_cache_entry_unhash(ce);
4511 + __mb_cache_entry_release_unlock(ce);
4516 + * mb_cache_entry_dup()
4518 + * Duplicate a handle to a cache entry (does not duplicate the cache entry
4519 + * itself). After the call, both the old and the new handle must be released.
4521 +struct mb_cache_entry *
4522 +mb_cache_entry_dup(struct mb_cache_entry *ce)
4524 + atomic_inc(&ce->e_used);
4530 + * mb_cache_entry_get()
4532 + * Get a cache entry by device / block number. (There can only be one entry
4533 + * in the cache per device and block.) Returns NULL if no such cache entry
4536 +struct mb_cache_entry *
4537 +mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
4539 + unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
4540 + struct list_head *l;
4541 + struct mb_cache_entry *ce;
4543 + spin_lock(&mb_cache_spinlock);
4544 + list_for_each(l, &cache->c_block_hash[bucket]) {
4545 + ce = list_entry(l, struct mb_cache_entry, e_block_list);
4546 + if (ce->e_dev == dev && ce->e_block == block) {
4547 + if (!list_empty(&ce->e_lru_list))
4548 + list_del_init(&ce->e_lru_list);
4549 + atomic_inc(&ce->e_used);
4556 + spin_unlock(&mb_cache_spinlock);
4560 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
4562 +static struct mb_cache_entry *
4563 +__mb_cache_entry_find(struct list_head *l, struct list_head *head,
4564 + int index, kdev_t dev, unsigned int key)
4566 + while (l != head) {
4567 + struct mb_cache_entry *ce =
4568 + list_entry(l, struct mb_cache_entry,
4569 + e_indexes[index].o_list);
4570 + if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
4571 + if (!list_empty(&ce->e_lru_list))
4572 + list_del_init(&ce->e_lru_list);
4573 + atomic_inc(&ce->e_used);
4583 + * mb_cache_entry_find_first()
4585 + * Find the first cache entry on a given device with a certain key in
4586 + * an additional index. Additonal matches can be found with
4587 + * mb_cache_entry_find_next(). Returns NULL if no match was found.
4589 + * @cache: the cache to search
4590 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4591 + * @dev: the device the cache entry should belong to
4592 + * @key: the key in the index
4594 +struct mb_cache_entry *
4595 +mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
4598 + unsigned int bucket = key % cache->c_bucket_count;
4599 + struct list_head *l;
4600 + struct mb_cache_entry *ce;
4602 + mb_assert(index < mb_cache_indexes(cache));
4603 + spin_lock(&mb_cache_spinlock);
4604 + l = cache->c_indexes_hash[index][bucket].next;
4605 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4607 + spin_unlock(&mb_cache_spinlock);
4613 + * mb_cache_entry_find_next()
4615 + * Find the next cache entry on a given device with a certain key in an
4616 + * additional index. Returns NULL if no match could be found. The previous
4617 + * entry is atomatically released, so that mb_cache_entry_find_next() can
4618 + * be called like this:
4620 + * entry = mb_cache_entry_find_first();
4623 + * entry = mb_cache_entry_find_next(entry, ...);
4626 + * @prev: The previous match
4627 + * @index: the number of the additonal index to search (0<=index<indexes_count)
4628 + * @dev: the device the cache entry should belong to
4629 + * @key: the key in the index
4631 +struct mb_cache_entry *
4632 +mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
4635 + struct mb_cache *cache = prev->e_cache;
4636 + unsigned int bucket = key % cache->c_bucket_count;
4637 + struct list_head *l;
4638 + struct mb_cache_entry *ce;
4640 + mb_assert(index < mb_cache_indexes(cache));
4641 + spin_lock(&mb_cache_spinlock);
4642 + l = prev->e_indexes[index].o_list.next;
4643 + ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
4645 + __mb_cache_entry_release_unlock(prev);
4649 +#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
4651 +static int __init init_mbcache(void)
4653 + register_cache(&mb_cache_definition);
4657 +static void __exit exit_mbcache(void)
4659 + unregister_cache(&mb_cache_definition);
4662 +module_init(init_mbcache)
4663 +module_exit(exit_mbcache)
4665 --- linux/include/asm-arm/unistd.h~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:45 2002
4666 +++ linux-mmonroe/include/asm-arm/unistd.h Fri May 16 08:43:01 2003
4668 #define __NR_security (__NR_SYSCALL_BASE+223)
4669 #define __NR_gettid (__NR_SYSCALL_BASE+224)
4670 #define __NR_readahead (__NR_SYSCALL_BASE+225)
4671 -#if 0 /* allocated in 2.5 */
4672 #define __NR_setxattr (__NR_SYSCALL_BASE+226)
4673 #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
4674 #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
4676 #define __NR_removexattr (__NR_SYSCALL_BASE+235)
4677 #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
4678 #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
4680 #define __NR_tkill (__NR_SYSCALL_BASE+238)
4682 * Please check 2.5 _before_ adding calls here,
4683 --- linux/include/asm-ppc64/unistd.h~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:45 2002
4684 +++ linux-mmonroe/include/asm-ppc64/unistd.h Fri May 16 08:43:01 2003
4686 #define __NR_gettid 207
4687 #if 0 /* Reserved syscalls */
4688 #define __NR_tkill 208
4690 #define __NR_setxattr 209
4691 #define __NR_lsetxattr 210
4692 #define __NR_fsetxattr 211
4694 #define __NR_removexattr 218
4695 #define __NR_lremovexattr 219
4696 #define __NR_fremovexattr 220
4697 +#if 0 /* Reserved syscalls */
4698 #define __NR_futex 221
4701 --- linux/include/asm-s390/unistd.h~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:45 2002
4702 +++ linux-mmonroe/include/asm-s390/unistd.h Fri May 16 08:43:01 2003
4703 @@ -212,9 +212,18 @@
4704 #define __NR_madvise 219
4705 #define __NR_getdents64 220
4706 #define __NR_fcntl64 221
4708 - * Numbers 224-235 are reserved for posix acl
4710 +#define __NR_setxattr 224
4711 +#define __NR_lsetxattr 225
4712 +#define __NR_fsetxattr 226
4713 +#define __NR_getxattr 227
4714 +#define __NR_lgetxattr 228
4715 +#define __NR_fgetxattr 229
4716 +#define __NR_listxattr 230
4717 +#define __NR_llistxattr 231
4718 +#define __NR_flistxattr 232
4719 +#define __NR_removexattr 233
4720 +#define __NR_lremovexattr 234
4721 +#define __NR_fremovexattr 235
4722 #define __NR_gettid 236
4723 #define __NR_tkill 237
4725 --- linux/include/asm-s390x/unistd.h~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:45 2002
4726 +++ linux-mmonroe/include/asm-s390x/unistd.h Fri May 16 08:43:01 2003
4727 @@ -180,9 +180,18 @@
4728 #define __NR_pivot_root 217
4729 #define __NR_mincore 218
4730 #define __NR_madvise 219
4732 - * Numbers 224-235 are reserved for posix acl
4734 +#define __NR_setxattr 224
4735 +#define __NR_lsetxattr 225
4736 +#define __NR_fsetxattr 226
4737 +#define __NR_getxattr 227
4738 +#define __NR_lgetxattr 228
4739 +#define __NR_fgetxattr 229
4740 +#define __NR_listxattr 230
4741 +#define __NR_llistxattr 231
4742 +#define __NR_flistxattr 232
4743 +#define __NR_removexattr 233
4744 +#define __NR_lremovexattr 234
4745 +#define __NR_fremovexattr 235
4746 #define __NR_gettid 236
4747 #define __NR_tkill 237
4749 --- linux/include/asm-sparc/unistd.h~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:45 2002
4750 +++ linux-mmonroe/include/asm-sparc/unistd.h Fri May 16 08:43:01 2003
4751 @@ -184,24 +184,24 @@
4752 /* #define __NR_exportfs 166 SunOS Specific */
4753 #define __NR_mount 167 /* Common */
4754 #define __NR_ustat 168 /* Common */
4755 -/* #define __NR_semsys 169 SunOS Specific */
4756 -/* #define __NR_msgsys 170 SunOS Specific */
4757 -/* #define __NR_shmsys 171 SunOS Specific */
4758 -/* #define __NR_auditsys 172 SunOS Specific */
4759 -/* #define __NR_rfssys 173 SunOS Specific */
4760 +#define __NR_setxattr 169 /* SunOS: semsys */
4761 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4762 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4763 +#define __NR_getxattr 172 /* SunOS: auditsys */
4764 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4765 #define __NR_getdents 174 /* Common */
4766 #define __NR_setsid 175 /* Common */
4767 #define __NR_fchdir 176 /* Common */
4768 -/* #define __NR_fchroot 177 SunOS Specific */
4769 -/* #define __NR_vpixsys 178 SunOS Specific */
4770 -/* #define __NR_aioread 179 SunOS Specific */
4771 -/* #define __NR_aiowrite 180 SunOS Specific */
4772 -/* #define __NR_aiowait 181 SunOS Specific */
4773 -/* #define __NR_aiocancel 182 SunOS Specific */
4774 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4775 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4776 +#define __NR_llistxattr 179 /* SunOS: aioread */
4777 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4778 +#define __NR_removexattr 181 /* SunOS: aiowait */
4779 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4780 #define __NR_sigpending 183 /* Common */
4781 #define __NR_query_module 184 /* Linux Specific */
4782 #define __NR_setpgid 185 /* Common */
4783 -/* #define __NR_pathconf 186 SunOS Specific */
4784 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4785 #define __NR_tkill 187 /* SunOS: fpathconf */
4786 /* #define __NR_sysconf 188 SunOS Specific */
4787 #define __NR_uname 189 /* Linux Specific */
4788 --- linux/include/asm-sparc64/unistd.h~linux-2.4.20-xattr-0.8.54-hp Fri Aug 2 17:39:45 2002
4789 +++ linux-mmonroe/include/asm-sparc64/unistd.h Fri May 16 08:43:01 2003
4790 @@ -184,24 +184,24 @@
4791 /* #define __NR_exportfs 166 SunOS Specific */
4792 #define __NR_mount 167 /* Common */
4793 #define __NR_ustat 168 /* Common */
4794 -/* #define __NR_semsys 169 SunOS Specific */
4795 -/* #define __NR_msgsys 170 SunOS Specific */
4796 -/* #define __NR_shmsys 171 SunOS Specific */
4797 -/* #define __NR_auditsys 172 SunOS Specific */
4798 -/* #define __NR_rfssys 173 SunOS Specific */
4799 +#define __NR_setxattr 169 /* SunOS: semsys */
4800 +#define __NR_lsetxattr 170 /* SunOS: msgsys */
4801 +#define __NR_fsetxattr 171 /* SunOS: shmsys */
4802 +#define __NR_getxattr 172 /* SunOS: auditsys */
4803 +#define __NR_lgetxattr 173 /* SunOS: rfssys */
4804 #define __NR_getdents 174 /* Common */
4805 #define __NR_setsid 175 /* Common */
4806 #define __NR_fchdir 176 /* Common */
4807 -/* #define __NR_fchroot 177 SunOS Specific */
4808 -/* #define __NR_vpixsys 178 SunOS Specific */
4809 -/* #define __NR_aioread 179 SunOS Specific */
4810 -/* #define __NR_aiowrite 180 SunOS Specific */
4811 -/* #define __NR_aiowait 181 SunOS Specific */
4812 -/* #define __NR_aiocancel 182 SunOS Specific */
4813 +#define __NR_fgetxattr 177 /* SunOS: fchroot */
4814 +#define __NR_listxattr 178 /* SunOS: vpixsys */
4815 +#define __NR_llistxattr 179 /* SunOS: aioread */
4816 +#define __NR_flistxattr 180 /* SunOS: aiowrite */
4817 +#define __NR_removexattr 181 /* SunOS: aiowait */
4818 +#define __NR_lremovexattr 182 /* SunOS: aiocancel */
4819 #define __NR_sigpending 183 /* Common */
4820 #define __NR_query_module 184 /* Linux Specific */
4821 #define __NR_setpgid 185 /* Common */
4822 -/* #define __NR_pathconf 186 SunOS Specific */
4823 +#define __NR_fremovexattr 186 /* SunOS: pathconf */
4824 #define __NR_tkill 187 /* SunOS: fpathconf */
4825 /* #define __NR_sysconf 188 SunOS Specific */
4826 #define __NR_uname 189 /* Linux Specific */
4827 --- /dev/null Mon May 20 21:11:23 2002
4828 +++ linux-mmonroe/include/linux/cache_def.h Fri May 16 08:43:01 2003
4831 + * linux/cache_def.h
4832 + * Handling of caches defined in drivers, filesystems, ...
4834 + * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
4837 +struct cache_definition {
4839 + void (*shrink)(int, unsigned int);
4840 + struct list_head link;
4843 +extern void register_cache(struct cache_definition *);
4844 +extern void unregister_cache(struct cache_definition *);
4845 --- linux/include/linux/errno.h~linux-2.4.20-xattr-0.8.54-hp Fri Feb 9 14:46:13 2001
4846 +++ linux-mmonroe/include/linux/errno.h Fri May 16 08:43:01 2003
4851 +/* Defined for extended attributes */
4852 +#define ENOATTR ENODATA /* No such attribute */
4853 +#define ENOTSUP EOPNOTSUPP /* Operation not supported */
4856 --- linux/include/linux/ext2_fs.h~linux-2.4.20-xattr-0.8.54-hp Thu Nov 22 11:46:52 2001
4857 +++ linux-mmonroe/include/linux/ext2_fs.h Fri May 16 08:43:01 2003
4860 #define EXT2_BAD_INO 1 /* Bad blocks inode */
4861 #define EXT2_ROOT_INO 2 /* Root inode */
4862 -#define EXT2_ACL_IDX_INO 3 /* ACL inode */
4863 -#define EXT2_ACL_DATA_INO 4 /* ACL inode */
4864 #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
4865 #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
4869 # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
4871 -#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
4872 #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
4874 # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
4875 @@ -121,28 +118,6 @@
4881 -struct ext2_acl_header /* Header of Access Control Lists */
4884 - __u32 aclh_file_count;
4885 - __u32 aclh_acle_count;
4886 - __u32 aclh_first_acle;
4889 -struct ext2_acl_entry /* Access Control List Entry */
4892 - __u16 acle_perms; /* Access permissions */
4893 - __u16 acle_type; /* Type of entry */
4894 - __u16 acle_tag; /* User or group identity */
4896 - __u32 acle_next; /* Pointer on next entry for the */
4897 - /* same inode or on next free entry */
4901 * Structure of a blocks group descriptor
4903 struct ext2_group_desc
4904 @@ -314,6 +289,7 @@ struct ext2_inode {
4905 #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
4906 #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
4907 #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
4908 +#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
4910 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
4911 #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
4912 @@ -397,6 +373,7 @@ struct ext2_super_block {
4915 #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
4916 +#define EXT2_I(inode) (&((inode)->u.ext2_i))
4918 /* Assume that user mode programs are passing in an ext2fs superblock, not
4919 * a kernel struct super_block. This will allow us to call the feature-test
4920 @@ -466,7 +443,7 @@ struct ext2_super_block {
4921 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
4922 #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
4924 -#define EXT2_FEATURE_COMPAT_SUPP 0
4925 +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
4926 #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
4927 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
4928 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
4929 @@ -623,8 +600,10 @@ extern struct address_space_operations e
4932 extern struct inode_operations ext2_dir_inode_operations;
4933 +extern struct inode_operations ext2_special_inode_operations;
4936 +extern struct inode_operations ext2_symlink_inode_operations;
4937 extern struct inode_operations ext2_fast_symlink_inode_operations;
4939 #endif /* __KERNEL__ */
4940 --- /dev/null Mon May 20 21:11:23 2002
4941 +++ linux-mmonroe/include/linux/ext2_xattr.h Fri May 16 08:43:01 2003
4944 + File: linux/ext2_xattr.h
4946 + On-disk format of extended attributes for the ext2 filesystem.
4948 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4951 +#include <linux/config.h>
4952 +#include <linux/init.h>
4953 +#include <linux/xattr.h>
4955 +/* Magic value in attribute blocks */
4956 +#define EXT2_XATTR_MAGIC 0xEA020000
4958 +/* Maximum number of references to one attribute block */
4959 +#define EXT2_XATTR_REFCOUNT_MAX 1024
4962 +#define EXT2_XATTR_INDEX_MAX 10
4963 +#define EXT2_XATTR_INDEX_USER 1
4964 +#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
4965 +#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
4967 +struct ext2_xattr_header {
4968 + __u32 h_magic; /* magic number for identification */
4969 + __u32 h_refcount; /* reference count */
4970 + __u32 h_blocks; /* number of disk blocks used */
4971 + __u32 h_hash; /* hash value of all attributes */
4972 + __u32 h_reserved[4]; /* zero right now */
4975 +struct ext2_xattr_entry {
4976 + __u8 e_name_len; /* length of name */
4977 + __u8 e_name_index; /* attribute name index */
4978 + __u16 e_value_offs; /* offset in disk block of value */
4979 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
4980 + __u32 e_value_size; /* size of attribute value */
4981 + __u32 e_hash; /* hash value of name and value */
4982 + char e_name[0]; /* attribute name */
4985 +#define EXT2_XATTR_PAD_BITS 2
4986 +#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
4987 +#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
4988 +#define EXT2_XATTR_LEN(name_len) \
4989 + (((name_len) + EXT2_XATTR_ROUND + \
4990 + sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
4991 +#define EXT2_XATTR_NEXT(entry) \
4992 + ( (struct ext2_xattr_entry *)( \
4993 + (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
4994 +#define EXT2_XATTR_SIZE(size) \
4995 + (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
4999 +# ifdef CONFIG_EXT2_FS_XATTR
5001 +struct ext2_xattr_handler {
5003 + size_t (*list)(char *list, struct inode *inode, const char *name,
5005 + int (*get)(struct inode *inode, const char *name, void *buffer,
5007 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5008 + size_t size, int flags);
5011 +extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
5012 +extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
5014 +extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
5015 +extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
5016 +extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
5017 +extern int ext2_removexattr(struct dentry *, const char *);
5019 +extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
5020 +extern int ext2_xattr_list(struct inode *, char *, size_t);
5021 +extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
5023 +extern void ext2_xattr_delete_inode(struct inode *);
5024 +extern void ext2_xattr_put_super(struct super_block *);
5026 +extern int init_ext2_xattr(void) __init;
5027 +extern void exit_ext2_xattr(void);
5029 +# else /* CONFIG_EXT2_FS_XATTR */
5030 +# define ext2_setxattr NULL
5031 +# define ext2_getxattr NULL
5032 +# define ext2_listxattr NULL
5033 +# define ext2_removexattr NULL
5036 +ext2_xattr_get(struct inode *inode, int name_index,
5037 + const char *name, void *buffer, size_t size)
5043 +ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
5049 +ext2_xattr_set(struct inode *inode, int name_index, const char *name,
5050 + const void *value, size_t size, int flags)
5056 +ext2_xattr_delete_inode(struct inode *inode)
5061 +ext2_xattr_put_super(struct super_block *sb)
5066 +init_ext2_xattr(void)
5072 +exit_ext2_xattr(void)
5076 +# endif /* CONFIG_EXT2_FS_XATTR */
5078 +# ifdef CONFIG_EXT2_FS_XATTR_USER
5080 +extern int init_ext2_xattr_user(void) __init;
5081 +extern void exit_ext2_xattr_user(void);
5083 +# else /* CONFIG_EXT2_FS_XATTR_USER */
5086 +init_ext2_xattr_user(void)
5092 +exit_ext2_xattr_user(void)
5096 +# endif /* CONFIG_EXT2_FS_XATTR_USER */
5098 +#endif /* __KERNEL__ */
5100 --- linux/include/linux/ext3_fs.h~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:47 2003
5101 +++ linux-mmonroe/include/linux/ext3_fs.h Fri May 16 08:43:01 2003
5104 #define EXT3_BAD_INO 1 /* Bad blocks inode */
5105 #define EXT3_ROOT_INO 2 /* Root inode */
5106 -#define EXT3_ACL_IDX_INO 3 /* ACL inode */
5107 -#define EXT3_ACL_DATA_INO 4 /* ACL inode */
5108 #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
5109 #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
5110 #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
5113 # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
5115 -#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
5116 #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
5118 # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
5119 @@ -129,28 +126,6 @@
5125 -struct ext3_acl_header /* Header of Access Control Lists */
5128 - __u32 aclh_file_count;
5129 - __u32 aclh_acle_count;
5130 - __u32 aclh_first_acle;
5133 -struct ext3_acl_entry /* Access Control List Entry */
5136 - __u16 acle_perms; /* Access permissions */
5137 - __u16 acle_type; /* Type of entry */
5138 - __u16 acle_tag; /* User or group identity */
5140 - __u32 acle_next; /* Pointer on next entry for the */
5141 - /* same inode or on next free entry */
5145 * Structure of a blocks group descriptor
5147 struct ext3_group_desc
5148 @@ -344,6 +319,7 @@ struct ext3_inode {
5149 #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
5150 #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
5151 #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
5152 +#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
5154 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
5155 #ifndef _LINUX_EXT2_FS_H
5156 @@ -520,7 +496,7 @@ struct ext3_super_block {
5157 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
5158 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
5160 -#define EXT3_FEATURE_COMPAT_SUPP 0
5161 +#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
5162 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
5163 EXT3_FEATURE_INCOMPAT_RECOVER)
5164 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
5165 @@ -703,6 +679,7 @@ extern void ext3_check_inodes_bitmap (st
5166 extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
5169 +extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
5170 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
5171 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
5173 @@ -771,8 +748,10 @@ extern struct address_space_operations e
5176 extern struct inode_operations ext3_dir_inode_operations;
5177 +extern struct inode_operations ext3_special_inode_operations;
5180 +extern struct inode_operations ext3_symlink_inode_operations;
5181 extern struct inode_operations ext3_fast_symlink_inode_operations;
5184 --- linux/include/linux/ext3_jbd.h~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003
5185 +++ linux-mmonroe/include/linux/ext3_jbd.h Fri May 16 08:43:01 2003
5188 #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
5190 +/* Extended attributes may touch two data buffers, two bitmap buffers,
5191 + * and two group and summaries. */
5193 +#define EXT3_XATTR_TRANS_BLOCKS 8
5195 /* Define the minimum size for a transaction which modifies data. This
5196 * needs to take into account the fact that we may end up modifying two
5197 * quota files too (one for the group, one for the user quota). The
5198 * superblock only gets updated once, of course, so don't bother
5199 * counting that again for the quota updates. */
5201 -#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
5202 +#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
5203 + EXT3_XATTR_TRANS_BLOCKS - 2)
5205 extern int ext3_writepage_trans_blocks(struct inode *inode);
5207 --- /dev/null Mon May 20 21:11:23 2002
5208 +++ linux-mmonroe/include/linux/ext3_xattr.h Fri May 16 08:43:01 2003
5211 + File: linux/ext3_xattr.h
5213 + On-disk format of extended attributes for the ext3 filesystem.
5215 + (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5218 +#include <linux/config.h>
5219 +#include <linux/init.h>
5220 +#include <linux/xattr.h>
5222 +/* Magic value in attribute blocks */
5223 +#define EXT3_XATTR_MAGIC 0xEA020000
5225 +/* Maximum number of references to one attribute block */
5226 +#define EXT3_XATTR_REFCOUNT_MAX 1024
5229 +#define EXT3_XATTR_INDEX_MAX 10
5230 +#define EXT3_XATTR_INDEX_USER 1
5231 +#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
5232 +#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
5234 +struct ext3_xattr_header {
5235 + __u32 h_magic; /* magic number for identification */
5236 + __u32 h_refcount; /* reference count */
5237 + __u32 h_blocks; /* number of disk blocks used */
5238 + __u32 h_hash; /* hash value of all attributes */
5239 + __u32 h_reserved[4]; /* zero right now */
5242 +struct ext3_xattr_entry {
5243 + __u8 e_name_len; /* length of name */
5244 + __u8 e_name_index; /* attribute name index */
5245 + __u16 e_value_offs; /* offset in disk block of value */
5246 + __u32 e_value_block; /* disk block attribute is stored on (n/i) */
5247 + __u32 e_value_size; /* size of attribute value */
5248 + __u32 e_hash; /* hash value of name and value */
5249 + char e_name[0]; /* attribute name */
5252 +#define EXT3_XATTR_PAD_BITS 2
5253 +#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
5254 +#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
5255 +#define EXT3_XATTR_LEN(name_len) \
5256 + (((name_len) + EXT3_XATTR_ROUND + \
5257 + sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
5258 +#define EXT3_XATTR_NEXT(entry) \
5259 + ( (struct ext3_xattr_entry *)( \
5260 + (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
5261 +#define EXT3_XATTR_SIZE(size) \
5262 + (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
5266 +# ifdef CONFIG_EXT3_FS_XATTR
5268 +struct ext3_xattr_handler {
5270 + size_t (*list)(char *list, struct inode *inode, const char *name,
5272 + int (*get)(struct inode *inode, const char *name, void *buffer,
5274 + int (*set)(struct inode *inode, const char *name, const void *buffer,
5275 + size_t size, int flags);
5278 +extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
5279 +extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
5281 +extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
5282 +extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
5283 +extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
5284 +extern int ext3_removexattr(struct dentry *, const char *);
5286 +extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
5287 +extern int ext3_xattr_list(struct inode *, char *, size_t);
5288 +extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
5290 +extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
5291 +extern void ext3_xattr_put_super(struct super_block *);
5293 +extern int init_ext3_xattr(void) __init;
5294 +extern void exit_ext3_xattr(void);
5296 +# else /* CONFIG_EXT3_FS_XATTR */
5297 +# define ext3_setxattr NULL
5298 +# define ext3_getxattr NULL
5299 +# define ext3_listxattr NULL
5300 +# define ext3_removexattr NULL
5303 +ext3_xattr_get(struct inode *inode, int name_index, const char *name,
5304 + void *buffer, size_t size)
5310 +ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
5316 +ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
5317 + const char *name, const void *value, size_t size, int flags)
5323 +ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
5328 +ext3_xattr_put_super(struct super_block *sb)
5333 +init_ext3_xattr(void)
5339 +exit_ext3_xattr(void)
5343 +# endif /* CONFIG_EXT3_FS_XATTR */
5345 +# ifdef CONFIG_EXT3_FS_XATTR_USER
5347 +extern int init_ext3_xattr_user(void) __init;
5348 +extern void exit_ext3_xattr_user(void);
5350 +# else /* CONFIG_EXT3_FS_XATTR_USER */
5353 +init_ext3_xattr_user(void)
5359 +exit_ext3_xattr_user(void)
5363 +#endif /* CONFIG_EXT3_FS_XATTR_USER */
5365 +#endif /* __KERNEL__ */
5367 --- linux/include/linux/fs.h~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003
5368 +++ linux-mmonroe/include/linux/fs.h Fri May 16 08:43:01 2003
5369 @@ -909,7 +909,7 @@ struct inode_operations {
5370 int (*setattr) (struct dentry *, struct iattr *);
5371 int (*setattr_raw) (struct inode *, struct iattr *);
5372 int (*getattr) (struct dentry *, struct iattr *);
5373 - int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
5374 + int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5375 ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5376 ssize_t (*listxattr) (struct dentry *, char *, size_t);
5377 int (*removexattr) (struct dentry *, const char *);
5378 --- /dev/null Mon May 20 21:11:23 2002
5379 +++ linux-mmonroe/include/linux/mbcache.h Fri May 16 08:43:01 2003
5382 + File: linux/mbcache.h
5384 + (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5387 +/* Hardwire the number of additional indexes */
5388 +#define MB_CACHE_INDEXES_COUNT 1
5390 +struct mb_cache_entry;
5392 +struct mb_cache_op {
5393 + int (*free)(struct mb_cache_entry *, int);
5397 + struct list_head c_cache_list;
5398 + const char *c_name;
5399 + struct mb_cache_op c_op;
5400 + atomic_t c_entry_count;
5401 + int c_bucket_count;
5402 +#ifndef MB_CACHE_INDEXES_COUNT
5403 + int c_indexes_count;
5405 + kmem_cache_t *c_entry_cache;
5406 + struct list_head *c_block_hash;
5407 + struct list_head *c_indexes_hash[0];
5410 +struct mb_cache_entry_index {
5411 + struct list_head o_list;
5412 + unsigned int o_key;
5415 +struct mb_cache_entry {
5416 + struct list_head e_lru_list;
5417 + struct mb_cache *e_cache;
5420 + unsigned long e_block;
5421 + struct list_head e_block_list;
5422 + struct mb_cache_entry_index e_indexes[0];
5425 +/* Functions on caches */
5427 +struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
5429 +void mb_cache_shrink(struct mb_cache *, kdev_t);
5430 +void mb_cache_destroy(struct mb_cache *);
5432 +/* Functions on cache entries */
5434 +struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
5435 +int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
5437 +void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
5438 +void mb_cache_entry_release(struct mb_cache_entry *);
5439 +void mb_cache_entry_takeout(struct mb_cache_entry *);
5440 +void mb_cache_entry_free(struct mb_cache_entry *);
5441 +struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
5442 +struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
5444 +#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
5445 +struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
5446 + kdev_t, unsigned int);
5447 +struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
5448 + kdev_t, unsigned int);
5450 --- linux/kernel/ksyms.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:45 2003
5451 +++ linux-mmonroe/kernel/ksyms.c Fri May 16 08:43:52 2003
5454 #include <linux/config.h>
5455 #include <linux/slab.h>
5456 +#include <linux/cache_def.h>
5457 #include <linux/module.h>
5458 #include <linux/blkdev.h>
5459 #include <linux/cdrom.h>
5460 @@ -106,6 +107,7 @@ EXPORT_SYMBOL(exit_mm);
5461 EXPORT_SYMBOL(exit_files);
5462 EXPORT_SYMBOL(exit_fs);
5463 EXPORT_SYMBOL(exit_sighand);
5464 +EXPORT_SYMBOL(copy_fs_struct);
5465 EXPORT_SYMBOL_GPL(make_pages_present);
5467 /* internal kernel memory management */
5468 @@ -126,6 +128,8 @@ EXPORT_SYMBOL(kmem_cache_validate);
5469 EXPORT_SYMBOL(kmem_cache_alloc);
5470 EXPORT_SYMBOL(kmem_cache_free);
5471 EXPORT_SYMBOL(kmem_cache_size);
5472 +EXPORT_SYMBOL(register_cache);
5473 +EXPORT_SYMBOL(unregister_cache);
5474 EXPORT_SYMBOL(kmalloc);
5475 EXPORT_SYMBOL(kfree);
5476 EXPORT_SYMBOL(vfree);
5477 --- linux/mm/vmscan.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:23 2003
5478 +++ linux-mmonroe/mm/vmscan.c Fri May 16 08:43:01 2003
5480 #include <linux/kernel_stat.h>
5481 #include <linux/swap.h>
5482 #include <linux/swapctl.h>
5483 +#include <linux/cache_def.h>
5484 #include <linux/smp_lock.h>
5485 #include <linux/pagemap.h>
5486 #include <linux/init.h>
5489 #define DEF_PRIORITY (6)
5491 +static DECLARE_MUTEX(other_caches_sem);
5492 +static LIST_HEAD(cache_definitions);
5494 +void register_cache(struct cache_definition *cache)
5496 + down(&other_caches_sem);
5497 + list_add(&cache->link, &cache_definitions);
5498 + up(&other_caches_sem);
5501 +void unregister_cache(struct cache_definition *cache)
5503 + down(&other_caches_sem);
5504 + list_del(&cache->link);
5505 + up(&other_caches_sem);
5508 +static void shrink_other_caches(unsigned int priority, int gfp_mask)
5510 + struct list_head *p;
5512 + if (down_trylock(&other_caches_sem))
5515 + list_for_each_prev(p, &cache_definitions) {
5516 + struct cache_definition *cache =
5517 + list_entry(p, struct cache_definition, link);
5519 + cache->shrink(priority, gfp_mask);
5521 + up(&other_caches_sem);
5525 * The swap-out function returns 1 if it successfully
5526 * scanned all the pages it was asked to (`count').
5527 @@ -579,6 +613,7 @@ static int shrink_caches(zone_t * classz
5529 shrink_dcache_memory(priority, gfp_mask);
5530 shrink_icache_memory(priority, gfp_mask);
5531 + shrink_other_caches(priority, gfp_mask);
5533 shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);