Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 35819 | Differences between
and this patch

Collapse All | Expand All

(-)linux-2.4.22-ppc-dev.orig/Documentation/Configure.help (+106 lines)
Lines 13024-13029 Link Here
13024
  The module will be called isp16.o. If you want to compile it as a
13024
  The module will be called isp16.o. If you want to compile it as a
13025
  module, say M here and read <file:Documentation/modules.txt>.
13025
  module, say M here and read <file:Documentation/modules.txt>.
13026
13026
13027
Posix Access Control Lists
13028
CONFIG_FS_POSIX_ACL
13029
  Posix Access Control Lists (ACLs) support permissions for users and
13030
  groups beyond the owner/group/world scheme.
13031
13032
  To learn more about Access Control Lists, visit the Posix ACLs for
13033
  Linux website <http://acl.bestbits.at/>.
13034
13035
  If you plan to use Access Control Lists, you may also need the
13036
  getfacl and setfacl utilities, along with some additional patches
13037
  from the website.
13038
13039
  If you don't know what Access Control Lists are, say N.
13040
13027
iSeries Virtual I/O CD Support
13041
iSeries Virtual I/O CD Support
13028
CONFIG_VIOCD
13042
CONFIG_VIOCD
13029
  If you are running Linux on an IBM iSeries system and you want to
13043
  If you are running Linux on an IBM iSeries system and you want to
Lines 15627-15632 Link Here
15627
  be compiled as a module, and so this could be dangerous.  Most
15641
  be compiled as a module, and so this could be dangerous.  Most
15628
  everyone wants to say Y here.
15642
  everyone wants to say Y here.
15629
15643
15644
Ext2 extended attributes
15645
CONFIG_EXT2_FS_XATTR
15646
  Extended attributes are name:value pairs associated with inodes by
15647
  the kernel or by users (see the attr(5) manual page, or visit
15648
  <http://acl.bestbits.at/> for details).
15649
15650
  You need this for POSIX ACL support on ext2.
15651
15652
  If unsure, say N.
15653
15654
Ext2 extended attribute block sharing
15655
CONFIG_EXT2_FS_XATTR_SHARING
15656
  This options enables code for sharing identical extended attribute
15657
  blocks among multiple inodes.
15658
15659
  Usually, say Y.
15660
15661
Ext2 extended user attributes
15662
CONFIG_EXT2_FS_XATTR_USER
15663
  This option enables extended user attributes on ext2. Processes can
15664
  associate extended user attributes with inodes to store additional
15665
  information such as the character encoding of files, etc. (see the
15666
  attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
15667
15668
  If unsure, say N.
15669
15670
Ext2 POSIX Access Control Lists
15671
CONFIG_EXT2_FS_POSIX_ACL
15672
  POSIX Access Control Lists (ACLs) support permissions for users and
15673
  groups beyond the owner/group/world scheme. This option enables
15674
  POSIX ACLs on ext2.
15675
15676
  To learn more about Access Control Lists, visit the Posix ACLs for
15677
  Linux website <http://acl.bestbits.at/>.
15678
15679
  If unsure, say N.
15680
15630
Ext3 journalling file system support (EXPERIMENTAL)
15681
Ext3 journalling file system support (EXPERIMENTAL)
15631
CONFIG_EXT3_FS
15682
CONFIG_EXT3_FS
15632
  This is the journalling version of the Second extended file system
15683
  This is the journalling version of the Second extended file system
Lines 15659-15664 Link Here
15659
  of your root partition (the one containing the directory /) cannot
15710
  of your root partition (the one containing the directory /) cannot
15660
  be compiled as a module, and so this may be dangerous.
15711
  be compiled as a module, and so this may be dangerous.
15661
15712
15713
Ext3 extended attributes
15714
CONFIG_EXT3_FS_XATTR
15715
  Extended attributes are name:value pairs associated with inodes by
15716
  the kernel or by users (see the attr(5) manual page, or visit
15717
  <http://acl.bestbits.at/> for details).
15718
15719
  You need this for POSIX ACL support on ext3.
15720
15721
  If unsure, say N.
15722
15723
Ext3 extended attribute block sharing
15724
CONFIG_EXT3_FS_XATTR_SHARING
15725
  This options enables code for sharing identical extended attribute
15726
  blocks among multiple inodes.
15727
15728
  Usually, say Y.
15729
15730
Ext3 extended user attributes
15731
CONFIG_EXT3_FS_XATTR_USER
15732
  This option enables extended user attributes on ext3. Processes can
15733
  associate extended user attributes with inodes to store additional
15734
  information such as the character encoding of files, etc. (see the
15735
  attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
15736
15737
  If unsure, say N.
15738
15739
Ext3 POSIX Access Control Lists
15740
CONFIG_EXT3_FS_POSIX_ACL
15741
  POSIX Access Control Lists (ACLs) support permissions for users and
15742
  groups beyond the owner/group/world scheme. This option enables
15743
  POSIX ACLs on ext3.
15744
15745
  To learn more about Access Control Lists, visit the Posix ACLs for
15746
  Linux website <http://acl.bestbits.at/>.
15747
15748
  If unsure, say N.
15749
15662
Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
15750
Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
15663
CONFIG_JBD
15751
CONFIG_JBD
15664
  This is a generic journalling layer for block devices.  It is
15752
  This is a generic journalling layer for block devices.  It is
Lines 16153-16158 Link Here
16153
16241
16154
  If unsure, say N.
16242
  If unsure, say N.
16155
16243
16244
Solaris ACL RPCs
16245
CONFIG_NFS_ACL
16246
  Allows manipulating POSIX Access Control Lists on NFS file systems
16247
  on NFS servers that implement the GETACL and SETACL extensions also
16248
  found in Solaris NFSv3. On Linux NFS servers the CONFIG_NFSD_ACL
16249
  option implements these extensions.
16250
16251
  In doubt say N.
16252
16156
Root file system on NFS
16253
Root file system on NFS
16157
CONFIG_ROOT_NFS
16254
CONFIG_ROOT_NFS
16158
  If you want your Linux box to mount its whole root file system (the
16255
  If you want your Linux box to mount its whole root file system (the
Lines 16197-16202 Link Here
16197
  If you would like to include the NFSv3 server as well as the NFSv2
16294
  If you would like to include the NFSv3 server as well as the NFSv2
16198
  server, say Y here.  If unsure, say Y.
16295
  server, say Y here.  If unsure, say Y.
16199
16296
16297
Solaris ACL RPCs
16298
CONFIG_NFSD_ACL
16299
  Allows manipulating POSIX Access Control Lists on exported file
16300
  systems. The client(s) must implement the GETACL and SETACL
16301
  extensions of Solaris NFSv3 in order to use these extensions. The
16302
  CONFIG_NFS_ACL option enables this.
16303
16304
  In doubt say N.
16305
16200
Provide NFS over TCP server support EXPERIMENTAL
16306
Provide NFS over TCP server support EXPERIMENTAL
16201
CONFIG_NFSD_TCP
16307
CONFIG_NFSD_TCP
16202
  Enable NFS service over TCP connections.  This the officially
16308
  Enable NFS service over TCP connections.  This the officially
(-)linux-2.4.22-ppc-dev.orig/Documentation/filesystems/Locking (-2 / +2 lines)
Lines 69-76 Link Here
69
getattr:						(see below)
69
getattr:						(see below)
70
revalidate:	no					(see below)
70
revalidate:	no					(see below)
71
setxattr:	yes	yes		no
71
setxattr:	yes	yes		no
72
getxattr:	yes	yes		no
72
getxattr:	yes	no		no
73
listxattr:	yes	yes		no
73
listxattr:	yes	no		no
74
removexattr:	yes	yes		no
74
removexattr:	yes	yes		no
75
	Additionally, ->rmdir() has i_zombie on victim and so does ->rename()
75
	Additionally, ->rmdir() has i_zombie on victim and so does ->rename()
76
in case when target exists and is a directory.
76
in case when target exists and is a directory.
(-)linux-2.4.22-ppc-dev.orig/arch/alpha/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
CONFIG_ALPHA=y
14
CONFIG_ALPHA=y
5
# CONFIG_UID16 is not set
15
# CONFIG_UID16 is not set
6
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
16
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
(-)linux-2.4.22-ppc-dev.orig/arch/alpha/kernel/entry.S (-1 / +13 lines)
Lines 10-16 Link Here
10
10
11
#define SIGCHLD 20
11
#define SIGCHLD 20
12
12
13
#define NR_SYSCALLS 382
13
#define NR_SYSCALLS 394
14
14
15
/*
15
/*
16
 * These offsets must match with alpha_mv in <asm/machvec.h>.
16
 * These offsets must match with alpha_mv in <asm/machvec.h>.
Lines 1154-1159 Link Here
1154
	.quad sys_readahead
1154
	.quad sys_readahead
1155
	.quad sys_ni_syscall			/* 380, sys_security */
1155
	.quad sys_ni_syscall			/* 380, sys_security */
1156
	.quad sys_tkill
1156
	.quad sys_tkill
1157
	.quad sys_setxattr
1158
	.quad sys_lsetxattr
1159
	.quad sys_fsetxattr
1160
	.quad sys_getxattr			/* 385 */
1161
	.quad sys_lgetxattr
1162
	.quad sys_fgetxattr
1163
	.quad sys_listxattr
1164
	.quad sys_llistxattr
1165
	.quad sys_flistxattr			/* 390 */
1166
	.quad sys_removexattr
1167
	.quad sys_lremovexattr
1168
	.quad sys_fremovexattr
1157
1169
1158
/* Remember to update everything, kids.  */
1170
/* Remember to update everything, kids.  */
1159
.ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
1171
.ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
(-)linux-2.4.22-ppc-dev.orig/arch/arm/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
CONFIG_ARM=y
14
CONFIG_ARM=y
5
# CONFIG_EISA is not set
15
# CONFIG_EISA is not set
6
# CONFIG_SBUS is not set
16
# CONFIG_SBUS is not set
(-)linux-2.4.22-ppc-dev.orig/arch/arm/kernel/calls.S (-12 / +12 lines)
Lines 240-257 Link Here
240
		.long	SYMBOL_NAME(sys_ni_syscall) /* Security */
240
		.long	SYMBOL_NAME(sys_ni_syscall) /* Security */
241
		.long	SYMBOL_NAME(sys_gettid)
241
		.long	SYMBOL_NAME(sys_gettid)
242
/* 225 */	.long	SYMBOL_NAME(sys_readahead)
242
/* 225 */	.long	SYMBOL_NAME(sys_readahead)
243
		.long	SYMBOL_NAME(sys_ni_syscall) /* setxattr */
243
		.long	SYMBOL_NAME(sys_setxattr)
244
		.long	SYMBOL_NAME(sys_ni_syscall) /* lsetxattr */
244
		.long	SYMBOL_NAME(sys_lsetxattr)
245
		.long	SYMBOL_NAME(sys_ni_syscall) /* fsetxattr */
245
		.long	SYMBOL_NAME(sys_fsetxattr)
246
		.long	SYMBOL_NAME(sys_ni_syscall) /* getxattr */
246
		.long	SYMBOL_NAME(sys_getxattr)
247
/* 230 */	.long	SYMBOL_NAME(sys_ni_syscall) /* lgetxattr */
247
/* 230 */	.long	SYMBOL_NAME(sys_lgetxattr)
248
		.long	SYMBOL_NAME(sys_ni_syscall) /* fgetxattr */
248
		.long	SYMBOL_NAME(sys_fgetxattr)
249
		.long	SYMBOL_NAME(sys_ni_syscall) /* listxattr */
249
		.long	SYMBOL_NAME(sys_listxattr)
250
		.long	SYMBOL_NAME(sys_ni_syscall) /* llistxattr */
250
		.long	SYMBOL_NAME(sys_llistxattr)
251
		.long	SYMBOL_NAME(sys_ni_syscall) /* flistxattr */
251
		.long	SYMBOL_NAME(sys_flistxattr)
252
/* 235 */	.long	SYMBOL_NAME(sys_ni_syscall) /* removexattr */
252
/* 235 */	.long	SYMBOL_NAME(sys_removexattr)
253
		.long	SYMBOL_NAME(sys_ni_syscall) /* lremovexattr */
253
		.long	SYMBOL_NAME(sys_lremovexattr)
254
		.long	SYMBOL_NAME(sys_ni_syscall) /* fremovexattr */
254
		.long	SYMBOL_NAME(sys_fremovexattr)
255
		.long	SYMBOL_NAME(sys_tkill)
255
		.long	SYMBOL_NAME(sys_tkill)
256
		.long	SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */
256
		.long	SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */
257
/* 240 */	.long	SYMBOL_NAME(sys_ni_syscall) /* futex */
257
/* 240 */	.long	SYMBOL_NAME(sys_ni_syscall) /* futex */
(-)linux-2.4.22-ppc-dev.orig/arch/i386/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
CONFIG_X86=y
14
CONFIG_X86=y
5
CONFIG_ISA=y
15
CONFIG_ISA=y
6
# CONFIG_SBUS is not set
16
# CONFIG_SBUS is not set
(-)linux-2.4.22-ppc-dev.orig/arch/ia64/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
14
5
#
15
#
6
# Code maturity level options
16
# Code maturity level options
(-)linux-2.4.22-ppc-dev.orig/arch/m68k/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
CONFIG_UID16=y
14
CONFIG_UID16=y
5
15
6
#
16
#
(-)linux-2.4.22-ppc-dev.orig/arch/mips/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
CONFIG_MIPS=y
14
CONFIG_MIPS=y
5
CONFIG_MIPS32=y
15
CONFIG_MIPS32=y
6
# CONFIG_MIPS64 is not set
16
# CONFIG_MIPS64 is not set
(-)linux-2.4.22-ppc-dev.orig/arch/mips64/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
CONFIG_MIPS=y
14
CONFIG_MIPS=y
5
# CONFIG_MIPS32 is not set
15
# CONFIG_MIPS32 is not set
6
CONFIG_MIPS64=y
16
CONFIG_MIPS64=y
(-)linux-2.4.22-ppc-dev.orig/arch/ppc/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
# CONFIG_UID16 is not set
14
# CONFIG_UID16 is not set
5
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
15
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
6
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
16
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
(-)linux-2.4.22-ppc-dev.orig/arch/ppc64/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
# CONFIG_UID16 is not set
14
# CONFIG_UID16 is not set
5
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
15
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
6
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
16
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
(-)linux-2.4.22-ppc-dev.orig/arch/ppc64/kernel/misc.S (-2 / +28 lines)
Lines 820-826 Link Here
820
	.llong .sys_futex
820
	.llong .sys_futex
821
#endif
821
#endif
822
	.llong .sys_perfmonctl   /* Put this here for now ... */
822
	.llong .sys_perfmonctl   /* Put this here for now ... */
823
	.rept NR_syscalls-222
823
	.llong .sys_ni_syscall
824
	.llong .sys_setxattr
825
	.llong .sys_lsetxattr		/* 225 */
826
	.llong .sys_fsetxattr
827
	.llong .sys_getxattr
828
	.llong .sys_lgetxattr
829
	.llong .sys_fgetxattr
830
	.llong .sys_listxattr		/* 230 */
831
	.llong .sys_llistxattr
832
	.llong .sys_flistxattr
833
	.llong .sys_removexattr
834
	.llong .sys_lremovexattr
835
	.llong .sys_fremovexattr	/* 235 */
836
	.rept NR_syscalls-236
824
		.llong .sys_ni_syscall
837
		.llong .sys_ni_syscall
825
	.endr
838
	.endr
826
#endif
839
#endif
Lines 1051-1056 Link Here
1051
	.llong .sys_futex
1064
	.llong .sys_futex
1052
#endif
1065
#endif
1053
	.llong .sys_perfmonctl   /* Put this here for now ... */
1066
	.llong .sys_perfmonctl   /* Put this here for now ... */
1054
	.rept NR_syscalls-222
1067
	.llong .sys_ni_syscall
1068
	.llong .sys_setxattr
1069
	.llong .sys_lsetxattr		/* 225 */
1070
	.llong .sys_fsetxattr
1071
	.llong .sys_getxattr
1072
	.llong .sys_lgetxattr
1073
	.llong .sys_fgetxattr
1074
	.llong .sys_listxattr		/* 230 */
1075
	.llong .sys_llistxattr
1076
	.llong .sys_flistxattr
1077
	.llong .sys_removexattr
1078
	.llong .sys_lremovexattr
1079
	.llong .sys_fremovexattr	/* 235 */
1080
	.rept NR_syscalls-236
1055
	.llong .sys_ni_syscall
1081
	.llong .sys_ni_syscall
1056
	.endr
1082
	.endr
(-)linux-2.4.22-ppc-dev.orig/arch/s390/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
# CONFIG_ISA is not set
14
# CONFIG_ISA is not set
5
# CONFIG_EISA is not set
15
# CONFIG_EISA is not set
6
# CONFIG_MCA is not set
16
# CONFIG_MCA is not set
(-)linux-2.4.22-ppc-dev.orig/arch/s390/kernel/entry.S (-12 / +12 lines)
Lines 558-575 Link Here
558
        .long  sys_fcntl64 
558
        .long  sys_fcntl64 
559
	.long  sys_readahead
559
	.long  sys_readahead
560
	.long  sys_ni_syscall
560
	.long  sys_ni_syscall
561
	.long  sys_ni_syscall		 /* 224 - reserved for setxattr  */
561
	.long  sys_setxattr
562
	.long  sys_ni_syscall            /* 225 - reserved for lsetxattr */
562
	.long  sys_lsetxattr		/* 225 */
563
	.long  sys_ni_syscall		 /* 226 - reserved for fsetxattr */
563
	.long  sys_fsetxattr
564
	.long  sys_ni_syscall		 /* 227 - reserved for getxattr  */
564
	.long  sys_getxattr
565
	.long  sys_ni_syscall		 /* 228 - reserved for lgetxattr */
565
	.long  sys_lgetxattr
566
	.long  sys_ni_syscall		 /* 229 - reserved for fgetxattr */
566
	.long  sys_fgetxattr
567
	.long  sys_ni_syscall		 /* 230 - reserved for listxattr */
567
	.long  sys_listxattr		/* 230 */
568
	.long  sys_ni_syscall		 /* 231 - reserved for llistxattr */
568
	.long  sys_llistxattr
569
	.long  sys_ni_syscall		 /* 232 - reserved for flistxattr */
569
	.long  sys_flistxattr
570
	.long  sys_ni_syscall		 /* 233 - reserved for removexattr */
570
	.long  sys_removexattr
571
	.long  sys_ni_syscall		 /* 234 - reserved for lremovexattr */
571
	.long  sys_lremovexattr
572
	.long  sys_ni_syscall		 /* 235 - reserved for fremovexattr */
572
	.long  sys_fremovexattr		/* 235 */
573
	.long  sys_gettid
573
	.long  sys_gettid
574
	.long  sys_tkill
574
	.long  sys_tkill
575
	.rept  255-237
575
	.rept  255-237
(-)linux-2.4.22-ppc-dev.orig/arch/s390x/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
# CONFIG_ISA is not set
14
# CONFIG_ISA is not set
5
# CONFIG_EISA is not set
15
# CONFIG_EISA is not set
6
# CONFIG_MCA is not set
16
# CONFIG_MCA is not set
(-)linux-2.4.22-ppc-dev.orig/arch/s390x/kernel/entry.S (-12 / +12 lines)
Lines 591-608 Link Here
591
	.long  SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
591
	.long  SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
592
	.long  SYSCALL(sys_readahead,sys32_readahead)
592
	.long  SYSCALL(sys_readahead,sys32_readahead)
593
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
593
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
594
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr  */
594
	.long  SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
595
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
595
	.long  SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper)	/* 225 */
596
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
596
	.long  SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
597
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr  */
597
	.long  SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
598
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
598
	.long  SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
599
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
599
	.long  SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
600
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
600
	.long  SYSCALL(sys_listxattr,sys32_listxattr_wrapper)	/* 230 */
601
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
601
	.long  SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
602
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
602
	.long  SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
603
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
603
	.long  SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
604
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
604
	.long  SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
605
	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
605
	.long  SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
606
	.long  SYSCALL(sys_gettid,sys_gettid)
606
	.long  SYSCALL(sys_gettid,sys_gettid)
607
	.long  SYSCALL(sys_tkill,sys_tkill)
607
	.long  SYSCALL(sys_tkill,sys_tkill)
608
	.rept  255-237
608
	.rept  255-237
(-)linux-2.4.22-ppc-dev.orig/arch/s390x/kernel/wrapper32.S (+90 lines)
Lines 1098-1103 Link Here
1098
	llgfr	%r4,%r4			# long
1098
	llgfr	%r4,%r4			# long
1099
	jg	sys32_fstat64		# branch to system call
1099
	jg	sys32_fstat64		# branch to system call
1100
1100
1101
	.globl	sys32_setxattr_wrapper
1102
sys32_setxattr_wrapper:
1103
	llgtr	%r2,%r2			# char *
1104
	llgtr	%r3,%r3			# char *
1105
	llgtr	%r4,%r4			# void *
1106
	llgfr	%r5,%r5			# size_t
1107
	lgfr	%r6,%r6			# int
1108
	jg	sys_setxattr
1109
1110
	.globl	sys32_lsetxattr_wrapper
1111
sys32_lsetxattr_wrapper:
1112
	llgtr	%r2,%r2			# char *
1113
	llgtr	%r3,%r3			# char *
1114
	llgtr	%r4,%r4			# void *
1115
	llgfr	%r5,%r5			# size_t
1116
	lgfr	%r6,%r6			# int
1117
	jg	sys_lsetxattr
1118
1119
	.globl	sys32_fsetxattr_wrapper
1120
sys32_fsetxattr_wrapper:
1121
	lgfr	%r2,%r2			# int
1122
	llgtr	%r3,%r3			# char *
1123
	llgtr	%r4,%r4			# void *
1124
	llgfr	%r5,%r5			# size_t
1125
	lgfr	%r6,%r6			# int
1126
	jg	sys_fsetxattr
1127
1128
	.globl	sys32_getxattr_wrapper
1129
sys32_getxattr_wrapper:
1130
	llgtr	%r2,%r2			# char *
1131
	llgtr	%r3,%r3			# char *
1132
	llgtr	%r4,%r4			# void *
1133
	llgfr	%r5,%r5			# size_t
1134
	jg	sys_getxattr
1135
1136
	.globl	sys32_lgetxattr_wrapper
1137
sys32_lgetxattr_wrapper:
1138
	llgtr	%r2,%r2			# char *
1139
	llgtr	%r3,%r3			# char *
1140
	llgtr	%r4,%r4			# void *
1141
	llgfr	%r5,%r5			# size_t
1142
	jg	sys_lgetxattr
1143
1144
	.globl	sys32_fgetxattr_wrapper
1145
sys32_fgetxattr_wrapper:
1146
	lgfr	%r2,%r2			# int
1147
	llgtr	%r3,%r3			# char *
1148
	llgtr	%r4,%r4			# void *
1149
	llgfr	%r5,%r5			# size_t
1150
	jg	sys_fgetxattr
1151
1152
	.globl	sys32_listxattr_wrapper
1153
sys32_listxattr_wrapper:
1154
	llgtr	%r2,%r2			# char *
1155
	llgtr	%r3,%r3			# char *
1156
	llgfr	%r4,%r4			# size_t
1157
	jg	sys_listxattr
1158
1159
	.globl	sys32_llistxattr_wrapper
1160
sys32_llistxattr_wrapper:
1161
	llgtr	%r2,%r2			# char *
1162
	llgtr	%r3,%r3			# char *
1163
	llgfr	%r4,%r4			# size_t
1164
	jg	sys_llistxattr
1165
1166
	.globl	sys32_flistxattr_wrapper
1167
sys32_flistxattr_wrapper:
1168
	lgfr	%r2,%r2			# int
1169
	llgtr	%r3,%r3			# char *
1170
	llgfr	%r4,%r4			# size_t
1171
	jg	sys_flistxattr
1172
1173
	.globl	sys32_removexattr_wrapper
1174
sys32_removexattr_wrapper:
1175
	llgtr	%r2,%r2			# char *
1176
	llgtr	%r3,%r3			# char *
1177
	jg	sys_removexattr
1178
1179
	.globl	sys32_lremovexattr_wrapper
1180
sys32_lremovexattr_wrapper:
1181
	llgtr	%r2,%r2			# char *
1182
	llgtr	%r3,%r3			# char *
1183
	jg	sys_lremovexattr
1184
1185
	.globl	sys32_fremovexattr_wrapper
1186
sys32_fremovexattr_wrapper:
1187
	lgfr	%r2,%r2			# int
1188
	llgtr	%r3,%r3			# char *
1189
	jg	sys_fremovexattr
1190
1101
	.globl	sys32_stime_wrapper
1191
	.globl	sys32_stime_wrapper
1102
sys32_stime_wrapper:
1192
sys32_stime_wrapper:
1103
	llgtr	%r2,%r2			# int *
1193
	llgtr	%r2,%r2			# int *
(-)linux-2.4.22-ppc-dev.orig/arch/sparc/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# Automatically generated make config: don't edit
2
# Automatically generated make config: don't edit
3
#
3
#
4
# CONFIG_FS_POSIX_ACL is not set
5
# CONFIG_EXT3_FS_POSIX_ACL is not set
6
# CONFIG_EXT2_FS_POSIX_ACL is not set
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
CONFIG_UID16=y
14
CONFIG_UID16=y
5
CONFIG_HIGHMEM=y
15
CONFIG_HIGHMEM=y
6
16
(-)linux-2.4.22-ppc-dev.orig/arch/sparc64/defconfig (+10 lines)
Lines 1-6 Link Here
1
#
1
#
2
# CONFIG_FS_POSIX_ACL is not set
3
# CONFIG_EXT3_FS_POSIX_ACL is not set
4
# CONFIG_EXT2_FS_POSIX_ACL is not set
2
# Automatically generated make config: don't edit
5
# Automatically generated make config: don't edit
3
#
6
#
7
# CONFIG_EXT3_FS_XATTR is not set
8
# CONFIG_EXT3_FS_XATTR_SHARING is not set
9
# CONFIG_EXT3_FS_XATTR_USER is not set
10
# CONFIG_EXT2_FS_XATTR is not set
11
# CONFIG_EXT2_FS_XATTR_SHARING is not set
12
# CONFIG_EXT2_FS_XATTR_USER is not set
13
# CONFIG_FS_MBCACHE is not set
4
14
5
#
15
#
6
# Code maturity level options
16
# Code maturity level options
(-)linux-2.4.22-ppc-dev.orig/fs/Config.in (+33 lines)
Lines 31-36 Link Here
31
dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
31
dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
32
32
33
tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
33
tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
34
dep_mbool '  Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
35
dep_bool '    Ext3 extended attribute block sharing' \
36
    CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
37
dep_bool '    Ext3 extended user attributes' \
38
    CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
39
dep_bool '    Ext3 trusted extended attributes' \
40
    CONFIG_EXT3_FS_XATTR_TRUSTED $CONFIG_EXT3_FS_XATTR
41
dep_bool '    Ext3 POSIX Access Control Lists' \
42
    CONFIG_EXT3_FS_POSIX_ACL $CONFIG_EXT3_FS_XATTR
34
# CONFIG_JBD could be its own option (even modular), but until there are
43
# CONFIG_JBD could be its own option (even modular), but until there are
35
# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
44
# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
36
# dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
45
# dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
Lines 90-95 Link Here
90
tristate 'ROM file system support' CONFIG_ROMFS_FS
99
tristate 'ROM file system support' CONFIG_ROMFS_FS
91
100
92
tristate 'Second extended fs support' CONFIG_EXT2_FS
101
tristate 'Second extended fs support' CONFIG_EXT2_FS
102
dep_mbool '  Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
103
dep_bool '    Ext2 extended attribute block sharing' \
104
    CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
105
dep_bool '    Ext2 extended user attributes' \
106
    CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
107
dep_bool '    Ext2 trusted extended attributes' \
108
    CONFIG_EXT2_FS_XATTR_TRUSTED $CONFIG_EXT2_FS_XATTR
109
dep_bool '    Ext2 POSIX Access Control Lists' \
110
	CONFIG_EXT2_FS_POSIX_ACL $CONFIG_EXT2_FS_XATTR
93
111
94
tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
112
tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
95
113
Lines 108-118 Link Here
108
   dep_tristate 'InterMezzo file system support (replicating fs) (EXPERIMENTAL)' CONFIG_INTERMEZZO_FS $CONFIG_INET $CONFIG_EXPERIMENTAL
126
   dep_tristate 'InterMezzo file system support (replicating fs) (EXPERIMENTAL)' CONFIG_INTERMEZZO_FS $CONFIG_INET $CONFIG_EXPERIMENTAL
109
   dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
127
   dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
110
   dep_mbool '  Provide NFSv3 client support' CONFIG_NFS_V3 $CONFIG_NFS_FS
128
   dep_mbool '  Provide NFSv3 client support' CONFIG_NFS_V3 $CONFIG_NFS_FS
129
   dep_mbool '    Solaris ACL RPCs' CONFIG_NFS_ACL $CONFIG_NFS_V3
111
   dep_mbool '  Allow direct I/O on NFS files (EXPERIMENTAL)' CONFIG_NFS_DIRECTIO $CONFIG_NFS_FS $CONFIG_EXPERIMENTAL
130
   dep_mbool '  Allow direct I/O on NFS files (EXPERIMENTAL)' CONFIG_NFS_DIRECTIO $CONFIG_NFS_FS $CONFIG_EXPERIMENTAL
112
   dep_bool '  Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
131
   dep_bool '  Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
113
132
114
   dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
133
   dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
115
   dep_mbool '  Provide NFSv3 server support' CONFIG_NFSD_V3 $CONFIG_NFSD
134
   dep_mbool '  Provide NFSv3 server support' CONFIG_NFSD_V3 $CONFIG_NFSD
135
   dep_mbool '    Solaris ACL RPCs' CONFIG_NFSD_ACL $CONFIG_NFSD_V3
116
   dep_mbool '  Provide NFS server over TCP support (EXPERIMENTAL)' CONFIG_NFSD_TCP $CONFIG_NFSD $CONFIG_EXPERIMENTAL
136
   dep_mbool '  Provide NFS server over TCP support (EXPERIMENTAL)' CONFIG_NFSD_TCP $CONFIG_NFSD $CONFIG_EXPERIMENTAL
117
137
118
   if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
138
   if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
Lines 162-167 Link Here
162
   define_tristate CONFIG_ZISOFS_FS n
182
   define_tristate CONFIG_ZISOFS_FS n
163
fi
183
fi
164
184
185
# Meta block cache for Extended Attributes (ext2/ext3)
186
#tristate 'Meta block cache' CONFIG_FS_MBCACHE
187
define_tristate CONFIG_FS_MBCACHE y
188
189
# POSIX ACL helper functions
190
191
if [ "$CONFIG_EXT2_FS_POSIX_ACL" = "y" -o \
192
     "$CONFIG_EXT3_FS_POSIX_ACL" = "y" ]; then
193
   define_bool CONFIG_FS_POSIX_ACL y
194
else
195
   bool "POSIX ACL helper functions" CONFIG_FS_POSIX_ACL
196
fi
197
165
mainmenu_option next_comment
198
mainmenu_option next_comment
166
comment 'Partition Types'
199
comment 'Partition Types'
167
source fs/partitions/Config.in
200
source fs/partitions/Config.in
(-)linux-2.4.22-ppc-dev.orig/fs/Makefile (+7 lines)
Lines 78-83 Link Here
78
78
79
obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
79
obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
80
80
81
export-objs += mbcache.o posix_acl.o xattr_acl.o solaris_acl.o
82
obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o
83
obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o xattr_acl.o
84
85
obj-$(CONFIG_NFS_ACL)		+= solaris_acl.o
86
obj-$(CONFIG_NFSD_ACL)		+= solaris_acl.o
87
81
# persistent filesystems
88
# persistent filesystems
82
obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
89
obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
83
90
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/Makefile (+6 lines)
Lines 13-16 Link Here
13
		ioctl.o namei.o super.o symlink.o
13
		ioctl.o namei.o super.o symlink.o
14
obj-m    := $(O_TARGET)
14
obj-m    := $(O_TARGET)
15
15
16
export-objs += xattr.o
17
obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
18
obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
19
obj-$(CONFIG_EXT2_FS_XATTR_TRUSTED) += xattr_trusted.o
20
obj-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o
21
16
include $(TOPDIR)/Rules.make
22
include $(TOPDIR)/Rules.make
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/acl.c (+575 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext2/acl.c
3
 *
4
 * Copyright (C) 2001-2003 by Andreas Gruenbacher, <agruen@suse.de>
5
 */
6
7
#include <linux/module.h>
8
#include <linux/sched.h>
9
#include <linux/slab.h>
10
#include <linux/fs.h>
11
#include <linux/ext2_fs.h>
12
#include <linux/ext2_xattr.h>
13
#include <linux/ext2_acl.h>
14
15
/*
16
 * Convert from filesystem to in-memory representation.
17
 */
18
static struct posix_acl *
19
ext2_acl_from_disk(const void *value, size_t size)
20
{
21
	const char *end = (char *)value + size;
22
	size_t n, count;
23
	struct posix_acl *acl;
24
25
	if (!value)
26
		return NULL;
27
	if (size < sizeof(ext2_acl_header))
28
		 return ERR_PTR(-EINVAL);
29
	if (((ext2_acl_header *)value)->a_version !=
30
	    cpu_to_le32(EXT2_ACL_VERSION))
31
		return ERR_PTR(-EINVAL);
32
	value = (char *)value + sizeof(ext2_acl_header);
33
	count = ext2_acl_count(size);
34
	if (count < 0)
35
		return ERR_PTR(-EINVAL);
36
	if (count == 0)
37
		return NULL;
38
	acl = posix_acl_alloc(count, GFP_KERNEL);
39
	if (!acl)
40
		return ERR_PTR(-ENOMEM);
41
	for (n=0; n < count; n++) {
42
		ext2_acl_entry *entry =
43
			(ext2_acl_entry *)value;
44
		if ((char *)value + sizeof(ext2_acl_entry_short) > end)
45
			goto fail;
46
		acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
47
		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
48
		switch(acl->a_entries[n].e_tag) {
49
			case ACL_USER_OBJ:
50
			case ACL_GROUP_OBJ:
51
			case ACL_MASK:
52
			case ACL_OTHER:
53
				value = (char *)value +
54
					sizeof(ext2_acl_entry_short);
55
				acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
56
				break;
57
58
			case ACL_USER:
59
			case ACL_GROUP:
60
				value = (char *)value + sizeof(ext2_acl_entry);
61
				if ((char *)value > end)
62
					goto fail;
63
				acl->a_entries[n].e_id =
64
					le32_to_cpu(entry->e_id);
65
				break;
66
67
			default:
68
				goto fail;
69
		}
70
	}
71
	if (value != end)
72
		goto fail;
73
	return acl;
74
75
fail:
76
	posix_acl_release(acl);
77
	return ERR_PTR(-EINVAL);
78
}
79
80
/*
81
 * Convert from in-memory to filesystem representation.
82
 */
83
static void *
84
ext2_acl_to_disk(const struct posix_acl *acl, size_t *size)
85
{
86
	ext2_acl_header *ext_acl;
87
	char *e;
88
	size_t n;
89
90
	*size = ext2_acl_size(acl->a_count);
91
	ext_acl = (ext2_acl_header *)kmalloc(sizeof(ext2_acl_header) +
92
		acl->a_count * sizeof(ext2_acl_entry), GFP_KERNEL);
93
	if (!ext_acl)
94
		return ERR_PTR(-ENOMEM);
95
	ext_acl->a_version = cpu_to_le32(EXT2_ACL_VERSION);
96
	e = (char *)ext_acl + sizeof(ext2_acl_header);
97
	for (n=0; n < acl->a_count; n++) {
98
		ext2_acl_entry *entry = (ext2_acl_entry *)e;
99
		entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
100
		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
101
		switch(acl->a_entries[n].e_tag) {
102
			case ACL_USER:
103
			case ACL_GROUP:
104
				entry->e_id =
105
					cpu_to_le32(acl->a_entries[n].e_id);
106
				e += sizeof(ext2_acl_entry);
107
				break;
108
109
			case ACL_USER_OBJ:
110
			case ACL_GROUP_OBJ:
111
			case ACL_MASK:
112
			case ACL_OTHER:
113
				e += sizeof(ext2_acl_entry_short);
114
				break;
115
116
			default:
117
				goto fail;
118
		}
119
	}
120
	return (char *)ext_acl;
121
122
fail:
123
	kfree(ext_acl);
124
	return ERR_PTR(-EINVAL);
125
}
126
127
/*
128
 * inode->i_sem: don't care
129
 * BKL: held
130
 */
131
static struct posix_acl *
132
ext2_get_acl(struct inode *inode, int type)
133
{
134
	const size_t max_size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
135
	struct ext2_inode_info *ei = EXT2_I(inode);
136
	int name_index;
137
	char *value;
138
	struct posix_acl *acl;
139
	int retval;
140
141
	if (!IS_POSIXACL(inode))
142
		return 0;
143
144
	switch(type) {
145
		case ACL_TYPE_ACCESS:
146
			if (ei->i_acl != EXT2_ACL_NOT_CACHED)
147
				return posix_acl_dup(ei->i_acl);
148
			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
149
			break;
150
151
		case ACL_TYPE_DEFAULT:
152
			if (ei->i_default_acl != EXT2_ACL_NOT_CACHED)
153
				return posix_acl_dup(ei->i_default_acl);
154
			name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
155
			break;
156
157
		default:
158
			return ERR_PTR(-EINVAL);
159
	}
160
	value = kmalloc(max_size, GFP_KERNEL);
161
	if (!value)
162
		return ERR_PTR(-ENOMEM);
163
164
	retval = ext2_xattr_get(inode, name_index, "", value, max_size);
165
	acl = ERR_PTR(retval);
166
	if (retval >= 0)
167
		acl = ext2_acl_from_disk(value, retval);
168
	else if (retval == -ENODATA || retval == -ENOSYS)
169
		acl = NULL;
170
	kfree(value);
171
	
172
	if (!IS_ERR(acl)) {
173
		switch(type) {
174
			case ACL_TYPE_ACCESS:
175
				ei->i_acl = posix_acl_dup(acl);
176
				break;
177
178
			case ACL_TYPE_DEFAULT:
179
				ei->i_default_acl = posix_acl_dup(acl);
180
				break;
181
		}
182
	}
183
	return acl;
184
}
185
186
/*
187
 * inode->i_sem: down, or inode is just being initialized
188
 * BKL: held
189
 */
190
static int
191
ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
192
{
193
	struct ext2_inode_info *ei = EXT2_I(inode);
194
	int name_index;
195
	void *value = NULL;
196
	size_t size;
197
	int error;
198
199
	if (S_ISLNK(inode->i_mode))
200
		return -EOPNOTSUPP;
201
	if (!IS_POSIXACL(inode))
202
		return 0;
203
204
	switch(type) {
205
		case ACL_TYPE_ACCESS:
206
			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
207
			if (acl) {
208
				mode_t mode = inode->i_mode;
209
				error = posix_acl_equiv_mode(acl, &mode);
210
				if (error < 0)
211
					return error;
212
				else {
213
					inode->i_mode = mode;
214
					mark_inode_dirty(inode);
215
					if (error == 0)
216
						acl = NULL;
217
				}
218
			}
219
			break;
220
221
		case ACL_TYPE_DEFAULT:
222
			name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
223
			if (!S_ISDIR(inode->i_mode))
224
				return acl ? -EACCES : 0;
225
			break;
226
227
		default:
228
			return -EINVAL;
229
	}
230
 	if (acl) {
231
		if (acl->a_count > EXT2_ACL_MAX_ENTRIES)
232
			return -EINVAL;
233
		value = ext2_acl_to_disk(acl, &size);
234
		if (IS_ERR(value))
235
			return (int)PTR_ERR(value);
236
	}
237
238
	error = ext2_xattr_set(inode, name_index, "", value, size, 0);
239
240
	if (value)
241
		kfree(value);
242
	if (!error) {
243
		switch(type) {
244
			case ACL_TYPE_ACCESS:
245
				if (ei->i_acl != EXT2_ACL_NOT_CACHED)
246
					posix_acl_release(ei->i_acl);
247
				ei->i_acl = posix_acl_dup(acl);
248
				break;
249
250
			case ACL_TYPE_DEFAULT:
251
				if (ei->i_default_acl != EXT2_ACL_NOT_CACHED)
252
					posix_acl_release(ei->i_default_acl);
253
				ei->i_default_acl = posix_acl_dup(acl);
254
				break;
255
		}
256
	}
257
	return error;
258
}
259
260
/*
261
 * Inode operation permission().
262
 *
263
 * inode->i_sem: don't care
264
 * BKL: held
265
 */
266
int
267
ext2_permission(struct inode *inode, int mask)
268
{
269
	int mode = inode->i_mode;
270
271
	/* Nobody gets write access to a read-only fs */
272
	if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
273
	    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
274
		return -EROFS;
275
	/* Nobody gets write access to an immutable file */
276
	if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
277
	    return -EACCES;
278
	if (current->fsuid == inode->i_uid) {
279
		mode >>= 6;
280
	} else if (IS_POSIXACL(inode)) {
281
		struct ext2_inode_info *ei = EXT2_I(inode);
282
283
		/* The access ACL cannot grant access if the group class
284
		   permission bits don't contain all requested permissions. */
285
		if (((mode >> 3) & mask & S_IRWXO) != mask)
286
			goto check_groups;
287
		if (ei->i_acl == EXT2_ACL_NOT_CACHED) {
288
			struct posix_acl *acl =
289
				ext2_get_acl(inode, ACL_TYPE_ACCESS);
290
291
			if (IS_ERR(acl))
292
				return PTR_ERR(acl);
293
			posix_acl_release(acl);
294
			if (ei->i_acl == EXT2_ACL_NOT_CACHED)
295
				return -EIO;
296
		}
297
		if (ei->i_acl) {
298
			int error = posix_acl_permission(inode, ei->i_acl,mask);
299
			if (error == -EACCES)
300
				goto check_capabilities;
301
			return error;
302
		} else
303
			goto check_groups;
304
	} else {
305
check_groups:
306
		if (in_group_p(inode->i_gid))
307
			mode >>= 3;
308
	}
309
	if ((mode & mask & S_IRWXO) == mask)
310
		return 0;
311
312
check_capabilities:
313
	/* Allowed to override Discretionary Access Control? */
314
	if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
315
		if (capable(CAP_DAC_OVERRIDE))
316
			return 0;
317
	/* Read and search granted if capable(CAP_DAC_READ_SEARCH) */
318
	if (capable(CAP_DAC_READ_SEARCH) && ((mask == MAY_READ) ||
319
	    (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))))
320
		return 0;
321
	return -EACCES;
322
}
323
324
/*
325
 * Initialize the ACLs of a new inode. Called from ext2_new_inode.
326
 *
327
 * dir->i_sem: don't care
328
 * inode->i_sem: up (access to inode is still exclusive)
329
 * BKL: held
330
 */
331
int
332
ext2_init_acl(struct inode *inode, struct inode *dir)
333
{
334
	struct posix_acl *acl = NULL;
335
	int error = 0;
336
337
	if (!S_ISLNK(inode->i_mode)) {
338
		if (IS_POSIXACL(dir)) {
339
			acl = ext2_get_acl(dir, ACL_TYPE_DEFAULT);
340
			if (IS_ERR(acl))
341
				return PTR_ERR(acl);
342
		}
343
		if (!acl) {
344
			inode->i_mode &= ~current->fs->umask;
345
			mark_inode_dirty(inode);
346
		}
347
	}
348
	if (IS_POSIXACL(inode) && acl) {
349
               struct posix_acl *clone;
350
	       mode_t mode;
351
352
		if (S_ISDIR(inode->i_mode)) {
353
			error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
354
			if (error)
355
				goto cleanup;
356
		}
357
		clone = posix_acl_clone(acl, GFP_KERNEL);
358
		error = -ENOMEM;
359
		if (!clone)
360
			goto cleanup;
361
		mode = inode->i_mode;
362
		error = posix_acl_create_masq(clone, &mode);
363
		if (error >= 0) {
364
			inode->i_mode = mode;
365
			mark_inode_dirty(inode);
366
			if (error > 0) {
367
				/* This is an extended ACL */
368
				error = ext2_set_acl(inode,
369
						     ACL_TYPE_ACCESS, clone);
370
			}
371
		}
372
		posix_acl_release(clone);
373
	}
374
cleanup:
375
       posix_acl_release(acl);
376
       return error;
377
}
378
379
/*
380
 * Does chmod for an inode that may have an Access Control List. The
381
 * inode->i_mode field must be updated to the desired value by the caller
382
 * before calling this function.
383
 * Returns 0 on success, or a negative error number.
384
 *
385
 * We change the ACL rather than storing some ACL entries in the file
386
 * mode permission bits (which would be more efficient), because that
387
 * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
388
 * for directories) are added. There are no more bits available in the
389
 * file mode.
390
 *
391
 * inode->i_sem: down
392
 * BKL: held
393
 */
394
int
395
ext2_acl_chmod(struct inode *inode)
396
{
397
	struct posix_acl *acl, *clone;
398
        int error;
399
400
	if (!IS_POSIXACL(inode))
401
		return 0;
402
	if (S_ISLNK(inode->i_mode))
403
		return -EOPNOTSUPP;
404
	acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
405
	if (IS_ERR(acl) || !acl)
406
		return PTR_ERR(acl);
407
	clone = posix_acl_clone(acl, GFP_KERNEL);
408
	posix_acl_release(acl);
409
	if (!clone)
410
		return -ENOMEM;
411
	error = posix_acl_chmod_masq(clone, inode->i_mode);
412
	if (!error)
413
		error = ext2_set_acl(inode, ACL_TYPE_ACCESS, clone);
414
	posix_acl_release(clone);
415
	return error;
416
}
417
418
/*
419
 * Extended attribut handlers
420
 */
421
static size_t
422
ext2_xattr_list_acl_access(char *list, struct inode *inode,
423
			   const char *name, int name_len)
424
{
425
	const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
426
427
	if (!IS_POSIXACL(inode))
428
		return 0;
429
	if (list)
430
		memcpy(list, XATTR_NAME_ACL_ACCESS, size);
431
	return size;
432
}
433
434
static size_t
435
ext2_xattr_list_acl_default(char *list, struct inode *inode,
436
			    const char *name, int name_len)
437
{
438
	const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
439
440
	if (!IS_POSIXACL(inode))
441
		return 0;
442
	if (list)
443
		memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
444
	return size;
445
}
446
447
static int
448
ext2_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
449
{
450
	struct posix_acl *acl;
451
	int error;
452
453
	if (!IS_POSIXACL(inode))
454
		return -EOPNOTSUPP;
455
456
	acl = ext2_get_acl(inode, type);
457
	if (IS_ERR(acl))
458
		return PTR_ERR(acl);
459
	if (acl == NULL)
460
		return -ENODATA;
461
	error = posix_acl_to_xattr(acl, buffer, size);
462
	posix_acl_release(acl);
463
464
	return error;
465
}
466
467
static int
468
ext2_xattr_get_acl_access(struct inode *inode, const char *name,
469
			  void *buffer, size_t size)
470
{
471
	if (strcmp(name, "") != 0)
472
		return -EINVAL;
473
	return ext2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
474
}
475
476
static int
477
ext2_xattr_get_acl_default(struct inode *inode, const char *name,
478
			   void *buffer, size_t size)
479
{
480
	if (strcmp(name, "") != 0)
481
		return -EINVAL;
482
	return ext2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
483
}
484
485
static int
486
ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
487
		   size_t size)
488
{
489
	struct posix_acl *acl;
490
	int error;
491
492
	if (!IS_POSIXACL(inode))
493
		return -EOPNOTSUPP;
494
	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
495
		return -EPERM;
496
497
	if (value) {
498
		acl = posix_acl_from_xattr(value, size);
499
		if (IS_ERR(acl))
500
			return PTR_ERR(acl);
501
		else if (acl) {
502
			error = posix_acl_valid(acl);
503
			if (error)
504
				goto release_and_out;
505
		}
506
	} else
507
		acl = NULL;
508
509
	error = ext2_set_acl(inode, type, acl);
510
511
release_and_out:
512
	posix_acl_release(acl);
513
	return error;
514
}
515
516
static int
517
ext2_xattr_set_acl_access(struct inode *inode, const char *name,
518
			  const void *value, size_t size, int flags)
519
{
520
	if (strcmp(name, "") != 0)
521
		return -EINVAL;
522
	return ext2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
523
}
524
525
static int
526
ext2_xattr_set_acl_default(struct inode *inode, const char *name,
527
			   const void *value, size_t size, int flags)
528
{
529
	if (strcmp(name, "") != 0)
530
		return -EINVAL;
531
	return ext2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
532
}
533
534
struct ext2_xattr_handler ext2_xattr_acl_access_handler = {
535
	prefix:	XATTR_NAME_ACL_ACCESS,
536
	list:	ext2_xattr_list_acl_access,
537
	get:	ext2_xattr_get_acl_access,
538
	set:	ext2_xattr_set_acl_access,
539
};
540
541
struct ext2_xattr_handler ext2_xattr_acl_default_handler = {
542
	prefix:	XATTR_NAME_ACL_DEFAULT,
543
	list:	ext2_xattr_list_acl_default,
544
	get:	ext2_xattr_get_acl_default,
545
	set:	ext2_xattr_set_acl_default,
546
};
547
548
void
549
exit_ext2_acl(void)
550
{
551
	ext2_xattr_unregister(EXT2_XATTR_INDEX_POSIX_ACL_ACCESS,
552
			      &ext2_xattr_acl_access_handler);
553
	ext2_xattr_unregister(EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT,
554
			      &ext2_xattr_acl_default_handler);
555
}
556
557
int __init
558
init_ext2_acl(void)
559
{
560
	int error;
561
562
	error = ext2_xattr_register(EXT2_XATTR_INDEX_POSIX_ACL_ACCESS,
563
				    &ext2_xattr_acl_access_handler);
564
	if (error)
565
		goto fail;
566
	error = ext2_xattr_register(EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT,
567
				    &ext2_xattr_acl_default_handler);
568
	if (error)
569
		goto fail;
570
	return 0;
571
572
fail:
573
	exit_ext2_acl();
574
	return error;
575
}
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/file.c (+8 lines)
Lines 20-25 Link Here
20
20
21
#include <linux/fs.h>
21
#include <linux/fs.h>
22
#include <linux/ext2_fs.h>
22
#include <linux/ext2_fs.h>
23
#include <linux/ext2_xattr.h>
24
#include <linux/ext2_acl.h>
23
#include <linux/sched.h>
25
#include <linux/sched.h>
24
26
25
/*
27
/*
Lines 51-54 Link Here
51
53
52
struct inode_operations ext2_file_inode_operations = {
54
struct inode_operations ext2_file_inode_operations = {
53
	truncate:	ext2_truncate,
55
	truncate:	ext2_truncate,
56
	setxattr:	ext2_setxattr,
57
	getxattr:	ext2_getxattr,
58
	listxattr:	ext2_listxattr,
59
	removexattr:	ext2_removexattr,
60
	setattr:	ext2_setattr,
61
	permission:	ext2_permission,
54
};
62
};
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/ialloc.c (-5 / +22 lines)
Lines 15-20 Link Here
15
#include <linux/config.h>
15
#include <linux/config.h>
16
#include <linux/fs.h>
16
#include <linux/fs.h>
17
#include <linux/ext2_fs.h>
17
#include <linux/ext2_fs.h>
18
#include <linux/ext2_xattr.h>
19
#include <linux/ext2_acl.h>
18
#include <linux/locks.h>
20
#include <linux/locks.h>
19
#include <linux/quotaops.h>
21
#include <linux/quotaops.h>
20
22
Lines 167-172 Link Here
167
	 */
169
	 */
168
	if (!is_bad_inode(inode)) {
170
	if (!is_bad_inode(inode)) {
169
		/* Quota is already initialized in iput() */
171
		/* Quota is already initialized in iput() */
172
		ext2_xattr_delete_inode(inode);
170
	    	DQUOT_FREE_INODE(inode);
173
	    	DQUOT_FREE_INODE(inode);
171
		DQUOT_DROP(inode);
174
		DQUOT_DROP(inode);
172
	}
175
	}
Lines 311-317 Link Here
311
	return group;
314
	return group;
312
}
315
}
313
316
314
struct inode * ext2_new_inode (const struct inode * dir, int mode)
317
struct inode * ext2_new_inode (struct inode * dir, int mode)
315
{
318
{
316
	struct super_block * sb;
319
	struct super_block * sb;
317
	struct buffer_head * bh;
320
	struct buffer_head * bh;
Lines 395-411 Link Here
395
	inode->i_generation = event++;
398
	inode->i_generation = event++;
396
	mark_inode_dirty(inode);
399
	mark_inode_dirty(inode);
397
400
401
#ifdef CONFIG_EXT2_FS_XATTR
402
	init_rwsem(&inode->u.ext2_i.xattr_sem);
403
#endif
404
398
	unlock_super (sb);
405
	unlock_super (sb);
399
	if(DQUOT_ALLOC_INODE(inode)) {
406
	if(DQUOT_ALLOC_INODE(inode)) {
400
		DQUOT_DROP(inode);
407
		DQUOT_DROP(inode);
401
		inode->i_flags |= S_NOQUOTA;
408
		err = -EDQUOT;
402
		inode->i_nlink = 0;
409
		goto fail3;
403
		iput(inode);
404
		return ERR_PTR(-EDQUOT);
405
	}
410
	}
411
	err = ext2_init_acl(inode, dir);
412
	if (err) {
413
		DQUOT_FREE_INODE(inode);
414
		goto fail3;
415
	}
416
406
	ext2_debug ("allocating inode %lu\n", inode->i_ino);
417
	ext2_debug ("allocating inode %lu\n", inode->i_ino);
407
	return inode;
418
	return inode;
408
419
420
fail3:
421
	inode->i_flags |= S_NOQUOTA;
422
	inode->i_nlink = 0;
423
	iput(inode);
424
	return ERR_PTR(err);
425
409
fail2:
426
fail2:
410
	desc = ext2_get_group_desc (sb, group, &bh2);
427
	desc = ext2_get_group_desc (sb, group, &bh2);
411
	desc->bg_free_inodes_count =
428
	desc->bg_free_inodes_count =
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/inode.c (-12 / +55 lines)
Lines 24-29 Link Here
24
24
25
#include <linux/fs.h>
25
#include <linux/fs.h>
26
#include <linux/ext2_fs.h>
26
#include <linux/ext2_fs.h>
27
#include <linux/ext2_acl.h>
27
#include <linux/locks.h>
28
#include <linux/locks.h>
28
#include <linux/smp_lock.h>
29
#include <linux/smp_lock.h>
29
#include <linux/sched.h>
30
#include <linux/sched.h>
Lines 39-44 Link Here
39
static int ext2_update_inode(struct inode * inode, int do_sync);
40
static int ext2_update_inode(struct inode * inode, int do_sync);
40
41
41
/*
42
/*
43
 * Test whether an inode is a fast symlink.
44
 */
45
static inline int ext2_inode_is_fast_symlink(struct inode *inode)
46
{
47
	int ea_blocks = inode->u.ext2_i.i_file_acl ?
48
		(inode->i_sb->s_blocksize >> 9) : 0;
49
50
	return (S_ISLNK(inode->i_mode) &&
51
		inode->i_blocks - ea_blocks == 0);
52
}
53
54
/*
42
 * Called at each iput()
55
 * Called at each iput()
43
 */
56
 */
44
void ext2_put_inode (struct inode * inode)
57
void ext2_put_inode (struct inode * inode)
Lines 53-61 Link Here
53
{
66
{
54
	lock_kernel();
67
	lock_kernel();
55
68
56
	if (is_bad_inode(inode) ||
69
	if (is_bad_inode(inode))
57
	    inode->i_ino == EXT2_ACL_IDX_INO ||
58
	    inode->i_ino == EXT2_ACL_DATA_INO)
59
		goto no_delete;
70
		goto no_delete;
60
	inode->u.ext2_i.i_dtime	= CURRENT_TIME;
71
	inode->u.ext2_i.i_dtime	= CURRENT_TIME;
61
	mark_inode_dirty(inode);
72
	mark_inode_dirty(inode);
Lines 801-806 Link Here
801
	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
812
	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
802
	    S_ISLNK(inode->i_mode)))
813
	    S_ISLNK(inode->i_mode)))
803
		return;
814
		return;
815
	if (ext2_inode_is_fast_symlink(inode))
816
		return;
804
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
817
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
805
		return;
818
		return;
806
819
Lines 903-910 Link Here
903
	unsigned long offset;
916
	unsigned long offset;
904
	struct ext2_group_desc * gdp;
917
	struct ext2_group_desc * gdp;
905
918
906
	if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
919
	if ((inode->i_ino != EXT2_ROOT_INO &&
907
	     inode->i_ino != EXT2_ACL_DATA_INO &&
908
	     inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
920
	     inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
909
	    inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
921
	    inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
910
		ext2_error (inode->i_sb, "ext2_read_inode",
922
		ext2_error (inode->i_sb, "ext2_read_inode",
Lines 989-998 Link Here
989
	for (block = 0; block < EXT2_N_BLOCKS; block++)
1001
	for (block = 0; block < EXT2_N_BLOCKS; block++)
990
		inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
1002
		inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
991
1003
992
	if (inode->i_ino == EXT2_ACL_IDX_INO ||
1004
	if (S_ISREG(inode->i_mode)) {
993
	    inode->i_ino == EXT2_ACL_DATA_INO)
994
		/* Nothing to do */ ;
995
	else if (S_ISREG(inode->i_mode)) {
996
		inode->i_op = &ext2_file_inode_operations;
1005
		inode->i_op = &ext2_file_inode_operations;
997
		inode->i_fop = &ext2_file_operations;
1006
		inode->i_fop = &ext2_file_operations;
998
		inode->i_mapping->a_ops = &ext2_aops;
1007
		inode->i_mapping->a_ops = &ext2_aops;
Lines 1001-1018 Link Here
1001
		inode->i_fop = &ext2_dir_operations;
1010
		inode->i_fop = &ext2_dir_operations;
1002
		inode->i_mapping->a_ops = &ext2_aops;
1011
		inode->i_mapping->a_ops = &ext2_aops;
1003
	} else if (S_ISLNK(inode->i_mode)) {
1012
	} else if (S_ISLNK(inode->i_mode)) {
1004
		if (!inode->i_blocks)
1013
		if (ext2_inode_is_fast_symlink(inode))
1005
			inode->i_op = &ext2_fast_symlink_inode_operations;
1014
			inode->i_op = &ext2_fast_symlink_inode_operations;
1006
		else {
1015
		else {
1007
			inode->i_op = &page_symlink_inode_operations;
1016
			inode->i_op = &ext2_symlink_inode_operations;
1008
			inode->i_mapping->a_ops = &ext2_aops;
1017
			inode->i_mapping->a_ops = &ext2_aops;
1009
		}
1018
		}
1010
	} else 
1019
	} else {
1020
		inode->i_op = &ext2_special_inode_operations;
1011
		init_special_inode(inode, inode->i_mode,
1021
		init_special_inode(inode, inode->i_mode,
1012
				   le32_to_cpu(raw_inode->i_block[0]));
1022
				   le32_to_cpu(raw_inode->i_block[0]));
1023
	}
1013
	brelse (bh);
1024
	brelse (bh);
1014
	inode->i_attr_flags = 0;
1025
	inode->i_attr_flags = 0;
1015
	ext2_set_inode_flags(inode);
1026
	ext2_set_inode_flags(inode);
1027
#ifdef CONFIG_EXT2_FS_XATTR
1028
	init_rwsem(&inode->u.ext2_i.xattr_sem);
1029
#endif
1030
#ifdef CONFIG_EXT2_FS_POSIX_ACL
1031
	if (inode->u.ext2_i.i_file_acl) {
1032
		/* The filesystem is mounted with ACL support, and there
1033
		   are extended attributes for this inode. However we do
1034
		   not yet know whether there are actually any ACLs. */
1035
		inode->u.ext2_i.i_acl = EXT2_ACL_NOT_CACHED;
1036
		inode->u.ext2_i.i_default_acl = EXT2_ACL_NOT_CACHED;
1037
	}
1038
#endif
1016
	return;
1039
	return;
1017
	
1040
	
1018
bad_inode:
1041
bad_inode:
Lines 1157-1159 Link Here
1157
{
1180
{
1158
	return ext2_update_inode (inode, 1);
1181
	return ext2_update_inode (inode, 1);
1159
}
1182
}
1183
1184
int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
1185
{
1186
	struct inode *inode = dentry->d_inode;
1187
	int error;
1188
1189
	error = inode_change_ok(inode, iattr);
1190
	if (error)
1191
		return error;
1192
	inode_setattr(inode, iattr);
1193
	if (iattr->ia_valid & ATTR_MODE) {
1194
		if (!(iattr->ia_valid & ATTR_SIZE))
1195
			down(&inode->i_sem);
1196
		error = ext2_acl_chmod(inode);
1197
		if (!(iattr->ia_valid & ATTR_SIZE))
1198
			up(&inode->i_sem);
1199
	}
1200
	return error;
1201
}
1202
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/namei.c (-2 / +22 lines)
Lines 31-36 Link Here
31
31
32
#include <linux/fs.h>
32
#include <linux/fs.h>
33
#include <linux/ext2_fs.h>
33
#include <linux/ext2_fs.h>
34
#include <linux/ext2_xattr.h>
35
#include <linux/ext2_acl.h>
34
#include <linux/pagemap.h>
36
#include <linux/pagemap.h>
35
37
36
/*
38
/*
Lines 111-117 Link Here
111
	struct inode * inode = ext2_new_inode (dir, mode);
113
	struct inode * inode = ext2_new_inode (dir, mode);
112
	int err = PTR_ERR(inode);
114
	int err = PTR_ERR(inode);
113
	if (!IS_ERR(inode)) {
115
	if (!IS_ERR(inode)) {
114
		init_special_inode(inode, mode, rdev);
116
		init_special_inode(inode, inode->i_mode, rdev);
117
#ifdef CONFIG_EXT2_FS_POSIX_ACL
118
		inode->i_op = &ext2_special_inode_operations;
119
#endif
115
		mark_inode_dirty(inode);
120
		mark_inode_dirty(inode);
116
		err = ext2_add_nondir(dentry, inode);
121
		err = ext2_add_nondir(dentry, inode);
117
	}
122
	}
Lines 136-142 Link Here
136
141
137
	if (l > sizeof (inode->u.ext2_i.i_data)) {
142
	if (l > sizeof (inode->u.ext2_i.i_data)) {
138
		/* slow symlink */
143
		/* slow symlink */
139
		inode->i_op = &page_symlink_inode_operations;
144
		inode->i_op = &ext2_symlink_inode_operations;
140
		inode->i_mapping->a_ops = &ext2_aops;
145
		inode->i_mapping->a_ops = &ext2_aops;
141
		err = block_symlink(inode, symname, l);
146
		err = block_symlink(inode, symname, l);
142
		if (err)
147
		if (err)
Lines 345-348 Link Here
345
	rmdir:		ext2_rmdir,
350
	rmdir:		ext2_rmdir,
346
	mknod:		ext2_mknod,
351
	mknod:		ext2_mknod,
347
	rename:		ext2_rename,
352
	rename:		ext2_rename,
353
	setxattr:	ext2_setxattr,
354
	getxattr:	ext2_getxattr,
355
	listxattr:	ext2_listxattr,
356
	removexattr:	ext2_removexattr,
357
	setattr:	ext2_setattr,
358
	permission:	ext2_permission,
359
};
360
361
struct inode_operations ext2_special_inode_operations = {
362
	setxattr:	ext2_setxattr,
363
	getxattr:	ext2_getxattr,
364
	listxattr:	ext2_listxattr,
365
	removexattr:	ext2_removexattr,
366
	setattr:	ext2_setattr,
367
	permission:	ext2_permission,
348
};
368
};
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/super.c (-5 / +79 lines)
Lines 21-26 Link Here
21
#include <linux/string.h>
21
#include <linux/string.h>
22
#include <linux/fs.h>
22
#include <linux/fs.h>
23
#include <linux/ext2_fs.h>
23
#include <linux/ext2_fs.h>
24
#include <linux/ext2_xattr.h>
25
#include <linux/ext2_acl.h>
24
#include <linux/slab.h>
26
#include <linux/slab.h>
25
#include <linux/init.h>
27
#include <linux/init.h>
26
#include <linux/locks.h>
28
#include <linux/locks.h>
Lines 125-130 Link Here
125
	int db_count;
127
	int db_count;
126
	int i;
128
	int i;
127
129
130
	ext2_xattr_put_super(sb);
128
	if (!(sb->s_flags & MS_RDONLY)) {
131
	if (!(sb->s_flags & MS_RDONLY)) {
129
		struct ext2_super_block *es = EXT2_SB(sb)->s_es;
132
		struct ext2_super_block *es = EXT2_SB(sb)->s_es;
130
133
Lines 147-152 Link Here
147
	return;
150
	return;
148
}
151
}
149
152
153
#ifdef CONFIG_EXT2_FS_POSIX_ACL
154
155
static void ext2_clear_inode(struct inode *inode)
156
{
157
	if (inode->u.ext2_i.i_acl &&
158
	    inode->u.ext2_i.i_acl != EXT2_ACL_NOT_CACHED) {
159
		posix_acl_release(inode->u.ext2_i.i_acl);
160
		inode->u.ext2_i.i_acl = EXT2_ACL_NOT_CACHED;
161
	}
162
	if (inode->u.ext2_i.i_default_acl &&
163
	    inode->u.ext2_i.i_default_acl != EXT2_ACL_NOT_CACHED) {
164
		posix_acl_release(inode->u.ext2_i.i_default_acl);
165
		inode->u.ext2_i.i_default_acl = EXT2_ACL_NOT_CACHED;
166
	}
167
}
168
169
#else
170
# define ext2_clear_inode NULL
171
#endif
172
150
static struct super_operations ext2_sops = {
173
static struct super_operations ext2_sops = {
151
	read_inode:	ext2_read_inode,
174
	read_inode:	ext2_read_inode,
152
	write_inode:	ext2_write_inode,
175
	write_inode:	ext2_write_inode,
Lines 156-161 Link Here
156
	write_super:	ext2_write_super,
179
	write_super:	ext2_write_super,
157
	statfs:		ext2_statfs,
180
	statfs:		ext2_statfs,
158
	remount_fs:	ext2_remount,
181
	remount_fs:	ext2_remount,
182
	clear_inode:	ext2_clear_inode,
159
};
183
};
160
184
161
/*
185
/*
Lines 163-169 Link Here
163
 */
187
 */
164
static int parse_options (char * options, unsigned long * sb_block,
188
static int parse_options (char * options, unsigned long * sb_block,
165
			  unsigned short *resuid, unsigned short * resgid,
189
			  unsigned short *resuid, unsigned short * resgid,
166
			  unsigned long * mount_options)
190
			  unsigned long * mount_options,
191
			  unsigned long * mount_flags)
167
{
192
{
168
	char * this_char;
193
	char * this_char;
169
	char * value;
194
	char * value;
Lines 175-180 Link Here
175
	     this_char = strtok (NULL, ",")) {
200
	     this_char = strtok (NULL, ",")) {
176
		if ((value = strchr (this_char, '=')) != NULL)
201
		if ((value = strchr (this_char, '=')) != NULL)
177
			*value++ = 0;
202
			*value++ = 0;
203
#ifdef CONFIG_EXT2_FS_XATTR_USER
204
		if (!strcmp (this_char, "user_xattr"))
205
			set_opt (*mount_options, XATTR_USER);
206
		else if (!strcmp (this_char, "nouser_xattr"))
207
			clear_opt (*mount_options, XATTR_USER);
208
		else
209
#endif
210
#ifdef CONFIG_EXT2_FS_POSIX_ACL
211
		if (!strcmp(this_char, "acl"))
212
			*mount_flags |= MS_POSIXACL;
213
		else if (!strcmp(this_char, "noacl"))
214
			*mount_flags &= ~MS_POSIXACL;
215
		else
216
#endif
178
		if (!strcmp (this_char, "bsddf"))
217
		if (!strcmp (this_char, "bsddf"))
179
			clear_opt (*mount_options, MINIX_DF);
218
			clear_opt (*mount_options, MINIX_DF);
180
		else if (!strcmp (this_char, "nouid32")) {
219
		else if (!strcmp (this_char, "nouid32")) {
Lines 424-431 Link Here
424
	    blocksize = BLOCK_SIZE;
463
	    blocksize = BLOCK_SIZE;
425
464
426
	sb->u.ext2_sb.s_mount_opt = 0;
465
	sb->u.ext2_sb.s_mount_opt = 0;
466
#ifdef CONFIG_EXT2_FS_XATTR_USER
467
	/* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
468
#endif
469
#ifdef CONFIG_EXT2_FS_POSIX_ACL
470
	/* sb->s_flags |= MS_POSIXACL; */
471
#endif
427
	if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
472
	if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
428
	    &sb->u.ext2_sb.s_mount_opt)) {
473
	    &sb->u.ext2_sb.s_mount_opt, &sb->s_flags)) {
429
		return NULL;
474
		return NULL;
430
	}
475
	}
431
476
Lines 712-728 Link Here
712
	struct ext2_super_block * es;
757
	struct ext2_super_block * es;
713
	unsigned short resuid = sb->u.ext2_sb.s_resuid;
758
	unsigned short resuid = sb->u.ext2_sb.s_resuid;
714
	unsigned short resgid = sb->u.ext2_sb.s_resgid;
759
	unsigned short resgid = sb->u.ext2_sb.s_resgid;
715
	unsigned long new_mount_opt;
760
	unsigned long new_mount_opt, new_mount_flags;
716
	unsigned long tmp;
761
	unsigned long tmp;
717
762
718
	/*
763
	/*
719
	 * Allow the "check" option to be passed as a remount option.
764
	 * Allow the "check" option to be passed as a remount option.
720
	 */
765
	 */
721
	new_mount_opt = sb->u.ext2_sb.s_mount_opt;
766
	new_mount_opt = sb->u.ext2_sb.s_mount_opt;
767
	new_mount_flags = sb->s_flags;
722
	if (!parse_options (data, &tmp, &resuid, &resgid,
768
	if (!parse_options (data, &tmp, &resuid, &resgid,
723
			    &new_mount_opt))
769
			    &new_mount_opt, &new_mount_flags))
724
		return -EINVAL;
770
		return -EINVAL;
725
771
772
	sb->s_flags = new_mount_flags;
726
	sb->u.ext2_sb.s_mount_opt = new_mount_opt;
773
	sb->u.ext2_sb.s_mount_opt = new_mount_opt;
727
	sb->u.ext2_sb.s_resuid = resuid;
774
	sb->u.ext2_sb.s_resuid = resuid;
728
	sb->u.ext2_sb.s_resgid = resgid;
775
	sb->u.ext2_sb.s_resgid = resgid;
Lines 813-824 Link Here
813
860
814
static int __init init_ext2_fs(void)
861
static int __init init_ext2_fs(void)
815
{
862
{
816
        return register_filesystem(&ext2_fs_type);
863
	int error = init_ext2_xattr();
864
	if (error)
865
		return error;
866
	error = init_ext2_xattr_user();
867
	if (error)
868
		goto fail;
869
	error = init_ext2_xattr_trusted();
870
	if (error)
871
		goto fail2;
872
	error = init_ext2_acl();
873
	if (error)
874
		goto fail3;
875
	error = register_filesystem(&ext2_fs_type);
876
	if (!error)
877
		return 0;
878
879
	exit_ext2_acl();
880
fail3:
881
	exit_ext2_xattr_trusted();
882
fail2:
883
	exit_ext2_xattr_user();
884
fail:
885
	exit_ext2_xattr();
886
	return error;
817
}
887
}
818
888
819
static void __exit exit_ext2_fs(void)
889
static void __exit exit_ext2_fs(void)
820
{
890
{
821
	unregister_filesystem(&ext2_fs_type);
891
	unregister_filesystem(&ext2_fs_type);
892
	exit_ext2_acl();
893
	exit_ext2_xattr_trusted();
894
	exit_ext2_xattr_user();
895
	exit_ext2_xattr();
822
}
896
}
823
897
824
EXPORT_NO_SYMBOLS;
898
EXPORT_NO_SYMBOLS;
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/symlink.c (+14 lines)
Lines 19-24 Link Here
19
19
20
#include <linux/fs.h>
20
#include <linux/fs.h>
21
#include <linux/ext2_fs.h>
21
#include <linux/ext2_fs.h>
22
#include <linux/ext2_xattr.h>
22
23
23
static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
24
static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
24
{
25
{
Lines 32-38 Link Here
32
	return vfs_follow_link(nd, s);
33
	return vfs_follow_link(nd, s);
33
}
34
}
34
35
36
struct inode_operations ext2_symlink_inode_operations = {
37
	readlink:	page_readlink,
38
	follow_link:	page_follow_link,
39
	setxattr:	ext2_setxattr,
40
	getxattr:	ext2_getxattr,
41
	listxattr:	ext2_listxattr,
42
	removexattr:	ext2_removexattr,
43
};
44
35
struct inode_operations ext2_fast_symlink_inode_operations = {
45
struct inode_operations ext2_fast_symlink_inode_operations = {
36
	readlink:	ext2_readlink,
46
	readlink:	ext2_readlink,
37
	follow_link:	ext2_follow_link,
47
	follow_link:	ext2_follow_link,
48
	setxattr:	ext2_setxattr,
49
	getxattr:	ext2_getxattr,
50
	listxattr:	ext2_listxattr,
51
	removexattr:	ext2_removexattr,
38
};
52
};
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/xattr.c (+1165 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext2/xattr.c
3
 *
4
 * Copyright (C) 2001-2003 by Andreas Gruenbacher, <agruen@suse.de>
5
 *
6
 * Fix by Harrison Xing <harrison@mountainviewdata.com>.
7
 * Extended attributes for symlinks and special files added per
8
 *  suggestion of Luka Renko <luka.renko@hermes.si>.
9
 */
10
11
/*
12
 * Extended attributes are stored on disk blocks allocated outside of
13
 * any inode. The i_file_acl field is then made to point to this allocated
14
 * block. If all extended attributes of an inode are identical, these
15
 * inodes may share the same extended attribute block. Such situations
16
 * are automatically detected by keeping a cache of recent attribute block
17
 * numbers and hashes over the block's contents in memory.
18
 *
19
 *
20
 * Extended attribute block layout:
21
 *
22
 *   +------------------+
23
 *   | header           |
24
 *   | entry 1          | |
25
 *   | entry 2          | | growing downwards
26
 *   | entry 3          | v
27
 *   | four null bytes  |
28
 *   | . . .            |
29
 *   | value 1          | ^
30
 *   | value 3          | | growing upwards
31
 *   | value 2          | |
32
 *   +------------------+
33
 *
34
 * The block header is followed by multiple entry descriptors. These entry
35
 * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
36
 * byte boundaries. The entry descriptors are sorted by attribute name,
37
 * so that two extended attribute blocks can be compared efficiently.
38
 *
39
 * Attribute values are aligned to the end of the block, stored in
40
 * no specific order. They are also padded to EXT2_XATTR_PAD byte
41
 * boundaries. No additional gaps are left between them.
42
 *
43
 * Locking strategy
44
 * ----------------
45
 * EXT2_I(inode)->i_file_acl is protected by EXT2_I(inode)->xattr_sem.
46
 * EA blocks are only changed if they are exclusive to an inode, so
47
 * holding xattr_sem also means that nothing but the EA block's reference
48
 * count will change. Multiple writers to an EA block are synchronized
49
 * by the bh lock. No more than a single bh lock is held at any time,
50
 * which avoids deadlocks.
51
 */
52
53
#include <linux/module.h>
54
#include <linux/locks.h>
55
#include <linux/slab.h>
56
#include <linux/fs.h>
57
#include <linux/ext2_fs.h>
58
#include <linux/ext2_xattr.h>
59
#include <linux/mbcache.h>
60
#include <linux/quotaops.h>
61
#include <linux/rwsem.h>
62
63
/* These symbols may be needed by a module. */
64
EXPORT_SYMBOL(ext2_xattr_register);
65
EXPORT_SYMBOL(ext2_xattr_unregister);
66
EXPORT_SYMBOL(ext2_xattr_get);
67
EXPORT_SYMBOL(ext2_xattr_list);
68
EXPORT_SYMBOL(ext2_xattr_set);
69
70
#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
71
#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
72
#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
73
#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
74
75
#ifdef EXT2_XATTR_DEBUG
76
# define ea_idebug(inode, f...) do { \
77
		printk(KERN_DEBUG "inode %s:%ld: ", \
78
			kdevname(inode->i_dev), inode->i_ino); \
79
		printk(f); \
80
		printk("\n"); \
81
	} while (0)
82
# define ea_bdebug(bh, f...) do { \
83
		printk(KERN_DEBUG "block %s:%ld: ", \
84
			kdevname(bh->b_dev), bh->b_blocknr); \
85
		printk(f); \
86
		printk("\n"); \
87
	} while (0)
88
#else
89
# define ea_idebug(f...)
90
# define ea_bdebug(f...)
91
#endif
92
93
static int ext2_xattr_set2(struct inode *, struct buffer_head *,
94
			   struct ext2_xattr_header *);
95
96
#ifdef CONFIG_EXT2_FS_XATTR_SHARING
97
98
static int ext2_xattr_cache_insert(struct buffer_head *);
99
static struct buffer_head *ext2_xattr_cache_find(struct inode *,
100
						 struct ext2_xattr_header *);
101
static void ext2_xattr_cache_remove(struct buffer_head *);
102
static void ext2_xattr_rehash(struct ext2_xattr_header *,
103
			      struct ext2_xattr_entry *);
104
105
static struct mb_cache *ext2_xattr_cache;
106
107
#else
108
# define ext2_xattr_cache_insert(bh) 0
109
# define ext2_xattr_cache_find(inode, header) NULL
110
# define ext2_xattr_cache_remove(bh) while(0) {}
111
# define ext2_xattr_rehash(header, entry) while(0) {}
112
#endif
113
114
struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
115
rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
116
117
int
118
ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
119
{
120
	int error = -EINVAL;
121
122
	if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
123
		write_lock(&ext2_handler_lock);
124
		if (!ext2_xattr_handlers[name_index-1]) {
125
			ext2_xattr_handlers[name_index-1] = handler;
126
			error = 0;
127
		}
128
		write_unlock(&ext2_handler_lock);
129
	}
130
	return error;
131
}
132
133
void
134
ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
135
{
136
	if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
137
		write_lock(&ext2_handler_lock);
138
		ext2_xattr_handlers[name_index-1] = NULL;
139
		write_unlock(&ext2_handler_lock);
140
	}
141
}
142
143
static inline const char *
144
strcmp_prefix(const char *a, const char *a_prefix)
145
{
146
	while (*a_prefix && *a == *a_prefix) {
147
		a++;
148
		a_prefix++;
149
	}
150
	return *a_prefix ? NULL : a;
151
}
152
153
/*
154
 * Decode the extended attribute name, and translate it into
155
 * the name_index and name suffix.
156
 */
157
static struct ext2_xattr_handler *
158
ext2_xattr_resolve_name(const char **name)
159
{
160
	struct ext2_xattr_handler *handler = NULL;
161
	int i;
162
163
	if (!*name)
164
		return NULL;
165
	read_lock(&ext2_handler_lock);
166
	for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
167
		if (ext2_xattr_handlers[i]) {
168
			const char *n = strcmp_prefix(*name,
169
				ext2_xattr_handlers[i]->prefix);
170
			if (n) {
171
				handler = ext2_xattr_handlers[i];
172
				*name = n;
173
				break;
174
			}
175
		}
176
	}
177
	read_unlock(&ext2_handler_lock);
178
	return handler;
179
}
180
181
static inline struct ext2_xattr_handler *
182
ext2_xattr_handler(int name_index)
183
{
184
	struct ext2_xattr_handler *handler = NULL;
185
	if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
186
		read_lock(&ext2_handler_lock);
187
		handler = ext2_xattr_handlers[name_index-1];
188
		read_unlock(&ext2_handler_lock);
189
	}
190
	return handler;
191
}
192
193
/*
194
 * Inode operation getxattr()
195
 *
196
 * dentry->d_inode->i_sem: don't care
197
 * BKL: held
198
 */
199
ssize_t
200
ext2_getxattr(struct dentry *dentry, const char *name,
201
	      void *buffer, size_t size)
202
{
203
	struct ext2_xattr_handler *handler;
204
	struct inode *inode = dentry->d_inode;
205
206
	handler = ext2_xattr_resolve_name(&name);
207
	if (!handler)
208
		return -EOPNOTSUPP;
209
	return handler->get(inode, name, buffer, size);
210
}
211
212
/*
213
 * Inode operation listxattr()
214
 *
215
 * dentry->d_inode->i_sem: don't care
216
 * BKL: held
217
 */
218
ssize_t
219
ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
220
{
221
	return ext2_xattr_list(dentry->d_inode, buffer, size);
222
}
223
224
/*
225
 * Inode operation setxattr()
226
 *
227
 * dentry->d_inode->i_sem: down
228
 * BKL: held
229
 */
230
int
231
ext2_setxattr(struct dentry *dentry, const char *name,
232
	      const void *value, size_t size, int flags)
233
{
234
	struct ext2_xattr_handler *handler;
235
	struct inode *inode = dentry->d_inode;
236
237
	if (size == 0)
238
		value = "";  /* empty EA, do not remove */
239
	handler = ext2_xattr_resolve_name(&name);
240
	if (!handler)
241
		return -EOPNOTSUPP;
242
	return handler->set(inode, name, value, size, flags);
243
}
244
245
/*
246
 * Inode operation removexattr()
247
 *
248
 * dentry->d_inode->i_sem: down
249
 * BKL: held
250
 */
251
int
252
ext2_removexattr(struct dentry *dentry, const char *name)
253
{
254
	struct ext2_xattr_handler *handler;
255
	struct inode *inode = dentry->d_inode;
256
257
	handler = ext2_xattr_resolve_name(&name);
258
	if (!handler)
259
		return -EOPNOTSUPP;
260
	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
261
}
262
263
/*
264
 * ext2_xattr_get()
265
 *
266
 * Copy an extended attribute into the buffer
267
 * provided, or compute the buffer size required.
268
 * Buffer is NULL to compute the size of the buffer required.
269
 *
270
 * Returns a negative error number on failure, or the number of bytes
271
 * used / required on success.
272
 */
273
int
274
ext2_xattr_get(struct inode *inode, int name_index, const char *name,
275
	       void *buffer, size_t buffer_size)
276
{
277
	struct buffer_head *bh = NULL;
278
	struct ext2_xattr_entry *entry;
279
	size_t size, name_len;
280
	char *end;
281
	int error;
282
283
	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
284
		  name_index, name, buffer, (long)buffer_size);
285
286
	if (name == NULL)
287
		return -EINVAL;
288
	down_read(&EXT2_I(inode)->xattr_sem);
289
	error = -ENODATA;
290
	if (!EXT2_I(inode)->i_file_acl)
291
		goto cleanup;
292
	ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl);
293
	bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
294
	error = -EIO;
295
	if (!bh)
296
		goto cleanup;
297
	ea_bdebug(bh, "b_count=%d, refcount=%d",
298
		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
299
	end = bh->b_data + bh->b_size;
300
	if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
301
	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
302
bad_block:	ext2_error(inode->i_sb, "ext2_xattr_get",
303
			"inode %ld: bad block %d", inode->i_ino,
304
			EXT2_I(inode)->i_file_acl);
305
		error = -EIO;
306
		goto cleanup;
307
	}
308
	/* find named attribute */
309
	name_len = strlen(name);
310
311
	error = -ERANGE;
312
	if (name_len > 255)
313
		goto cleanup;
314
	entry = FIRST_ENTRY(bh);
315
	while (!IS_LAST_ENTRY(entry)) {
316
		struct ext2_xattr_entry *next =
317
			EXT2_XATTR_NEXT(entry);
318
		if ((char *)next >= end)
319
			goto bad_block;
320
		if (name_index == entry->e_name_index &&
321
		    name_len == entry->e_name_len &&
322
		    memcmp(name, entry->e_name, name_len) == 0)
323
			goto found;
324
		entry = next;
325
	}
326
	/* Check the remaining name entries */
327
	while (!IS_LAST_ENTRY(entry)) {
328
		struct ext2_xattr_entry *next =
329
			EXT2_XATTR_NEXT(entry);
330
		if ((char *)next >= end)
331
			goto bad_block;
332
		entry = next;
333
	}
334
	if (ext2_xattr_cache_insert(bh))
335
		ea_idebug(inode, "cache insert failed");
336
	error = -ENODATA;
337
	goto cleanup;
338
found:
339
	/* check the buffer size */
340
	if (entry->e_value_block != 0)
341
		goto bad_block;
342
	size = le32_to_cpu(entry->e_value_size);
343
	if (size > inode->i_sb->s_blocksize ||
344
	    le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
345
		goto bad_block;
346
347
	if (ext2_xattr_cache_insert(bh))
348
		ea_idebug(inode, "cache insert failed");
349
	if (buffer) {
350
		error = -ERANGE;
351
		if (size > buffer_size)
352
			goto cleanup;
353
		/* return value of attribute */
354
		memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
355
			size);
356
	}
357
	error = size;
358
359
cleanup:
360
	brelse(bh);
361
	up_read(&EXT2_I(inode)->xattr_sem);
362
363
	return error;
364
}
365
366
/*
367
 * ext2_xattr_list()
368
 *
369
 * Copy a list of attribute names into the buffer
370
 * provided, or compute the buffer size required.
371
 * Buffer is NULL to compute the size of the buffer required.
372
 *
373
 * Returns a negative error number on failure, or the number of bytes
374
 * used / required on success.
375
 */
376
int
377
ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
378
{
379
	struct buffer_head *bh = NULL;
380
	struct ext2_xattr_entry *entry;
381
	size_t size = 0;
382
	char *buf, *end;
383
	int error;
384
385
	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
386
		  buffer, (long)buffer_size);
387
388
	down_read(&EXT2_I(inode)->xattr_sem);
389
	error = 0;
390
	if (!EXT2_I(inode)->i_file_acl)
391
		goto cleanup;
392
	ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl);
393
	bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
394
	error = -EIO;
395
	if (!bh)
396
		goto cleanup;
397
	ea_bdebug(bh, "b_count=%d, refcount=%d",
398
		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
399
	end = bh->b_data + bh->b_size;
400
	if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
401
	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
402
bad_block:	ext2_error(inode->i_sb, "ext2_xattr_list",
403
			"inode %ld: bad block %d", inode->i_ino,
404
			EXT2_I(inode)->i_file_acl);
405
		error = -EIO;
406
		goto cleanup;
407
	}
408
	/* compute the size required for the list of attribute names */
409
	for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
410
	     entry = EXT2_XATTR_NEXT(entry)) {
411
		struct ext2_xattr_handler *handler;
412
		struct ext2_xattr_entry *next =
413
			EXT2_XATTR_NEXT(entry);
414
		if ((char *)next >= end)
415
			goto bad_block;
416
417
		handler = ext2_xattr_handler(entry->e_name_index);
418
		if (handler)
419
			size += handler->list(NULL, inode, entry->e_name,
420
					      entry->e_name_len);
421
	}
422
423
	if (ext2_xattr_cache_insert(bh))
424
		ea_idebug(inode, "cache insert failed");
425
	if (!buffer) {
426
		error = size;
427
		goto cleanup;
428
	} else {
429
		error = -ERANGE;
430
		if (size > buffer_size)
431
			goto cleanup;
432
	}
433
434
	/* list the attribute names */
435
	buf = buffer;
436
	for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
437
	     entry = EXT2_XATTR_NEXT(entry)) {
438
		struct ext2_xattr_handler *handler;
439
		
440
		handler = ext2_xattr_handler(entry->e_name_index);
441
		if (handler)
442
			buf += handler->list(buf, inode, entry->e_name,
443
					     entry->e_name_len);
444
	}
445
	error = size;
446
447
cleanup:
448
	brelse(bh);
449
	up_read(&EXT2_I(inode)->xattr_sem);
450
451
	return error;
452
}
453
454
/*
455
 * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
456
 * not set, set it.
457
 */
458
static void ext2_xattr_update_super_block(struct super_block *sb)
459
{
460
	if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
461
		return;
462
463
	lock_super(sb);
464
	EXT2_SB(sb)->s_es->s_feature_compat |=
465
		cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
466
	sb->s_dirt = 1;
467
	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
468
	unlock_super(sb);
469
}
470
471
/*
472
 * ext2_xattr_set()
473
 *
474
 * Create, replace or remove an extended attribute for this inode. Buffer
475
 * is NULL to remove an existing extended attribute, and non-NULL to
476
 * either replace an existing extended attribute, or create a new extended
477
 * attribute. The flags XATTR_REPLACE and XATTR_CREATE
478
 * specify that an extended attribute must exist and must not exist
479
 * previous to the call, respectively.
480
 *
481
 * Returns 0, or a negative error number on failure.
482
 */
483
int
484
ext2_xattr_set(struct inode *inode, int name_index, const char *name,
485
	       const void *value, size_t value_len, int flags)
486
{
487
	struct super_block *sb = inode->i_sb;
488
	struct buffer_head *bh = NULL;
489
	struct ext2_xattr_header *header = NULL;
490
	struct ext2_xattr_entry *here, *last;
491
	size_t name_len, free, min_offs = sb->s_blocksize;
492
	int not_found = 1, error;
493
	char *end;
494
	
495
	/*
496
	 * header -- Points either into bh, or to a temporarily
497
	 *           allocated buffer.
498
	 * here -- The named entry found, or the place for inserting, within
499
	 *         the block pointed to by header.
500
	 * last -- Points right after the last named entry within the block
501
	 *         pointed to by header.
502
	 * min_offs -- The offset of the first value (values are aligned
503
	 *             towards the end of the block).
504
	 * end -- Points right after the block pointed to by header.
505
	 */
506
	
507
	ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
508
		  name_index, name, value, (long)value_len);
509
510
	if (IS_RDONLY(inode))
511
		return -EROFS;
512
	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
513
		return -EPERM;
514
	if (value == NULL)
515
		value_len = 0;
516
	if (name == NULL)
517
		return -EINVAL;
518
	name_len = strlen(name);
519
	if (name_len > 255 || value_len > sb->s_blocksize)
520
		return -ERANGE;
521
	down_write(&EXT2_I(inode)->xattr_sem);
522
	if (EXT2_I(inode)->i_file_acl) {
523
		/* The inode already has an extended attribute block. */
524
525
		bh = sb_bread(sb, EXT2_I(inode)->i_file_acl);
526
		error = -EIO;
527
		if (!bh)
528
			goto cleanup;
529
		ea_bdebug(bh, "b_count=%d, refcount=%d",
530
			atomic_read(&(bh->b_count)),
531
			le32_to_cpu(HDR(bh)->h_refcount));
532
		header = HDR(bh);
533
		end = bh->b_data + bh->b_size;
534
		if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
535
		    header->h_blocks != cpu_to_le32(1)) {
536
bad_block:		ext2_error(sb, "ext2_xattr_set",
537
				"inode %ld: bad block %d", inode->i_ino,
538
				EXT2_I(inode)->i_file_acl);
539
			error = -EIO;
540
			goto cleanup;
541
		}
542
		/* Find the named attribute. */
543
		here = FIRST_ENTRY(bh);
544
		while (!IS_LAST_ENTRY(here)) {
545
			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
546
			if ((char *)next >= end)
547
				goto bad_block;
548
			if (!here->e_value_block && here->e_value_size) {
549
				size_t offs = le16_to_cpu(here->e_value_offs);
550
				if (offs < min_offs)
551
					min_offs = offs;
552
			}
553
			not_found = name_index - here->e_name_index;
554
			if (!not_found)
555
				not_found = name_len - here->e_name_len;
556
			if (!not_found)
557
				not_found = memcmp(name, here->e_name,name_len);
558
			if (not_found <= 0)
559
				break;
560
			here = next;
561
		}
562
		last = here;
563
		/* We still need to compute min_offs and last. */
564
		while (!IS_LAST_ENTRY(last)) {
565
			struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
566
			if ((char *)next >= end)
567
				goto bad_block;
568
			if (!last->e_value_block && last->e_value_size) {
569
				size_t offs = le16_to_cpu(last->e_value_offs);
570
				if (offs < min_offs)
571
					min_offs = offs;
572
			}
573
			last = next;
574
		}
575
576
		/* Check whether we have enough space left. */
577
		free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
578
	} else {
579
		/* We will use a new extended attribute block. */
580
		free = sb->s_blocksize -
581
			sizeof(struct ext2_xattr_header) - sizeof(__u32);
582
		here = last = NULL;  /* avoid gcc uninitialized warning. */
583
	}
584
585
	if (not_found) {
586
		/* Request to remove a nonexistent attribute? */
587
		error = -ENODATA;
588
		if (flags & XATTR_REPLACE)
589
			goto cleanup;
590
		error = 0;
591
		if (value == NULL)
592
			goto cleanup;
593
	} else {
594
		/* Request to create an existing attribute? */
595
		error = -EEXIST;
596
		if (flags & XATTR_CREATE)
597
			goto cleanup;
598
		if (!here->e_value_block && here->e_value_size) {
599
			size_t size = le32_to_cpu(here->e_value_size);
600
601
			if (le16_to_cpu(here->e_value_offs) + size > 
602
			    sb->s_blocksize || size > sb->s_blocksize)
603
				goto bad_block;
604
			free += EXT2_XATTR_SIZE(size);
605
		}
606
		free += EXT2_XATTR_LEN(name_len);
607
	}
608
	error = -ENOSPC;
609
	if (free < EXT2_XATTR_LEN(name_len) + EXT2_XATTR_SIZE(value_len))
610
		goto cleanup;
611
612
	/* Here we know that we can set the new attribute. */
613
614
	if (header) {
615
		/* assert(header == HDR(bh)); */
616
		lock_buffer(bh);
617
		if (header->h_refcount == cpu_to_le32(1)) {
618
			ea_bdebug(bh, "modifying in-place");
619
			ext2_xattr_cache_remove(bh);
620
			/* keep the buffer locked while modifying it. */
621
		} else {
622
			int offset;
623
624
			unlock_buffer(bh);
625
			ea_bdebug(bh, "cloning");
626
			header = kmalloc(bh->b_size, GFP_KERNEL);
627
			error = -ENOMEM;
628
			if (header == NULL)
629
				goto cleanup;
630
			memcpy(header, HDR(bh), bh->b_size);
631
			header->h_refcount = cpu_to_le32(1);
632
			offset = (char *)header - bh->b_data;
633
			here = ENTRY((char *)here + offset);
634
			last = ENTRY((char *)last + offset);
635
		}
636
	} else {
637
		/* Allocate a buffer where we construct the new block. */
638
		header = kmalloc(sb->s_blocksize, GFP_KERNEL);
639
		error = -ENOMEM;
640
		if (header == NULL)
641
			goto cleanup;
642
		memset(header, 0, sb->s_blocksize);
643
		end = (char *)header + sb->s_blocksize;
644
		header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
645
		header->h_blocks = header->h_refcount = cpu_to_le32(1);
646
		last = here = ENTRY(header+1);
647
	}
648
649
	/* Iff we are modifying the block in-place, bh is locked here. */
650
651
	if (not_found) {
652
		/* Insert the new name. */
653
		int size = EXT2_XATTR_LEN(name_len);
654
		int rest = (char *)last - (char *)here;
655
		memmove((char *)here + size, here, rest);
656
		memset(here, 0, size);
657
		here->e_name_index = name_index;
658
		here->e_name_len = name_len;
659
		memcpy(here->e_name, name, name_len);
660
	} else {
661
		if (!here->e_value_block && here->e_value_size) {
662
			char *first_val = (char *)header + min_offs;
663
			int offs = le16_to_cpu(here->e_value_offs);
664
			char *val = (char *)header + offs;
665
			size_t size = EXT2_XATTR_SIZE(
666
				le32_to_cpu(here->e_value_size));
667
668
			if (size == EXT2_XATTR_SIZE(value_len)) {
669
				/* The old and the new value have the same
670
				   size. Just replace. */
671
				here->e_value_size = cpu_to_le32(value_len);
672
				memset(val + size - EXT2_XATTR_PAD, 0,
673
				       EXT2_XATTR_PAD); /* Clear pad bytes. */
674
				memcpy(val, value, value_len);
675
				goto skip_replace;
676
			}
677
678
			/* Remove the old value. */
679
			memmove(first_val + size, first_val, val - first_val);
680
			memset(first_val, 0, size);
681
			here->e_value_offs = 0;
682
			min_offs += size;
683
684
			/* Adjust all value offsets. */
685
			last = ENTRY(header+1);
686
			while (!IS_LAST_ENTRY(last)) {
687
				int o = le16_to_cpu(last->e_value_offs);
688
				if (!last->e_value_block && o < offs)
689
					last->e_value_offs =
690
						cpu_to_le16(o + size);
691
				last = EXT2_XATTR_NEXT(last);
692
			}
693
		}
694
		if (value == NULL) {
695
			/* Remove the old name. */
696
			int size = EXT2_XATTR_LEN(name_len);
697
			last = ENTRY((char *)last - size);
698
			memmove(here, (char*)here + size,
699
				(char*)last - (char*)here);
700
			memset(last, 0, size);
701
		}
702
	}
703
704
	if (value != NULL) {
705
		/* Insert the new value. */
706
		here->e_value_size = cpu_to_le32(value_len);
707
		if (value_len) {
708
			size_t size = EXT2_XATTR_SIZE(value_len);
709
			char *val = (char *)header + min_offs - size;
710
			here->e_value_offs =
711
				cpu_to_le16((char *)val - (char *)header);
712
			memset(val + size - EXT2_XATTR_PAD, 0,
713
			       EXT2_XATTR_PAD); /* Clear the pad bytes. */
714
			memcpy(val, value, value_len);
715
		}
716
	}
717
718
skip_replace:
719
	if (IS_LAST_ENTRY(ENTRY(header+1))) {
720
		/* This block is now empty. */
721
		if (bh && header == HDR(bh))
722
			unlock_buffer(bh);  /* we were modifying in-place. */
723
		error = ext2_xattr_set2(inode, bh, NULL);
724
	} else {
725
		ext2_xattr_rehash(header, here);
726
		if (bh && header == HDR(bh))
727
			unlock_buffer(bh);  /* we were modifying in-place. */
728
		error = ext2_xattr_set2(inode, bh, header);
729
	}
730
731
cleanup:
732
	brelse(bh);
733
	if (!(bh && header == HDR(bh)))
734
		kfree(header);
735
	up_write(&EXT2_I(inode)->xattr_sem);
736
737
	return error;
738
}
739
740
/*
741
 * Second half of ext2_xattr_set(): Update the file system.
742
 */
743
static int
744
ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
745
		struct ext2_xattr_header *header)
746
{
747
	struct super_block *sb = inode->i_sb;
748
	struct buffer_head *new_bh = NULL;
749
	int error;
750
751
	if (header) {
752
		new_bh = ext2_xattr_cache_find(inode, header);
753
		if (new_bh) {
754
			/*
755
			 * We found an identical block in the cache. The
756
			 * block returned is locked. The old block will
757
			 * be released after updating the inode.
758
			 */
759
			ea_bdebug(new_bh, "%s block %ld",
760
				(old_bh == new_bh) ? "keeping" : "reusing",
761
				new_bh->b_blocknr);
762
			
763
			error = -EDQUOT;
764
			/* How can we enforce the allocation? */
765
			if (DQUOT_ALLOC_BLOCK(inode, 1)) {
766
				unlock_buffer(new_bh);
767
				goto cleanup;
768
			}
769
			
770
			HDR(new_bh)->h_refcount = cpu_to_le32(
771
				le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
772
			ea_bdebug(new_bh, "refcount now=%d",
773
				le32_to_cpu(HDR(new_bh)->h_refcount));
774
			unlock_buffer(new_bh);
775
		} else if (old_bh && header == HDR(old_bh)) {
776
			/* Keep this block. No need to lock the block as we
777
			 * don't need to change the reference count. */
778
			new_bh = old_bh;
779
			get_bh(new_bh);
780
			ext2_xattr_cache_insert(new_bh);
781
		} else {
782
			/* We need to allocate a new block */
783
			int goal = le32_to_cpu(EXT2_SB(inode->i_sb)->s_es->
784
							   s_first_data_block) +
785
				   EXT2_I(inode)->i_block_group *
786
				   EXT2_BLOCKS_PER_GROUP(inode->i_sb);
787
			/* How can we enforce the allocation? */
788
			int block = ext2_new_block(inode, goal, 0, 0, &error);
789
			if (error)
790
				goto cleanup;
791
			ea_idebug(inode, "creating block %d", block);
792
793
			new_bh = sb_getblk(sb, block);
794
			if (!new_bh) {
795
				ext2_free_blocks(inode, block, 1);
796
				error = -EIO;
797
				goto cleanup;
798
			}
799
			lock_buffer(new_bh);
800
			memcpy(new_bh->b_data, header, new_bh->b_size);
801
			mark_buffer_uptodate(new_bh, 1);
802
			unlock_buffer(new_bh);
803
			ext2_xattr_cache_insert(new_bh);
804
			
805
			ext2_xattr_update_super_block(sb);
806
		}
807
		mark_buffer_dirty(new_bh);
808
		if (IS_SYNC(inode)) {
809
			ll_rw_block(WRITE, 1, &new_bh);
810
			wait_on_buffer(new_bh); 
811
			error = -EIO;
812
			if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
813
				goto cleanup;
814
		}
815
	}
816
817
	/* Update the inode. */
818
	EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
819
	inode->i_ctime = CURRENT_TIME;
820
	if (IS_SYNC(inode)) {
821
		error = ext2_sync_inode (inode);
822
		if (error)
823
			goto cleanup;
824
	} else
825
		mark_inode_dirty(inode);
826
827
	error = 0;
828
	if (old_bh && old_bh != new_bh) {
829
		/*
830
		 * If there was an old block and we are no longer using it,
831
		 * release the old block.
832
		*/
833
		lock_buffer(old_bh);
834
		if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
835
			/* Free the old block. */
836
			ea_bdebug(old_bh, "freeing");
837
			ext2_free_blocks(inode, old_bh->b_blocknr, 1);
838
			mark_buffer_clean(old_bh);
839
		} else {
840
			/* Decrement the refcount only. */
841
			HDR(old_bh)->h_refcount = cpu_to_le32(
842
				le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
843
			DQUOT_FREE_BLOCK(inode, 1);
844
			mark_buffer_dirty(old_bh);
845
			ea_bdebug(old_bh, "refcount now=%d",
846
				le32_to_cpu(HDR(old_bh)->h_refcount));
847
		}
848
		unlock_buffer(old_bh);
849
	}
850
851
cleanup:
852
	brelse(new_bh);
853
854
	return error;
855
}
856
857
/*
858
 * ext2_xattr_delete_inode()
859
 *
860
 * Free extended attribute resources associated with this inode. This
861
 * is called immediately before an inode is freed.
862
 */
863
void
864
ext2_xattr_delete_inode(struct inode *inode)
865
{
866
	struct buffer_head *bh = NULL;
867
868
	down_write(&EXT2_I(inode)->xattr_sem);
869
	if (!EXT2_I(inode)->i_file_acl)
870
		goto cleanup;
871
	bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
872
	if (!bh) {
873
		ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
874
			"inode %ld: block %d read error", inode->i_ino,
875
			EXT2_I(inode)->i_file_acl);
876
		goto cleanup;
877
	}
878
	ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
879
	if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
880
	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
881
		ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
882
			"inode %ld: bad block %d", inode->i_ino,
883
			EXT2_I(inode)->i_file_acl);
884
		goto cleanup;
885
	}
886
	lock_buffer(bh);
887
	if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
888
		ext2_xattr_cache_remove(bh);
889
		ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
890
		mark_buffer_clean(bh);
891
	} else {
892
		HDR(bh)->h_refcount = cpu_to_le32(
893
			le32_to_cpu(HDR(bh)->h_refcount) - 1);
894
		mark_buffer_dirty(bh);
895
		if (IS_SYNC(inode)) {
896
			ll_rw_block(WRITE, 1, &bh);
897
			wait_on_buffer(bh);
898
		}
899
		DQUOT_FREE_BLOCK(inode, 1);
900
	}
901
	ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount));
902
	unlock_buffer(bh);
903
	EXT2_I(inode)->i_file_acl = 0;
904
905
cleanup:
906
	brelse(bh);
907
	up_write(&EXT2_I(inode)->xattr_sem);
908
}
909
910
/*
911
 * ext2_xattr_put_super()
912
 *
913
 * This is called when a file system is unmounted.
914
 */
915
void
916
ext2_xattr_put_super(struct super_block *sb)
917
{
918
#ifdef CONFIG_EXT2_FS_XATTR_SHARING
919
	mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
920
#endif
921
}
922
923
#ifdef CONFIG_EXT2_FS_XATTR_SHARING
924
925
/*
926
 * ext2_xattr_cache_insert()
927
 *
928
 * Create a new entry in the extended attribute cache, and insert
929
 * it unless such an entry is already in the cache.
930
 *
931
 * Returns 0, or a negative error number on failure.
932
 */
933
static int
934
ext2_xattr_cache_insert(struct buffer_head *bh)
935
{
936
	__u32 hash = le32_to_cpu(HDR(bh)->h_hash);
937
	struct mb_cache_entry *ce;
938
	int error;
939
940
	ce = mb_cache_entry_alloc(ext2_xattr_cache);
941
	if (!ce)
942
		return -ENOMEM;
943
	error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
944
	if (error) {
945
		mb_cache_entry_free(ce);
946
		if (error == -EBUSY) {
947
			ea_bdebug(bh, "already in cache (%d cache entries)",
948
				atomic_read(&ext2_xattr_cache->c_entry_count));
949
			error = 0;
950
		}
951
	} else {
952
		ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
953
			  atomic_read(&ext2_xattr_cache->c_entry_count));
954
		mb_cache_entry_release(ce);
955
	}
956
	return error;
957
}
958
959
/*
960
 * ext2_xattr_cmp()
961
 *
962
 * Compare two extended attribute blocks for equality.
963
 *
964
 * Returns 0 if the blocks are equal, 1 if they differ, and
965
 * a negative error number on errors.
966
 */
967
static int
968
ext2_xattr_cmp(struct ext2_xattr_header *header1,
969
	       struct ext2_xattr_header *header2)
970
{
971
	struct ext2_xattr_entry *entry1, *entry2;
972
973
	entry1 = ENTRY(header1+1);
974
	entry2 = ENTRY(header2+1);
975
	while (!IS_LAST_ENTRY(entry1)) {
976
		if (IS_LAST_ENTRY(entry2))
977
			return 1;
978
		if (entry1->e_hash != entry2->e_hash ||
979
		    entry1->e_name_len != entry2->e_name_len ||
980
		    entry1->e_value_size != entry2->e_value_size ||
981
		    memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
982
			return 1;
983
		if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
984
			return -EIO;
985
		if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
986
			   (char *)header2 + le16_to_cpu(entry2->e_value_offs),
987
			   le32_to_cpu(entry1->e_value_size)))
988
			return 1;
989
990
		entry1 = EXT2_XATTR_NEXT(entry1);
991
		entry2 = EXT2_XATTR_NEXT(entry2);
992
	}
993
	if (!IS_LAST_ENTRY(entry2))
994
		return 1;
995
	return 0;
996
}
997
998
/*
999
 * ext2_xattr_cache_find()
1000
 *
1001
 * Find an identical extended attribute block.
1002
 *
1003
 * Returns a locked buffer head to the block found, or NULL if such
1004
 * a block was not found or an error occurred.
1005
 */
1006
static struct buffer_head *
1007
ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
1008
{
1009
	__u32 hash = le32_to_cpu(header->h_hash);
1010
	struct mb_cache_entry *ce;
1011
1012
	if (!header->h_hash)
1013
		return NULL;  /* never share */
1014
	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
1015
	ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
1016
	while (ce) {
1017
		struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
1018
1019
		if (!bh) {
1020
			ext2_error(inode->i_sb, "ext2_xattr_cache_find",
1021
				"inode %ld: block %ld read error",
1022
				inode->i_ino, ce->e_block);
1023
		} else {
1024
			lock_buffer(bh);
1025
			if (le32_to_cpu(HDR(bh)->h_refcount) >
1026
			    EXT2_XATTR_REFCOUNT_MAX) {
1027
				ea_idebug(inode, "block %ld refcount %d>%d",
1028
					  ce->e_block,
1029
					  le32_to_cpu(HDR(bh)->h_refcount),
1030
					  EXT2_XATTR_REFCOUNT_MAX);
1031
			} else if (!ext2_xattr_cmp(header, HDR(bh))) {
1032
				ea_bdebug(bh, "b_count=%d",
1033
					  atomic_read(&(bh->b_count)));
1034
				mb_cache_entry_release(ce);
1035
				/* buffer will be unlocked by caller */
1036
				return bh;
1037
			}
1038
			unlock_buffer(bh);
1039
			brelse(bh);
1040
		}
1041
		ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
1042
	}
1043
	return NULL;
1044
}
1045
1046
/*
1047
 * ext2_xattr_cache_remove()
1048
 *
1049
 * Remove the cache entry of a block from the cache. Called when a
1050
 * block becomes invalid.
1051
 */
1052
static void
1053
ext2_xattr_cache_remove(struct buffer_head *bh)
1054
{
1055
	struct mb_cache_entry *ce;
1056
1057
	ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
1058
	if (ce) {
1059
		ea_bdebug(bh, "removing (%d cache entries remaining)",
1060
			  atomic_read(&ext2_xattr_cache->c_entry_count)-1);
1061
		mb_cache_entry_free(ce);
1062
	} else 
1063
		ea_bdebug(bh, "no cache entry");
1064
}
1065
1066
#define NAME_HASH_SHIFT 5
1067
#define VALUE_HASH_SHIFT 16
1068
1069
/*
1070
 * ext2_xattr_hash_entry()
1071
 *
1072
 * Compute the hash of an extended attribute.
1073
 */
1074
static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
1075
					 struct ext2_xattr_entry *entry)
1076
{
1077
	__u32 hash = 0;
1078
	char *name = entry->e_name;
1079
	int n;
1080
1081
	for (n=0; n < entry->e_name_len; n++) {
1082
		hash = (hash << NAME_HASH_SHIFT) ^
1083
		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
1084
		       *name++;
1085
	}
1086
1087
	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
1088
		__u32 *value = (__u32 *)((char *)header +
1089
			le16_to_cpu(entry->e_value_offs));
1090
		for (n = (le32_to_cpu(entry->e_value_size) +
1091
		     EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
1092
			hash = (hash << VALUE_HASH_SHIFT) ^
1093
			       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
1094
			       le32_to_cpu(*value++);
1095
		}
1096
	}
1097
	entry->e_hash = cpu_to_le32(hash);
1098
}
1099
1100
#undef NAME_HASH_SHIFT
1101
#undef VALUE_HASH_SHIFT
1102
1103
#define BLOCK_HASH_SHIFT 16
1104
1105
/*
1106
 * ext2_xattr_rehash()
1107
 *
1108
 * Re-compute the extended attribute hash value after an entry has changed.
1109
 */
1110
static void ext2_xattr_rehash(struct ext2_xattr_header *header,
1111
			      struct ext2_xattr_entry *entry)
1112
{
1113
	struct ext2_xattr_entry *here;
1114
	__u32 hash = 0;
1115
	
1116
	ext2_xattr_hash_entry(header, entry);
1117
	here = ENTRY(header+1);
1118
	while (!IS_LAST_ENTRY(here)) {
1119
		if (!here->e_hash) {
1120
			/* Block is not shared if an entry's hash value == 0 */
1121
			hash = 0;
1122
			break;
1123
		}
1124
		hash = (hash << BLOCK_HASH_SHIFT) ^
1125
		       (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
1126
		       le32_to_cpu(here->e_hash);
1127
		here = EXT2_XATTR_NEXT(here);
1128
	}
1129
	header->h_hash = cpu_to_le32(hash);
1130
}
1131
1132
#undef BLOCK_HASH_SHIFT
1133
1134
int __init
1135
init_ext2_xattr(void)
1136
{
1137
	ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
1138
		sizeof(struct mb_cache_entry) +
1139
		sizeof(struct mb_cache_entry_index), 1, 61);
1140
	if (!ext2_xattr_cache)
1141
		return -ENOMEM;
1142
1143
	return 0;
1144
}
1145
1146
void
1147
exit_ext2_xattr(void)
1148
{
1149
	mb_cache_destroy(ext2_xattr_cache);
1150
}
1151
1152
#else  /* CONFIG_EXT2_FS_XATTR_SHARING */
1153
1154
int __init
1155
init_ext2_xattr(void)
1156
{
1157
	return 0;
1158
}
1159
1160
void
1161
exit_ext2_xattr(void)
1162
{
1163
}
1164
1165
#endif  /* CONFIG_EXT2_FS_XATTR_SHARING */
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/xattr_trusted.c (+76 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext2/xattr_trusted.c
3
 * Handler for trusted extended attributes.
4
 *
5
 * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
6
 */
7
8
#include <linux/sched.h>
9
#include <linux/fs.h>
10
#include <linux/ext2_fs.h>
11
#include <linux/ext2_xattr.h>
12
13
#define XATTR_TRUSTED_PREFIX "trusted."
14
15
static size_t
16
ext2_xattr_trusted_list(char *list, struct inode *inode,
17
			const char *name, int name_len)
18
{
19
	const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
20
21
	if (!capable(CAP_SYS_ADMIN))
22
		return 0;
23
24
	if (list) {
25
		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
26
		memcpy(list+prefix_len, name, name_len);
27
		list[prefix_len + name_len] = '\0';
28
	}
29
	return prefix_len + name_len + 1;
30
}
31
32
static int
33
ext2_xattr_trusted_get(struct inode *inode, const char *name,
34
		       void *buffer, size_t size)
35
{
36
	if (strcmp(name, "") == 0)
37
		return -EINVAL;
38
	if (!capable(CAP_SYS_ADMIN))
39
		return -EPERM;
40
	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
41
			      buffer, size);
42
}
43
44
static int
45
ext2_xattr_trusted_set(struct inode *inode, const char *name,
46
		       const void *value, size_t size, int flags)
47
{
48
49
	if (strcmp(name, "") == 0)
50
		return -EINVAL;
51
	if (!capable(CAP_SYS_ADMIN))
52
		return -EPERM;
53
	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
54
			      value, size, flags);
55
}
56
57
struct ext2_xattr_handler ext2_xattr_trusted_handler = {
58
	prefix:	XATTR_TRUSTED_PREFIX,
59
	list:	ext2_xattr_trusted_list,
60
	get:	ext2_xattr_trusted_get,
61
	set:	ext2_xattr_trusted_set,
62
};
63
64
int __init
65
init_ext2_xattr_trusted(void)
66
{
67
	return ext2_xattr_register(EXT2_XATTR_INDEX_TRUSTED,
68
				   &ext2_xattr_trusted_handler);
69
}
70
71
void
72
exit_ext2_xattr_trusted(void)
73
{
74
	ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
75
			      &ext2_xattr_trusted_handler);
76
}
(-)linux-2.4.22-ppc-dev.orig/fs/ext2/xattr_user.c (+95 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext2/xattr_user.c
3
 * Handler for extended user attributes.
4
 *
5
 * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
6
 */
7
8
#include <linux/module.h>
9
#include <linux/string.h>
10
#include <linux/fs.h>
11
#include <linux/ext2_fs.h>
12
#include <linux/ext2_xattr.h>
13
14
#ifdef CONFIG_EXT2_FS_POSIX_ACL
15
# include <linux/ext2_acl.h>
16
#endif
17
18
#define XATTR_USER_PREFIX "user."
19
20
static size_t
21
ext2_xattr_user_list(char *list, struct inode *inode,
22
		     const char *name, int name_len)
23
{
24
	const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
25
26
	if (!test_opt(inode->i_sb, XATTR_USER))
27
		return 0;
28
29
	if (list) {
30
		memcpy(list, XATTR_USER_PREFIX, prefix_len);
31
		memcpy(list+prefix_len, name, name_len);
32
		list[prefix_len + name_len] = '\0';
33
	}
34
	return prefix_len + name_len + 1;
35
}
36
37
static int
38
ext2_xattr_user_get(struct inode *inode, const char *name,
39
		    void *buffer, size_t size)
40
{
41
	int error;
42
43
	if (strcmp(name, "") == 0)
44
		return -EINVAL;
45
	if (!test_opt(inode->i_sb, XATTR_USER))
46
		return -EOPNOTSUPP;
47
	error = permission(inode, MAY_READ);
48
	if (error)
49
		return error;
50
51
	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
52
			      buffer, size);
53
}
54
55
static int
56
ext2_xattr_user_set(struct inode *inode, const char *name,
57
		    const void *value, size_t size, int flags)
58
{
59
	int error;
60
61
	if (strcmp(name, "") == 0)
62
		return -EINVAL;
63
	if (!test_opt(inode->i_sb, XATTR_USER))
64
		return -EOPNOTSUPP;
65
	if (!S_ISREG(inode->i_mode) &&
66
	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
67
		return -EPERM;
68
	error = permission(inode, MAY_WRITE);
69
	if (error)
70
		return error;
71
72
	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
73
			      value, size, flags);
74
}
75
76
struct ext2_xattr_handler ext2_xattr_user_handler = {
77
	prefix:	XATTR_USER_PREFIX,
78
	list:	ext2_xattr_user_list,
79
	get:	ext2_xattr_user_get,
80
	set:	ext2_xattr_user_set,
81
};
82
83
int __init
84
init_ext2_xattr_user(void)
85
{
86
	return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
87
				   &ext2_xattr_user_handler);
88
}
89
90
void
91
exit_ext2_xattr_user(void)
92
{
93
	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
94
			      &ext2_xattr_user_handler);
95
}
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/Makefile (-1 / +7 lines)
Lines 1-5 Link Here
1
#
1
#
2
# Makefile for the linux ext2-filesystem routines.
2
# Makefile for the linux ext3-filesystem routines.
3
#
3
#
4
# Note! Dependencies are done automagically by 'make dep', which also
4
# Note! Dependencies are done automagically by 'make dep', which also
5
# removes any old dependencies. DON'T put your own dependencies here
5
# removes any old dependencies. DON'T put your own dependencies here
Lines 13-16 Link Here
13
		ioctl.o namei.o super.o symlink.o
13
		ioctl.o namei.o super.o symlink.o
14
obj-m    := $(O_TARGET)
14
obj-m    := $(O_TARGET)
15
15
16
export-objs += xattr.o
17
obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
18
obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
19
obj-$(CONFIG_EXT3_FS_XATTR_TRUSTED) += xattr_trusted.o
20
obj-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
21
16
include $(TOPDIR)/Rules.make
22
include $(TOPDIR)/Rules.make
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/acl.c (+585 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext3/acl.c
3
 *
4
 * Copyright (C) 2001-2003 by Andreas Gruenbacher, <agruen@suse.de>
5
 */
6
7
#include <linux/module.h>
8
#include <linux/sched.h>
9
#include <linux/slab.h>
10
#include <linux/fs.h>
11
#include <linux/ext3_jbd.h>
12
#include <linux/ext3_fs.h>
13
#include <linux/ext3_xattr.h>
14
#include <linux/ext3_acl.h>
15
16
/*
17
 * Convert from filesystem to in-memory representation.
18
 */
19
static struct posix_acl *
20
ext3_acl_from_disk(const void *value, size_t size)
21
{
22
	const char *end = (char *)value + size;
23
	size_t n, count;
24
	struct posix_acl *acl;
25
26
	if (!value)
27
		return NULL;
28
	if (size < sizeof(ext3_acl_header))
29
		 return ERR_PTR(-EINVAL);
30
	if (((ext3_acl_header *)value)->a_version !=
31
	    cpu_to_le32(EXT3_ACL_VERSION))
32
		return ERR_PTR(-EINVAL);
33
	value = (char *)value + sizeof(ext3_acl_header);
34
	count = ext3_acl_count(size);
35
	if (count < 0)
36
		return ERR_PTR(-EINVAL);
37
	if (count == 0)
38
		return NULL;
39
	acl = posix_acl_alloc(count, GFP_KERNEL);
40
	if (!acl)
41
		return ERR_PTR(-ENOMEM);
42
	for (n=0; n < count; n++) {
43
		ext3_acl_entry *entry =
44
			(ext3_acl_entry *)value;
45
		if ((char *)value + sizeof(ext3_acl_entry_short) > end)
46
			goto fail;
47
		acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
48
		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
49
		switch(acl->a_entries[n].e_tag) {
50
			case ACL_USER_OBJ:
51
			case ACL_GROUP_OBJ:
52
			case ACL_MASK:
53
			case ACL_OTHER:
54
				value = (char *)value +
55
					sizeof(ext3_acl_entry_short);
56
				acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
57
				break;
58
59
			case ACL_USER:
60
			case ACL_GROUP:
61
				value = (char *)value + sizeof(ext3_acl_entry);
62
				if ((char *)value > end)
63
					goto fail;
64
				acl->a_entries[n].e_id =
65
					le32_to_cpu(entry->e_id);
66
				break;
67
68
			default:
69
				goto fail;
70
		}
71
	}
72
	if (value != end)
73
		goto fail;
74
	return acl;
75
76
fail:
77
	posix_acl_release(acl);
78
	return ERR_PTR(-EINVAL);
79
}
80
81
/*
82
 * Convert from in-memory to filesystem representation.
83
 */
84
static void *
85
ext3_acl_to_disk(const struct posix_acl *acl, size_t *size)
86
{
87
	ext3_acl_header *ext_acl;
88
	char *e;
89
	size_t n;
90
91
	*size = ext3_acl_size(acl->a_count);
92
	ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) +
93
		acl->a_count * sizeof(ext3_acl_entry), GFP_KERNEL);
94
	if (!ext_acl)
95
		return ERR_PTR(-ENOMEM);
96
	ext_acl->a_version = cpu_to_le32(EXT3_ACL_VERSION);
97
	e = (char *)ext_acl + sizeof(ext3_acl_header);
98
	for (n=0; n < acl->a_count; n++) {
99
		ext3_acl_entry *entry = (ext3_acl_entry *)e;
100
		entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
101
		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
102
		switch(acl->a_entries[n].e_tag) {
103
			case ACL_USER:
104
			case ACL_GROUP:
105
				entry->e_id =
106
					cpu_to_le32(acl->a_entries[n].e_id);
107
				e += sizeof(ext3_acl_entry);
108
				break;
109
110
			case ACL_USER_OBJ:
111
			case ACL_GROUP_OBJ:
112
			case ACL_MASK:
113
			case ACL_OTHER:
114
				e += sizeof(ext3_acl_entry_short);
115
				break;
116
117
			default:
118
				goto fail;
119
		}
120
	}
121
	return (char *)ext_acl;
122
123
fail:
124
	kfree(ext_acl);
125
	return ERR_PTR(-EINVAL);
126
}
127
128
/*
129
 * Inode operation get_posix_acl().
130
 *
131
 * inode->i_sem: don't care
132
 * BKL: held
133
 */
134
struct posix_acl *
135
ext3_get_acl(struct inode *inode, int type)
136
{
137
	const size_t max_size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
138
	struct ext3_inode_info *ei = EXT3_I(inode);
139
	int name_index;
140
	char *value;
141
	struct posix_acl *acl;
142
	int retval;
143
144
	if (!IS_POSIXACL(inode))
145
		return 0;
146
147
	switch(type) {
148
		case ACL_TYPE_ACCESS:
149
			if (ei->i_acl != EXT3_ACL_NOT_CACHED)
150
				return posix_acl_dup(ei->i_acl);
151
			name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
152
			break;
153
154
		case ACL_TYPE_DEFAULT:
155
			if (ei->i_default_acl != EXT3_ACL_NOT_CACHED)
156
				return posix_acl_dup(ei->i_default_acl);
157
			name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
158
			break;
159
160
		default:
161
			return ERR_PTR(-EINVAL);
162
	}
163
	value = kmalloc(max_size, GFP_KERNEL);
164
	if (!value)
165
		return ERR_PTR(-ENOMEM);
166
167
	retval = ext3_xattr_get(inode, name_index, "", value, max_size);
168
	acl = ERR_PTR(retval);
169
	if (retval > 0)
170
		acl = ext3_acl_from_disk(value, retval);
171
	else if (retval == -ENODATA || retval == -ENOSYS)
172
		acl = NULL;
173
	kfree(value);
174
175
	if (!IS_ERR(acl)) {
176
		switch(type) {
177
			case ACL_TYPE_ACCESS:
178
				ei->i_acl = posix_acl_dup(acl);
179
				break;
180
181
			case ACL_TYPE_DEFAULT:
182
				ei->i_default_acl = posix_acl_dup(acl);
183
				break;
184
		}
185
	}
186
	return acl;
187
}
188
189
/*
190
 * inode->i_sem: down, or inode is just being initialized
191
 * BKL: held
192
 */
193
static int
194
ext3_do_set_acl(handle_t *handle, struct inode *inode, int type,
195
		struct posix_acl *acl)
196
{
197
	struct ext3_inode_info *ei = EXT3_I(inode);
198
	int name_index;
199
	void *value = NULL;
200
	size_t size;
201
	int error;
202
203
	if (S_ISLNK(inode->i_mode))
204
		return -ENODATA;
205
206
	switch(type) {
207
		case ACL_TYPE_ACCESS:
208
			name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
209
			if (acl) {
210
				mode_t mode = inode->i_mode;
211
				error = posix_acl_equiv_mode(acl, &mode);
212
				if (error < 0)
213
					return error;
214
				else {
215
					inode->i_mode = mode;
216
					ext3_mark_inode_dirty(handle, inode);
217
					if (error == 0)
218
						acl = NULL;
219
				}
220
			}
221
			break;
222
223
		case ACL_TYPE_DEFAULT:
224
			name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
225
			if (!S_ISDIR(inode->i_mode))
226
				return acl ? -EACCES : 0;
227
			break;
228
229
		default:
230
			return -EINVAL;
231
	}
232
 	if (acl) {
233
		if (acl->a_count > EXT3_ACL_MAX_ENTRIES)
234
			return -EINVAL;
235
		value = ext3_acl_to_disk(acl, &size);
236
		if (IS_ERR(value))
237
			return (int)PTR_ERR(value);
238
	}
239
240
	error = ext3_xattr_set_handle(handle, inode, name_index, "",
241
				      value, size, 0);
242
243
	if (value)
244
		kfree(value);
245
	if (!error) {
246
		switch(type) {
247
			case ACL_TYPE_ACCESS:
248
				if (ei->i_acl != EXT3_ACL_NOT_CACHED)
249
					posix_acl_release(ei->i_acl);
250
				ei->i_acl = posix_acl_dup(acl);
251
				break;
252
253
			case ACL_TYPE_DEFAULT:
254
				if (ei->i_default_acl != EXT3_ACL_NOT_CACHED)
255
					posix_acl_release(ei->i_default_acl);
256
				ei->i_default_acl = posix_acl_dup(acl);
257
				break;
258
		}
259
	}
260
	return error;
261
}
262
263
/*
264
 * Inode operation permission().
265
 *
266
 * inode->i_sem: don't care
267
 * BKL: held
268
 */
269
int
270
ext3_permission(struct inode *inode, int mask)
271
{
272
	int mode = inode->i_mode;
273
274
	/* Nobody gets write access to a read-only fs */
275
	if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
276
	    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
277
		return -EROFS;
278
	/* Nobody gets write access to an immutable file */
279
	if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
280
	    return -EACCES;
281
	if (current->fsuid == inode->i_uid) {
282
		mode >>= 6;
283
	} else if (IS_POSIXACL(inode)) {
284
		struct ext3_inode_info *ei = EXT3_I(inode);
285
286
		/* The access ACL cannot grant access if the group class
287
		   permission bits don't contain all requested permissions. */
288
		if (((mode >> 3) & mask & S_IRWXO) != mask)
289
			goto check_groups;
290
		if (ei->i_acl == EXT3_ACL_NOT_CACHED) {
291
			struct posix_acl *acl =
292
				ext3_get_acl(inode, ACL_TYPE_ACCESS);
293
294
			if (IS_ERR(acl))
295
				return PTR_ERR(acl);
296
			posix_acl_release(acl);
297
			if (ei->i_acl == EXT3_ACL_NOT_CACHED)
298
				return -EIO;
299
		}
300
		if (ei->i_acl) {
301
			int error = posix_acl_permission(inode, ei->i_acl,mask);
302
			if (error == -EACCES)
303
				goto check_capabilities;
304
			return error;
305
		} else
306
			goto check_groups;
307
	} else {
308
check_groups:
309
		if (in_group_p(inode->i_gid))
310
			mode >>= 3;
311
	}
312
	if ((mode & mask & S_IRWXO) == mask)
313
		return 0;
314
315
check_capabilities:
316
	/* Allowed to override Discretionary Access Control? */
317
	if ((mask & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
318
		if (capable(CAP_DAC_OVERRIDE))
319
			return 0;
320
	/* Read and search granted if capable(CAP_DAC_READ_SEARCH) */
321
	if (capable(CAP_DAC_READ_SEARCH) && ((mask == MAY_READ) ||
322
	    (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))))
323
		return 0;
324
	return -EACCES;
325
}
326
327
/*
328
 * Initialize the ACLs of a new inode. Called from ext3_new_inode.
329
 *
330
 * dir->i_sem: don't care
331
 * inode->i_sem: up (access to inode is still exclusive)
332
 * BKL: held
333
 */
334
int
335
ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
336
{
337
	struct posix_acl *acl = NULL;
338
	int error = 0;
339
340
	if (!S_ISLNK(inode->i_mode)) {
341
		if (IS_POSIXACL(dir)) {
342
			acl = ext3_get_acl(dir, ACL_TYPE_DEFAULT);
343
			if (IS_ERR(acl))
344
				return PTR_ERR(acl);
345
		}
346
		if (!acl) {
347
			inode->i_mode &= ~current->fs->umask;
348
			ext3_mark_inode_dirty(handle, inode);
349
		}
350
	}
351
	if (IS_POSIXACL(inode) && acl) {
352
		struct posix_acl *clone;
353
		mode_t mode;
354
355
		if (S_ISDIR(inode->i_mode)) {
356
			error = ext3_do_set_acl(handle, inode,
357
						ACL_TYPE_DEFAULT, acl);
358
			if (error)
359
				goto cleanup;
360
		}
361
		clone = posix_acl_clone(acl, GFP_KERNEL);
362
		error = -ENOMEM;
363
		if (!clone)
364
			goto cleanup;
365
		
366
		mode = inode->i_mode;
367
		error = posix_acl_create_masq(clone, &mode);
368
		if (error >= 0) {
369
			inode->i_mode = mode;
370
			ext3_mark_inode_dirty(handle, inode);
371
			if (error > 0) {
372
				/* This is an extended ACL */
373
				error = ext3_do_set_acl(handle, inode,
374
							ACL_TYPE_ACCESS, clone);
375
			}
376
		}
377
		posix_acl_release(clone);
378
	}
379
cleanup:
380
	posix_acl_release(acl);
381
	return error;
382
}
383
384
/*
385
 * Does chmod for an inode that may have an Access Control List. The
386
 * inode->i_mode field must be updated to the desired value by the caller
387
 * before calling this function.
388
 * Returns 0 on success, or a negative error number.
389
 *
390
 * We change the ACL rather than storing some ACL entries in the file
391
 * mode permission bits (which would be more efficient), because that
392
 * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
393
 * for directories) are added. There are no more bits available in the
394
 * file mode.
395
 *
396
 * inode->i_sem: down
397
 * BKL: held
398
 */
399
int
400
ext3_acl_chmod(handle_t *handle, struct inode *inode)
401
{
402
	struct posix_acl *acl, *clone;
403
        int error;
404
405
	if (S_ISLNK(inode->i_mode))
406
		return -EOPNOTSUPP;
407
	if (!IS_POSIXACL(inode))
408
		return 0;
409
	acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
410
	if (IS_ERR(acl) || !acl)
411
		return PTR_ERR(acl);
412
	clone = posix_acl_clone(acl, GFP_KERNEL);
413
	posix_acl_release(acl);
414
	if (!clone)
415
		return -ENOMEM;
416
	error = posix_acl_chmod_masq(clone, inode->i_mode);
417
	if (!error)
418
		error = ext3_do_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
419
	posix_acl_release(clone);
420
	return error;
421
}
422
423
/*
424
 * Extended attribut handlers
425
 */
426
static size_t
427
ext3_xattr_list_acl_access(char *list, struct inode *inode,
428
			   const char *name, int name_len)
429
{
430
	const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
431
432
	if (!IS_POSIXACL(inode))
433
		return 0;
434
	if (list)
435
		memcpy(list, XATTR_NAME_ACL_ACCESS, size);
436
	return size;
437
}
438
439
static size_t
440
ext3_xattr_list_acl_default(char *list, struct inode *inode,
441
			    const char *name, int name_len)
442
{
443
	const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
444
445
	if (!IS_POSIXACL(inode))
446
		return 0;
447
	if (list)
448
		memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
449
	return size;
450
}
451
452
static int
453
ext3_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
454
{
455
	struct posix_acl *acl;
456
	int error;
457
458
	if (!IS_POSIXACL(inode))
459
		return -EOPNOTSUPP;
460
461
	acl = ext3_get_acl(inode, type);
462
	if (IS_ERR(acl))
463
		return PTR_ERR(acl);
464
	if (acl == NULL)
465
		return -ENODATA;
466
	error = posix_acl_to_xattr(acl, buffer, size);
467
	posix_acl_release(acl);
468
469
	return error;
470
}
471
472
static int
473
ext3_xattr_get_acl_access(struct inode *inode, const char *name,
474
			  void *buffer, size_t size)
475
{
476
	if (strcmp(name, "") != 0)
477
		return -EINVAL;
478
	return ext3_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
479
}
480
481
static int
482
ext3_xattr_get_acl_default(struct inode *inode, const char *name,
483
			   void *buffer, size_t size)
484
{
485
	if (strcmp(name, "") != 0)
486
		return -EINVAL;
487
	return ext3_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
488
}
489
490
static int
491
ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
492
		   size_t size)
493
{
494
	handle_t *handle;
495
	struct posix_acl *acl;
496
	int error;
497
498
	if (!IS_POSIXACL(inode))
499
		return -EOPNOTSUPP;
500
	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
501
		return -EPERM;
502
503
	if (value) {
504
		acl = posix_acl_from_xattr(value, size);
505
		if (IS_ERR(acl))
506
			return PTR_ERR(acl);
507
		else if (acl) {
508
			error = posix_acl_valid(acl);
509
			if (error)
510
				goto release_and_out;
511
		}
512
	} else
513
		acl = NULL;
514
515
	handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
516
	if (IS_ERR(handle))
517
		return PTR_ERR(handle);
518
	error = ext3_do_set_acl(handle, inode, type, acl);
519
	ext3_journal_stop(handle, inode);
520
521
release_and_out:
522
	posix_acl_release(acl);
523
	return error;
524
}
525
526
static int
527
ext3_xattr_set_acl_access(struct inode *inode, const char *name,
528
			  const void *value, size_t size, int flags)
529
{
530
	if (strcmp(name, "") != 0)
531
		return -EINVAL;
532
	return ext3_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
533
}
534
535
static int
536
ext3_xattr_set_acl_default(struct inode *inode, const char *name,
537
			   const void *value, size_t size, int flags)
538
{
539
	if (strcmp(name, "") != 0)
540
		return -EINVAL;
541
	return ext3_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
542
}
543
544
struct ext3_xattr_handler ext3_xattr_acl_access_handler = {
545
	prefix:	XATTR_NAME_ACL_ACCESS,
546
	list:	ext3_xattr_list_acl_access,
547
	get:	ext3_xattr_get_acl_access,
548
	set:	ext3_xattr_set_acl_access,
549
};
550
551
struct ext3_xattr_handler ext3_xattr_acl_default_handler = {
552
	prefix:	XATTR_NAME_ACL_DEFAULT,
553
	list:	ext3_xattr_list_acl_default,
554
	get:	ext3_xattr_get_acl_default,
555
	set:	ext3_xattr_set_acl_default,
556
};
557
558
void
559
exit_ext3_acl(void)
560
{
561
	ext3_xattr_unregister(EXT3_XATTR_INDEX_POSIX_ACL_ACCESS,
562
			      &ext3_xattr_acl_access_handler);
563
	ext3_xattr_unregister(EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT,
564
			      &ext3_xattr_acl_default_handler);
565
}
566
567
int __init
568
init_ext3_acl(void)
569
{
570
	int error;
571
572
	error = ext3_xattr_register(EXT3_XATTR_INDEX_POSIX_ACL_ACCESS,
573
				    &ext3_xattr_acl_access_handler);
574
	if (error)
575
		goto fail;
576
	error = ext3_xattr_register(EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT,
577
				    &ext3_xattr_acl_default_handler);
578
	if (error)
579
		goto fail;
580
	return 0;
581
582
fail:
583
	exit_ext3_acl();
584
	return error;
585
}
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/file.c (+8 lines)
Lines 21-28 Link Here
21
#include <linux/sched.h>
21
#include <linux/sched.h>
22
#include <linux/fs.h>
22
#include <linux/fs.h>
23
#include <linux/locks.h>
23
#include <linux/locks.h>
24
#include <linux/ext3_jbd.h>
24
#include <linux/jbd.h>
25
#include <linux/jbd.h>
25
#include <linux/ext3_fs.h>
26
#include <linux/ext3_fs.h>
27
#include <linux/ext3_xattr.h>
28
#include <linux/ext3_acl.h>
26
#include <linux/ext3_jbd.h>
29
#include <linux/ext3_jbd.h>
27
#include <linux/smp_lock.h>
30
#include <linux/smp_lock.h>
28
31
Lines 124-128 Link Here
124
struct inode_operations ext3_file_inode_operations = {
127
struct inode_operations ext3_file_inode_operations = {
125
	truncate:	ext3_truncate,		/* BKL held */
128
	truncate:	ext3_truncate,		/* BKL held */
126
	setattr:	ext3_setattr,		/* BKL held */
129
	setattr:	ext3_setattr,		/* BKL held */
130
	setxattr:	ext3_setxattr,		/* BKL held */
131
	getxattr:	ext3_getxattr,		/* BKL held */
132
	listxattr:	ext3_listxattr,		/* BKL held */
133
	removexattr:	ext3_removexattr,	/* BKL held */
134
	permission:	ext3_permission,	/* BKL held */
127
};
135
};
128
136
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/ialloc.c (-6 / +21 lines)
Lines 17-22 Link Here
17
#include <linux/jbd.h>
17
#include <linux/jbd.h>
18
#include <linux/ext3_fs.h>
18
#include <linux/ext3_fs.h>
19
#include <linux/ext3_jbd.h>
19
#include <linux/ext3_jbd.h>
20
#include <linux/ext3_xattr.h>
21
#include <linux/ext3_acl.h>
20
#include <linux/stat.h>
22
#include <linux/stat.h>
21
#include <linux/string.h>
23
#include <linux/string.h>
22
#include <linux/locks.h>
24
#include <linux/locks.h>
Lines 216-221 Link Here
216
	 * as writing the quota to disk may need the lock as well.
218
	 * as writing the quota to disk may need the lock as well.
217
	 */
219
	 */
218
	DQUOT_INIT(inode);
220
	DQUOT_INIT(inode);
221
	ext3_xattr_delete_inode(handle, inode);
219
	DQUOT_FREE_INODE(inode);
222
	DQUOT_FREE_INODE(inode);
220
	DQUOT_DROP(inode);
223
	DQUOT_DROP(inode);
221
224
Lines 296-303 Link Here
296
 * For other inodes, search forward from the parent directory's block
299
 * For other inodes, search forward from the parent directory's block
297
 * group to find a free inode.
300
 * group to find a free inode.
298
 */
301
 */
299
struct inode * ext3_new_inode (handle_t *handle,
302
struct inode * ext3_new_inode (handle_t *handle, struct inode * dir, int mode)
300
				const struct inode * dir, int mode)
301
{
303
{
302
	struct super_block * sb;
304
	struct super_block * sb;
303
	struct buffer_head * bh;
305
	struct buffer_head * bh;
Lines 509-522 Link Here
509
	inode->u.ext3_i.i_state = EXT3_STATE_NEW;
511
	inode->u.ext3_i.i_state = EXT3_STATE_NEW;
510
	err = ext3_mark_inode_dirty(handle, inode);
512
	err = ext3_mark_inode_dirty(handle, inode);
511
	if (err) goto fail;
513
	if (err) goto fail;
514
515
#ifdef CONFIG_EXT2_FS_XATTR
516
	init_rwsem(&inode->u.ext3_i.xattr_sem);
517
#endif
512
	
518
	
513
	unlock_super (sb);
519
	unlock_super (sb);
514
	if(DQUOT_ALLOC_INODE(inode)) {
520
	if(DQUOT_ALLOC_INODE(inode)) {
515
		DQUOT_DROP(inode);
521
		DQUOT_DROP(inode);
516
		inode->i_flags |= S_NOQUOTA;
522
		err = -EDQUOT;
517
		inode->i_nlink = 0;
523
		goto fail2;
518
		iput(inode);
524
	}
519
		return ERR_PTR(-EDQUOT);
525
	err = ext3_init_acl(handle, inode, dir);
526
	if (err) {
527
		DQUOT_FREE_INODE(inode);
528
		goto fail2;
520
	}
529
	}
521
	ext3_debug ("allocating inode %lu\n", inode->i_ino);
530
	ext3_debug ("allocating inode %lu\n", inode->i_ino);
522
	return inode;
531
	return inode;
Lines 527-532 Link Here
527
	unlock_super(sb);
536
	unlock_super(sb);
528
	iput(inode);
537
	iput(inode);
529
	return ERR_PTR(err);
538
	return ERR_PTR(err);
539
540
fail2:
541
	inode->i_flags |= S_NOQUOTA;
542
	inode->i_nlink = 0;
543
	iput(inode);
544
	return ERR_PTR(err);
530
}
545
}
531
546
532
/* Verify that we are loading a valid orphan from disk */
547
/* Verify that we are loading a valid orphan from disk */
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/inode.c (-19 / +58 lines)
Lines 26-31 Link Here
26
#include <linux/sched.h>
26
#include <linux/sched.h>
27
#include <linux/ext3_jbd.h>
27
#include <linux/ext3_jbd.h>
28
#include <linux/jbd.h>
28
#include <linux/jbd.h>
29
#include <linux/ext3_xattr.h>
30
#include <linux/ext3_acl.h>
29
#include <linux/locks.h>
31
#include <linux/locks.h>
30
#include <linux/smp_lock.h>
32
#include <linux/smp_lock.h>
31
#include <linux/highuid.h>
33
#include <linux/highuid.h>
Lines 39-44 Link Here
39
 */
41
 */
40
#undef SEARCH_FROM_ZERO
42
#undef SEARCH_FROM_ZERO
41
43
44
/*
45
 * Test whether an inode is a fast symlink.
46
 */
47
static inline int ext3_inode_is_fast_symlink(struct inode *inode)
48
{
49
	int ea_blocks = inode->u.ext3_i.i_file_acl ?
50
		(inode->i_sb->s_blocksize >> 9) : 0;
51
52
	return (S_ISLNK(inode->i_mode) &&
53
		inode->i_blocks - ea_blocks == 0);
54
}
55
42
/* The ext3 forget function must perform a revoke if we are freeing data
56
/* The ext3 forget function must perform a revoke if we are freeing data
43
 * which has been journaled.  Metadata (eg. indirect blocks) must be
57
 * which has been journaled.  Metadata (eg. indirect blocks) must be
44
 * revoked in all cases. 
58
 * revoked in all cases. 
Lines 48-54 Link Here
48
 * still needs to be revoked.
62
 * still needs to be revoked.
49
 */
63
 */
50
64
51
static int ext3_forget(handle_t *handle, int is_metadata,
65
int ext3_forget(handle_t *handle, int is_metadata,
52
		       struct inode *inode, struct buffer_head *bh,
66
		       struct inode *inode, struct buffer_head *bh,
53
		       int blocknr)
67
		       int blocknr)
54
{
68
{
Lines 179-187 Link Here
179
{
193
{
180
	handle_t *handle;
194
	handle_t *handle;
181
	
195
	
182
	if (is_bad_inode(inode) ||
196
	if (is_bad_inode(inode))
183
	    inode->i_ino == EXT3_ACL_IDX_INO ||
184
	    inode->i_ino == EXT3_ACL_DATA_INO)
185
		goto no_delete;
197
		goto no_delete;
186
198
187
	lock_kernel();
199
	lock_kernel();
Lines 1870-1875 Link Here
1870
	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
1882
	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
1871
	    S_ISLNK(inode->i_mode)))
1883
	    S_ISLNK(inode->i_mode)))
1872
		return;
1884
		return;
1885
	if (ext3_inode_is_fast_symlink(inode))
1886
		return;
1873
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
1887
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
1874
		return;
1888
		return;
1875
1889
Lines 2017-2024 Link Here
2017
	struct ext3_group_desc * gdp;
2031
	struct ext3_group_desc * gdp;
2018
		
2032
		
2019
	if ((inode->i_ino != EXT3_ROOT_INO &&
2033
	if ((inode->i_ino != EXT3_ROOT_INO &&
2020
		inode->i_ino != EXT3_ACL_IDX_INO &&
2021
		inode->i_ino != EXT3_ACL_DATA_INO &&
2022
		inode->i_ino != EXT3_JOURNAL_INO &&
2034
		inode->i_ino != EXT3_JOURNAL_INO &&
2023
		inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2035
		inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
2024
		inode->i_ino > le32_to_cpu(
2036
		inode->i_ino > le32_to_cpu(
Lines 2159-2168 Link Here
2159
		inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
2171
		inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
2160
	INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
2172
	INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
2161
2173
2162
	if (inode->i_ino == EXT3_ACL_IDX_INO ||
2174
	if (S_ISREG(inode->i_mode)) {
2163
	    inode->i_ino == EXT3_ACL_DATA_INO)
2164
		/* Nothing to do */ ;
2165
	else if (S_ISREG(inode->i_mode)) {
2166
		inode->i_op = &ext3_file_inode_operations;
2175
		inode->i_op = &ext3_file_inode_operations;
2167
		inode->i_fop = &ext3_file_operations;
2176
		inode->i_fop = &ext3_file_operations;
2168
		inode->i_mapping->a_ops = &ext3_aops;
2177
		inode->i_mapping->a_ops = &ext3_aops;
Lines 2170-2186 Link Here
2170
		inode->i_op = &ext3_dir_inode_operations;
2179
		inode->i_op = &ext3_dir_inode_operations;
2171
		inode->i_fop = &ext3_dir_operations;
2180
		inode->i_fop = &ext3_dir_operations;
2172
	} else if (S_ISLNK(inode->i_mode)) {
2181
	} else if (S_ISLNK(inode->i_mode)) {
2173
		if (!inode->i_blocks)
2182
		if (ext3_inode_is_fast_symlink(inode))
2174
			inode->i_op = &ext3_fast_symlink_inode_operations;
2183
			inode->i_op = &ext3_fast_symlink_inode_operations;
2175
		else {
2184
		else {
2176
			inode->i_op = &page_symlink_inode_operations;
2185
			inode->i_op = &ext3_symlink_inode_operations;
2177
			inode->i_mapping->a_ops = &ext3_aops;
2186
			inode->i_mapping->a_ops = &ext3_aops;
2178
		}
2187
		}
2179
	} else 
2188
	} else  {
2189
		inode->i_op = &ext3_special_inode_operations;
2180
		init_special_inode(inode, inode->i_mode,
2190
		init_special_inode(inode, inode->i_mode,
2181
				   le32_to_cpu(iloc.raw_inode->i_block[0]));
2191
				   le32_to_cpu(iloc.raw_inode->i_block[0]));
2192
	}
2182
	brelse(iloc.bh);
2193
	brelse(iloc.bh);
2183
	ext3_set_inode_flags(inode);
2194
	ext3_set_inode_flags(inode);
2195
#ifdef CONFIG_EXT3_FS_XATTR
2196
	init_rwsem(&inode->u.ext3_i.xattr_sem);
2197
#endif
2198
#ifdef CONFIG_EXT3_FS_POSIX_ACL
2199
	if (inode->u.ext3_i.i_file_acl) {
2200
		/* The filesystem is mounted with ACL support, and there
2201
		   are extended attributes for this inode. However we do
2202
		   not yet know whether there are actually any ACLs. */
2203
		inode->u.ext3_i.i_acl = EXT3_ACL_NOT_CACHED;
2204
		inode->u.ext3_i.i_default_acl = EXT3_ACL_NOT_CACHED;
2205
	}
2206
#endif
2207
2184
	return;
2208
	return;
2185
	
2209
	
2186
bad_inode:
2210
bad_inode:
Lines 2369-2378 Link Here
2369
 * be freed, so we have a strong guarantee that no future commit will
2393
 * be freed, so we have a strong guarantee that no future commit will
2370
 * leave these blocks visible to the user.)  
2394
 * leave these blocks visible to the user.)  
2371
 *
2395
 *
2372
 * This is only needed for regular files.  rmdir() has its own path, and
2373
 * we can never truncate a direcory except on final unlink (at which
2374
 * point i_nlink is zero so recovery is easy.)
2375
 *
2376
 * Called with the BKL.  
2396
 * Called with the BKL.  
2377
 */
2397
 */
2378
2398
Lines 2393-2399 Link Here
2393
			return error;
2413
			return error;
2394
	}
2414
	}
2395
2415
2396
	if (attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
2416
	if (S_ISREG(inode->i_mode) &&
2417
	    attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
2397
		handle_t *handle;
2418
		handle_t *handle;
2398
2419
2399
		handle = ext3_journal_start(inode, 3);
2420
		handle = ext3_journal_start(inode, 3);
Lines 2415-2423 Link Here
2415
	/* If inode_setattr's call to ext3_truncate failed to get a
2436
	/* If inode_setattr's call to ext3_truncate failed to get a
2416
	 * transaction handle at all, we need to clean up the in-core
2437
	 * transaction handle at all, we need to clean up the in-core
2417
	 * orphan list manually. */
2438
	 * orphan list manually. */
2418
	if (inode->i_nlink)
2439
	if (S_ISREG(inode->i_mode) && inode->i_nlink)
2419
		ext3_orphan_del(NULL, inode);
2440
		ext3_orphan_del(NULL, inode);
2420
2441
2442
#ifdef CONFIG_EXT3_FS_POSIX_ACL
2443
	if (!rc && (ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) {
2444
		handle_t *handle;
2445
2446
		if (!(ia_valid & ATTR_SIZE))
2447
			down(&inode->i_sem);
2448
		handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
2449
		if (IS_ERR(handle))
2450
			error = PTR_ERR(handle);
2451
		else {
2452
			rc = ext3_acl_chmod(handle, inode);
2453
			ext3_journal_stop(handle, inode);
2454
		}
2455
		if (!(ia_valid & ATTR_SIZE))
2456
			up(&inode->i_sem);
2457
	}
2458
#endif
2459
2421
err_out:
2460
err_out:
2422
	ext3_std_error(inode->i_sb, error);
2461
	ext3_std_error(inode->i_sb, error);
2423
	if (!error)
2462
	if (!error)
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/namei.c (-7 / +24 lines)
Lines 23-28 Link Here
23
#include <linux/sched.h>
23
#include <linux/sched.h>
24
#include <linux/ext3_fs.h>
24
#include <linux/ext3_fs.h>
25
#include <linux/ext3_jbd.h>
25
#include <linux/ext3_jbd.h>
26
#include <linux/ext3_xattr.h>
27
#include <linux/ext3_acl.h>
26
#include <linux/fcntl.h>
28
#include <linux/fcntl.h>
27
#include <linux/stat.h>
29
#include <linux/stat.h>
28
#include <linux/string.h>
30
#include <linux/string.h>
Lines 490-496 Link Here
490
	inode = ext3_new_inode (handle, dir, mode);
492
	inode = ext3_new_inode (handle, dir, mode);
491
	err = PTR_ERR(inode);
493
	err = PTR_ERR(inode);
492
	if (!IS_ERR(inode)) {
494
	if (!IS_ERR(inode)) {
493
		init_special_inode(inode, mode, rdev);
495
		init_special_inode(inode, inode->i_mode, rdev);
496
#ifdef CONFIG_EXT3_FS_XATTR
497
		inode->i_op = &ext3_special_inode_operations;
498
#endif
494
		err = ext3_add_nondir(handle, dentry, inode);
499
		err = ext3_add_nondir(handle, dentry, inode);
495
	}
500
	}
496
	ext3_journal_stop(handle, dir);
501
	ext3_journal_stop(handle, dir);
Lines 515-521 Link Here
515
	if (IS_SYNC(dir))
520
	if (IS_SYNC(dir))
516
		handle->h_sync = 1;
521
		handle->h_sync = 1;
517
522
518
	inode = ext3_new_inode (handle, dir, S_IFDIR);
523
	inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
519
	err = PTR_ERR(inode);
524
	err = PTR_ERR(inode);
520
	if (IS_ERR(inode))
525
	if (IS_ERR(inode))
521
		goto out_stop;
526
		goto out_stop;
Lines 523-529 Link Here
523
	inode->i_op = &ext3_dir_inode_operations;
528
	inode->i_op = &ext3_dir_inode_operations;
524
	inode->i_fop = &ext3_dir_operations;
529
	inode->i_fop = &ext3_dir_operations;
525
	inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize;
530
	inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize;
526
	inode->i_blocks = 0;	
527
	dir_block = ext3_bread (handle, inode, 0, 1, &err);
531
	dir_block = ext3_bread (handle, inode, 0, 1, &err);
528
	if (!dir_block) {
532
	if (!dir_block) {
529
		inode->i_nlink--; /* is this nlink == 0? */
533
		inode->i_nlink--; /* is this nlink == 0? */
Lines 550-558 Link Here
550
	BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
554
	BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
551
	ext3_journal_dirty_metadata(handle, dir_block);
555
	ext3_journal_dirty_metadata(handle, dir_block);
552
	brelse (dir_block);
556
	brelse (dir_block);
553
	inode->i_mode = S_IFDIR | mode;
554
	if (dir->i_mode & S_ISGID)
555
		inode->i_mode |= S_ISGID;
556
	ext3_mark_inode_dirty(handle, inode);
557
	ext3_mark_inode_dirty(handle, inode);
557
	err = ext3_add_entry (handle, dentry, inode);
558
	err = ext3_add_entry (handle, dentry, inode);
558
	if (err)
559
	if (err)
Lines 918-924 Link Here
918
		goto out_stop;
919
		goto out_stop;
919
920
920
	if (l > sizeof (inode->u.ext3_i.i_data)) {
921
	if (l > sizeof (inode->u.ext3_i.i_data)) {
921
		inode->i_op = &page_symlink_inode_operations;
922
		inode->i_op = &ext3_symlink_inode_operations;
922
		inode->i_mapping->a_ops = &ext3_aops;
923
		inode->i_mapping->a_ops = &ext3_aops;
923
		/*
924
		/*
924
		 * block_symlink() calls back into ext3_prepare/commit_write.
925
		 * block_symlink() calls back into ext3_prepare/commit_write.
Lines 1121-1124 Link Here
1121
	rmdir:		ext3_rmdir,		/* BKL held */
1122
	rmdir:		ext3_rmdir,		/* BKL held */
1122
	mknod:		ext3_mknod,		/* BKL held */
1123
	mknod:		ext3_mknod,		/* BKL held */
1123
	rename:		ext3_rename,		/* BKL held */
1124
	rename:		ext3_rename,		/* BKL held */
1125
	setattr:	ext3_setattr,		/* BKL held */
1126
	setxattr:	ext3_setxattr,		/* BKL held */
1127
	getxattr:	ext3_getxattr,		/* BKL held */
1128
	listxattr:	ext3_listxattr,		/* BKL held */
1129
	removexattr:	ext3_removexattr,	/* BKL held */
1130
	permission:	ext3_permission,	/* BKL held */
1131
};
1132
1133
struct inode_operations ext3_special_inode_operations = {
1134
	setattr:	ext3_setattr,		/* BKL held */
1135
	setxattr:	ext3_setxattr,		/* BKL held */
1136
	getxattr:	ext3_getxattr,		/* BKL held */
1137
	listxattr:	ext3_listxattr,		/* BKL held */
1138
	removexattr:	ext3_removexattr,	/* BKL held */
1139
	permission:	ext3_permission,	/* BKL held */
1124
};
1140
};
1141
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/super.c (-4 / +83 lines)
Lines 24-29 Link Here
24
#include <linux/jbd.h>
24
#include <linux/jbd.h>
25
#include <linux/ext3_fs.h>
25
#include <linux/ext3_fs.h>
26
#include <linux/ext3_jbd.h>
26
#include <linux/ext3_jbd.h>
27
#include <linux/ext3_xattr.h>
28
#include <linux/ext3_acl.h>
27
#include <linux/slab.h>
29
#include <linux/slab.h>
28
#include <linux/init.h>
30
#include <linux/init.h>
29
#include <linux/locks.h>
31
#include <linux/locks.h>
Lines 406-411 Link Here
406
	kdev_t j_dev = sbi->s_journal->j_dev;
408
	kdev_t j_dev = sbi->s_journal->j_dev;
407
	int i;
409
	int i;
408
410
411
	ext3_xattr_put_super(sb);
409
	journal_destroy(sbi->s_journal);
412
	journal_destroy(sbi->s_journal);
410
	if (!(sb->s_flags & MS_RDONLY)) {
413
	if (!(sb->s_flags & MS_RDONLY)) {
411
		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
414
		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
Lines 451-456 Link Here
451
static struct dquot_operations ext3_qops;
454
static struct dquot_operations ext3_qops;
452
static int (*old_sync_dquot)(struct dquot *dquot);
455
static int (*old_sync_dquot)(struct dquot *dquot);
453
456
457
#ifdef CONFIG_EXT3_FS_POSIX_ACL
458
459
static void ext3_clear_inode(struct inode *inode)
460
{
461
       if (inode->u.ext3_i.i_acl &&
462
           inode->u.ext3_i.i_acl != EXT3_ACL_NOT_CACHED) {
463
               posix_acl_release(inode->u.ext3_i.i_acl);
464
               inode->u.ext3_i.i_acl = EXT3_ACL_NOT_CACHED;
465
       }
466
       if (inode->u.ext3_i.i_default_acl &&
467
           inode->u.ext3_i.i_default_acl != EXT3_ACL_NOT_CACHED) {
468
               posix_acl_release(inode->u.ext3_i.i_default_acl);
469
               inode->u.ext3_i.i_default_acl = EXT3_ACL_NOT_CACHED;
470
       }
471
}
472
473
#else
474
# define ext3_clear_inode NULL
475
#endif
476
454
static struct super_operations ext3_sops = {
477
static struct super_operations ext3_sops = {
455
	read_inode:	ext3_read_inode,	/* BKL held */
478
	read_inode:	ext3_read_inode,	/* BKL held */
456
	write_inode:	ext3_write_inode,	/* BKL not held.  Don't need */
479
	write_inode:	ext3_write_inode,	/* BKL not held.  Don't need */
Lines 464-469 Link Here
464
	unlockfs:	ext3_unlockfs,		/* BKL not held.  We take it */
487
	unlockfs:	ext3_unlockfs,		/* BKL not held.  We take it */
465
	statfs:		ext3_statfs,		/* BKL held */
488
	statfs:		ext3_statfs,		/* BKL held */
466
	remount_fs:	ext3_remount,		/* BKL held */
489
	remount_fs:	ext3_remount,		/* BKL held */
490
	clear_inode:	ext3_clear_inode,	/* BKL not needed. */
467
};
491
};
468
492
469
static int want_value(char *value, char *option)
493
static int want_value(char *value, char *option)
Lines 501-510 Link Here
501
 */
525
 */
502
static int parse_options (char * options, unsigned long * sb_block,
526
static int parse_options (char * options, unsigned long * sb_block,
503
			  struct ext3_sb_info *sbi,
527
			  struct ext3_sb_info *sbi,
528
			  unsigned long *mount_flags,
504
			  unsigned long * inum,
529
			  unsigned long * inum,
505
			  int is_remount)
530
			  int is_remount)
506
{
531
{
507
	unsigned long *mount_options = &sbi->s_mount_opt;
532
	unsigned long *mount_options = &sbi->s_mount_opt;
533
	
508
	uid_t *resuid = &sbi->s_resuid;
534
	uid_t *resuid = &sbi->s_resuid;
509
	gid_t *resgid = &sbi->s_resgid;
535
	gid_t *resgid = &sbi->s_resgid;
510
	char * this_char;
536
	char * this_char;
Lines 517-522 Link Here
517
	     this_char = strtok (NULL, ",")) {
543
	     this_char = strtok (NULL, ",")) {
518
		if ((value = strchr (this_char, '=')) != NULL)
544
		if ((value = strchr (this_char, '=')) != NULL)
519
			*value++ = 0;
545
			*value++ = 0;
546
#ifdef CONFIG_EXT3_FS_XATTR_USER
547
		if (!strcmp (this_char, "user_xattr"))
548
			set_opt (*mount_options, XATTR_USER);
549
		else if (!strcmp (this_char, "nouser_xattr"))
550
			clear_opt (*mount_options, XATTR_USER);
551
		else
552
#endif
553
#ifdef CONFIG_EXT3_FS_POSIX_ACL
554
		if (!strcmp(this_char, "acl"))
555
			*mount_flags |= MS_POSIXACL;
556
		else if (!strcmp(this_char, "noacl"))
557
			*mount_flags &= ~MS_POSIXACL;
558
		else
559
#endif
520
		if (!strcmp (this_char, "bsddf"))
560
		if (!strcmp (this_char, "bsddf"))
521
			clear_opt (*mount_options, MINIX_DF);
561
			clear_opt (*mount_options, MINIX_DF);
522
		else if (!strcmp (this_char, "nouid32")) {
562
		else if (!strcmp (this_char, "nouid32")) {
Lines 931-937 Link Here
931
	sbi->s_mount_opt = 0;
971
	sbi->s_mount_opt = 0;
932
	sbi->s_resuid = EXT3_DEF_RESUID;
972
	sbi->s_resuid = EXT3_DEF_RESUID;
933
	sbi->s_resgid = EXT3_DEF_RESGID;
973
	sbi->s_resgid = EXT3_DEF_RESGID;
934
	if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
974
975
	/* Default extended attribute flags */
976
#ifdef CONFIG_EXT3_FS_XATTR_USER
977
	/* set_opt(sbi->s_mount_opt, XATTR_USER); */
978
#endif
979
#ifdef CONFIG_EXT3_FS_POSIX_ACL
980
	/* sb->s_flags |= MS_POSIXACL; */
981
#endif
982
983
	if (!parse_options ((char *) data, &sb_block, sbi, &sb->s_flags,
984
			    &journal_inum, 0)) {
935
		sb->s_dev = 0;
985
		sb->s_dev = 0;
936
		goto out_fail;
986
		goto out_fail;
937
	}
987
	}
Lines 1649-1667 Link Here
1649
{
1699
{
1650
	struct ext3_super_block * es;
1700
	struct ext3_super_block * es;
1651
	struct ext3_sb_info *sbi = EXT3_SB(sb);
1701
	struct ext3_sb_info *sbi = EXT3_SB(sb);
1652
	unsigned long tmp;
1702
	unsigned long mount_flags = sb->s_flags, tmp;
1653
1703
1654
	clear_ro_after(sb);
1704
	clear_ro_after(sb);
1655
1705
1656
	/*
1706
	/*
1657
	 * Allow the "check" option to be passed as a remount option.
1707
	 * Allow the "check" option to be passed as a remount option.
1658
	 */
1708
	 */
1659
	if (!parse_options(data, &tmp, sbi, &tmp, 1))
1709
	if (!parse_options(data, &tmp, sbi, &mount_flags, &tmp, 1))
1660
		return -EINVAL;
1710
		return -EINVAL;
1661
1711
1662
	if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
1712
	if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
1663
		ext3_abort(sb, __FUNCTION__, "Abort forced by user");
1713
		ext3_abort(sb, __FUNCTION__, "Abort forced by user");
1664
1714
1715
	sb->s_flags = mount_flags;
1716
1665
	es = sbi->s_es;
1717
	es = sbi->s_es;
1666
1718
1667
	ext3_init_journal_params(sbi, sbi->s_journal);
1719
	ext3_init_journal_params(sbi, sbi->s_journal);
Lines 1821-1831 Link Here
1821
	old_sync_dquot = ext3_qops.sync_dquot;
1873
	old_sync_dquot = ext3_qops.sync_dquot;
1822
	ext3_qops.sync_dquot = ext3_sync_dquot;
1874
	ext3_qops.sync_dquot = ext3_sync_dquot;
1823
#endif
1875
#endif
1824
        return register_filesystem(&ext3_fs_type);
1876
	int error = init_ext3_xattr();
1877
	if (error)
1878
		return error;
1879
	error = init_ext3_xattr_user();
1880
	if (error)
1881
		goto fail;
1882
	error = init_ext3_xattr_trusted();
1883
	if (error)
1884
		goto fail2;
1885
	error = init_ext3_acl();
1886
	if (error)
1887
		goto fail3;
1888
	error = register_filesystem_lifo(&ext3_fs_type);
1889
	if (!error)
1890
		return 0;
1891
	
1892
	exit_ext3_acl();
1893
fail3:
1894
	exit_ext3_xattr_trusted();
1895
fail2:
1896
	exit_ext3_xattr_user();
1897
fail:
1898
	exit_ext3_xattr();
1899
	return error;
1825
}
1900
}
1826
1901
1827
static void __exit exit_ext3_fs(void)
1902
static void __exit exit_ext3_fs(void)
1828
{
1903
{
1904
	exit_ext3_acl();
1905
	exit_ext3_xattr_trusted();
1906
	exit_ext3_xattr_user();
1907
	exit_ext3_xattr();
1829
	unregister_filesystem(&ext3_fs_type);
1908
	unregister_filesystem(&ext3_fs_type);
1830
}
1909
}
1831
1910
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/symlink.c (+14 lines)
Lines 20-25 Link Here
20
#include <linux/fs.h>
20
#include <linux/fs.h>
21
#include <linux/jbd.h>
21
#include <linux/jbd.h>
22
#include <linux/ext3_fs.h>
22
#include <linux/ext3_fs.h>
23
#include <linux/ext3_xattr.h>
23
24
24
static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
25
static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
25
{
26
{
Lines 33-39 Link Here
33
	return vfs_follow_link(nd, s);
34
	return vfs_follow_link(nd, s);
34
}
35
}
35
36
37
struct inode_operations ext3_symlink_inode_operations = {
38
	readlink:	page_readlink,		/* BKL not held.  Don't need */
39
	follow_link:	page_follow_link,	/* BKL not held.  Don't need */
40
	setxattr:	ext3_setxattr,		/* BKL held */
41
	getxattr:	ext3_getxattr,		/* BKL held */
42
	listxattr:	ext3_listxattr,		/* BKL held */
43
	removexattr:	ext3_removexattr,	/* BKL held */
44
};
45
36
struct inode_operations ext3_fast_symlink_inode_operations = {
46
struct inode_operations ext3_fast_symlink_inode_operations = {
37
	readlink:	ext3_readlink,		/* BKL not held.  Don't need */
47
	readlink:	ext3_readlink,		/* BKL not held.  Don't need */
38
	follow_link:	ext3_follow_link,	/* BKL not held.  Don't need */
48
	follow_link:	ext3_follow_link,	/* BKL not held.  Don't need */
49
	setxattr:	ext3_setxattr,		/* BKL held */
50
	getxattr:	ext3_getxattr,		/* BKL held */
51
	listxattr:	ext3_listxattr,		/* BKL held */
52
	removexattr:	ext3_removexattr,	/* BKL held */
39
};
53
};
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/xattr.c (+1221 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext3/xattr.c
3
 *
4
 * Copyright (C) 2001-2003 by Andreas Gruenbacher, <agruen@suse.de>
5
 *
6
 * Fix by Harrison Xing <harrison@mountainviewdata.com>.
7
 * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
8
 * Extended attributes for symlinks and special files added per
9
 *  suggestion of Luka Renko <luka.renko@hermes.si>.
10
 */
11
12
/*
13
 * Extended attributes are stored on disk blocks allocated outside of
14
 * any inode. The i_file_acl field is then made to point to this allocated
15
 * block. If all extended attributes of an inode are identical, these
16
 * inodes may share the same extended attribute block. Such situations
17
 * are automatically detected by keeping a cache of recent attribute block
18
 * numbers and hashes over the block's contents in memory.
19
 *
20
 *
21
 * Extended attribute block layout:
22
 *
23
 *   +------------------+
24
 *   | header           |
25
 *   | entry 1          | |
26
 *   | entry 2          | | growing downwards
27
 *   | entry 3          | v
28
 *   | four null bytes  |
29
 *   | . . .            |
30
 *   | value 1          | ^
31
 *   | value 3          | | growing upwards
32
 *   | value 2          | |
33
 *   +------------------+
34
 *
35
 * The block header is followed by multiple entry descriptors. These entry
36
 * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
37
 * byte boundaries. The entry descriptors are sorted by attribute name,
38
 * so that two extended attribute blocks can be compared efficiently.
39
 *
40
 * Attribute values are aligned to the end of the block, stored in
41
 * no specific order. They are also padded to EXT3_XATTR_PAD byte
42
 * boundaries. No additional gaps are left between them.
43
 *
44
 * Locking strategy
45
 * ----------------
46
 * EXT3_I(inode)->i_file_acl is protected by EXT3_I(inode)->xattr_sem.
47
 * EA blocks are only changed if they are exclusive to an inode, so
48
 * holding xattr_sem also means that nothing but the EA block's reference
49
 * count will change. Multiple writers to an EA block are synchronized
50
 * by the bh lock. No more than a single bh lock is held at any time,
51
 * which avoids deadlocks.
52
 */
53
54
#include <linux/fs.h>
55
#include <linux/locks.h>
56
#include <linux/slab.h>
57
#include <linux/ext3_jbd.h>
58
#include <linux/ext3_fs.h>
59
#include <linux/ext3_xattr.h>
60
#include <linux/mbcache.h>
61
#include <linux/quotaops.h>
62
#include <linux/rwsem.h>
63
64
#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
65
#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
66
#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
67
#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
68
69
#ifdef EXT3_XATTR_DEBUG
70
# define ea_idebug(inode, f...) do { \
71
		printk(KERN_DEBUG "inode %s:%ld: ", \
72
			kdevname(inode->i_dev), inode->i_ino); \
73
		printk(f); \
74
		printk("\n"); \
75
	} while (0)
76
# define ea_bdebug(bh, f...) do { \
77
		printk(KERN_DEBUG "block %s:%ld: ", \
78
			kdevname(bh->b_dev), bh->b_blocknr); \
79
		printk(f); \
80
		printk("\n"); \
81
	} while (0)
82
#else
83
# define ea_idebug(f...)
84
# define ea_bdebug(f...)
85
#endif
86
87
static int ext3_xattr_set_handle2(handle_t *, struct inode *,
88
				  struct buffer_head *,
89
				  struct ext3_xattr_header *);
90
91
#ifdef CONFIG_EXT3_FS_XATTR_SHARING
92
93
static int ext3_xattr_cache_insert(struct buffer_head *);
94
static struct buffer_head *ext3_xattr_cache_find(handle_t *, struct inode *,
95
						 struct ext3_xattr_header *);
96
static void ext3_xattr_cache_remove(struct buffer_head *);
97
static void ext3_xattr_rehash(struct ext3_xattr_header *,
98
			      struct ext3_xattr_entry *);
99
100
static struct mb_cache *ext3_xattr_cache;
101
102
#else
103
# define ext3_xattr_cache_insert(bh) 0
104
# define ext3_xattr_cache_find(handle, inode, header) NULL
105
# define ext3_xattr_cache_remove(bh) while(0) {}
106
# define ext3_xattr_rehash(header, entry) while(0) {}
107
#endif
108
109
struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
110
rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
111
112
int
113
ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
114
{
115
	int error = -EINVAL;
116
117
	if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
118
		write_lock(&ext3_handler_lock);
119
		if (!ext3_xattr_handlers[name_index-1]) {
120
			ext3_xattr_handlers[name_index-1] = handler;
121
			error = 0;
122
		}
123
		write_unlock(&ext3_handler_lock);
124
	}
125
	return error;
126
}
127
128
void
129
ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
130
{
131
	if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
132
		write_lock(&ext3_handler_lock);
133
		ext3_xattr_handlers[name_index-1] = NULL;
134
		write_unlock(&ext3_handler_lock);
135
	}
136
}
137
138
static inline const char *
139
strcmp_prefix(const char *a, const char *a_prefix)
140
{
141
	while (*a_prefix && *a == *a_prefix) {
142
		a++;
143
		a_prefix++;
144
	}
145
	return *a_prefix ? NULL : a;
146
}
147
148
/*
149
 * Decode the extended attribute name, and translate it into
150
 * the name_index and name suffix.
151
 */
152
static inline struct ext3_xattr_handler *
153
ext3_xattr_resolve_name(const char **name)
154
{
155
	struct ext3_xattr_handler *handler = NULL;
156
	int i;
157
158
	if (!*name)
159
		return NULL;
160
	read_lock(&ext3_handler_lock);
161
	for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
162
		if (ext3_xattr_handlers[i]) {
163
			const char *n = strcmp_prefix(*name,
164
				ext3_xattr_handlers[i]->prefix);
165
			if (n) {
166
				handler = ext3_xattr_handlers[i];
167
				*name = n;
168
				break;
169
			}
170
		}
171
	}
172
	read_unlock(&ext3_handler_lock);
173
	return handler;
174
}
175
176
static inline struct ext3_xattr_handler *
177
ext3_xattr_handler(int name_index)
178
{
179
	struct ext3_xattr_handler *handler = NULL;
180
	if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
181
		read_lock(&ext3_handler_lock);
182
		handler = ext3_xattr_handlers[name_index-1];
183
		read_unlock(&ext3_handler_lock);
184
	}
185
	return handler;
186
}
187
188
/*
189
 * Inode operation getxattr()
190
 *
191
 * dentry->d_inode->i_sem: don't care
192
 * BKL: held
193
 */
194
ssize_t
195
ext3_getxattr(struct dentry *dentry, const char *name,
196
	      void *buffer, size_t size)
197
{
198
	struct ext3_xattr_handler *handler;
199
	struct inode *inode = dentry->d_inode;
200
201
	handler = ext3_xattr_resolve_name(&name);
202
	if (!handler)
203
		return -EOPNOTSUPP;
204
	return handler->get(inode, name, buffer, size);
205
}
206
207
/*
208
 * Inode operation listxattr()
209
 *
210
 * dentry->d_inode->i_sem: don't care
211
 * BKL: held
212
 */
213
ssize_t
214
ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
215
{
216
	return ext3_xattr_list(dentry->d_inode, buffer, size);
217
}
218
219
/*
220
 * Inode operation setxattr()
221
 *
222
 * dentry->d_inode->i_sem: down
223
 * BKL: held
224
 */
225
int
226
ext3_setxattr(struct dentry *dentry, const char *name,
227
	      const void *value, size_t size, int flags)
228
{
229
	struct ext3_xattr_handler *handler;
230
	struct inode *inode = dentry->d_inode;
231
232
	if (size == 0)
233
		value = "";  /* empty EA, do not remove */
234
	handler = ext3_xattr_resolve_name(&name);
235
	if (!handler)
236
		return -EOPNOTSUPP;
237
	return handler->set(inode, name, value, size, flags);
238
}
239
240
/*
241
 * Inode operation removexattr()
242
 *
243
 * dentry->d_inode->i_sem: down
244
 * BKL: held
245
 */
246
int
247
ext3_removexattr(struct dentry *dentry, const char *name)
248
{
249
	struct ext3_xattr_handler *handler;
250
	struct inode *inode = dentry->d_inode;
251
252
	handler = ext3_xattr_resolve_name(&name);
253
	if (!handler)
254
		return -EOPNOTSUPP;
255
	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
256
}
257
258
/*
259
 * ext3_xattr_get()
260
 *
261
 * Copy an extended attribute into the buffer
262
 * provided, or compute the buffer size required.
263
 * Buffer is NULL to compute the size of the buffer required.
264
 *
265
 * Returns a negative error number on failure, or the number of bytes
266
 * used / required on success.
267
 */
268
int
269
ext3_xattr_get(struct inode *inode, int name_index, const char *name,
270
	       void *buffer, size_t buffer_size)
271
{
272
	struct buffer_head *bh = NULL;
273
	struct ext3_xattr_entry *entry;
274
	size_t size, name_len;
275
	char *end;
276
	int error;
277
278
	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
279
		  name_index, name, buffer, (long)buffer_size);
280
281
	if (name == NULL)
282
		return -EINVAL;
283
	down_read(&EXT3_I(inode)->xattr_sem);
284
	error = -ENODATA;
285
	if (!EXT3_I(inode)->i_file_acl)
286
		goto cleanup;
287
	ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
288
	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
289
	error = -EIO;
290
	if (!bh)
291
		goto cleanup;
292
	ea_bdebug(bh, "b_count=%d, refcount=%d",
293
		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
294
	end = bh->b_data + bh->b_size;
295
	if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
296
	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
297
bad_block:	ext3_error(inode->i_sb, "ext3_xattr_get",
298
			"inode %ld: bad block %d", inode->i_ino,
299
			EXT3_I(inode)->i_file_acl);
300
		error = -EIO;
301
		goto cleanup;
302
	}
303
	/* find named attribute */
304
	name_len = strlen(name);
305
306
	error = -ERANGE;
307
	if (name_len > 255)
308
		goto cleanup;
309
	entry = FIRST_ENTRY(bh);
310
	while (!IS_LAST_ENTRY(entry)) {
311
		struct ext3_xattr_entry *next =
312
			EXT3_XATTR_NEXT(entry);
313
		if ((char *)next >= end)
314
			goto bad_block;
315
		if (name_index == entry->e_name_index &&
316
		    name_len == entry->e_name_len &&
317
		    memcmp(name, entry->e_name, name_len) == 0)
318
			goto found;
319
		entry = next;
320
	}
321
	/* Check the remaining name entries */
322
	while (!IS_LAST_ENTRY(entry)) {
323
		struct ext3_xattr_entry *next =
324
			EXT3_XATTR_NEXT(entry);
325
		if ((char *)next >= end)
326
			goto bad_block;
327
		entry = next;
328
	}
329
	if (ext3_xattr_cache_insert(bh))
330
		ea_idebug(inode, "cache insert failed");
331
	error = -ENODATA;
332
	goto cleanup;
333
found:
334
	/* check the buffer size */
335
	if (entry->e_value_block != 0)
336
		goto bad_block;
337
	size = le32_to_cpu(entry->e_value_size);
338
	if (size > inode->i_sb->s_blocksize ||
339
	    le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
340
		goto bad_block;
341
342
	if (ext3_xattr_cache_insert(bh))
343
		ea_idebug(inode, "cache insert failed");
344
	if (buffer) {
345
		error = -ERANGE;
346
		if (size > buffer_size)
347
			goto cleanup;
348
		/* return value of attribute */
349
		memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
350
			size);
351
	}
352
	error = size;
353
354
cleanup:
355
	brelse(bh);
356
	up_read(&EXT3_I(inode)->xattr_sem);
357
358
	return error;
359
}
360
361
/*
362
 * ext3_xattr_list()
363
 *
364
 * Copy a list of attribute names into the buffer
365
 * provided, or compute the buffer size required.
366
 * Buffer is NULL to compute the size of the buffer required.
367
 *
368
 * Returns a negative error number on failure, or the number of bytes
369
 * used / required on success.
370
 */
371
int
372
ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
373
{
374
	struct buffer_head *bh = NULL;
375
	struct ext3_xattr_entry *entry;
376
	size_t size = 0;
377
	char *buf, *end;
378
	int error;
379
380
	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
381
		  buffer, (long)buffer_size);
382
383
	down_read(&EXT3_I(inode)->xattr_sem);
384
	error = 0;
385
	if (!EXT3_I(inode)->i_file_acl)
386
		goto cleanup;
387
	ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
388
	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
389
	error = -EIO;
390
	if (!bh)
391
		goto cleanup;
392
	ea_bdebug(bh, "b_count=%d, refcount=%d",
393
		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
394
	end = bh->b_data + bh->b_size;
395
	if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
396
	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
397
bad_block:	ext3_error(inode->i_sb, "ext3_xattr_list",
398
			"inode %ld: bad block %d", inode->i_ino,
399
			EXT3_I(inode)->i_file_acl);
400
		error = -EIO;
401
		goto cleanup;
402
	}
403
	/* compute the size required for the list of attribute names */
404
	for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
405
	     entry = EXT3_XATTR_NEXT(entry)) {
406
		struct ext3_xattr_handler *handler;
407
		struct ext3_xattr_entry *next =
408
			EXT3_XATTR_NEXT(entry);
409
		if ((char *)next >= end)
410
			goto bad_block;
411
412
		handler = ext3_xattr_handler(entry->e_name_index);
413
		if (handler)
414
			size += handler->list(NULL, inode, entry->e_name,
415
					      entry->e_name_len);
416
	}
417
418
	if (ext3_xattr_cache_insert(bh))
419
		ea_idebug(inode, "cache insert failed");
420
	if (!buffer) {
421
		error = size;
422
		goto cleanup;
423
	} else {
424
		error = -ERANGE;
425
		if (size > buffer_size)
426
			goto cleanup;
427
	}
428
429
	/* list the attribute names */
430
	buf = buffer;
431
	for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
432
	     entry = EXT3_XATTR_NEXT(entry)) {
433
		struct ext3_xattr_handler *handler;
434
435
		handler = ext3_xattr_handler(entry->e_name_index);
436
		if (handler)
437
			buf += handler->list(buf, inode, entry->e_name,
438
					     entry->e_name_len);
439
	}
440
	error = size;
441
442
cleanup:
443
	brelse(bh);
444
	up_read(&EXT3_I(inode)->xattr_sem);
445
446
	return error;
447
}
448
449
/*
450
 * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
451
 * not set, set it.
452
 */
453
static void ext3_xattr_update_super_block(handle_t *handle,
454
					  struct super_block *sb)
455
{
456
	if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
457
		return;
458
459
	lock_super(sb);
460
	if (ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh) == 0) {
461
		EXT3_SB(sb)->s_es->s_feature_compat |=
462
			cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
463
		sb->s_dirt = 1;
464
		ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
465
	}
466
	unlock_super(sb);
467
}
468
469
/*
470
 * ext3_xattr_set_handle()
471
 *
472
 * Create, replace or remove an extended attribute for this inode. Buffer
473
 * is NULL to remove an existing extended attribute, and non-NULL to
474
 * either replace an existing extended attribute, or create a new extended
475
 * attribute. The flags XATTR_REPLACE and XATTR_CREATE
476
 * specify that an extended attribute must exist and must not exist
477
 * previous to the call, respectively.
478
 *
479
 * Returns 0, or a negative error number on failure.
480
 */
481
int
482
ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
483
		      const char *name, const void *value, size_t value_len,
484
		      int flags)
485
{
486
	struct super_block *sb = inode->i_sb;
487
	struct buffer_head *bh = NULL;
488
	struct ext3_xattr_header *header = NULL;
489
	struct ext3_xattr_entry *here, *last;
490
	size_t name_len, free, min_offs = sb->s_blocksize;
491
	int not_found = 1, error;
492
	char *end;
493
	
494
	/*
495
	 * header -- Points either into bh, or to a temporarily
496
	 *           allocated buffer.
497
	 * here -- The named entry found, or the place for inserting, within
498
	 *         the block pointed to by header.
499
	 * last -- Points right after the last named entry within the block
500
	 *         pointed to by header.
501
	 * min_offs -- The offset of the first value (values are aligned
502
	 *             towards the end of the block).
503
	 * end -- Points right after the block pointed to by header.
504
	 */
505
	
506
	ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
507
		  name_index, name, value, (long)value_len);
508
509
	if (IS_RDONLY(inode))
510
		return -EROFS;
511
	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
512
		return -EPERM;
513
	if (value == NULL)
514
		value_len = 0;
515
	if (name == NULL)
516
		return -EINVAL;
517
	name_len = strlen(name);
518
	if (name_len > 255 || value_len > sb->s_blocksize)
519
		return -ERANGE;
520
	down_write(&EXT3_I(inode)->xattr_sem);
521
	if (EXT3_I(inode)->i_file_acl) {
522
		/* The inode already has an extended attribute block. */
523
		bh = sb_bread(sb, EXT3_I(inode)->i_file_acl);
524
		error = -EIO;
525
		if (!bh)
526
			goto cleanup;
527
		ea_bdebug(bh, "b_count=%d, refcount=%d",
528
			atomic_read(&(bh->b_count)),
529
			le32_to_cpu(HDR(bh)->h_refcount));
530
		header = HDR(bh);
531
		end = bh->b_data + bh->b_size;
532
		if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
533
		    header->h_blocks != cpu_to_le32(1)) {
534
bad_block:		ext3_error(sb, "ext3_xattr_set",
535
				"inode %ld: bad block %d", inode->i_ino,
536
				EXT3_I(inode)->i_file_acl);
537
			error = -EIO;
538
			goto cleanup;
539
		}
540
		/* Find the named attribute. */
541
		here = FIRST_ENTRY(bh);
542
		while (!IS_LAST_ENTRY(here)) {
543
			struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
544
			if ((char *)next >= end)
545
				goto bad_block;
546
			if (!here->e_value_block && here->e_value_size) {
547
				size_t offs = le16_to_cpu(here->e_value_offs);
548
				if (offs < min_offs)
549
					min_offs = offs;
550
			}
551
			not_found = name_index - here->e_name_index;
552
			if (!not_found)
553
				not_found = name_len - here->e_name_len;
554
			if (!not_found)
555
				not_found = memcmp(name, here->e_name,name_len);
556
			if (not_found <= 0)
557
				break;
558
			here = next;
559
		}
560
		last = here;
561
		/* We still need to compute min_offs and last. */
562
		while (!IS_LAST_ENTRY(last)) {
563
			struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
564
			if ((char *)next >= end)
565
				goto bad_block;
566
			if (!last->e_value_block && last->e_value_size) {
567
				size_t offs = le16_to_cpu(last->e_value_offs);
568
				if (offs < min_offs)
569
					min_offs = offs;
570
			}
571
			last = next;
572
		}
573
574
		/* Check whether we have enough space left. */
575
		free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
576
	} else {
577
		/* We will use a new extended attribute block. */
578
		free = sb->s_blocksize -
579
			sizeof(struct ext3_xattr_header) - sizeof(__u32);
580
		here = last = NULL;  /* avoid gcc uninitialized warning. */
581
	}
582
583
	if (not_found) {
584
		/* Request to remove a nonexistent attribute? */
585
		error = -ENODATA;
586
		if (flags & XATTR_REPLACE)
587
			goto cleanup;
588
		error = 0;
589
		if (value == NULL)
590
			goto cleanup;
591
	} else {
592
		/* Request to create an existing attribute? */
593
		error = -EEXIST;
594
		if (flags & XATTR_CREATE)
595
			goto cleanup;
596
		if (!here->e_value_block && here->e_value_size) {
597
			size_t size = le32_to_cpu(here->e_value_size);
598
599
			if (le16_to_cpu(here->e_value_offs) + size > 
600
			    sb->s_blocksize || size > sb->s_blocksize)
601
				goto bad_block;
602
			free += EXT3_XATTR_SIZE(size);
603
		}
604
		free += EXT3_XATTR_LEN(name_len);
605
	}
606
	error = -ENOSPC;
607
	if (free < EXT3_XATTR_LEN(name_len) + EXT3_XATTR_SIZE(value_len))
608
		goto cleanup;
609
610
	/* Here we know that we can set the new attribute. */
611
612
	if (header) {
613
		/* assert(header == HDR(bh)); */
614
		if (header->h_refcount != cpu_to_le32(1))
615
			goto skip_get_write_access;
616
		/* ext3_journal_get_write_access() requires an unlocked bh,
617
		   which complicates things here. */
618
		error = ext3_journal_get_write_access(handle, bh);
619
		if (error)
620
			goto cleanup;
621
		lock_buffer(bh);
622
		if (header->h_refcount == cpu_to_le32(1)) {
623
			ea_bdebug(bh, "modifying in-place");
624
			ext3_xattr_cache_remove(bh);
625
			/* keep the buffer locked while modifying it. */
626
		} else {
627
			int offset;
628
629
			unlock_buffer(bh);
630
			journal_release_buffer(handle, bh);
631
		skip_get_write_access:
632
			ea_bdebug(bh, "cloning");
633
			header = kmalloc(bh->b_size, GFP_KERNEL);
634
			error = -ENOMEM;
635
			if (header == NULL)
636
				goto cleanup;
637
			memcpy(header, HDR(bh), bh->b_size);
638
			header->h_refcount = cpu_to_le32(1);
639
			offset = (char *)header - bh->b_data;
640
			here = ENTRY((char *)here + offset);
641
			last = ENTRY((char *)last + offset);
642
		}
643
	} else {
644
		/* Allocate a buffer where we construct the new block. */
645
		header = kmalloc(sb->s_blocksize, GFP_KERNEL);
646
		error = -ENOMEM;
647
		if (header == NULL)
648
			goto cleanup;
649
		memset(header, 0, sb->s_blocksize);
650
		end = (char *)header + sb->s_blocksize;
651
		header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
652
		header->h_blocks = header->h_refcount = cpu_to_le32(1);
653
		last = here = ENTRY(header+1);
654
	}
655
656
	/* Iff we are modifying the block in-place, bh is locked here. */
657
658
	if (not_found) {
659
		/* Insert the new name. */
660
		int size = EXT3_XATTR_LEN(name_len);
661
		int rest = (char *)last - (char *)here;
662
		memmove((char *)here + size, here, rest);
663
		memset(here, 0, size);
664
		here->e_name_index = name_index;
665
		here->e_name_len = name_len;
666
		memcpy(here->e_name, name, name_len);
667
	} else {
668
		if (!here->e_value_block && here->e_value_size) {
669
			char *first_val = (char *)header + min_offs;
670
			int offs = le16_to_cpu(here->e_value_offs);
671
			char *val = (char *)header + offs;
672
			size_t size = EXT3_XATTR_SIZE(
673
				le32_to_cpu(here->e_value_size));
674
675
			if (size == EXT3_XATTR_SIZE(value_len)) {
676
				/* The old and the new value have the same
677
				   size. Just replace. */
678
				here->e_value_size = cpu_to_le32(value_len);
679
				memset(val + size - EXT3_XATTR_PAD, 0,
680
				       EXT3_XATTR_PAD); /* Clear pad bytes. */
681
				memcpy(val, value, value_len);
682
				goto skip_replace;
683
			}
684
685
			/* Remove the old value. */
686
			memmove(first_val + size, first_val, val - first_val);
687
			memset(first_val, 0, size);
688
			here->e_value_offs = 0;
689
			min_offs += size;
690
691
			/* Adjust all value offsets. */
692
			last = ENTRY(header+1);
693
			while (!IS_LAST_ENTRY(last)) {
694
				int o = le16_to_cpu(last->e_value_offs);
695
				if (!last->e_value_block && o < offs)
696
					last->e_value_offs =
697
						cpu_to_le16(o + size);
698
				last = EXT3_XATTR_NEXT(last);
699
			}
700
		}
701
		if (value == NULL) {
702
			/* Remove the old name. */
703
			int size = EXT3_XATTR_LEN(name_len);
704
			last = ENTRY((char *)last - size);
705
			memmove(here, (char*)here + size,
706
				(char*)last - (char*)here);
707
			memset(last, 0, size);
708
		}
709
	}
710
711
	if (value != NULL) {
712
		/* Insert the new value. */
713
		here->e_value_size = cpu_to_le32(value_len);
714
		if (value_len) {
715
			size_t size = EXT3_XATTR_SIZE(value_len);
716
			char *val = (char *)header + min_offs - size;
717
			here->e_value_offs =
718
				cpu_to_le16((char *)val - (char *)header);
719
			memset(val + size - EXT3_XATTR_PAD, 0,
720
			       EXT3_XATTR_PAD); /* Clear the pad bytes. */
721
			memcpy(val, value, value_len);
722
		}
723
	}
724
725
skip_replace:
726
	if (IS_LAST_ENTRY(ENTRY(header+1))) {
727
		/* This block is now empty. */
728
		if (bh && header == HDR(bh))
729
			unlock_buffer(bh);  /* we were modifying in-place. */
730
		error = ext3_xattr_set_handle2(handle, inode, bh, NULL);
731
	} else {
732
		ext3_xattr_rehash(header, here);
733
		if (bh && header == HDR(bh))
734
			unlock_buffer(bh);  /* we were modifying in-place. */
735
		error = ext3_xattr_set_handle2(handle, inode, bh, header);
736
	}
737
738
cleanup:
739
	brelse(bh);
740
	if (!(bh && header == HDR(bh)))
741
		kfree(header);
742
	up_write(&EXT3_I(inode)->xattr_sem);
743
744
	return error;
745
}
746
747
/*
748
 * Second half of ext3_xattr_set_handle(): Update the file system.
749
 */
750
static int
751
ext3_xattr_set_handle2(handle_t *handle, struct inode *inode,
752
		struct buffer_head *old_bh, struct ext3_xattr_header *header)
753
{
754
	struct super_block *sb = inode->i_sb;
755
	struct buffer_head *new_bh = NULL;
756
	int error;
757
758
	if (header) {
759
		new_bh = ext3_xattr_cache_find(handle, inode, header);
760
		if (new_bh) {
761
			/* We found an identical block in the cache. The
762
			 * block returned is locked. The old block will
763
			 * be released after updating the inode.
764
			 */
765
			ea_bdebug(new_bh, "%s block %ld",
766
				(old_bh == new_bh) ? "keeping" : "reusing",
767
				new_bh->b_blocknr);
768
			
769
			error = -EDQUOT;
770
			/* How can we enforce the allocation? */
771
			if (DQUOT_ALLOC_BLOCK(inode, 1)) {
772
				unlock_buffer(new_bh);
773
				journal_release_buffer(handle, new_bh);
774
				goto cleanup;
775
			}
776
			HDR(new_bh)->h_refcount = cpu_to_le32(
777
				le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
778
			ea_bdebug(new_bh, "refcount now=%d",
779
				le32_to_cpu(HDR(new_bh)->h_refcount));
780
			unlock_buffer(new_bh);
781
		} else if (old_bh && header == HDR(old_bh)) {
782
                       /* Keep this block. No need to lock the block as we
783
		        * don't need to change the reference count. */
784
			new_bh = old_bh;
785
			get_bh(new_bh);
786
			ext3_xattr_cache_insert(new_bh);
787
		} else {
788
			/* We need to allocate a new block */
789
			int goal = le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->
790
							   s_first_data_block) +
791
				   EXT3_I(inode)->i_block_group *
792
				   EXT3_BLOCKS_PER_GROUP(inode->i_sb);
793
			/* How can we enforce the allocation? */
794
			int block = ext3_new_block(handle, inode, goal, 0, 0,
795
						   &error);
796
			if (error)
797
				goto cleanup;
798
			ea_idebug(inode, "creating block %d", block);
799
800
			new_bh = sb_getblk(sb, block);
801
			if (!new_bh) {
802
getblk_failed:			ext3_free_blocks(handle, inode, block, 1);
803
				error = -EIO;
804
				goto cleanup;
805
			}
806
			lock_buffer(new_bh);
807
			error = ext3_journal_get_create_access(handle, new_bh);
808
			if (error) {
809
				unlock_buffer(new_bh);
810
				goto getblk_failed;
811
			}
812
			memcpy(new_bh->b_data, header, new_bh->b_size);
813
			mark_buffer_uptodate(new_bh, 1);
814
			unlock_buffer(new_bh);
815
			ext3_xattr_cache_insert(new_bh);
816
			
817
			ext3_xattr_update_super_block(handle, sb);
818
		}
819
		error = ext3_journal_dirty_metadata(handle, new_bh);
820
		if (error)
821
			goto cleanup;
822
	}
823
824
	/* Update the inode. */
825
	EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
826
	inode->i_ctime = CURRENT_TIME;
827
	ext3_mark_inode_dirty(handle, inode);
828
	if (IS_SYNC(inode))
829
		handle->h_sync = 1;
830
831
	error = 0;
832
	if (old_bh && old_bh != new_bh) {
833
		/*
834
		 * If there was an old block and we are no longer using it,
835
		 * release the old block.
836
		*/
837
838
		error = ext3_journal_get_write_access(handle, old_bh);
839
		if (error)
840
			goto cleanup;
841
		lock_buffer(old_bh);
842
		if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
843
			/* Free the old block. */
844
			ea_bdebug(old_bh, "freeing");
845
			ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1);
846
847
			/* ext3_forget() calls bforget() for us, but we
848
			   let our caller release old_bh, so we need to
849
			   duplicate the handle before. */
850
			get_bh(old_bh);
851
			ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
852
		} else {
853
			/* Decrement the refcount only. */
854
			HDR(old_bh)->h_refcount = cpu_to_le32(
855
				le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
856
			DQUOT_FREE_BLOCK(inode, 1);
857
			ext3_journal_dirty_metadata(handle, old_bh);
858
			ea_bdebug(old_bh, "refcount now=%d",
859
				  le32_to_cpu(HDR(old_bh)->h_refcount));
860
		}
861
		unlock_buffer(old_bh);
862
	}
863
864
cleanup:
865
	brelse(new_bh);
866
867
	return error;
868
}
869
870
/*
871
 * ext3_xattr_set()
872
 *
873
 * Like ext3_xattr_set_handle, but start from an inode. This extended
874
 * attribute modification is a filesystem transaction by itself.
875
 *
876
 * Returns 0, or a negative error number on failure.
877
 */
878
int
879
ext3_xattr_set(struct inode *inode, int name_index, const char *name,
880
               const void *value, size_t value_len, int flags)
881
{
882
	handle_t *handle;
883
	int error, error2;
884
885
	lock_kernel();
886
	handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
887
	error = PTR_ERR(handle);
888
	if (IS_ERR(handle))
889
		goto cleanup;
890
	error = ext3_xattr_set_handle(handle, inode, name_index, name,
891
				      value, value_len, flags);
892
	error2 = ext3_journal_stop(handle, inode);
893
	if (!error)
894
		error = error2;
895
896
cleanup:
897
	unlock_kernel();
898
	return error;
899
}
900
901
/*
902
 * ext3_xattr_delete_inode()
903
 *
904
 * Free extended attribute resources associated with this inode. This
905
 * is called immediately before an inode is freed.
906
 */
907
void
908
ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
909
{
910
	struct buffer_head *bh = NULL;
911
912
	down_write(&EXT3_I(inode)->xattr_sem);
913
	if (!EXT3_I(inode)->i_file_acl)
914
		goto cleanup;
915
	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
916
	if (!bh) {
917
		ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
918
			"inode %ld: block %d read error", inode->i_ino,
919
			EXT3_I(inode)->i_file_acl);
920
		goto cleanup;
921
	}
922
	ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
923
	if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
924
	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
925
		ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
926
			"inode %ld: bad block %d", inode->i_ino,
927
			EXT3_I(inode)->i_file_acl);
928
		goto cleanup;
929
	}
930
	if (ext3_journal_get_write_access(handle, bh) != 0)
931
		goto cleanup;
932
	lock_buffer(bh);
933
	if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
934
		ext3_xattr_cache_remove(bh);
935
		ext3_free_blocks(handle, inode, EXT3_I(inode)->i_file_acl, 1);
936
937
		/* ext3_forget() calls bforget() for us, but we release
938
		   old_bh blow, so we need to duplicate the handle before. */
939
		get_bh(bh);
940
		ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
941
	} else {
942
		HDR(bh)->h_refcount = cpu_to_le32(
943
			le32_to_cpu(HDR(bh)->h_refcount) - 1);
944
		ext3_journal_dirty_metadata(handle, bh);
945
		if (IS_SYNC(inode))
946
			handle->h_sync = 1;
947
		DQUOT_FREE_BLOCK(inode, 1);
948
	}
949
	ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount));
950
	unlock_buffer(bh);
951
	EXT3_I(inode)->i_file_acl = 0;
952
953
cleanup:
954
	brelse(bh);
955
	up_write(&EXT3_I(inode)->xattr_sem);
956
}
957
958
/*
959
 * ext3_xattr_put_super()
960
 *
961
 * This is called when a file system is unmounted.
962
 */
963
void
964
ext3_xattr_put_super(struct super_block *sb)
965
{
966
#ifdef CONFIG_EXT3_FS_XATTR_SHARING
967
	mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
968
#endif
969
}
970
971
#ifdef CONFIG_EXT3_FS_XATTR_SHARING
972
973
/*
974
 * ext3_xattr_cache_insert()
975
 *
976
 * Create a new entry in the extended attribute cache, and insert
977
 * it unless such an entry is already in the cache.
978
 *
979
 * Returns 0, or a negative error number on failure.
980
 */
981
static int
982
ext3_xattr_cache_insert(struct buffer_head *bh)
983
{
984
	__u32 hash = le32_to_cpu(HDR(bh)->h_hash);
985
	struct mb_cache_entry *ce;
986
	int error;
987
988
	ce = mb_cache_entry_alloc(ext3_xattr_cache);
989
	if (!ce)
990
		return -ENOMEM;
991
	error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
992
	if (error) {
993
		mb_cache_entry_free(ce);
994
		if (error == -EBUSY) {
995
			ea_bdebug(bh, "already in cache (%d cache entries)",
996
				atomic_read(&ext3_xattr_cache->c_entry_count));
997
			error = 0;
998
		}
999
	} else {
1000
		ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
1001
			  atomic_read(&ext3_xattr_cache->c_entry_count));
1002
		mb_cache_entry_release(ce);
1003
	}
1004
	return error;
1005
}
1006
1007
/*
1008
 * ext3_xattr_cmp()
1009
 *
1010
 * Compare two extended attribute blocks for equality.
1011
 *
1012
 * Returns 0 if the blocks are equal, 1 if they differ, and
1013
 * a negative error number on errors.
1014
 */
1015
static int
1016
ext3_xattr_cmp(struct ext3_xattr_header *header1,
1017
	       struct ext3_xattr_header *header2)
1018
{
1019
	struct ext3_xattr_entry *entry1, *entry2;
1020
1021
	entry1 = ENTRY(header1+1);
1022
	entry2 = ENTRY(header2+1);
1023
	while (!IS_LAST_ENTRY(entry1)) {
1024
		if (IS_LAST_ENTRY(entry2))
1025
			return 1;
1026
		if (entry1->e_hash != entry2->e_hash ||
1027
		    entry1->e_name_len != entry2->e_name_len ||
1028
		    entry1->e_value_size != entry2->e_value_size ||
1029
		    memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
1030
			return 1;
1031
		if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
1032
			return -EIO;
1033
		if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
1034
			   (char *)header2 + le16_to_cpu(entry2->e_value_offs),
1035
			   le32_to_cpu(entry1->e_value_size)))
1036
			return 1;
1037
1038
		entry1 = EXT3_XATTR_NEXT(entry1);
1039
		entry2 = EXT3_XATTR_NEXT(entry2);
1040
	}
1041
	if (!IS_LAST_ENTRY(entry2))
1042
		return 1;
1043
	return 0;
1044
}
1045
1046
/*
1047
 * ext3_xattr_cache_find()
1048
 *
1049
 * Find an identical extended attribute block.
1050
 *
1051
 * Returns a pointer to the block found, or NULL if such a block was
1052
 * not found or an error occurred.
1053
 */
1054
static struct buffer_head *
1055
ext3_xattr_cache_find(handle_t *handle, struct inode *inode,
1056
		      struct ext3_xattr_header *header)
1057
{
1058
	__u32 hash = le32_to_cpu(header->h_hash);
1059
	struct mb_cache_entry *ce;
1060
1061
	if (!header->h_hash)
1062
		return NULL;  /* never share */
1063
	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
1064
	ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
1065
	while (ce) {
1066
		struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
1067
1068
		if (!bh) {
1069
			ext3_error(inode->i_sb, "ext3_xattr_cache_find",
1070
				"inode %ld: block %ld read error",
1071
				inode->i_ino, ce->e_block);
1072
		} else {
1073
			/* ext3_journal_get_write_access() requires an unlocked
1074
			   bh, which complicates things here. */
1075
			if (ext3_journal_get_write_access(handle, bh) != 0)
1076
				return NULL;
1077
			lock_buffer(bh);
1078
			if (le32_to_cpu(HDR(bh)->h_refcount) >
1079
			    EXT3_XATTR_REFCOUNT_MAX) {
1080
				ea_idebug(inode, "block %ld refcount %d>%d",
1081
					  ce->e_block,
1082
					  le32_to_cpu(HDR(bh)->h_refcount),
1083
					  EXT3_XATTR_REFCOUNT_MAX);
1084
			} else if (!ext3_xattr_cmp(header, HDR(bh))) {
1085
				ea_bdebug(bh, "b_count=%d",
1086
					  atomic_read(&(bh->b_count)));
1087
				mb_cache_entry_release(ce);
1088
				/* buffer will be unlocked by caller */
1089
				return bh;
1090
			}
1091
			unlock_buffer(bh);
1092
			journal_release_buffer(handle, bh);
1093
			brelse(bh);
1094
		}
1095
		ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
1096
	}
1097
	return NULL;
1098
}
1099
1100
/*
1101
 * ext3_xattr_cache_remove()
1102
 *
1103
 * Remove the cache entry of a block from the cache. Called when a
1104
 * block becomes invalid.
1105
 */
1106
static void
1107
ext3_xattr_cache_remove(struct buffer_head *bh)
1108
{
1109
	struct mb_cache_entry *ce;
1110
1111
	ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
1112
	if (ce) {
1113
		ea_bdebug(bh, "removing (%d cache entries remaining)",
1114
			  atomic_read(&ext3_xattr_cache->c_entry_count)-1);
1115
		mb_cache_entry_free(ce);
1116
	} else 
1117
		ea_bdebug(bh, "no cache entry");
1118
}
1119
1120
#define NAME_HASH_SHIFT 5
1121
#define VALUE_HASH_SHIFT 16
1122
1123
/*
1124
 * ext3_xattr_hash_entry()
1125
 *
1126
 * Compute the hash of an extended attribute.
1127
 */
1128
static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
1129
					 struct ext3_xattr_entry *entry)
1130
{
1131
	__u32 hash = 0;
1132
	char *name = entry->e_name;
1133
	int n;
1134
1135
	for (n=0; n < entry->e_name_len; n++) {
1136
		hash = (hash << NAME_HASH_SHIFT) ^
1137
		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
1138
		       *name++;
1139
	}
1140
1141
	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
1142
		__u32 *value = (__u32 *)((char *)header +
1143
			le16_to_cpu(entry->e_value_offs));
1144
		for (n = (le32_to_cpu(entry->e_value_size) +
1145
		     EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
1146
			hash = (hash << VALUE_HASH_SHIFT) ^
1147
			       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
1148
			       le32_to_cpu(*value++);
1149
		}
1150
	}
1151
	entry->e_hash = cpu_to_le32(hash);
1152
}
1153
1154
#undef NAME_HASH_SHIFT
1155
#undef VALUE_HASH_SHIFT
1156
1157
#define BLOCK_HASH_SHIFT 16
1158
1159
/*
1160
 * ext3_xattr_rehash()
1161
 *
1162
 * Re-compute the extended attribute hash value after an entry has changed.
1163
 */
1164
static void ext3_xattr_rehash(struct ext3_xattr_header *header,
1165
			      struct ext3_xattr_entry *entry)
1166
{
1167
	struct ext3_xattr_entry *here;
1168
	__u32 hash = 0;
1169
	
1170
	ext3_xattr_hash_entry(header, entry);
1171
	here = ENTRY(header+1);
1172
	while (!IS_LAST_ENTRY(here)) {
1173
		if (!here->e_hash) {
1174
			/* Block is not shared if an entry's hash value == 0 */
1175
			hash = 0;
1176
			break;
1177
		}
1178
		hash = (hash << BLOCK_HASH_SHIFT) ^
1179
		       (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
1180
		       le32_to_cpu(here->e_hash);
1181
		here = EXT3_XATTR_NEXT(here);
1182
	}
1183
	header->h_hash = cpu_to_le32(hash);
1184
}
1185
1186
#undef BLOCK_HASH_SHIFT
1187
1188
int __init
1189
init_ext3_xattr(void)
1190
{
1191
	ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
1192
		sizeof(struct mb_cache_entry) +
1193
		sizeof(struct mb_cache_entry_index), 1, 61);
1194
	if (!ext3_xattr_cache)
1195
		return -ENOMEM;
1196
1197
	return 0;
1198
}
1199
1200
void
1201
exit_ext3_xattr(void)
1202
{
1203
	if (ext3_xattr_cache)
1204
		mb_cache_destroy(ext3_xattr_cache);
1205
	ext3_xattr_cache = NULL;
1206
}
1207
1208
#else  /* CONFIG_EXT3_FS_XATTR_SHARING */
1209
1210
int __init
1211
init_ext3_xattr(void)
1212
{
1213
	return 0;
1214
}
1215
1216
void
1217
exit_ext3_xattr(void)
1218
{
1219
}
1220
1221
#endif  /* CONFIG_EXT3_FS_XATTR_SHARING */
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/xattr_trusted.c (+76 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext3/xattr_trusted.c
3
 * Handler for trusted extended attributes.
4
 *
5
 * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
6
 */
7
8
#include <linux/sched.h>
9
#include <linux/fs.h>
10
#include <linux/ext3_jbd.h>
11
#include <linux/ext3_fs.h>
12
#include <linux/ext3_xattr.h>
13
14
#define XATTR_TRUSTED_PREFIX "trusted."
15
16
static size_t
17
ext3_xattr_trusted_list(char *list, struct inode *inode,
18
			const char *name, int name_len)
19
{
20
	const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
21
22
	if (!capable(CAP_SYS_ADMIN))
23
		return 0;
24
25
	if (list) {
26
		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
27
		memcpy(list+prefix_len, name, name_len);
28
		list[prefix_len + name_len] = '\0';
29
	}
30
	return prefix_len + name_len + 1;
31
}
32
33
static int
34
ext3_xattr_trusted_get(struct inode *inode, const char *name,
35
		       void *buffer, size_t size)
36
{
37
	if (strcmp(name, "") == 0)
38
		return -EINVAL;
39
	if (!capable(CAP_SYS_ADMIN))
40
		return -EPERM;
41
	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
42
			      buffer, size);
43
}
44
45
static int
46
ext3_xattr_trusted_set(struct inode *inode, const char *name,
47
		       const void *value, size_t size, int flags)
48
{
49
	if (strcmp(name, "") == 0)
50
		return -EINVAL;
51
	if (!capable(CAP_SYS_ADMIN))
52
		return -EPERM;
53
	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
54
			      value, size, flags);
55
}
56
57
struct ext3_xattr_handler ext3_xattr_trusted_handler = {
58
	prefix:	XATTR_TRUSTED_PREFIX,
59
	list:	ext3_xattr_trusted_list,
60
	get:	ext3_xattr_trusted_get,
61
	set:	ext3_xattr_trusted_set,
62
};
63
64
int __init
65
init_ext3_xattr_trusted(void)
66
{
67
	return ext3_xattr_register(EXT3_XATTR_INDEX_TRUSTED,
68
				   &ext3_xattr_trusted_handler);
69
}
70
71
void
72
exit_ext3_xattr_trusted(void)
73
{
74
	ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
75
			      &ext3_xattr_trusted_handler);
76
}
(-)linux-2.4.22-ppc-dev.orig/fs/ext3/xattr_user.c (+96 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/ext3/xattr_user.c
3
 * Handler for extended user attributes.
4
 *
5
 * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
6
 */
7
8
#include <linux/module.h>
9
#include <linux/string.h>
10
#include <linux/fs.h>
11
#include <linux/ext3_jbd.h>
12
#include <linux/ext3_fs.h>
13
#include <linux/ext3_xattr.h>
14
15
#ifdef CONFIG_EXT3_FS_POSIX_ACL
16
# include <linux/ext3_acl.h>
17
#endif
18
19
#define XATTR_USER_PREFIX "user."
20
21
static size_t
22
ext3_xattr_user_list(char *list, struct inode *inode,
23
		     const char *name, int name_len)
24
{
25
	const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
26
27
	if (!test_opt(inode->i_sb, XATTR_USER))
28
		return 0;
29
30
	if (list) {
31
		memcpy(list, XATTR_USER_PREFIX, prefix_len);
32
		memcpy(list+prefix_len, name, name_len);
33
		list[prefix_len + name_len] = '\0';
34
	}
35
	return prefix_len + name_len + 1;
36
}
37
38
static int
39
ext3_xattr_user_get(struct inode *inode, const char *name,
40
		    void *buffer, size_t size)
41
{
42
	int error;
43
44
	if (strcmp(name, "") == 0)
45
		return -EINVAL;
46
	if (!test_opt(inode->i_sb, XATTR_USER))
47
		return -EOPNOTSUPP;
48
	error = permission(inode, MAY_READ);
49
	if (error)
50
		return error;
51
52
	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
53
			      buffer, size);
54
}
55
56
static int
57
ext3_xattr_user_set(struct inode *inode, const char *name,
58
		    const void *value, size_t size, int flags)
59
{
60
	int error;
61
62
	if (strcmp(name, "") == 0)
63
		return -EINVAL;
64
	if ( !S_ISREG(inode->i_mode) &&
65
	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
66
		return -EPERM;
67
	if (!test_opt(inode->i_sb, XATTR_USER))
68
		return -EOPNOTSUPP;
69
	error = permission(inode, MAY_WRITE);
70
	if (error)
71
		return error;
72
  
73
	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
74
			      value, size, flags);
75
}
76
77
struct ext3_xattr_handler ext3_xattr_user_handler = {
78
	prefix:	XATTR_USER_PREFIX,
79
	list:	ext3_xattr_user_list,
80
	get:	ext3_xattr_user_get,
81
	set:	ext3_xattr_user_set,
82
};
83
84
int __init
85
init_ext3_xattr_user(void)
86
{
87
	return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
88
				   &ext3_xattr_user_handler);
89
}
90
91
void
92
exit_ext3_xattr_user(void)
93
{
94
	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
95
			      &ext3_xattr_user_handler);
96
}
(-)linux-2.4.22-ppc-dev.orig/fs/jbd/journal.c (-2 lines)
Lines 48-56 Link Here
48
EXPORT_SYMBOL(journal_get_undo_access);
48
EXPORT_SYMBOL(journal_get_undo_access);
49
EXPORT_SYMBOL(journal_dirty_data);
49
EXPORT_SYMBOL(journal_dirty_data);
50
EXPORT_SYMBOL(journal_dirty_metadata);
50
EXPORT_SYMBOL(journal_dirty_metadata);
51
#if 0
52
EXPORT_SYMBOL(journal_release_buffer);
51
EXPORT_SYMBOL(journal_release_buffer);
53
#endif
54
EXPORT_SYMBOL(journal_forget);
52
EXPORT_SYMBOL(journal_forget);
55
#if 0
53
#if 0
56
EXPORT_SYMBOL(journal_sync_buffer);
54
EXPORT_SYMBOL(journal_sync_buffer);
(-)linux-2.4.22-ppc-dev.orig/fs/jbd/transaction.c (-25 / +17 lines)
Lines 630-635 Link Here
630
	error = 0;
630
	error = 0;
631
631
632
	spin_lock(&journal_datalist_lock);
632
	spin_lock(&journal_datalist_lock);
633
	handle->h_last_buffer_credits = 0;
633
634
634
	/* The buffer is already part of this transaction if
635
	/* The buffer is already part of this transaction if
635
	 * b_transaction or b_next_transaction points to it. */
636
	 * b_transaction or b_next_transaction points to it. */
Lines 648-653 Link Here
648
649
649
		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
650
		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
650
		handle->h_buffer_credits--;
651
		handle->h_buffer_credits--;
652
		handle->h_last_buffer_credits++;
651
		goto done_locked;
653
		goto done_locked;
652
	}
654
	}
653
	
655
	
Lines 723-728 Link Here
723
725
724
	J_ASSERT(handle->h_buffer_credits > 0);
726
	J_ASSERT(handle->h_buffer_credits > 0);
725
	handle->h_buffer_credits--;
727
	handle->h_buffer_credits--;
728
	handle->h_last_buffer_credits++;
726
729
727
	/* Finally, if the buffer is not journaled right now, we need to
730
	/* Finally, if the buffer is not journaled right now, we need to
728
	 * make sure it doesn't get written to disk before the caller
731
	 * make sure it doesn't get written to disk before the caller
Lines 1178-1218 Link Here
1178
	return 0;
1181
	return 0;
1179
}
1182
}
1180
1183
1181
#if 0
1182
/* 
1184
/* 
1183
 * journal_release_buffer: undo a get_write_access without any buffer
1185
 * journal_release_buffer: undo a get_write_access without any buffer
1184
 * updates, if the update decided in the end that it didn't need access.
1186
 * updates, if the update decided in the end that it didn't need access.
1185
 *
1187
 *
1186
 * journal_get_write_access() can block, so it is quite possible for a
1188
 * journal_get_write_access() can block, so it is quite possible for a
1187
 * journaling component to decide after the write access is returned
1189
 * journaling component to decide after the write access is returned
1188
 * that global state has changed and the update is no longer required.  */
1190
 * that global state has changed and the update is no longer required.
1191
 *
1192
 * We leave the buffer attached to t_reserved_list because even though this
1193
 * handle doesn't want it, some other concurrent handle may want to journal
1194
 * this buffer.  If that handle is curently in between get_write_access() and
1195
 * journal_dirty_metadata() then it expects the buffer to be reserved.  If
1196
 * we were to rip it off t_reserved_list here, the other handle will explode
1197
 * when journal_dirty_metadata is presented with a non-reserved buffer.
1198
 *
1199
 * If nobody really wants to journal this buffer then it will be thrown
1200
 * away at the start of commit.
1201
 */
1189
1202
1190
void journal_release_buffer (handle_t *handle, struct buffer_head *bh)
1203
void journal_release_buffer (handle_t *handle, struct buffer_head *bh)
1191
{
1204
{
1192
	transaction_t *transaction = handle->h_transaction;
1205
	BUFFER_TRACE(bh, "entry");
1193
	journal_t *journal = transaction->t_journal;
1206
	handle->h_buffer_credits += handle->h_last_buffer_credits;
1194
	struct journal_head *jh = bh2jh(bh);
1195
1196
	lock_journal(journal);
1197
	JBUFFER_TRACE(jh, "entry");
1198
1199
	/* If the buffer is reserved but not modified by this
1200
	 * transaction, then it is safe to release it.  In all other
1201
	 * cases, just leave the buffer as it is. */
1202
1203
	spin_lock(&journal_datalist_lock);
1204
	if (jh->b_jlist == BJ_Reserved && jh->b_transaction == transaction &&
1205
	    !buffer_jdirty(jh2bh(jh))) {
1206
		JBUFFER_TRACE(jh, "unused: refiling it");
1207
		handle->h_buffer_credits++;
1208
		__journal_refile_buffer(jh);
1209
	}
1210
	spin_unlock(&journal_datalist_lock);
1211
1212
	JBUFFER_TRACE(jh, "exit");
1213
	unlock_journal(journal);
1214
}
1207
}
1215
#endif
1216
1208
1217
/** 
1209
/** 
1218
 * void journal_forget() - bforget() for potentially-journaled buffers.
1210
 * void journal_forget() - bforget() for potentially-journaled buffers.
(-)linux-2.4.22-ppc-dev.orig/fs/jfs/jfs_xattr.h (-2 / +4 lines)
Lines 52-59 Link Here
52
#define	END_EALIST(ealist) \
52
#define	END_EALIST(ealist) \
53
	((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
53
	((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
54
54
55
extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
55
extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
56
extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
56
			  int);
57
extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
58
			int);
57
extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
59
extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
58
extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
60
extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
59
extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
61
extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
(-)linux-2.4.22-ppc-dev.orig/fs/jfs/xattr.c (-6 / +23 lines)
Lines 641-647 Link Here
641
}
641
}
642
642
643
static int can_set_xattr(struct inode *inode, const char *name,
643
static int can_set_xattr(struct inode *inode, const char *name,
644
			 void *value, size_t value_len)
644
			 const void *value, size_t value_len)
645
{
645
{
646
	if (IS_RDONLY(inode))
646
	if (IS_RDONLY(inode))
647
		return -EROFS;
647
		return -EROFS;
Lines 660-666 Link Here
660
	return permission(inode, MAY_WRITE);
660
	return permission(inode, MAY_WRITE);
661
}
661
}
662
662
663
int __jfs_setxattr(struct inode *inode, const char *name, void *value,
663
int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
664
		   size_t value_len, int flags)
664
		   size_t value_len, int flags)
665
{
665
{
666
	struct jfs_ea_list *ealist;
666
	struct jfs_ea_list *ealist;
Lines 799-805 Link Here
799
	return rc;
799
	return rc;
800
}
800
}
801
801
802
int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
802
int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
803
		 size_t value_len, int flags)
803
		 size_t value_len, int flags)
804
{
804
{
805
	if (value == NULL) {	/* empty EA, do not remove */
805
	if (value == NULL) {	/* empty EA, do not remove */
Lines 882-893 Link Here
882
ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
882
ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
883
		     size_t buf_size)
883
		     size_t buf_size)
884
{
884
{
885
	return __jfs_getxattr(dentry->d_inode, name, data, buf_size);
885
	int err;
886
	
887
	down(&dentry->d_inode->i_sem);
888
	err = __jfs_getxattr(dentry->d_inode, name, data, buf_size);
889
	up(&dentry->d_inode->i_sem);
890
	
891
	return err;
886
}
892
}
887
893
888
ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
894
static ssize_t __jfs_listxattr(struct inode *inode, char *data,
895
			       size_t buf_size)
889
{
896
{
890
	struct inode *inode = dentry->d_inode;
891
	char *buffer;
897
	char *buffer;
892
	ssize_t size = 0;
898
	ssize_t size = 0;
893
	int xattr_size;
899
	int xattr_size;
Lines 931-936 Link Here
931
	return size;
937
	return size;
932
}
938
}
933
939
940
ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
941
{
942
	int err;
943
	
944
	down(&dentry->d_inode->i_sem);
945
	err = __jfs_listxattr(dentry->d_inode, data, buf_size);
946
	up(&dentry->d_inode->i_sem);
947
	
948
	return err;
949
}
950
934
int jfs_removexattr(struct dentry *dentry, const char *name)
951
int jfs_removexattr(struct dentry *dentry, const char *name)
935
{
952
{
936
	return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE);
953
	return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE);
(-)linux-2.4.22-ppc-dev.orig/fs/lockd/svc.c (+1 lines)
Lines 389-394 Link Here
389
389
390
#define NLM_NRVERS	(sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
390
#define NLM_NRVERS	(sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
391
struct svc_program		nlmsvc_program = {
391
struct svc_program		nlmsvc_program = {
392
	NULL,			/* last registered program */
392
	NLM_PROGRAM,		/* program number */
393
	NLM_PROGRAM,		/* program number */
393
	1, NLM_NRVERS-1,	/* version range */
394
	1, NLM_NRVERS-1,	/* version range */
394
	NLM_NRVERS,		/* number of entries in nlmsvc_version */
395
	NLM_NRVERS,		/* number of entries in nlmsvc_version */
(-)linux-2.4.22-ppc-dev.orig/fs/mbcache.c (+649 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/mbcache.c
3
 * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
4
 */
5
6
/*
7
 * Filesystem Meta Information Block Cache (mbcache)
8
 *
9
 * The mbcache caches blocks of block devices that need to be located
10
 * by their device/block number, as well as by other criteria (such
11
 * as the block's contents).
12
 *
13
 * There can only be one cache entry in a cache per device and block number.
14
 * Additional indexes need not be unique in this sense. The number of
15
 * additional indexes (=other criteria) can be hardwired at compile time
16
 * or specified at cache create time.
17
 *
18
 * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
19
 * in the cache. A valid entry is in the main hash tables of the cache,
20
 * and may also be in the lru list. An invalid entry is not in any hashes
21
 * or lists.
22
 *
23
 * A valid cache entry is only in the lru list if no handles refer to it.
24
 * Invalid cache entries will be freed when the last handle to the cache
25
 * entry is released. Entries that cannot be freed immediately are put
26
 * back on the lru list.
27
 */
28
29
#include <linux/kernel.h>
30
#include <linux/module.h>
31
32
#include <linux/fs.h>
33
#include <linux/slab.h>
34
#include <linux/sched.h>
35
#include <linux/cache_def.h>
36
#include <linux/version.h>
37
#include <linux/init.h>
38
#include <linux/mbcache.h>
39
40
41
#ifdef MB_CACHE_DEBUG
42
# define mb_debug(f...) do { \
43
		printk(KERN_DEBUG f); \
44
		printk("\n"); \
45
	} while (0)
46
#define mb_assert(c) do { if (!(c)) \
47
		printk(KERN_ERR "assertion " #c " failed\n"); \
48
	} while(0)
49
#else
50
# define mb_debug(f...) do { } while(0)
51
# define mb_assert(c) do { } while(0)
52
#endif
53
#define mb_error(f...) do { \
54
		printk(KERN_ERR f); \
55
		printk("\n"); \
56
	} while(0)
57
		
58
MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
59
MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
60
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
61
MODULE_LICENSE("GPL");
62
#endif
63
64
EXPORT_SYMBOL(mb_cache_create);
65
EXPORT_SYMBOL(mb_cache_shrink);
66
EXPORT_SYMBOL(mb_cache_destroy);
67
EXPORT_SYMBOL(mb_cache_entry_alloc);
68
EXPORT_SYMBOL(mb_cache_entry_insert);
69
EXPORT_SYMBOL(mb_cache_entry_release);
70
EXPORT_SYMBOL(mb_cache_entry_takeout);
71
EXPORT_SYMBOL(mb_cache_entry_free);
72
EXPORT_SYMBOL(mb_cache_entry_dup);
73
EXPORT_SYMBOL(mb_cache_entry_get);
74
#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
75
EXPORT_SYMBOL(mb_cache_entry_find_first);
76
EXPORT_SYMBOL(mb_cache_entry_find_next);
77
#endif
78
79
80
/*
81
 * Global data: list of all mbcache's, lru list, and a spinlock for
82
 * accessing cache data structures on SMP machines. The lru list is
83
 * global across all mbcaches.
84
 */
85
86
static LIST_HEAD(mb_cache_list);
87
static LIST_HEAD(mb_cache_lru_list);
88
static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
89
90
static inline int
91
mb_cache_indexes(struct mb_cache *cache)
92
{
93
#ifdef MB_CACHE_INDEXES_COUNT
94
	return MB_CACHE_INDEXES_COUNT;
95
#else
96
	return cache->c_indexes_count;
97
#endif
98
}
99
100
/*
101
 * What the mbcache registers as to get shrunk dynamically.
102
 */
103
104
static void
105
mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
106
107
static struct cache_definition mb_cache_definition = {
108
	"mb_cache",
109
	mb_cache_memory_pressure
110
};
111
112
113
static inline int
114
__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
115
{
116
	return !list_empty(&ce->e_block_list);
117
}
118
119
120
static inline void
121
__mb_cache_entry_unhash(struct mb_cache_entry *ce)
122
{
123
	int n;
124
125
	if (__mb_cache_entry_is_hashed(ce)) {
126
		list_del_init(&ce->e_block_list);
127
		for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
128
			list_del(&ce->e_indexes[n].o_list);
129
	}
130
}
131
132
133
static inline void
134
__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
135
{
136
	struct mb_cache *cache = ce->e_cache;
137
138
	mb_assert(atomic_read(&ce->e_used) == 0);
139
	if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
140
		/* free failed -- put back on the lru list
141
		   for freeing later. */
142
		spin_lock(&mb_cache_spinlock);
143
		list_add(&ce->e_lru_list, &mb_cache_lru_list);
144
		spin_unlock(&mb_cache_spinlock);
145
	} else {
146
		kmem_cache_free(cache->c_entry_cache, ce);
147
		atomic_dec(&cache->c_entry_count);
148
	}
149
}
150
151
152
static inline void
153
__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
154
{
155
	if (atomic_dec_and_test(&ce->e_used)) {
156
		if (__mb_cache_entry_is_hashed(ce))
157
			list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
158
		else {
159
			spin_unlock(&mb_cache_spinlock);
160
			__mb_cache_entry_forget(ce, GFP_KERNEL);
161
			return;
162
		}
163
	}
164
	spin_unlock(&mb_cache_spinlock);
165
}
166
167
168
/*
169
 * mb_cache_memory_pressure()  memory pressure callback
170
 *
171
 * This function is called by the kernel memory management when memory
172
 * gets low.
173
 *
174
 * @priority: Amount by which to shrink the cache (0 = highes priority)
175
 * @gfp_mask: (ignored)
176
 */
177
static void
178
mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
179
{
180
	LIST_HEAD(free_list);
181
	struct list_head *l, *ltmp;
182
	int count = 0;
183
184
	spin_lock(&mb_cache_spinlock);
185
	list_for_each(l, &mb_cache_list) {
186
		struct mb_cache *cache =
187
			list_entry(l, struct mb_cache, c_cache_list);
188
		mb_debug("cache %s (%d)", cache->c_name,
189
			  atomic_read(&cache->c_entry_count));
190
		count += atomic_read(&cache->c_entry_count);
191
	}
192
	mb_debug("trying to free %d of %d entries",
193
		  count / (priority ? priority : 1), count);
194
	if (priority)
195
		count /= priority;
196
	while (count-- && !list_empty(&mb_cache_lru_list)) {
197
		struct mb_cache_entry *ce =
198
			list_entry(mb_cache_lru_list.next,
199
				   struct mb_cache_entry, e_lru_list);
200
		list_del(&ce->e_lru_list);
201
		__mb_cache_entry_unhash(ce);
202
		list_add_tail(&ce->e_lru_list, &free_list);
203
	}
204
	spin_unlock(&mb_cache_spinlock);
205
	list_for_each_safe(l, ltmp, &free_list) {
206
		__mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
207
						   e_lru_list), gfp_mask);
208
	}
209
}
210
211
212
/*
213
 * mb_cache_create()  create a new cache
214
 *
215
 * All entries in one cache are equal size. Cache entries may be from
216
 * multiple devices. If this is the first mbcache created, registers
217
 * the cache with kernel memory management. Returns NULL if no more
218
 * memory was available.
219
 *
220
 * @name: name of the cache (informal)
221
 * @cache_op: contains the callback called when freeing a cache entry
222
 * @entry_size: The size of a cache entry, including
223
 *              struct mb_cache_entry
224
 * @indexes_count: number of additional indexes in the cache. Must equal
225
 *                 MB_CACHE_INDEXES_COUNT if the number of indexes is
226
 *                 hardwired.
227
 * @bucket_count: number of hash buckets
228
 */
229
struct mb_cache *
230
mb_cache_create(const char *name, struct mb_cache_op *cache_op,
231
		size_t entry_size, int indexes_count, int bucket_count)
232
{
233
	int m=0, n;
234
	struct mb_cache *cache = NULL;
235
236
	if(entry_size < sizeof(struct mb_cache_entry) +
237
	   indexes_count * sizeof(struct mb_cache_entry_index))
238
		return NULL;
239
240
	MOD_INC_USE_COUNT;
241
	cache = kmalloc(sizeof(struct mb_cache) +
242
	                indexes_count * sizeof(struct list_head), GFP_KERNEL);
243
	if (!cache)
244
		goto fail;
245
	cache->c_name = name;
246
	cache->c_op.free = NULL;
247
	if (cache_op)
248
		cache->c_op.free = cache_op->free;
249
	atomic_set(&cache->c_entry_count, 0);
250
	cache->c_bucket_count = bucket_count;
251
#ifdef MB_CACHE_INDEXES_COUNT
252
	mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
253
#else
254
	cache->c_indexes_count = indexes_count;
255
#endif
256
	cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
257
	                              GFP_KERNEL);
258
	if (!cache->c_block_hash)
259
		goto fail;
260
	for (n=0; n<bucket_count; n++)
261
		INIT_LIST_HEAD(&cache->c_block_hash[n]);
262
	for (m=0; m<indexes_count; m++) {
263
		cache->c_indexes_hash[m] = kmalloc(bucket_count *
264
		                                 sizeof(struct list_head),
265
		                                 GFP_KERNEL);
266
		if (!cache->c_indexes_hash[m])
267
			goto fail;
268
		for (n=0; n<bucket_count; n++)
269
			INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
270
	}
271
	cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
272
		0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
273
	if (!cache->c_entry_cache)
274
		goto fail;
275
276
	spin_lock(&mb_cache_spinlock);
277
	list_add(&cache->c_cache_list, &mb_cache_list);
278
	spin_unlock(&mb_cache_spinlock);
279
	return cache;
280
281
fail:
282
	if (cache) {
283
		while (--m >= 0)
284
			kfree(cache->c_indexes_hash[m]);
285
		if (cache->c_block_hash)
286
			kfree(cache->c_block_hash);
287
		kfree(cache);
288
	}
289
	MOD_DEC_USE_COUNT;
290
	return NULL;
291
}
292
293
294
/*
295
 * mb_cache_shrink()
296
 *
297
 * Removes all cache entires of a device from the cache. All cache entries
298
 * currently in use cannot be freed, and thus remain in the cache.
299
 *
300
 * @cache: which cache to shrink
301
 * @dev: which device's cache entries to shrink
302
 */
303
void
304
mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
305
{
306
	LIST_HEAD(free_list);
307
	struct list_head *l, *ltmp;
308
309
	spin_lock(&mb_cache_spinlock);
310
	list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
311
		struct mb_cache_entry *ce =
312
			list_entry(l, struct mb_cache_entry, e_lru_list);
313
		if (ce->e_dev == dev) {
314
			list_del(&ce->e_lru_list);
315
			list_add_tail(&ce->e_lru_list, &free_list);
316
			__mb_cache_entry_unhash(ce);
317
		}
318
	}
319
	spin_unlock(&mb_cache_spinlock);
320
	list_for_each_safe(l, ltmp, &free_list) {
321
		__mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
322
						   e_lru_list), GFP_KERNEL);
323
	}
324
}
325
326
327
/*
328
 * mb_cache_destroy()
329
 *
330
 * Shrinks the cache to its minimum possible size (hopefully 0 entries),
331
 * and then destroys it. If this was the last mbcache, un-registers the
332
 * mbcache from kernel memory management.
333
 */
334
void
335
mb_cache_destroy(struct mb_cache *cache)
336
{
337
	LIST_HEAD(free_list);
338
	struct list_head *l, *ltmp;
339
	int n;
340
341
	spin_lock(&mb_cache_spinlock);
342
	list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
343
		struct mb_cache_entry *ce =
344
			list_entry(l, struct mb_cache_entry, e_lru_list);
345
		if (ce->e_cache == cache) {
346
			list_del(&ce->e_lru_list);
347
			list_add_tail(&ce->e_lru_list, &free_list);
348
			__mb_cache_entry_unhash(ce);
349
		}
350
	}
351
	list_del(&cache->c_cache_list);
352
	spin_unlock(&mb_cache_spinlock);
353
	list_for_each_safe(l, ltmp, &free_list) {
354
		__mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
355
						   e_lru_list), GFP_KERNEL);
356
	}
357
358
	if (atomic_read(&cache->c_entry_count) > 0) {
359
		mb_error("cache %s: %d orphaned entries",
360
			  cache->c_name,
361
			  atomic_read(&cache->c_entry_count));
362
	}
363
364
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
365
	/* We don't have kmem_cache_destroy() in 2.2.x */
366
	kmem_cache_shrink(cache->c_entry_cache);
367
#else
368
	kmem_cache_destroy(cache->c_entry_cache);
369
#endif
370
	for (n=0; n < mb_cache_indexes(cache); n++)
371
		kfree(cache->c_indexes_hash[n]);
372
	kfree(cache->c_block_hash);
373
	kfree(cache);
374
375
	MOD_DEC_USE_COUNT;
376
}
377
378
379
/*
380
 * mb_cache_entry_alloc()
381
 *
382
 * Allocates a new cache entry. The new entry will not be valid initially,
383
 * and thus cannot be looked up yet. It should be filled with data, and
384
 * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
385
 * if no more memory was available.
386
 */
387
struct mb_cache_entry *
388
mb_cache_entry_alloc(struct mb_cache *cache)
389
{
390
	struct mb_cache_entry *ce;
391
392
	atomic_inc(&cache->c_entry_count);
393
	ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
394
	if (ce) {
395
		INIT_LIST_HEAD(&ce->e_lru_list);
396
		INIT_LIST_HEAD(&ce->e_block_list);
397
		ce->e_cache = cache;
398
		atomic_set(&ce->e_used, 1);
399
	}
400
	return ce;
401
}
402
403
404
/*
405
 * mb_cache_entry_insert()
406
 *
407
 * Inserts an entry that was allocated using mb_cache_entry_alloc() into
408
 * the cache. After this, the cache entry can be looked up, but is not yet
409
 * in the lru list as the caller still holds a handle to it. Returns 0 on
410
 * success, or -EBUSY if a cache entry for that device + inode exists
411
 * already (this may happen after a failed lookup, if another process has
412
 * inserted the same cache entry in the meantime).
413
 *
414
 * @dev: device the cache entry belongs to
415
 * @block: block number
416
 * @keys: array of additional keys. There must be indexes_count entries
417
 *        in the array (as specified when creating the cache).
418
 */
419
int
420
mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
421
		      unsigned long block, unsigned int keys[])
422
{
423
	struct mb_cache *cache = ce->e_cache;
424
	unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
425
	struct list_head *l;
426
	int error = -EBUSY, n;
427
428
	spin_lock(&mb_cache_spinlock);
429
	list_for_each(l, &cache->c_block_hash[bucket]) {
430
		struct mb_cache_entry *ce =
431
			list_entry(l, struct mb_cache_entry, e_block_list);
432
		if (ce->e_dev == dev && ce->e_block == block)
433
			goto out;
434
	}
435
	__mb_cache_entry_unhash(ce);
436
	ce->e_dev = dev;
437
	ce->e_block = block;
438
	list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
439
	for (n=0; n<mb_cache_indexes(cache); n++) {
440
		ce->e_indexes[n].o_key = keys[n];
441
		bucket = keys[n] % cache->c_bucket_count;
442
		list_add(&ce->e_indexes[n].o_list,
443
		         &cache->c_indexes_hash[n][bucket]);
444
	}
445
	error = 0;
446
out:
447
	spin_unlock(&mb_cache_spinlock);
448
	return error;
449
}
450
451
452
/*
453
 * mb_cache_entry_release()
454
 *
455
 * Release a handle to a cache entry. When the last handle to a cache entry
456
 * is released it is either freed (if it is invalid) or otherwise inserted
457
 * in to the lru list.
458
 */
459
void
460
mb_cache_entry_release(struct mb_cache_entry *ce)
461
{
462
	spin_lock(&mb_cache_spinlock);
463
	__mb_cache_entry_release_unlock(ce);
464
}
465
466
467
/*
468
 * mb_cache_entry_takeout()
469
 *
470
 * Take a cache entry out of the cache, making it invalid. The entry can later
471
 * be re-inserted using mb_cache_entry_insert(), or released using
472
 * mb_cache_entry_release().
473
 */
474
void
475
mb_cache_entry_takeout(struct mb_cache_entry *ce)
476
{
477
	spin_lock(&mb_cache_spinlock);
478
	mb_assert(list_empty(&ce->e_lru_list));
479
	__mb_cache_entry_unhash(ce);
480
	spin_unlock(&mb_cache_spinlock);
481
}
482
483
484
/*
485
 * mb_cache_entry_free()
486
 *
487
 * This is equivalent to the sequence mb_cache_entry_takeout() --
488
 * mb_cache_entry_release().
489
 */
490
void
491
mb_cache_entry_free(struct mb_cache_entry *ce)
492
{
493
	spin_lock(&mb_cache_spinlock);
494
	mb_assert(list_empty(&ce->e_lru_list));
495
	__mb_cache_entry_unhash(ce);
496
	__mb_cache_entry_release_unlock(ce);
497
}
498
499
500
/*
501
 * mb_cache_entry_dup()
502
 *
503
 * Duplicate a handle to a cache entry (does not duplicate the cache entry
504
 * itself). After the call, both the old and the new handle must be released.
505
 */
506
struct mb_cache_entry *
507
mb_cache_entry_dup(struct mb_cache_entry *ce)
508
{
509
	atomic_inc(&ce->e_used);
510
	return ce;
511
}
512
513
514
/*
515
 * mb_cache_entry_get()
516
 *
517
 * Get a cache entry  by device / block number. (There can only be one entry
518
 * in the cache per device and block.) Returns NULL if no such cache entry
519
 * exists.
520
 */
521
struct mb_cache_entry *
522
mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
523
{
524
	unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
525
	struct list_head *l;
526
	struct mb_cache_entry *ce;
527
528
	spin_lock(&mb_cache_spinlock);
529
	list_for_each(l, &cache->c_block_hash[bucket]) {
530
		ce = list_entry(l, struct mb_cache_entry, e_block_list);
531
		if (ce->e_dev == dev && ce->e_block == block) {
532
			if (!list_empty(&ce->e_lru_list))
533
				list_del_init(&ce->e_lru_list);
534
			atomic_inc(&ce->e_used);
535
			goto cleanup;
536
		}
537
	}
538
	ce = NULL;
539
540
cleanup:
541
	spin_unlock(&mb_cache_spinlock);
542
	return ce;
543
}
544
545
#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
546
547
static struct mb_cache_entry *
548
__mb_cache_entry_find(struct list_head *l, struct list_head *head,
549
		      int index, kdev_t dev, unsigned int key)
550
{
551
	while (l != head) {
552
		struct mb_cache_entry *ce =
553
			list_entry(l, struct mb_cache_entry,
554
			           e_indexes[index].o_list);
555
		if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
556
			if (!list_empty(&ce->e_lru_list))
557
				list_del_init(&ce->e_lru_list);
558
			atomic_inc(&ce->e_used);
559
			return ce;
560
		}
561
		l = l->next;
562
	}
563
	return NULL;
564
}
565
566
567
/*
568
 * mb_cache_entry_find_first()
569
 *
570
 * Find the first cache entry on a given device with a certain key in
571
 * an additional index. Additonal matches can be found with
572
 * mb_cache_entry_find_next(). Returns NULL if no match was found.
573
 *
574
 * @cache: the cache to search
575
 * @index: the number of the additonal index to search (0<=index<indexes_count)
576
 * @dev: the device the cache entry should belong to
577
 * @key: the key in the index
578
 */
579
struct mb_cache_entry *
580
mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
581
			  unsigned int key)
582
{
583
	unsigned int bucket = key % cache->c_bucket_count;
584
	struct list_head *l;
585
	struct mb_cache_entry *ce;
586
587
	mb_assert(index < mb_cache_indexes(cache));
588
	spin_lock(&mb_cache_spinlock);
589
	l = cache->c_indexes_hash[index][bucket].next;
590
	ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
591
	                           index, dev, key);
592
	spin_unlock(&mb_cache_spinlock);
593
	return ce;
594
}
595
596
597
/*
598
 * mb_cache_entry_find_next()
599
 *
600
 * Find the next cache entry on a given device with a certain key in an
601
 * additional index. Returns NULL if no match could be found. The previous
602
 * entry is atomatically released, so that mb_cache_entry_find_next() can
603
 * be called like this:
604
 *
605
 * entry = mb_cache_entry_find_first();
606
 * while (entry) {
607
 * 	...
608
 *	entry = mb_cache_entry_find_next(entry, ...);
609
 * }
610
 *
611
 * @prev: The previous match
612
 * @index: the number of the additonal index to search (0<=index<indexes_count)
613
 * @dev: the device the cache entry should belong to
614
 * @key: the key in the index
615
 */
616
struct mb_cache_entry *
617
mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
618
			 unsigned int key)
619
{
620
	struct mb_cache *cache = prev->e_cache;
621
	unsigned int bucket = key % cache->c_bucket_count;
622
	struct list_head *l;
623
	struct mb_cache_entry *ce;
624
625
	mb_assert(index < mb_cache_indexes(cache));
626
	spin_lock(&mb_cache_spinlock);
627
	l = prev->e_indexes[index].o_list.next;
628
	ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
629
	                           index, dev, key);
630
	__mb_cache_entry_release_unlock(prev);
631
	return ce;
632
}
633
634
#endif  /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
635
636
static int __init init_mbcache(void)
637
{
638
	register_cache(&mb_cache_definition);
639
	return 0;
640
}
641
642
static void __exit exit_mbcache(void)
643
{
644
	unregister_cache(&mb_cache_definition);
645
}
646
647
module_init(init_mbcache)
648
module_exit(exit_mbcache)
649
(-)linux-2.4.22-ppc-dev.orig/fs/namei.c (-6 / +10 lines)
Lines 1078-1085 Link Here
1078
			goto exit_dput;
1078
			goto exit_dput;
1079
		}
1079
		}
1080
1080
1081
		error = vfs_create(dir->d_inode, dentry,
1081
		if (!IS_POSIXACL(dir->d_inode))
1082
				   mode & ~current->fs->umask);
1082
			mode &= ~current->fs->umask;
1083
		error = vfs_create(dir->d_inode, dentry, mode);
1083
		if (!error)
1084
		if (!error)
1084
			gr_handle_create(dentry, nd->mnt);
1085
			gr_handle_create(dentry, nd->mnt);
1085
1086
Lines 1343-1349 Link Here
1343
	dentry = lookup_create(&nd, 0);
1344
	dentry = lookup_create(&nd, 0);
1344
	error = PTR_ERR(dentry);
1345
	error = PTR_ERR(dentry);
1345
1346
1346
	mode &= ~current->fs->umask;
1347
	if (!IS_POSIXACL(nd.dentry->d_inode))
1348
		mode &= ~current->fs->umask;
1347
	if (!IS_ERR(dentry)) {
1349
	if (!IS_ERR(dentry)) {
1348
		if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) {
1350
		if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) {
1349
			error = -EPERM;
1351
			error = -EPERM;
Lines 1433-1441 Link Here
1433
			if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt))
1435
			if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt))
1434
				error = -EACCES;
1436
				error = -EACCES;
1435
1437
1436
			if(!error)
1438
			if(!error) {
1437
				error = vfs_mkdir(nd.dentry->d_inode, dentry,
1439
				if (!IS_POSIXACL(nd.dentry->d_inode))
1438
					  mode & ~current->fs->umask);
1440
					mode &= ~current->fs->umask;
1441
				error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
1442
			}
1439
			if(!error)
1443
			if(!error)
1440
				gr_handle_create(dentry, nd.mnt);
1444
				gr_handle_create(dentry, nd.mnt);
1441
			
1445
			
(-)linux-2.4.22-ppc-dev.orig/fs/nfs/Makefile (+1 lines)
Lines 15-20 Link Here
15
obj-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o      
15
obj-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o      
16
obj-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
16
obj-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
17
obj-$(CONFIG_NFS_DIRECTIO) += direct.o
17
obj-$(CONFIG_NFS_DIRECTIO) += direct.o
18
obj-$(CONFIG_NFS_ACL) += xattr.o
18
19
19
obj-m   := $(O_TARGET)
20
obj-m   := $(O_TARGET)
20
21
(-)linux-2.4.22-ppc-dev.orig/fs/nfs/dir.c (-25 / +58 lines)
Lines 68-73 Link Here
68
	permission:	nfs_permission,
68
	permission:	nfs_permission,
69
	revalidate:	nfs_revalidate,
69
	revalidate:	nfs_revalidate,
70
	setattr:	nfs_notify_change,
70
	setattr:	nfs_notify_change,
71
	listxattr:	nfs_listxattr,
72
	getxattr:	nfs_getxattr,
73
	setxattr:	nfs_setxattr,
74
	removexattr:	nfs_removexattr,
71
};
75
};
72
76
73
typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int);
77
typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int);
Lines 1082-1115 Link Here
1082
int
1086
int
1083
nfs_permission(struct inode *inode, int mask)
1087
nfs_permission(struct inode *inode, int mask)
1084
{
1088
{
1085
	int			error = vfs_permission(inode, mask);
1089
	struct nfs_server *server = NFS_SERVER(inode);
1086
1090
	struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
1087
	if (!NFS_PROTO(inode)->access)
1091
	struct rpc_cred *cred;
1088
		goto out;
1092
	int mode = inode->i_mode;
1089
1093
	int error;
1090
	if (error == -EROFS)
1091
		goto out;
1092
1093
	/*
1094
	 * Trust UNIX mode bits except:
1095
	 *
1096
	 * 1) When override capabilities may have been invoked
1097
	 * 2) When root squashing may be involved
1098
	 * 3) When ACLs may overturn a negative answer */
1099
	if (!capable(CAP_DAC_OVERRIDE) && !capable(CAP_DAC_READ_SEARCH)
1100
	    && (current->fsuid != 0) && (current->fsgid != 0)
1101
	    && error != -EACCES)
1102
		goto out;
1103
1094
1104
	error = NFS_PROTO(inode)->access(inode, mask, 0);
1095
	if (mask & MAY_WRITE) {
1096
		/*
1097
		 *
1098
		 * Nobody gets write access to a read-only fs.
1099
		 *
1100
		 */
1101
		if (IS_RDONLY(inode) &&
1102
		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
1103
			return -EROFS;
1105
1104
1106
	if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv &&
1105
		/*
1107
	    current->uid != 0 && current->gid != 0 &&
1106
		 *
1108
	    (current->fsuid != current->uid || current->fsgid != current->gid))
1107
		 * Nobody gets write access to an immutable file.
1109
		error = NFS_PROTO(inode)->access(inode, mask, 1);
1108
		 *
1109
		 */
1110
		if (IS_IMMUTABLE(inode))
1111
			return -EACCES;
1112
	}
1110
1113
1111
 out:
1114
	if ((server->flags & NFS_MOUNT_NOACL) || !NFS_PROTO(inode)->access)
1112
	return error;
1115
		goto out_notsup;
1116
	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
1117
	if (cache->cred == cred
1118
	    && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) {
1119
		if (!cache->err) {
1120
			/* Is the mask a subset of an accepted mask? */
1121
			if ((cache->mask & mask) == mask)
1122
				goto out_cached;
1123
	       	} else {
1124
			/* ...or is it a superset of a rejected mask? */
1125
			if ((cache->mask & mask) == cache->mask)
1126
				goto out_cached;
1127
		}
1128
	}
1129
	error = NFS_PROTO(inode)->access(inode, cred, mask);
1130
	if (!error || error == -EACCES) {
1131
		cache->jiffies = jiffies;
1132
		if (cache->cred)
1133
			put_rpccred(cache->cred);
1134
		cache->cred = cred;
1135
		cache->mask = mask;
1136
		cache->err = error;
1137
		return error;
1138
	}
1139
	put_rpccred(cred);
1140
out_notsup:
1141
	nfs_revalidate_inode(NFS_SERVER(inode), inode);
1142
	return vfs_permission(inode, mask);
1143
out_cached:
1144
	put_rpccred(cred);
1145
	return cache->err;
1113
}
1146
}
1114
1147
1115
/*
1148
/*
(-)linux-2.4.22-ppc-dev.orig/fs/nfs/file.c (+4 lines)
Lines 57-62 Link Here
57
	permission:	nfs_permission,
57
	permission:	nfs_permission,
58
	revalidate:	nfs_revalidate,
58
	revalidate:	nfs_revalidate,
59
	setattr:	nfs_notify_change,
59
	setattr:	nfs_notify_change,
60
	listxattr:	nfs_listxattr,
61
	getxattr:	nfs_getxattr,
62
	setxattr:	nfs_setxattr,
63
	removexattr:	nfs_removexattr,
60
};
64
};
61
65
62
/* Hack for future NFS swap support */
66
/* Hack for future NFS swap support */
(-)linux-2.4.22-ppc-dev.orig/fs/nfs/inode.c (-2 / +80 lines)
Lines 65-70 Link Here
65
	show_options:	nfs_show_options,
65
	show_options:	nfs_show_options,
66
};
66
};
67
67
68
#ifdef CONFIG_NFS_ACL
69
static struct rpc_stat		nfs_acl_rpcstat = { &nfs_acl_program };
70
static struct rpc_version *	nfs_acl_version[] = {
71
	NULL,
72
	NULL,
73
	NULL,
74
	&nfs_acl_version3,
75
};
76
77
struct rpc_program		nfs_acl_program = {
78
	"nfs_acl",
79
	NFS3_ACL_PROGRAM,
80
	sizeof(nfs_acl_version) / sizeof(nfs_acl_version[0]),
81
	nfs_acl_version,
82
	&nfs_acl_rpcstat,
83
};
84
#endif  /* CONFIG_NFS_ACL */
85
68
/*
86
/*
69
 * RPC cruft for NFS
87
 * RPC cruft for NFS
70
 */
88
 */
Lines 146-155 Link Here
146
static void
164
static void
147
nfs_clear_inode(struct inode *inode)
165
nfs_clear_inode(struct inode *inode)
148
{
166
{
149
	struct rpc_cred *cred = NFS_I(inode)->mm_cred;
167
	struct nfs_inode_info *nfsi = NFS_I(inode);
168
	struct rpc_cred *cred = nfsi->mm_cred;
150
169
151
	if (cred)
170
	if (cred)
152
		put_rpccred(cred);
171
		put_rpccred(cred);
172
	cred = nfsi->cache_access.cred;
173
	if (cred)
174
		put_rpccred(cred);
153
}
175
}
154
176
155
void
177
void
Lines 168-173 Link Here
168
	if ((rpc = server->client) != NULL)
190
	if ((rpc = server->client) != NULL)
169
		rpc_shutdown_client(rpc);
191
		rpc_shutdown_client(rpc);
170
192
193
#ifdef CONFIG_NFS_ACL
194
	if ((rpc = server->acl_client) != NULL)
195
		rpc_shutdown_client(rpc);
196
#endif  /* CONFIG_NFS_ACL */
197
171
	nfs_reqlist_free(server);
198
	nfs_reqlist_free(server);
172
199
173
	if (!(server->flags & NFS_MOUNT_NONLM))
200
	if (!(server->flags & NFS_MOUNT_NONLM))
Lines 186-191 Link Here
186
	/* -EIO all pending I/O */
213
	/* -EIO all pending I/O */
187
	if ((rpc = server->client) != NULL)
214
	if ((rpc = server->client) != NULL)
188
		rpc_killall_tasks(rpc);
215
		rpc_killall_tasks(rpc);
216
	
217
#ifdef CONFIG_NFS_ACL
218
	if ((rpc = server->acl_client) != NULL)
219
		rpc_killall_tasks(rpc);
220
#endif  /* CONFIG_NFS_ACL */
189
}
221
}
190
222
191
223
Lines 383-388 Link Here
383
	clnt->cl_chatty   = 1;
415
	clnt->cl_chatty   = 1;
384
	server->client    = clnt;
416
	server->client    = clnt;
385
417
418
#ifdef CONFIG_NFS_ACL
419
	if (version == 3) {
420
		clnt = rpc_create_client(xprt, server->hostname,
421
					 &nfs_acl_program, version, authflavor);
422
		if (clnt == NULL) {
423
			rpc_shutdown_client(server->client);
424
			goto out_no_client;
425
		}
426
427
		clnt->cl_intr      = (data->flags & NFS_MOUNT_INTR)? 1 : 0;
428
		clnt->cl_softrtry  = (data->flags & NFS_MOUNT_SOFT)? 1 : 0;
429
		clnt->cl_droppriv  = (data->flags & NFS_MOUNT_BROKEN_SUID) ?1:0;
430
		clnt->cl_chatty    = 1;
431
		server->acl_client = clnt;
432
433
		/* Initially assume the nfs_acl program is supported */
434
		server->flags |= (NFS_SOLARIS_GETACL | NFS_SOLARIS_SETACL);
435
	}
436
#endif  /* CONFIG_NFS_ACL */
437
386
	/* Fire up rpciod if not yet running */
438
	/* Fire up rpciod if not yet running */
387
	if (rpciod_up() != 0)
439
	if (rpciod_up() != 0)
388
		goto out_no_iod;
440
		goto out_no_iod;
Lines 397-402 Link Here
397
		data->flags &= ~NFS_MOUNT_VER3;
449
		data->flags &= ~NFS_MOUNT_VER3;
398
		rpciod_down();
450
		rpciod_down();
399
		rpc_shutdown_client(server->client);
451
		rpc_shutdown_client(server->client);
452
#ifdef CONFIG_NFS_ACL
453
		rpc_shutdown_client(server->acl_client);
454
#endif  /* CONFIG_NFS_ACL */
400
		goto nfsv3_try_again;
455
		goto nfsv3_try_again;
401
	}
456
	}
402
457
Lines 493-498 Link Here
493
	printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
548
	printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
494
out_shutdown:
549
out_shutdown:
495
	rpc_shutdown_client(server->client);
550
	rpc_shutdown_client(server->client);
551
#ifdef CONFIG_NFS_ACL
552
	rpc_shutdown_client(server->acl_client);
553
#endif  /* CONFIG_NFS_ACL */
496
	goto out_free_host;
554
	goto out_free_host;
497
555
498
out_no_client:
556
out_no_client:
Lines 568-573 Link Here
568
		{ NFS_MOUNT_NOAC, ",noac", "" },
626
		{ NFS_MOUNT_NOAC, ",noac", "" },
569
		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
627
		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
570
		{ NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
628
		{ NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
629
		{ NFS_MOUNT_NOACL, ",noacl", "" },
571
		{ 0, NULL, NULL }
630
		{ 0, NULL, NULL }
572
	};
631
	};
573
	struct proc_nfs_info *nfs_infop;
632
	struct proc_nfs_info *nfs_infop;
Lines 623-628 Link Here
623
	nfs_zap_caches(inode);
682
	nfs_zap_caches(inode);
624
}
683
}
625
684
685
static struct inode_operations nfs_special_inode_operations = {
686
	listxattr:	nfs_listxattr,
687
	getxattr:	nfs_getxattr,
688
	setxattr:	nfs_setxattr,
689
	removexattr:	nfs_removexattr,
690
};
691
626
/*
692
/*
627
 * Fill in inode information from the fattr.
693
 * Fill in inode information from the fattr.
628
 */
694
 */
Lines 648-655 Link Here
648
			inode->i_fop = &nfs_dir_operations;
714
			inode->i_fop = &nfs_dir_operations;
649
		} else if (S_ISLNK(inode->i_mode))
715
		} else if (S_ISLNK(inode->i_mode))
650
			inode->i_op = &nfs_symlink_inode_operations;
716
			inode->i_op = &nfs_symlink_inode_operations;
651
		else
717
		else {
718
			inode->i_op = &nfs_special_inode_operations;
652
			init_special_inode(inode, inode->i_mode, fattr->rdev);
719
			init_special_inode(inode, inode->i_mode, fattr->rdev);
720
		}
653
		memcpy(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh));
721
		memcpy(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh));
654
	}
722
	}
655
	nfs_refresh_inode(inode, fattr);
723
	nfs_refresh_inode(inode, fattr);
Lines 1068-1073 Link Here
1068
	NFS_CACHE_ISIZE(inode) = new_size;
1136
	NFS_CACHE_ISIZE(inode) = new_size;
1069
	inode->i_size = new_isize;
1137
	inode->i_size = new_isize;
1070
1138
1139
	if (inode->i_mode != fattr->mode ||
1140
	    inode->i_uid != fattr->uid ||
1141
	    inode->i_gid != fattr->gid) {
1142
		struct rpc_cred **cred = &NFS_I(inode)->cache_access.cred;
1143
		if (*cred) {
1144
			put_rpccred(*cred);
1145
			*cred = NULL;
1146
		}
1147
	}
1148
1071
	inode->i_mode = fattr->mode;
1149
	inode->i_mode = fattr->mode;
1072
	inode->i_nlink = fattr->nlink;
1150
	inode->i_nlink = fattr->nlink;
1073
	inode->i_uid = fattr->uid;
1151
	inode->i_uid = fattr->uid;
(-)linux-2.4.22-ppc-dev.orig/fs/nfs/nfs3proc.c (-4 / +242 lines)
Lines 14-19 Link Here
14
#include <linux/nfs.h>
14
#include <linux/nfs.h>
15
#include <linux/nfs3.h>
15
#include <linux/nfs3.h>
16
#include <linux/nfs_fs.h>
16
#include <linux/nfs_fs.h>
17
#include <linux/nfs_mount.h>
17
18
18
#define NFSDBG_FACILITY		NFSDBG_PROC
19
#define NFSDBG_FACILITY		NFSDBG_PROC
19
20
Lines 117-128 Link Here
117
}
118
}
118
119
119
static int
120
static int
120
nfs3_proc_access(struct inode *inode, int mode, int ruid)
121
nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
121
{
122
{
122
	struct nfs_fattr	fattr;
123
	struct nfs_fattr	fattr;
123
	struct nfs3_accessargs	arg = { NFS_FH(inode), 0 };
124
	struct nfs3_accessargs	arg = { NFS_FH(inode), 0 };
124
	struct nfs3_accessres	res = { &fattr, 0 };
125
	struct nfs3_accessres	res = { &fattr, 0 };
125
	int	status, flags;
126
	struct rpc_message msg = { NFS3PROC_ACCESS, &arg, &res, cred };
127
	int	status;
126
128
127
	dprintk("NFS call  access\n");
129
	dprintk("NFS call  access\n");
128
	fattr.valid = 0;
130
	fattr.valid = 0;
Lines 140-147 Link Here
140
		if (mode & MAY_EXEC)
142
		if (mode & MAY_EXEC)
141
			arg.access |= NFS3_ACCESS_EXECUTE;
143
			arg.access |= NFS3_ACCESS_EXECUTE;
142
	}
144
	}
143
	flags = (ruid) ? RPC_CALL_REALUID : 0;
145
	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
144
	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
145
	nfs_refresh_inode(inode, &fattr);
146
	nfs_refresh_inode(inode, &fattr);
146
	dprintk("NFS reply access\n");
147
	dprintk("NFS reply access\n");
147
148
Lines 509-514 Link Here
509
	return status;
510
	return status;
510
}
511
}
511
512
513
#ifdef CONFIG_NFS_ACL
514
static int
515
nfs3_proc_checkacls(struct inode *inode)
516
{
517
	struct nfs_server *server = NFS_SERVER(inode);
518
	struct nfs_fattr fattr;
519
	struct nfs3_getaclargs args;
520
	struct nfs3_getaclres res = { &fattr };
521
	int status;
522
523
	if (!(server->flags & NFS_SOLARIS_GETACL) ||
524
	    (server->flags & NFS_MOUNT_NOACL))
525
		return -EOPNOTSUPP;
526
527
	args.fh = NFS_FH(inode);
528
	args.mask = NFS3_ACLCNT | NFS3_DFACLCNT;
529
530
	dprintk("NFS call getacl\n");
531
	status = rpc_call(NFS_ACL_CLIENT(inode), NFS3_ACL_PROC_GETACL,
532
			  &args, &res, 0);
533
	dprintk("NFS reply getacl: %d\n", status);
534
535
	if (status) {
536
		if (status == -ENOSYS) {
537
			dprintk("NFS_ACL GETACL RPC not supported "
538
				"(will not retry)\n");
539
			server->flags &= ~NFS_SOLARIS_GETACL;
540
			status = -EOPNOTSUPP;
541
		} else if (status == -ENOTSUPP)
542
			status = -EOPNOTSUPP;
543
		goto getout;
544
	}
545
	if ((args.mask & res.mask) != args.mask) {
546
		status = -EIO;
547
		goto getout;
548
	}
549
550
	status = nfs_refresh_inode(inode, &fattr);
551
552
getout:
553
	posix_acl_release(res.acl_access);
554
	posix_acl_release(res.acl_default);
555
556
	if (!status) {
557
		/* The (count > 4) test will exclude ACL entries from the list
558
		   of names even if their ACL_GROUP_ENTRY and ACL_MASK have
559
		   different permissions. Getacl still returns these as
560
		   four-entry ACLs, instead of minimal (three-entry) ACLs. */
561
		   
562
		if ((args.mask & NFS3_ACLCNT) && res.acl_access_count > 4)
563
			status |= ACL_TYPE_ACCESS;
564
		if ((args.mask & NFS3_DFACLCNT) && res.acl_default_count > 0)
565
			status |= ACL_TYPE_DEFAULT;
566
	}
567
	return status;
568
}
569
#endif  /* CONFIG_NFS_ACL */
570
571
#ifdef CONFIG_NFS_ACL
572
static struct posix_acl *
573
nfs3_proc_getacl(struct inode *inode, int type)
574
{
575
	struct nfs_server *server = NFS_SERVER(inode);
576
	struct nfs_fattr fattr;
577
	struct nfs3_getaclargs args;
578
	struct nfs3_getaclres res = { &fattr };
579
	struct posix_acl *acl = NULL;
580
	int status;
581
582
	if (!(server->flags & NFS_SOLARIS_GETACL) ||
583
	    (server->flags & NFS_MOUNT_NOACL))
584
		return ERR_PTR(-EOPNOTSUPP);
585
586
	args.fh = NFS_FH(inode);
587
	switch(type) {
588
		case ACL_TYPE_ACCESS:
589
			args.mask = NFS3_ACLCNT|NFS3_ACL;
590
			break;
591
592
		case ACL_TYPE_DEFAULT:
593
			args.mask = NFS3_DFACLCNT|NFS3_DFACL;
594
			break;
595
596
		default:
597
			return ERR_PTR(-EINVAL);
598
	}
599
600
	dprintk("NFS call getacl\n");
601
	status = rpc_call(NFS_ACL_CLIENT(inode), NFS3_ACL_PROC_GETACL,
602
			  &args, &res, 0);
603
	dprintk("NFS reply getacl: %d\n", status);
604
605
	if (status) {
606
		if (status == -ENOSYS) {
607
			dprintk("NFS_ACL GETACL RPC not supported "
608
				"(will not retry)\n");
609
			server->flags &= ~NFS_SOLARIS_GETACL;
610
			status = -EOPNOTSUPP;
611
		} else if (status == -ENOTSUPP)
612
			status = -EOPNOTSUPP;
613
		goto getout;
614
	}
615
	if ((args.mask & res.mask) != args.mask) {
616
		status = -EIO;
617
		goto getout;
618
	}
619
620
	if (type == ACL_TYPE_ACCESS) {
621
		if (res.acl_access) {
622
			mode_t mode = inode->i_mode;
623
			if (!posix_acl_equiv_mode(res.acl_access, &mode) &&
624
			    inode->i_mode == mode) {
625
				posix_acl_release(res.acl_access);
626
				res.acl_access = NULL;
627
			}
628
		}
629
		acl = res.acl_access;
630
		res.acl_access = NULL;
631
	} else {
632
		acl = res.acl_default;
633
		res.acl_default = NULL;
634
	}
635
636
	status = nfs_refresh_inode(inode, &fattr);
637
638
getout:
639
	posix_acl_release(res.acl_access);
640
	posix_acl_release(res.acl_default);
641
642
	if (status) {
643
		posix_acl_release(acl);
644
		acl = ERR_PTR(status);
645
	}
646
	return acl;
647
}
648
#endif  /* CONFIG_NFS_ACL */
649
650
#ifdef CONFIG_NFS_ACL
651
static int
652
nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
653
{
654
	struct nfs_server *server = NFS_SERVER(inode);
655
	struct nfs_fattr fattr;
656
	struct nfs3_setaclargs args = { };
657
	int status;
658
659
	if (!(server->flags & NFS_SOLARIS_SETACL) ||
660
	    (server->flags & NFS_MOUNT_NOACL))
661
		return -EOPNOTSUPP;
662
663
	/* We are doing this here, because XDR marshalling can only
664
	   return -ENOMEM. */
665
	if (acl && acl->a_count > NFS3_ACL_MAX_ENTRIES)
666
		return -EINVAL;
667
	args.inode = inode;
668
	args.mask = NFS3_ACL|NFS3_DFACL;
669
	if (S_ISDIR(inode->i_mode)) {
670
		switch(type) {
671
			case ACL_TYPE_ACCESS:
672
				args.acl_access = acl;
673
				args.acl_default = NFS_PROTO(inode)->getacl(
674
					inode, ACL_TYPE_DEFAULT);
675
				status = PTR_ERR(args.acl_default);
676
				if (IS_ERR(args.acl_default)) {
677
					args.acl_default = NULL;
678
					goto cleanup;
679
				}
680
				break;
681
682
			case ACL_TYPE_DEFAULT:
683
				args.acl_access = NFS_PROTO(inode)->getacl(
684
					inode, ACL_TYPE_ACCESS);
685
				status = PTR_ERR(args.acl_access);
686
				if (IS_ERR(args.acl_access)) {
687
					args.acl_access = NULL;
688
					goto cleanup;
689
				}
690
				args.acl_default = acl;
691
				break;
692
693
			default:
694
				status = -EINVAL;
695
				goto cleanup;
696
		}
697
	} else {
698
		status = -EINVAL;
699
		if (type != ACL_TYPE_ACCESS)
700
			goto cleanup;
701
		args.mask = NFS3_ACL;
702
		args.acl_access = acl;
703
	}
704
	if (args.acl_access == NULL) {
705
		args.acl_access = posix_acl_from_mode(inode->i_mode,
706
						      GFP_KERNEL);
707
		status = PTR_ERR(args.acl_access);
708
		if (IS_ERR(args.acl_access)) {
709
			args.acl_access = NULL;
710
			goto cleanup;
711
		}
712
	}
713
	args.mask = NFS3_ACL | (args.acl_default ? NFS3_DFACL : 0);
714
715
	dprintk("NFS call setacl\n");
716
	status = rpc_call(NFS_ACL_CLIENT(inode), NFS3_ACL_PROC_SETACL,
717
			  &args, &fattr, 0);
718
	dprintk("NFS reply setacl: %d\n", status);
719
720
	if (status) {
721
		if (status == -ENOSYS) {
722
			dprintk("NFS_ACL SETACL RPC not supported"
723
				"(will not retry)\n");
724
			server->flags &= ~NFS_SOLARIS_SETACL;
725
			status = -EOPNOTSUPP;
726
		} else if (status == -ENOTSUPP)
727
			status = -EOPNOTSUPP;
728
	} else {
729
		/* Force an attribute cache update if the file mode
730
		 * has changed. */
731
		if (inode->i_mode != fattr.mode)
732
			NFS_CACHEINV(inode);
733
		status = nfs_refresh_inode(inode, &fattr);
734
	}
735
736
cleanup:
737
	if (args.acl_access != acl)
738
		posix_acl_release(args.acl_access);
739
	if (args.acl_default != acl)
740
		posix_acl_release(args.acl_default);
741
	return status;
742
}
743
#endif  /* CONFIG_NFS_ACL */
744
512
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
745
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
513
746
514
struct nfs_rpc_ops	nfs_v3_clientops = {
747
struct nfs_rpc_ops	nfs_v3_clientops = {
Lines 535-538 Link Here
535
	nfs3_proc_mknod,
768
	nfs3_proc_mknod,
536
	nfs3_proc_statfs,
769
	nfs3_proc_statfs,
537
	nfs3_decode_dirent,
770
	nfs3_decode_dirent,
771
#ifdef CONFIG_NFS_ACL
772
	nfs3_proc_getacl,
773
	nfs3_proc_setacl,
774
	nfs3_proc_checkacls,
775
#endif  /* CONFIG_NFS_ACL */
538
};
776
};
(-)linux-2.4.22-ppc-dev.orig/fs/nfs/nfs3xdr.c (+114 lines)
Lines 21-26 Link Here
21
#include <linux/nfs.h>
21
#include <linux/nfs.h>
22
#include <linux/nfs3.h>
22
#include <linux/nfs3.h>
23
#include <linux/nfs_fs.h>
23
#include <linux/nfs_fs.h>
24
#include <linux/solaris_acl.h>
24
25
25
#define NFSDBG_FACILITY		NFSDBG_XDR
26
#define NFSDBG_FACILITY		NFSDBG_XDR
26
27
Lines 47-52 Link Here
47
#define NFS3_fsinfo_sz		
48
#define NFS3_fsinfo_sz		
48
#define NFS3_pathconf_sz		
49
#define NFS3_pathconf_sz		
49
#define NFS3_entry_sz		NFS3_filename_sz+3
50
#define NFS3_entry_sz		NFS3_filename_sz+3
51
#define NFS3_acl_sz		1+NFS3_ACL_MAX_ENTRIES*3
50
52
51
#define NFS3_enc_void_sz	0
53
#define NFS3_enc_void_sz	0
52
#define NFS3_sattrargs_sz	NFS3_fh_sz+NFS3_sattr_sz+3
54
#define NFS3_sattrargs_sz	NFS3_fh_sz+NFS3_sattr_sz+3
Lines 63-68 Link Here
63
#define NFS3_linkargs_sz		NFS3_fh_sz+NFS3_diropargs_sz
65
#define NFS3_linkargs_sz		NFS3_fh_sz+NFS3_diropargs_sz
64
#define NFS3_readdirargs_sz	NFS3_fh_sz+2
66
#define NFS3_readdirargs_sz	NFS3_fh_sz+2
65
#define NFS3_commitargs_sz	NFS3_fh_sz+3
67
#define NFS3_commitargs_sz	NFS3_fh_sz+3
68
#define NFS3_getaclargs_sz	NFS3_fh_sz+1
69
#define NFS3_setaclargs_sz	NFS3_fh_sz+1+2*(1+NFS3_acl_sz)
66
70
67
#define NFS3_dec_void_sz	0
71
#define NFS3_dec_void_sz	0
68
#define NFS3_attrstat_sz	1+NFS3_fattr_sz
72
#define NFS3_attrstat_sz	1+NFS3_fattr_sz
Lines 80-85 Link Here
80
#define NFS3_fsinfores_sz	1+NFS3_post_op_attr_sz+12
84
#define NFS3_fsinfores_sz	1+NFS3_post_op_attr_sz+12
81
#define NFS3_pathconfres_sz	1+NFS3_post_op_attr_sz+6
85
#define NFS3_pathconfres_sz	1+NFS3_post_op_attr_sz+6
82
#define NFS3_commitres_sz	1+NFS3_wcc_data_sz+2
86
#define NFS3_commitres_sz	1+NFS3_wcc_data_sz+2
87
#define NFS3_getaclres_sz	1+NFS3_post_op_attr_sz+1+2*(1+NFS3_acl_sz)
88
#define NFS3_setaclres_sz	1+NFS3_post_op_attr_sz
83
89
84
/*
90
/*
85
 * Map file type to S_IFMT bits
91
 * Map file type to S_IFMT bits
Lines 650-655 Link Here
650
	return 0;
656
	return 0;
651
}
657
}
652
658
659
#ifdef CONFIG_NFS_ACL
660
/*
661
 * Encode GETACL arguments
662
 */
663
static int
664
nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
665
		    struct nfs3_getaclargs *args)
666
{
667
	p = xdr_encode_fhandle(p, args->fh);
668
	*p++ = htonl(args->mask);
669
	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
670
671
	return 0;
672
}
673
#endif  /* CONFIG_NFS_ACL */
674
675
#ifdef CONFIG_NFS_ACL
676
/*
677
 * Encode SETACL arguments
678
 */
679
static int
680
nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
681
		    struct nfs3_setaclargs *args)
682
{
683
	struct iovec *iov = req->rq_svec;
684
	u32 *end = (u32 *)((u8 *)iov->iov_base + iov->iov_len);
685
	struct posix_acl *acl;
686
687
	p = xdr_encode_fhandle(p, NFS_FH(args->inode));
688
	*p++ = htonl(args->mask);
689
	acl = (args->mask & NFS3_ACL) ? args->acl_access : NULL;
690
	if (!(p = nfs_acl_encode(p, end, args->inode, acl, 1, 0)))
691
		return -ENOMEM;
692
	acl = (args->mask & NFS3_DFACL) ? args->acl_default : NULL;
693
	if (!(p = nfs_acl_encode(p, end, args->inode, acl, 1, NFS3_ACL_DEFAULT)))
694
		return -ENOMEM;
695
	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
696
	
697
	return 0;
698
}
699
#endif  /* CONFIG_NFS_ACL */
700
653
/*
701
/*
654
 * NFS XDR decode functions
702
 * NFS XDR decode functions
655
 */
703
 */
Lines 1002-1007 Link Here
1002
	return 0;
1050
	return 0;
1003
}
1051
}
1004
1052
1053
#ifdef CONFIG_NFS_ACL
1054
/*
1055
 * Decode GETACL reply
1056
 */
1057
static int
1058
nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
1059
		   struct nfs3_getaclres *res)
1060
{
1061
	struct iovec *iov = req->rq_rvec;
1062
	u32 *end = (u32 *)((u8 *)iov->iov_base + iov->iov_len);
1063
	int status = ntohl(*p++);
1064
	struct posix_acl **acl;
1065
	unsigned int *aclcnt;
1066
1067
	if (status != 0)
1068
		return -nfs_stat_to_errno(status);
1069
1070
	p = xdr_decode_post_op_attr(p, res->fattr);
1071
1072
	res->mask = ntohl(*p++);
1073
	if (res->mask & ~(NFS3_ACL|NFS3_ACLCNT|NFS3_DFACL|NFS3_DFACLCNT))
1074
		return -EINVAL;
1075
		
1076
	/* res->acl_{access,default} are released in nfs3_proc_getacl. */
1077
	acl = (res->mask & NFS3_ACL) ? &res->acl_access : NULL;
1078
	aclcnt = (res->mask & NFS3_ACLCNT) ? &res->acl_access_count : NULL;
1079
	if (!(p = nfs_acl_decode(p, end, aclcnt, acl)))
1080
		return -EINVAL;
1081
1082
	acl = (res->mask & NFS3_DFACL) ? &res->acl_default : NULL;
1083
	aclcnt = (res->mask & NFS3_DFACLCNT) ? &res->acl_default_count : NULL;
1084
	if (!(p = nfs_acl_decode(p, end, aclcnt, acl)))
1085
		return -EINVAL;
1086
	return 0;
1087
}
1088
#endif  /* CONFIG_NFS_ACL */
1089
1090
#ifdef CONFIG_NFS_ACL
1091
/*
1092
 * Decode setacl reply.
1093
 */
1094
static int
1095
nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
1096
{
1097
	int status = ntohl(*p++);
1098
1099
	if (status)
1100
		return -nfs_stat_to_errno(status);
1101
	xdr_decode_post_op_attr(p, fattr);
1102
	return 0;
1103
}
1104
#endif  /* CONFIG_NFS_ACL */
1105
1005
#ifndef MAX
1106
#ifndef MAX
1006
# define MAX(a, b)	(((a) > (b))? (a) : (b))
1107
# define MAX(a, b)	(((a) > (b))? (a) : (b))
1007
#endif
1108
#endif
Lines 1045-1047 Link Here
1045
	nfs3_procedures
1146
	nfs3_procedures
1046
};
1147
};
1047
1148
1149
#ifdef CONFIG_NFS_ACL
1150
static struct rpc_procinfo	nfs3_acl_procedures[] = {
1151
  PROC(null,		enc_void,	dec_void, 0),
1152
  PROC(getacl,		getaclargs,	getaclres, 1),
1153
  PROC(setacl,		setaclargs,	setaclres, 0),
1154
};
1155
1156
struct rpc_version		nfs_acl_version3 = {
1157
	3,
1158
	sizeof(nfs3_acl_procedures)/sizeof(nfs3_acl_procedures[0]),
1159
	nfs3_acl_procedures
1160
};
1161
#endif  /* CONFIG_NFS_ACL */
(-)linux-2.4.22-ppc-dev.orig/fs/nfs/xattr.c (+115 lines)
Line 0 Link Here
1
#include <linux/fs.h>
2
#include <linux/nfs.h>
3
#include <linux/nfs3.h>
4
#include <linux/nfs_fs.h>
5
#include <linux/xattr_acl.h>
6
7
ssize_t
8
nfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
9
{
10
	struct inode *inode = dentry->d_inode;
11
	int error=0, pos=0, len=0;
12
13
	error = -EOPNOTSUPP;
14
	if (NFS_PROTO(inode)->version == 3 && NFS_PROTO(inode)->checkacls)
15
		error = NFS_PROTO(inode)->checkacls(inode);
16
	if (error < 0)
17
		return error;
18
	
19
#	define output(s) do {						\
20
			if (pos + sizeof(s) <= size) {			\
21
				memcpy(buffer + pos, s, sizeof(s));	\
22
				pos += sizeof(s);			\
23
			}						\
24
			len += sizeof(s);				\
25
		} while(0)
26
27
	if (error & ACL_TYPE_ACCESS)
28
		output("system.posix_acl_access");
29
	if (error & ACL_TYPE_DEFAULT)
30
		output("system.posix_acl_default");
31
32
#	undef output
33
34
	if (!buffer || len <= size)
35
		return len;
36
	return -ERANGE;
37
}
38
39
ssize_t
40
nfs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
41
{
42
	struct inode *inode = dentry->d_inode;
43
	struct posix_acl *acl;
44
	int type, error = 0;
45
46
	if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
47
		type = ACL_TYPE_ACCESS;
48
	else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
49
		type = ACL_TYPE_DEFAULT;
50
	else
51
		return -EOPNOTSUPP;
52
53
	acl = ERR_PTR(-EOPNOTSUPP);
54
	if (NFS_PROTO(inode)->version == 3 && NFS_PROTO(inode)->getacl)
55
		acl = NFS_PROTO(inode)->getacl(inode, type);
56
	if (IS_ERR(acl))
57
		return PTR_ERR(acl);
58
	else if (acl) {
59
		if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
60
			error = -ENODATA;
61
		else
62
			error = posix_acl_to_xattr(acl, buffer, size);
63
		posix_acl_release(acl);
64
	} else
65
		error = -ENODATA;
66
67
	return error;
68
}
69
70
int
71
nfs_setxattr(struct dentry *dentry, const char *name,
72
	     const void *value, size_t size, int flags)
73
{
74
	struct inode *inode = dentry->d_inode;
75
	struct posix_acl *acl;
76
	int type, error;
77
78
	if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
79
		type = ACL_TYPE_ACCESS;
80
	else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
81
		type = ACL_TYPE_DEFAULT;
82
	else
83
		return -EOPNOTSUPP;
84
85
	acl = posix_acl_from_xattr(value, size);
86
	if (IS_ERR(acl))
87
		return PTR_ERR(acl);
88
89
	error = -EOPNOTSUPP;
90
	if (NFS_PROTO(inode)->version == 3 && NFS_PROTO(inode)->setacl)
91
		error = NFS_PROTO(inode)->setacl(inode, type, acl);
92
	posix_acl_release(acl);
93
94
	return error;
95
}
96
97
int
98
nfs_removexattr(struct dentry *dentry, const char *name)
99
{
100
	struct inode *inode = dentry->d_inode;
101
	int error, type;
102
103
	if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
104
		type = ACL_TYPE_ACCESS;
105
	else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
106
		type = ACL_TYPE_DEFAULT;
107
	else
108
		return -EOPNOTSUPP;
109
110
	error = -EOPNOTSUPP;
111
	if (NFS_PROTO(inode)->version == 3 && NFS_PROTO(inode)->setacl)
112
		error = NFS_PROTO(inode)->setacl(inode, type, NULL);
113
114
	return error;
115
}
(-)linux-2.4.22-ppc-dev.orig/fs/nfsd/export.c (+1 lines)
Lines 643-648 Link Here
643
	{ NFSEXP_CROSSMNT, {"nohide", ""}},
643
	{ NFSEXP_CROSSMNT, {"nohide", ""}},
644
	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
644
	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
645
	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
645
	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
646
	{ NFSEXP_NOACL, {"no_acl", ""}},
646
#ifdef MSNFS
647
#ifdef MSNFS
647
	{ NFSEXP_MSNFS, {"msnfs", ""}},
648
	{ NFSEXP_MSNFS, {"msnfs", ""}},
648
#endif
649
#endif
(-)linux-2.4.22-ppc-dev.orig/fs/nfsd/nfs3proc.c (+109 lines)
Lines 628-633 Link Here
628
	RETURN_STATUS(nfserr);
628
	RETURN_STATUS(nfserr);
629
}
629
}
630
630
631
#ifdef CONFIG_NFSD_ACL
632
/*
633
 * Get the Access and/or Default ACL of a file.
634
 */
635
static int
636
nfsd3_proc_getacl(struct svc_rqst * rqstp, struct nfsd3_getaclargs *argp,
637
					     struct nfsd3_getaclres *resp)
638
{
639
	svc_fh *fh;
640
	struct posix_acl *acl;
641
	int nfserr = 0;
642
643
	fh = fh_copy(&resp->fh, &argp->fh);
644
	if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
645
		RETURN_STATUS(nfserr_inval);
646
	
647
	if (argp->mask & ~(NFS3_ACL|NFS3_ACLCNT|NFS3_DFACL|NFS3_DFACLCNT))
648
		RETURN_STATUS(nfserr_inval);
649
	resp->mask = argp->mask;
650
651
	if (resp->mask & (NFS3_ACL|NFS3_ACLCNT)) {
652
		acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
653
		if (IS_ERR(acl)) {
654
			int err = PTR_ERR(acl);
655
656
			if (err == -ENODATA || err == -EOPNOTSUPP)
657
				acl = NULL;
658
			else {
659
				nfserr = nfserrno(err);
660
				goto fail;
661
			}
662
		}
663
		if (acl == NULL) {
664
			/* Solaris returns the inode's minimum ACL. */
665
666
			struct inode *inode = fh->fh_dentry->d_inode;
667
			acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
668
		}
669
		resp->acl_access = acl;
670
	}
671
	if (resp->mask & (NFS3_DFACL|NFS3_DFACLCNT)) {
672
		/* Check how Solaris handles requests for the Default ACL
673
		   of a non-directory! */
674
675
		acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
676
		if (IS_ERR(acl)) {
677
			int err = PTR_ERR(acl);
678
679
			if (err == -ENODATA || err == -EOPNOTSUPP)
680
				acl = NULL;
681
			else {
682
				nfserr = nfserrno(err);
683
				goto fail;
684
			}
685
		}
686
		resp->acl_default = acl;
687
	}
688
689
	/* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
690
	RETURN_STATUS(0);
691
692
fail:
693
	posix_acl_release(resp->acl_access);
694
	posix_acl_release(resp->acl_default);
695
	RETURN_STATUS(nfserr);
696
}
697
#endif  /* CONFIG_NFSD_ACL */
698
699
#ifdef CONFIG_NFSD_ACL
700
/*
701
 * Set the Access and/or Default ACL of a file.
702
 */
703
static int
704
nfsd3_proc_setacl(struct svc_rqst * rqstp, struct nfsd3_setaclargs *argp,
705
					     struct nfsd3_attrstat *resp)
706
{
707
	svc_fh *fh;
708
	int nfserr = 0;
709
710
	fh = fh_copy(&resp->fh, &argp->fh);
711
	nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
712
	
713
	if (!nfserr) {
714
		nfserr = nfserrno( nfsd_set_posix_acl(
715
			fh, ACL_TYPE_ACCESS, argp->acl_access) );
716
	}
717
	if (!nfserr) {
718
		nfserr = nfserrno( nfsd_set_posix_acl(
719
			fh, ACL_TYPE_DEFAULT, argp->acl_default) );
720
	}
721
722
	/* argp->acl_{access,default} may have been allocated in
723
	   nfs3svc_decode_setaclargs. */
724
	posix_acl_release(argp->acl_access);
725
	posix_acl_release(argp->acl_default);
726
	RETURN_STATUS(nfserr);
727
}
728
#endif  /* CONFIG_NFSD_ACL */
729
631
730
632
/*
731
/*
633
 * NFSv3 Server procedures.
732
 * NFSv3 Server procedures.
Lines 644-649 Link Here
644
#define nfsd3_fhandleres		nfsd3_attrstat
743
#define nfsd3_fhandleres		nfsd3_attrstat
645
#define nfsd3_attrstatres		nfsd3_attrstat
744
#define nfsd3_attrstatres		nfsd3_attrstat
646
#define nfsd3_wccstatres		nfsd3_attrstat
745
#define nfsd3_wccstatres		nfsd3_attrstat
746
#define nfsd3_setaclres			nfsd3_attrstat
647
#define nfsd3_createres			nfsd3_diropres
747
#define nfsd3_createres			nfsd3_diropres
648
#define nfsd3_voidres			nfsd3_voidargs
748
#define nfsd3_voidres			nfsd3_voidargs
649
struct nfsd3_voidargs { int dummy; };
749
struct nfsd3_voidargs { int dummy; };
Lines 665-670 Link Here
665
#define AT 21		/* attributes */
765
#define AT 21		/* attributes */
666
#define pAT (1+AT)	/* post attributes - conditional */
766
#define pAT (1+AT)	/* post attributes - conditional */
667
#define WC (7+pAT)	/* WCC attributes */
767
#define WC (7+pAT)	/* WCC attributes */
768
#define ACL (1+NFS3_ACL_MAX_ENTRIES*3)  /* Access Control List */
668
769
669
struct svc_procedure		nfsd_procedures3[22] = {
770
struct svc_procedure		nfsd_procedures3[22] = {
670
  PROC(null,	 void,		void,		void,	 RC_NOCACHE, ST),
771
  PROC(null,	 void,		void,		void,	 RC_NOCACHE, ST),
Lines 690-692 Link Here
690
  PROC(pathconf, fhandle,	pathconf,	void,     RC_NOCACHE, ST+pAT+6),
791
  PROC(pathconf, fhandle,	pathconf,	void,     RC_NOCACHE, ST+pAT+6),
691
  PROC(commit,	 commit,	commit,		fhandle,  RC_NOCACHE, ST+WC+2),
792
  PROC(commit,	 commit,	commit,		fhandle,  RC_NOCACHE, ST+WC+2),
692
};
793
};
794
795
#ifdef CONFIG_NFSD_ACL
796
struct svc_procedure		nfsd_acl_procedures3[] = {
797
  PROC(null,	 void,		void,		void,	 RC_NOCACHE, ST),
798
  PROC(getacl,	 getacl,	getacl,		getacl,  RC_NOCACHE, ST+1+2*(1+ACL)),
799
  PROC(setacl,	 setacl,	setacl,		fhandle, RC_NOCACHE, ST+pAT)
800
};
801
#endif  /* CONFIG_NFSD_ACL */
(-)linux-2.4.22-ppc-dev.orig/fs/nfsd/nfs3xdr.c (-1 / +110 lines)
Lines 15-20 Link Here
15
#include <linux/nfsd/nfsd.h>
15
#include <linux/nfsd/nfsd.h>
16
#include <linux/nfsd/xdr3.h>
16
#include <linux/nfsd/xdr3.h>
17
17
18
#include <linux/solaris_acl.h>
19
18
#define NFSDDBG_FACILITY		NFSDDBG_XDR
20
#define NFSDDBG_FACILITY		NFSDDBG_XDR
19
21
20
#ifdef NFSD_OPTIMIZE_SPACE
22
#ifdef NFSD_OPTIMIZE_SPACE
Lines 157-165 Link Here
157
encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
159
encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
158
{
160
{
159
	struct inode	*inode = fhp->fh_dentry->d_inode;
161
	struct inode	*inode = fhp->fh_dentry->d_inode;
162
	mode_t		mode = inode->i_mode;
163
164
	if (IS_POSIXACL(inode) && !EX_ACL(fhp->fh_export)) {
165
		struct posix_acl *acl = nfsd_get_posix_acl(fhp,ACL_TYPE_ACCESS);
160
166
167
		if (!IS_ERR(acl) && acl) {
168
			posix_acl_masq_nfs_mode(acl, &mode);
169
			posix_acl_release(acl);
170
		}
171
	}
172
  
161
	*p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]);
173
	*p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]);
162
	*p++ = htonl((u32) inode->i_mode);
174
	*p++ = htonl((u32) mode);
163
	*p++ = htonl((u32) inode->i_nlink);
175
	*p++ = htonl((u32) inode->i_nlink);
164
	*p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
176
	*p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
165
	*p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
177
	*p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
Lines 501-506 Link Here
501
	return xdr_argsize_check(rqstp, p);
513
	return xdr_argsize_check(rqstp, p);
502
}
514
}
503
515
516
#ifdef CONFIG_NFSD_ACL
517
int
518
nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
519
					struct nfsd3_getaclargs *args)
520
{
521
	if (!(p = decode_fh(p, &args->fh)))
522
		return 0;
523
	args->mask = ntohl(*p); p++;
524
525
	return xdr_argsize_check(rqstp, p);
526
}
527
#endif  /* CONFIG_NFS_ACL */
528
529
#ifdef CONFIG_NFSD_ACL
530
int
531
nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
532
					struct nfsd3_setaclargs *args)
533
{
534
        struct svc_buf  *buf = &rqstp->rq_argbuf;
535
	u32 *end = buf->base + buf->buflen;
536
	struct posix_acl **acl;
537
538
	if (!(p = decode_fh(p, &args->fh)))
539
		return 0;
540
	args->mask = ntohl(*p++);
541
	if (args->mask & ~(NFS3_ACL|NFS3_ACLCNT|NFS3_DFACL|NFS3_DFACLCNT) ||
542
	    !xdr_argsize_check(rqstp, p))
543
		return 0;
544
	
545
	/* argp->acl_{access,default} are released in nfsd3_proc_setacl. */
546
	acl = (args->mask & NFS3_ACL) ? &args->acl_access : NULL;
547
	if (!(p = nfs_acl_decode(p, end, NULL, acl)))
548
		return 0;
549
	
550
	acl = (args->mask & NFS3_DFACL) ? &args->acl_default : NULL;
551
	if (!(p = nfs_acl_decode(p, end, NULL, acl))) {
552
		posix_acl_release(args->acl_access);
553
		args->acl_access = NULL;
554
		return 0;
555
	}
556
	
557
	return 1;
558
}
559
#endif  /* CONFIG_NFS_ACL */
560
504
/*
561
/*
505
 * XDR encode functions
562
 * XDR encode functions
506
 */
563
 */
Lines 830-835 Link Here
830
	return xdr_ressize_check(rqstp, p);
887
	return xdr_ressize_check(rqstp, p);
831
}
888
}
832
889
890
891
#ifdef CONFIG_NFSD_ACL
892
/* GETACL */
893
int
894
nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
895
					struct nfsd3_getaclres *resp)
896
{
897
	struct dentry *dentry = resp->fh.fh_dentry;
898
	struct svc_buf *buf = &rqstp->rq_resbuf;
899
	u32 *end = buf->base + buf->buflen;
900
901
	if (resp->status == 0 && dentry && dentry->d_inode) {
902
		struct inode *inode = dentry->d_inode;
903
904
		p = encode_post_op_attr(rqstp, p, &resp->fh);
905
		*p++ = htonl(resp->mask);
906
		if (!(p = nfs_acl_encode(p, end, inode, resp->acl_access,
907
				   resp->mask & NFS3_ACL, 0)))
908
			return 0;
909
		if (!(p = nfs_acl_encode(p, end, inode, resp->acl_default,
910
		    			 resp->mask & NFS3_DFACL,
911
					 NFS3_ACL_DEFAULT)))
912
			return 0;
913
	}
914
915
	return xdr_ressize_check(rqstp, p);
916
}
917
#endif  /* CONFIG_NFS_ACL */
918
919
/* SETACL */
920
int
921
nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p,
922
					struct nfsd3_attrstat *resp)
923
{
924
	if (resp->status == 0)
925
		p = encode_post_op_attr(rqstp, p, &resp->fh);
926
927
	return xdr_ressize_check(rqstp, p);
928
}
929
833
/*
930
/*
834
 * XDR release functions
931
 * XDR release functions
835
 */
932
 */
Lines 849-851 Link Here
849
	fh_put(&resp->fh2);
946
	fh_put(&resp->fh2);
850
	return 1;
947
	return 1;
851
}
948
}
949
950
#ifdef CONFIG_NFSD_ACL
951
int
952
nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p,
953
					struct nfsd3_getaclres *resp)
954
{
955
	fh_put(&resp->fh);
956
	posix_acl_release(resp->acl_access);
957
	posix_acl_release(resp->acl_default);
958
	return 1;
959
}
960
#endif  /* CONFIG_NFS_ACL */
(-)linux-2.4.22-ppc-dev.orig/fs/nfsd/nfsproc.c (+2 lines)
Lines 595-600 Link Here
595
#endif
595
#endif
596
		{ nfserr_stale, -ESTALE },
596
		{ nfserr_stale, -ESTALE },
597
		{ nfserr_dropit, -ENOMEM },
597
		{ nfserr_dropit, -ENOMEM },
598
		{ nfserr_notsupp, -EOPNOTSUPP },
599
		{ nfserr_notsupp, -ENOTSUPP },
598
		{ -1, -EIO }
600
		{ -1, -EIO }
599
	};
601
	};
600
	int	i;
602
	int	i;
(-)linux-2.4.22-ppc-dev.orig/fs/nfsd/nfssvc.c (-2 / +50 lines)
Lines 34-40 Link Here
34
#include <linux/lockd/bind.h>
34
#include <linux/lockd/bind.h>
35
35
36
#define NFSDDBG_FACILITY	NFSDDBG_SVC
36
#define NFSDDBG_FACILITY	NFSDDBG_SVC
37
#define NFSD_BUFSIZE		(1024 + NFSSVC_MAXBLKSIZE)
37
/* The nfs_acl RPCs may transmit two ACLs with 1024 entries each! */
38
#define NFSSVC_MAXACLSIZE	((28+2*3*1024)<<2)
39
#define NFSD_BUFSIZE	(1024 + (NFSSVC_MAXACLSIZE > NFSSVC_MAXBLKSIZE ? \
40
				 NFSSVC_MAXACLSIZE : NFSSVC_MAXBLKSIZE ))
38
41
39
/* these signals will be delivered to an nfsd thread 
42
/* these signals will be delivered to an nfsd thread 
40
 * when handling a request
43
 * when handling a request
Lines 155-160 Link Here
155
nfsd(struct svc_rqst *rqstp)
158
nfsd(struct svc_rqst *rqstp)
156
{
159
{
157
	struct svc_serv	*serv = rqstp->rq_server;
160
	struct svc_serv	*serv = rqstp->rq_server;
161
	struct fs_struct *fsp;
158
	int		err;
162
	int		err;
159
	struct nfsd_list me;
163
	struct nfsd_list me;
160
164
Lines 165-170 Link Here
165
	sprintf(current->comm, "nfsd");
169
	sprintf(current->comm, "nfsd");
166
	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
170
	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
167
171
172
	/* Make sure umask is 0.
173
	 * This is required by the new ACL code which does the umask
174
	 * munging below vfs_create() level.
175
	 */
176
	fsp = copy_fs_struct(current->fs);
177
	if (fsp == NULL) {
178
		printk("Unable to start nfsd thread: out of memory\n");
179
		goto out;
180
	}
181
	exit_fs(current);
182
	current->fs = fsp;
183
	fsp->umask = 0;
184
168
	nfsdstats.th_cnt++;
185
	nfsdstats.th_cnt++;
169
	/* Let svc_process check client's authentication. */
186
	/* Let svc_process check client's authentication. */
170
	rqstp->rq_auth = 1;
187
	rqstp->rq_auth = 1;
Lines 246-251 Link Here
246
	list_del(&me.list);
263
	list_del(&me.list);
247
	nfsdstats.th_cnt --;
264
	nfsdstats.th_cnt --;
248
265
266
out:
249
	/* Release the thread */
267
	/* Release the thread */
250
	svc_exit_thread(rqstp);
268
	svc_exit_thread(rqstp);
251
269
Lines 314-319 Link Here
314
	return 1;
332
	return 1;
315
}
333
}
316
334
335
#ifdef CONFIG_NFSD_ACL
336
static struct svc_version       nfsd_acl_version3 = {
337
	3, 3, nfsd_acl_procedures3, nfsd_dispatch
338
};
339
340
static struct svc_version *     nfsd_acl_version[] = {
341
	NULL,
342
	NULL,
343
	NULL,
344
	&nfsd_acl_version3,
345
};
346
347
struct svc_stat nfsd_acl_svcstats = { &nfsd_acl_program, };
348
349
# define NFSD_ACL_NRVERS (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
350
struct svc_program		nfsd_acl_program = {
351
	NULL,			/* last registered program */
352
	NFS3_ACL_PROGRAM,	/* program number */
353
	2, NFSD_ACL_NRVERS-1,	/* version range */
354
	NFSD_ACL_NRVERS,	/* nr of entries in nfsd_acl_version */
355
	nfsd_acl_version,	/* version table */
356
	"nfsd",			/* program name */
357
	&nfsd_acl_svcstats,	/* version table */
358
};
359
# define nfsd_acl_program_p &nfsd_acl_program
360
#else  /* CONFIG_NFS_ACL */
361
# define nfsd_acl_program_p NULL
362
#endif  /* CONFIG_NFS_ACL */
363
317
static struct svc_version	nfsd_version2 = {
364
static struct svc_version	nfsd_version2 = {
318
	2, 18, nfsd_procedures2, nfsd_dispatch
365
	2, 18, nfsd_procedures2, nfsd_dispatch
319
};
366
};
Lines 333-342 Link Here
333
380
334
#define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
381
#define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
335
struct svc_program		nfsd_program = {
382
struct svc_program		nfsd_program = {
383
	nfsd_acl_program_p,	/* next registered program */
336
	NFS_PROGRAM,		/* program number */
384
	NFS_PROGRAM,		/* program number */
337
	2, NFSD_NRVERS-1,	/* version range */
385
	2, NFSD_NRVERS-1,	/* version range */
338
	NFSD_NRVERS,		/* nr of entries in nfsd_version */
386
	NFSD_NRVERS,		/* nr of entries in nfsd_version */
339
	nfsd_version,		/* version table */
387
	nfsd_version,		/* version table */
340
	"nfsd",			/* program name */
388
	"nfsd",			/* program name */
341
	&nfsd_svcstats,		/* version table */
389
	&nfsd_svcstats,		/* rpc statistics */
342
};
390
};
(-)linux-2.4.22-ppc-dev.orig/fs/nfsd/nfsxdr.c (-1 / +11 lines)
Lines 135-144 Link Here
135
encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
135
encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
136
{
136
{
137
	struct inode *inode = fhp->fh_dentry->d_inode;
137
	struct inode *inode = fhp->fh_dentry->d_inode;
138
 	mode_t mode = inode->i_mode;
138
	int type = (inode->i_mode & S_IFMT);
139
	int type = (inode->i_mode & S_IFMT);
140
  
141
	if (IS_POSIXACL(inode) && !EX_ACL(fhp->fh_export)) {
142
		struct posix_acl *acl = nfsd_get_posix_acl(fhp,ACL_TYPE_ACCESS);
143
144
		if (!IS_ERR(acl) && acl) {
145
			posix_acl_masq_nfs_mode(acl, &mode);
146
			posix_acl_release(acl);
147
		}
148
	}
139
149
140
	*p++ = htonl(nfs_ftypes[type >> 12]);
150
	*p++ = htonl(nfs_ftypes[type >> 12]);
141
	*p++ = htonl((u32) inode->i_mode);
151
	*p++ = htonl((u32) mode);
142
	*p++ = htonl((u32) inode->i_nlink);
152
	*p++ = htonl((u32) inode->i_nlink);
143
	*p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
153
	*p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
144
	*p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
154
	*p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
(-)linux-2.4.22-ppc-dev.orig/fs/nfsd/vfs.c (+102 lines)
Lines 22-27 Link Here
22
#include <linux/errno.h>
22
#include <linux/errno.h>
23
#include <linux/locks.h>
23
#include <linux/locks.h>
24
#include <linux/fs.h>
24
#include <linux/fs.h>
25
#include <linux/xattr_acl.h>
25
#include <linux/major.h>
26
#include <linux/major.h>
26
#include <linux/ext2_fs.h>
27
#include <linux/ext2_fs.h>
27
#include <linux/proc_fs.h>
28
#include <linux/proc_fs.h>
Lines 1590-1592 Link Here
1590
	nfsdstats.ra_size = cache_size;
1591
	nfsdstats.ra_size = cache_size;
1591
	return 0;
1592
	return 0;
1592
}
1593
}
1594
1595
#ifdef CONFIG_FS_POSIX_ACL
1596
struct posix_acl *
1597
nfsd_get_posix_acl(struct svc_fh *fhp, int type)
1598
{
1599
	struct inode *inode = fhp->fh_dentry->d_inode;
1600
	char *name;
1601
	void *value = NULL;
1602
	ssize_t size;
1603
	struct posix_acl *acl;
1604
1605
	if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
1606
		return ERR_PTR(-EOPNOTSUPP);
1607
	switch(type) {
1608
		case ACL_TYPE_ACCESS:
1609
			name = XATTR_NAME_ACL_ACCESS;
1610
			break;
1611
		case ACL_TYPE_DEFAULT:
1612
			name = XATTR_NAME_ACL_DEFAULT;
1613
			break;
1614
		default:
1615
			return ERR_PTR(-EOPNOTSUPP);
1616
	}
1617
1618
	lock_kernel();  /* goes away in 2.5 */
1619
	size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
1620
	unlock_kernel();  /* goes away in 2.5 */
1621
1622
	if (size < 0) {
1623
		acl = ERR_PTR(size);
1624
		goto getout;
1625
	} else if (size > 0) {
1626
		value = kmalloc(size, GFP_KERNEL);
1627
		if (!value) {
1628
			acl = ERR_PTR(-ENOMEM);
1629
			goto getout;
1630
		}
1631
		size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
1632
		if (size < 0) {
1633
			acl = ERR_PTR(size);
1634
			goto getout;
1635
		}
1636
	}
1637
	acl = posix_acl_from_xattr(value, size);
1638
1639
getout:
1640
	kfree(value);
1641
	return acl;
1642
}
1643
1644
int
1645
nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1646
{
1647
	struct inode *inode = fhp->fh_dentry->d_inode;
1648
	char *name;
1649
	void *value = NULL;
1650
	size_t size;
1651
	int error;
1652
1653
	if (!IS_POSIXACL(inode) || !inode->i_op ||
1654
	    !inode->i_op->setxattr || !inode->i_op->removexattr)
1655
		return -EOPNOTSUPP;
1656
	switch(type) {
1657
		case ACL_TYPE_ACCESS:
1658
			name = XATTR_NAME_ACL_ACCESS;
1659
			break;
1660
		case ACL_TYPE_DEFAULT:
1661
			name = XATTR_NAME_ACL_DEFAULT;
1662
			break;
1663
		default:
1664
			return -EOPNOTSUPP;
1665
	}
1666
1667
	if (acl && acl->a_count) {
1668
		size = xattr_acl_size(acl->a_count);
1669
		value = kmalloc(size, GFP_KERNEL);
1670
		if (!value)
1671
			return -ENOMEM;
1672
		size = posix_acl_to_xattr(acl, value, size);
1673
		if (size < 0) {
1674
			error = size;
1675
			goto getout;
1676
		}
1677
	} else
1678
		size = 0;
1679
1680
	if (!fhp->fh_locked)
1681
		fh_lock(fhp);  /* unlocking is done automatically */
1682
	lock_kernel();  /* goes away in 2.5 */
1683
	if (size)
1684
		error = inode->i_op->setxattr(fhp->fh_dentry, name,
1685
					      value, size, 0);
1686
	else
1687
		error = inode->i_op->removexattr(fhp->fh_dentry, name);
1688
	unlock_kernel();  /* goes away in 2.5 */
1689
1690
getout:
1691
	kfree(value);
1692
	return error;
1693
}
1694
#endif
(-)linux-2.4.22-ppc-dev.orig/fs/posix_acl.c (+430 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/posix_acl.c
3
 *
4
 *  Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org>
5
 *
6
 *  Fixes from William Schumacher incorporated on 15 March 2001.
7
 *     (Reported by Charles Bertsch, <CBertsch@microtest.com>).
8
 */
9
10
/*
11
 *  This file contains generic functions for manipulating
12
 *  POSIX 1003.1e draft standard 17 ACLs.
13
 */
14
15
#include <linux/version.h>
16
#include <linux/kernel.h>
17
#include <linux/slab.h>
18
#include <asm/atomic.h>
19
#include <linux/fs.h>
20
#include <linux/posix_acl.h>
21
#include <linux/module.h>
22
23
#include <linux/smp_lock.h>
24
#include <linux/errno.h>
25
26
MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
27
MODULE_DESCRIPTION("Generic Posix Access Control List (ACL) Manipulation");
28
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
29
MODULE_LICENSE("GPL");
30
#endif
31
32
EXPORT_SYMBOL(posix_acl_alloc);
33
EXPORT_SYMBOL(posix_acl_clone);
34
EXPORT_SYMBOL(posix_acl_valid);
35
EXPORT_SYMBOL(posix_acl_equiv_mode);
36
EXPORT_SYMBOL(posix_acl_from_mode);
37
EXPORT_SYMBOL(posix_acl_create_masq);
38
EXPORT_SYMBOL(posix_acl_chmod_masq);
39
EXPORT_SYMBOL(posix_acl_masq_nfs_mode);
40
EXPORT_SYMBOL(posix_acl_permission);
41
42
/*
43
 * Allocate a new ACL with the specified number of entries.
44
 */
45
struct posix_acl *
46
posix_acl_alloc(int count, int flags)
47
{
48
	const size_t size = sizeof(struct posix_acl) +
49
	                    count * sizeof(struct posix_acl_entry);
50
	struct posix_acl *acl = kmalloc(size, flags);
51
	if (acl) {
52
		atomic_set(&acl->a_refcount, 1);
53
		acl->a_count = count;
54
	}
55
	return acl;
56
}
57
58
/*
59
 * Clone an ACL.
60
 */
61
struct posix_acl *
62
posix_acl_clone(const struct posix_acl *acl, int flags)
63
{
64
	struct posix_acl *clone = NULL;
65
66
	if (acl) {
67
		int size = sizeof(struct posix_acl) + acl->a_count *
68
		           sizeof(struct posix_acl_entry);
69
		clone = kmalloc(size, flags);
70
		if (clone) {
71
			memcpy(clone, acl, size);
72
			atomic_set(&clone->a_refcount, 1);
73
		}
74
	}
75
	return clone;
76
}
77
78
/*
79
 * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
80
 */
81
int
82
posix_acl_valid(const struct posix_acl *acl)
83
{
84
	const struct posix_acl_entry *pa, *pe;
85
	int state = ACL_USER_OBJ;
86
	unsigned int id = 0;  /* keep gcc happy */
87
	int needs_mask = 0;
88
89
	FOREACH_ACL_ENTRY(pa, acl, pe) {
90
		if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
91
			return -EINVAL;
92
		switch (pa->e_tag) {
93
			case ACL_USER_OBJ:
94
				if (state == ACL_USER_OBJ) {
95
					id = 0;
96
					state = ACL_USER;
97
					break;
98
				}
99
				return -EINVAL;
100
101
			case ACL_USER:
102
				if (state != ACL_USER)
103
					return -EINVAL;
104
				if (pa->e_id == ACL_UNDEFINED_ID ||
105
				    pa->e_id < id)
106
					return -EINVAL;
107
				id = pa->e_id + 1;
108
				needs_mask = 1;
109
				break;
110
111
			case ACL_GROUP_OBJ:
112
				if (state == ACL_USER) {
113
					id = 0;
114
					state = ACL_GROUP;
115
					break;
116
				}
117
				return -EINVAL;
118
119
			case ACL_GROUP:
120
				if (state != ACL_GROUP)
121
					return -EINVAL;
122
				if (pa->e_id == ACL_UNDEFINED_ID ||
123
				    pa->e_id < id)
124
					return -EINVAL;
125
				id = pa->e_id + 1;
126
				needs_mask = 1;
127
				break;
128
129
			case ACL_MASK:
130
				if (state != ACL_GROUP)
131
					return -EINVAL;
132
				state = ACL_OTHER;
133
				break;
134
135
			case ACL_OTHER:
136
				if (state == ACL_OTHER ||
137
				    (state == ACL_GROUP && !needs_mask)) {
138
					state = 0;
139
					break;
140
				}
141
				return -EINVAL;
142
143
			default:
144
				return -EINVAL;
145
		}
146
	}
147
	if (state == 0)
148
		return 0;
149
	return -EINVAL;
150
}
151
152
/*
153
 * Returns 0 if the acl can be exactly represented in the traditional
154
 * file mode permission bits, or else 1. Returns -E... on error.
155
 */
156
int
157
posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
158
{
159
	const struct posix_acl_entry *pa, *pe;
160
	mode_t mode = 0;
161
	int not_equiv = 0;
162
163
	FOREACH_ACL_ENTRY(pa, acl, pe) {
164
		switch (pa->e_tag) {
165
			case ACL_USER_OBJ:
166
				mode |= (pa->e_perm & S_IRWXO) << 6;
167
				break;
168
			case ACL_GROUP_OBJ:
169
				mode |= (pa->e_perm & S_IRWXO) << 3;
170
				break;
171
			case ACL_OTHER:
172
				mode |= pa->e_perm & S_IRWXO;
173
				break;
174
			case ACL_MASK:
175
				mode = (mode & ~S_IRWXG) |
176
				       ((pa->e_perm & S_IRWXO) << 3);
177
				not_equiv = 1;
178
				break;
179
			case ACL_USER:
180
			case ACL_GROUP:
181
				not_equiv = 1;
182
				break;
183
			default:
184
				return -EINVAL;
185
		}
186
	}
187
        if (mode_p)
188
                *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
189
        return not_equiv;
190
}
191
192
/*
193
 * Create an ACL representing the file mode permission bits of an inode.
194
 */
195
struct posix_acl *
196
posix_acl_from_mode(mode_t mode, int flags)
197
{
198
	struct posix_acl *acl = posix_acl_alloc(3, flags);
199
	if (!acl)
200
		return ERR_PTR(-ENOMEM);
201
202
	acl->a_entries[0].e_tag  = ACL_USER_OBJ;
203
	acl->a_entries[0].e_id   = ACL_UNDEFINED_ID;
204
	acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
205
206
	acl->a_entries[1].e_tag  = ACL_GROUP_OBJ;
207
	acl->a_entries[1].e_id   = ACL_UNDEFINED_ID;
208
	acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
209
210
	acl->a_entries[2].e_tag  = ACL_OTHER;
211
	acl->a_entries[2].e_id   = ACL_UNDEFINED_ID;
212
	acl->a_entries[2].e_perm = (mode & S_IRWXO);
213
	return acl;
214
}
215
216
/*
217
 * Return 0 if current is granted want access to the inode
218
 * by the acl. Returns -E... otherwise.
219
 */
220
int
221
posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
222
{
223
	const struct posix_acl_entry *pa, *pe, *mask_obj;
224
	int found = 0;
225
226
	FOREACH_ACL_ENTRY(pa, acl, pe) {
227
                switch(pa->e_tag) {
228
                        case ACL_USER_OBJ:
229
				/* (May have been checked already) */
230
                                if (inode->i_uid == current->fsuid)
231
                                        goto check_perm;
232
                                break;
233
                        case ACL_USER:
234
                                if (pa->e_id == current->fsuid)
235
                                        goto mask;
236
				break;
237
                        case ACL_GROUP_OBJ:
238
                                if (in_group_p(inode->i_gid)) {
239
					found = 1;
240
					if ((pa->e_perm & want) == want)
241
						goto mask;
242
                                }
243
				break;
244
                        case ACL_GROUP:
245
                                if (in_group_p(pa->e_id)) {
246
					found = 1;
247
					if ((pa->e_perm & want) == want)
248
						goto mask;
249
                                }
250
                                break;
251
                        case ACL_MASK:
252
                                break;
253
                        case ACL_OTHER:
254
				if (found)
255
					return -EACCES;
256
				else
257
					goto check_perm;
258
			default:
259
				return -EIO;
260
                }
261
        }
262
	return -EIO;
263
264
mask:
265
	for (mask_obj = pa+1; mask_obj != pe; mask_obj++) {
266
		if (mask_obj->e_tag == ACL_MASK) {
267
			if ((pa->e_perm & mask_obj->e_perm & want) == want)
268
				return 0;
269
			return -EACCES;
270
		}
271
	}
272
273
check_perm:
274
	if ((pa->e_perm & want) == want)
275
		return 0;
276
	return -EACCES;
277
}
278
279
/*
280
 * Modify acl when creating a new inode. The caller must ensure the acl is
281
 * only referenced once.
282
 *
283
 * mode_p initially must contain the mode parameter to the open() / creat()
284
 * system calls. All permissions that are not granted by the acl are removed.
285
 * The permissions in the acl are changed to reflect the mode_p parameter.
286
 */
287
int
288
posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
289
{
290
	struct posix_acl_entry *pa, *pe;
291
	struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
292
	mode_t mode = *mode_p;
293
	int not_equiv = 0;
294
295
	/* assert(atomic_read(acl->a_refcount) == 1); */
296
297
	FOREACH_ACL_ENTRY(pa, acl, pe) {
298
                switch(pa->e_tag) {
299
                        case ACL_USER_OBJ:
300
				pa->e_perm &= (mode >> 6) | ~S_IRWXO;
301
				mode &= (pa->e_perm << 6) | ~S_IRWXU;
302
				break;
303
304
			case ACL_USER:
305
			case ACL_GROUP:
306
				not_equiv = 1;
307
				break;
308
309
                        case ACL_GROUP_OBJ:
310
				group_obj = pa;
311
                                break;
312
313
                        case ACL_OTHER:
314
				pa->e_perm &= mode | ~S_IRWXO;
315
				mode &= pa->e_perm | ~S_IRWXO;
316
                                break;
317
318
                        case ACL_MASK:
319
				mask_obj = pa;
320
				not_equiv = 1;
321
                                break;
322
323
			default:
324
				return -EIO;
325
                }
326
        }
327
328
	if (mask_obj) {
329
		mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
330
		mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
331
	} else {
332
		if (!group_obj)
333
			return -EIO;
334
		group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
335
		mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
336
	}
337
338
	*mode_p = (*mode_p & ~S_IRWXUGO) | mode;
339
        return not_equiv;
340
}
341
342
/*
343
 * Modify the ACL for the chmod syscall.
344
 */
345
int
346
posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
347
{
348
	struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
349
	struct posix_acl_entry *pa, *pe;
350
351
	/* assert(atomic_read(acl->a_refcount) == 1); */
352
353
	FOREACH_ACL_ENTRY(pa, acl, pe) {
354
		switch(pa->e_tag) {
355
			case ACL_USER_OBJ:
356
				pa->e_perm = (mode & S_IRWXU) >> 6;
357
				break;
358
359
			case ACL_USER:
360
			case ACL_GROUP:
361
				break;
362
363
			case ACL_GROUP_OBJ:
364
				group_obj = pa;
365
				break;
366
367
			case ACL_MASK:
368
				mask_obj = pa;
369
				break;
370
371
			case ACL_OTHER:
372
				pa->e_perm = (mode & S_IRWXO);
373
				break;
374
375
			default:
376
				return -EIO;
377
		}
378
	}
379
380
	if (mask_obj) {
381
		mask_obj->e_perm = (mode & S_IRWXG) >> 3;
382
	} else {
383
		if (!group_obj)
384
			return -EIO;
385
		group_obj->e_perm = (mode & S_IRWXG) >> 3;
386
	}
387
388
	return 0;
389
}
390
391
/*
392
 * Adjust the mode parameter so that NFSv2 grants nobody permissions
393
 * that may not be granted by the ACL. This is necessary because NFSv2
394
 * may compute access permissions on the client side, and may serve cached
395
 * data whenever it assumes access would be granted.  Since ACLs may also
396
 * be used to deny access to specific users, the minimal permissions
397
 * for secure operation over NFSv2 are very restrictive. Permissions
398
 * granted to users via Access Control Lists will not be effective over
399
 * NFSv2.
400
 *
401
 * Privilege escalation can only happen for read operations, as writes are
402
 * always carried out on the NFS server, where the proper access checks are
403
 * implemented.
404
 */
405
int
406
posix_acl_masq_nfs_mode(struct posix_acl *acl, mode_t *mode_p)
407
{
408
	struct posix_acl_entry *pa, *pe; int min_perm = S_IRWXO;
409
410
	FOREACH_ACL_ENTRY(pa, acl, pe) {
411
                switch(pa->e_tag) {
412
			case ACL_USER_OBJ:
413
				break;
414
415
			case ACL_USER:
416
			case ACL_GROUP_OBJ:
417
			case ACL_GROUP:
418
			case ACL_MASK:
419
			case ACL_OTHER:
420
				min_perm &= pa->e_perm;
421
				break;
422
423
			default:
424
				return -EIO;
425
		}
426
	}
427
	*mode_p = (*mode_p & ~(S_IRWXG|S_IRWXO)) | (min_perm << 3) | min_perm;
428
429
	return 0;
430
}
(-)linux-2.4.22-ppc-dev.orig/fs/solaris_acl.c (+198 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/solaris_acl.c
3
 *
4
 *  Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org>
5
 */
6
7
/*
8
 * The Solaris nfs_acl protocol represents some ACLs slightly differently
9
 * than POSIX 1003.1e draft 17 does (and we do):
10
 *
11
 *  - Minimal ACLs always have an ACL_MASK entry, so they have
12
 *    four instead of three entries.
13
 *  - The ACL_MASK entry in such minimal ACLs always has the same
14
 *    permissions as the ACL_GROUP_OBJ entry. (In extended ACLs
15
 *    the ACL_MASK and ACL_GROUP_OBJ entries may differ.)
16
 *  - The identifier fields of the ACL_USER_OBJ and ACL_GROUP_OBJ
17
 *    entries contain the identifiers of the owner and owning group.
18
 *    (In POSIX ACLs we always set them to ACL_UNDEFINED_ID).
19
 *  - ACL entries in the kernel are kept sorted in ascending order
20
 *    of (e_tag, e_id). Solaris ACLs are unsorted.
21
 */
22
23
#include <linux/module.h>
24
#include <linux/solaris_acl.h>
25
#include <linux/nfs3.h>
26
27
EXPORT_SYMBOL(nfs_acl_encode);
28
EXPORT_SYMBOL(nfs_acl_decode);
29
30
u32 *
31
nfs_acl_encode(u32 *p, u32 *end, struct inode *inode, struct posix_acl *acl,
32
	       int encode_entries, int typeflag)
33
{
34
	int entries = acl ? acl->a_count : 0;
35
	
36
	if (entries == 3)
37
		entries++;  /* need to fake up ACL_MASK entry */
38
	if (entries > NFS3_ACL_MAX_ENTRIES ||
39
	    p + 2 + (encode_entries ? (3 * entries) : 0) > end)
40
		return NULL;
41
	*p++ = htonl(entries);
42
	if (acl && encode_entries) {
43
		struct posix_acl_entry *pa, *pe;
44
		int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE;
45
46
		*p++ = htonl(entries);
47
		FOREACH_ACL_ENTRY(pa, acl, pe) {
48
			*p++ = htonl(pa->e_tag | typeflag);
49
			switch(pa->e_tag) {
50
				case ACL_USER_OBJ:
51
					*p++ = htonl(inode->i_uid);
52
					break;
53
				case ACL_GROUP_OBJ:
54
					*p++ = htonl(inode->i_gid);
55
					group_obj_perm = pa->e_perm;
56
					break;
57
				default:
58
					*p++ = htonl(pa->e_id);
59
					break;
60
			}
61
			*p++ = htonl(pa->e_perm & S_IRWXO);
62
		}
63
		if (acl->a_count < entries) {
64
			/* fake up ACL_MASK entry */
65
			*p++ = htonl(ACL_MASK | typeflag);
66
			*p++ = htonl(ACL_UNDEFINED_ID);
67
			*p++ = htonl(group_obj_perm & S_IRWXO);
68
		}
69
	} else
70
		*p++ = 0;
71
72
	return p;
73
}
74
75
static int
76
cmp_acl_entry(const struct posix_acl_entry *a, const struct posix_acl_entry *b)
77
{
78
	if (a->e_tag != b->e_tag)
79
		return a->e_tag - b->e_tag;
80
	else if (a->e_id > b->e_id)
81
		return 1;
82
	else if (a->e_id < b->e_id)
83
		return -1;
84
	else
85
		return 0;
86
}
87
88
/*
89
 * Convert from a Solaris ACL to a POSIX 1003.1e draft 17 ACL.
90
 */
91
static int
92
posix_acl_from_solaris(struct posix_acl *acl)
93
{
94
	struct posix_acl_entry *pa, *pe,
95
	       *group_obj = NULL, *mask = NULL;
96
97
	if (!acl)
98
		return 0;
99
100
	qsort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry),
101
	      (int(*)(const void *,const void *))cmp_acl_entry);
102
103
	/* Clear undefined identifier fields and find the ACL_GROUP_OBJ
104
	   and ACL_MASK entries. */
105
	FOREACH_ACL_ENTRY(pa, acl, pe) {
106
		switch(pa->e_tag) {
107
			case ACL_USER_OBJ:
108
				pa->e_id = ACL_UNDEFINED_ID;
109
				break;
110
			case ACL_GROUP_OBJ:
111
				pa->e_id = ACL_UNDEFINED_ID;
112
				group_obj = pa;
113
				break;
114
			case ACL_MASK:
115
				mask = pa;
116
				/* fall through */
117
			case ACL_OTHER:
118
				pa->e_id = ACL_UNDEFINED_ID;
119
				break;
120
		}
121
	}
122
	if (acl->a_count == 4 && group_obj && mask &&
123
	    mask->e_perm == group_obj->e_perm) {
124
		/* remove bogus ACL_MASK entry */
125
		memmove(mask, mask+1, (acl->a_entries + 4 - mask) *
126
				      sizeof(struct posix_acl_entry));
127
		acl->a_count = 3;
128
	}
129
	return 0;
130
}
131
132
static u32 *
133
nfs_acl_decode_entry(u32 *p, struct posix_acl_entry *entry)
134
{
135
	entry->e_tag = ntohl(*p++) & ~NFS3_ACL_DEFAULT;
136
	entry->e_id = ntohl(*p++);
137
	entry->e_perm = ntohl(*p++);
138
139
	switch(entry->e_tag) {
140
		case ACL_USER_OBJ:
141
		case ACL_USER:
142
		case ACL_GROUP_OBJ:
143
		case ACL_GROUP:
144
		case ACL_OTHER:
145
			if (entry->e_perm & ~S_IRWXO)
146
				return NULL;
147
			break;
148
		case ACL_MASK:
149
			/* Solaris sometimes sets additonal bits in the mask */
150
			entry->e_perm &= S_IRWXO;
151
			break;
152
		default:
153
			return NULL;
154
	}
155
	return p;
156
}
157
158
u32 *
159
nfs_acl_decode(u32 *p, u32 *end, unsigned int *aclcnt, struct posix_acl **pacl)
160
{
161
	struct posix_acl_entry *pa, *pe;
162
	unsigned int entries, array_len;
163
164
	if (p + 2 > end)
165
		return NULL;
166
	entries = ntohl(*p++);
167
	array_len = ntohl(*p++);
168
	if (entries > NFS3_ACL_MAX_ENTRIES || (pacl && entries != array_len))
169
		return NULL;
170
	if (p + 3 * array_len > end)
171
		return NULL;
172
	if (pacl) {
173
		*pacl = NULL;
174
		if (entries) {
175
			struct posix_acl *acl;
176
			
177
			if (!(acl = posix_acl_alloc(array_len, GFP_KERNEL)))
178
				return NULL;
179
			FOREACH_ACL_ENTRY(pa, acl, pe) {
180
				if (!(p = nfs_acl_decode_entry(p, pa))) {
181
					posix_acl_release(acl);
182
					return NULL;
183
				}
184
			}
185
			if (posix_acl_from_solaris(acl) != 0) {
186
				posix_acl_release(acl);
187
				return NULL;
188
			}
189
			*pacl = acl;
190
		}
191
	} else 
192
		p += 3 * array_len;
193
194
	if (aclcnt)
195
		*aclcnt = entries;
196
	return p;
197
}
198
(-)linux-2.4.22-ppc-dev.orig/fs/super.c (-3 / +9 lines)
Lines 89-95 Link Here
89
 *	unregistered.
89
 *	unregistered.
90
 */
90
 */
91
 
91
 
92
int register_filesystem(struct file_system_type * fs)
92
int __register_filesystem(struct file_system_type * fs, int lifo)
93
{
93
{
94
	int res = 0;
94
	int res = 0;
95
	struct file_system_type ** p;
95
	struct file_system_type ** p;
Lines 103-110 Link Here
103
	p = find_filesystem(fs->name);
103
	p = find_filesystem(fs->name);
104
	if (*p)
104
	if (*p)
105
		res = -EBUSY;
105
		res = -EBUSY;
106
	else
106
	else {
107
		*p = fs;
107
		if (!lifo)
108
			*p = fs;
109
		else {
110
			fs->next = file_systems;
111
			file_systems = fs;
112
		}
113
	}
108
	write_unlock(&file_systems_lock);
114
	write_unlock(&file_systems_lock);
109
	return res;
115
	return res;
110
}
116
}
(-)linux-2.4.22-ppc-dev.orig/fs/xattr.c (-4 lines)
Lines 159-169 Link Here
159
159
160
	error = -EOPNOTSUPP;
160
	error = -EOPNOTSUPP;
161
	if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
161
	if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
162
		down(&d->d_inode->i_sem);
163
		lock_kernel();
162
		lock_kernel();
164
		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
163
		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
165
		unlock_kernel();
164
		unlock_kernel();
166
		up(&d->d_inode->i_sem);
167
	}
165
	}
168
166
169
	if (kvalue && error > 0)
167
	if (kvalue && error > 0)
Lines 230-240 Link Here
230
228
231
	error = -EOPNOTSUPP;
229
	error = -EOPNOTSUPP;
232
	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
230
	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
233
		down(&d->d_inode->i_sem);
234
		lock_kernel();
231
		lock_kernel();
235
		error = d->d_inode->i_op->listxattr(d, klist, size);
232
		error = d->d_inode->i_op->listxattr(d, klist, size);
236
		unlock_kernel();
233
		unlock_kernel();
237
		up(&d->d_inode->i_sem);
238
	}
234
	}
239
235
240
	if (klist && error > 0)
236
	if (klist && error > 0)
(-)linux-2.4.22-ppc-dev.orig/fs/xattr_acl.c (+99 lines)
Line 0 Link Here
1
/*
2
 * linux/fs/xattr_acl.c
3
 *
4
 * Almost all from linux/fs/ext2/acl.c:
5
 * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
6
 */
7
8
#include <linux/module.h>
9
#include <linux/sched.h>
10
#include <linux/slab.h>
11
#include <linux/fs.h>
12
#include <linux/xattr_acl.h>
13
14
15
/*
16
 * Convert from extended attribute to in-memory representation.
17
 */
18
struct posix_acl *
19
posix_acl_from_xattr(const void *value, size_t size)
20
{
21
	xattr_acl_header *header = (xattr_acl_header *)value;
22
	xattr_acl_entry *entry = (xattr_acl_entry *)(header+1), *end;
23
	int count;
24
	struct posix_acl *acl;
25
	struct posix_acl_entry *acl_e;
26
27
	if (!value)
28
		return NULL;
29
	if (size < sizeof(xattr_acl_header))
30
		 return ERR_PTR(-EINVAL);
31
	if (header->a_version != cpu_to_le32(XATTR_ACL_VERSION))
32
		return ERR_PTR(-EINVAL);
33
34
	count = xattr_acl_count(size);
35
	if (count < 0)
36
		return ERR_PTR(-EINVAL);
37
	if (count == 0)
38
		return NULL;
39
	
40
	acl = posix_acl_alloc(count, GFP_KERNEL);
41
	if (!acl)
42
		return ERR_PTR(-ENOMEM);
43
	acl_e = acl->a_entries;
44
	
45
	for (end = entry + count; entry != end; acl_e++, entry++) {
46
		acl_e->e_tag  = le16_to_cpu(entry->e_tag);
47
		acl_e->e_perm = le16_to_cpu(entry->e_perm);
48
49
		switch(acl_e->e_tag) {
50
			case ACL_USER_OBJ:
51
			case ACL_GROUP_OBJ:
52
			case ACL_MASK:
53
			case ACL_OTHER:
54
				acl_e->e_id = ACL_UNDEFINED_ID;
55
				break;
56
57
			case ACL_USER:
58
			case ACL_GROUP:
59
				acl_e->e_id = le32_to_cpu(entry->e_id);
60
				break;
61
62
			default:
63
				goto fail;
64
		}
65
	}
66
	return acl;
67
68
fail:
69
	posix_acl_release(acl);
70
	return ERR_PTR(-EINVAL);
71
}
72
EXPORT_SYMBOL (posix_acl_from_xattr);
73
74
/*
75
 * Convert from in-memory to extended attribute representation.
76
 */
77
int
78
posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size)
79
{
80
	xattr_acl_header *ext_acl = (xattr_acl_header *)buffer;
81
	xattr_acl_entry *ext_entry = ext_acl->a_entries;
82
	int real_size, n;
83
84
	real_size = xattr_acl_size(acl->a_count);
85
	if (!buffer)
86
		return real_size;
87
	if (real_size > size)
88
		return -ERANGE;
89
	
90
	ext_acl->a_version = cpu_to_le32(XATTR_ACL_VERSION);
91
92
	for (n=0; n < acl->a_count; n++, ext_entry++) {
93
		ext_entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
94
		ext_entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
95
		ext_entry->e_id   = cpu_to_le32(acl->a_entries[n].e_id);
96
	}
97
	return real_size;
98
}
99
EXPORT_SYMBOL (posix_acl_to_xattr);
(-)linux-2.4.22-ppc-dev.orig/include/asm-arm/unistd.h (-2 lines)
Lines 250-256 Link Here
250
#define __NR_security			(__NR_SYSCALL_BASE+223)
250
#define __NR_security			(__NR_SYSCALL_BASE+223)
251
#define __NR_gettid			(__NR_SYSCALL_BASE+224)
251
#define __NR_gettid			(__NR_SYSCALL_BASE+224)
252
#define __NR_readahead			(__NR_SYSCALL_BASE+225)
252
#define __NR_readahead			(__NR_SYSCALL_BASE+225)
253
#if 0 /* allocated in 2.5 */
254
#define __NR_setxattr			(__NR_SYSCALL_BASE+226)
253
#define __NR_setxattr			(__NR_SYSCALL_BASE+226)
255
#define __NR_lsetxattr			(__NR_SYSCALL_BASE+227)
254
#define __NR_lsetxattr			(__NR_SYSCALL_BASE+227)
256
#define __NR_fsetxattr			(__NR_SYSCALL_BASE+228)
255
#define __NR_fsetxattr			(__NR_SYSCALL_BASE+228)
Lines 263-269 Link Here
263
#define __NR_removexattr		(__NR_SYSCALL_BASE+235)
262
#define __NR_removexattr		(__NR_SYSCALL_BASE+235)
264
#define __NR_lremovexattr		(__NR_SYSCALL_BASE+236)
263
#define __NR_lremovexattr		(__NR_SYSCALL_BASE+236)
265
#define __NR_fremovexattr		(__NR_SYSCALL_BASE+237)
264
#define __NR_fremovexattr		(__NR_SYSCALL_BASE+237)
266
#endif
267
#define __NR_tkill			(__NR_SYSCALL_BASE+238)
265
#define __NR_tkill			(__NR_SYSCALL_BASE+238)
268
#if 0 /* allocated in 2.5 */
266
#if 0 /* allocated in 2.5 */
269
#define __NR_sendfile64                 (__NR_SYSCALL_BASE+239)
267
#define __NR_sendfile64                 (__NR_SYSCALL_BASE+239)
(-)linux-2.4.22-ppc-dev.orig/include/asm-s390/unistd.h (-3 / +13 lines)
Lines 213-221 Link Here
213
#define __NR_getdents64		220
213
#define __NR_getdents64		220
214
#define __NR_fcntl64		221
214
#define __NR_fcntl64		221
215
#define __NR_readahead		222
215
#define __NR_readahead		222
216
/*
216
217
 * Numbers 224-235 are reserved for posix acl
217
#define __NR_setxattr		224
218
 */
218
#define __NR_lsetxattr		225
219
#define __NR_fsetxattr		226
220
#define __NR_getxattr		227
221
#define __NR_lgetxattr		228
222
#define __NR_fgetxattr		229
223
#define __NR_listxattr		230
224
#define __NR_llistxattr		231
225
#define __NR_flistxattr		232
226
#define __NR_removexattr	233
227
#define __NR_lremovexattr	234
228
#define __NR_fremovexattr	235
219
#define __NR_gettid		236
229
#define __NR_gettid		236
220
#define __NR_tkill		237
230
#define __NR_tkill		237
221
231
(-)linux-2.4.22-ppc-dev.orig/include/asm-s390x/unistd.h (-3 / +13 lines)
Lines 181-189 Link Here
181
#define __NR_mincore            218
181
#define __NR_mincore            218
182
#define __NR_madvise            219
182
#define __NR_madvise            219
183
#define __NR_readahead		222
183
#define __NR_readahead		222
184
/*
184
185
 * Numbers 224-235 are reserved for posix acl
185
#define __NR_setxattr		224
186
 */
186
#define __NR_lsetxattr		225
187
#define __NR_fsetxattr		226
188
#define __NR_getxattr		227
189
#define __NR_lgetxattr		228
190
#define __NR_fgetxattr		229
191
#define __NR_listxattr		230
192
#define __NR_llistxattr		231
193
#define __NR_flistxattr		232
194
#define __NR_removexattr	233
195
#define __NR_lremovexattr	234
196
#define __NR_fremovexattr	235
187
#define __NR_gettid		236
197
#define __NR_gettid		236
188
#define __NR_tkill		237
198
#define __NR_tkill		237
189
199
(-)linux-2.4.22-ppc-dev.orig/include/asm-sparc/unistd.h (-1 / +1 lines)
Lines 1-4 Link Here
1
/* $Id: unistd.h,v 1.72 2001/10/18 08:27:05 davem Exp $ */
1
/* $Id: unistd.h,v 1.74 2002/02/08 03:57:18 davem Exp $ */
2
#ifndef _SPARC_UNISTD_H
2
#ifndef _SPARC_UNISTD_H
3
#define _SPARC_UNISTD_H
3
#define _SPARC_UNISTD_H
4
4
(-)linux-2.4.22-ppc-dev.orig/include/linux/cache_def.h (+15 lines)
Line 0 Link Here
1
/*
2
 * linux/cache_def.h
3
 * Handling of caches defined in drivers, filesystems, ...
4
 *
5
 * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
6
 */
7
8
struct cache_definition {
9
	const char *name;
10
	void (*shrink)(int, unsigned int);
11
	struct list_head link;
12
};
13
14
extern void register_cache(struct cache_definition *);
15
extern void unregister_cache(struct cache_definition *);
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext2_acl.h (+101 lines)
Line 0 Link Here
1
/*
2
  File: linux/ext2_acl.h
3
4
  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5
*/
6
7
#include <linux/init.h>
8
#include <linux/posix_acl.h>
9
#include <linux/xattr_acl.h>
10
11
#define EXT2_ACL_VERSION	0x0001
12
#define EXT2_ACL_MAX_ENTRIES	32
13
14
typedef struct {
15
	__u16		e_tag;
16
	__u16		e_perm;
17
	__u32		e_id;
18
} ext2_acl_entry;
19
20
typedef struct {
21
	__u16		e_tag;
22
	__u16		e_perm;
23
} ext2_acl_entry_short;
24
25
typedef struct {
26
	__u32		a_version;
27
} ext2_acl_header;
28
29
static inline size_t ext2_acl_size(int count)
30
{
31
	if (count <= 4) {
32
		return sizeof(ext2_acl_header) +
33
		       count * sizeof(ext2_acl_entry_short);
34
	} else {
35
		return sizeof(ext2_acl_header) +
36
		       4 * sizeof(ext2_acl_entry_short) +
37
		       (count - 4) * sizeof(ext2_acl_entry);
38
	}
39
}
40
41
static inline int ext2_acl_count(size_t size)
42
{
43
	ssize_t s;
44
	size -= sizeof(ext2_acl_header);
45
	s = size - 4 * sizeof(ext2_acl_entry_short);
46
	if (s < 0) {
47
		if (size % sizeof(ext2_acl_entry_short))
48
			return -1;
49
		return size / sizeof(ext2_acl_entry_short);
50
	} else {
51
		if (s % sizeof(ext2_acl_entry))
52
			return -1;
53
		return s / sizeof(ext2_acl_entry) + 4;
54
	}
55
}
56
57
#ifdef __KERNEL__
58
# ifdef CONFIG_EXT2_FS_POSIX_ACL
59
60
/* Value for inode->u.ext2_i.i_acl and inode->u.ext2_i.i_default_acl
61
   if the ACL has not been cached */
62
# define EXT2_ACL_NOT_CACHED ((void *)-1)
63
64
/* acl.c */
65
extern int ext2_permission (struct inode *, int);
66
extern int ext2_acl_chmod (struct inode *);
67
extern int ext2_init_acl (struct inode *, struct inode *);
68
69
extern int init_ext2_acl(void) __init;
70
extern void exit_ext2_acl(void);
71
72
# else
73
#  include <linux/sched.h>
74
#  define ext2_permission NULL
75
76
static inline int
77
ext2_acl_chmod (struct inode *inode)
78
{
79
	return 0;
80
}
81
82
static inline int ext2_init_acl (struct inode *inode, struct inode *dir)
83
{
84
	inode->i_mode &= ~current->fs->umask;
85
	mark_inode_dirty(inode);
86
	return 0;
87
}
88
89
static inline int
90
init_ext2_acl(void)
91
{
92
	return 0;
93
}
94
95
static inline void
96
exit_ext2_acl(void)
97
{
98
}
99
100
# endif
101
#endif
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext2_fs.h (-27 / +7 lines)
Lines 57-64 Link Here
57
 */
57
 */
58
#define	EXT2_BAD_INO		 1	/* Bad blocks inode */
58
#define	EXT2_BAD_INO		 1	/* Bad blocks inode */
59
#define EXT2_ROOT_INO		 2	/* Root inode */
59
#define EXT2_ROOT_INO		 2	/* Root inode */
60
#define EXT2_ACL_IDX_INO	 3	/* ACL inode */
61
#define EXT2_ACL_DATA_INO	 4	/* ACL inode */
62
#define EXT2_BOOT_LOADER_INO	 5	/* Boot loader inode */
60
#define EXT2_BOOT_LOADER_INO	 5	/* Boot loader inode */
63
#define EXT2_UNDEL_DIR_INO	 6	/* Undelete directory inode */
61
#define EXT2_UNDEL_DIR_INO	 6	/* Undelete directory inode */
64
62
Lines 86-92 Link Here
86
#else
84
#else
87
# define EXT2_BLOCK_SIZE(s)		(EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
85
# define EXT2_BLOCK_SIZE(s)		(EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
88
#endif
86
#endif
89
#define EXT2_ACLE_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
90
#define	EXT2_ADDR_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (__u32))
87
#define	EXT2_ADDR_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (__u32))
91
#ifdef __KERNEL__
88
#ifdef __KERNEL__
92
# define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
89
# define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
Lines 121-148 Link Here
121
#endif
118
#endif
122
119
123
/*
120
/*
124
 * ACL structures
125
 */
126
struct ext2_acl_header	/* Header of Access Control Lists */
127
{
128
	__u32	aclh_size;
129
	__u32	aclh_file_count;
130
	__u32	aclh_acle_count;
131
	__u32	aclh_first_acle;
132
};
133
134
struct ext2_acl_entry	/* Access Control List Entry */
135
{
136
	__u32	acle_size;
137
	__u16	acle_perms;	/* Access permissions */
138
	__u16	acle_type;	/* Type of entry */
139
	__u16	acle_tag;	/* User or group identity */
140
	__u16	acle_pad1;
141
	__u32	acle_next;	/* Pointer on next entry for the */
142
					/* same inode or on next free entry */
143
};
144
145
/*
146
 * Structure of a blocks group descriptor
121
 * Structure of a blocks group descriptor
147
 */
122
 */
148
struct ext2_group_desc
123
struct ext2_group_desc
Lines 314-319 Link Here
314
#define EXT2_MOUNT_ERRORS_PANIC		0x0040	/* Panic on errors */
289
#define EXT2_MOUNT_ERRORS_PANIC		0x0040	/* Panic on errors */
315
#define EXT2_MOUNT_MINIX_DF		0x0080	/* Mimics the Minix statfs */
290
#define EXT2_MOUNT_MINIX_DF		0x0080	/* Mimics the Minix statfs */
316
#define EXT2_MOUNT_NO_UID32		0x0200  /* Disable 32-bit UIDs */
291
#define EXT2_MOUNT_NO_UID32		0x0200  /* Disable 32-bit UIDs */
292
#define EXT2_MOUNT_XATTR_USER		0x4000	/* Extended user attributes */
317
293
318
#define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
294
#define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
319
#define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
295
#define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
Lines 397-402 Link Here
397
373
398
#ifdef __KERNEL__
374
#ifdef __KERNEL__
399
#define EXT2_SB(sb)	(&((sb)->u.ext2_sb))
375
#define EXT2_SB(sb)	(&((sb)->u.ext2_sb))
376
#define EXT2_I(inode)	(&((inode)->u.ext2_i))
400
#else
377
#else
401
/* Assume that user mode programs are passing in an ext2fs superblock, not
378
/* Assume that user mode programs are passing in an ext2fs superblock, not
402
 * a kernel struct super_block.  This will allow us to call the feature-test
379
 * a kernel struct super_block.  This will allow us to call the feature-test
Lines 466-472 Link Here
466
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008
443
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008
467
#define EXT2_FEATURE_INCOMPAT_ANY		0xffffffff
444
#define EXT2_FEATURE_INCOMPAT_ANY		0xffffffff
468
445
469
#define EXT2_FEATURE_COMPAT_SUPP	0
446
#define EXT2_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
470
#define EXT2_FEATURE_INCOMPAT_SUPP	EXT2_FEATURE_INCOMPAT_FILETYPE
447
#define EXT2_FEATURE_INCOMPAT_SUPP	EXT2_FEATURE_INCOMPAT_FILETYPE
471
#define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
448
#define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
472
					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
449
					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
Lines 573-579 Link Here
573
extern int ext2_fsync_inode (struct inode *, int);
550
extern int ext2_fsync_inode (struct inode *, int);
574
551
575
/* ialloc.c */
552
/* ialloc.c */
576
extern struct inode * ext2_new_inode (const struct inode *, int);
553
extern struct inode * ext2_new_inode (struct inode *, int);
577
extern void ext2_free_inode (struct inode *);
554
extern void ext2_free_inode (struct inode *);
578
extern unsigned long ext2_count_free_inodes (struct super_block *);
555
extern unsigned long ext2_count_free_inodes (struct super_block *);
579
extern void ext2_check_inodes_bitmap (struct super_block *);
556
extern void ext2_check_inodes_bitmap (struct super_block *);
Lines 588-593 Link Here
588
extern void ext2_discard_prealloc (struct inode *);
565
extern void ext2_discard_prealloc (struct inode *);
589
extern void ext2_truncate (struct inode *);
566
extern void ext2_truncate (struct inode *);
590
extern void ext2_set_inode_flags(struct inode *inode);
567
extern void ext2_set_inode_flags(struct inode *inode);
568
extern int ext2_setattr (struct dentry *, struct iattr *);
591
569
592
/* ioctl.c */
570
/* ioctl.c */
593
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
571
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
Lines 624-631 Link Here
624
602
625
/* namei.c */
603
/* namei.c */
626
extern struct inode_operations ext2_dir_inode_operations;
604
extern struct inode_operations ext2_dir_inode_operations;
605
extern struct inode_operations ext2_special_inode_operations;
627
606
628
/* symlink.c */
607
/* symlink.c */
608
extern struct inode_operations ext2_symlink_inode_operations;
629
extern struct inode_operations ext2_fast_symlink_inode_operations;
609
extern struct inode_operations ext2_fast_symlink_inode_operations;
630
610
631
#endif	/* __KERNEL__ */
611
#endif	/* __KERNEL__ */
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext2_fs_i.h (+14 lines)
Lines 34-39 Link Here
34
	__u32	i_prealloc_block;
34
	__u32	i_prealloc_block;
35
	__u32	i_prealloc_count;
35
	__u32	i_prealloc_count;
36
	__u32	i_dir_start_lookup;
36
	__u32	i_dir_start_lookup;
37
#ifdef CONFIG_EXT2_FS_XATTR
38
	/*
39
	 * Extended attributes can be read independently of the main file
40
	 * data. Taking i_sem even when reading would cause contention
41
	 * between readers of EAs and writers of regular file data, so
42
	 * instead we synchronize on xattr_sem when reading or changing
43
	 * EAs.
44
	 */
45
	struct rw_semaphore xattr_sem;
46
#endif
47
#ifdef CONFIG_EXT2_FS_POSIX_ACL
48
	struct posix_acl	*i_acl;
49
	struct posix_acl	*i_default_acl;
50
#endif
37
	int	i_new_inode:1;	/* Is a freshly allocated inode */
51
	int	i_new_inode:1;	/* Is a freshly allocated inode */
38
};
52
};
39
53
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext2_xattr.h (+180 lines)
Line 0 Link Here
1
/*
2
  File: linux/ext2_xattr.h
3
4
  On-disk format of extended attributes for the ext2 filesystem.
5
6
  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
7
*/
8
9
#include <linux/config.h>
10
#include <linux/init.h>
11
#include <linux/xattr.h>
12
13
/* Magic value in attribute blocks */
14
#define EXT2_XATTR_MAGIC		0xEA020000
15
16
/* Maximum number of references to one attribute block */
17
#define EXT2_XATTR_REFCOUNT_MAX		1024
18
19
/* Name indexes */
20
#define EXT2_XATTR_INDEX_MAX			10
21
#define EXT2_XATTR_INDEX_USER			1
22
#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS	2
23
#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT	3
24
#define EXT2_XATTR_INDEX_TRUSTED		4
25
26
struct ext2_xattr_header {
27
	__u32	h_magic;	/* magic number for identification */
28
	__u32	h_refcount;	/* reference count */
29
	__u32	h_blocks;	/* number of disk blocks used */
30
	__u32	h_hash;		/* hash value of all attributes */
31
	__u32	h_reserved[4];	/* zero right now */
32
};
33
34
struct ext2_xattr_entry {
35
	__u8	e_name_len;	/* length of name */
36
	__u8	e_name_index;	/* attribute name index */
37
	__u16	e_value_offs;	/* offset in disk block of value */
38
	__u32	e_value_block;	/* disk block attribute is stored on (n/i) */
39
	__u32	e_value_size;	/* size of attribute value */
40
	__u32	e_hash;		/* hash value of name and value */
41
	char	e_name[0];	/* attribute name */
42
};
43
44
#define EXT2_XATTR_PAD_BITS		2
45
#define EXT2_XATTR_PAD		(1<<EXT2_XATTR_PAD_BITS)
46
#define EXT2_XATTR_ROUND		(EXT2_XATTR_PAD-1)
47
#define EXT2_XATTR_LEN(name_len) \
48
	(((name_len) + EXT2_XATTR_ROUND + \
49
	sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
50
#define EXT2_XATTR_NEXT(entry) \
51
	( (struct ext2_xattr_entry *)( \
52
	  (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
53
#define EXT2_XATTR_SIZE(size) \
54
	(((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
55
56
#ifdef __KERNEL__
57
58
# ifdef CONFIG_EXT2_FS_XATTR
59
60
struct ext2_xattr_handler {
61
	char *prefix;
62
	size_t (*list)(char *list, struct inode *inode, const char *name,
63
		       int name_len);
64
	int (*get)(struct inode *inode, const char *name, void *buffer,
65
		   size_t size);
66
	int (*set)(struct inode *inode, const char *name, const void *buffer,
67
		   size_t size, int flags);
68
};
69
70
extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
71
extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
72
73
extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t,
74
			 int);
75
extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
76
extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
77
extern int ext2_removexattr(struct dentry *, const char *);
78
79
extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
80
extern int ext2_xattr_list(struct inode *, char *, size_t);
81
extern int ext2_xattr_set(struct inode *, int, const char *, const void *,
82
			  size_t, int);
83
84
extern void ext2_xattr_delete_inode(struct inode *);
85
extern void ext2_xattr_put_super(struct super_block *);
86
87
extern int init_ext2_xattr(void) __init;
88
extern void exit_ext2_xattr(void);
89
90
# else  /* CONFIG_EXT2_FS_XATTR */
91
#  define ext2_setxattr		NULL
92
#  define ext2_getxattr		NULL
93
#  define ext2_listxattr	NULL
94
#  define ext2_removexattr	NULL
95
96
static inline int
97
ext2_xattr_get(struct inode *inode, int name_index,
98
	       const char *name, void *buffer, size_t size)
99
{
100
	return -EOPNOTSUPP;
101
}
102
103
static inline int
104
ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
105
{
106
	return -EOPNOTSUPP;
107
}
108
109
static inline int
110
ext2_xattr_set(struct inode *inode, int name_index, const char *name,
111
	       const void *value, size_t size, int flags)
112
{
113
	return -EOPNOTSUPP;
114
}
115
116
static inline void
117
ext2_xattr_delete_inode(struct inode *inode)
118
{
119
}
120
121
static inline void
122
ext2_xattr_put_super(struct super_block *sb)
123
{
124
}
125
126
static inline int
127
init_ext2_xattr(void)
128
{
129
	return 0;
130
}
131
132
static inline void
133
exit_ext2_xattr(void)
134
{
135
}
136
137
# endif  /* CONFIG_EXT2_FS_XATTR */
138
139
# ifdef CONFIG_EXT2_FS_XATTR_USER
140
141
extern int init_ext2_xattr_user(void) __init;
142
extern void exit_ext2_xattr_user(void);
143
144
# else  /* CONFIG_EXT2_FS_XATTR_USER */
145
146
static inline int
147
init_ext2_xattr_user(void)
148
{
149
	return 0;
150
}
151
152
static inline void
153
exit_ext2_xattr_user(void)
154
{
155
}
156
157
# endif  /* CONFIG_EXT2_FS_XATTR_USER */
158
159
# ifdef CONFIG_EXT2_FS_XATTR_TRUSTED
160
161
extern int init_ext2_xattr_trusted(void) __init;
162
extern void exit_ext2_xattr_trusted(void);
163
164
# else  /* CONFIG_EXT2_FS_XATTR_TRUSTED */
165
166
static inline int
167
init_ext2_xattr_trusted(void)
168
{
169
	return 0;
170
}
171
172
static inline void
173
exit_ext2_xattr_trusted(void)
174
{
175
}
176
177
# endif  /* CONFIG_EXT2_FS_XATTR_TRUSTED */
178
179
#endif  /* __KERNEL__ */
180
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext3_acl.h (+108 lines)
Line 0 Link Here
1
/*
2
  File: linux/ext3_acl.h
3
4
  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5
*/
6
7
#include <linux/init.h>
8
#include <linux/posix_acl.h>
9
#include <linux/xattr_acl.h>
10
11
#define EXT3_ACL_VERSION	0x0001
12
#define EXT3_ACL_MAX_ENTRIES	32
13
14
typedef struct {
15
	__u16		e_tag;
16
	__u16		e_perm;
17
	__u32		e_id;
18
} ext3_acl_entry;
19
20
typedef struct {
21
	__u16		e_tag;
22
	__u16		e_perm;
23
} ext3_acl_entry_short;
24
25
typedef struct {
26
	__u32		a_version;
27
} ext3_acl_header;
28
29
static inline size_t ext3_acl_size(int count)
30
{
31
	if (count <= 4) {
32
		return sizeof(ext3_acl_header) +
33
		       count * sizeof(ext3_acl_entry_short);
34
	} else {
35
		return sizeof(ext3_acl_header) +
36
		       4 * sizeof(ext3_acl_entry_short) +
37
		       (count - 4) * sizeof(ext3_acl_entry);
38
	}
39
}
40
41
static inline int ext3_acl_count(size_t size)
42
{
43
	ssize_t s;
44
	size -= sizeof(ext3_acl_header);
45
	s = size - 4 * sizeof(ext3_acl_entry_short);
46
	if (s < 0) {
47
		if (size % sizeof(ext3_acl_entry_short))
48
			return -1;
49
		return size / sizeof(ext3_acl_entry_short);
50
	} else {
51
		if (s % sizeof(ext3_acl_entry))
52
			return -1;
53
		return s / sizeof(ext3_acl_entry) + 4;
54
	}
55
}
56
57
#ifdef __KERNEL__
58
# ifdef CONFIG_EXT3_FS_POSIX_ACL
59
60
/* Value for inode->u.ext3_i.i_acl and inode->u.ext3_i.i_default_acl
61
   if the ACL has not been cached */
62
# define EXT3_ACL_NOT_CACHED ((void *)-1)
63
64
/* acl.c */
65
extern int ext3_permission (struct inode *, int);
66
extern struct posix_acl *ext3_get_acl (struct inode *, int);
67
extern int ext3_set_acl (struct inode *, int, struct posix_acl *);
68
extern int ext3_acl_chmod (handle_t *, struct inode *);
69
extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
70
extern int ext3_get_acl_xattr (struct inode *, int, void *, size_t);
71
extern int ext3_set_acl_xattr (struct inode *, int, void *, size_t);
72
73
extern int init_ext3_acl(void) __init;
74
extern void exit_ext3_acl(void);
75
76
# else  /* CONFIG_EXT3_FS_POSIX_ACL */
77
#  include <linux/sched.h>
78
#  define ext3_permission NULL
79
#  define ext3_get_acl	NULL
80
#  define ext3_set_acl	NULL
81
82
static inline int
83
ext3_acl_chmod(handle_t *handle, struct inode *inode)
84
{
85
	return 0;
86
}
87
88
static inline int
89
ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
90
{
91
	inode->i_mode &= ~current->fs->umask;
92
	ext3_mark_inode_dirty(handle, inode);
93
	return 0;
94
}
95
96
static inline int
97
init_ext3_acl(void)
98
{
99
	return 0;
100
}
101
102
static inline void
103
exit_ext3_acl(void)
104
{
105
}
106
107
# endif  /* CONFIG_EXT3_FS_POSIX_ACL */
108
#endif  /* __KERNEL__ */
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext3_fs.h (-27 / +7 lines)
Lines 58-65 Link Here
58
 */
58
 */
59
#define	EXT3_BAD_INO		 1	/* Bad blocks inode */
59
#define	EXT3_BAD_INO		 1	/* Bad blocks inode */
60
#define EXT3_ROOT_INO		 2	/* Root inode */
60
#define EXT3_ROOT_INO		 2	/* Root inode */
61
#define EXT3_ACL_IDX_INO	 3	/* ACL inode */
62
#define EXT3_ACL_DATA_INO	 4	/* ACL inode */
63
#define EXT3_BOOT_LOADER_INO	 5	/* Boot loader inode */
61
#define EXT3_BOOT_LOADER_INO	 5	/* Boot loader inode */
64
#define EXT3_UNDEL_DIR_INO	 6	/* Undelete directory inode */
62
#define EXT3_UNDEL_DIR_INO	 6	/* Undelete directory inode */
65
#define EXT3_RESIZE_INO		 7	/* Reserved group descriptors inode */
63
#define EXT3_RESIZE_INO		 7	/* Reserved group descriptors inode */
Lines 89-95 Link Here
89
#else
87
#else
90
# define EXT3_BLOCK_SIZE(s)		(EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
88
# define EXT3_BLOCK_SIZE(s)		(EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
91
#endif
89
#endif
92
#define EXT3_ACLE_PER_BLOCK(s)		(EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
93
#define	EXT3_ADDR_PER_BLOCK(s)		(EXT3_BLOCK_SIZE(s) / sizeof (__u32))
90
#define	EXT3_ADDR_PER_BLOCK(s)		(EXT3_BLOCK_SIZE(s) / sizeof (__u32))
94
#ifdef __KERNEL__
91
#ifdef __KERNEL__
95
# define EXT3_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
92
# define EXT3_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
Lines 124-151 Link Here
124
#endif
121
#endif
125
122
126
/*
123
/*
127
 * ACL structures
128
 */
129
struct ext3_acl_header	/* Header of Access Control Lists */
130
{
131
	__u32	aclh_size;
132
	__u32	aclh_file_count;
133
	__u32	aclh_acle_count;
134
	__u32	aclh_first_acle;
135
};
136
137
struct ext3_acl_entry	/* Access Control List Entry */
138
{
139
	__u32	acle_size;
140
	__u16	acle_perms;	/* Access permissions */
141
	__u16	acle_type;	/* Type of entry */
142
	__u16	acle_tag;	/* User or group identity */
143
	__u16	acle_pad1;
144
	__u32	acle_next;	/* Pointer on next entry for the */
145
					/* same inode or on next free entry */
146
};
147
148
/*
149
 * Structure of a blocks group descriptor
124
 * Structure of a blocks group descriptor
150
 */
125
 */
151
struct ext3_group_desc
126
struct ext3_group_desc
Lines 339-344 Link Here
339
  #define EXT3_MOUNT_WRITEBACK_DATA	0x0C00	/* No data ordering */
314
  #define EXT3_MOUNT_WRITEBACK_DATA	0x0C00	/* No data ordering */
340
#define EXT3_MOUNT_UPDATE_JOURNAL	0x1000	/* Update the journal format */
315
#define EXT3_MOUNT_UPDATE_JOURNAL	0x1000	/* Update the journal format */
341
#define EXT3_MOUNT_NO_UID32		0x2000  /* Disable 32-bit UIDs */
316
#define EXT3_MOUNT_NO_UID32		0x2000  /* Disable 32-bit UIDs */
317
#define EXT3_MOUNT_XATTR_USER		0x4000	/* Extended user attributes */
318
#define EXT3_MOUNT_POSIX_ACL		0x8000	/* POSIX Access Control Lists */
342
319
343
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
320
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
344
#ifndef _LINUX_EXT2_FS_H
321
#ifndef _LINUX_EXT2_FS_H
Lines 513-519 Link Here
513
#define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004 /* Needs recovery */
490
#define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004 /* Needs recovery */
514
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
491
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
515
492
516
#define EXT3_FEATURE_COMPAT_SUPP	0
493
#define EXT3_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
517
#define EXT3_FEATURE_INCOMPAT_SUPP	(EXT3_FEATURE_INCOMPAT_FILETYPE| \
494
#define EXT3_FEATURE_INCOMPAT_SUPP	(EXT3_FEATURE_INCOMPAT_FILETYPE| \
518
					 EXT3_FEATURE_INCOMPAT_RECOVER)
495
					 EXT3_FEATURE_INCOMPAT_RECOVER)
519
#define EXT3_FEATURE_RO_COMPAT_SUPP	(EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
496
#define EXT3_FEATURE_RO_COMPAT_SUPP	(EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
Lines 621-627 Link Here
621
extern int ext3_sync_file (struct file *, struct dentry *, int);
598
extern int ext3_sync_file (struct file *, struct dentry *, int);
622
599
623
/* ialloc.c */
600
/* ialloc.c */
624
extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int);
601
extern struct inode * ext3_new_inode (handle_t *, struct inode *, int);
625
extern void ext3_free_inode (handle_t *, struct inode *);
602
extern void ext3_free_inode (handle_t *, struct inode *);
626
extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
603
extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
627
extern unsigned long ext3_count_free_inodes (struct super_block *);
604
extern unsigned long ext3_count_free_inodes (struct super_block *);
Lines 629-634 Link Here
629
extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
606
extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
630
607
631
/* inode.c */
608
/* inode.c */
609
extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
632
extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
610
extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
633
extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
611
extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
634
612
Lines 696-703 Link Here
696
674
697
/* namei.c */
675
/* namei.c */
698
extern struct inode_operations ext3_dir_inode_operations;
676
extern struct inode_operations ext3_dir_inode_operations;
677
extern struct inode_operations ext3_special_inode_operations;
699
678
700
/* symlink.c */
679
/* symlink.c */
680
extern struct inode_operations ext3_symlink_inode_operations;
701
extern struct inode_operations ext3_fast_symlink_inode_operations;
681
extern struct inode_operations ext3_fast_symlink_inode_operations;
702
682
703
683
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext3_fs_i.h (+14 lines)
Lines 42-47 Link Here
42
	__u32	i_prealloc_count;
42
	__u32	i_prealloc_count;
43
#endif
43
#endif
44
	__u32	i_dir_start_lookup;
44
	__u32	i_dir_start_lookup;
45
#ifdef CONFIG_EXT3_FS_XATTR
46
	/*
47
	 * Extended attributes can be read independently of the main file
48
	 * data. Taking i_sem even when reading would cause contention
49
	 * between readers of EAs and writers of regular file data, so
50
	 * instead we synchronize on xattr_sem when reading or changing
51
	 * EAs.
52
	 */
53
	struct rw_semaphore xattr_sem;
54
#endif
55
#ifdef CONFIG_EXT3_FS_POSIX_ACL
56
	struct posix_acl	*i_acl;
57
	struct posix_acl	*i_default_acl;
58
#endif
45
	
59
	
46
	struct list_head i_orphan;	/* unlinked but open inodes */
60
	struct list_head i_orphan;	/* unlinked but open inodes */
47
61
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext3_jbd.h (-1 / +7 lines)
Lines 30-42 Link Here
30
30
31
#define EXT3_SINGLEDATA_TRANS_BLOCKS	8U
31
#define EXT3_SINGLEDATA_TRANS_BLOCKS	8U
32
32
33
/* Extended attributes may touch two data buffers, two bitmap buffers,
34
 * and two group and summaries. */
35
36
#define EXT3_XATTR_TRANS_BLOCKS		8
37
33
/* Define the minimum size for a transaction which modifies data.  This
38
/* Define the minimum size for a transaction which modifies data.  This
34
 * needs to take into account the fact that we may end up modifying two
39
 * needs to take into account the fact that we may end up modifying two
35
 * quota files too (one for the group, one for the user quota).  The
40
 * quota files too (one for the group, one for the user quota).  The
36
 * superblock only gets updated once, of course, so don't bother
41
 * superblock only gets updated once, of course, so don't bother
37
 * counting that again for the quota updates. */
42
 * counting that again for the quota updates. */
38
43
39
#define EXT3_DATA_TRANS_BLOCKS		(3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
44
#define EXT3_DATA_TRANS_BLOCKS		(3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
45
					 EXT3_XATTR_TRANS_BLOCKS - 2)
40
46
41
extern int ext3_writepage_trans_blocks(struct inode *inode);
47
extern int ext3_writepage_trans_blocks(struct inode *inode);
42
48
(-)linux-2.4.22-ppc-dev.orig/include/linux/ext3_xattr.h (+182 lines)
Line 0 Link Here
1
/*
2
  File: linux/ext3_xattr.h
3
4
  On-disk format of extended attributes for the ext3 filesystem.
5
6
  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
7
*/
8
9
#include <linux/config.h>
10
#include <linux/init.h>
11
#include <linux/xattr.h>
12
13
/* Magic value in attribute blocks */
14
#define EXT3_XATTR_MAGIC		0xEA020000
15
16
/* Maximum number of references to one attribute block */
17
#define EXT3_XATTR_REFCOUNT_MAX		1024
18
19
/* Name indexes */
20
#define EXT3_XATTR_INDEX_MAX			10
21
#define EXT3_XATTR_INDEX_USER			1
22
#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS	2
23
#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT	3
24
#define EXT3_XATTR_INDEX_TRUSTED		4
25
26
struct ext3_xattr_header {
27
	__u32	h_magic;	/* magic number for identification */
28
	__u32	h_refcount;	/* reference count */
29
	__u32	h_blocks;	/* number of disk blocks used */
30
	__u32	h_hash;		/* hash value of all attributes */
31
	__u32	h_reserved[4];	/* zero right now */
32
};
33
34
struct ext3_xattr_entry {
35
	__u8	e_name_len;	/* length of name */
36
	__u8	e_name_index;	/* attribute name index */
37
	__u16	e_value_offs;	/* offset in disk block of value */
38
	__u32	e_value_block;	/* disk block attribute is stored on (n/i) */
39
	__u32	e_value_size;	/* size of attribute value */
40
	__u32	e_hash;		/* hash value of name and value */
41
	char	e_name[0];	/* attribute name */
42
};
43
44
#define EXT3_XATTR_PAD_BITS		2
45
#define EXT3_XATTR_PAD		(1<<EXT3_XATTR_PAD_BITS)
46
#define EXT3_XATTR_ROUND		(EXT3_XATTR_PAD-1)
47
#define EXT3_XATTR_LEN(name_len) \
48
	(((name_len) + EXT3_XATTR_ROUND + \
49
	sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
50
#define EXT3_XATTR_NEXT(entry) \
51
	( (struct ext3_xattr_entry *)( \
52
	  (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
53
#define EXT3_XATTR_SIZE(size) \
54
	(((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
55
56
#ifdef __KERNEL__
57
58
# ifdef CONFIG_EXT3_FS_XATTR
59
60
struct ext3_xattr_handler {
61
	char *prefix;
62
	size_t (*list)(char *list, struct inode *inode, const char *name,
63
		       int name_len);
64
	int (*get)(struct inode *inode, const char *name, void *buffer,
65
		   size_t size);
66
	int (*set)(struct inode *inode, const char *name, const void *buffer,
67
		   size_t size, int flags);
68
};
69
70
extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
71
extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
72
73
extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t,
74
			 int);
75
extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
76
extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
77
extern int ext3_removexattr(struct dentry *, const char *);
78
79
extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
80
extern int ext3_xattr_list(struct inode *, char *, size_t);
81
extern int ext3_xattr_set_handle(handle_t *handle, struct inode *, int,
82
				 const char *, const void *, size_t, int);
83
extern int ext3_xattr_set(struct inode *, int, const char *, const void *,
84
			  size_t, int);
85
86
extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
87
extern void ext3_xattr_put_super(struct super_block *);
88
89
extern int init_ext3_xattr(void) __init;
90
extern void exit_ext3_xattr(void);
91
92
# else  /* CONFIG_EXT3_FS_XATTR */
93
#  define ext3_setxattr		NULL
94
#  define ext3_getxattr		NULL
95
#  define ext3_listxattr	NULL
96
#  define ext3_removexattr	NULL
97
98
static inline int
99
ext3_xattr_get(struct inode *inode, int name_index, const char *name,
100
	       void *buffer, size_t size)
101
{
102
	return -EOPNOTSUPP;
103
}
104
105
static inline int
106
ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
107
{
108
	return -EOPNOTSUPP;
109
}
110
111
static inline int
112
ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
113
	       const char *name, const void *value, size_t size)
114
{
115
	return -EOPNOTSUPP;
116
}
117
118
static inline void
119
ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
120
{
121
}
122
123
static inline void
124
ext3_xattr_put_super(struct super_block *sb)
125
{
126
}
127
128
static inline int
129
init_ext3_xattr(void)
130
{
131
	return 0;
132
}
133
134
static inline void
135
exit_ext3_xattr(void)
136
{
137
}
138
139
# endif  /* CONFIG_EXT3_FS_XATTR */
140
141
# ifdef CONFIG_EXT3_FS_XATTR_USER
142
143
extern int init_ext3_xattr_user(void) __init;
144
extern void exit_ext3_xattr_user(void);
145
146
# else  /* CONFIG_EXT3_FS_XATTR_USER */
147
148
static inline int
149
init_ext3_xattr_user(void)
150
{
151
	return 0;
152
}
153
154
static inline void
155
exit_ext3_xattr_user(void)
156
{
157
}
158
159
#endif  /* CONFIG_EXT3_FS_XATTR_USER */
160
161
# ifdef CONFIG_EXT3_FS_XATTR_TRUSTED
162
163
extern int init_ext3_xattr_trusted(void) __init;
164
extern void exit_ext3_xattr_trusted(void);
165
166
# else  /* CONFIG_EXT3_FS_XATTR_TRUSTED */
167
168
static inline int
169
init_ext3_xattr_trusted(void)
170
{
171
	return 0;
172
}
173
174
static inline void
175
exit_ext3_xattr_trusted(void)
176
{
177
}
178
179
#endif  /* CONFIG_EXT3_FS_XATTR_TRUSTED */
180
181
#endif  /* __KERNEL__ */
182
(-)linux-2.4.22-ppc-dev.orig/include/linux/fs.h (-2 / +6 lines)
Lines 111-116 Link Here
111
#define MS_MOVE		8192
111
#define MS_MOVE		8192
112
#define MS_REC		16384
112
#define MS_REC		16384
113
#define MS_VERBOSE	32768
113
#define MS_VERBOSE	32768
114
#define MS_POSIXACL	65536	/* VFS does not apply the umask */
114
#define MS_ACTIVE	(1<<30)
115
#define MS_ACTIVE	(1<<30)
115
#define MS_NOUSER	(1<<31)
116
#define MS_NOUSER	(1<<31)
116
117
Lines 161-166 Link Here
161
#define IS_IMMUTABLE(inode)	((inode)->i_flags & S_IMMUTABLE)
162
#define IS_IMMUTABLE(inode)	((inode)->i_flags & S_IMMUTABLE)
162
#define IS_NOATIME(inode)	(__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
163
#define IS_NOATIME(inode)	(__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
163
#define IS_NODIRATIME(inode)	__IS_FLG(inode, MS_NODIRATIME)
164
#define IS_NODIRATIME(inode)	__IS_FLG(inode, MS_NODIRATIME)
165
#define IS_POSIXACL(inode)	__IS_FLG(inode, MS_POSIXACL)
164
166
165
#define IS_DEADDIR(inode)	((inode)->i_flags & S_DEAD)
167
#define IS_DEADDIR(inode)	((inode)->i_flags & S_DEAD)
166
168
Lines 898-904 Link Here
898
	int (*revalidate) (struct dentry *);
900
	int (*revalidate) (struct dentry *);
899
	int (*setattr) (struct dentry *, struct iattr *);
901
	int (*setattr) (struct dentry *, struct iattr *);
900
	int (*getattr) (struct dentry *, struct iattr *);
902
	int (*getattr) (struct dentry *, struct iattr *);
901
	int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
903
	int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
902
	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
904
	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
903
	ssize_t (*listxattr) (struct dentry *, char *, size_t);
905
	ssize_t (*listxattr) (struct dentry *, char *, size_t);
904
	int (*removexattr) (struct dentry *, const char *);
906
	int (*removexattr) (struct dentry *, const char *);
Lines 1022-1028 Link Here
1022
		__MOD_DEC_USE_COUNT((fops)->owner);	\
1024
		__MOD_DEC_USE_COUNT((fops)->owner);	\
1023
} while(0)
1025
} while(0)
1024
1026
1025
extern int register_filesystem(struct file_system_type *);
1027
extern int __register_filesystem(struct file_system_type *, int);
1028
#define register_filesystem(fs) __register_filesystem(fs, 0)
1029
#define register_filesystem_lifo(fs) __register_filesystem(fs, 1)
1026
extern int unregister_filesystem(struct file_system_type *);
1030
extern int unregister_filesystem(struct file_system_type *);
1027
extern struct vfsmount *kern_mount(struct file_system_type *);
1031
extern struct vfsmount *kern_mount(struct file_system_type *);
1028
extern int may_umount(struct vfsmount *);
1032
extern int may_umount(struct vfsmount *);
(-)linux-2.4.22-ppc-dev.orig/include/linux/jbd.h (+4 lines)
Lines 359-364 Link Here
359
	/* Number of remaining buffers we are allowed to dirty: */
359
	/* Number of remaining buffers we are allowed to dirty: */
360
	int			h_buffer_credits;
360
	int			h_buffer_credits;
361
361
362
	/* Number of credits consumed by the last journal_get_write_access
363
	   or get_undo_access operation */
364
	int			h_last_buffer_credits;
365
362
	/* Reference count on this handle */
366
	/* Reference count on this handle */
363
	int			h_ref;
367
	int			h_ref;
364
368
(-)linux-2.4.22-ppc-dev.orig/include/linux/kernel.h (+2 lines)
Lines 83-88 Link Here
83
extern int vsscanf(const char *, const char *, va_list)
83
extern int vsscanf(const char *, const char *, va_list)
84
	__attribute__ ((format (scanf, 2, 0)));
84
	__attribute__ ((format (scanf, 2, 0)));
85
85
86
extern void qsort(void *, size_t, size_t, int (*)(const void *,const void *));
87
86
extern int get_option(char **str, int *pint);
88
extern int get_option(char **str, int *pint);
87
extern char *get_options(char *str, int nints, int *ints);
89
extern char *get_options(char *str, int nints, int *ints);
88
extern unsigned long long memparse(char *ptr, char **retptr);
90
extern unsigned long long memparse(char *ptr, char **retptr);
(-)linux-2.4.22-ppc-dev.orig/include/linux/mbcache.h (+69 lines)
Line 0 Link Here
1
/*
2
  File: linux/mbcache.h
3
4
  (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
5
*/
6
7
/* Hardwire the number of additional indexes */
8
#define MB_CACHE_INDEXES_COUNT 1
9
10
struct mb_cache_entry;
11
12
struct mb_cache_op {
13
	int (*free)(struct mb_cache_entry *, int);
14
};
15
16
struct mb_cache {
17
	struct list_head		c_cache_list;
18
	const char			*c_name;
19
	struct mb_cache_op		c_op;
20
	atomic_t			c_entry_count;
21
	int				c_bucket_count;
22
#ifndef MB_CACHE_INDEXES_COUNT
23
	int				c_indexes_count;
24
#endif
25
	kmem_cache_t			*c_entry_cache;
26
	struct list_head		*c_block_hash;
27
	struct list_head		*c_indexes_hash[0];
28
};
29
30
struct mb_cache_entry_index {
31
	struct list_head		o_list;
32
	unsigned int			o_key;
33
};
34
35
struct mb_cache_entry {
36
	struct list_head		e_lru_list;
37
	struct mb_cache			*e_cache;
38
	atomic_t			e_used;
39
	kdev_t				e_dev;
40
	unsigned long			e_block;
41
	struct list_head		e_block_list;
42
	struct mb_cache_entry_index	e_indexes[0];
43
};
44
45
/* Functions on caches */
46
47
struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
48
				  int, int);
49
void mb_cache_shrink(struct mb_cache *, kdev_t);
50
void mb_cache_destroy(struct mb_cache *);
51
52
/* Functions on cache entries */
53
54
struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
55
int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
56
			  unsigned int[]);
57
void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
58
void mb_cache_entry_release(struct mb_cache_entry *);
59
void mb_cache_entry_takeout(struct mb_cache_entry *);
60
void mb_cache_entry_free(struct mb_cache_entry *);
61
struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
62
struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
63
					  unsigned long);
64
#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
65
struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
66
						 kdev_t, unsigned int);
67
struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
68
						kdev_t, unsigned int);
69
#endif
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfs3.h (+16 lines)
Lines 36-41 Link Here
36
	NFS3_CREATE_EXCLUSIVE = 2
36
	NFS3_CREATE_EXCLUSIVE = 2
37
};
37
};
38
38
39
/* Flags for the getacl/setacl mode */
40
#define NFS3_ACL		0x0001
41
#define NFS3_ACLCNT		0x0002
42
#define NFS3_DFACL		0x0004
43
#define NFS3_DFACLCNT		0x0008
44
45
/* Flag for Default ACL entries */
46
#define NFS3_ACL_DEFAULT	0x1000
47
48
/* Maximum number of ACL entries over NFS */
49
#define NFS3_ACL_MAX_ENTRIES	1024
50
39
/* NFSv3 file system properties */
51
/* NFSv3 file system properties */
40
#define NFS3_FSF_LINK		0x0001
52
#define NFS3_FSF_LINK		0x0001
41
#define NFS3_FSF_SYMLINK	0x0002
53
#define NFS3_FSF_SYMLINK	0x0002
Lines 82-87 Link Here
82
#define NFS3PROC_PATHCONF	20
94
#define NFS3PROC_PATHCONF	20
83
#define NFS3PROC_COMMIT		21
95
#define NFS3PROC_COMMIT		21
84
96
97
#define NFS3_ACL_PROGRAM	100227
98
#define NFS3_ACL_PROC_GETACL	1
99
#define NFS3_ACL_PROC_SETACL	2
100
85
#define NFS_MNT3_PROGRAM	100005
101
#define NFS_MNT3_PROGRAM	100005
86
#define NFS_MNT3_VERSION	3
102
#define NFS_MNT3_VERSION	3
87
#define MOUNTPROC3_NULL		0
103
#define MOUNTPROC3_NULL		0
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfs_fs.h (+18 lines)
Lines 102-107 Link Here
102
102
103
#define NFS_FILEID(inode)		((inode)->u.nfs_i.fileid)
103
#define NFS_FILEID(inode)		((inode)->u.nfs_i.fileid)
104
104
105
#define NFS_ACL_CLIENT(inode)		(NFS_SERVER(inode)->acl_client)
106
105
/* Inode Flags */
107
/* Inode Flags */
106
#define NFS_USE_READDIRPLUS(inode)	((NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) ? 1 : 0)
108
#define NFS_USE_READDIRPLUS(inode)	((NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) ? 1 : 0)
107
109
Lines 163-168 Link Here
163
extern struct file_operations nfs_file_operations;
165
extern struct file_operations nfs_file_operations;
164
extern struct address_space_operations nfs_file_aops;
166
extern struct address_space_operations nfs_file_aops;
165
167
168
/*
169
 * linux/fs/nfs/xattr.c
170
 */
171
#ifdef CONFIG_NFS_ACL
172
extern ssize_t nfs_listxattr(struct dentry *, char *, size_t);
173
extern ssize_t nfs_getxattr(struct dentry *, const char *, void *, size_t);
174
extern int nfs_setxattr(struct dentry *, const char *,
175
			const void *, size_t, int);
176
extern int nfs_removexattr (struct dentry *, const char *name);
177
#else
178
# define nfs_listxattr NULL
179
# define nfs_getxattr NULL
180
# define nfs_setxattr NULL
181
# define nfs_removexattr NULL
182
#endif
183
166
static __inline__ struct rpc_cred *
184
static __inline__ struct rpc_cred *
167
nfs_file_cred(struct file *file)
185
nfs_file_cred(struct file *file)
168
{
186
{
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfs_fs_i.h (+12 lines)
Lines 6-11 Link Here
6
#include <linux/nfs.h>
6
#include <linux/nfs.h>
7
7
8
/*
8
/*
9
 * NFSv3 Access mode cache
10
 */
11
struct nfs_access_cache {
12
	unsigned long		jiffies;
13
	struct rpc_cred *	cred;
14
	int			mask;
15
	int			err;
16
};
17
18
/*
9
 * nfs fs inode data in memory
19
 * nfs fs inode data in memory
10
 */
20
 */
11
struct nfs_inode_info {
21
struct nfs_inode_info {
Lines 54-59 Link Here
54
	 */
64
	 */
55
	unsigned long		cache_mtime_jiffies;
65
	unsigned long		cache_mtime_jiffies;
56
66
67
	struct nfs_access_cache	cache_access;
68
57
	/*
69
	/*
58
	 * This is the cookie verifier used for NFSv3 readdir
70
	 * This is the cookie verifier used for NFSv3 readdir
59
	 * operations
71
	 * operations
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfs_fs_sb.h (+3 lines)
Lines 8-13 Link Here
8
 */
8
 */
9
struct nfs_server {
9
struct nfs_server {
10
	struct rpc_clnt *	client;		/* RPC client handle */
10
	struct rpc_clnt *	client;		/* RPC client handle */
11
#ifdef CONFIG_NFS_ACL
12
	struct rpc_clnt *	acl_client;	/* ACL RPC client handle */
13
#endif
11
	struct nfs_rpc_ops *	rpc_ops;	/* NFS protocol vector */
14
	struct nfs_rpc_ops *	rpc_ops;	/* NFS protocol vector */
12
	int			flags;		/* various flags */
15
	int			flags;		/* various flags */
13
	unsigned int		rsize;		/* read size */
16
	unsigned int		rsize;		/* read size */
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfs_mount.h (+5 lines)
Lines 53-58 Link Here
53
#define NFS_MOUNT_KERBEROS	0x0100	/* 3 */
53
#define NFS_MOUNT_KERBEROS	0x0100	/* 3 */
54
#define NFS_MOUNT_NONLM		0x0200	/* 3 */
54
#define NFS_MOUNT_NONLM		0x0200	/* 3 */
55
#define NFS_MOUNT_BROKEN_SUID	0x0400	/* 4 */
55
#define NFS_MOUNT_BROKEN_SUID	0x0400	/* 4 */
56
#define NFS_MOUNT_NOACL		0x0800  /* 4 */
56
#define NFS_MOUNT_FLAGMASK	0xFFFF
57
#define NFS_MOUNT_FLAGMASK	0xFFFF
57
58
59
/* Feature flags for the NFS_ACL GETACL and SETACL RPC's */
60
#define NFS_SOLARIS_GETACL	0x10000
61
#define NFS_SOLARIS_SETACL	0x20000
62
58
#endif
63
#endif
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfs_xdr.h (-1 / +34 lines)
Lines 1-6 Link Here
1
#ifndef _LINUX_NFS_XDR_H
1
#ifndef _LINUX_NFS_XDR_H
2
#define _LINUX_NFS_XDR_H
2
#define _LINUX_NFS_XDR_H
3
3
4
#include <linux/posix_acl.h>
5
4
struct nfs_fattr {
6
struct nfs_fattr {
5
	unsigned short		valid;		/* which fields are valid */
7
	unsigned short		valid;		/* which fields are valid */
6
	__u64			pre_size;	/* pre_op_attr.size	  */
8
	__u64			pre_size;	/* pre_op_attr.size	  */
Lines 254-259 Link Here
254
	struct page **		pages;
256
	struct page **		pages;
255
};
257
};
256
258
259
struct nfs3_getaclargs {
260
	struct nfs_fh *		fh;
261
	int			mask;
262
};
263
264
struct nfs3_setaclargs {
265
	struct inode *		inode;
266
	int			mask;
267
	struct posix_acl *	acl_access;
268
	struct posix_acl *	acl_default;
269
};
270
257
struct nfs3_diropres {
271
struct nfs3_diropres {
258
	struct nfs_fattr *	dir_attr;
272
	struct nfs_fattr *	dir_attr;
259
	struct nfs_fh *		fh;
273
	struct nfs_fh *		fh;
Lines 287-292 Link Here
287
	int			plus;
301
	int			plus;
288
};
302
};
289
303
304
struct nfs3_getaclres {
305
	struct nfs_fattr *	fattr;
306
	int			mask;
307
	unsigned int		acl_access_count;
308
	unsigned int		acl_default_count;
309
	struct posix_acl *	acl_access;
310
	struct posix_acl *	acl_default;
311
};
312
290
/*
313
/*
291
 * RPC procedure vector for NFSv2/NFSv3 demuxing
314
 * RPC procedure vector for NFSv2/NFSv3 demuxing
292
 */
315
 */
Lines 300-306 Link Here
300
			    struct iattr *);
323
			    struct iattr *);
301
	int	(*lookup)  (struct inode *, struct qstr *,
324
	int	(*lookup)  (struct inode *, struct qstr *,
302
			    struct nfs_fh *, struct nfs_fattr *);
325
			    struct nfs_fh *, struct nfs_fattr *);
303
	int	(*access)  (struct inode *, int , int);
326
	int	(*access)  (struct inode *, struct rpc_cred *, int);
304
	int	(*readlink)(struct inode *, struct page *);
327
	int	(*readlink)(struct inode *, struct page *);
305
	int	(*read)    (struct inode *, struct rpc_cred *,
328
	int	(*read)    (struct inode *, struct rpc_cred *,
306
			    struct nfs_fattr *,
329
			    struct nfs_fattr *,
Lines 334-339 Link Here
334
	int	(*statfs)  (struct nfs_server *, struct nfs_fh *,
357
	int	(*statfs)  (struct nfs_server *, struct nfs_fh *,
335
			    struct nfs_fsinfo *);
358
			    struct nfs_fsinfo *);
336
	u32 *	(*decode_dirent)(u32 *, struct nfs_entry *, int plus);
359
	u32 *	(*decode_dirent)(u32 *, struct nfs_entry *, int plus);
360
#ifdef CONFIG_NFS_ACL
361
	struct posix_acl * (*getacl)(struct inode *, int);
362
	int (*setacl)(struct inode *, int, struct posix_acl *);
363
	int (*checkacls)(struct inode *inode);
364
#endif  /* CONFIG_NFS_ACL */
337
};
365
};
338
366
339
/*
367
/*
Lines 353-356 Link Here
353
extern struct rpc_program	nfs_program;
381
extern struct rpc_program	nfs_program;
354
extern struct rpc_stat		nfs_rpcstat;
382
extern struct rpc_stat		nfs_rpcstat;
355
383
384
#ifdef CONFIG_NFS_ACL
385
extern struct rpc_version	nfs_acl_version3;
386
extern struct rpc_program	nfs_acl_program;
387
#endif  /* CONFIG_NFS_ACL */
388
356
#endif
389
#endif
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfsd/export.h (-1 / +15 lines)
Lines 40-46 Link Here
40
#define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
40
#define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
41
#define NFSEXP_MSNFS		0x1000	/* do silly things that MS clients expect */
41
#define NFSEXP_MSNFS		0x1000	/* do silly things that MS clients expect */
42
#define NFSEXP_FSID		0x2000
42
#define NFSEXP_FSID		0x2000
43
#define NFSEXP_ALLFLAGS		0x3FFF
43
#define NFSEXP_NOACL			0x4000
44
#define NFSEXP_ALLFLAGS		0x7FFF
44
45
45
46
46
#ifdef __KERNEL__
47
#ifdef __KERNEL__
Lines 83-88 Link Here
83
#define EX_CROSSMNT(exp)	((exp)->ex_flags & NFSEXP_CROSSMNT)
84
#define EX_CROSSMNT(exp)	((exp)->ex_flags & NFSEXP_CROSSMNT)
84
#define EX_SUNSECURE(exp)	((exp)->ex_flags & NFSEXP_SUNSECURE)
85
#define EX_SUNSECURE(exp)	((exp)->ex_flags & NFSEXP_SUNSECURE)
85
#define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
86
#define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
87
/*
88
 * With Posix Access Control Lists, pre-NFS3 clients and older Linux
89
 * NFSv3 clients in some cases mis-interpret the file mode permission
90
 * bits, and either allow the remote user to read data she is not
91
 * permitted to, or deny the user read access that should be granted.
92
 * (With proper NFSv3, the access RPC is used to check access, and
93
 * access decisions are not implemented on the client.)
94
 *
95
 * The no_acl option should be set in environments with clients that do
96
 * not use the NFSv3 ACCESS RPC. This option should always be set for NFSv2
97
 * clients.
98
 */
99
#define EX_ACL(exp)		(!((exp)->ex_flags & NFSEXP_NOACL))
86
100
87
101
88
/*
102
/*
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfsd/nfsd.h (+22 lines)
Lines 15-20 Link Here
15
#include <linux/unistd.h>
15
#include <linux/unistd.h>
16
#include <linux/dirent.h>
16
#include <linux/dirent.h>
17
#include <linux/fs.h>
17
#include <linux/fs.h>
18
#include <linux/posix_acl.h>
18
19
19
#include <linux/nfsd/debug.h>
20
#include <linux/nfsd/debug.h>
20
#include <linux/nfsd/nfsfh.h>
21
#include <linux/nfsd/nfsfh.h>
Lines 70-75 Link Here
70
#endif /* CONFIG_NFSD_V3 */
71
#endif /* CONFIG_NFSD_V3 */
71
extern struct svc_program	nfsd_program;
72
extern struct svc_program	nfsd_program;
72
73
74
#ifdef CONFIG_NFSD_ACL
75
extern struct svc_procedure	nfsd_acl_procedures3[];
76
extern struct svc_program	nfsd_acl_program;
77
#endif /* CONFIG_NFSD_ACL */
78
73
/*
79
/*
74
 * Function prototypes.
80
 * Function prototypes.
75
 */
81
 */
Lines 127-132 Link Here
127
int		nfsd_notify_change(struct inode *, struct iattr *);
133
int		nfsd_notify_change(struct inode *, struct iattr *);
128
int		nfsd_permission(struct svc_export *, struct dentry *, int);
134
int		nfsd_permission(struct svc_export *, struct dentry *, int);
129
135
136
#ifdef CONFIG_FS_POSIX_ACL
137
struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
138
int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
139
#else
140
static inline struct posix_acl *
141
nfsd_get_posix_acl(struct svc_fh *fhp, int acl_type)
142
{
143
	return ERR_PTR(-EOPNOTSUPP);
144
}
145
static inline int
146
nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
147
{
148
	return -EOPNOTSUPP;
149
}
150
#endif
151
130
152
131
/*
153
/*
132
 * lockd binding
154
 * lockd binding
(-)linux-2.4.22-ppc-dev.orig/include/linux/nfsd/xdr3.h (+34 lines)
Lines 10-15 Link Here
10
#define _LINUX_NFSD_XDR3_H
10
#define _LINUX_NFSD_XDR3_H
11
11
12
#include <linux/nfsd/xdr.h>
12
#include <linux/nfsd/xdr.h>
13
#include <linux/posix_acl.h>
13
14
14
struct nfsd3_sattrargs {
15
struct nfsd3_sattrargs {
15
	struct svc_fh		fh;
16
	struct svc_fh		fh;
Lines 101-106 Link Here
101
	__u32			count;
102
	__u32			count;
102
};
103
};
103
104
105
struct nfsd3_getaclargs {
106
	struct svc_fh		fh;
107
	int			mask;
108
};
109
110
struct nfsd3_setaclargs {
111
	struct svc_fh		fh;
112
	int			mask;
113
	struct posix_acl	*acl_access;
114
	struct posix_acl	*acl_default;
115
};
116
104
struct nfsd3_attrstat {
117
struct nfsd3_attrstat {
105
	__u32			status;
118
	__u32			status;
106
	struct svc_fh		fh;
119
	struct svc_fh		fh;
Lines 192-197 Link Here
192
	struct svc_fh		fh;
205
	struct svc_fh		fh;
193
};
206
};
194
207
208
struct nfsd3_getaclres {
209
	__u32			status;
210
	struct svc_fh		fh;
211
	int			mask;
212
	struct posix_acl	*acl_access;
213
	struct posix_acl	*acl_default;
214
};
215
195
/* dummy type for release */
216
/* dummy type for release */
196
struct nfsd3_fhandle_pair {
217
struct nfsd3_fhandle_pair {
197
	__u32			dummy;
218
	__u32			dummy;
Lines 224-229 Link Here
224
	struct nfsd3_fsinfores		fsinfores;
245
	struct nfsd3_fsinfores		fsinfores;
225
	struct nfsd3_pathconfres	pathconfres;
246
	struct nfsd3_pathconfres	pathconfres;
226
	struct nfsd3_commitres		commitres;
247
	struct nfsd3_commitres		commitres;
248
	struct nfsd3_getaclres		getaclres;
227
};
249
};
228
250
229
#define NFS3_SVC_XDRSIZE		sizeof(union nfsd3_xdrstore)
251
#define NFS3_SVC_XDRSIZE		sizeof(union nfsd3_xdrstore)
Lines 257-262 Link Here
257
				struct nfsd3_readdirargs *);
279
				struct nfsd3_readdirargs *);
258
int nfs3svc_decode_commitargs(struct svc_rqst *, u32 *,
280
int nfs3svc_decode_commitargs(struct svc_rqst *, u32 *,
259
				struct nfsd3_commitargs *);
281
				struct nfsd3_commitargs *);
282
int nfs3svc_decode_getaclargs(struct svc_rqst *, u32 *,
283
				struct nfsd3_getaclargs *);
284
int nfs3svc_decode_setaclargs(struct svc_rqst *, u32 *,
285
				struct nfsd3_setaclargs *);
260
int nfs3svc_encode_voidres(struct svc_rqst *, u32 *, void *);
286
int nfs3svc_encode_voidres(struct svc_rqst *, u32 *, void *);
261
int nfs3svc_encode_attrstat(struct svc_rqst *, u32 *,
287
int nfs3svc_encode_attrstat(struct svc_rqst *, u32 *,
262
				struct nfsd3_attrstat *);
288
				struct nfsd3_attrstat *);
Lines 286-296 Link Here
286
				struct nfsd3_pathconfres *);
312
				struct nfsd3_pathconfres *);
287
int nfs3svc_encode_commitres(struct svc_rqst *, u32 *,
313
int nfs3svc_encode_commitres(struct svc_rqst *, u32 *,
288
				struct nfsd3_commitres *);
314
				struct nfsd3_commitres *);
315
int nfs3svc_encode_getaclres(struct svc_rqst *, u32 *,
316
				struct nfsd3_getaclres *);
317
int nfs3svc_encode_setaclres(struct svc_rqst *, u32 *,
318
				struct nfsd3_attrstat *);
319
289
320
290
int nfs3svc_release_fhandle(struct svc_rqst *, u32 *,
321
int nfs3svc_release_fhandle(struct svc_rqst *, u32 *,
291
				struct nfsd3_attrstat *);
322
				struct nfsd3_attrstat *);
292
int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *,
323
int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *,
293
				struct nfsd3_fhandle_pair *);
324
				struct nfsd3_fhandle_pair *);
325
int nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p,
326
				struct nfsd3_getaclres *resp);
327
294
int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
328
int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
295
				int namlen, loff_t offset, ino_t ino,
329
				int namlen, loff_t offset, ino_t ino,
296
				unsigned int);
330
				unsigned int);
(-)linux-2.4.22-ppc-dev.orig/include/linux/posix_acl.h (+87 lines)
Line 0 Link Here
1
/*
2
  File: linux/posix_acl.h
3
4
  (C) 2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5
*/
6
7
8
#ifndef __LINUX_POSIX_ACL_H
9
#define __LINUX_POSIX_ACL_H
10
11
#include <linux/slab.h>
12
13
#define ACL_UNDEFINED_ID	(-1)
14
15
/* a_type field in acl_user_posix_entry_t */
16
#define ACL_TYPE_ACCESS		(0x8000)
17
#define ACL_TYPE_DEFAULT	(0x4000)
18
19
/* e_tag entry in struct posix_acl_entry */
20
#define ACL_USER_OBJ		(0x01)
21
#define ACL_USER		(0x02)
22
#define ACL_GROUP_OBJ		(0x04)
23
#define ACL_GROUP		(0x08)
24
#define ACL_MASK		(0x10)
25
#define ACL_OTHER		(0x20)
26
27
/* permissions in the e_perm field */
28
#define ACL_READ		(0x04)
29
#define ACL_WRITE		(0x02)
30
#define ACL_EXECUTE		(0x01)
31
//#define ACL_ADD		(0x08)
32
//#define ACL_DELETE		(0x10)
33
34
struct posix_acl_entry {
35
	short			e_tag;
36
	unsigned short		e_perm;
37
	unsigned int		e_id;
38
};
39
40
struct posix_acl {
41
	atomic_t		a_refcount;
42
	unsigned int		a_count;
43
	struct posix_acl_entry	a_entries[0];
44
};
45
46
#define FOREACH_ACL_ENTRY(pa, acl, pe) \
47
	for(pa=(acl)->a_entries, pe=pa+(acl)->a_count; pa<pe; pa++)
48
49
50
/*
51
 * Duplicate an ACL handle.
52
 */
53
static inline struct posix_acl *
54
posix_acl_dup(struct posix_acl *acl)
55
{
56
	if (acl)
57
		atomic_inc(&acl->a_refcount);
58
	return acl;
59
}
60
61
/*
62
 * Free an ACL handle.
63
 */
64
static inline void
65
posix_acl_release(struct posix_acl *acl)
66
{
67
	if (acl && atomic_dec_and_test(&acl->a_refcount))
68
		kfree(acl);
69
}
70
71
72
/* posix_acl.c */
73
74
extern struct posix_acl *posix_acl_alloc(int, int);
75
extern struct posix_acl *posix_acl_clone(const struct posix_acl *, int);
76
extern int posix_acl_valid(const struct posix_acl *);
77
extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
78
extern struct posix_acl *posix_acl_from_mode(mode_t, int);
79
extern int posix_acl_equiv_mode(const struct posix_acl *, mode_t *);
80
extern int posix_acl_create_masq(struct posix_acl *, mode_t *);
81
extern int posix_acl_chmod_masq(struct posix_acl *, mode_t);
82
extern int posix_acl_masq_nfs_mode(struct posix_acl *, mode_t *);
83
84
extern struct posix_acl *get_posix_acl(struct inode *, int);
85
extern int set_posix_acl(struct inode *, int, struct posix_acl *);
86
87
#endif  /* __LINUX_POSIX_ACL_H */
(-)linux-2.4.22-ppc-dev.orig/include/linux/posix_acl_xattr.h (+66 lines)
Line 0 Link Here
1
/*
2
  File: linux/posix_acl_xattr.h
3
4
  Extended attribute system call representation of Access Control Lists.
5
6
  Copyright (C) 2000 by Andreas Gruenbacher <a.gruenbacher@computer.org>
7
 */
8
#ifndef _POSIX_ACL_XATTR_H
9
#define _POSIX_ACL_XATTR_H
10
11
/* Extended attribute names */
12
#define POSIX_ACL_XATTR_ACCESS	"system.posix_acl_access"
13
#define POSIX_ACL_XATTR_DEFAULT	"system.posix_acl_default"
14
15
/* Supported ACL a_version fields */
16
#define POSIX_ACL_XATTR_VERSION	0x0002
17
18
19
/* An undefined entry e_id value */
20
#define ACL_UNDEFINED_ID	(-1)
21
22
/* ACL entry e_tag field values */
23
#define ACL_USER_OBJ		(0x01)
24
#define ACL_USER		(0x02)
25
#define ACL_GROUP_OBJ		(0x04)
26
#define ACL_GROUP		(0x08)
27
#define ACL_MASK		(0x10)
28
#define ACL_OTHER		(0x20)
29
30
/* ACL entry e_perm bitfield values */
31
#define ACL_READ		(0x04)
32
#define ACL_WRITE		(0x02)
33
#define ACL_EXECUTE		(0x01)
34
35
36
typedef struct {
37
	__u16			e_tag;
38
	__u16			e_perm;
39
	__u32			e_id;
40
} posix_acl_xattr_entry;
41
42
typedef struct {
43
	__u32			a_version;
44
	posix_acl_xattr_entry	a_entries[0];
45
} posix_acl_xattr_header;
46
47
48
static inline size_t
49
posix_acl_xattr_size(int count)
50
{
51
	return (sizeof(posix_acl_xattr_header) +
52
		(count * sizeof(posix_acl_xattr_entry)));
53
}
54
55
static inline int
56
posix_acl_xattr_count(size_t size)
57
{
58
	if (size < sizeof(posix_acl_xattr_header))
59
		return -1;
60
	size -= sizeof(posix_acl_xattr_header);
61
	if (size % sizeof(posix_acl_xattr_entry))
62
		return -1;
63
	return size / sizeof(posix_acl_xattr_entry);
64
}
65
66
#endif	/* _POSIX_ACL_XATTR_H */
(-)linux-2.4.22-ppc-dev.orig/include/linux/solaris_acl.h (+16 lines)
Line 0 Link Here
1
/*
2
  File: linux/solaris_acl.h
3
4
  (C) 2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5
*/
6
7
8
#ifndef __LINUX_SOLARIS_ACL_H
9
#define __LINUX_SOLARIS_ACL_H
10
11
#include <linux/posix_acl.h>
12
13
u32 *nfs_acl_encode(u32 *, u32 *, struct inode *, struct posix_acl *, int, int);
14
u32 *nfs_acl_decode(u32 *, u32 *, unsigned int *, struct posix_acl **);
15
16
#endif  /* __LINUX_SOLARIS_ACL_H */
(-)linux-2.4.22-ppc-dev.orig/include/linux/sunrpc/svc.h (-1 / +2 lines)
Lines 131-139 Link Here
131
};
131
};
132
132
133
/*
133
/*
134
 * RPC program
134
 * List of RPC programs on the same transport endpoint
135
 */
135
 */
136
struct svc_program {
136
struct svc_program {
137
	struct svc_program *	pg_next;	/* other programs */
137
	u32			pg_prog;	/* program number */
138
	u32			pg_prog;	/* program number */
138
	unsigned int		pg_lovers;	/* lowest version */
139
	unsigned int		pg_lovers;	/* lowest version */
139
	unsigned int		pg_hivers;	/* lowest version */
140
	unsigned int		pg_hivers;	/* lowest version */
(-)linux-2.4.22-ppc-dev.orig/include/linux/sunrpc/xprt.h (+2 lines)
Lines 152-157 Link Here
152
				nocong	   : 1,	/* no congestion control */
152
				nocong	   : 1,	/* no congestion control */
153
				resvport   : 1, /* use a reserved port */
153
				resvport   : 1, /* use a reserved port */
154
				stream     : 1;	/* TCP */
154
				stream     : 1;	/* TCP */
155
	unsigned int		clients;	/* Number of clients using
156
						   this transport */
155
157
156
	/*
158
	/*
157
	 * State of TCP reply receive stuff
159
	 * State of TCP reply receive stuff
(-)linux-2.4.22-ppc-dev.orig/include/linux/xattr_acl.h (+50 lines)
Line 0 Link Here
1
/*
2
  File: linux/xattr_acl.h
3
4
  (extended attribute representation of access control lists)
5
6
  (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
7
*/
8
9
#ifndef _LINUX_XATTR_ACL_H
10
#define _LINUX_XATTR_ACL_H
11
12
#include <linux/posix_acl.h>
13
14
#define XATTR_NAME_ACL_ACCESS	"system.posix_acl_access"
15
#define XATTR_NAME_ACL_DEFAULT	"system.posix_acl_default"
16
17
#define XATTR_ACL_VERSION	0x0002
18
19
typedef struct {
20
	__u16		e_tag;
21
	__u16		e_perm;
22
	__u32		e_id;
23
} xattr_acl_entry;
24
25
typedef struct {
26
	__u32		a_version;
27
	xattr_acl_entry	a_entries[0];
28
} xattr_acl_header;
29
30
static inline size_t xattr_acl_size(int count)
31
{
32
	return sizeof(xattr_acl_header) + count * sizeof(xattr_acl_entry);
33
}
34
35
static inline int xattr_acl_count(size_t size)
36
{
37
	if (size < sizeof(xattr_acl_header))
38
		return -1;
39
	size -= sizeof(xattr_acl_header);
40
	if (size % sizeof(xattr_acl_entry))
41
		return -1;
42
	return size / sizeof(xattr_acl_entry);
43
}
44
45
struct posix_acl * posix_acl_from_xattr(const void *value, size_t size);
46
int posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size);
47
48
49
50
#endif /* _LINUX_XATTR_ACL_H */
(-)linux-2.4.22-ppc-dev.orig/kernel/Makefile (-1 / +1 lines)
Lines 9-15 Link Here
9
9
10
O_TARGET := kernel.o
10
O_TARGET := kernel.o
11
11
12
export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o cpufreq.o
12
export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o cpufreq.o fork.o
13
13
14
obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
14
obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
15
	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
15
	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
(-)linux-2.4.22-ppc-dev.orig/kernel/fork.c (+1 lines)
Lines 409-414 Link Here
409
{
409
{
410
	return __copy_fs_struct(old);
410
	return __copy_fs_struct(old);
411
}
411
}
412
EXPORT_SYMBOL(copy_fs_struct);
412
413
413
static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
414
static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
414
{
415
{
(-)linux-2.4.22-ppc-dev.orig/kernel/ksyms.c (-1 / +7 lines)
Lines 32-37 Link Here
32
#include <linux/genhd.h>
32
#include <linux/genhd.h>
33
#include <linux/blkpg.h>
33
#include <linux/blkpg.h>
34
#include <linux/swap.h>
34
#include <linux/swap.h>
35
#include <linux/cache_def.h>
35
#include <linux/ctype.h>
36
#include <linux/ctype.h>
36
#include <linux/file.h>
37
#include <linux/file.h>
37
#include <linux/iobuf.h>
38
#include <linux/iobuf.h>
Lines 109-114 Link Here
109
EXPORT_SYMBOL(kmem_cache_alloc);
110
EXPORT_SYMBOL(kmem_cache_alloc);
110
EXPORT_SYMBOL(kmem_cache_free);
111
EXPORT_SYMBOL(kmem_cache_free);
111
EXPORT_SYMBOL(kmem_cache_size);
112
EXPORT_SYMBOL(kmem_cache_size);
113
EXPORT_SYMBOL(register_cache);
114
EXPORT_SYMBOL(unregister_cache);
112
EXPORT_SYMBOL(kmalloc);
115
EXPORT_SYMBOL(kmalloc);
113
EXPORT_SYMBOL(kfree);
116
EXPORT_SYMBOL(kfree);
114
EXPORT_SYMBOL(vfree);
117
EXPORT_SYMBOL(vfree);
Lines 342-348 Link Here
342
EXPORT_SYMBOL(do_SAK);
345
EXPORT_SYMBOL(do_SAK);
343
346
344
/* filesystem registration */
347
/* filesystem registration */
345
EXPORT_SYMBOL(register_filesystem);
348
EXPORT_SYMBOL(__register_filesystem);
346
EXPORT_SYMBOL(unregister_filesystem);
349
EXPORT_SYMBOL(unregister_filesystem);
347
EXPORT_SYMBOL(kern_mount);
350
EXPORT_SYMBOL(kern_mount);
348
EXPORT_SYMBOL(__mntput);
351
EXPORT_SYMBOL(__mntput);
Lines 565-570 Link Here
565
EXPORT_SYMBOL(strnicmp);
568
EXPORT_SYMBOL(strnicmp);
566
EXPORT_SYMBOL(strspn);
569
EXPORT_SYMBOL(strspn);
567
EXPORT_SYMBOL(strsep);
570
EXPORT_SYMBOL(strsep);
571
#if defined(CONFIG_QSORT) && ! defined(CONFIG_QSORT_MODULE)
572
EXPORT_SYMBOL(qsort);
573
#endif
568
574
569
#ifdef CONFIG_CRC32
575
#ifdef CONFIG_CRC32
570
EXPORT_SYMBOL(crc32_le);
576
EXPORT_SYMBOL(crc32_le);
(-)linux-2.4.22-ppc-dev.orig/lib/Config.in (+2 lines)
Lines 41-44 Link Here
41
  fi
41
  fi
42
fi
42
fi
43
43
44
tristate 'Quick Sort' CONFIG_QSORT
45
44
endmenu
46
endmenu
(-)linux-2.4.22-ppc-dev.orig/lib/Makefile (-1 / +2 lines)
Lines 9-21 Link Here
9
L_TARGET := lib.a
9
L_TARGET := lib.a
10
10
11
export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o \
11
export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o \
12
	       rbtree.o crc32.o
12
	       rbtree.o crc32.o qsort.o
13
13
14
obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
14
obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
15
	 bust_spinlocks.o rbtree.o dump_stack.o
15
	 bust_spinlocks.o rbtree.o dump_stack.o
16
16
17
obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
17
obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
18
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
18
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
19
obj-$(CONFIG_QSORT) += qsort.o
19
20
20
ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
21
ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
21
  obj-y += dec_and_lock.o
22
  obj-y += dec_and_lock.o
(-)linux-2.4.22-ppc-dev.orig/lib/qsort.c (+254 lines)
Line 0 Link Here
1
/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
2
   This file is part of the GNU C Library.
3
   Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
4
5
   The GNU C Library is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU Lesser General Public
7
   License as published by the Free Software Foundation; either
8
   version 2.1 of the License, or (at your option) any later version.
9
10
   The GNU C Library is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Lesser General Public License for more details.
14
15
   You should have received a copy of the GNU Lesser General Public
16
   License along with the GNU C Library; if not, write to the Free
17
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
   02111-1307 USA.  */
19
20
/* If you consider tuning this algorithm, you should consult first:
21
   Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
22
   Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993.  */
23
24
# include <linux/module.h>
25
# include <linux/slab.h>
26
# include <linux/string.h>
27
28
MODULE_LICENSE("GPL");
29
30
/* Byte-wise swap two items of size SIZE. */
31
#define SWAP(a, b, size)						      \
32
  do									      \
33
    {									      \
34
      register size_t __size = (size);					      \
35
      register char *__a = (a), *__b = (b);				      \
36
      do								      \
37
	{								      \
38
	  char __tmp = *__a;						      \
39
	  *__a++ = *__b;						      \
40
	  *__b++ = __tmp;						      \
41
	} while (--__size > 0);						      \
42
    } while (0)
43
44
/* Discontinue quicksort algorithm when partition gets below this size.
45
   This particular magic number was chosen to work best on a Sun 4/260. */
46
#define MAX_THRESH 4
47
48
/* Stack node declarations used to store unfulfilled partition obligations. */
49
typedef struct
50
  {
51
    char *lo;
52
    char *hi;
53
  } stack_node;
54
55
/* The next 5 #defines implement a very fast in-line stack abstraction. */
56
/* The stack needs log (total_elements) entries (we could even subtract
57
   log(MAX_THRESH)).  Since total_elements has type size_t, we get as
58
   upper bound for log (total_elements):
59
   bits per byte (CHAR_BIT) * sizeof(size_t).  */
60
#define CHAR_BIT 8
61
#define STACK_SIZE	(CHAR_BIT * sizeof(size_t))
62
#define PUSH(low, high)	((void) ((top->lo = (low)), (top->hi = (high)), ++top))
63
#define	POP(low, high)	((void) (--top, (low = top->lo), (high = top->hi)))
64
#define	STACK_NOT_EMPTY	(stack < top)
65
66
67
/* Order size using quicksort.  This implementation incorporates
68
   four optimizations discussed in Sedgewick:
69
70
   1. Non-recursive, using an explicit stack of pointer that store the
71
      next array partition to sort.  To save time, this maximum amount
72
      of space required to store an array of SIZE_MAX is allocated on the
73
      stack.  Assuming a 32-bit (64 bit) integer for size_t, this needs
74
      only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
75
      Pretty cheap, actually.
76
77
   2. Chose the pivot element using a median-of-three decision tree.
78
      This reduces the probability of selecting a bad pivot value and
79
      eliminates certain extraneous comparisons.
80
81
   3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
82
      insertion sort to order the MAX_THRESH items within each partition.
83
      This is a big win, since insertion sort is faster for small, mostly
84
      sorted array segments.
85
86
   4. The larger of the two sub-partitions is always pushed onto the
87
      stack first, with the algorithm then concentrating on the
88
      smaller partition.  This *guarantees* no more than log (total_elems)
89
      stack size is needed (actually O(1) in this case)!  */
90
91
void
92
qsort(void *const pbase, size_t total_elems, size_t size,
93
      int(*cmp)(const void *,const void *))
94
{
95
  register char *base_ptr = (char *) pbase;
96
97
  const size_t max_thresh = MAX_THRESH * size;
98
99
  if (total_elems == 0)
100
    /* Avoid lossage with unsigned arithmetic below.  */
101
    return;
102
103
  if (total_elems > MAX_THRESH)
104
    {
105
      char *lo = base_ptr;
106
      char *hi = &lo[size * (total_elems - 1)];
107
      stack_node stack[STACK_SIZE];
108
      stack_node *top = stack + 1;
109
110
      while (STACK_NOT_EMPTY)
111
        {
112
          char *left_ptr;
113
          char *right_ptr;
114
115
	  /* Select median value from among LO, MID, and HI. Rearrange
116
	     LO and HI so the three values are sorted. This lowers the
117
	     probability of picking a pathological pivot value and
118
	     skips a comparison for both the LEFT_PTR and RIGHT_PTR in
119
	     the while loops. */
120
121
	  char *mid = lo + size * ((hi - lo) / size >> 1);
122
123
	  if ((*cmp) ((void *) mid, (void *) lo) < 0)
124
	    SWAP (mid, lo, size);
125
	  if ((*cmp) ((void *) hi, (void *) mid) < 0)
126
	    SWAP (mid, hi, size);
127
	  else
128
	    goto jump_over;
129
	  if ((*cmp) ((void *) mid, (void *) lo) < 0)
130
	    SWAP (mid, lo, size);
131
	jump_over:;
132
133
	  left_ptr  = lo + size;
134
	  right_ptr = hi - size;
135
136
	  /* Here's the famous ``collapse the walls'' section of quicksort.
137
	     Gotta like those tight inner loops!  They are the main reason
138
	     that this algorithm runs much faster than others. */
139
	  do
140
	    {
141
	      while ((*cmp) ((void *) left_ptr, (void *) mid) < 0)
142
		left_ptr += size;
143
144
	      while ((*cmp) ((void *) mid, (void *) right_ptr) < 0)
145
		right_ptr -= size;
146
147
	      if (left_ptr < right_ptr)
148
		{
149
		  SWAP (left_ptr, right_ptr, size);
150
		  if (mid == left_ptr)
151
		    mid = right_ptr;
152
		  else if (mid == right_ptr)
153
		    mid = left_ptr;
154
		  left_ptr += size;
155
		  right_ptr -= size;
156
		}
157
	      else if (left_ptr == right_ptr)
158
		{
159
		  left_ptr += size;
160
		  right_ptr -= size;
161
		  break;
162
		}
163
	    }
164
	  while (left_ptr <= right_ptr);
165
166
          /* Set up pointers for next iteration.  First determine whether
167
             left and right partitions are below the threshold size.  If so,
168
             ignore one or both.  Otherwise, push the larger partition's
169
             bounds on the stack and continue sorting the smaller one. */
170
171
          if ((size_t) (right_ptr - lo) <= max_thresh)
172
            {
173
              if ((size_t) (hi - left_ptr) <= max_thresh)
174
		/* Ignore both small partitions. */
175
                POP (lo, hi);
176
              else
177
		/* Ignore small left partition. */
178
                lo = left_ptr;
179
            }
180
          else if ((size_t) (hi - left_ptr) <= max_thresh)
181
	    /* Ignore small right partition. */
182
            hi = right_ptr;
183
          else if ((right_ptr - lo) > (hi - left_ptr))
184
            {
185
	      /* Push larger left partition indices. */
186
              PUSH (lo, right_ptr);
187
              lo = left_ptr;
188
            }
189
          else
190
            {
191
	      /* Push larger right partition indices. */
192
              PUSH (left_ptr, hi);
193
              hi = right_ptr;
194
            }
195
        }
196
    }
197
198
  /* Once the BASE_PTR array is partially sorted by quicksort the rest
199
     is completely sorted using insertion sort, since this is efficient
200
     for partitions below MAX_THRESH size. BASE_PTR points to the beginning
201
     of the array to sort, and END_PTR points at the very last element in
202
     the array (*not* one beyond it!). */
203
204
  {
205
    char *end_ptr = &base_ptr[size * (total_elems - 1)];
206
    char *tmp_ptr = base_ptr;
207
    char *thresh = min(end_ptr, base_ptr + max_thresh);
208
    register char *run_ptr;
209
210
    /* Find smallest element in first threshold and place it at the
211
       array's beginning.  This is the smallest array element,
212
       and the operation speeds up insertion sort's inner loop. */
213
214
    for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
215
      if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
216
        tmp_ptr = run_ptr;
217
218
    if (tmp_ptr != base_ptr)
219
      SWAP (tmp_ptr, base_ptr, size);
220
221
    /* Insertion sort, running from left-hand-side up to right-hand-side.  */
222
223
    run_ptr = base_ptr + size;
224
    while ((run_ptr += size) <= end_ptr)
225
      {
226
	tmp_ptr = run_ptr - size;
227
	while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
228
	  tmp_ptr -= size;
229
230
	tmp_ptr += size;
231
        if (tmp_ptr != run_ptr)
232
          {
233
            char *trav;
234
235
	    trav = run_ptr + size;
236
	    while (--trav >= run_ptr)
237
              {
238
                char c = *trav;
239
                char *hi, *lo;
240
241
                for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
242
                  *hi = *lo;
243
                *hi = c;
244
              }
245
          }
246
      }
247
  }
248
}
249
/* If qsort is built into the kernel, we export the qsort symbol in
250
   kernel/ksyms.c: The files in lib/ end up in lib.a, so qsort.o only
251
   gets linked into the kernel image if it is used somewhere.  */
252
#if defined(CONFIG_QSORT_MODULE)
253
EXPORT_SYMBOL(qsort);
254
#endif
(-)linux-2.4.22-ppc-dev.orig/mm/vmscan.c (+45 lines)
Lines 18-23 Link Here
18
#include <linux/kernel_stat.h>
18
#include <linux/kernel_stat.h>
19
#include <linux/swap.h>
19
#include <linux/swap.h>
20
#include <linux/swapctl.h>
20
#include <linux/swapctl.h>
21
#include <linux/cache_def.h>
21
#include <linux/smp_lock.h>
22
#include <linux/smp_lock.h>
22
#include <linux/pagemap.h>
23
#include <linux/pagemap.h>
23
#include <linux/init.h>
24
#include <linux/init.h>
Lines 35-40 Link Here
35
#define DEF_PRIORITY (6)
36
#define DEF_PRIORITY (6)
36
37
37
/*
38
/*
39
 * Handling of caches defined in drivers, filesystems, ...
40
 *
41
 * The cache definition contains a callback for shrinking 
42
 * the cache.
43
 *
44
 * The [un]register_cache() functions may only be called when
45
 * the kernel lock is held. The shrink() functions are also
46
 * called with the kernel lock held.
47
 */
48
static DECLARE_MUTEX(other_caches_sem);
49
static LIST_HEAD(other_caches);
50
51
void register_cache(struct cache_definition *cache)
52
{
53
	down(&other_caches_sem);
54
	list_add(&cache->link, &other_caches);
55
	up(&other_caches_sem);
56
}
57
58
void unregister_cache(struct cache_definition *cache)
59
{
60
	down(&other_caches_sem);
61
	list_del(&cache->link);
62
	up(&other_caches_sem);
63
}
64
65
static void shrink_other_caches(unsigned int priority, int gfp_mask)
66
{
67
	struct list_head *p;
68
69
	if (down_trylock(&other_caches_sem))
70
		return;
71
72
	list_for_each_prev(p, &other_caches) {
73
		struct cache_definition *cache =
74
			list_entry(p, struct cache_definition, link);
75
76
		cache->shrink(priority, gfp_mask);
77
	}
78
	up(&other_caches_sem);
79
}
80
81
/*
38
 * The swap-out function returns 1 if it successfully
82
 * The swap-out function returns 1 if it successfully
39
 * scanned all the pages it was asked to (`count').
83
 * scanned all the pages it was asked to (`count').
40
 * It returns zero if it couldn't do anything,
84
 * It returns zero if it couldn't do anything,
Lines 580-585 Link Here
580
#ifdef CONFIG_QUOTA
624
#ifdef CONFIG_QUOTA
581
	shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
625
	shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
582
#endif
626
#endif
627
	shrink_other_caches(priority, gfp_mask);
583
628
584
	return nr_pages;
629
	return nr_pages;
585
}
630
}
(-)linux-2.4.22-ppc-dev.orig/net/sunrpc/clnt.c (-1 / +13 lines)
Lines 89-94 Link Here
89
	memset(clnt, 0, sizeof(*clnt));
89
	memset(clnt, 0, sizeof(*clnt));
90
	atomic_set(&clnt->cl_users, 0);
90
	atomic_set(&clnt->cl_users, 0);
91
91
92
	xprt->clients++;
93
92
	clnt->cl_xprt     = xprt;
94
	clnt->cl_xprt     = xprt;
93
	clnt->cl_procinfo = version->procs;
95
	clnt->cl_procinfo = version->procs;
94
	clnt->cl_maxproc  = version->nrprocs;
96
	clnt->cl_maxproc  = version->nrprocs;
Lines 166-172 Link Here
166
		rpcauth_destroy(clnt->cl_auth);
168
		rpcauth_destroy(clnt->cl_auth);
167
		clnt->cl_auth = NULL;
169
		clnt->cl_auth = NULL;
168
	}
170
	}
169
	if (clnt->cl_xprt) {
171
	if (clnt->cl_xprt && !(--clnt->cl_xprt->clients)) {
170
		xprt_destroy(clnt->cl_xprt);
172
		xprt_destroy(clnt->cl_xprt);
171
		clnt->cl_xprt = NULL;
173
		clnt->cl_xprt = NULL;
172
	}
174
	}
Lines 923-928 Link Here
923
		return p;
925
		return p;
924
	case RPC_GARBAGE_ARGS:
926
	case RPC_GARBAGE_ARGS:
925
		break;			/* retry */
927
		break;			/* retry */
928
	case RPC_PROG_UNAVAIL:
929
		/* report requested program number*/
930
		dprintk(KERN_WARNING "RPC: unknown program\n");
931
		rpc_exit(task, -ENOSYS);
932
		return NULL;
933
	case RPC_PROC_UNAVAIL:
934
		/* report requested program and procedure number, version */
935
		dprintk(KERN_WARNING "RPC: unknown procedure\n");
936
		rpc_exit(task, -ENOSYS);
937
		return NULL;
926
	default:
938
	default:
927
		printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
939
		printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
928
		/* Also retry */
940
		/* Also retry */
(-)linux-2.4.22-ppc-dev.orig/net/sunrpc/svc.c (-5 / +5 lines)
Lines 281-288 Link Here
281
	if (auth_stat != rpc_auth_ok)
281
	if (auth_stat != rpc_auth_ok)
282
		goto err_bad_auth;
282
		goto err_bad_auth;
283
283
284
	progp = serv->sv_program;
284
	for (progp = serv->sv_program; progp; progp = progp->pg_next)
285
	if (prog != progp->pg_prog)
285
		if (prog == progp->pg_prog)
286
			break;
287
	if (progp == NULL)
286
		goto err_bad_prog;
288
		goto err_bad_prog;
287
289
288
	if (vers >= progp->pg_nvers ||
290
	if (vers >= progp->pg_nvers ||
Lines 390-398 Link Here
390
392
391
err_bad_prog:
393
err_bad_prog:
392
#ifdef RPC_PARANOIA
394
#ifdef RPC_PARANOIA
393
	if (prog != 100227 || progp->pg_prog != 100003)
395
	printk("svc: unknown program %d\n", prog);
394
		printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog);
395
	/* else it is just a Solaris client seeing if ACLs are supported */
396
#endif
396
#endif
397
	serv->sv_stats->rpcbadfmt++;
397
	serv->sv_stats->rpcbadfmt++;
398
	svc_putlong(resp, rpc_prog_unavail);
398
	svc_putlong(resp, rpc_prog_unavail);

Return to bug 35819