aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@tglx.tec.linutronix.de>2005-06-26 17:20:36 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-06-26 17:20:36 -0400
commit7ca6448dbfb398bba36eda3c01bc14b86c3675be (patch)
tree82d934ebf07f22a2c64c3b6d82ec24082878b43a /fs
parentf1f67a9874f1a4bba1adff6d694aa52e5f52ff1a (diff)
parent7d681b23d6cc14a8c026ea6756242cb522cbbcae (diff)
Merge with rsync://fileserver/linux
Update to Linus latest
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig110
-rw-r--r--fs/Makefile1
-rw-r--r--fs/afs/kafsasyncd.c2
-rw-r--r--fs/afs/kafstimod.c2
-rw-r--r--fs/autofs4/autofs_i.h13
-rw-r--r--fs/autofs4/expire.c5
-rw-r--r--fs/autofs4/root.c15
-rw-r--r--fs/autofs4/waitq.c7
-rw-r--r--fs/binfmt_aout.c1
-rw-r--r--fs/binfmt_elf.c3
-rw-r--r--fs/binfmt_flat.c6
-rw-r--r--fs/block_dev.c5
-rw-r--r--fs/buffer.c59
-rw-r--r--fs/char_dev.c13
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/README4
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c56
-rw-r--r--fs/cifs/dir.c3
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c48
-rw-r--r--fs/cifs/misc.c1
-rw-r--r--fs/coda/psdev.c18
-rw-r--r--fs/debugfs/file.c67
-rw-r--r--fs/debugfs/inode.c12
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/dquot.c23
-rw-r--r--fs/eventpoll.c195
-rw-r--r--fs/exec.c39
-rw-r--r--fs/ext2/Makefile1
-rw-r--r--fs/ext2/acl.c12
-rw-r--r--fs/ext2/acl.h2
-rw-r--r--fs/ext2/ext2.h2
-rw-r--r--fs/ext2/file.c14
-rw-r--r--fs/ext2/inode.c31
-rw-r--r--fs/ext2/namei.c12
-rw-r--r--fs/ext2/super.c27
-rw-r--r--fs/ext2/xip.c80
-rw-r--r--fs/ext2/xip.h25
-rw-r--r--fs/ext3/acl.c17
-rw-r--r--fs/ext3/acl.h2
-rw-r--r--fs/ext3/inode.c7
-rw-r--r--fs/ext3/namei.c37
-rw-r--r--fs/ext3/super.c55
-rw-r--r--fs/ext3/xattr.c2
-rw-r--r--fs/file_table.c57
-rw-r--r--fs/fs-writeback.c64
-rw-r--r--fs/hostfs/hostfs_kern.c1
-rw-r--r--fs/hugetlbfs/inode.c3
-rw-r--r--fs/inode.c16
-rw-r--r--fs/isofs/dir.c17
-rw-r--r--fs/isofs/inode.c128
-rw-r--r--fs/isofs/isofs.h2
-rw-r--r--fs/isofs/namei.c16
-rw-r--r--fs/isofs/rock.c962
-rw-r--r--fs/isofs/rock.h183
-rw-r--r--fs/jbd/checkpoint.c5
-rw-r--r--fs/jbd/journal.c4
-rw-r--r--fs/jffs/intrep.c114
-rw-r--r--fs/jffs/intrep.h2
-rw-r--r--fs/jffs/jffs_fm.c105
-rw-r--r--fs/jffs/jffs_fm.h3
-rw-r--r--fs/jffs2/background.c2
-rw-r--r--fs/jfs/acl.c17
-rw-r--r--fs/jfs/file.c9
-rw-r--r--fs/jfs/inode.c11
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/jfs/jfs_debug.c10
-rw-r--r--fs/jfs/jfs_debug.h15
-rw-r--r--fs/jfs/jfs_dmap.c9
-rw-r--r--fs/jfs/jfs_dtree.c3
-rw-r--r--fs/jfs/jfs_extent.c7
-rw-r--r--fs/jfs/jfs_imap.c6
-rw-r--r--fs/jfs/jfs_inode.c1
-rw-r--r--fs/jfs/jfs_inode.h19
-rw-r--r--fs/jfs/jfs_logmgr.c18
-rw-r--r--fs/jfs/jfs_logmgr.h2
-rw-r--r--fs/jfs/jfs_metapage.c6
-rw-r--r--fs/jfs/jfs_metapage.h6
-rw-r--r--fs/jfs/jfs_superblock.h11
-rw-r--r--fs/jfs/jfs_txnmgr.c48
-rw-r--r--fs/jfs/jfs_txnmgr.h52
-rw-r--r--fs/jfs/namei.c28
-rw-r--r--fs/jfs/super.c38
-rw-r--r--fs/jfs/symlink.c3
-rw-r--r--fs/jfs/xattr.c13
-rw-r--r--fs/libfs.c101
-rw-r--r--fs/lockd/clntlock.c113
-rw-r--r--fs/lockd/clntproc.c42
-rw-r--r--fs/lockd/host.c8
-rw-r--r--fs/lockd/mon.c7
-rw-r--r--fs/lockd/svc.c4
-rw-r--r--fs/locks.c6
-rw-r--r--fs/mpage.c5
-rw-r--r--fs/namei.c173
-rw-r--r--fs/namespace.c2
-rw-r--r--fs/ncpfs/dir.c13
-rw-r--r--fs/ncpfs/ncplib_kernel.c40
-rw-r--r--fs/ncpfs/ncplib_kernel.h3
-rw-r--r--fs/nfs/Makefile1
-rw-r--r--fs/nfs/callback.c1
-rw-r--r--fs/nfs/callback_proc.c1
-rw-r--r--fs/nfs/callback_xdr.c2
-rw-r--r--fs/nfs/delegation.c1
-rw-r--r--fs/nfs/dir.c209
-rw-r--r--fs/nfs/direct.c7
-rw-r--r--fs/nfs/file.c88
-rw-r--r--fs/nfs/idmap.c1
-rw-r--r--fs/nfs/inode.c427
-rw-r--r--fs/nfs/mount_clnt.c4
-rw-r--r--fs/nfs/nfs3acl.c403
-rw-r--r--fs/nfs/nfs3proc.c43
-rw-r--r--fs/nfs/nfs3xdr.c147
-rw-r--r--fs/nfs/nfs4_fs.h253
-rw-r--r--fs/nfs/nfs4proc.c429
-rw-r--r--fs/nfs/nfs4renewd.c1
-rw-r--r--fs/nfs/nfs4state.c193
-rw-r--r--fs/nfs/nfs4xdr.c241
-rw-r--r--fs/nfs/nfsroot.c9
-rw-r--r--fs/nfs/pagelist.c142
-rw-r--r--fs/nfs/proc.c1
-rw-r--r--fs/nfs/read.c3
-rw-r--r--fs/nfs/write.c108
-rw-r--r--fs/nfs_common/Makefile7
-rw-r--r--fs/nfs_common/nfsacl.c257
-rw-r--r--fs/nfsd/Makefile4
-rw-r--r--fs/nfsd/nfs2acl.c336
-rw-r--r--fs/nfsd/nfs3acl.c267
-rw-r--r--fs/nfsd/nfs3xdr.c13
-rw-r--r--fs/nfsd/nfs4acl.c4
-rw-r--r--fs/nfsd/nfs4callback.c17
-rw-r--r--fs/nfsd/nfs4idmap.c12
-rw-r--r--fs/nfsd/nfs4proc.c26
-rw-r--r--fs/nfsd/nfs4recover.c431
-rw-r--r--fs/nfsd/nfs4state.c1028
-rw-r--r--fs/nfsd/nfs4xdr.c11
-rw-r--r--fs/nfsd/nfsctl.c28
-rw-r--r--fs/nfsd/nfsproc.c1
-rw-r--r--fs/nfsd/nfssvc.c30
-rw-r--r--fs/nfsd/nfsxdr.c11
-rw-r--r--fs/nfsd/vfs.c116
-rw-r--r--fs/open.c45
-rw-r--r--fs/partitions/Makefile1
-rw-r--r--fs/partitions/check.c3
-rw-r--r--fs/partitions/check.h4
-rw-r--r--fs/partitions/msdos.c4
-rw-r--r--fs/proc/Makefile1
-rw-r--r--fs/proc/base.c6
-rw-r--r--fs/proc/proc_devtree.c105
-rw-r--r--fs/proc/proc_misc.c22
-rw-r--r--fs/proc/vmcore.c669
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/qnx4/inode.c4
-rw-r--r--fs/quota.c60
-rw-r--r--fs/read_write.c20
-rw-r--r--fs/reiserfs/file.c4
-rw-r--r--fs/reiserfs/inode.c28
-rw-r--r--fs/reiserfs/journal.c2
-rw-r--r--fs/reiserfs/namei.c25
-rw-r--r--fs/reiserfs/stree.c2
-rw-r--r--fs/reiserfs/super.c102
-rw-r--r--fs/reiserfs/xattr_acl.c26
-rw-r--r--fs/super.c84
-rw-r--r--fs/sysfs/bin.c4
-rw-r--r--fs/sysfs/dir.c31
-rw-r--r--fs/sysfs/file.c16
-rw-r--r--fs/sysfs/group.c4
-rw-r--r--fs/sysfs/inode.c112
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/symlink.c8
-rw-r--r--fs/sysfs/sysfs.h5
-rw-r--r--fs/udf/udftime.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c157
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c34
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c29
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h12
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c34
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c17
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h2
-rw-r--r--fs/xfs/quota/xfs_dquot.c105
-rw-r--r--fs/xfs/quota/xfs_dquot.h30
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c6
-rw-r--r--fs/xfs/quota/xfs_qm.c202
-rw-r--r--fs/xfs/quota/xfs_qm.h16
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c43
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c175
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h15
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c60
-rw-r--r--fs/xfs/support/debug.c1
-rw-r--r--fs/xfs/support/debug.h7
-rw-r--r--fs/xfs/xfs_alloc.c4
-rw-r--r--fs/xfs/xfs_attr.c17
-rw-r--r--fs/xfs/xfs_attr.h7
-rw-r--r--fs/xfs/xfs_attr_leaf.c28
-rw-r--r--fs/xfs/xfs_attr_leaf.h12
-rw-r--r--fs/xfs/xfs_bit.c2
-rw-r--r--fs/xfs/xfs_bmap.c127
-rw-r--r--fs/xfs/xfs_bmap.h13
-rw-r--r--fs/xfs/xfs_bmap_btree.c14
-rw-r--r--fs/xfs/xfs_bmap_btree.h8
-rw-r--r--fs/xfs/xfs_btree.c12
-rw-r--r--fs/xfs/xfs_btree.h10
-rw-r--r--fs/xfs/xfs_buf_item.c24
-rw-r--r--fs/xfs/xfs_buf_item.h2
-rw-r--r--fs/xfs/xfs_da_btree.c9
-rw-r--r--fs/xfs/xfs_da_btree.h3
-rw-r--r--fs/xfs/xfs_dfrag.c7
-rw-r--r--fs/xfs/xfs_dir2_data.c2
-rw-r--r--fs/xfs/xfs_dir2_data.h4
-rw-r--r--fs/xfs/xfs_dir2_leaf.c8
-rw-r--r--fs/xfs/xfs_dir2_leaf.h7
-rw-r--r--fs/xfs/xfs_dir_leaf.c6
-rw-r--r--fs/xfs/xfs_dir_leaf.h2
-rw-r--r--fs/xfs/xfs_dmapi.h19
-rw-r--r--fs/xfs/xfs_error.c2
-rw-r--r--fs/xfs/xfs_error.h3
-rw-r--r--fs/xfs/xfs_extfree_item.c126
-rw-r--r--fs/xfs/xfs_extfree_item.h2
-rw-r--r--fs/xfs/xfs_fs.h3
-rw-r--r--fs/xfs/xfs_fsops.c26
-rw-r--r--fs/xfs/xfs_ialloc_btree.h8
-rw-r--r--fs/xfs/xfs_inode.c185
-rw-r--r--fs/xfs/xfs_inode.h9
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_iomap.c69
-rw-r--r--fs/xfs/xfs_log.c6
-rw-r--r--fs/xfs/xfs_log_priv.h2
-rw-r--r--fs/xfs/xfs_log_recover.c31
-rw-r--r--fs/xfs/xfs_macros.c5
-rw-r--r--fs/xfs/xfs_mount.c16
-rw-r--r--fs/xfs/xfs_mount.h7
-rw-r--r--fs/xfs/xfs_quota.h72
-rw-r--r--fs/xfs/xfs_rename.c18
-rw-r--r--fs/xfs/xfs_trans.c21
-rw-r--r--fs/xfs/xfs_trans.h3
-rw-r--r--fs/xfs/xfs_trans_buf.c1
-rw-r--r--fs/xfs/xfs_trans_inode.c18
-rw-r--r--fs/xfs/xfs_types.h2
-rw-r--r--fs/xfs/xfs_utils.c2
-rw-r--r--fs/xfs/xfs_vfsops.c74
-rw-r--r--fs/xfs/xfs_vnodeops.c95
249 files changed, 8353 insertions, 4075 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 475769c25d64..8d50a610c0e0 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -50,6 +50,23 @@ config EXT2_FS_SECURITY
50 If you are not using a security module that requires using 50 If you are not using a security module that requires using
51 extended attributes for file security labels, say N. 51 extended attributes for file security labels, say N.
52 52
53config EXT2_FS_XIP
54 bool "Ext2 execute in place support"
55 depends on EXT2_FS
56 help
57 Execute in place can be used on memory-backed block devices. If you
58 enable this option, you can select to mount block devices which are
59 capable of this feature without using the page cache.
60
61 If you do not use a block device that is capable of using this,
62 or if unsure, say N.
63
64config FS_XIP
65# execute in place
66 bool
67 depends on EXT2_FS_XIP
68 default y
69
53config EXT3_FS 70config EXT3_FS
54 tristate "Ext3 journalling file system support" 71 tristate "Ext3 journalling file system support"
55 help 72 help
@@ -717,6 +734,12 @@ config PROC_KCORE
717 bool "/proc/kcore support" if !ARM 734 bool "/proc/kcore support" if !ARM
718 depends on PROC_FS && MMU 735 depends on PROC_FS && MMU
719 736
737config PROC_VMCORE
738 bool "/proc/vmcore support (EXPERIMENTAL)"
739 depends on PROC_FS && EMBEDDED && EXPERIMENTAL && CRASH_DUMP
740 help
741 Exports the dump image of crashed kernel in ELF format.
742
720config SYSFS 743config SYSFS
721 bool "sysfs file system support" if EMBEDDED 744 bool "sysfs file system support" if EMBEDDED
722 default y 745 default y
@@ -741,56 +764,6 @@ config SYSFS
741 764
742 Designers of embedded systems may wish to say N here to conserve space. 765 Designers of embedded systems may wish to say N here to conserve space.
743 766
744config DEVFS_FS
745 bool "/dev file system support (OBSOLETE)"
746 depends on EXPERIMENTAL
747 help
748 This is support for devfs, a virtual file system (like /proc) which
749 provides the file system interface to device drivers, normally found
750 in /dev. Devfs does not depend on major and minor number
751 allocations. Device drivers register entries in /dev which then
752 appear automatically, which means that the system administrator does
753 not have to create character and block special device files in the
754 /dev directory using the mknod command (or MAKEDEV script) anymore.
755
756 This is work in progress. If you want to use this, you *must* read
757 the material in <file:Documentation/filesystems/devfs/>, especially
758 the file README there.
759
760 Note that devfs no longer manages /dev/pts! If you are using UNIX98
761 ptys, you will also need to mount the /dev/pts filesystem (devpts).
762
763 Note that devfs has been obsoleted by udev,
764 <http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
765 It has been stripped down to a bare minimum and is only provided for
766 legacy installations that use its naming scheme which is
767 unfortunately different from the names normal Linux installations
768 use.
769
770 If unsure, say N.
771
772config DEVFS_MOUNT
773 bool "Automatically mount at boot"
774 depends on DEVFS_FS
775 help
776 This option appears if you have CONFIG_DEVFS_FS enabled. Setting
777 this to 'Y' will make the kernel automatically mount devfs onto /dev
778 when the system is booted, before the init thread is started.
779 You can override this with the "devfs=nomount" boot option.
780
781 If unsure, say N.
782
783config DEVFS_DEBUG
784 bool "Debug devfs"
785 depends on DEVFS_FS
786 help
787 If you say Y here, then the /dev file system code will generate
788 debugging messages. See the file
789 <file:Documentation/filesystems/devfs/boot-options> for more
790 details.
791
792 If unsure, say N.
793
794config DEVPTS_FS_XATTR 767config DEVPTS_FS_XATTR
795 bool "/dev/pts Extended Attributes" 768 bool "/dev/pts Extended Attributes"
796 depends on UNIX98_PTYS 769 depends on UNIX98_PTYS
@@ -1310,6 +1283,7 @@ config NFS_FS
1310 depends on INET 1283 depends on INET
1311 select LOCKD 1284 select LOCKD
1312 select SUNRPC 1285 select SUNRPC
1286 select NFS_ACL_SUPPORT if NFS_V3_ACL
1313 help 1287 help
1314 If you are connected to some other (usually local) Unix computer 1288 If you are connected to some other (usually local) Unix computer
1315 (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing 1289 (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
@@ -1352,6 +1326,16 @@ config NFS_V3
1352 1326
1353 If unsure, say Y. 1327 If unsure, say Y.
1354 1328
1329config NFS_V3_ACL
1330 bool "Provide client support for the NFSv3 ACL protocol extension"
1331 depends on NFS_V3
1332 help
1333 Implement the NFSv3 ACL protocol extension for manipulating POSIX
1334 Access Control Lists. The server should also be compiled with
1335 the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option.
1336
1337 If unsure, say N.
1338
1355config NFS_V4 1339config NFS_V4
1356 bool "Provide NFSv4 client support (EXPERIMENTAL)" 1340 bool "Provide NFSv4 client support (EXPERIMENTAL)"
1357 depends on NFS_FS && EXPERIMENTAL 1341 depends on NFS_FS && EXPERIMENTAL
@@ -1395,6 +1379,7 @@ config NFSD
1395 select LOCKD 1379 select LOCKD
1396 select SUNRPC 1380 select SUNRPC
1397 select EXPORTFS 1381 select EXPORTFS
1382 select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL
1398 help 1383 help
1399 If you want your Linux box to act as an NFS *server*, so that other 1384 If you want your Linux box to act as an NFS *server*, so that other
1400 computers on your local network which support NFS can access certain 1385 computers on your local network which support NFS can access certain
@@ -1418,6 +1403,10 @@ config NFSD
1418 To compile the NFS server support as a module, choose M here: the 1403 To compile the NFS server support as a module, choose M here: the
1419 module will be called nfsd. If unsure, say N. 1404 module will be called nfsd. If unsure, say N.
1420 1405
1406config NFSD_V2_ACL
1407 bool
1408 depends on NFSD
1409
1421config NFSD_V3 1410config NFSD_V3
1422 bool "Provide NFSv3 server support" 1411 bool "Provide NFSv3 server support"
1423 depends on NFSD 1412 depends on NFSD
@@ -1425,10 +1414,22 @@ config NFSD_V3
1425 If you would like to include the NFSv3 server as well as the NFSv2 1414 If you would like to include the NFSv3 server as well as the NFSv2
1426 server, say Y here. If unsure, say Y. 1415 server, say Y here. If unsure, say Y.
1427 1416
1417config NFSD_V3_ACL
1418 bool "Provide server support for the NFSv3 ACL protocol extension"
1419 depends on NFSD_V3
1420 select NFSD_V2_ACL
1421 help
1422 Implement the NFSv3 ACL protocol extension for manipulating POSIX
1423 Access Control Lists on exported file systems. NFS clients should
1424 be compiled with the NFSv3 ACL protocol extension; see the
1425 CONFIG_NFS_V3_ACL option. If unsure, say N.
1426
1428config NFSD_V4 1427config NFSD_V4
1429 bool "Provide NFSv4 server support (EXPERIMENTAL)" 1428 bool "Provide NFSv4 server support (EXPERIMENTAL)"
1430 depends on NFSD_V3 && EXPERIMENTAL 1429 depends on NFSD_V3 && EXPERIMENTAL
1431 select NFSD_TCP 1430 select NFSD_TCP
1431 select CRYPTO_MD5
1432 select CRYPTO
1432 help 1433 help
1433 If you would like to include the NFSv4 server as well as the NFSv2 1434 If you would like to include the NFSv4 server as well as the NFSv2
1434 and NFSv3 servers, say Y here. This feature is experimental, and 1435 and NFSv3 servers, say Y here. This feature is experimental, and
@@ -1469,6 +1470,15 @@ config LOCKD_V4
1469config EXPORTFS 1470config EXPORTFS
1470 tristate 1471 tristate
1471 1472
1473config NFS_ACL_SUPPORT
1474 tristate
1475 select FS_POSIX_ACL
1476
1477config NFS_COMMON
1478 bool
1479 depends on NFSD || NFS_FS
1480 default y
1481
1472config SUNRPC 1482config SUNRPC
1473 tristate 1483 tristate
1474 1484
diff --git a/fs/Makefile b/fs/Makefile
index 443f2bc56ccf..fc92e59e9faf 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o
31 31
32obj-$(CONFIG_FS_MBCACHE) += mbcache.o 32obj-$(CONFIG_FS_MBCACHE) += mbcache.o
33obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o 33obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o
34obj-$(CONFIG_NFS_COMMON) += nfs_common/
34 35
35obj-$(CONFIG_QUOTA) += dquot.o 36obj-$(CONFIG_QUOTA) += dquot.o
36obj-$(CONFIG_QFMT_V1) += quota_v1.o 37obj-$(CONFIG_QFMT_V1) += quota_v1.o
diff --git a/fs/afs/kafsasyncd.c b/fs/afs/kafsasyncd.c
index 6fc88ae8ad94..7ac07d0d47b9 100644
--- a/fs/afs/kafsasyncd.c
+++ b/fs/afs/kafsasyncd.c
@@ -116,7 +116,7 @@ static int kafsasyncd(void *arg)
116 remove_wait_queue(&kafsasyncd_sleepq, &myself); 116 remove_wait_queue(&kafsasyncd_sleepq, &myself);
117 set_current_state(TASK_RUNNING); 117 set_current_state(TASK_RUNNING);
118 118
119 try_to_freeze(PF_FREEZE); 119 try_to_freeze();
120 120
121 /* discard pending signals */ 121 /* discard pending signals */
122 afs_discard_my_signals(); 122 afs_discard_my_signals();
diff --git a/fs/afs/kafstimod.c b/fs/afs/kafstimod.c
index 86e710dd057e..65bc05ab8182 100644
--- a/fs/afs/kafstimod.c
+++ b/fs/afs/kafstimod.c
@@ -91,7 +91,7 @@ static int kafstimod(void *arg)
91 complete_and_exit(&kafstimod_dead, 0); 91 complete_and_exit(&kafstimod_dead, 0);
92 } 92 }
93 93
94 try_to_freeze(PF_FREEZE); 94 try_to_freeze();
95 95
96 /* discard pending signals */ 96 /* discard pending signals */
97 afs_discard_my_signals(); 97 afs_discard_my_signals();
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index c7b2b8890188..9c09641ce907 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -185,6 +185,19 @@ int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
185int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int); 185int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
186void autofs4_catatonic_mode(struct autofs_sb_info *); 186void autofs4_catatonic_mode(struct autofs_sb_info *);
187 187
188static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **dentry)
189{
190 int res = 0;
191
192 while (d_mountpoint(*dentry)) {
193 int followed = follow_down(mnt, dentry);
194 if (!followed)
195 break;
196 res = 1;
197 }
198 return res;
199}
200
188static inline int simple_positive(struct dentry *dentry) 201static inline int simple_positive(struct dentry *dentry)
189{ 202{
190 return dentry->d_inode && !d_unhashed(dentry); 203 return dentry->d_inode && !d_unhashed(dentry);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 500425e24fba..feb6ac427d05 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -56,12 +56,9 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
56 mntget(mnt); 56 mntget(mnt);
57 dget(dentry); 57 dget(dentry);
58 58
59 if (!follow_down(&mnt, &dentry)) 59 if (!autofs4_follow_mount(&mnt, &dentry))
60 goto done; 60 goto done;
61 61
62 while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
63 ;
64
65 /* This is an autofs submount, we can't expire it */ 62 /* This is an autofs submount, we can't expire it */
66 if (is_autofs4_dentry(dentry)) 63 if (is_autofs4_dentry(dentry))
67 goto done; 64 goto done;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 3765c047f157..2a771ec66956 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -205,7 +205,11 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
205 struct vfsmount *fp_mnt = mntget(mnt); 205 struct vfsmount *fp_mnt = mntget(mnt);
206 struct dentry *fp_dentry = dget(dentry); 206 struct dentry *fp_dentry = dget(dentry);
207 207
208 while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry)); 208 if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
209 dput(fp_dentry);
210 mntput(fp_mnt);
211 return -ENOENT;
212 }
209 213
210 fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); 214 fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
211 status = PTR_ERR(fp); 215 status = PTR_ERR(fp);
@@ -302,7 +306,14 @@ static int try_to_fill_dentry(struct dentry *dentry,
302 306
303 DPRINTK("expire done status=%d", status); 307 DPRINTK("expire done status=%d", status);
304 308
305 return 0; 309 /*
310 * If the directory still exists the mount request must
311 * continue otherwise it can't be followed at the right
312 * time during the walk.
313 */
314 status = d_invalidate(dentry);
315 if (status != -EBUSY)
316 return 0;
306 } 317 }
307 318
308 DPRINTK("dentry=%p %.*s ino=%p", 319 DPRINTK("dentry=%p %.*s ino=%p",
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 5a40d36e5a51..fa2348dcd671 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -191,6 +191,13 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
191 } 191 }
192 192
193 if ( !wq ) { 193 if ( !wq ) {
194 /* Can't wait for an expire if there's no mount */
195 if (notify == NFY_NONE && !d_mountpoint(dentry)) {
196 kfree(name);
197 up(&sbi->wq_sem);
198 return -ENOENT;
199 }
200
194 /* Create a new wait queue */ 201 /* Create a new wait queue */
195 wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); 202 wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
196 if ( !wq ) { 203 if ( !wq ) {
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 009b8920c1ff..dd9baabaf016 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -316,6 +316,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
316 current->mm->brk = ex.a_bss + 316 current->mm->brk = ex.a_bss +
317 (current->mm->start_brk = N_BSSADDR(ex)); 317 (current->mm->start_brk = N_BSSADDR(ex));
318 current->mm->free_area_cache = current->mm->mmap_base; 318 current->mm->free_area_cache = current->mm->mmap_base;
319 current->mm->cached_hole_size = 0;
319 320
320 set_mm_counter(current->mm, rss, 0); 321 set_mm_counter(current->mm, rss, 0);
321 current->mm->mmap = NULL; 322 current->mm->mmap = NULL;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index c374be51b041..7976a238f0a3 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -775,6 +775,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
775 change some of these later */ 775 change some of these later */
776 set_mm_counter(current->mm, rss, 0); 776 set_mm_counter(current->mm, rss, 0);
777 current->mm->free_area_cache = current->mm->mmap_base; 777 current->mm->free_area_cache = current->mm->mmap_base;
778 current->mm->cached_hole_size = 0;
778 retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), 779 retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
779 executable_stack); 780 executable_stack);
780 if (retval < 0) { 781 if (retval < 0) {
@@ -1125,7 +1126,7 @@ static int dump_write(struct file *file, const void *addr, int nr)
1125 return file->f_op->write(file, addr, nr, &file->f_pos) == nr; 1126 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
1126} 1127}
1127 1128
1128static int dump_seek(struct file *file, off_t off) 1129static int dump_seek(struct file *file, loff_t off)
1129{ 1130{
1130 if (file->f_op->llseek) { 1131 if (file->f_op->llseek) {
1131 if (file->f_op->llseek(file, off, 0) != off) 1132 if (file->f_op->llseek(file, off, 0) != off)
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index f0cd67d9d31b..c8998dc66882 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm,
520 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); 520 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
521 521
522 down_write(&current->mm->mmap_sem); 522 down_write(&current->mm->mmap_sem);
523 textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0); 523 textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0);
524 up_write(&current->mm->mmap_sem); 524 up_write(&current->mm->mmap_sem);
525 if (!textpos || textpos >= (unsigned long) -4096) { 525 if (!textpos || textpos >= (unsigned long) -4096) {
526 if (!textpos) 526 if (!textpos)
@@ -532,7 +532,7 @@ static int load_flat_file(struct linux_binprm * bprm,
532 down_write(&current->mm->mmap_sem); 532 down_write(&current->mm->mmap_sem);
533 realdatastart = do_mmap(0, 0, data_len + extra + 533 realdatastart = do_mmap(0, 0, data_len + extra +
534 MAX_SHARED_LIBS * sizeof(unsigned long), 534 MAX_SHARED_LIBS * sizeof(unsigned long),
535 PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0); 535 PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
536 up_write(&current->mm->mmap_sem); 536 up_write(&current->mm->mmap_sem);
537 537
538 if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { 538 if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -574,7 +574,7 @@ static int load_flat_file(struct linux_binprm * bprm,
574 down_write(&current->mm->mmap_sem); 574 down_write(&current->mm->mmap_sem);
575 textpos = do_mmap(0, 0, text_len + data_len + extra + 575 textpos = do_mmap(0, 0, text_len + data_len + extra +
576 MAX_SHARED_LIBS * sizeof(unsigned long), 576 MAX_SHARED_LIBS * sizeof(unsigned long),
577 PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0); 577 PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
578 up_write(&current->mm->mmap_sem); 578 up_write(&current->mm->mmap_sem);
579 if (!textpos || textpos >= (unsigned long) -4096) { 579 if (!textpos || textpos >= (unsigned long) -4096) {
580 if (!textpos) 580 if (!textpos)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index c0cbd1bc1a02..e0df94c37b7e 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -777,8 +777,7 @@ static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
777 return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); 777 return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
778} 778}
779 779
780static int block_ioctl(struct inode *inode, struct file *file, unsigned cmd, 780static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
781 unsigned long arg)
782{ 781{
783 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); 782 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
784} 783}
@@ -803,7 +802,7 @@ struct file_operations def_blk_fops = {
803 .aio_write = blkdev_file_aio_write, 802 .aio_write = blkdev_file_aio_write,
804 .mmap = generic_file_mmap, 803 .mmap = generic_file_mmap,
805 .fsync = block_fsync, 804 .fsync = block_fsync,
806 .ioctl = block_ioctl, 805 .unlocked_ioctl = block_ioctl,
807#ifdef CONFIG_COMPAT 806#ifdef CONFIG_COMPAT
808 .compat_ioctl = compat_blkdev_ioctl, 807 .compat_ioctl = compat_blkdev_ioctl,
809#endif 808#endif
diff --git a/fs/buffer.c b/fs/buffer.c
index 7e9e409feaa7..13e5938a64f6 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -331,7 +331,7 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
331 return ret; 331 return ret;
332} 332}
333 333
334asmlinkage long sys_fsync(unsigned int fd) 334static long do_fsync(unsigned int fd, int datasync)
335{ 335{
336 struct file * file; 336 struct file * file;
337 struct address_space *mapping; 337 struct address_space *mapping;
@@ -342,14 +342,14 @@ asmlinkage long sys_fsync(unsigned int fd)
342 if (!file) 342 if (!file)
343 goto out; 343 goto out;
344 344
345 mapping = file->f_mapping;
346
347 ret = -EINVAL; 345 ret = -EINVAL;
348 if (!file->f_op || !file->f_op->fsync) { 346 if (!file->f_op || !file->f_op->fsync) {
349 /* Why? We can still call filemap_fdatawrite */ 347 /* Why? We can still call filemap_fdatawrite */
350 goto out_putf; 348 goto out_putf;
351 } 349 }
352 350
351 mapping = file->f_mapping;
352
353 current->flags |= PF_SYNCWRITE; 353 current->flags |= PF_SYNCWRITE;
354 ret = filemap_fdatawrite(mapping); 354 ret = filemap_fdatawrite(mapping);
355 355
@@ -358,7 +358,7 @@ asmlinkage long sys_fsync(unsigned int fd)
358 * which could cause livelocks in fsync_buffers_list 358 * which could cause livelocks in fsync_buffers_list
359 */ 359 */
360 down(&mapping->host->i_sem); 360 down(&mapping->host->i_sem);
361 err = file->f_op->fsync(file, file->f_dentry, 0); 361 err = file->f_op->fsync(file, file->f_dentry, datasync);
362 if (!ret) 362 if (!ret)
363 ret = err; 363 ret = err;
364 up(&mapping->host->i_sem); 364 up(&mapping->host->i_sem);
@@ -373,39 +373,14 @@ out:
373 return ret; 373 return ret;
374} 374}
375 375
376asmlinkage long sys_fdatasync(unsigned int fd) 376asmlinkage long sys_fsync(unsigned int fd)
377{ 377{
378 struct file * file; 378 return do_fsync(fd, 0);
379 struct address_space *mapping; 379}
380 int ret, err;
381
382 ret = -EBADF;
383 file = fget(fd);
384 if (!file)
385 goto out;
386
387 ret = -EINVAL;
388 if (!file->f_op || !file->f_op->fsync)
389 goto out_putf;
390
391 mapping = file->f_mapping;
392
393 current->flags |= PF_SYNCWRITE;
394 ret = filemap_fdatawrite(mapping);
395 down(&mapping->host->i_sem);
396 err = file->f_op->fsync(file, file->f_dentry, 1);
397 if (!ret)
398 ret = err;
399 up(&mapping->host->i_sem);
400 err = filemap_fdatawait(mapping);
401 if (!ret)
402 ret = err;
403 current->flags &= ~PF_SYNCWRITE;
404 380
405out_putf: 381asmlinkage long sys_fdatasync(unsigned int fd)
406 fput(file); 382{
407out: 383 return do_fsync(fd, 1);
408 return ret;
409} 384}
410 385
411/* 386/*
@@ -528,7 +503,7 @@ static void free_more_memory(void)
528 for_each_pgdat(pgdat) { 503 for_each_pgdat(pgdat) {
529 zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones; 504 zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
530 if (*zones) 505 if (*zones)
531 try_to_free_pages(zones, GFP_NOFS, 0); 506 try_to_free_pages(zones, GFP_NOFS);
532 } 507 }
533} 508}
534 509
@@ -1951,7 +1926,6 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
1951 if (err) 1926 if (err)
1952 break; 1927 break;
1953 if (buffer_new(bh)) { 1928 if (buffer_new(bh)) {
1954 clear_buffer_new(bh);
1955 unmap_underlying_metadata(bh->b_bdev, 1929 unmap_underlying_metadata(bh->b_bdev,
1956 bh->b_blocknr); 1930 bh->b_blocknr);
1957 if (PageUptodate(page)) { 1931 if (PageUptodate(page)) {
@@ -1993,9 +1967,14 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
1993 if (!buffer_uptodate(*wait_bh)) 1967 if (!buffer_uptodate(*wait_bh))
1994 err = -EIO; 1968 err = -EIO;
1995 } 1969 }
1996 if (!err) 1970 if (!err) {
1997 return err; 1971 bh = head;
1998 1972 do {
1973 if (buffer_new(bh))
1974 clear_buffer_new(bh);
1975 } while ((bh = bh->b_this_page) != head);
1976 return 0;
1977 }
1999 /* Error case: */ 1978 /* Error case: */
2000 /* 1979 /*
2001 * Zero out any newly allocated blocks to avoid exposing stale 1980 * Zero out any newly allocated blocks to avoid exposing stale
diff --git a/fs/char_dev.c b/fs/char_dev.c
index c1e3537909fc..e82aac9cc2f5 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -56,10 +56,21 @@ int get_chrdev_list(char *page)
56 56
57 down(&chrdevs_lock); 57 down(&chrdevs_lock);
58 for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { 58 for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
59 for (cd = chrdevs[i]; cd; cd = cd->next) 59 for (cd = chrdevs[i]; cd; cd = cd->next) {
60 /*
61 * if the current name, plus the 5 extra characters
62 * in the device line for this entry
63 * would run us off the page, we're done
64 */
65 if ((len+strlen(cd->name) + 5) >= PAGE_SIZE)
66 goto page_full;
67
68
60 len += sprintf(page+len, "%3d %s\n", 69 len += sprintf(page+len, "%3d %s\n",
61 cd->major, cd->name); 70 cd->major, cd->name);
71 }
62 } 72 }
73page_full:
63 up(&chrdevs_lock); 74 up(&chrdevs_lock);
64 75
65 return len; 76 return len;
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 95483baab706..dab4774ee7bb 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -6,7 +6,8 @@ kills the cifsd thread (NB: killing the cifs kernel threads is not
6recommended, unmount and rmmod cifs will kill them when they are 6recommended, unmount and rmmod cifs will kill them when they are
7no longer needed). Fix readdir to ASCII servers (ie older servers 7no longer needed). Fix readdir to ASCII servers (ie older servers
8which do not support Unicode) and also require asterik. 8which do not support Unicode) and also require asterik.
9 9Fix out of memory case in which data could be written one page
10off in the page cache.
10 11
11Version 1.33 12Version 1.33
12------------ 13------------
diff --git a/fs/cifs/README b/fs/cifs/README
index e74df0c73256..34b0cf7111f3 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -371,7 +371,7 @@ A partial list of the supported mount options follows:
371 on newly created files, directories, and devices (create, 371 on newly created files, directories, and devices (create,
372 mkdir, mknod) which will result in the server setting the 372 mkdir, mknod) which will result in the server setting the
373 uid and gid to the default (usually the server uid of the 373 uid and gid to the default (usually the server uid of the
374 usern who mounted the share). Letting the server (rather than 374 user who mounted the share). Letting the server (rather than
375 the client) set the uid and gid is the default. This 375 the client) set the uid and gid is the default. This
376 parameter has no effect if the CIFS Unix Extensions are not 376 parameter has no effect if the CIFS Unix Extensions are not
377 negotiated. 377 negotiated.
@@ -384,7 +384,7 @@ A partial list of the supported mount options follows:
384 client (e.g. when the application is doing large sequential 384 client (e.g. when the application is doing large sequential
385 reads bigger than page size without rereading the same data) 385 reads bigger than page size without rereading the same data)
386 this can provide better performance than the default 386 this can provide better performance than the default
387 behavior which caches reads (reaadahead) and writes 387 behavior which caches reads (readahead) and writes
388 (writebehind) through the local Linux client pagecache 388 (writebehind) through the local Linux client pagecache
389 if oplock (caching token) is granted and held. Note that 389 if oplock (caching token) is granted and held. Note that
390 direct allows write operations larger than page size 390 direct allows write operations larger than page size
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d00b3bfe1a52..78af5850c558 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -96,5 +96,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
97extern int cifs_ioctl (struct inode * inode, struct file * filep, 97extern int cifs_ioctl (struct inode * inode, struct file * filep,
98 unsigned int command, unsigned long arg); 98 unsigned int command, unsigned long arg);
99#define CIFS_VERSION "1.34" 99#define CIFS_VERSION "1.35"
100#endif /* _CIFSFS_H */ 100#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0010511083fc..ea239dea571e 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -228,7 +228,7 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
228 const struct nls_table *nls_codepage, 228 const struct nls_table *nls_codepage,
229 int remap_special_chars); 229 int remap_special_chars);
230#endif /* CONFIG_CIFS_EXPERIMENTAL */ 230#endif /* CONFIG_CIFS_EXPERIMENTAL */
231extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, 231extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
232 const struct nls_table * codepage); 232 const struct nls_table * codepage);
233extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, 233extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
234 const struct nls_table * cp, int mapChars); 234 const struct nls_table * cp, int mapChars);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 741ff0c69f37..3c628bf667a5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -567,7 +567,7 @@ DelFileRetry:
567 567
568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
569 name_len = 569 name_len =
570 cifsConvertToUCS((__u16 *) pSMB->fileName, fileName, 570 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
571 PATH_MAX, nls_codepage, remap); 571 PATH_MAX, nls_codepage, remap);
572 name_len++; /* trailing null */ 572 name_len++; /* trailing null */
573 name_len *= 2; 573 name_len *= 2;
@@ -665,7 +665,7 @@ MkDirRetry:
665 return rc; 665 return rc;
666 666
667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
668 name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name, 668 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
669 PATH_MAX, nls_codepage, remap); 669 PATH_MAX, nls_codepage, remap);
670 name_len++; /* trailing null */ 670 name_len++; /* trailing null */
671 name_len *= 2; 671 name_len *= 2;
@@ -719,7 +719,7 @@ openRetry:
719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
720 count = 1; /* account for one byte pad to word boundary */ 720 count = 1; /* account for one byte pad to word boundary */
721 name_len = 721 name_len =
722 cifsConvertToUCS((__u16 *) (pSMB->fileName + 1), 722 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
723 fileName, PATH_MAX, nls_codepage, remap); 723 fileName, PATH_MAX, nls_codepage, remap);
724 name_len++; /* trailing null */ 724 name_len++; /* trailing null */
725 name_len *= 2; 725 name_len *= 2;
@@ -1141,7 +1141,7 @@ renameRetry:
1141 1141
1142 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1142 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1143 name_len = 1143 name_len =
1144 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, 1144 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1145 PATH_MAX, nls_codepage, remap); 1145 PATH_MAX, nls_codepage, remap);
1146 name_len++; /* trailing null */ 1146 name_len++; /* trailing null */
1147 name_len *= 2; 1147 name_len *= 2;
@@ -1149,7 +1149,7 @@ renameRetry:
1149 /* protocol requires ASCII signature byte on Unicode string */ 1149 /* protocol requires ASCII signature byte on Unicode string */
1150 pSMB->OldFileName[name_len + 1] = 0x00; 1150 pSMB->OldFileName[name_len + 1] = 0x00;
1151 name_len2 = 1151 name_len2 =
1152 cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2], 1152 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1153 toName, PATH_MAX, nls_codepage, remap); 1153 toName, PATH_MAX, nls_codepage, remap);
1154 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1154 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1155 name_len2 *= 2; /* convert to bytes */ 1155 name_len2 *= 2; /* convert to bytes */
@@ -1236,10 +1236,10 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1236 /* unicode only call */ 1236 /* unicode only call */
1237 if(target_name == NULL) { 1237 if(target_name == NULL) {
1238 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); 1238 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1239 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, 1239 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1240 dummy_string, 24, nls_codepage, remap); 1240 dummy_string, 24, nls_codepage, remap);
1241 } else { 1241 } else {
1242 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, 1242 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1243 target_name, PATH_MAX, nls_codepage, remap); 1243 target_name, PATH_MAX, nls_codepage, remap);
1244 } 1244 }
1245 rename_info->target_name_len = cpu_to_le32(2 * len_of_str); 1245 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
@@ -1296,7 +1296,7 @@ copyRetry:
1296 pSMB->Flags = cpu_to_le16(flags & COPY_TREE); 1296 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1297 1297
1298 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1298 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1299 name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName, 1299 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1300 fromName, PATH_MAX, nls_codepage, 1300 fromName, PATH_MAX, nls_codepage,
1301 remap); 1301 remap);
1302 name_len++; /* trailing null */ 1302 name_len++; /* trailing null */
@@ -1304,7 +1304,7 @@ copyRetry:
1304 pSMB->OldFileName[name_len] = 0x04; /* pad */ 1304 pSMB->OldFileName[name_len] = 0x04; /* pad */
1305 /* protocol requires ASCII signature byte on Unicode string */ 1305 /* protocol requires ASCII signature byte on Unicode string */
1306 pSMB->OldFileName[name_len + 1] = 0x00; 1306 pSMB->OldFileName[name_len + 1] = 0x00;
1307 name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], 1307 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1308 toName, PATH_MAX, nls_codepage, remap); 1308 toName, PATH_MAX, nls_codepage, remap);
1309 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1309 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1310 name_len2 *= 2; /* convert to bytes */ 1310 name_len2 *= 2; /* convert to bytes */
@@ -1453,7 +1453,7 @@ createHardLinkRetry:
1453 return rc; 1453 return rc;
1454 1454
1455 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1455 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1456 name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName, 1456 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1457 PATH_MAX, nls_codepage, remap); 1457 PATH_MAX, nls_codepage, remap);
1458 name_len++; /* trailing null */ 1458 name_len++; /* trailing null */
1459 name_len *= 2; 1459 name_len *= 2;
@@ -1476,7 +1476,7 @@ createHardLinkRetry:
1476 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 1476 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1477 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1477 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1478 name_len_target = 1478 name_len_target =
1479 cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX, 1479 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1480 nls_codepage, remap); 1480 nls_codepage, remap);
1481 name_len_target++; /* trailing null */ 1481 name_len_target++; /* trailing null */
1482 name_len_target *= 2; 1482 name_len_target *= 2;
@@ -1546,14 +1546,14 @@ winCreateHardLinkRetry:
1546 1546
1547 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1547 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1548 name_len = 1548 name_len =
1549 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, 1549 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1550 PATH_MAX, nls_codepage, remap); 1550 PATH_MAX, nls_codepage, remap);
1551 name_len++; /* trailing null */ 1551 name_len++; /* trailing null */
1552 name_len *= 2; 1552 name_len *= 2;
1553 pSMB->OldFileName[name_len] = 0; /* pad */ 1553 pSMB->OldFileName[name_len] = 0; /* pad */
1554 pSMB->OldFileName[name_len + 1] = 0x04; 1554 pSMB->OldFileName[name_len + 1] = 0x04;
1555 name_len2 = 1555 name_len2 =
1556 cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], 1556 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1557 toName, PATH_MAX, nls_codepage, remap); 1557 toName, PATH_MAX, nls_codepage, remap);
1558 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1558 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1559 name_len2 *= 2; /* convert to bytes */ 1559 name_len2 *= 2; /* convert to bytes */
@@ -1939,7 +1939,7 @@ queryAclRetry:
1939 1939
1940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1941 name_len = 1941 name_len =
1942 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 1942 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
1943 PATH_MAX, nls_codepage, remap); 1943 PATH_MAX, nls_codepage, remap);
1944 name_len++; /* trailing null */ 1944 name_len++; /* trailing null */
1945 name_len *= 2; 1945 name_len *= 2;
@@ -2024,7 +2024,7 @@ setAclRetry:
2024 return rc; 2024 return rc;
2025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2026 name_len = 2026 name_len =
2027 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 2027 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2028 PATH_MAX, nls_codepage, remap); 2028 PATH_MAX, nls_codepage, remap);
2029 name_len++; /* trailing null */ 2029 name_len++; /* trailing null */
2030 name_len *= 2; 2030 name_len *= 2;
@@ -2188,7 +2188,7 @@ QPathInfoRetry:
2188 2188
2189 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2189 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2190 name_len = 2190 name_len =
2191 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 2191 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2192 PATH_MAX, nls_codepage, remap); 2192 PATH_MAX, nls_codepage, remap);
2193 name_len++; /* trailing null */ 2193 name_len++; /* trailing null */
2194 name_len *= 2; 2194 name_len *= 2;
@@ -2269,7 +2269,7 @@ UnixQPathInfoRetry:
2269 2269
2270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2271 name_len = 2271 name_len =
2272 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 2272 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2273 PATH_MAX, nls_codepage, remap); 2273 PATH_MAX, nls_codepage, remap);
2274 name_len++; /* trailing null */ 2274 name_len++; /* trailing null */
2275 name_len *= 2; 2275 name_len *= 2;
@@ -2350,7 +2350,7 @@ findUniqueRetry:
2350 2350
2351 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2351 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2352 name_len = 2352 name_len =
2353 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 2353 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2354 /* find define for this maxpathcomponent */ 2354 /* find define for this maxpathcomponent */
2355 , nls_codepage); 2355 , nls_codepage);
2356 name_len++; /* trailing null */ 2356 name_len++; /* trailing null */
@@ -2435,7 +2435,7 @@ findFirstRetry:
2435 2435
2436 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2436 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2437 name_len = 2437 name_len =
2438 cifsConvertToUCS((__u16 *) pSMB->FileName,searchName, 2438 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2439 PATH_MAX, nls_codepage, remap); 2439 PATH_MAX, nls_codepage, remap);
2440 /* We can not add the asterik earlier in case 2440 /* We can not add the asterik earlier in case
2441 it got remapped to 0xF03A as if it were part of the 2441 it got remapped to 0xF03A as if it were part of the
@@ -2726,7 +2726,7 @@ GetInodeNumberRetry:
2726 2726
2727 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2727 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2728 name_len = 2728 name_len =
2729 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 2729 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2730 PATH_MAX,nls_codepage, remap); 2730 PATH_MAX,nls_codepage, remap);
2731 name_len++; /* trailing null */ 2731 name_len++; /* trailing null */
2732 name_len *= 2; 2732 name_len *= 2;
@@ -2837,7 +2837,7 @@ getDFSRetry:
2837 if (ses->capabilities & CAP_UNICODE) { 2837 if (ses->capabilities & CAP_UNICODE) {
2838 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 2838 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2839 name_len = 2839 name_len =
2840 cifsConvertToUCS((__u16 *) pSMB->RequestFileName, 2840 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
2841 searchName, PATH_MAX, nls_codepage, remap); 2841 searchName, PATH_MAX, nls_codepage, remap);
2842 name_len++; /* trailing null */ 2842 name_len++; /* trailing null */
2843 name_len *= 2; 2843 name_len *= 2;
@@ -3369,7 +3369,7 @@ SetEOFRetry:
3369 3369
3370 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3370 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3371 name_len = 3371 name_len =
3372 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 3372 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3373 PATH_MAX, nls_codepage, remap); 3373 PATH_MAX, nls_codepage, remap);
3374 name_len++; /* trailing null */ 3374 name_len++; /* trailing null */
3375 name_len *= 2; 3375 name_len *= 2;
@@ -3627,7 +3627,7 @@ SetTimesRetry:
3627 3627
3628 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3628 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3629 name_len = 3629 name_len =
3630 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 3630 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3631 PATH_MAX, nls_codepage, remap); 3631 PATH_MAX, nls_codepage, remap);
3632 name_len++; /* trailing null */ 3632 name_len++; /* trailing null */
3633 name_len *= 2; 3633 name_len *= 2;
@@ -3708,7 +3708,7 @@ SetAttrLgcyRetry:
3708 3708
3709 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3709 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3710 name_len = 3710 name_len =
3711 ConvertToUCS((wchar_t *) pSMB->fileName, fileName, 3711 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
3712 PATH_MAX, nls_codepage); 3712 PATH_MAX, nls_codepage);
3713 name_len++; /* trailing null */ 3713 name_len++; /* trailing null */
3714 name_len *= 2; 3714 name_len *= 2;
@@ -3759,7 +3759,7 @@ setPermsRetry:
3759 3759
3760 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3760 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3761 name_len = 3761 name_len =
3762 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 3762 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3763 PATH_MAX, nls_codepage, remap); 3763 PATH_MAX, nls_codepage, remap);
3764 name_len++; /* trailing null */ 3764 name_len++; /* trailing null */
3765 name_len *= 2; 3765 name_len *= 2;
@@ -3904,7 +3904,7 @@ QAllEAsRetry:
3904 3904
3905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3906 name_len = 3906 name_len =
3907 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, 3907 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3908 PATH_MAX, nls_codepage, remap); 3908 PATH_MAX, nls_codepage, remap);
3909 name_len++; /* trailing null */ 3909 name_len++; /* trailing null */
3910 name_len *= 2; 3910 name_len *= 2;
@@ -4047,7 +4047,7 @@ QEARetry:
4047 4047
4048 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4048 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4049 name_len = 4049 name_len =
4050 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 4050 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4051 PATH_MAX, nls_codepage, remap); 4051 PATH_MAX, nls_codepage, remap);
4052 name_len++; /* trailing null */ 4052 name_len++; /* trailing null */
4053 name_len *= 2; 4053 name_len *= 2;
@@ -4194,7 +4194,7 @@ SetEARetry:
4194 4194
4195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4196 name_len = 4196 name_len =
4197 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 4197 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4198 PATH_MAX, nls_codepage, remap); 4198 PATH_MAX, nls_codepage, remap);
4199 name_len++; /* trailing null */ 4199 name_len++; /* trailing null */
4200 name_len *= 2; 4200 name_len *= 2;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e3137aa48cdd..3f3538d4a1fa 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -392,7 +392,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
392 rc = 0; 392 rc = 0;
393 d_add(direntry, NULL); 393 d_add(direntry, NULL);
394 } else { 394 } else {
395 cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc)); 395 cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
396 rc,full_path));
396 /* BB special case check for Access Denied - watch security 397 /* BB special case check for Access Denied - watch security
397 exposure of returning dir info implicitly via different rc 398 exposure of returning dir info implicitly via different rc
398 if file exists or not but no access BB */ 399 if file exists or not but no access BB */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dde2d251fc3d..30ab70ce5547 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1352,6 +1352,8 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
1352 GFP_KERNEL)) { 1352 GFP_KERNEL)) {
1353 page_cache_release(page); 1353 page_cache_release(page);
1354 cFYI(1, ("Add page cache failed")); 1354 cFYI(1, ("Add page cache failed"));
1355 data += PAGE_CACHE_SIZE;
1356 bytes_read -= PAGE_CACHE_SIZE;
1355 continue; 1357 continue;
1356 } 1358 }
1357 1359
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 670947288262..8d336a900255 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -82,12 +82,12 @@ int cifs_get_inode_info_unix(struct inode **pinode,
82 /* get new inode */ 82 /* get new inode */
83 if (*pinode == NULL) { 83 if (*pinode == NULL) {
84 *pinode = new_inode(sb); 84 *pinode = new_inode(sb);
85 if(*pinode == NULL) 85 if (*pinode == NULL)
86 return -ENOMEM; 86 return -ENOMEM;
87 /* Is an i_ino of zero legal? */ 87 /* Is an i_ino of zero legal? */
88 /* Are there sanity checks we can use to ensure that 88 /* Are there sanity checks we can use to ensure that
89 the server is really filling in that field? */ 89 the server is really filling in that field? */
90 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 90 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
91 (*pinode)->i_ino = 91 (*pinode)->i_ino =
92 (unsigned long)findData.UniqueId; 92 (unsigned long)findData.UniqueId;
93 } /* note ino incremented to unique num in new_inode */ 93 } /* note ino incremented to unique num in new_inode */
@@ -134,7 +134,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
134 inode->i_gid = le64_to_cpu(findData.Gid); 134 inode->i_gid = le64_to_cpu(findData.Gid);
135 inode->i_nlink = le64_to_cpu(findData.Nlinks); 135 inode->i_nlink = le64_to_cpu(findData.Nlinks);
136 136
137 if(is_size_safe_to_change(cifsInfo)) { 137 if (is_size_safe_to_change(cifsInfo)) {
138 /* can not safely change the file size here if the 138 /* can not safely change the file size here if the
139 client is writing to it due to potential races */ 139 client is writing to it due to potential races */
140 140
@@ -162,7 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
162 if (S_ISREG(inode->i_mode)) { 162 if (S_ISREG(inode->i_mode)) {
163 cFYI(1, (" File inode ")); 163 cFYI(1, (" File inode "));
164 inode->i_op = &cifs_file_inode_ops; 164 inode->i_op = &cifs_file_inode_ops;
165 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 165 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
166 inode->i_fop = &cifs_file_direct_ops; 166 inode->i_fop = &cifs_file_direct_ops;
167 else 167 else
168 inode->i_fop = &cifs_file_ops; 168 inode->i_fop = &cifs_file_ops;
@@ -198,17 +198,17 @@ int cifs_get_inode_info(struct inode **pinode,
198 pTcon = cifs_sb->tcon; 198 pTcon = cifs_sb->tcon;
199 cFYI(1,("Getting info on %s ", search_path)); 199 cFYI(1,("Getting info on %s ", search_path));
200 200
201 if((pfindData == NULL) && (*pinode != NULL)) { 201 if ((pfindData == NULL) && (*pinode != NULL)) {
202 if(CIFS_I(*pinode)->clientCanCacheRead) { 202 if (CIFS_I(*pinode)->clientCanCacheRead) {
203 cFYI(1,("No need to revalidate cached inode sizes")); 203 cFYI(1,("No need to revalidate cached inode sizes"));
204 return rc; 204 return rc;
205 } 205 }
206 } 206 }
207 207
208 /* if file info not passed in then get it from server */ 208 /* if file info not passed in then get it from server */
209 if(pfindData == NULL) { 209 if (pfindData == NULL) {
210 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 210 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
211 if(buf == NULL) 211 if (buf == NULL)
212 return -ENOMEM; 212 return -ENOMEM;
213 pfindData = (FILE_ALL_INFO *)buf; 213 pfindData = (FILE_ALL_INFO *)buf;
214 /* could do find first instead but this returns more info */ 214 /* could do find first instead but this returns more info */
@@ -268,7 +268,7 @@ int cifs_get_inode_info(struct inode **pinode,
268 IndexNumber field is not guaranteed unique? */ 268 IndexNumber field is not guaranteed unique? */
269 269
270#ifdef CONFIG_CIFS_EXPERIMENTAL 270#ifdef CONFIG_CIFS_EXPERIMENTAL
271 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ 271 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
272 int rc1 = 0; 272 int rc1 = 0;
273 __u64 inode_num; 273 __u64 inode_num;
274 274
@@ -277,7 +277,7 @@ int cifs_get_inode_info(struct inode **pinode,
277 cifs_sb->local_nls, 277 cifs_sb->local_nls,
278 cifs_sb->mnt_cifs_flags & 278 cifs_sb->mnt_cifs_flags &
279 CIFS_MOUNT_MAP_SPECIAL_CHR); 279 CIFS_MOUNT_MAP_SPECIAL_CHR);
280 if(rc1) { 280 if (rc1) {
281 cFYI(1,("GetSrvInodeNum rc %d", rc1)); 281 cFYI(1,("GetSrvInodeNum rc %d", rc1));
282 /* BB EOPNOSUPP disable SERVER_INUM? */ 282 /* BB EOPNOSUPP disable SERVER_INUM? */
283 } else /* do we need cast or hash to ino? */ 283 } else /* do we need cast or hash to ino? */
@@ -355,7 +355,7 @@ int cifs_get_inode_info(struct inode **pinode,
355 if (S_ISREG(inode->i_mode)) { 355 if (S_ISREG(inode->i_mode)) {
356 cFYI(1, (" File inode ")); 356 cFYI(1, (" File inode "));
357 inode->i_op = &cifs_file_inode_ops; 357 inode->i_op = &cifs_file_inode_ops;
358 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 358 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
359 inode->i_fop = &cifs_file_direct_ops; 359 inode->i_fop = &cifs_file_direct_ops;
360 else 360 else
361 inode->i_fop = &cifs_file_ops; 361 inode->i_fop = &cifs_file_ops;
@@ -422,7 +422,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
422 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 422 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
423 423
424 if (!rc) { 424 if (!rc) {
425 direntry->d_inode->i_nlink--; 425 if (direntry->d_inode)
426 direntry->d_inode->i_nlink--;
426 } else if (rc == -ENOENT) { 427 } else if (rc == -ENOENT) {
427 d_drop(direntry); 428 d_drop(direntry);
428 } else if (rc == -ETXTBSY) { 429 } else if (rc == -ETXTBSY) {
@@ -440,7 +441,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
440 cifs_sb->mnt_cifs_flags & 441 cifs_sb->mnt_cifs_flags &
441 CIFS_MOUNT_MAP_SPECIAL_CHR); 442 CIFS_MOUNT_MAP_SPECIAL_CHR);
442 CIFSSMBClose(xid, pTcon, netfid); 443 CIFSSMBClose(xid, pTcon, netfid);
443 direntry->d_inode->i_nlink--; 444 if (direntry->d_inode)
445 direntry->d_inode->i_nlink--;
444 } 446 }
445 } else if (rc == -EACCES) { 447 } else if (rc == -EACCES) {
446 /* try only if r/o attribute set in local lookup data? */ 448 /* try only if r/o attribute set in local lookup data? */
@@ -494,7 +496,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
494 cifs_sb->mnt_cifs_flags & 496 cifs_sb->mnt_cifs_flags &
495 CIFS_MOUNT_MAP_SPECIAL_CHR); 497 CIFS_MOUNT_MAP_SPECIAL_CHR);
496 if (!rc) { 498 if (!rc) {
497 direntry->d_inode->i_nlink--; 499 if (direntry->d_inode)
500 direntry->d_inode->i_nlink--;
498 } else if (rc == -ETXTBSY) { 501 } else if (rc == -ETXTBSY) {
499 int oplock = FALSE; 502 int oplock = FALSE;
500 __u16 netfid; 503 __u16 netfid;
@@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
514 cifs_sb->mnt_cifs_flags & 517 cifs_sb->mnt_cifs_flags &
515 CIFS_MOUNT_MAP_SPECIAL_CHR); 518 CIFS_MOUNT_MAP_SPECIAL_CHR);
516 CIFSSMBClose(xid, pTcon, netfid); 519 CIFSSMBClose(xid, pTcon, netfid);
517 direntry->d_inode->i_nlink--; 520 if (direntry->d_inode)
521 direntry->d_inode->i_nlink--;
518 } 522 }
519 /* BB if rc = -ETXTBUSY goto the rename logic BB */ 523 /* BB if rc = -ETXTBUSY goto the rename logic BB */
520 } 524 }
521 } 525 }
522 } 526 }
523 cifsInode = CIFS_I(direntry->d_inode); 527 if (direntry->d_inode) {
524 cifsInode->time = 0; /* will force revalidate to get info when 528 cifsInode = CIFS_I(direntry->d_inode);
525 needed */ 529 cifsInode->time = 0; /* will force revalidate to get info
526 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = 530 when needed */
527 current_fs_time(inode->i_sb); 531 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
532 }
533 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
528 cifsInode = CIFS_I(inode); 534 cifsInode = CIFS_I(inode);
529 cifsInode->time = 0; /* force revalidate of dir as well */ 535 cifsInode->time = 0; /* force revalidate of dir as well */
530 536
@@ -576,7 +582,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
576 if (direntry->d_inode) 582 if (direntry->d_inode)
577 direntry->d_inode->i_nlink = 2; 583 direntry->d_inode->i_nlink = 2;
578 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) 584 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
579 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 585 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
580 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 586 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
581 mode, 587 mode,
582 (__u64)current->euid, 588 (__u64)current->euid,
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index db14b503d89e..072b4ee8c53e 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -571,6 +571,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
571 break; 571 break;
572 case UNI_LESSTHAN: 572 case UNI_LESSTHAN:
573 target[j] = '<'; 573 target[j] = '<';
574 break;
574 default: 575 default:
575 len = cp->uni2char(src_char, &target[j], 576 len = cp->uni2char(src_char, &target[j],
576 NLS_MAX_CHARSET_SIZE); 577 NLS_MAX_CHARSET_SIZE);
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index ef001a9313e6..3d1cce3653b8 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -61,7 +61,7 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
61 61
62 62
63struct venus_comm coda_comms[MAX_CODADEVS]; 63struct venus_comm coda_comms[MAX_CODADEVS];
64static struct class_simple *coda_psdev_class; 64static struct class *coda_psdev_class;
65 65
66/* 66/*
67 * Device operations 67 * Device operations
@@ -363,14 +363,14 @@ static int init_coda_psdev(void)
363 CODA_PSDEV_MAJOR); 363 CODA_PSDEV_MAJOR);
364 return -EIO; 364 return -EIO;
365 } 365 }
366 coda_psdev_class = class_simple_create(THIS_MODULE, "coda"); 366 coda_psdev_class = class_create(THIS_MODULE, "coda");
367 if (IS_ERR(coda_psdev_class)) { 367 if (IS_ERR(coda_psdev_class)) {
368 err = PTR_ERR(coda_psdev_class); 368 err = PTR_ERR(coda_psdev_class);
369 goto out_chrdev; 369 goto out_chrdev;
370 } 370 }
371 devfs_mk_dir ("coda"); 371 devfs_mk_dir ("coda");
372 for (i = 0; i < MAX_CODADEVS; i++) { 372 for (i = 0; i < MAX_CODADEVS; i++) {
373 class_simple_device_add(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i), 373 class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
374 NULL, "cfs%d", i); 374 NULL, "cfs%d", i);
375 err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i), 375 err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
376 S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i); 376 S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
@@ -382,8 +382,8 @@ static int init_coda_psdev(void)
382 382
383out_class: 383out_class:
384 for (i = 0; i < MAX_CODADEVS; i++) 384 for (i = 0; i < MAX_CODADEVS; i++)
385 class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); 385 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
386 class_simple_destroy(coda_psdev_class); 386 class_destroy(coda_psdev_class);
387out_chrdev: 387out_chrdev:
388 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 388 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
389out: 389out:
@@ -425,10 +425,10 @@ static int __init init_coda(void)
425 return 0; 425 return 0;
426out: 426out:
427 for (i = 0; i < MAX_CODADEVS; i++) { 427 for (i = 0; i < MAX_CODADEVS; i++) {
428 class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); 428 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
429 devfs_remove("coda/%d", i); 429 devfs_remove("coda/%d", i);
430 } 430 }
431 class_simple_destroy(coda_psdev_class); 431 class_destroy(coda_psdev_class);
432 devfs_remove("coda"); 432 devfs_remove("coda");
433 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 433 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
434 coda_sysctl_clean(); 434 coda_sysctl_clean();
@@ -447,10 +447,10 @@ static void __exit exit_coda(void)
447 printk("coda: failed to unregister filesystem\n"); 447 printk("coda: failed to unregister filesystem\n");
448 } 448 }
449 for (i = 0; i < MAX_CODADEVS; i++) { 449 for (i = 0; i < MAX_CODADEVS; i++) {
450 class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); 450 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
451 devfs_remove("coda/%d", i); 451 devfs_remove("coda/%d", i);
452 } 452 }
453 class_simple_destroy(coda_psdev_class); 453 class_destroy(coda_psdev_class);
454 devfs_remove("coda"); 454 devfs_remove("coda");
455 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 455 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
456 coda_sysctl_clean(); 456 coda_sysctl_clean();
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 548556ff2506..efc97d9b7860 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -45,44 +45,15 @@ struct file_operations debugfs_file_operations = {
45 .open = default_open, 45 .open = default_open,
46}; 46};
47 47
48#define simple_type(type, format, temptype, strtolfn) \ 48static void debugfs_u8_set(void *data, u64 val)
49static ssize_t read_file_##type(struct file *file, char __user *user_buf, \ 49{
50 size_t count, loff_t *ppos) \ 50 *(u8 *)data = val;
51{ \ 51}
52 char buf[32]; \ 52static u64 debugfs_u8_get(void *data)
53 type *val = file->private_data; \ 53{
54 \ 54 return *(u8 *)data;
55 snprintf(buf, sizeof(buf), format "\n", *val); \ 55}
56 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\ 56DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
57} \
58static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\
59 size_t count, loff_t *ppos) \
60{ \
61 char *endp; \
62 char buf[32]; \
63 int buf_size; \
64 type *val = file->private_data; \
65 temptype tmp; \
66 \
67 memset(buf, 0x00, sizeof(buf)); \
68 buf_size = min(count, (sizeof(buf)-1)); \
69 if (copy_from_user(buf, user_buf, buf_size)) \
70 return -EFAULT; \
71 \
72 tmp = strtolfn(buf, &endp, 0); \
73 if ((endp == buf) || ((type)tmp != tmp)) \
74 return -EINVAL; \
75 *val = tmp; \
76 return count; \
77} \
78static struct file_operations fops_##type = { \
79 .read = read_file_##type, \
80 .write = write_file_##type, \
81 .open = default_open, \
82};
83simple_type(u8, "%c", unsigned long, simple_strtoul);
84simple_type(u16, "%hi", unsigned long, simple_strtoul);
85simple_type(u32, "%i", unsigned long, simple_strtoul);
86 57
87/** 58/**
88 * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 59 * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
@@ -116,6 +87,16 @@ struct dentry *debugfs_create_u8(const char *name, mode_t mode,
116} 87}
117EXPORT_SYMBOL_GPL(debugfs_create_u8); 88EXPORT_SYMBOL_GPL(debugfs_create_u8);
118 89
90static void debugfs_u16_set(void *data, u64 val)
91{
92 *(u16 *)data = val;
93}
94static u64 debugfs_u16_get(void *data)
95{
96 return *(u16 *)data;
97}
98DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
99
119/** 100/**
120 * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 101 * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
121 * 102 *
@@ -148,6 +129,16 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode,
148} 129}
149EXPORT_SYMBOL_GPL(debugfs_create_u16); 130EXPORT_SYMBOL_GPL(debugfs_create_u16);
150 131
132static void debugfs_u32_set(void *data, u64 val)
133{
134 *(u32 *)data = val;
135}
136static u64 debugfs_u32_get(void *data)
137{
138 return *(u32 *)data;
139}
140DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
141
151/** 142/**
152 * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 143 * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
153 * 144 *
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index b529786699e7..a86ac4aeaedb 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -110,16 +110,6 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent)
110 return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); 110 return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
111} 111}
112 112
113static struct dentry * get_dentry(struct dentry *parent, const char *name)
114{
115 struct qstr qstr;
116
117 qstr.name = name;
118 qstr.len = strlen(name);
119 qstr.hash = full_name_hash(name,qstr.len);
120 return lookup_hash(&qstr,parent);
121}
122
123static struct super_block *debug_get_sb(struct file_system_type *fs_type, 113static struct super_block *debug_get_sb(struct file_system_type *fs_type,
124 int flags, const char *dev_name, 114 int flags, const char *dev_name,
125 void *data) 115 void *data)
@@ -157,7 +147,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
157 147
158 *dentry = NULL; 148 *dentry = NULL;
159 down(&parent->d_inode->i_sem); 149 down(&parent->d_inode->i_sem);
160 *dentry = get_dentry (parent, name); 150 *dentry = lookup_one_len(name, parent, strlen(name));
161 if (!IS_ERR(dentry)) { 151 if (!IS_ERR(dentry)) {
162 if ((mode & S_IFMT) == S_IFDIR) 152 if ((mode & S_IFMT) == S_IFDIR)
163 error = debugfs_mkdir(parent->d_inode, *dentry, mode); 153 error = debugfs_mkdir(parent->d_inode, *dentry, mode);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 1d55e7e67342..0d06097bc995 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -215,7 +215,7 @@ static struct page *dio_get_page(struct dio *dio)
215static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes) 215static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
216{ 216{
217 if (dio->end_io && dio->result) 217 if (dio->end_io && dio->result)
218 dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private); 218 dio->end_io(dio->iocb, offset, bytes, dio->map_bh.b_private);
219 if (dio->lock_type == DIO_LOCKING) 219 if (dio->lock_type == DIO_LOCKING)
220 up_read(&dio->inode->i_alloc_sem); 220 up_read(&dio->inode->i_alloc_sem);
221} 221}
diff --git a/fs/dquot.c b/fs/dquot.c
index 3995ce7907cc..b9732335bcdc 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -409,13 +409,10 @@ out_dqlock:
409 * for this sb+type at all. */ 409 * for this sb+type at all. */
410static void invalidate_dquots(struct super_block *sb, int type) 410static void invalidate_dquots(struct super_block *sb, int type)
411{ 411{
412 struct dquot *dquot; 412 struct dquot *dquot, *tmp;
413 struct list_head *head;
414 413
415 spin_lock(&dq_list_lock); 414 spin_lock(&dq_list_lock);
416 for (head = inuse_list.next; head != &inuse_list;) { 415 list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) {
417 dquot = list_entry(head, struct dquot, dq_inuse);
418 head = head->next;
419 if (dquot->dq_sb != sb) 416 if (dquot->dq_sb != sb)
420 continue; 417 continue;
421 if (dquot->dq_type != type) 418 if (dquot->dq_type != type)
@@ -1519,14 +1516,22 @@ out_path:
1519 * This function is used when filesystem needs to initialize quotas 1516 * This function is used when filesystem needs to initialize quotas
1520 * during mount time. 1517 * during mount time.
1521 */ 1518 */
1522int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry) 1519int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
1520 int format_id, int type)
1523{ 1521{
1522 struct dentry *dentry;
1524 int error; 1523 int error;
1525 1524
1525 dentry = lookup_one_len(qf_name, sb->s_root, strlen(qf_name));
1526 if (IS_ERR(dentry))
1527 return PTR_ERR(dentry);
1528
1526 error = security_quota_on(dentry); 1529 error = security_quota_on(dentry);
1527 if (error) 1530 if (!error)
1528 return error; 1531 error = vfs_quota_on_inode(dentry->d_inode, type, format_id);
1529 return vfs_quota_on_inode(dentry->d_inode, type, format_id); 1532
1533 dput(dentry);
1534 return error;
1530} 1535}
1531 1536
1532/* Generic routine for getting common part of quota structure */ 1537/* Generic routine for getting common part of quota structure */
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 9900e333655a..6ab1dd0ca904 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -101,57 +101,6 @@
101/* Maximum number of poll wake up nests we are allowing */ 101/* Maximum number of poll wake up nests we are allowing */
102#define EP_MAX_POLLWAKE_NESTS 4 102#define EP_MAX_POLLWAKE_NESTS 4
103 103
104/* Macro to allocate a "struct epitem" from the slab cache */
105#define EPI_MEM_ALLOC() (struct epitem *) kmem_cache_alloc(epi_cache, SLAB_KERNEL)
106
107/* Macro to free a "struct epitem" to the slab cache */
108#define EPI_MEM_FREE(p) kmem_cache_free(epi_cache, p)
109
110/* Macro to allocate a "struct eppoll_entry" from the slab cache */
111#define PWQ_MEM_ALLOC() (struct eppoll_entry *) kmem_cache_alloc(pwq_cache, SLAB_KERNEL)
112
113/* Macro to free a "struct eppoll_entry" to the slab cache */
114#define PWQ_MEM_FREE(p) kmem_cache_free(pwq_cache, p)
115
116/* Fast test to see if the file is an evenpoll file */
117#define IS_FILE_EPOLL(f) ((f)->f_op == &eventpoll_fops)
118
119/* Setup the structure that is used as key for the rb-tree */
120#define EP_SET_FFD(p, f, d) do { (p)->file = (f); (p)->fd = (d); } while (0)
121
122/* Compare rb-tree keys */
123#define EP_CMP_FFD(p1, p2) ((p1)->file > (p2)->file ? +1: \
124 ((p1)->file < (p2)->file ? -1: (p1)->fd - (p2)->fd))
125
126/* Special initialization for the rb-tree node to detect linkage */
127#define EP_RB_INITNODE(n) (n)->rb_parent = (n)
128
129/* Removes a node from the rb-tree and marks it for a fast is-linked check */
130#define EP_RB_ERASE(n, r) do { rb_erase(n, r); (n)->rb_parent = (n); } while (0)
131
132/* Fast check to verify that the item is linked to the main rb-tree */
133#define EP_RB_LINKED(n) ((n)->rb_parent != (n))
134
135/*
136 * Remove the item from the list and perform its initialization.
137 * This is useful for us because we can test if the item is linked
138 * using "EP_IS_LINKED(p)".
139 */
140#define EP_LIST_DEL(p) do { list_del(p); INIT_LIST_HEAD(p); } while (0)
141
142/* Tells us if the item is currently linked */
143#define EP_IS_LINKED(p) (!list_empty(p))
144
145/* Get the "struct epitem" from a wait queue pointer */
146#define EP_ITEM_FROM_WAIT(p) ((struct epitem *) container_of(p, struct eppoll_entry, wait)->base)
147
148/* Get the "struct epitem" from an epoll queue wrapper */
149#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
150
151/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
152#define EP_OP_HASH_EVENT(op) ((op) != EPOLL_CTL_DEL)
153
154
155struct epoll_filefd { 104struct epoll_filefd {
156 struct file *file; 105 struct file *file;
157 int fd; 106 int fd;
@@ -357,6 +306,82 @@ static struct dentry_operations eventpollfs_dentry_operations = {
357 306
358 307
359 308
309/* Fast test to see if the file is an evenpoll file */
310static inline int is_file_epoll(struct file *f)
311{
312 return f->f_op == &eventpoll_fops;
313}
314
315/* Setup the structure that is used as key for the rb-tree */
316static inline void ep_set_ffd(struct epoll_filefd *ffd,
317 struct file *file, int fd)
318{
319 ffd->file = file;
320 ffd->fd = fd;
321}
322
323/* Compare rb-tree keys */
324static inline int ep_cmp_ffd(struct epoll_filefd *p1,
325 struct epoll_filefd *p2)
326{
327 return (p1->file > p2->file ? +1:
328 (p1->file < p2->file ? -1 : p1->fd - p2->fd));
329}
330
331/* Special initialization for the rb-tree node to detect linkage */
332static inline void ep_rb_initnode(struct rb_node *n)
333{
334 n->rb_parent = n;
335}
336
337/* Removes a node from the rb-tree and marks it for a fast is-linked check */
338static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
339{
340 rb_erase(n, r);
341 n->rb_parent = n;
342}
343
344/* Fast check to verify that the item is linked to the main rb-tree */
345static inline int ep_rb_linked(struct rb_node *n)
346{
347 return n->rb_parent != n;
348}
349
350/*
351 * Remove the item from the list and perform its initialization.
352 * This is useful for us because we can test if the item is linked
353 * using "ep_is_linked(p)".
354 */
355static inline void ep_list_del(struct list_head *p)
356{
357 list_del(p);
358 INIT_LIST_HEAD(p);
359}
360
361/* Tells us if the item is currently linked */
362static inline int ep_is_linked(struct list_head *p)
363{
364 return !list_empty(p);
365}
366
367/* Get the "struct epitem" from a wait queue pointer */
368static inline struct epitem * ep_item_from_wait(wait_queue_t *p)
369{
370 return container_of(p, struct eppoll_entry, wait)->base;
371}
372
373/* Get the "struct epitem" from an epoll queue wrapper */
374static inline struct epitem * ep_item_from_epqueue(poll_table *p)
375{
376 return container_of(p, struct ep_pqueue, pt)->epi;
377}
378
379/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
380static inline int ep_op_hash_event(int op)
381{
382 return op != EPOLL_CTL_DEL;
383}
384
360/* Initialize the poll safe wake up structure */ 385/* Initialize the poll safe wake up structure */
361static void ep_poll_safewake_init(struct poll_safewake *psw) 386static void ep_poll_safewake_init(struct poll_safewake *psw)
362{ 387{
@@ -456,7 +481,7 @@ void eventpoll_release_file(struct file *file)
456 epi = list_entry(lsthead->next, struct epitem, fllink); 481 epi = list_entry(lsthead->next, struct epitem, fllink);
457 482
458 ep = epi->ep; 483 ep = epi->ep;
459 EP_LIST_DEL(&epi->fllink); 484 ep_list_del(&epi->fllink);
460 down_write(&ep->sem); 485 down_write(&ep->sem);
461 ep_remove(ep, epi); 486 ep_remove(ep, epi);
462 up_write(&ep->sem); 487 up_write(&ep->sem);
@@ -534,7 +559,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
534 current, epfd, op, fd, event)); 559 current, epfd, op, fd, event));
535 560
536 error = -EFAULT; 561 error = -EFAULT;
537 if (EP_OP_HASH_EVENT(op) && 562 if (ep_op_hash_event(op) &&
538 copy_from_user(&epds, event, sizeof(struct epoll_event))) 563 copy_from_user(&epds, event, sizeof(struct epoll_event)))
539 goto eexit_1; 564 goto eexit_1;
540 565
@@ -560,7 +585,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
560 * adding an epoll file descriptor inside itself. 585 * adding an epoll file descriptor inside itself.
561 */ 586 */
562 error = -EINVAL; 587 error = -EINVAL;
563 if (file == tfile || !IS_FILE_EPOLL(file)) 588 if (file == tfile || !is_file_epoll(file))
564 goto eexit_3; 589 goto eexit_3;
565 590
566 /* 591 /*
@@ -656,7 +681,7 @@ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
656 * the user passed to us _is_ an eventpoll file. 681 * the user passed to us _is_ an eventpoll file.
657 */ 682 */
658 error = -EINVAL; 683 error = -EINVAL;
659 if (!IS_FILE_EPOLL(file)) 684 if (!is_file_epoll(file))
660 goto eexit_2; 685 goto eexit_2;
661 686
662 /* 687 /*
@@ -831,11 +856,11 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
831 struct epitem *epi, *epir = NULL; 856 struct epitem *epi, *epir = NULL;
832 struct epoll_filefd ffd; 857 struct epoll_filefd ffd;
833 858
834 EP_SET_FFD(&ffd, file, fd); 859 ep_set_ffd(&ffd, file, fd);
835 read_lock_irqsave(&ep->lock, flags); 860 read_lock_irqsave(&ep->lock, flags);
836 for (rbp = ep->rbr.rb_node; rbp; ) { 861 for (rbp = ep->rbr.rb_node; rbp; ) {
837 epi = rb_entry(rbp, struct epitem, rbn); 862 epi = rb_entry(rbp, struct epitem, rbn);
838 kcmp = EP_CMP_FFD(&ffd, &epi->ffd); 863 kcmp = ep_cmp_ffd(&ffd, &epi->ffd);
839 if (kcmp > 0) 864 if (kcmp > 0)
840 rbp = rbp->rb_right; 865 rbp = rbp->rb_right;
841 else if (kcmp < 0) 866 else if (kcmp < 0)
@@ -875,7 +900,7 @@ static void ep_release_epitem(struct epitem *epi)
875{ 900{
876 901
877 if (atomic_dec_and_test(&epi->usecnt)) 902 if (atomic_dec_and_test(&epi->usecnt))
878 EPI_MEM_FREE(epi); 903 kmem_cache_free(epi_cache, epi);
879} 904}
880 905
881 906
@@ -886,10 +911,10 @@ static void ep_release_epitem(struct epitem *epi)
886static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, 911static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
887 poll_table *pt) 912 poll_table *pt)
888{ 913{
889 struct epitem *epi = EP_ITEM_FROM_EPQUEUE(pt); 914 struct epitem *epi = ep_item_from_epqueue(pt);
890 struct eppoll_entry *pwq; 915 struct eppoll_entry *pwq;
891 916
892 if (epi->nwait >= 0 && (pwq = PWQ_MEM_ALLOC())) { 917 if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, SLAB_KERNEL))) {
893 init_waitqueue_func_entry(&pwq->wait, ep_poll_callback); 918 init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
894 pwq->whead = whead; 919 pwq->whead = whead;
895 pwq->base = epi; 920 pwq->base = epi;
@@ -912,7 +937,7 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
912 while (*p) { 937 while (*p) {
913 parent = *p; 938 parent = *p;
914 epic = rb_entry(parent, struct epitem, rbn); 939 epic = rb_entry(parent, struct epitem, rbn);
915 kcmp = EP_CMP_FFD(&epi->ffd, &epic->ffd); 940 kcmp = ep_cmp_ffd(&epi->ffd, &epic->ffd);
916 if (kcmp > 0) 941 if (kcmp > 0)
917 p = &parent->rb_right; 942 p = &parent->rb_right;
918 else 943 else
@@ -932,17 +957,17 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
932 struct ep_pqueue epq; 957 struct ep_pqueue epq;
933 958
934 error = -ENOMEM; 959 error = -ENOMEM;
935 if (!(epi = EPI_MEM_ALLOC())) 960 if (!(epi = kmem_cache_alloc(epi_cache, SLAB_KERNEL)))
936 goto eexit_1; 961 goto eexit_1;
937 962
938 /* Item initialization follow here ... */ 963 /* Item initialization follow here ... */
939 EP_RB_INITNODE(&epi->rbn); 964 ep_rb_initnode(&epi->rbn);
940 INIT_LIST_HEAD(&epi->rdllink); 965 INIT_LIST_HEAD(&epi->rdllink);
941 INIT_LIST_HEAD(&epi->fllink); 966 INIT_LIST_HEAD(&epi->fllink);
942 INIT_LIST_HEAD(&epi->txlink); 967 INIT_LIST_HEAD(&epi->txlink);
943 INIT_LIST_HEAD(&epi->pwqlist); 968 INIT_LIST_HEAD(&epi->pwqlist);
944 epi->ep = ep; 969 epi->ep = ep;
945 EP_SET_FFD(&epi->ffd, tfile, fd); 970 ep_set_ffd(&epi->ffd, tfile, fd);
946 epi->event = *event; 971 epi->event = *event;
947 atomic_set(&epi->usecnt, 1); 972 atomic_set(&epi->usecnt, 1);
948 epi->nwait = 0; 973 epi->nwait = 0;
@@ -978,7 +1003,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
978 ep_rbtree_insert(ep, epi); 1003 ep_rbtree_insert(ep, epi);
979 1004
980 /* If the file is already "ready" we drop it inside the ready list */ 1005 /* If the file is already "ready" we drop it inside the ready list */
981 if ((revents & event->events) && !EP_IS_LINKED(&epi->rdllink)) { 1006 if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
982 list_add_tail(&epi->rdllink, &ep->rdllist); 1007 list_add_tail(&epi->rdllink, &ep->rdllist);
983 1008
984 /* Notify waiting tasks that events are available */ 1009 /* Notify waiting tasks that events are available */
@@ -1007,11 +1032,11 @@ eexit_2:
1007 * allocated wait queue. 1032 * allocated wait queue.
1008 */ 1033 */
1009 write_lock_irqsave(&ep->lock, flags); 1034 write_lock_irqsave(&ep->lock, flags);
1010 if (EP_IS_LINKED(&epi->rdllink)) 1035 if (ep_is_linked(&epi->rdllink))
1011 EP_LIST_DEL(&epi->rdllink); 1036 ep_list_del(&epi->rdllink);
1012 write_unlock_irqrestore(&ep->lock, flags); 1037 write_unlock_irqrestore(&ep->lock, flags);
1013 1038
1014 EPI_MEM_FREE(epi); 1039 kmem_cache_free(epi_cache, epi);
1015eexit_1: 1040eexit_1:
1016 return error; 1041 return error;
1017} 1042}
@@ -1050,14 +1075,14 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
1050 * If the item is not linked to the hash it means that it's on its 1075 * If the item is not linked to the hash it means that it's on its
1051 * way toward the removal. Do nothing in this case. 1076 * way toward the removal. Do nothing in this case.
1052 */ 1077 */
1053 if (EP_RB_LINKED(&epi->rbn)) { 1078 if (ep_rb_linked(&epi->rbn)) {
1054 /* 1079 /*
1055 * If the item is "hot" and it is not registered inside the ready 1080 * If the item is "hot" and it is not registered inside the ready
1056 * list, push it inside. If the item is not "hot" and it is currently 1081 * list, push it inside. If the item is not "hot" and it is currently
1057 * registered inside the ready list, unlink it. 1082 * registered inside the ready list, unlink it.
1058 */ 1083 */
1059 if (revents & event->events) { 1084 if (revents & event->events) {
1060 if (!EP_IS_LINKED(&epi->rdllink)) { 1085 if (!ep_is_linked(&epi->rdllink)) {
1061 list_add_tail(&epi->rdllink, &ep->rdllist); 1086 list_add_tail(&epi->rdllink, &ep->rdllist);
1062 1087
1063 /* Notify waiting tasks that events are available */ 1088 /* Notify waiting tasks that events are available */
@@ -1097,9 +1122,9 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
1097 while (!list_empty(lsthead)) { 1122 while (!list_empty(lsthead)) {
1098 pwq = list_entry(lsthead->next, struct eppoll_entry, llink); 1123 pwq = list_entry(lsthead->next, struct eppoll_entry, llink);
1099 1124
1100 EP_LIST_DEL(&pwq->llink); 1125 ep_list_del(&pwq->llink);
1101 remove_wait_queue(pwq->whead, &pwq->wait); 1126 remove_wait_queue(pwq->whead, &pwq->wait);
1102 PWQ_MEM_FREE(pwq); 1127 kmem_cache_free(pwq_cache, pwq);
1103 } 1128 }
1104 } 1129 }
1105} 1130}
@@ -1118,7 +1143,7 @@ static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
1118 * The check protect us from doing a double unlink ( crash ). 1143 * The check protect us from doing a double unlink ( crash ).
1119 */ 1144 */
1120 error = -ENOENT; 1145 error = -ENOENT;
1121 if (!EP_RB_LINKED(&epi->rbn)) 1146 if (!ep_rb_linked(&epi->rbn))
1122 goto eexit_1; 1147 goto eexit_1;
1123 1148
1124 /* 1149 /*
@@ -1133,14 +1158,14 @@ static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
1133 * This operation togheter with the above check closes the door to 1158 * This operation togheter with the above check closes the door to
1134 * double unlinks. 1159 * double unlinks.
1135 */ 1160 */
1136 EP_RB_ERASE(&epi->rbn, &ep->rbr); 1161 ep_rb_erase(&epi->rbn, &ep->rbr);
1137 1162
1138 /* 1163 /*
1139 * If the item we are going to remove is inside the ready file descriptors 1164 * If the item we are going to remove is inside the ready file descriptors
1140 * we want to remove it from this list to avoid stale events. 1165 * we want to remove it from this list to avoid stale events.
1141 */ 1166 */
1142 if (EP_IS_LINKED(&epi->rdllink)) 1167 if (ep_is_linked(&epi->rdllink))
1143 EP_LIST_DEL(&epi->rdllink); 1168 ep_list_del(&epi->rdllink);
1144 1169
1145 error = 0; 1170 error = 0;
1146eexit_1: 1171eexit_1:
@@ -1174,8 +1199,8 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
1174 1199
1175 /* Remove the current item from the list of epoll hooks */ 1200 /* Remove the current item from the list of epoll hooks */
1176 spin_lock(&file->f_ep_lock); 1201 spin_lock(&file->f_ep_lock);
1177 if (EP_IS_LINKED(&epi->fllink)) 1202 if (ep_is_linked(&epi->fllink))
1178 EP_LIST_DEL(&epi->fllink); 1203 ep_list_del(&epi->fllink);
1179 spin_unlock(&file->f_ep_lock); 1204 spin_unlock(&file->f_ep_lock);
1180 1205
1181 /* We need to acquire the write IRQ lock before calling ep_unlink() */ 1206 /* We need to acquire the write IRQ lock before calling ep_unlink() */
@@ -1210,7 +1235,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
1210{ 1235{
1211 int pwake = 0; 1236 int pwake = 0;
1212 unsigned long flags; 1237 unsigned long flags;
1213 struct epitem *epi = EP_ITEM_FROM_WAIT(wait); 1238 struct epitem *epi = ep_item_from_wait(wait);
1214 struct eventpoll *ep = epi->ep; 1239 struct eventpoll *ep = epi->ep;
1215 1240
1216 DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n", 1241 DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
@@ -1228,7 +1253,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
1228 goto is_disabled; 1253 goto is_disabled;
1229 1254
1230 /* If this file is already in the ready list we exit soon */ 1255 /* If this file is already in the ready list we exit soon */
1231 if (EP_IS_LINKED(&epi->rdllink)) 1256 if (ep_is_linked(&epi->rdllink))
1232 goto is_linked; 1257 goto is_linked;
1233 1258
1234 list_add_tail(&epi->rdllink, &ep->rdllist); 1259 list_add_tail(&epi->rdllink, &ep->rdllist);
@@ -1307,7 +1332,7 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist
1307 lnk = lnk->next; 1332 lnk = lnk->next;
1308 1333
1309 /* If this file is already in the ready list we exit soon */ 1334 /* If this file is already in the ready list we exit soon */
1310 if (!EP_IS_LINKED(&epi->txlink)) { 1335 if (!ep_is_linked(&epi->txlink)) {
1311 /* 1336 /*
1312 * This is initialized in this way so that the default 1337 * This is initialized in this way so that the default
1313 * behaviour of the reinjecting code will be to push back 1338 * behaviour of the reinjecting code will be to push back
@@ -1322,7 +1347,7 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist
1322 /* 1347 /*
1323 * Unlink the item from the ready list. 1348 * Unlink the item from the ready list.
1324 */ 1349 */
1325 EP_LIST_DEL(&epi->rdllink); 1350 ep_list_del(&epi->rdllink);
1326 } 1351 }
1327 } 1352 }
1328 1353
@@ -1401,7 +1426,7 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
1401 epi = list_entry(txlist->next, struct epitem, txlink); 1426 epi = list_entry(txlist->next, struct epitem, txlink);
1402 1427
1403 /* Unlink the current item from the transfer list */ 1428 /* Unlink the current item from the transfer list */
1404 EP_LIST_DEL(&epi->txlink); 1429 ep_list_del(&epi->txlink);
1405 1430
1406 /* 1431 /*
1407 * If the item is no more linked to the interest set, we don't 1432 * If the item is no more linked to the interest set, we don't
@@ -1410,8 +1435,8 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
1410 * item is set to have an Edge Triggered behaviour, we don't have 1435 * item is set to have an Edge Triggered behaviour, we don't have
1411 * to push it back either. 1436 * to push it back either.
1412 */ 1437 */
1413 if (EP_RB_LINKED(&epi->rbn) && !(epi->event.events & EPOLLET) && 1438 if (ep_rb_linked(&epi->rbn) && !(epi->event.events & EPOLLET) &&
1414 (epi->revents & epi->event.events) && !EP_IS_LINKED(&epi->rdllink)) { 1439 (epi->revents & epi->event.events) && !ep_is_linked(&epi->rdllink)) {
1415 list_add_tail(&epi->rdllink, &ep->rdllist); 1440 list_add_tail(&epi->rdllink, &ep->rdllist);
1416 ricnt++; 1441 ricnt++;
1417 } 1442 }
diff --git a/fs/exec.c b/fs/exec.c
index e56ee2437025..48871917d363 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -58,6 +58,9 @@
58 58
59int core_uses_pid; 59int core_uses_pid;
60char core_pattern[65] = "core"; 60char core_pattern[65] = "core";
61int suid_dumpable = 0;
62
63EXPORT_SYMBOL(suid_dumpable);
61/* The maximal length of core_pattern is also specified in sysctl.c */ 64/* The maximal length of core_pattern is also specified in sysctl.c */
62 65
63static struct linux_binfmt *formats; 66static struct linux_binfmt *formats;
@@ -649,6 +652,7 @@ static inline int de_thread(struct task_struct *tsk)
649 } 652 }
650 sig->group_exit_task = NULL; 653 sig->group_exit_task = NULL;
651 sig->notify_count = 0; 654 sig->notify_count = 0;
655 sig->real_timer.data = (unsigned long)current;
652 spin_unlock_irq(lock); 656 spin_unlock_irq(lock);
653 657
654 /* 658 /*
@@ -675,10 +679,8 @@ static inline int de_thread(struct task_struct *tsk)
675 proc_dentry2 = proc_pid_unhash(leader); 679 proc_dentry2 = proc_pid_unhash(leader);
676 write_lock_irq(&tasklist_lock); 680 write_lock_irq(&tasklist_lock);
677 681
678 if (leader->tgid != current->tgid) 682 BUG_ON(leader->tgid != current->tgid);
679 BUG(); 683 BUG_ON(current->pid == current->tgid);
680 if (current->pid == current->tgid)
681 BUG();
682 /* 684 /*
683 * An exec() starts a new thread group with the 685 * An exec() starts a new thread group with the
684 * TGID of the previous thread group. Rehash the 686 * TGID of the previous thread group. Rehash the
@@ -726,8 +728,7 @@ static inline int de_thread(struct task_struct *tsk)
726 proc_pid_flush(proc_dentry1); 728 proc_pid_flush(proc_dentry1);
727 proc_pid_flush(proc_dentry2); 729 proc_pid_flush(proc_dentry2);
728 730
729 if (exit_state != EXIT_ZOMBIE) 731 BUG_ON(exit_state != EXIT_ZOMBIE);
730 BUG();
731 release_task(leader); 732 release_task(leader);
732 } 733 }
733 734
@@ -772,10 +773,8 @@ no_thread_group:
772 kmem_cache_free(sighand_cachep, oldsighand); 773 kmem_cache_free(sighand_cachep, oldsighand);
773 } 774 }
774 775
775 if (!thread_group_empty(current)) 776 BUG_ON(!thread_group_empty(current));
776 BUG(); 777 BUG_ON(!thread_group_leader(current));
777 if (!thread_group_leader(current))
778 BUG();
779 return 0; 778 return 0;
780} 779}
781 780
@@ -868,6 +867,9 @@ int flush_old_exec(struct linux_binprm * bprm)
868 867
869 if (current->euid == current->uid && current->egid == current->gid) 868 if (current->euid == current->uid && current->egid == current->gid)
870 current->mm->dumpable = 1; 869 current->mm->dumpable = 1;
870 else
871 current->mm->dumpable = suid_dumpable;
872
871 name = bprm->filename; 873 name = bprm->filename;
872 874
873 /* Copies the binary name from after last slash */ 875 /* Copies the binary name from after last slash */
@@ -888,7 +890,7 @@ int flush_old_exec(struct linux_binprm * bprm)
888 permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || 890 permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
889 (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { 891 (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
890 suid_keys(current); 892 suid_keys(current);
891 current->mm->dumpable = 0; 893 current->mm->dumpable = suid_dumpable;
892 } 894 }
893 895
894 /* An exec changes our domain. We are no longer part of the thread 896 /* An exec changes our domain. We are no longer part of the thread
@@ -1436,6 +1438,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1436 struct inode * inode; 1438 struct inode * inode;
1437 struct file * file; 1439 struct file * file;
1438 int retval = 0; 1440 int retval = 0;
1441 int fsuid = current->fsuid;
1442 int flag = 0;
1439 1443
1440 binfmt = current->binfmt; 1444 binfmt = current->binfmt;
1441 if (!binfmt || !binfmt->core_dump) 1445 if (!binfmt || !binfmt->core_dump)
@@ -1445,6 +1449,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1445 up_write(&mm->mmap_sem); 1449 up_write(&mm->mmap_sem);
1446 goto fail; 1450 goto fail;
1447 } 1451 }
1452
1453 /*
1454 * We cannot trust fsuid as being the "true" uid of the
1455 * process nor do we know its entire history. We only know it
1456 * was tainted so we dump it as root in mode 2.
1457 */
1458 if (mm->dumpable == 2) { /* Setuid core dump mode */
1459 flag = O_EXCL; /* Stop rewrite attacks */
1460 current->fsuid = 0; /* Dump root private */
1461 }
1448 mm->dumpable = 0; 1462 mm->dumpable = 0;
1449 init_completion(&mm->core_done); 1463 init_completion(&mm->core_done);
1450 spin_lock_irq(&current->sighand->siglock); 1464 spin_lock_irq(&current->sighand->siglock);
@@ -1470,7 +1484,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1470 lock_kernel(); 1484 lock_kernel();
1471 format_corename(corename, core_pattern, signr); 1485 format_corename(corename, core_pattern, signr);
1472 unlock_kernel(); 1486 unlock_kernel();
1473 file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600); 1487 file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600);
1474 if (IS_ERR(file)) 1488 if (IS_ERR(file))
1475 goto fail_unlock; 1489 goto fail_unlock;
1476 inode = file->f_dentry->d_inode; 1490 inode = file->f_dentry->d_inode;
@@ -1495,6 +1509,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1495close_fail: 1509close_fail:
1496 filp_close(file, NULL); 1510 filp_close(file, NULL);
1497fail_unlock: 1511fail_unlock:
1512 current->fsuid = fsuid;
1498 complete_all(&mm->core_done); 1513 complete_all(&mm->core_done);
1499fail: 1514fail:
1500 return retval; 1515 return retval;
diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile
index ee240a14e70f..c5d02da73bc3 100644
--- a/fs/ext2/Makefile
+++ b/fs/ext2/Makefile
@@ -10,3 +10,4 @@ ext2-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
10ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o 10ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
11ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o 11ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o
12ext2-$(CONFIG_EXT2_FS_SECURITY) += xattr_security.o 12ext2-$(CONFIG_EXT2_FS_SECURITY) += xattr_security.o
13ext2-$(CONFIG_EXT2_FS_XIP) += xip.o
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 25f4a64fd6bc..213148c36ebe 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -396,12 +396,12 @@ static size_t
396ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size, 396ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
397 const char *name, size_t name_len) 397 const char *name, size_t name_len)
398{ 398{
399 const size_t size = sizeof(XATTR_NAME_ACL_ACCESS); 399 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
400 400
401 if (!test_opt(inode->i_sb, POSIX_ACL)) 401 if (!test_opt(inode->i_sb, POSIX_ACL))
402 return 0; 402 return 0;
403 if (list && size <= list_size) 403 if (list && size <= list_size)
404 memcpy(list, XATTR_NAME_ACL_ACCESS, size); 404 memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
405 return size; 405 return size;
406} 406}
407 407
@@ -409,12 +409,12 @@ static size_t
409ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size, 409ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
410 const char *name, size_t name_len) 410 const char *name, size_t name_len)
411{ 411{
412 const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT); 412 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
413 413
414 if (!test_opt(inode->i_sb, POSIX_ACL)) 414 if (!test_opt(inode->i_sb, POSIX_ACL))
415 return 0; 415 return 0;
416 if (list && size <= list_size) 416 if (list && size <= list_size)
417 memcpy(list, XATTR_NAME_ACL_DEFAULT, size); 417 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
418 return size; 418 return size;
419} 419}
420 420
@@ -506,14 +506,14 @@ ext2_xattr_set_acl_default(struct inode *inode, const char *name,
506} 506}
507 507
508struct xattr_handler ext2_xattr_acl_access_handler = { 508struct xattr_handler ext2_xattr_acl_access_handler = {
509 .prefix = XATTR_NAME_ACL_ACCESS, 509 .prefix = POSIX_ACL_XATTR_ACCESS,
510 .list = ext2_xattr_list_acl_access, 510 .list = ext2_xattr_list_acl_access,
511 .get = ext2_xattr_get_acl_access, 511 .get = ext2_xattr_get_acl_access,
512 .set = ext2_xattr_set_acl_access, 512 .set = ext2_xattr_set_acl_access,
513}; 513};
514 514
515struct xattr_handler ext2_xattr_acl_default_handler = { 515struct xattr_handler ext2_xattr_acl_default_handler = {
516 .prefix = XATTR_NAME_ACL_DEFAULT, 516 .prefix = POSIX_ACL_XATTR_DEFAULT,
517 .list = ext2_xattr_list_acl_default, 517 .list = ext2_xattr_list_acl_default,
518 .get = ext2_xattr_get_acl_default, 518 .get = ext2_xattr_get_acl_default,
519 .set = ext2_xattr_set_acl_default, 519 .set = ext2_xattr_set_acl_default,
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index fed96ae81a7d..0bde85bafe38 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -4,7 +4,7 @@
4 (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org> 4 (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5*/ 5*/
6 6
7#include <linux/xattr_acl.h> 7#include <linux/posix_acl_xattr.h>
8 8
9#define EXT2_ACL_VERSION 0x0001 9#define EXT2_ACL_VERSION 0x0001
10 10
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 8f0fd726c3f1..eed521d22cf0 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -147,9 +147,11 @@ extern struct file_operations ext2_dir_operations;
147/* file.c */ 147/* file.c */
148extern struct inode_operations ext2_file_inode_operations; 148extern struct inode_operations ext2_file_inode_operations;
149extern struct file_operations ext2_file_operations; 149extern struct file_operations ext2_file_operations;
150extern struct file_operations ext2_xip_file_operations;
150 151
151/* inode.c */ 152/* inode.c */
152extern struct address_space_operations ext2_aops; 153extern struct address_space_operations ext2_aops;
154extern struct address_space_operations ext2_aops_xip;
153extern struct address_space_operations ext2_nobh_aops; 155extern struct address_space_operations ext2_nobh_aops;
154 156
155/* namei.c */ 157/* namei.c */
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index f5e86141ec54..a484412fc782 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -55,6 +55,20 @@ struct file_operations ext2_file_operations = {
55 .sendfile = generic_file_sendfile, 55 .sendfile = generic_file_sendfile,
56}; 56};
57 57
58#ifdef CONFIG_EXT2_FS_XIP
59struct file_operations ext2_xip_file_operations = {
60 .llseek = generic_file_llseek,
61 .read = xip_file_read,
62 .write = xip_file_write,
63 .ioctl = ext2_ioctl,
64 .mmap = xip_file_mmap,
65 .open = generic_file_open,
66 .release = ext2_release_file,
67 .fsync = ext2_sync_file,
68 .sendfile = xip_file_sendfile,
69};
70#endif
71
58struct inode_operations ext2_file_inode_operations = { 72struct inode_operations ext2_file_inode_operations = {
59 .truncate = ext2_truncate, 73 .truncate = ext2_truncate,
60#ifdef CONFIG_EXT2_FS_XATTR 74#ifdef CONFIG_EXT2_FS_XATTR
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a50d9db4b6e4..53dceb0c6593 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -33,6 +33,7 @@
33#include <linux/mpage.h> 33#include <linux/mpage.h>
34#include "ext2.h" 34#include "ext2.h"
35#include "acl.h" 35#include "acl.h"
36#include "xip.h"
36 37
37MODULE_AUTHOR("Remy Card and others"); 38MODULE_AUTHOR("Remy Card and others");
38MODULE_DESCRIPTION("Second Extended Filesystem"); 39MODULE_DESCRIPTION("Second Extended Filesystem");
@@ -594,6 +595,16 @@ out:
594 if (err) 595 if (err)
595 goto cleanup; 596 goto cleanup;
596 597
598 if (ext2_use_xip(inode->i_sb)) {
599 /*
600 * we need to clear the block
601 */
602 err = ext2_clear_xip_target (inode,
603 le32_to_cpu(chain[depth-1].key));
604 if (err)
605 goto cleanup;
606 }
607
597 if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0) 608 if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0)
598 goto changed; 609 goto changed;
599 610
@@ -691,6 +702,11 @@ struct address_space_operations ext2_aops = {
691 .writepages = ext2_writepages, 702 .writepages = ext2_writepages,
692}; 703};
693 704
705struct address_space_operations ext2_aops_xip = {
706 .bmap = ext2_bmap,
707 .get_xip_page = ext2_get_xip_page,
708};
709
694struct address_space_operations ext2_nobh_aops = { 710struct address_space_operations ext2_nobh_aops = {
695 .readpage = ext2_readpage, 711 .readpage = ext2_readpage,
696 .readpages = ext2_readpages, 712 .readpages = ext2_readpages,
@@ -910,7 +926,9 @@ void ext2_truncate (struct inode * inode)
910 iblock = (inode->i_size + blocksize-1) 926 iblock = (inode->i_size + blocksize-1)
911 >> EXT2_BLOCK_SIZE_BITS(inode->i_sb); 927 >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
912 928
913 if (test_opt(inode->i_sb, NOBH)) 929 if (mapping_is_xip(inode->i_mapping))
930 xip_truncate_page(inode->i_mapping, inode->i_size);
931 else if (test_opt(inode->i_sb, NOBH))
914 nobh_truncate_page(inode->i_mapping, inode->i_size); 932 nobh_truncate_page(inode->i_mapping, inode->i_size);
915 else 933 else
916 block_truncate_page(inode->i_mapping, 934 block_truncate_page(inode->i_mapping,
@@ -1110,11 +1128,16 @@ void ext2_read_inode (struct inode * inode)
1110 1128
1111 if (S_ISREG(inode->i_mode)) { 1129 if (S_ISREG(inode->i_mode)) {
1112 inode->i_op = &ext2_file_inode_operations; 1130 inode->i_op = &ext2_file_inode_operations;
1113 inode->i_fop = &ext2_file_operations; 1131 if (ext2_use_xip(inode->i_sb)) {
1114 if (test_opt(inode->i_sb, NOBH)) 1132 inode->i_mapping->a_ops = &ext2_aops_xip;
1133 inode->i_fop = &ext2_xip_file_operations;
1134 } else if (test_opt(inode->i_sb, NOBH)) {
1115 inode->i_mapping->a_ops = &ext2_nobh_aops; 1135 inode->i_mapping->a_ops = &ext2_nobh_aops;
1116 else 1136 inode->i_fop = &ext2_file_operations;
1137 } else {
1117 inode->i_mapping->a_ops = &ext2_aops; 1138 inode->i_mapping->a_ops = &ext2_aops;
1139 inode->i_fop = &ext2_file_operations;
1140 }
1118 } else if (S_ISDIR(inode->i_mode)) { 1141 } else if (S_ISDIR(inode->i_mode)) {
1119 inode->i_op = &ext2_dir_inode_operations; 1142 inode->i_op = &ext2_dir_inode_operations;
1120 inode->i_fop = &ext2_dir_operations; 1143 inode->i_fop = &ext2_dir_operations;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 3176b3d3ffa8..c5513953c825 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -34,6 +34,7 @@
34#include "ext2.h" 34#include "ext2.h"
35#include "xattr.h" 35#include "xattr.h"
36#include "acl.h" 36#include "acl.h"
37#include "xip.h"
37 38
38/* 39/*
39 * Couple of helper functions - make the code slightly cleaner. 40 * Couple of helper functions - make the code slightly cleaner.
@@ -127,11 +128,16 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st
127 int err = PTR_ERR(inode); 128 int err = PTR_ERR(inode);
128 if (!IS_ERR(inode)) { 129 if (!IS_ERR(inode)) {
129 inode->i_op = &ext2_file_inode_operations; 130 inode->i_op = &ext2_file_inode_operations;
130 inode->i_fop = &ext2_file_operations; 131 if (ext2_use_xip(inode->i_sb)) {
131 if (test_opt(inode->i_sb, NOBH)) 132 inode->i_mapping->a_ops = &ext2_aops_xip;
133 inode->i_fop = &ext2_xip_file_operations;
134 } else if (test_opt(inode->i_sb, NOBH)) {
132 inode->i_mapping->a_ops = &ext2_nobh_aops; 135 inode->i_mapping->a_ops = &ext2_nobh_aops;
133 else 136 inode->i_fop = &ext2_file_operations;
137 } else {
134 inode->i_mapping->a_ops = &ext2_aops; 138 inode->i_mapping->a_ops = &ext2_aops;
139 inode->i_fop = &ext2_file_operations;
140 }
135 mark_inode_dirty(inode); 141 mark_inode_dirty(inode);
136 err = ext2_add_nondir(dentry, inode); 142 err = ext2_add_nondir(dentry, inode);
137 } 143 }
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 661c3d98d946..876e391f2871 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -31,6 +31,7 @@
31#include "ext2.h" 31#include "ext2.h"
32#include "xattr.h" 32#include "xattr.h"
33#include "acl.h" 33#include "acl.h"
34#include "xip.h"
34 35
35static void ext2_sync_super(struct super_block *sb, 36static void ext2_sync_super(struct super_block *sb,
36 struct ext2_super_block *es); 37 struct ext2_super_block *es);
@@ -257,7 +258,7 @@ enum {
257 Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, 258 Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
258 Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, 259 Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
259 Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, 260 Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,
260 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, 261 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip,
261 Opt_ignore, Opt_err, 262 Opt_ignore, Opt_err,
262}; 263};
263 264
@@ -286,6 +287,7 @@ static match_table_t tokens = {
286 {Opt_nouser_xattr, "nouser_xattr"}, 287 {Opt_nouser_xattr, "nouser_xattr"},
287 {Opt_acl, "acl"}, 288 {Opt_acl, "acl"},
288 {Opt_noacl, "noacl"}, 289 {Opt_noacl, "noacl"},
290 {Opt_xip, "xip"},
289 {Opt_ignore, "grpquota"}, 291 {Opt_ignore, "grpquota"},
290 {Opt_ignore, "noquota"}, 292 {Opt_ignore, "noquota"},
291 {Opt_ignore, "quota"}, 293 {Opt_ignore, "quota"},
@@ -397,6 +399,13 @@ static int parse_options (char * options,
397 printk("EXT2 (no)acl options not supported\n"); 399 printk("EXT2 (no)acl options not supported\n");
398 break; 400 break;
399#endif 401#endif
402 case Opt_xip:
403#ifdef CONFIG_EXT2_FS_XIP
404 set_opt (sbi->s_mount_opt, XIP);
405#else
406 printk("EXT2 xip option not supported\n");
407#endif
408 break;
400 case Opt_ignore: 409 case Opt_ignore:
401 break; 410 break;
402 default: 411 default:
@@ -640,6 +649,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
640 ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? 649 ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
641 MS_POSIXACL : 0); 650 MS_POSIXACL : 0);
642 651
652 ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
653 EXT2_MOUNT_XIP if not */
654
643 if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV && 655 if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
644 (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) || 656 (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
645 EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) || 657 EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
@@ -668,6 +680,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
668 680
669 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); 681 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
670 682
683 if ((ext2_use_xip(sb)) && ((blocksize != PAGE_SIZE) ||
684 (sb->s_blocksize != blocksize))) {
685 if (!silent)
686 printk("XIP: Unsupported blocksize\n");
687 goto failed_mount;
688 }
689
671 /* If the blocksize doesn't match, re-read the thing.. */ 690 /* If the blocksize doesn't match, re-read the thing.. */
672 if (sb->s_blocksize != blocksize) { 691 if (sb->s_blocksize != blocksize) {
673 brelse(bh); 692 brelse(bh);
@@ -916,6 +935,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
916{ 935{
917 struct ext2_sb_info * sbi = EXT2_SB(sb); 936 struct ext2_sb_info * sbi = EXT2_SB(sb);
918 struct ext2_super_block * es; 937 struct ext2_super_block * es;
938 unsigned long old_mount_opt = sbi->s_mount_opt;
919 939
920 /* 940 /*
921 * Allow the "check" option to be passed as a remount option. 941 * Allow the "check" option to be passed as a remount option.
@@ -927,6 +947,11 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
927 ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); 947 ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
928 948
929 es = sbi->s_es; 949 es = sbi->s_es;
950 if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
951 (old_mount_opt & EXT2_MOUNT_XIP)) &&
952 invalidate_inodes(sb))
953 ext2_warning(sb, __FUNCTION__, "busy inodes while remounting "\
954 "xip remain in cache (no functional problem)");
930 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) 955 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
931 return 0; 956 return 0;
932 if (*flags & MS_RDONLY) { 957 if (*flags & MS_RDONLY) {
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
new file mode 100644
index 000000000000..d44431d1a338
--- /dev/null
+++ b/fs/ext2/xip.c
@@ -0,0 +1,80 @@
1/*
2 * linux/fs/ext2/xip.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 * Author: Carsten Otte (cotte@de.ibm.com)
6 */
7
8#include <linux/mm.h>
9#include <linux/fs.h>
10#include <linux/genhd.h>
11#include <linux/buffer_head.h>
12#include <linux/ext2_fs_sb.h>
13#include <linux/ext2_fs.h>
14#include "ext2.h"
15#include "xip.h"
16
17static inline int
18__inode_direct_access(struct inode *inode, sector_t sector, unsigned long *data) {
19 BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
20 return inode->i_sb->s_bdev->bd_disk->fops
21 ->direct_access(inode->i_sb->s_bdev,sector,data);
22}
23
24int
25ext2_clear_xip_target(struct inode *inode, int block) {
26 sector_t sector = block*(PAGE_SIZE/512);
27 unsigned long data;
28 int rc;
29
30 rc = __inode_direct_access(inode, sector, &data);
31 if (rc)
32 return rc;
33 clear_page((void*)data);
34 return 0;
35}
36
37void ext2_xip_verify_sb(struct super_block *sb)
38{
39 struct ext2_sb_info *sbi = EXT2_SB(sb);
40
41 if ((sbi->s_mount_opt & EXT2_MOUNT_XIP)) {
42 if ((sb->s_bdev == NULL) ||
43 sb->s_bdev->bd_disk == NULL ||
44 sb->s_bdev->bd_disk->fops == NULL ||
45 sb->s_bdev->bd_disk->fops->direct_access == NULL) {
46 sbi->s_mount_opt &= (~EXT2_MOUNT_XIP);
47 ext2_warning(sb, __FUNCTION__,
48 "ignoring xip option - not supported by bdev");
49 }
50 }
51}
52
53struct page*
54ext2_get_xip_page(struct address_space *mapping, sector_t blockno,
55 int create)
56{
57 int rc;
58 unsigned long data;
59 struct buffer_head tmp;
60
61 tmp.b_state = 0;
62 tmp.b_blocknr = 0;
63 rc = ext2_get_block(mapping->host, blockno/(PAGE_SIZE/512) , &tmp,
64 create);
65 if (rc)
66 return ERR_PTR(rc);
67 if (tmp.b_blocknr == 0) {
68 /* SPARSE block */
69 BUG_ON(create);
70 return ERR_PTR(-ENODATA);
71 }
72
73 rc = __inode_direct_access
74 (mapping->host,tmp.b_blocknr*(PAGE_SIZE/512) ,&data);
75 if (rc)
76 return ERR_PTR(rc);
77
78 SetPageUptodate(virt_to_page(data));
79 return virt_to_page(data);
80}
diff --git a/fs/ext2/xip.h b/fs/ext2/xip.h
new file mode 100644
index 000000000000..aa85331d6c56
--- /dev/null
+++ b/fs/ext2/xip.h
@@ -0,0 +1,25 @@
1/*
2 * linux/fs/ext2/xip.h
3 *
4 * Copyright (C) 2005 IBM Corporation
5 * Author: Carsten Otte (cotte@de.ibm.com)
6 */
7
8#ifdef CONFIG_EXT2_FS_XIP
9extern void ext2_xip_verify_sb (struct super_block *);
10extern int ext2_clear_xip_target (struct inode *, int);
11
12static inline int ext2_use_xip (struct super_block *sb)
13{
14 struct ext2_sb_info *sbi = EXT2_SB(sb);
15 return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
16}
17struct page* ext2_get_xip_page (struct address_space *, sector_t, int);
18#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page)
19#else
20#define mapping_is_xip(map) 0
21#define ext2_xip_verify_sb(sb) do { } while (0)
22#define ext2_use_xip(sb) 0
23#define ext2_clear_xip_target(inode, chain) 0
24#define ext2_get_xip_page NULL
25#endif
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 638c13a26c03..3ac38266fc9e 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -393,7 +393,8 @@ ext3_acl_chmod(struct inode *inode)
393 int retries = 0; 393 int retries = 0;
394 394
395 retry: 395 retry:
396 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); 396 handle = ext3_journal_start(inode,
397 EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
397 if (IS_ERR(handle)) { 398 if (IS_ERR(handle)) {
398 error = PTR_ERR(handle); 399 error = PTR_ERR(handle);
399 ext3_std_error(inode->i_sb, error); 400 ext3_std_error(inode->i_sb, error);
@@ -417,12 +418,12 @@ static size_t
417ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len, 418ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
418 const char *name, size_t name_len) 419 const char *name, size_t name_len)
419{ 420{
420 const size_t size = sizeof(XATTR_NAME_ACL_ACCESS); 421 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
421 422
422 if (!test_opt(inode->i_sb, POSIX_ACL)) 423 if (!test_opt(inode->i_sb, POSIX_ACL))
423 return 0; 424 return 0;
424 if (list && size <= list_len) 425 if (list && size <= list_len)
425 memcpy(list, XATTR_NAME_ACL_ACCESS, size); 426 memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
426 return size; 427 return size;
427} 428}
428 429
@@ -430,12 +431,12 @@ static size_t
430ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len, 431ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
431 const char *name, size_t name_len) 432 const char *name, size_t name_len)
432{ 433{
433 const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT); 434 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
434 435
435 if (!test_opt(inode->i_sb, POSIX_ACL)) 436 if (!test_opt(inode->i_sb, POSIX_ACL))
436 return 0; 437 return 0;
437 if (list && size <= list_len) 438 if (list && size <= list_len)
438 memcpy(list, XATTR_NAME_ACL_DEFAULT, size); 439 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
439 return size; 440 return size;
440} 441}
441 442
@@ -503,7 +504,7 @@ ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
503 acl = NULL; 504 acl = NULL;
504 505
505retry: 506retry:
506 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); 507 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
507 if (IS_ERR(handle)) 508 if (IS_ERR(handle))
508 return PTR_ERR(handle); 509 return PTR_ERR(handle);
509 error = ext3_set_acl(handle, inode, type, acl); 510 error = ext3_set_acl(handle, inode, type, acl);
@@ -535,14 +536,14 @@ ext3_xattr_set_acl_default(struct inode *inode, const char *name,
535} 536}
536 537
537struct xattr_handler ext3_xattr_acl_access_handler = { 538struct xattr_handler ext3_xattr_acl_access_handler = {
538 .prefix = XATTR_NAME_ACL_ACCESS, 539 .prefix = POSIX_ACL_XATTR_ACCESS,
539 .list = ext3_xattr_list_acl_access, 540 .list = ext3_xattr_list_acl_access,
540 .get = ext3_xattr_get_acl_access, 541 .get = ext3_xattr_get_acl_access,
541 .set = ext3_xattr_set_acl_access, 542 .set = ext3_xattr_set_acl_access,
542}; 543};
543 544
544struct xattr_handler ext3_xattr_acl_default_handler = { 545struct xattr_handler ext3_xattr_acl_default_handler = {
545 .prefix = XATTR_NAME_ACL_DEFAULT, 546 .prefix = POSIX_ACL_XATTR_DEFAULT,
546 .list = ext3_xattr_list_acl_default, 547 .list = ext3_xattr_list_acl_default,
547 .get = ext3_xattr_get_acl_default, 548 .get = ext3_xattr_get_acl_default,
548 .set = ext3_xattr_set_acl_default, 549 .set = ext3_xattr_set_acl_default,
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 98af0c0d0ba9..92d50b53a933 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -4,7 +4,7 @@
4 (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org> 4 (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5*/ 5*/
6 6
7#include <linux/xattr_acl.h> 7#include <linux/posix_acl_xattr.h>
8 8
9#define EXT3_ACL_VERSION 0x0001 9#define EXT3_ACL_VERSION 0x0001
10 10
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 0d5fa73b18dc..0b2db4f618cb 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -128,7 +128,7 @@ static unsigned long blocks_for_truncate(struct inode *inode)
128 if (needed > EXT3_MAX_TRANS_DATA) 128 if (needed > EXT3_MAX_TRANS_DATA)
129 needed = EXT3_MAX_TRANS_DATA; 129 needed = EXT3_MAX_TRANS_DATA;
130 130
131 return EXT3_DATA_TRANS_BLOCKS + needed; 131 return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
132} 132}
133 133
134/* 134/*
@@ -2763,7 +2763,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
2763 2763
2764 /* (user+group)*(old+new) structure, inode write (sb, 2764 /* (user+group)*(old+new) structure, inode write (sb,
2765 * inode block, ? - but truncate inode update has it) */ 2765 * inode block, ? - but truncate inode update has it) */
2766 handle = ext3_journal_start(inode, 4*EXT3_QUOTA_INIT_BLOCKS+3); 2766 handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
2767 EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
2767 if (IS_ERR(handle)) { 2768 if (IS_ERR(handle)) {
2768 error = PTR_ERR(handle); 2769 error = PTR_ERR(handle);
2769 goto err_out; 2770 goto err_out;
@@ -2861,7 +2862,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode)
2861#ifdef CONFIG_QUOTA 2862#ifdef CONFIG_QUOTA
2862 /* We know that structure was already allocated during DQUOT_INIT so 2863 /* We know that structure was already allocated during DQUOT_INIT so
2863 * we will be updating only the data blocks + inodes */ 2864 * we will be updating only the data blocks + inodes */
2864 ret += 2*EXT3_QUOTA_TRANS_BLOCKS; 2865 ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb);
2865#endif 2866#endif
2866 2867
2867 return ret; 2868 return ret;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 79742d824a0a..50378d8ff84b 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -932,8 +932,16 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
932 struct inode *dir = dentry->d_parent->d_inode; 932 struct inode *dir = dentry->d_parent->d_inode;
933 933
934 sb = dir->i_sb; 934 sb = dir->i_sb;
935 if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err))) 935 /* NFS may look up ".." - look at dx_root directory block */
936 return NULL; 936 if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
937 if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
938 return NULL;
939 } else {
940 frame = frames;
941 frame->bh = NULL; /* for dx_release() */
942 frame->at = (struct dx_entry *)frames; /* hack for zero entry*/
943 dx_set_block(frame->at, 0); /* dx_root block is 0 */
944 }
937 hash = hinfo.hash; 945 hash = hinfo.hash;
938 do { 946 do {
939 block = dx_get_block(frame->at); 947 block = dx_get_block(frame->at);
@@ -1637,9 +1645,9 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
1637 int err, retries = 0; 1645 int err, retries = 0;
1638 1646
1639retry: 1647retry:
1640 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 1648 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
1641 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 1649 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
1642 2*EXT3_QUOTA_INIT_BLOCKS); 1650 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
1643 if (IS_ERR(handle)) 1651 if (IS_ERR(handle))
1644 return PTR_ERR(handle); 1652 return PTR_ERR(handle);
1645 1653
@@ -1671,9 +1679,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
1671 return -EINVAL; 1679 return -EINVAL;
1672 1680
1673retry: 1681retry:
1674 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 1682 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
1675 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 1683 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
1676 2*EXT3_QUOTA_INIT_BLOCKS); 1684 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
1677 if (IS_ERR(handle)) 1685 if (IS_ERR(handle))
1678 return PTR_ERR(handle); 1686 return PTR_ERR(handle);
1679 1687
@@ -1707,9 +1715,9 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
1707 return -EMLINK; 1715 return -EMLINK;
1708 1716
1709retry: 1717retry:
1710 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 1718 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
1711 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 1719 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
1712 2*EXT3_QUOTA_INIT_BLOCKS); 1720 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
1713 if (IS_ERR(handle)) 1721 if (IS_ERR(handle))
1714 return PTR_ERR(handle); 1722 return PTR_ERR(handle);
1715 1723
@@ -1998,7 +2006,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
1998 /* Initialize quotas before so that eventual writes go in 2006 /* Initialize quotas before so that eventual writes go in
1999 * separate transaction */ 2007 * separate transaction */
2000 DQUOT_INIT(dentry->d_inode); 2008 DQUOT_INIT(dentry->d_inode);
2001 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); 2009 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
2002 if (IS_ERR(handle)) 2010 if (IS_ERR(handle))
2003 return PTR_ERR(handle); 2011 return PTR_ERR(handle);
2004 2012
@@ -2057,7 +2065,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
2057 /* Initialize quotas before so that eventual writes go 2065 /* Initialize quotas before so that eventual writes go
2058 * in separate transaction */ 2066 * in separate transaction */
2059 DQUOT_INIT(dentry->d_inode); 2067 DQUOT_INIT(dentry->d_inode);
2060 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); 2068 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
2061 if (IS_ERR(handle)) 2069 if (IS_ERR(handle))
2062 return PTR_ERR(handle); 2070 return PTR_ERR(handle);
2063 2071
@@ -2112,9 +2120,9 @@ static int ext3_symlink (struct inode * dir,
2112 return -ENAMETOOLONG; 2120 return -ENAMETOOLONG;
2113 2121
2114retry: 2122retry:
2115 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 2123 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
2116 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + 2124 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
2117 2*EXT3_QUOTA_INIT_BLOCKS); 2125 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
2118 if (IS_ERR(handle)) 2126 if (IS_ERR(handle))
2119 return PTR_ERR(handle); 2127 return PTR_ERR(handle);
2120 2128
@@ -2166,7 +2174,7 @@ static int ext3_link (struct dentry * old_dentry,
2166 return -EMLINK; 2174 return -EMLINK;
2167 2175
2168retry: 2176retry:
2169 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 2177 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
2170 EXT3_INDEX_EXTRA_TRANS_BLOCKS); 2178 EXT3_INDEX_EXTRA_TRANS_BLOCKS);
2171 if (IS_ERR(handle)) 2179 if (IS_ERR(handle))
2172 return PTR_ERR(handle); 2180 return PTR_ERR(handle);
@@ -2208,7 +2216,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
2208 * in separate transaction */ 2216 * in separate transaction */
2209 if (new_dentry->d_inode) 2217 if (new_dentry->d_inode)
2210 DQUOT_INIT(new_dentry->d_inode); 2218 DQUOT_INIT(new_dentry->d_inode);
2211 handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2219 handle = ext3_journal_start(old_dir, 2 *
2220 EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
2212 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); 2221 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
2213 if (IS_ERR(handle)) 2222 if (IS_ERR(handle))
2214 return PTR_ERR(handle); 2223 return PTR_ERR(handle);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 981ccb233ef5..b4b3e8a39131 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -589,7 +589,7 @@ enum {
589 Opt_commit, Opt_journal_update, Opt_journal_inum, 589 Opt_commit, Opt_journal_update, Opt_journal_inum,
590 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, 590 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
591 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, 591 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
592 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, 592 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
593 Opt_ignore, Opt_barrier, Opt_err, Opt_resize, 593 Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
594}; 594};
595 595
@@ -634,10 +634,10 @@ static match_table_t tokens = {
634 {Opt_grpjquota, "grpjquota=%s"}, 634 {Opt_grpjquota, "grpjquota=%s"},
635 {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, 635 {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
636 {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, 636 {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
637 {Opt_ignore, "grpquota"}, 637 {Opt_quota, "grpquota"},
638 {Opt_ignore, "noquota"}, 638 {Opt_noquota, "noquota"},
639 {Opt_ignore, "quota"}, 639 {Opt_quota, "quota"},
640 {Opt_ignore, "usrquota"}, 640 {Opt_quota, "usrquota"},
641 {Opt_barrier, "barrier=%u"}, 641 {Opt_barrier, "barrier=%u"},
642 {Opt_err, NULL}, 642 {Opt_err, NULL},
643 {Opt_resize, "resize"}, 643 {Opt_resize, "resize"},
@@ -876,6 +876,7 @@ set_qf_name:
876 sbi->s_qf_names[qtype] = NULL; 876 sbi->s_qf_names[qtype] = NULL;
877 return 0; 877 return 0;
878 } 878 }
879 set_opt(sbi->s_mount_opt, QUOTA);
879 break; 880 break;
880 case Opt_offusrjquota: 881 case Opt_offusrjquota:
881 qtype = USRQUOTA; 882 qtype = USRQUOTA;
@@ -898,6 +899,17 @@ clear_qf_name:
898 case Opt_jqfmt_vfsv0: 899 case Opt_jqfmt_vfsv0:
899 sbi->s_jquota_fmt = QFMT_VFS_V0; 900 sbi->s_jquota_fmt = QFMT_VFS_V0;
900 break; 901 break;
902 case Opt_quota:
903 set_opt(sbi->s_mount_opt, QUOTA);
904 break;
905 case Opt_noquota:
906 if (sb_any_quota_enabled(sb)) {
907 printk(KERN_ERR "EXT3-fs: Cannot change quota "
908 "options when quota turned on.\n");
909 return 0;
910 }
911 clear_opt(sbi->s_mount_opt, QUOTA);
912 break;
901#else 913#else
902 case Opt_usrjquota: 914 case Opt_usrjquota:
903 case Opt_grpjquota: 915 case Opt_grpjquota:
@@ -909,6 +921,9 @@ clear_qf_name:
909 "EXT3-fs: journalled quota options not " 921 "EXT3-fs: journalled quota options not "
910 "supported.\n"); 922 "supported.\n");
911 break; 923 break;
924 case Opt_quota:
925 case Opt_noquota:
926 break;
912#endif 927#endif
913 case Opt_abort: 928 case Opt_abort:
914 set_opt(sbi->s_mount_opt, ABORT); 929 set_opt(sbi->s_mount_opt, ABORT);
@@ -2238,7 +2253,7 @@ static int ext3_dquot_initialize(struct inode *inode, int type)
2238 int ret, err; 2253 int ret, err;
2239 2254
2240 /* We may create quota structure so we need to reserve enough blocks */ 2255 /* We may create quota structure so we need to reserve enough blocks */
2241 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); 2256 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
2242 if (IS_ERR(handle)) 2257 if (IS_ERR(handle))
2243 return PTR_ERR(handle); 2258 return PTR_ERR(handle);
2244 ret = dquot_initialize(inode, type); 2259 ret = dquot_initialize(inode, type);
@@ -2254,7 +2269,7 @@ static int ext3_dquot_drop(struct inode *inode)
2254 int ret, err; 2269 int ret, err;
2255 2270
2256 /* We may delete quota structure so we need to reserve enough blocks */ 2271 /* We may delete quota structure so we need to reserve enough blocks */
2257 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); 2272 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
2258 if (IS_ERR(handle)) 2273 if (IS_ERR(handle))
2259 return PTR_ERR(handle); 2274 return PTR_ERR(handle);
2260 ret = dquot_drop(inode); 2275 ret = dquot_drop(inode);
@@ -2272,7 +2287,7 @@ static int ext3_write_dquot(struct dquot *dquot)
2272 2287
2273 inode = dquot_to_inode(dquot); 2288 inode = dquot_to_inode(dquot);
2274 handle = ext3_journal_start(inode, 2289 handle = ext3_journal_start(inode,
2275 EXT3_QUOTA_TRANS_BLOCKS); 2290 EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
2276 if (IS_ERR(handle)) 2291 if (IS_ERR(handle))
2277 return PTR_ERR(handle); 2292 return PTR_ERR(handle);
2278 ret = dquot_commit(dquot); 2293 ret = dquot_commit(dquot);
@@ -2288,7 +2303,7 @@ static int ext3_acquire_dquot(struct dquot *dquot)
2288 handle_t *handle; 2303 handle_t *handle;
2289 2304
2290 handle = ext3_journal_start(dquot_to_inode(dquot), 2305 handle = ext3_journal_start(dquot_to_inode(dquot),
2291 EXT3_QUOTA_INIT_BLOCKS); 2306 EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb));
2292 if (IS_ERR(handle)) 2307 if (IS_ERR(handle))
2293 return PTR_ERR(handle); 2308 return PTR_ERR(handle);
2294 ret = dquot_acquire(dquot); 2309 ret = dquot_acquire(dquot);
@@ -2304,7 +2319,7 @@ static int ext3_release_dquot(struct dquot *dquot)
2304 handle_t *handle; 2319 handle_t *handle;
2305 2320
2306 handle = ext3_journal_start(dquot_to_inode(dquot), 2321 handle = ext3_journal_start(dquot_to_inode(dquot),
2307 EXT3_QUOTA_INIT_BLOCKS); 2322 EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
2308 if (IS_ERR(handle)) 2323 if (IS_ERR(handle))
2309 return PTR_ERR(handle); 2324 return PTR_ERR(handle);
2310 ret = dquot_release(dquot); 2325 ret = dquot_release(dquot);
@@ -2348,22 +2363,8 @@ static int ext3_write_info(struct super_block *sb, int type)
2348 */ 2363 */
2349static int ext3_quota_on_mount(struct super_block *sb, int type) 2364static int ext3_quota_on_mount(struct super_block *sb, int type)
2350{ 2365{
2351 int err; 2366 return vfs_quota_on_mount(sb, EXT3_SB(sb)->s_qf_names[type],
2352 struct dentry *dentry; 2367 EXT3_SB(sb)->s_jquota_fmt, type);
2353 struct qstr name = { .name = EXT3_SB(sb)->s_qf_names[type],
2354 .hash = 0,
2355 .len = strlen(EXT3_SB(sb)->s_qf_names[type])};
2356
2357 dentry = lookup_hash(&name, sb->s_root);
2358 if (IS_ERR(dentry))
2359 return PTR_ERR(dentry);
2360 err = vfs_quota_on_mount(type, EXT3_SB(sb)->s_jquota_fmt, dentry);
2361 /* Now invalidate and put the dentry - quota got its own reference
2362 * to inode and dentry has at least wrong hash so we had better
2363 * throw it away */
2364 d_invalidate(dentry);
2365 dput(dentry);
2366 return err;
2367} 2368}
2368 2369
2369/* 2370/*
@@ -2375,6 +2376,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
2375 int err; 2376 int err;
2376 struct nameidata nd; 2377 struct nameidata nd;
2377 2378
2379 if (!test_opt(sb, QUOTA))
2380 return -EINVAL;
2378 /* Not journalling quota? */ 2381 /* Not journalling quota? */
2379 if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && 2382 if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
2380 !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) 2383 !EXT3_SB(sb)->s_qf_names[GRPQUOTA])
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 4cbc6d0212d3..3f9dfa643b19 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1044,7 +1044,7 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
1044 int error, retries = 0; 1044 int error, retries = 0;
1045 1045
1046retry: 1046retry:
1047 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); 1047 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
1048 if (IS_ERR(handle)) { 1048 if (IS_ERR(handle)) {
1049 error = PTR_ERR(handle); 1049 error = PTR_ERR(handle);
1050 } else { 1050 } else {
diff --git a/fs/file_table.c b/fs/file_table.c
index 03d83cb686b1..fa7849fae134 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -63,42 +63,45 @@ static inline void file_free(struct file *f)
63 */ 63 */
64struct file *get_empty_filp(void) 64struct file *get_empty_filp(void)
65{ 65{
66static int old_max; 66 static int old_max;
67 struct file * f; 67 struct file * f;
68 68
69 /* 69 /*
70 * Privileged users can go above max_files 70 * Privileged users can go above max_files
71 */ 71 */
72 if (files_stat.nr_files < files_stat.max_files || 72 if (files_stat.nr_files >= files_stat.max_files &&
73 capable(CAP_SYS_ADMIN)) { 73 !capable(CAP_SYS_ADMIN))
74 f = kmem_cache_alloc(filp_cachep, GFP_KERNEL); 74 goto over;
75 if (f) { 75
76 memset(f, 0, sizeof(*f)); 76 f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
77 if (security_file_alloc(f)) { 77 if (f == NULL)
78 file_free(f); 78 goto fail;
79 goto fail; 79
80 } 80 memset(f, 0, sizeof(*f));
81 eventpoll_init_file(f); 81 if (security_file_alloc(f))
82 atomic_set(&f->f_count, 1); 82 goto fail_sec;
83 f->f_uid = current->fsuid; 83
84 f->f_gid = current->fsgid; 84 eventpoll_init_file(f);
85 rwlock_init(&f->f_owner.lock); 85 atomic_set(&f->f_count, 1);
86 /* f->f_version: 0 */ 86 f->f_uid = current->fsuid;
87 INIT_LIST_HEAD(&f->f_list); 87 f->f_gid = current->fsgid;
88 f->f_maxcount = INT_MAX; 88 rwlock_init(&f->f_owner.lock);
89 return f; 89 /* f->f_version: 0 */
90 } 90 INIT_LIST_HEAD(&f->f_list);
91 } 91 f->f_maxcount = INT_MAX;
92 92 return f;
93
94over:
93 /* Ran out of filps - report that */ 95 /* Ran out of filps - report that */
94 if (files_stat.max_files >= old_max) { 96 if (files_stat.nr_files > old_max) {
95 printk(KERN_INFO "VFS: file-max limit %d reached\n", 97 printk(KERN_INFO "VFS: file-max limit %d reached\n",
96 files_stat.max_files); 98 files_stat.max_files);
97 old_max = files_stat.max_files; 99 old_max = files_stat.nr_files;
98 } else {
99 /* Big problems... */
100 printk(KERN_WARNING "VFS: filp allocation failed\n");
101 } 100 }
101 goto fail;
102
103fail_sec:
104 file_free(f);
102fail: 105fail:
103 return NULL; 106 return NULL;
104} 107}
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8e050fa58218..e94ab398b717 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -485,32 +485,6 @@ static void set_sb_syncing(int val)
485 spin_unlock(&sb_lock); 485 spin_unlock(&sb_lock);
486} 486}
487 487
488/*
489 * Find a superblock with inodes that need to be synced
490 */
491static struct super_block *get_super_to_sync(void)
492{
493 struct super_block *sb;
494restart:
495 spin_lock(&sb_lock);
496 sb = sb_entry(super_blocks.prev);
497 for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
498 if (sb->s_syncing)
499 continue;
500 sb->s_syncing = 1;
501 sb->s_count++;
502 spin_unlock(&sb_lock);
503 down_read(&sb->s_umount);
504 if (!sb->s_root) {
505 drop_super(sb);
506 goto restart;
507 }
508 return sb;
509 }
510 spin_unlock(&sb_lock);
511 return NULL;
512}
513
514/** 488/**
515 * sync_inodes - writes all inodes to disk 489 * sync_inodes - writes all inodes to disk
516 * @wait: wait for completion 490 * @wait: wait for completion
@@ -530,23 +504,39 @@ restart:
530 * outstanding dirty inodes, the writeback goes block-at-a-time within the 504 * outstanding dirty inodes, the writeback goes block-at-a-time within the
531 * filesystem's write_inode(). This is extremely slow. 505 * filesystem's write_inode(). This is extremely slow.
532 */ 506 */
533void sync_inodes(int wait) 507static void __sync_inodes(int wait)
534{ 508{
535 struct super_block *sb; 509 struct super_block *sb;
536 510
537 set_sb_syncing(0); 511 spin_lock(&sb_lock);
538 while ((sb = get_super_to_sync()) != NULL) { 512restart:
539 sync_inodes_sb(sb, 0); 513 list_for_each_entry(sb, &super_blocks, s_list) {
540 sync_blockdev(sb->s_bdev); 514 if (sb->s_syncing)
541 drop_super(sb); 515 continue;
516 sb->s_syncing = 1;
517 sb->s_count++;
518 spin_unlock(&sb_lock);
519 down_read(&sb->s_umount);
520 if (sb->s_root) {
521 sync_inodes_sb(sb, wait);
522 sync_blockdev(sb->s_bdev);
523 }
524 up_read(&sb->s_umount);
525 spin_lock(&sb_lock);
526 if (__put_super_and_need_restart(sb))
527 goto restart;
542 } 528 }
529 spin_unlock(&sb_lock);
530}
531
532void sync_inodes(int wait)
533{
534 set_sb_syncing(0);
535 __sync_inodes(0);
536
543 if (wait) { 537 if (wait) {
544 set_sb_syncing(0); 538 set_sb_syncing(0);
545 while ((sb = get_super_to_sync()) != NULL) { 539 __sync_inodes(1);
546 sync_inodes_sb(sb, 1);
547 sync_blockdev(sb->s_bdev);
548 drop_super(sb);
549 }
550 } 540 }
551} 541}
552 542
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 14a0d339d036..4bf43ea87c46 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -23,7 +23,6 @@
23#include "kern_util.h" 23#include "kern_util.h"
24#include "kern.h" 24#include "kern.h"
25#include "user_util.h" 25#include "user_util.h"
26#include "2_5compat.h"
27#include "init.h" 26#include "init.h"
28 27
29struct hostfs_inode_info { 28struct hostfs_inode_info {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 2af3338f891b..3a9b6d179cbd 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -122,6 +122,9 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
122 122
123 start_addr = mm->free_area_cache; 123 start_addr = mm->free_area_cache;
124 124
125 if (len <= mm->cached_hole_size)
126 start_addr = TASK_UNMAPPED_BASE;
127
125full_search: 128full_search:
126 addr = ALIGN(start_addr, HPAGE_SIZE); 129 addr = ALIGN(start_addr, HPAGE_SIZE);
127 130
diff --git a/fs/inode.c b/fs/inode.c
index 801fe7f36280..1f9a3a2b89bc 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -500,7 +500,7 @@ repeat:
500 continue; 500 continue;
501 if (!test(inode, data)) 501 if (!test(inode, data))
502 continue; 502 continue;
503 if (inode->i_state & (I_FREEING|I_CLEAR)) { 503 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
504 __wait_on_freeing_inode(inode); 504 __wait_on_freeing_inode(inode);
505 goto repeat; 505 goto repeat;
506 } 506 }
@@ -525,7 +525,7 @@ repeat:
525 continue; 525 continue;
526 if (inode->i_sb != sb) 526 if (inode->i_sb != sb)
527 continue; 527 continue;
528 if (inode->i_state & (I_FREEING|I_CLEAR)) { 528 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
529 __wait_on_freeing_inode(inode); 529 __wait_on_freeing_inode(inode);
530 goto repeat; 530 goto repeat;
531 } 531 }
@@ -727,7 +727,7 @@ EXPORT_SYMBOL(iunique);
727struct inode *igrab(struct inode *inode) 727struct inode *igrab(struct inode *inode)
728{ 728{
729 spin_lock(&inode_lock); 729 spin_lock(&inode_lock);
730 if (!(inode->i_state & I_FREEING)) 730 if (!(inode->i_state & (I_FREEING|I_WILL_FREE)))
731 __iget(inode); 731 __iget(inode);
732 else 732 else
733 /* 733 /*
@@ -1024,17 +1024,21 @@ static void generic_forget_inode(struct inode *inode)
1024 if (!(inode->i_state & (I_DIRTY|I_LOCK))) 1024 if (!(inode->i_state & (I_DIRTY|I_LOCK)))
1025 list_move(&inode->i_list, &inode_unused); 1025 list_move(&inode->i_list, &inode_unused);
1026 inodes_stat.nr_unused++; 1026 inodes_stat.nr_unused++;
1027 spin_unlock(&inode_lock); 1027 if (!sb || (sb->s_flags & MS_ACTIVE)) {
1028 if (!sb || (sb->s_flags & MS_ACTIVE)) 1028 spin_unlock(&inode_lock);
1029 return; 1029 return;
1030 }
1031 inode->i_state |= I_WILL_FREE;
1032 spin_unlock(&inode_lock);
1030 write_inode_now(inode, 1); 1033 write_inode_now(inode, 1);
1031 spin_lock(&inode_lock); 1034 spin_lock(&inode_lock);
1035 inode->i_state &= ~I_WILL_FREE;
1032 inodes_stat.nr_unused--; 1036 inodes_stat.nr_unused--;
1033 hlist_del_init(&inode->i_hash); 1037 hlist_del_init(&inode->i_hash);
1034 } 1038 }
1035 list_del_init(&inode->i_list); 1039 list_del_init(&inode->i_list);
1036 list_del_init(&inode->i_sb_list); 1040 list_del_init(&inode->i_sb_list);
1037 inode->i_state|=I_FREEING; 1041 inode->i_state |= I_FREEING;
1038 inodes_stat.nr_inodes--; 1042 inodes_stat.nr_inodes--;
1039 spin_unlock(&inode_lock); 1043 spin_unlock(&inode_lock);
1040 if (inode->i_data.nrpages) 1044 if (inode->i_data.nrpages)
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 6030956b894b..7901ac9f97ab 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -193,12 +193,17 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
193 193
194 /* Handle everything else. Do name translation if there 194 /* Handle everything else. Do name translation if there
195 is no Rock Ridge NM field. */ 195 is no Rock Ridge NM field. */
196 if (sbi->s_unhide == 'n') { 196
197 /* Do not report hidden or associated files */ 197 /*
198 if (de->flags[-sbi->s_high_sierra] & 5) { 198 * Do not report hidden files if so instructed, or associated
199 filp->f_pos += de_len; 199 * files unless instructed to do so
200 continue; 200 */
201 } 201 if ((sbi->s_hide == 'y' &&
202 (de->flags[-sbi->s_high_sierra] & 1)) ||
203 (sbi->s_showassoc =='n' &&
204 (de->flags[-sbi->s_high_sierra] & 4))) {
205 filp->f_pos += de_len;
206 continue;
202 } 207 }
203 208
204 map = 1; 209 map = 1;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index abd7b12eeca7..1652de1b6cb9 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -28,11 +28,6 @@
28 28
29#define BEQUIET 29#define BEQUIET
30 30
31#ifdef LEAK_CHECK
32static int check_malloc;
33static int check_bread;
34#endif
35
36static int isofs_hashi(struct dentry *parent, struct qstr *qstr); 31static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
37static int isofs_hash(struct dentry *parent, struct qstr *qstr); 32static int isofs_hash(struct dentry *parent, struct qstr *qstr);
38static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b); 33static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
@@ -55,11 +50,6 @@ static void isofs_put_super(struct super_block *sb)
55 } 50 }
56#endif 51#endif
57 52
58#ifdef LEAK_CHECK
59 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
60 check_malloc, check_bread);
61#endif
62
63 kfree(sbi); 53 kfree(sbi);
64 sb->s_fs_info = NULL; 54 sb->s_fs_info = NULL;
65 return; 55 return;
@@ -73,7 +63,7 @@ static kmem_cache_t *isofs_inode_cachep;
73static struct inode *isofs_alloc_inode(struct super_block *sb) 63static struct inode *isofs_alloc_inode(struct super_block *sb)
74{ 64{
75 struct iso_inode_info *ei; 65 struct iso_inode_info *ei;
76 ei = (struct iso_inode_info *)kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL); 66 ei = kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
77 if (!ei) 67 if (!ei)
78 return NULL; 68 return NULL;
79 return &ei->vfs_inode; 69 return &ei->vfs_inode;
@@ -84,9 +74,9 @@ static void isofs_destroy_inode(struct inode *inode)
84 kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode)); 74 kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
85} 75}
86 76
87static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) 77static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
88{ 78{
89 struct iso_inode_info *ei = (struct iso_inode_info *) foo; 79 struct iso_inode_info *ei = foo;
90 80
91 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 81 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
92 SLAB_CTOR_CONSTRUCTOR) 82 SLAB_CTOR_CONSTRUCTOR)
@@ -107,7 +97,8 @@ static int init_inodecache(void)
107static void destroy_inodecache(void) 97static void destroy_inodecache(void)
108{ 98{
109 if (kmem_cache_destroy(isofs_inode_cachep)) 99 if (kmem_cache_destroy(isofs_inode_cachep))
110 printk(KERN_INFO "iso_inode_cache: not all structures were freed\n"); 100 printk(KERN_INFO "iso_inode_cache: not all structures were "
101 "freed\n");
111} 102}
112 103
113static int isofs_remount(struct super_block *sb, int *flags, char *data) 104static int isofs_remount(struct super_block *sb, int *flags, char *data)
@@ -144,7 +135,7 @@ static struct dentry_operations isofs_dentry_ops[] = {
144 { 135 {
145 .d_hash = isofs_hashi_ms, 136 .d_hash = isofs_hashi_ms,
146 .d_compare = isofs_dentry_cmpi_ms, 137 .d_compare = isofs_dentry_cmpi_ms,
147 } 138 },
148#endif 139#endif
149}; 140};
150 141
@@ -153,7 +144,8 @@ struct iso9660_options{
153 char rock; 144 char rock;
154 char joliet; 145 char joliet;
155 char cruft; 146 char cruft;
156 char unhide; 147 char hide;
148 char showassoc;
157 char nocompress; 149 char nocompress;
158 unsigned char check; 150 unsigned char check;
159 unsigned int blocksize; 151 unsigned int blocksize;
@@ -219,8 +211,8 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
219/* 211/*
220 * Case insensitive compare of two isofs names. 212 * Case insensitive compare of two isofs names.
221 */ 213 */
222static int 214static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a,
223isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms) 215 struct qstr *b, int ms)
224{ 216{
225 int alen, blen; 217 int alen, blen;
226 218
@@ -243,8 +235,8 @@ isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int
243/* 235/*
244 * Case sensitive compare of two isofs names. 236 * Case sensitive compare of two isofs names.
245 */ 237 */
246static int 238static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a,
247isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms) 239 struct qstr *b, int ms)
248{ 240{
249 int alen, blen; 241 int alen, blen;
250 242
@@ -318,13 +310,15 @@ enum {
318 Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore, 310 Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
319 Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet, 311 Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
320 Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err, 312 Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
321 Opt_nocompress, 313 Opt_nocompress, Opt_hide, Opt_showassoc,
322}; 314};
323 315
324static match_table_t tokens = { 316static match_table_t tokens = {
325 {Opt_norock, "norock"}, 317 {Opt_norock, "norock"},
326 {Opt_nojoliet, "nojoliet"}, 318 {Opt_nojoliet, "nojoliet"},
327 {Opt_unhide, "unhide"}, 319 {Opt_unhide, "unhide"},
320 {Opt_hide, "hide"},
321 {Opt_showassoc, "showassoc"},
328 {Opt_cruft, "cruft"}, 322 {Opt_cruft, "cruft"},
329 {Opt_utf8, "utf8"}, 323 {Opt_utf8, "utf8"},
330 {Opt_iocharset, "iocharset=%s"}, 324 {Opt_iocharset, "iocharset=%s"},
@@ -356,7 +350,7 @@ static match_table_t tokens = {
356 {Opt_err, NULL} 350 {Opt_err, NULL}
357}; 351};
358 352
359static int parse_options(char *options, struct iso9660_options * popt) 353static int parse_options(char *options, struct iso9660_options *popt)
360{ 354{
361 char *p; 355 char *p;
362 int option; 356 int option;
@@ -365,7 +359,8 @@ static int parse_options(char *options, struct iso9660_options * popt)
365 popt->rock = 'y'; 359 popt->rock = 'y';
366 popt->joliet = 'y'; 360 popt->joliet = 'y';
367 popt->cruft = 'n'; 361 popt->cruft = 'n';
368 popt->unhide = 'n'; 362 popt->hide = 'n';
363 popt->showassoc = 'n';
369 popt->check = 'u'; /* unset */ 364 popt->check = 'u'; /* unset */
370 popt->nocompress = 0; 365 popt->nocompress = 0;
371 popt->blocksize = 1024; 366 popt->blocksize = 1024;
@@ -398,8 +393,12 @@ static int parse_options(char *options, struct iso9660_options * popt)
398 case Opt_nojoliet: 393 case Opt_nojoliet:
399 popt->joliet = 'n'; 394 popt->joliet = 'n';
400 break; 395 break;
396 case Opt_hide:
397 popt->hide = 'y';
398 break;
401 case Opt_unhide: 399 case Opt_unhide:
402 popt->unhide = 'y'; 400 case Opt_showassoc:
401 popt->showassoc = 'y';
403 break; 402 break;
404 case Opt_cruft: 403 case Opt_cruft:
405 popt->cruft = 'y'; 404 popt->cruft = 'y';
@@ -493,7 +492,7 @@ static int parse_options(char *options, struct iso9660_options * popt)
493 */ 492 */
494#define WE_OBEY_THE_WRITTEN_STANDARDS 1 493#define WE_OBEY_THE_WRITTEN_STANDARDS 1
495 494
496static unsigned int isofs_get_last_session(struct super_block *sb,s32 session ) 495static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
497{ 496{
498 struct cdrom_multisession ms_info; 497 struct cdrom_multisession ms_info;
499 unsigned int vol_desc_start; 498 unsigned int vol_desc_start;
@@ -518,7 +517,8 @@ static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
518 printk(KERN_ERR "Invalid session number or type of track\n"); 517 printk(KERN_ERR "Invalid session number or type of track\n");
519 } 518 }
520 i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info); 519 i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
521 if(session > 0) printk(KERN_ERR "Invalid session number\n"); 520 if (session > 0)
521 printk(KERN_ERR "Invalid session number\n");
522#if 0 522#if 0
523 printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i); 523 printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
524 if (i==0) { 524 if (i==0) {
@@ -557,13 +557,13 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
557 struct iso9660_options opt; 557 struct iso9660_options opt;
558 struct isofs_sb_info * sbi; 558 struct isofs_sb_info * sbi;
559 559
560 sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL); 560 sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
561 if (!sbi) 561 if (!sbi)
562 return -ENOMEM; 562 return -ENOMEM;
563 s->s_fs_info = sbi; 563 s->s_fs_info = sbi;
564 memset(sbi, 0, sizeof(struct isofs_sb_info)); 564 memset(sbi, 0, sizeof(*sbi));
565 565
566 if (!parse_options((char *) data, &opt)) 566 if (!parse_options((char *)data, &opt))
567 goto out_freesbi; 567 goto out_freesbi;
568 568
569 /* 569 /*
@@ -792,7 +792,8 @@ root_found:
792 sbi->s_rock = (opt.rock == 'y' ? 2 : 0); 792 sbi->s_rock = (opt.rock == 'y' ? 2 : 0);
793 sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/ 793 sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
794 sbi->s_cruft = opt.cruft; 794 sbi->s_cruft = opt.cruft;
795 sbi->s_unhide = opt.unhide; 795 sbi->s_hide = opt.hide;
796 sbi->s_showassoc = opt.showassoc;
796 sbi->s_uid = opt.uid; 797 sbi->s_uid = opt.uid;
797 sbi->s_gid = opt.gid; 798 sbi->s_gid = opt.gid;
798 sbi->s_utf8 = opt.utf8; 799 sbi->s_utf8 = opt.utf8;
@@ -1002,7 +1003,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
1002 rv++; 1003 rv++;
1003 } 1004 }
1004 1005
1005
1006abort: 1006abort:
1007 unlock_kernel(); 1007 unlock_kernel();
1008 return rv; 1008 return rv;
@@ -1014,7 +1014,7 @@ abort:
1014static int isofs_get_block(struct inode *inode, sector_t iblock, 1014static int isofs_get_block(struct inode *inode, sector_t iblock,
1015 struct buffer_head *bh_result, int create) 1015 struct buffer_head *bh_result, int create)
1016{ 1016{
1017 if ( create ) { 1017 if (create) {
1018 printk("isofs_get_block: Kernel tries to allocate a block\n"); 1018 printk("isofs_get_block: Kernel tries to allocate a block\n");
1019 return -EROFS; 1019 return -EROFS;
1020 } 1020 }
@@ -1061,19 +1061,17 @@ static struct address_space_operations isofs_aops = {
1061 1061
1062static inline void test_and_set_uid(uid_t *p, uid_t value) 1062static inline void test_and_set_uid(uid_t *p, uid_t value)
1063{ 1063{
1064 if(value) { 1064 if (value)
1065 *p = value; 1065 *p = value;
1066 }
1067} 1066}
1068 1067
1069static inline void test_and_set_gid(gid_t *p, gid_t value) 1068static inline void test_and_set_gid(gid_t *p, gid_t value)
1070{ 1069{
1071 if(value) { 1070 if (value)
1072 *p = value; 1071 *p = value;
1073 }
1074} 1072}
1075 1073
1076static int isofs_read_level3_size(struct inode * inode) 1074static int isofs_read_level3_size(struct inode *inode)
1077{ 1075{
1078 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); 1076 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
1079 int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra; 1077 int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
@@ -1136,7 +1134,7 @@ static int isofs_read_level3_size(struct inode * inode)
1136 bh = sb_bread(inode->i_sb, block); 1134 bh = sb_bread(inode->i_sb, block);
1137 if (!bh) 1135 if (!bh)
1138 goto out_noread; 1136 goto out_noread;
1139 memcpy((void *) tmpde + slop, bh->b_data, offset); 1137 memcpy((void *)tmpde+slop, bh->b_data, offset);
1140 } 1138 }
1141 de = tmpde; 1139 de = tmpde;
1142 } 1140 }
@@ -1150,12 +1148,11 @@ static int isofs_read_level3_size(struct inode * inode)
1150 more_entries = de->flags[-high_sierra] & 0x80; 1148 more_entries = de->flags[-high_sierra] & 0x80;
1151 1149
1152 i++; 1150 i++;
1153 if(i > 100) 1151 if (i > 100)
1154 goto out_toomany; 1152 goto out_toomany;
1155 } while(more_entries); 1153 } while (more_entries);
1156out: 1154out:
1157 if (tmpde) 1155 kfree(tmpde);
1158 kfree(tmpde);
1159 if (bh) 1156 if (bh)
1160 brelse(bh); 1157 brelse(bh);
1161 return 0; 1158 return 0;
@@ -1179,7 +1176,7 @@ out_toomany:
1179 goto out; 1176 goto out;
1180} 1177}
1181 1178
1182static void isofs_read_inode(struct inode * inode) 1179static void isofs_read_inode(struct inode *inode)
1183{ 1180{
1184 struct super_block *sb = inode->i_sb; 1181 struct super_block *sb = inode->i_sb;
1185 struct isofs_sb_info *sbi = ISOFS_SB(sb); 1182 struct isofs_sb_info *sbi = ISOFS_SB(sb);
@@ -1249,7 +1246,7 @@ static void isofs_read_inode(struct inode * inode)
1249 ei->i_format_parm[2] = 0; 1246 ei->i_format_parm[2] = 0;
1250 1247
1251 ei->i_section_size = isonum_733 (de->size); 1248 ei->i_section_size = isonum_733 (de->size);
1252 if(de->flags[-high_sierra] & 0x80) { 1249 if (de->flags[-high_sierra] & 0x80) {
1253 if(isofs_read_level3_size(inode)) goto fail; 1250 if(isofs_read_level3_size(inode)) goto fail;
1254 } else { 1251 } else {
1255 ei->i_next_section_block = 0; 1252 ei->i_next_section_block = 0;
@@ -1336,16 +1333,16 @@ static void isofs_read_inode(struct inode * inode)
1336 /* XXX - parse_rock_ridge_inode() had already set i_rdev. */ 1333 /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
1337 init_special_inode(inode, inode->i_mode, inode->i_rdev); 1334 init_special_inode(inode, inode->i_mode, inode->i_rdev);
1338 1335
1339 out: 1336out:
1340 if (tmpde) 1337 if (tmpde)
1341 kfree(tmpde); 1338 kfree(tmpde);
1342 if (bh) 1339 if (bh)
1343 brelse(bh); 1340 brelse(bh);
1344 return; 1341 return;
1345 1342
1346 out_badread: 1343out_badread:
1347 printk(KERN_WARNING "ISOFS: unable to read i-node block\n"); 1344 printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
1348 fail: 1345fail:
1349 make_bad_inode(inode); 1346 make_bad_inode(inode);
1350 goto out; 1347 goto out;
1351} 1348}
@@ -1394,11 +1391,8 @@ struct inode *isofs_iget(struct super_block *sb,
1394 1391
1395 hashval = (block << sb->s_blocksize_bits) | offset; 1392 hashval = (block << sb->s_blocksize_bits) | offset;
1396 1393
1397 inode = iget5_locked(sb, 1394 inode = iget5_locked(sb, hashval, &isofs_iget5_test,
1398 hashval, 1395 &isofs_iget5_set, &data);
1399 &isofs_iget5_test,
1400 &isofs_iget5_set,
1401 &data);
1402 1396
1403 if (inode && (inode->i_state & I_NEW)) { 1397 if (inode && (inode->i_state & I_NEW)) {
1404 sb->s_op->read_inode(inode); 1398 sb->s_op->read_inode(inode);
@@ -1408,36 +1402,6 @@ struct inode *isofs_iget(struct super_block *sb,
1408 return inode; 1402 return inode;
1409} 1403}
1410 1404
1411#ifdef LEAK_CHECK
1412#undef malloc
1413#undef free_s
1414#undef sb_bread
1415#undef brelse
1416
1417void * leak_check_malloc(unsigned int size){
1418 void * tmp;
1419 check_malloc++;
1420 tmp = kmalloc(size, GFP_KERNEL);
1421 return tmp;
1422}
1423
1424void leak_check_free_s(void * obj, int size){
1425 check_malloc--;
1426 return kfree(obj);
1427}
1428
1429struct buffer_head * leak_check_bread(struct super_block *sb, int block){
1430 check_bread++;
1431 return sb_bread(sb, block);
1432}
1433
1434void leak_check_brelse(struct buffer_head * bh){
1435 check_bread--;
1436 return brelse(bh);
1437}
1438
1439#endif
1440
1441static struct super_block *isofs_get_sb(struct file_system_type *fs_type, 1405static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
1442 int flags, const char *dev_name, void *data) 1406 int flags, const char *dev_name, void *data)
1443{ 1407{
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 9ce7b51fb614..38c75151fc66 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -47,6 +47,8 @@ struct isofs_sb_info {
47 unsigned char s_nosuid; 47 unsigned char s_nosuid;
48 unsigned char s_nodev; 48 unsigned char s_nodev;
49 unsigned char s_nocompress; 49 unsigned char s_nocompress;
50 unsigned char s_hide;
51 unsigned char s_showassoc;
50 52
51 mode_t s_mode; 53 mode_t s_mode;
52 gid_t s_gid; 54 gid_t s_gid;
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 690edf37173c..e37e82b7cbf0 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -131,14 +131,16 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
131 } 131 }
132 132
133 /* 133 /*
134 * Skip hidden or associated files unless unhide is set 134 * Skip hidden or associated files unless hide or showassoc,
135 * respectively, is set
135 */ 136 */
136 match = 0; 137 match = 0;
137 if (dlen > 0 && 138 if (dlen > 0 &&
138 (!(de->flags[-sbi->s_high_sierra] & 5) 139 (sbi->s_hide =='n' ||
139 || sbi->s_unhide == 'y')) 140 (!(de->flags[-sbi->s_high_sierra] & 1))) &&
140 { 141 (sbi->s_showassoc =='y' ||
141 match = (isofs_cmp(dentry,dpnt,dlen) == 0); 142 (!(de->flags[-sbi->s_high_sierra] & 4)))) {
143 match = (isofs_cmp(dentry, dpnt, dlen) == 0);
142 } 144 }
143 if (match) { 145 if (match) {
144 isofs_normalize_block_and_offset(de, 146 isofs_normalize_block_and_offset(de,
@@ -146,11 +148,11 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
146 &offset_saved); 148 &offset_saved);
147 *block_rv = block_saved; 149 *block_rv = block_saved;
148 *offset_rv = offset_saved; 150 *offset_rv = offset_saved;
149 if (bh) brelse(bh); 151 brelse(bh);
150 return 1; 152 return 1;
151 } 153 }
152 } 154 }
153 if (bh) brelse(bh); 155 brelse(bh);
154 return 0; 156 return 0;
155} 157}
156 158
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 089e79c65585..4326cb47f8fa 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -13,352 +13,542 @@
13#include "isofs.h" 13#include "isofs.h"
14#include "rock.h" 14#include "rock.h"
15 15
16/* These functions are designed to read the system areas of a directory record 16/*
17 * These functions are designed to read the system areas of a directory record
17 * and extract relevant information. There are different functions provided 18 * and extract relevant information. There are different functions provided
18 * depending upon what information we need at the time. One function fills 19 * depending upon what information we need at the time. One function fills
19 * out an inode structure, a second one extracts a filename, a third one 20 * out an inode structure, a second one extracts a filename, a third one
20 * returns a symbolic link name, and a fourth one returns the extent number 21 * returns a symbolic link name, and a fourth one returns the extent number
21 * for the file. */ 22 * for the file.
22 23 */
23#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */ 24
24 25#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
25 26
26/* This is a way of ensuring that we have something in the system 27struct rock_state {
27 use fields that is compatible with Rock Ridge */ 28 void *buffer;
28#define CHECK_SP(FAIL) \ 29 unsigned char *chr;
29 if(rr->u.SP.magic[0] != 0xbe) FAIL; \ 30 int len;
30 if(rr->u.SP.magic[1] != 0xef) FAIL; \ 31 int cont_size;
31 ISOFS_SB(inode->i_sb)->s_rock_offset=rr->u.SP.skip; 32 int cont_extent;
32/* We define a series of macros because each function must do exactly the 33 int cont_offset;
33 same thing in certain places. We use the macros to ensure that everything 34 struct inode *inode;
34 is done correctly */ 35};
35 36
36#define CONTINUE_DECLS \ 37/*
37 int cont_extent = 0, cont_offset = 0, cont_size = 0; \ 38 * This is a way of ensuring that we have something in the system
38 void *buffer = NULL 39 * use fields that is compatible with Rock Ridge. Return zero on success.
39 40 */
40#define CHECK_CE \ 41
41 {cont_extent = isonum_733(rr->u.CE.extent); \ 42static int check_sp(struct rock_ridge *rr, struct inode *inode)
42 cont_offset = isonum_733(rr->u.CE.offset); \
43 cont_size = isonum_733(rr->u.CE.size);}
44
45#define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
46 {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
47 if(LEN & 1) LEN++; \
48 CHR = ((unsigned char *) DE) + LEN; \
49 LEN = *((unsigned char *) DE) - LEN; \
50 if (LEN<0) LEN=0; \
51 if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \
52 { \
53 LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \
54 CHR+=ISOFS_SB(inode->i_sb)->s_rock_offset; \
55 if (LEN<0) LEN=0; \
56 } \
57}
58
59#define MAYBE_CONTINUE(LABEL,DEV) \
60 {if (buffer) { kfree(buffer); buffer = NULL; } \
61 if (cont_extent){ \
62 int block, offset, offset1; \
63 struct buffer_head * pbh; \
64 buffer = kmalloc(cont_size,GFP_KERNEL); \
65 if (!buffer) goto out; \
66 block = cont_extent; \
67 offset = cont_offset; \
68 offset1 = 0; \
69 pbh = sb_bread(DEV->i_sb, block); \
70 if(pbh){ \
71 if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \
72 brelse(pbh); \
73 goto out; \
74 } \
75 memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
76 brelse(pbh); \
77 chr = (unsigned char *) buffer; \
78 len = cont_size; \
79 cont_extent = 0; \
80 cont_size = 0; \
81 cont_offset = 0; \
82 goto LABEL; \
83 } \
84 printk("Unable to read rock-ridge attributes\n"); \
85 }}
86
87/* return length of name field; 0: not found, -1: to be ignored */
88int get_rock_ridge_filename(struct iso_directory_record * de,
89 char * retname, struct inode * inode)
90{ 43{
91 int len; 44 if (rr->u.SP.magic[0] != 0xbe)
92 unsigned char * chr; 45 return -1;
93 CONTINUE_DECLS; 46 if (rr->u.SP.magic[1] != 0xef)
94 int retnamlen = 0, truncate=0; 47 return -1;
95 48 ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
96 if (!ISOFS_SB(inode->i_sb)->s_rock) return 0; 49 return 0;
97 *retname = 0; 50}
98 51
99 SETUP_ROCK_RIDGE(de, chr, len); 52static void setup_rock_ridge(struct iso_directory_record *de,
100 repeat: 53 struct inode *inode, struct rock_state *rs)
101 { 54{
102 struct rock_ridge * rr; 55 rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
103 int sig; 56 if (rs->len & 1)
104 57 (rs->len)++;
105 while (len > 2){ /* There may be one byte for padding somewhere */ 58 rs->chr = (unsigned char *)de + rs->len;
106 rr = (struct rock_ridge *) chr; 59 rs->len = *((unsigned char *)de) - rs->len;
107 if (rr->len < 3) goto out; /* Something got screwed up here */ 60 if (rs->len < 0)
108 sig = isonum_721(chr); 61 rs->len = 0;
109 chr += rr->len; 62
110 len -= rr->len; 63 if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
111 if (len < 0) goto out; /* corrupted isofs */ 64 rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
112 65 rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
113 switch(sig){ 66 if (rs->len < 0)
114 case SIG('R','R'): 67 rs->len = 0;
115 if((rr->u.RR.flags[0] & RR_NM) == 0) goto out; 68 }
116 break; 69}
117 case SIG('S','P'): 70
118 CHECK_SP(goto out); 71static void init_rock_state(struct rock_state *rs, struct inode *inode)
119 break; 72{
120 case SIG('C','E'): 73 memset(rs, 0, sizeof(*rs));
121 CHECK_CE; 74 rs->inode = inode;
122 break; 75}
123 case SIG('N','M'): 76
124 if (truncate) break; 77/*
125 if (rr->len < 5) break; 78 * Returns 0 if the caller should continue scanning, 1 if the scan must end
126 /* 79 * and -ve on error.
127 * If the flags are 2 or 4, this indicates '.' or '..'. 80 */
128 * We don't want to do anything with this, because it 81static int rock_continue(struct rock_state *rs)
129 * screws up the code that calls us. We don't really 82{
130 * care anyways, since we can just use the non-RR 83 int ret = 1;
131 * name. 84 int blocksize = 1 << rs->inode->i_blkbits;
132 */ 85 const int min_de_size = offsetof(struct rock_ridge, u);
133 if (rr->u.NM.flags & 6) { 86
134 break; 87 kfree(rs->buffer);
88 rs->buffer = NULL;
89
90 if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
91 (unsigned)rs->cont_size > blocksize ||
92 (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
93 printk(KERN_NOTICE "rock: corrupted directory entry. "
94 "extent=%d, offset=%d, size=%d\n",
95 rs->cont_extent, rs->cont_offset, rs->cont_size);
96 ret = -EIO;
97 goto out;
135 } 98 }
136 99
137 if (rr->u.NM.flags & ~1) { 100 if (rs->cont_extent) {
138 printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags); 101 struct buffer_head *bh;
139 break; 102
103 rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
104 if (!rs->buffer) {
105 ret = -ENOMEM;
106 goto out;
107 }
108 ret = -EIO;
109 bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
110 if (bh) {
111 memcpy(rs->buffer, bh->b_data + rs->cont_offset,
112 rs->cont_size);
113 put_bh(bh);
114 rs->chr = rs->buffer;
115 rs->len = rs->cont_size;
116 rs->cont_extent = 0;
117 rs->cont_size = 0;
118 rs->cont_offset = 0;
119 return 0;
120 }
121 printk("Unable to read rock-ridge attributes\n");
122 }
123out:
124 kfree(rs->buffer);
125 rs->buffer = NULL;
126 return ret;
127}
128
129/*
130 * We think there's a record of type `sig' at rs->chr. Parse the signature
131 * and make sure that there's really room for a record of that type.
132 */
133static int rock_check_overflow(struct rock_state *rs, int sig)
134{
135 int len;
136
137 switch (sig) {
138 case SIG('S', 'P'):
139 len = sizeof(struct SU_SP_s);
140 break;
141 case SIG('C', 'E'):
142 len = sizeof(struct SU_CE_s);
143 break;
144 case SIG('E', 'R'):
145 len = sizeof(struct SU_ER_s);
146 break;
147 case SIG('R', 'R'):
148 len = sizeof(struct RR_RR_s);
149 break;
150 case SIG('P', 'X'):
151 len = sizeof(struct RR_PX_s);
152 break;
153 case SIG('P', 'N'):
154 len = sizeof(struct RR_PN_s);
155 break;
156 case SIG('S', 'L'):
157 len = sizeof(struct RR_SL_s);
158 break;
159 case SIG('N', 'M'):
160 len = sizeof(struct RR_NM_s);
161 break;
162 case SIG('C', 'L'):
163 len = sizeof(struct RR_CL_s);
164 break;
165 case SIG('P', 'L'):
166 len = sizeof(struct RR_PL_s);
167 break;
168 case SIG('T', 'F'):
169 len = sizeof(struct RR_TF_s);
170 break;
171 case SIG('Z', 'F'):
172 len = sizeof(struct RR_ZF_s);
173 break;
174 default:
175 len = 0;
176 break;
140 } 177 }
141 if((strlen(retname) + rr->len - 5) >= 254) { 178 len += offsetof(struct rock_ridge, u);
142 truncate = 1; 179 if (len > rs->len) {
143 break; 180 printk(KERN_NOTICE "rock: directory entry would overflow "
181 "storage\n");
182 printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
183 sig, len, rs->len);
184 return -EIO;
185 }
186 return 0;
187}
188
189/*
190 * return length of name field; 0: not found, -1: to be ignored
191 */
192int get_rock_ridge_filename(struct iso_directory_record *de,
193 char *retname, struct inode *inode)
194{
195 struct rock_state rs;
196 struct rock_ridge *rr;
197 int sig;
198 int retnamlen = 0;
199 int truncate = 0;
200 int ret = 0;
201
202 if (!ISOFS_SB(inode->i_sb)->s_rock)
203 return 0;
204 *retname = 0;
205
206 init_rock_state(&rs, inode);
207 setup_rock_ridge(de, inode, &rs);
208repeat:
209
210 while (rs.len > 2) { /* There may be one byte for padding somewhere */
211 rr = (struct rock_ridge *)rs.chr;
212 if (rr->len < 3)
213 goto out; /* Something got screwed up here */
214 sig = isonum_721(rs.chr);
215 if (rock_check_overflow(&rs, sig))
216 goto eio;
217 rs.chr += rr->len;
218 rs.len -= rr->len;
219 if (rs.len < 0)
220 goto eio; /* corrupted isofs */
221
222 switch (sig) {
223 case SIG('R', 'R'):
224 if ((rr->u.RR.flags[0] & RR_NM) == 0)
225 goto out;
226 break;
227 case SIG('S', 'P'):
228 if (check_sp(rr, inode))
229 goto out;
230 break;
231 case SIG('C', 'E'):
232 rs.cont_extent = isonum_733(rr->u.CE.extent);
233 rs.cont_offset = isonum_733(rr->u.CE.offset);
234 rs.cont_size = isonum_733(rr->u.CE.size);
235 break;
236 case SIG('N', 'M'):
237 if (truncate)
238 break;
239 if (rr->len < 5)
240 break;
241 /*
242 * If the flags are 2 or 4, this indicates '.' or '..'.
243 * We don't want to do anything with this, because it
244 * screws up the code that calls us. We don't really
245 * care anyways, since we can just use the non-RR
246 * name.
247 */
248 if (rr->u.NM.flags & 6)
249 break;
250
251 if (rr->u.NM.flags & ~1) {
252 printk("Unsupported NM flag settings (%d)\n",
253 rr->u.NM.flags);
254 break;
255 }
256 if ((strlen(retname) + rr->len - 5) >= 254) {
257 truncate = 1;
258 break;
259 }
260 strncat(retname, rr->u.NM.name, rr->len - 5);
261 retnamlen += rr->len - 5;
262 break;
263 case SIG('R', 'E'):
264 kfree(rs.buffer);
265 return -1;
266 default:
267 break;
268 }
144 } 269 }
145 strncat(retname, rr->u.NM.name, rr->len - 5); 270 ret = rock_continue(&rs);
146 retnamlen += rr->len - 5; 271 if (ret == 0)
147 break; 272 goto repeat;
148 case SIG('R','E'): 273 if (ret == 1)
149 if (buffer) kfree(buffer); 274 return retnamlen; /* If 0, this file did not have a NM field */
150 return -1; 275out:
151 default: 276 kfree(rs.buffer);
152 break; 277 return ret;
153 } 278eio:
154 } 279 ret = -EIO;
155 } 280 goto out;
156 MAYBE_CONTINUE(repeat,inode);
157 if (buffer) kfree(buffer);
158 return retnamlen; /* If 0, this file did not have a NM field */
159 out:
160 if(buffer) kfree(buffer);
161 return 0;
162} 281}
163 282
164static int 283static int
165parse_rock_ridge_inode_internal(struct iso_directory_record *de, 284parse_rock_ridge_inode_internal(struct iso_directory_record *de,
166 struct inode *inode, int regard_xa) 285 struct inode *inode, int regard_xa)
167{ 286{
168 int len; 287 int symlink_len = 0;
169 unsigned char * chr; 288 int cnt, sig;
170 int symlink_len = 0; 289 struct inode *reloc;
171 CONTINUE_DECLS; 290 struct rock_ridge *rr;
172 291 int rootflag;
173 if (!ISOFS_SB(inode->i_sb)->s_rock) return 0; 292 struct rock_state rs;
174 293 int ret = 0;
175 SETUP_ROCK_RIDGE(de, chr, len); 294
176 if (regard_xa) 295 if (!ISOFS_SB(inode->i_sb)->s_rock)
177 { 296 return 0;
178 chr+=14; 297
179 len-=14; 298 init_rock_state(&rs, inode);
180 if (len<0) len=0; 299 setup_rock_ridge(de, inode, &rs);
181 } 300 if (regard_xa) {
182 301 rs.chr += 14;
183 repeat: 302 rs.len -= 14;
184 { 303 if (rs.len < 0)
185 int cnt, sig; 304 rs.len = 0;
186 struct inode * reloc; 305 }
187 struct rock_ridge * rr; 306
188 int rootflag; 307repeat:
189 308 while (rs.len > 2) { /* There may be one byte for padding somewhere */
190 while (len > 2){ /* There may be one byte for padding somewhere */ 309 rr = (struct rock_ridge *)rs.chr;
191 rr = (struct rock_ridge *) chr; 310 if (rr->len < 3)
192 if (rr->len < 3) goto out; /* Something got screwed up here */ 311 goto out; /* Something got screwed up here */
193 sig = isonum_721(chr); 312 sig = isonum_721(rs.chr);
194 chr += rr->len; 313 if (rock_check_overflow(&rs, sig))
195 len -= rr->len; 314 goto eio;
196 if (len < 0) goto out; /* corrupted isofs */ 315 rs.chr += rr->len;
197 316 rs.len -= rr->len;
198 switch(sig){ 317 if (rs.len < 0)
318 goto eio; /* corrupted isofs */
319
320 switch (sig) {
199#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ 321#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
200 case SIG('R','R'): 322 case SIG('R', 'R'):
201 if((rr->u.RR.flags[0] & 323 if ((rr->u.RR.flags[0] &
202 (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out; 324 (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
203 break; 325 goto out;
326 break;
204#endif 327#endif
205 case SIG('S','P'): 328 case SIG('S', 'P'):
206 CHECK_SP(goto out); 329 if (check_sp(rr, inode))
207 break; 330 goto out;
208 case SIG('C','E'): 331 break;
209 CHECK_CE; 332 case SIG('C', 'E'):
210 break; 333 rs.cont_extent = isonum_733(rr->u.CE.extent);
211 case SIG('E','R'): 334 rs.cont_offset = isonum_733(rr->u.CE.offset);
212 ISOFS_SB(inode->i_sb)->s_rock = 1; 335 rs.cont_size = isonum_733(rr->u.CE.size);
213 printk(KERN_DEBUG "ISO 9660 Extensions: "); 336 break;
214 { int p; 337 case SIG('E', 'R'):
215 for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]); 338 ISOFS_SB(inode->i_sb)->s_rock = 1;
216 } 339 printk(KERN_DEBUG "ISO 9660 Extensions: ");
217 printk("\n"); 340 {
218 break; 341 int p;
219 case SIG('P','X'): 342 for (p = 0; p < rr->u.ER.len_id; p++)
220 inode->i_mode = isonum_733(rr->u.PX.mode); 343 printk("%c", rr->u.ER.data[p]);
221 inode->i_nlink = isonum_733(rr->u.PX.n_links); 344 }
222 inode->i_uid = isonum_733(rr->u.PX.uid); 345 printk("\n");
223 inode->i_gid = isonum_733(rr->u.PX.gid); 346 break;
224 break; 347 case SIG('P', 'X'):
225 case SIG('P','N'): 348 inode->i_mode = isonum_733(rr->u.PX.mode);
226 { int high, low; 349 inode->i_nlink = isonum_733(rr->u.PX.n_links);
227 high = isonum_733(rr->u.PN.dev_high); 350 inode->i_uid = isonum_733(rr->u.PX.uid);
228 low = isonum_733(rr->u.PN.dev_low); 351 inode->i_gid = isonum_733(rr->u.PX.gid);
229 /* 352 break;
230 * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4, 353 case SIG('P', 'N'):
231 * then the high field is unused, and the device number is completely 354 {
232 * stored in the low field. Some writers may ignore this subtlety, 355 int high, low;
233 * and as a result we test to see if the entire device number is 356 high = isonum_733(rr->u.PN.dev_high);
234 * stored in the low field, and use that. 357 low = isonum_733(rr->u.PN.dev_low);
235 */ 358 /*
236 if((low & ~0xff) && high == 0) { 359 * The Rock Ridge standard specifies that if
237 inode->i_rdev = MKDEV(low >> 8, low & 0xff); 360 * sizeof(dev_t) <= 4, then the high field is
238 } else { 361 * unused, and the device number is completely
239 inode->i_rdev = MKDEV(high, low); 362 * stored in the low field. Some writers may
240 } 363 * ignore this subtlety,
241 } 364 * and as a result we test to see if the entire
242 break; 365 * device number is
243 case SIG('T','F'): 366 * stored in the low field, and use that.
244 /* Some RRIP writers incorrectly place ctime in the TF_CREATE field. 367 */
245 Try to handle this correctly for either case. */ 368 if ((low & ~0xff) && high == 0) {
246 cnt = 0; /* Rock ridge never appears on a High Sierra disk */ 369 inode->i_rdev =
247 if(rr->u.TF.flags & TF_CREATE) { 370 MKDEV(low >> 8, low & 0xff);
248 inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); 371 } else {
249 inode->i_ctime.tv_nsec = 0; 372 inode->i_rdev =
250 } 373 MKDEV(high, low);
251 if(rr->u.TF.flags & TF_MODIFY) { 374 }
252 inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); 375 }
253 inode->i_mtime.tv_nsec = 0; 376 break;
254 } 377 case SIG('T', 'F'):
255 if(rr->u.TF.flags & TF_ACCESS) { 378 /*
256 inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); 379 * Some RRIP writers incorrectly place ctime in the
257 inode->i_atime.tv_nsec = 0; 380 * TF_CREATE field. Try to handle this correctly for
258 } 381 * either case.
259 if(rr->u.TF.flags & TF_ATTRIBUTES) { 382 */
260 inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0); 383 /* Rock ridge never appears on a High Sierra disk */
261 inode->i_ctime.tv_nsec = 0; 384 cnt = 0;
262 } 385 if (rr->u.TF.flags & TF_CREATE) {
263 break; 386 inode->i_ctime.tv_sec =
264 case SIG('S','L'): 387 iso_date(rr->u.TF.times[cnt++].time,
265 {int slen; 388 0);
266 struct SL_component * slp; 389 inode->i_ctime.tv_nsec = 0;
267 struct SL_component * oldslp; 390 }
268 slen = rr->len - 5; 391 if (rr->u.TF.flags & TF_MODIFY) {
269 slp = &rr->u.SL.link; 392 inode->i_mtime.tv_sec =
270 inode->i_size = symlink_len; 393 iso_date(rr->u.TF.times[cnt++].time,
271 while (slen > 1){ 394 0);
272 rootflag = 0; 395 inode->i_mtime.tv_nsec = 0;
273 switch(slp->flags &~1){ 396 }
274 case 0: 397 if (rr->u.TF.flags & TF_ACCESS) {
275 inode->i_size += slp->len; 398 inode->i_atime.tv_sec =
276 break; 399 iso_date(rr->u.TF.times[cnt++].time,
277 case 2: 400 0);
278 inode->i_size += 1; 401 inode->i_atime.tv_nsec = 0;
279 break; 402 }
280 case 4: 403 if (rr->u.TF.flags & TF_ATTRIBUTES) {
281 inode->i_size += 2; 404 inode->i_ctime.tv_sec =
282 break; 405 iso_date(rr->u.TF.times[cnt++].time,
283 case 8: 406 0);
284 rootflag = 1; 407 inode->i_ctime.tv_nsec = 0;
285 inode->i_size += 1; 408 }
286 break; 409 break;
287 default: 410 case SIG('S', 'L'):
288 printk("Symlink component flag not implemented\n"); 411 {
289 } 412 int slen;
290 slen -= slp->len + 2; 413 struct SL_component *slp;
291 oldslp = slp; 414 struct SL_component *oldslp;
292 slp = (struct SL_component *) (((char *) slp) + slp->len + 2); 415 slen = rr->len - 5;
293 416 slp = &rr->u.SL.link;
294 if(slen < 2) { 417 inode->i_size = symlink_len;
295 if( ((rr->u.SL.flags & 1) != 0) 418 while (slen > 1) {
296 && ((oldslp->flags & 1) == 0) ) inode->i_size += 1; 419 rootflag = 0;
297 break; 420 switch (slp->flags & ~1) {
298 } 421 case 0:
299 422 inode->i_size +=
300 /* 423 slp->len;
301 * If this component record isn't continued, then append a '/'. 424 break;
302 */ 425 case 2:
303 if (!rootflag && (oldslp->flags & 1) == 0) 426 inode->i_size += 1;
304 inode->i_size += 1; 427 break;
305 } 428 case 4:
306 } 429 inode->i_size += 2;
307 symlink_len = inode->i_size; 430 break;
308 break; 431 case 8:
309 case SIG('R','E'): 432 rootflag = 1;
310 printk(KERN_WARNING "Attempt to read inode for relocated directory\n"); 433 inode->i_size += 1;
311 goto out; 434 break;
312 case SIG('C','L'): 435 default:
313 ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location); 436 printk("Symlink component flag "
314 reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0); 437 "not implemented\n");
315 if (!reloc) 438 }
316 goto out; 439 slen -= slp->len + 2;
317 inode->i_mode = reloc->i_mode; 440 oldslp = slp;
318 inode->i_nlink = reloc->i_nlink; 441 slp = (struct SL_component *)
319 inode->i_uid = reloc->i_uid; 442 (((char *)slp) + slp->len + 2);
320 inode->i_gid = reloc->i_gid; 443
321 inode->i_rdev = reloc->i_rdev; 444 if (slen < 2) {
322 inode->i_size = reloc->i_size; 445 if (((rr->u.SL.
323 inode->i_blocks = reloc->i_blocks; 446 flags & 1) != 0)
324 inode->i_atime = reloc->i_atime; 447 &&
325 inode->i_ctime = reloc->i_ctime; 448 ((oldslp->
326 inode->i_mtime = reloc->i_mtime; 449 flags & 1) == 0))
327 iput(reloc); 450 inode->i_size +=
328 break; 451 1;
452 break;
453 }
454
455 /*
456 * If this component record isn't
457 * continued, then append a '/'.
458 */
459 if (!rootflag
460 && (oldslp->flags & 1) == 0)
461 inode->i_size += 1;
462 }
463 }
464 symlink_len = inode->i_size;
465 break;
466 case SIG('R', 'E'):
467 printk(KERN_WARNING "Attempt to read inode for "
468 "relocated directory\n");
469 goto out;
470 case SIG('C', 'L'):
471 ISOFS_I(inode)->i_first_extent =
472 isonum_733(rr->u.CL.location);
473 reloc =
474 isofs_iget(inode->i_sb,
475 ISOFS_I(inode)->i_first_extent,
476 0);
477 if (!reloc)
478 goto out;
479 inode->i_mode = reloc->i_mode;
480 inode->i_nlink = reloc->i_nlink;
481 inode->i_uid = reloc->i_uid;
482 inode->i_gid = reloc->i_gid;
483 inode->i_rdev = reloc->i_rdev;
484 inode->i_size = reloc->i_size;
485 inode->i_blocks = reloc->i_blocks;
486 inode->i_atime = reloc->i_atime;
487 inode->i_ctime = reloc->i_ctime;
488 inode->i_mtime = reloc->i_mtime;
489 iput(reloc);
490 break;
329#ifdef CONFIG_ZISOFS 491#ifdef CONFIG_ZISOFS
330 case SIG('Z','F'): 492 case SIG('Z', 'F'): {
331 if ( !ISOFS_SB(inode->i_sb)->s_nocompress ) { 493 int algo;
332 int algo; 494
333 algo = isonum_721(rr->u.ZF.algorithm); 495 if (ISOFS_SB(inode->i_sb)->s_nocompress)
334 if ( algo == SIG('p','z') ) { 496 break;
335 int block_shift = isonum_711(&rr->u.ZF.parms[1]); 497 algo = isonum_721(rr->u.ZF.algorithm);
336 if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) { 498 if (algo == SIG('p', 'z')) {
337 printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift); 499 int block_shift =
338 } else { 500 isonum_711(&rr->u.ZF.parms[1]);
339 /* Note: we don't change i_blocks here */ 501 if (block_shift < PAGE_CACHE_SHIFT
340 ISOFS_I(inode)->i_file_format = isofs_file_compressed; 502 || block_shift > 17) {
341 /* Parameters to compression algorithm (header size, block size) */ 503 printk(KERN_WARNING "isofs: "
342 ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]); 504 "Can't handle ZF block "
343 ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]); 505 "size of 2^%d\n",
344 inode->i_size = isonum_733(rr->u.ZF.real_size); 506 block_shift);
345 } 507 } else {
346 } else { 508 /*
347 printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n", 509 * Note: we don't change
348 rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]); 510 * i_blocks here
349 } 511 */
350 } 512 ISOFS_I(inode)->i_file_format =
351 break; 513 isofs_file_compressed;
514 /*
515 * Parameters to compression
516 * algorithm (header size,
517 * block size)
518 */
519 ISOFS_I(inode)->i_format_parm[0] =
520 isonum_711(&rr->u.ZF.parms[0]);
521 ISOFS_I(inode)->i_format_parm[1] =
522 isonum_711(&rr->u.ZF.parms[1]);
523 inode->i_size =
524 isonum_733(rr->u.ZF.
525 real_size);
526 }
527 } else {
528 printk(KERN_WARNING
529 "isofs: Unknown ZF compression "
530 "algorithm: %c%c\n",
531 rr->u.ZF.algorithm[0],
532 rr->u.ZF.algorithm[1]);
533 }
534 break;
535 }
352#endif 536#endif
353 default: 537 default:
354 break; 538 break;
355 } 539 }
356 } 540 }
357 } 541 ret = rock_continue(&rs);
358 MAYBE_CONTINUE(repeat,inode); 542 if (ret == 0)
359 out: 543 goto repeat;
360 if(buffer) kfree(buffer); 544 if (ret == 1)
361 return 0; 545 ret = 0;
546out:
547 kfree(rs.buffer);
548 return ret;
549eio:
550 ret = -EIO;
551 goto out;
362} 552}
363 553
364static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) 554static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
@@ -376,32 +566,32 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
376 if (slp->len > plimit - rpnt) 566 if (slp->len > plimit - rpnt)
377 return NULL; 567 return NULL;
378 memcpy(rpnt, slp->text, slp->len); 568 memcpy(rpnt, slp->text, slp->len);
379 rpnt+=slp->len; 569 rpnt += slp->len;
380 break; 570 break;
381 case 2: 571 case 2:
382 if (rpnt >= plimit) 572 if (rpnt >= plimit)
383 return NULL; 573 return NULL;
384 *rpnt++='.'; 574 *rpnt++ = '.';
385 break; 575 break;
386 case 4: 576 case 4:
387 if (2 > plimit - rpnt) 577 if (2 > plimit - rpnt)
388 return NULL; 578 return NULL;
389 *rpnt++='.'; 579 *rpnt++ = '.';
390 *rpnt++='.'; 580 *rpnt++ = '.';
391 break; 581 break;
392 case 8: 582 case 8:
393 if (rpnt >= plimit) 583 if (rpnt >= plimit)
394 return NULL; 584 return NULL;
395 rootflag = 1; 585 rootflag = 1;
396 *rpnt++='/'; 586 *rpnt++ = '/';
397 break; 587 break;
398 default: 588 default:
399 printk("Symlink component flag not implemented (%d)\n", 589 printk("Symlink component flag not implemented (%d)\n",
400 slp->flags); 590 slp->flags);
401 } 591 }
402 slen -= slp->len + 2; 592 slen -= slp->len + 2;
403 oldslp = slp; 593 oldslp = slp;
404 slp = (struct SL_component *) ((char *) slp + slp->len + 2); 594 slp = (struct SL_component *)((char *)slp + slp->len + 2);
405 595
406 if (slen < 2) { 596 if (slen < 2) {
407 /* 597 /*
@@ -412,7 +602,7 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
412 !(oldslp->flags & 1)) { 602 !(oldslp->flags & 1)) {
413 if (rpnt >= plimit) 603 if (rpnt >= plimit)
414 return NULL; 604 return NULL;
415 *rpnt++='/'; 605 *rpnt++ = '/';
416 } 606 }
417 break; 607 break;
418 } 608 }
@@ -423,59 +613,61 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
423 if (!rootflag && !(oldslp->flags & 1)) { 613 if (!rootflag && !(oldslp->flags & 1)) {
424 if (rpnt >= plimit) 614 if (rpnt >= plimit)
425 return NULL; 615 return NULL;
426 *rpnt++='/'; 616 *rpnt++ = '/';
427 } 617 }
428 } 618 }
429 return rpnt; 619 return rpnt;
430} 620}
431 621
432int parse_rock_ridge_inode(struct iso_directory_record * de, 622int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
433 struct inode * inode)
434{ 623{
435 int result=parse_rock_ridge_inode_internal(de,inode,0); 624 int result = parse_rock_ridge_inode_internal(de, inode, 0);
436 /* if rockridge flag was reset and we didn't look for attributes
437 * behind eventual XA attributes, have a look there */
438 if ((ISOFS_SB(inode->i_sb)->s_rock_offset==-1)
439 &&(ISOFS_SB(inode->i_sb)->s_rock==2))
440 {
441 result=parse_rock_ridge_inode_internal(de,inode,14);
442 }
443 return result;
444}
445 625
446/* readpage() for symlinks: reads symlink contents into the page and either 626 /*
447 makes it uptodate and returns 0 or returns error (-EIO) */ 627 * if rockridge flag was reset and we didn't look for attributes
628 * behind eventual XA attributes, have a look there
629 */
630 if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
631 && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
632 result = parse_rock_ridge_inode_internal(de, inode, 14);
633 }
634 return result;
635}
448 636
637/*
638 * readpage() for symlinks: reads symlink contents into the page and either
639 * makes it uptodate and returns 0 or returns error (-EIO)
640 */
449static int rock_ridge_symlink_readpage(struct file *file, struct page *page) 641static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
450{ 642{
451 struct inode *inode = page->mapping->host; 643 struct inode *inode = page->mapping->host;
452 struct iso_inode_info *ei = ISOFS_I(inode); 644 struct iso_inode_info *ei = ISOFS_I(inode);
453 char *link = kmap(page); 645 char *link = kmap(page);
454 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); 646 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
455 struct buffer_head *bh; 647 struct buffer_head *bh;
456 char *rpnt = link; 648 char *rpnt = link;
457 unsigned char *pnt; 649 unsigned char *pnt;
458 struct iso_directory_record *raw_inode; 650 struct iso_directory_record *raw_de;
459 CONTINUE_DECLS;
460 unsigned long block, offset; 651 unsigned long block, offset;
461 int sig; 652 int sig;
462 int len;
463 unsigned char *chr;
464 struct rock_ridge *rr; 653 struct rock_ridge *rr;
654 struct rock_state rs;
655 int ret;
465 656
466 if (!ISOFS_SB(inode->i_sb)->s_rock) 657 if (!ISOFS_SB(inode->i_sb)->s_rock)
467 goto error; 658 goto error;
468 659
660 init_rock_state(&rs, inode);
469 block = ei->i_iget5_block; 661 block = ei->i_iget5_block;
470 lock_kernel(); 662 lock_kernel();
471 bh = sb_bread(inode->i_sb, block); 663 bh = sb_bread(inode->i_sb, block);
472 if (!bh) 664 if (!bh)
473 goto out_noread; 665 goto out_noread;
474 666
475 offset = ei->i_iget5_offset; 667 offset = ei->i_iget5_offset;
476 pnt = (unsigned char *) bh->b_data + offset; 668 pnt = (unsigned char *)bh->b_data + offset;
477 669
478 raw_inode = (struct iso_directory_record *) pnt; 670 raw_de = (struct iso_directory_record *)pnt;
479 671
480 /* 672 /*
481 * If we go past the end of the buffer, there is some sort of error. 673 * If we go past the end of the buffer, there is some sort of error.
@@ -483,20 +675,24 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
483 if (offset + *pnt > bufsize) 675 if (offset + *pnt > bufsize)
484 goto out_bad_span; 676 goto out_bad_span;
485 677
486 /* Now test for possible Rock Ridge extensions which will override 678 /*
487 some of these numbers in the inode structure. */ 679 * Now test for possible Rock Ridge extensions which will override
680 * some of these numbers in the inode structure.
681 */
488 682
489 SETUP_ROCK_RIDGE(raw_inode, chr, len); 683 setup_rock_ridge(raw_de, inode, &rs);
490 684
491 repeat: 685repeat:
492 while (len > 2) { /* There may be one byte for padding somewhere */ 686 while (rs.len > 2) { /* There may be one byte for padding somewhere */
493 rr = (struct rock_ridge *) chr; 687 rr = (struct rock_ridge *)rs.chr;
494 if (rr->len < 3) 688 if (rr->len < 3)
495 goto out; /* Something got screwed up here */ 689 goto out; /* Something got screwed up here */
496 sig = isonum_721(chr); 690 sig = isonum_721(rs.chr);
497 chr += rr->len; 691 if (rock_check_overflow(&rs, sig))
498 len -= rr->len; 692 goto out;
499 if (len < 0) 693 rs.chr += rr->len;
694 rs.len -= rr->len;
695 if (rs.len < 0)
500 goto out; /* corrupted isofs */ 696 goto out; /* corrupted isofs */
501 697
502 switch (sig) { 698 switch (sig) {
@@ -505,7 +701,8 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
505 goto out; 701 goto out;
506 break; 702 break;
507 case SIG('S', 'P'): 703 case SIG('S', 'P'):
508 CHECK_SP(goto out); 704 if (check_sp(rr, inode))
705 goto out;
509 break; 706 break;
510 case SIG('S', 'L'): 707 case SIG('S', 'L'):
511 rpnt = get_symlink_chunk(rpnt, rr, 708 rpnt = get_symlink_chunk(rpnt, rr,
@@ -515,14 +712,18 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
515 break; 712 break;
516 case SIG('C', 'E'): 713 case SIG('C', 'E'):
517 /* This tells is if there is a continuation record */ 714 /* This tells is if there is a continuation record */
518 CHECK_CE; 715 rs.cont_extent = isonum_733(rr->u.CE.extent);
716 rs.cont_offset = isonum_733(rr->u.CE.offset);
717 rs.cont_size = isonum_733(rr->u.CE.size);
519 default: 718 default:
520 break; 719 break;
521 } 720 }
522 } 721 }
523 MAYBE_CONTINUE(repeat, inode); 722 ret = rock_continue(&rs);
524 if (buffer) 723 if (ret == 0)
525 kfree(buffer); 724 goto repeat;
725 if (ret < 0)
726 goto fail;
526 727
527 if (rpnt == link) 728 if (rpnt == link)
528 goto fail; 729 goto fail;
@@ -535,19 +736,18 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
535 return 0; 736 return 0;
536 737
537 /* error exit from macro */ 738 /* error exit from macro */
538 out: 739out:
539 if (buffer) 740 kfree(rs.buffer);
540 kfree(buffer);
541 goto fail; 741 goto fail;
542 out_noread: 742out_noread:
543 printk("unable to read i-node block"); 743 printk("unable to read i-node block");
544 goto fail; 744 goto fail;
545 out_bad_span: 745out_bad_span:
546 printk("symlink spans iso9660 blocks\n"); 746 printk("symlink spans iso9660 blocks\n");
547 fail: 747fail:
548 brelse(bh); 748 brelse(bh);
549 unlock_kernel(); 749 unlock_kernel();
550 error: 750error:
551 SetPageError(page); 751 SetPageError(page);
552 kunmap(page); 752 kunmap(page);
553 unlock_page(page); 753 unlock_page(page);
@@ -555,5 +755,5 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
555} 755}
556 756
557struct address_space_operations isofs_symlink_aops = { 757struct address_space_operations isofs_symlink_aops = {
558 .readpage = rock_ridge_symlink_readpage 758 .readpage = rock_ridge_symlink_readpage
559}; 759};
diff --git a/fs/isofs/rock.h b/fs/isofs/rock.h
index deaf5c8e8b4a..ed09e2b08637 100644
--- a/fs/isofs/rock.h
+++ b/fs/isofs/rock.h
@@ -1,85 +1,88 @@
1/* These structs are used by the system-use-sharing protocol, in which the 1/*
2 Rock Ridge extensions are embedded. It is quite possible that other 2 * These structs are used by the system-use-sharing protocol, in which the
3 extensions are present on the disk, and this is fine as long as they 3 * Rock Ridge extensions are embedded. It is quite possible that other
4 all use SUSP */ 4 * extensions are present on the disk, and this is fine as long as they
5 5 * all use SUSP
6struct SU_SP{ 6 */
7 unsigned char magic[2]; 7
8 unsigned char skip; 8struct SU_SP_s {
9} __attribute__((packed)); 9 unsigned char magic[2];
10 10 unsigned char skip;
11struct SU_CE{ 11} __attribute__ ((packed));
12 char extent[8]; 12
13 char offset[8]; 13struct SU_CE_s {
14 char size[8]; 14 char extent[8];
15 char offset[8];
16 char size[8];
15}; 17};
16 18
17struct SU_ER{ 19struct SU_ER_s {
18 unsigned char len_id; 20 unsigned char len_id;
19 unsigned char len_des; 21 unsigned char len_des;
20 unsigned char len_src; 22 unsigned char len_src;
21 unsigned char ext_ver; 23 unsigned char ext_ver;
22 char data[0]; 24 char data[0];
23} __attribute__((packed)); 25} __attribute__ ((packed));
24 26
25struct RR_RR{ 27struct RR_RR_s {
26 char flags[1]; 28 char flags[1];
27} __attribute__((packed)); 29} __attribute__ ((packed));
28 30
29struct RR_PX{ 31struct RR_PX_s {
30 char mode[8]; 32 char mode[8];
31 char n_links[8]; 33 char n_links[8];
32 char uid[8]; 34 char uid[8];
33 char gid[8]; 35 char gid[8];
34}; 36};
35 37
36struct RR_PN{ 38struct RR_PN_s {
37 char dev_high[8]; 39 char dev_high[8];
38 char dev_low[8]; 40 char dev_low[8];
39}; 41};
40 42
43struct SL_component {
44 unsigned char flags;
45 unsigned char len;
46 char text[0];
47} __attribute__ ((packed));
41 48
42struct SL_component{ 49struct RR_SL_s {
43 unsigned char flags; 50 unsigned char flags;
44 unsigned char len; 51 struct SL_component link;
45 char text[0]; 52} __attribute__ ((packed));
46} __attribute__((packed));
47 53
48struct RR_SL{ 54struct RR_NM_s {
49 unsigned char flags; 55 unsigned char flags;
50 struct SL_component link; 56 char name[0];
51} __attribute__((packed)); 57} __attribute__ ((packed));
52 58
53struct RR_NM{ 59struct RR_CL_s {
54 unsigned char flags; 60 char location[8];
55 char name[0];
56} __attribute__((packed));
57
58struct RR_CL{
59 char location[8];
60}; 61};
61 62
62struct RR_PL{ 63struct RR_PL_s {
63 char location[8]; 64 char location[8];
64}; 65};
65 66
66struct stamp{ 67struct stamp {
67 char time[7]; 68 char time[7];
68} __attribute__((packed)); 69} __attribute__ ((packed));
69 70
70struct RR_TF{ 71struct RR_TF_s {
71 char flags; 72 char flags;
72 struct stamp times[0]; /* Variable number of these beasts */ 73 struct stamp times[0]; /* Variable number of these beasts */
73} __attribute__((packed)); 74} __attribute__ ((packed));
74 75
75/* Linux-specific extension for transparent decompression */ 76/* Linux-specific extension for transparent decompression */
76struct RR_ZF{ 77struct RR_ZF_s {
77 char algorithm[2]; 78 char algorithm[2];
78 char parms[2]; 79 char parms[2];
79 char real_size[8]; 80 char real_size[8];
80}; 81};
81 82
82/* These are the bits and their meanings for flags in the TF structure. */ 83/*
84 * These are the bits and their meanings for flags in the TF structure.
85 */
83#define TF_CREATE 1 86#define TF_CREATE 1
84#define TF_MODIFY 2 87#define TF_MODIFY 2
85#define TF_ACCESS 4 88#define TF_ACCESS 4
@@ -89,31 +92,31 @@ struct RR_ZF{
89#define TF_EFFECTIVE 64 92#define TF_EFFECTIVE 64
90#define TF_LONG_FORM 128 93#define TF_LONG_FORM 128
91 94
92struct rock_ridge{ 95struct rock_ridge {
93 char signature[2]; 96 char signature[2];
94 unsigned char len; 97 unsigned char len;
95 unsigned char version; 98 unsigned char version;
96 union{ 99 union {
97 struct SU_SP SP; 100 struct SU_SP_s SP;
98 struct SU_CE CE; 101 struct SU_CE_s CE;
99 struct SU_ER ER; 102 struct SU_ER_s ER;
100 struct RR_RR RR; 103 struct RR_RR_s RR;
101 struct RR_PX PX; 104 struct RR_PX_s PX;
102 struct RR_PN PN; 105 struct RR_PN_s PN;
103 struct RR_SL SL; 106 struct RR_SL_s SL;
104 struct RR_NM NM; 107 struct RR_NM_s NM;
105 struct RR_CL CL; 108 struct RR_CL_s CL;
106 struct RR_PL PL; 109 struct RR_PL_s PL;
107 struct RR_TF TF; 110 struct RR_TF_s TF;
108 struct RR_ZF ZF; 111 struct RR_ZF_s ZF;
109 } u; 112 } u;
110}; 113};
111 114
112#define RR_PX 1 /* POSIX attributes */ 115#define RR_PX 1 /* POSIX attributes */
113#define RR_PN 2 /* POSIX devices */ 116#define RR_PN 2 /* POSIX devices */
114#define RR_SL 4 /* Symbolic link */ 117#define RR_SL 4 /* Symbolic link */
115#define RR_NM 8 /* Alternate Name */ 118#define RR_NM 8 /* Alternate Name */
116#define RR_CL 16 /* Child link */ 119#define RR_CL 16 /* Child link */
117#define RR_PL 32 /* Parent link */ 120#define RR_PL 32 /* Parent link */
118#define RR_RE 64 /* Relocation directory */ 121#define RR_RE 64 /* Relocation directory */
119#define RR_TF 128 /* Timestamps */ 122#define RR_TF 128 /* Timestamps */
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 98d830401c56..5a97e346bd95 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -188,7 +188,6 @@ static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
188 } else { 188 } else {
189 jbd_unlock_bh_state(bh); 189 jbd_unlock_bh_state(bh);
190 } 190 }
191 jh = next_jh;
192 } while (jh != last_jh); 191 } while (jh != last_jh);
193 192
194 return ret; 193 return ret;
@@ -339,8 +338,10 @@ int log_do_checkpoint(journal_t *journal)
339 } 338 }
340 } while (jh != last_jh && !retry); 339 } while (jh != last_jh && !retry);
341 340
342 if (batch_count) 341 if (batch_count) {
343 __flush_batch(journal, bhs, &batch_count); 342 __flush_batch(journal, bhs, &batch_count);
343 retry = 1;
344 }
344 345
345 /* 346 /*
346 * If someone cleaned up this transaction while we slept, we're 347 * If someone cleaned up this transaction while we slept, we're
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 1e6f2e2ad4a3..5e7b43949517 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -167,7 +167,7 @@ loop:
167 } 167 }
168 168
169 wake_up(&journal->j_wait_done_commit); 169 wake_up(&journal->j_wait_done_commit);
170 if (current->flags & PF_FREEZE) { 170 if (freezing(current)) {
171 /* 171 /*
172 * The simpler the better. Flushing journal isn't a 172 * The simpler the better. Flushing journal isn't a
173 * good idea, because that depends on threads that may 173 * good idea, because that depends on threads that may
@@ -175,7 +175,7 @@ loop:
175 */ 175 */
176 jbd_debug(1, "Now suspending kjournald\n"); 176 jbd_debug(1, "Now suspending kjournald\n");
177 spin_unlock(&journal->j_state_lock); 177 spin_unlock(&journal->j_state_lock);
178 refrigerator(PF_FREEZE); 178 refrigerator();
179 spin_lock(&journal->j_state_lock); 179 spin_lock(&journal->j_state_lock);
180 } else { 180 } else {
181 /* 181 /*
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 8cc6893fc56c..fc589ddd0762 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -175,8 +175,64 @@ jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size)
175 } 175 }
176} 176}
177 177
178/* Print the contents of a node. */
179static void
180jffs_print_node(struct jffs_node *n)
181{
182 D(printk("jffs_node: 0x%p\n", n));
183 D(printk("{\n"));
184 D(printk(" 0x%08x, /* version */\n", n->version));
185 D(printk(" 0x%08x, /* data_offset */\n", n->data_offset));
186 D(printk(" 0x%08x, /* data_size */\n", n->data_size));
187 D(printk(" 0x%08x, /* removed_size */\n", n->removed_size));
188 D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset));
189 D(printk(" 0x%02x, /* name_size */\n", n->name_size));
190 D(printk(" 0x%p, /* fm, fm->offset: %u */\n",
191 n->fm, (n->fm ? n->fm->offset : 0)));
192 D(printk(" 0x%p, /* version_prev */\n", n->version_prev));
193 D(printk(" 0x%p, /* version_next */\n", n->version_next));
194 D(printk(" 0x%p, /* range_prev */\n", n->range_prev));
195 D(printk(" 0x%p, /* range_next */\n", n->range_next));
196 D(printk("}\n"));
197}
198
178#endif 199#endif
179 200
201/* Print the contents of a raw inode. */
202static void
203jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
204{
205 D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
206 D(printk("{\n"));
207 D(printk(" 0x%08x, /* magic */\n", raw_inode->magic));
208 D(printk(" 0x%08x, /* ino */\n", raw_inode->ino));
209 D(printk(" 0x%08x, /* pino */\n", raw_inode->pino));
210 D(printk(" 0x%08x, /* version */\n", raw_inode->version));
211 D(printk(" 0x%08x, /* mode */\n", raw_inode->mode));
212 D(printk(" 0x%04x, /* uid */\n", raw_inode->uid));
213 D(printk(" 0x%04x, /* gid */\n", raw_inode->gid));
214 D(printk(" 0x%08x, /* atime */\n", raw_inode->atime));
215 D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime));
216 D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime));
217 D(printk(" 0x%08x, /* offset */\n", raw_inode->offset));
218 D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize));
219 D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize));
220 D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize));
221 D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink));
222 D(printk(" 0x%02x, /* spare */\n",
223 raw_inode->spare));
224 D(printk(" %u, /* rename */\n",
225 raw_inode->rename));
226 D(printk(" %u, /* deleted */\n",
227 raw_inode->deleted));
228 D(printk(" 0x%02x, /* accurate */\n",
229 raw_inode->accurate));
230 D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum));
231 D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum));
232 D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum));
233 D(printk("}\n"));
234}
235
180#define flash_safe_acquire(arg) 236#define flash_safe_acquire(arg)
181#define flash_safe_release(arg) 237#define flash_safe_release(arg)
182 238
@@ -2507,64 +2563,6 @@ jffs_update_file(struct jffs_file *f, struct jffs_node *node)
2507 return 0; 2563 return 0;
2508} 2564}
2509 2565
2510/* Print the contents of a node. */
2511void
2512jffs_print_node(struct jffs_node *n)
2513{
2514 D(printk("jffs_node: 0x%p\n", n));
2515 D(printk("{\n"));
2516 D(printk(" 0x%08x, /* version */\n", n->version));
2517 D(printk(" 0x%08x, /* data_offset */\n", n->data_offset));
2518 D(printk(" 0x%08x, /* data_size */\n", n->data_size));
2519 D(printk(" 0x%08x, /* removed_size */\n", n->removed_size));
2520 D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset));
2521 D(printk(" 0x%02x, /* name_size */\n", n->name_size));
2522 D(printk(" 0x%p, /* fm, fm->offset: %u */\n",
2523 n->fm, (n->fm ? n->fm->offset : 0)));
2524 D(printk(" 0x%p, /* version_prev */\n", n->version_prev));
2525 D(printk(" 0x%p, /* version_next */\n", n->version_next));
2526 D(printk(" 0x%p, /* range_prev */\n", n->range_prev));
2527 D(printk(" 0x%p, /* range_next */\n", n->range_next));
2528 D(printk("}\n"));
2529}
2530
2531
2532/* Print the contents of a raw inode. */
2533void
2534jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
2535{
2536 D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
2537 D(printk("{\n"));
2538 D(printk(" 0x%08x, /* magic */\n", raw_inode->magic));
2539 D(printk(" 0x%08x, /* ino */\n", raw_inode->ino));
2540 D(printk(" 0x%08x, /* pino */\n", raw_inode->pino));
2541 D(printk(" 0x%08x, /* version */\n", raw_inode->version));
2542 D(printk(" 0x%08x, /* mode */\n", raw_inode->mode));
2543 D(printk(" 0x%04x, /* uid */\n", raw_inode->uid));
2544 D(printk(" 0x%04x, /* gid */\n", raw_inode->gid));
2545 D(printk(" 0x%08x, /* atime */\n", raw_inode->atime));
2546 D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime));
2547 D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime));
2548 D(printk(" 0x%08x, /* offset */\n", raw_inode->offset));
2549 D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize));
2550 D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize));
2551 D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize));
2552 D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink));
2553 D(printk(" 0x%02x, /* spare */\n",
2554 raw_inode->spare));
2555 D(printk(" %u, /* rename */\n",
2556 raw_inode->rename));
2557 D(printk(" %u, /* deleted */\n",
2558 raw_inode->deleted));
2559 D(printk(" 0x%02x, /* accurate */\n",
2560 raw_inode->accurate));
2561 D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum));
2562 D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum));
2563 D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum));
2564 D(printk("}\n"));
2565}
2566
2567
2568/* Print the contents of a file. */ 2566/* Print the contents of a file. */
2569#if 0 2567#if 0
2570int 2568int
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h
index 4ae97b17911c..5c7abe0e2695 100644
--- a/fs/jffs/intrep.h
+++ b/fs/jffs/intrep.h
@@ -49,8 +49,6 @@ int jffs_garbage_collect_thread(void *c);
49void jffs_garbage_collect_trigger(struct jffs_control *c); 49void jffs_garbage_collect_trigger(struct jffs_control *c);
50 50
51/* For debugging purposes. */ 51/* For debugging purposes. */
52void jffs_print_node(struct jffs_node *n);
53void jffs_print_raw_inode(struct jffs_raw_inode *raw_inode);
54#if 0 52#if 0
55int jffs_print_file(struct jffs_file *f); 53int jffs_print_file(struct jffs_file *f);
56#endif /* 0 */ 54#endif /* 0 */
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
index 0cab8da49d3c..053e3a98a276 100644
--- a/fs/jffs/jffs_fm.c
+++ b/fs/jffs/jffs_fm.c
@@ -31,6 +31,60 @@ static void jffs_free_fm(struct jffs_fm *n);
31extern kmem_cache_t *fm_cache; 31extern kmem_cache_t *fm_cache;
32extern kmem_cache_t *node_cache; 32extern kmem_cache_t *node_cache;
33 33
34#if CONFIG_JFFS_FS_VERBOSE > 0
35void
36jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
37{
38 D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
39 D(printk("{\n"));
40 D(printk(" %u, /* flash_size */\n", fmc->flash_size));
41 D(printk(" %u, /* used_size */\n", fmc->used_size));
42 D(printk(" %u, /* dirty_size */\n", fmc->dirty_size));
43 D(printk(" %u, /* free_size */\n", fmc->free_size));
44 D(printk(" %u, /* sector_size */\n", fmc->sector_size));
45 D(printk(" %u, /* min_free_size */\n", fmc->min_free_size));
46 D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size));
47 D(printk(" 0x%p, /* mtd */\n", fmc->mtd));
48 D(printk(" 0x%p, /* head */ "
49 "(head->offset = 0x%08x)\n",
50 fmc->head, (fmc->head ? fmc->head->offset : 0)));
51 D(printk(" 0x%p, /* tail */ "
52 "(tail->offset + tail->size = 0x%08x)\n",
53 fmc->tail,
54 (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
55 D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra));
56 D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra));
57 D(printk("}\n"));
58}
59#endif /* CONFIG_JFFS_FS_VERBOSE > 0 */
60
61#if CONFIG_JFFS_FS_VERBOSE > 2
62static void
63jffs_print_fm(struct jffs_fm *fm)
64{
65 D(printk("struct jffs_fm: 0x%p\n", fm));
66 D(printk("{\n"));
67 D(printk(" 0x%08x, /* offset */\n", fm->offset));
68 D(printk(" %u, /* size */\n", fm->size));
69 D(printk(" 0x%p, /* prev */\n", fm->prev));
70 D(printk(" 0x%p, /* next */\n", fm->next));
71 D(printk(" 0x%p, /* nodes */\n", fm->nodes));
72 D(printk("}\n"));
73}
74#endif /* CONFIG_JFFS_FS_VERBOSE > 2 */
75
76#if 0
77void
78jffs_print_node_ref(struct jffs_node_ref *ref)
79{
80 D(printk("struct jffs_node_ref: 0x%p\n", ref));
81 D(printk("{\n"));
82 D(printk(" 0x%p, /* node */\n", ref->node));
83 D(printk(" 0x%p, /* next */\n", ref->next));
84 D(printk("}\n"));
85}
86#endif /* 0 */
87
34/* This function creates a new shiny flash memory control structure. */ 88/* This function creates a new shiny flash memory control structure. */
35struct jffs_fmcontrol * 89struct jffs_fmcontrol *
36jffs_build_begin(struct jffs_control *c, int unit) 90jffs_build_begin(struct jffs_control *c, int unit)
@@ -742,54 +796,3 @@ int jffs_get_node_inuse(void)
742{ 796{
743 return no_jffs_node; 797 return no_jffs_node;
744} 798}
745
746void
747jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
748{
749 D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
750 D(printk("{\n"));
751 D(printk(" %u, /* flash_size */\n", fmc->flash_size));
752 D(printk(" %u, /* used_size */\n", fmc->used_size));
753 D(printk(" %u, /* dirty_size */\n", fmc->dirty_size));
754 D(printk(" %u, /* free_size */\n", fmc->free_size));
755 D(printk(" %u, /* sector_size */\n", fmc->sector_size));
756 D(printk(" %u, /* min_free_size */\n", fmc->min_free_size));
757 D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size));
758 D(printk(" 0x%p, /* mtd */\n", fmc->mtd));
759 D(printk(" 0x%p, /* head */ "
760 "(head->offset = 0x%08x)\n",
761 fmc->head, (fmc->head ? fmc->head->offset : 0)));
762 D(printk(" 0x%p, /* tail */ "
763 "(tail->offset + tail->size = 0x%08x)\n",
764 fmc->tail,
765 (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
766 D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra));
767 D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra));
768 D(printk("}\n"));
769}
770
771void
772jffs_print_fm(struct jffs_fm *fm)
773{
774 D(printk("struct jffs_fm: 0x%p\n", fm));
775 D(printk("{\n"));
776 D(printk(" 0x%08x, /* offset */\n", fm->offset));
777 D(printk(" %u, /* size */\n", fm->size));
778 D(printk(" 0x%p, /* prev */\n", fm->prev));
779 D(printk(" 0x%p, /* next */\n", fm->next));
780 D(printk(" 0x%p, /* nodes */\n", fm->nodes));
781 D(printk("}\n"));
782}
783
784#if 0
785void
786jffs_print_node_ref(struct jffs_node_ref *ref)
787{
788 D(printk("struct jffs_node_ref: 0x%p\n", ref));
789 D(printk("{\n"));
790 D(printk(" 0x%p, /* node */\n", ref->node));
791 D(printk(" 0x%p, /* next */\n", ref->next));
792 D(printk("}\n"));
793}
794#endif /* 0 */
795
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h
index bc291c431822..f64151e74122 100644
--- a/fs/jffs/jffs_fm.h
+++ b/fs/jffs/jffs_fm.h
@@ -139,8 +139,9 @@ int jffs_add_node(struct jffs_node *node);
139void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, 139void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
140 __u32 size); 140 __u32 size);
141 141
142#if CONFIG_JFFS_FS_VERBOSE > 0
142void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc); 143void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
143void jffs_print_fm(struct jffs_fm *fm); 144#endif
144#if 0 145#if 0
145void jffs_print_node_ref(struct jffs_node_ref *ref); 146void jffs_print_node_ref(struct jffs_node_ref *ref);
146#endif /* 0 */ 147#endif /* 0 */
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 65119d72cce0..0f224384f176 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -95,7 +95,7 @@ static int jffs2_garbage_collect_thread(void *_c)
95 schedule(); 95 schedule();
96 } 96 }
97 97
98 if (try_to_freeze(0)) 98 if (try_to_freeze())
99 continue; 99 continue;
100 100
101 cond_resched(); 101 cond_resched();
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 8d2a9ab981d4..e892dab40c26 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -21,6 +21,7 @@
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/quotaops.h> 23#include <linux/quotaops.h>
24#include <linux/posix_acl_xattr.h>
24#include "jfs_incore.h" 25#include "jfs_incore.h"
25#include "jfs_xattr.h" 26#include "jfs_xattr.h"
26#include "jfs_acl.h" 27#include "jfs_acl.h"
@@ -36,11 +37,11 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
36 37
37 switch(type) { 38 switch(type) {
38 case ACL_TYPE_ACCESS: 39 case ACL_TYPE_ACCESS:
39 ea_name = XATTR_NAME_ACL_ACCESS; 40 ea_name = POSIX_ACL_XATTR_ACCESS;
40 p_acl = &ji->i_acl; 41 p_acl = &ji->i_acl;
41 break; 42 break;
42 case ACL_TYPE_DEFAULT: 43 case ACL_TYPE_DEFAULT:
43 ea_name = XATTR_NAME_ACL_DEFAULT; 44 ea_name = POSIX_ACL_XATTR_DEFAULT;
44 p_acl = &ji->i_default_acl; 45 p_acl = &ji->i_default_acl;
45 break; 46 break;
46 default: 47 default:
@@ -70,8 +71,7 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
70 if (!IS_ERR(acl)) 71 if (!IS_ERR(acl))
71 *p_acl = posix_acl_dup(acl); 72 *p_acl = posix_acl_dup(acl);
72 } 73 }
73 if (value) 74 kfree(value);
74 kfree(value);
75 return acl; 75 return acl;
76} 76}
77 77
@@ -89,11 +89,11 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
89 89
90 switch(type) { 90 switch(type) {
91 case ACL_TYPE_ACCESS: 91 case ACL_TYPE_ACCESS:
92 ea_name = XATTR_NAME_ACL_ACCESS; 92 ea_name = POSIX_ACL_XATTR_ACCESS;
93 p_acl = &ji->i_acl; 93 p_acl = &ji->i_acl;
94 break; 94 break;
95 case ACL_TYPE_DEFAULT: 95 case ACL_TYPE_DEFAULT:
96 ea_name = XATTR_NAME_ACL_DEFAULT; 96 ea_name = POSIX_ACL_XATTR_DEFAULT;
97 p_acl = &ji->i_default_acl; 97 p_acl = &ji->i_default_acl;
98 if (!S_ISDIR(inode->i_mode)) 98 if (!S_ISDIR(inode->i_mode))
99 return acl ? -EACCES : 0; 99 return acl ? -EACCES : 0;
@@ -102,7 +102,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
102 return -EINVAL; 102 return -EINVAL;
103 } 103 }
104 if (acl) { 104 if (acl) {
105 size = xattr_acl_size(acl->a_count); 105 size = posix_acl_xattr_size(acl->a_count);
106 value = kmalloc(size, GFP_KERNEL); 106 value = kmalloc(size, GFP_KERNEL);
107 if (!value) 107 if (!value)
108 return -ENOMEM; 108 return -ENOMEM;
@@ -112,8 +112,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
112 } 112 }
113 rc = __jfs_setxattr(inode, ea_name, value, size, 0); 113 rc = __jfs_setxattr(inode, ea_name, value, size, 0);
114out: 114out:
115 if (value) 115 kfree(value);
116 kfree(value);
117 116
118 if (!rc) { 117 if (!rc) {
119 if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) 118 if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED))
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index a87b06fa8ff8..c2c19c9ed9a4 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) International Business Machines Corp., 2000-2002 2 * Copyright (C) International Business Machines Corp., 2000-2002
3 * Portions Copyright (c) Christoph Hellwig, 2001-2002 3 * Portions Copyright (C) Christoph Hellwig, 2001-2002
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -19,16 +19,13 @@
19 19
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include "jfs_incore.h" 21#include "jfs_incore.h"
22#include "jfs_inode.h"
22#include "jfs_dmap.h" 23#include "jfs_dmap.h"
23#include "jfs_txnmgr.h" 24#include "jfs_txnmgr.h"
24#include "jfs_xattr.h" 25#include "jfs_xattr.h"
25#include "jfs_acl.h" 26#include "jfs_acl.h"
26#include "jfs_debug.h" 27#include "jfs_debug.h"
27 28
28
29extern int jfs_commit_inode(struct inode *, int);
30extern void jfs_truncate(struct inode *);
31
32int jfs_fsync(struct file *file, struct dentry *dentry, int datasync) 29int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
33{ 30{
34 struct inode *inode = dentry->d_inode; 31 struct inode *inode = dentry->d_inode;
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 24a689179af2..2137138c59b0 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -23,6 +23,7 @@
23#include <linux/pagemap.h> 23#include <linux/pagemap.h>
24#include <linux/quotaops.h> 24#include <linux/quotaops.h>
25#include "jfs_incore.h" 25#include "jfs_incore.h"
26#include "jfs_inode.h"
26#include "jfs_filsys.h" 27#include "jfs_filsys.h"
27#include "jfs_imap.h" 28#include "jfs_imap.h"
28#include "jfs_extent.h" 29#include "jfs_extent.h"
@@ -30,14 +31,6 @@
30#include "jfs_debug.h" 31#include "jfs_debug.h"
31 32
32 33
33extern struct inode_operations jfs_dir_inode_operations;
34extern struct inode_operations jfs_file_inode_operations;
35extern struct inode_operations jfs_symlink_inode_operations;
36extern struct file_operations jfs_dir_operations;
37extern struct file_operations jfs_file_operations;
38struct address_space_operations jfs_aops;
39extern int freeZeroLink(struct inode *);
40
41void jfs_read_inode(struct inode *inode) 34void jfs_read_inode(struct inode *inode)
42{ 35{
43 if (diRead(inode)) { 36 if (diRead(inode)) {
@@ -136,7 +129,7 @@ void jfs_delete_inode(struct inode *inode)
136 jfs_info("In jfs_delete_inode, inode = 0x%p", inode); 129 jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
137 130
138 if (test_cflag(COMMIT_Freewmap, inode)) 131 if (test_cflag(COMMIT_Freewmap, inode))
139 freeZeroLink(inode); 132 jfs_free_zero_link(inode);
140 133
141 diFree(inode); 134 diFree(inode);
142 135
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index d2ae430adecf..a3acd3eec059 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -20,8 +20,6 @@
20 20
21#ifdef CONFIG_JFS_POSIX_ACL 21#ifdef CONFIG_JFS_POSIX_ACL
22 22
23#include <linux/xattr_acl.h>
24
25int jfs_permission(struct inode *, int, struct nameidata *); 23int jfs_permission(struct inode *, int, struct nameidata *);
26int jfs_init_acl(struct inode *, struct inode *); 24int jfs_init_acl(struct inode *, struct inode *);
27int jfs_setattr(struct dentry *, struct iattr *); 25int jfs_setattr(struct dentry *, struct iattr *);
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 91a0a889ebc5..4caea6b43b92 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -58,8 +58,6 @@ void dump_mem(char *label, void *data, int length)
58 58
59static struct proc_dir_entry *base; 59static struct proc_dir_entry *base;
60#ifdef CONFIG_JFS_DEBUG 60#ifdef CONFIG_JFS_DEBUG
61extern read_proc_t jfs_txanchor_read;
62
63static int loglevel_read(char *page, char **start, off_t off, 61static int loglevel_read(char *page, char **start, off_t off,
64 int count, int *eof, void *data) 62 int count, int *eof, void *data)
65{ 63{
@@ -97,14 +95,6 @@ static int loglevel_write(struct file *file, const char __user *buffer,
97} 95}
98#endif 96#endif
99 97
100
101#ifdef CONFIG_JFS_STATISTICS
102extern read_proc_t jfs_lmstats_read;
103extern read_proc_t jfs_txstats_read;
104extern read_proc_t jfs_xtstat_read;
105extern read_proc_t jfs_mpstat_read;
106#endif
107
108static struct { 98static struct {
109 const char *name; 99 const char *name;
110 read_proc_t *read_fn; 100 read_proc_t *read_fn;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index a38079ae1e00..ddffbbd4d955 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) International Business Machines Corp., 2000-2002 2 * Copyright (C) International Business Machines Corp., 2000-2002
3 * Portions Copyright (c) Christoph Hellwig, 2001-2002 3 * Portions Copyright (C) Christoph Hellwig, 2001-2002
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -31,7 +31,9 @@
31 * CONFIG_JFS_DEBUG or CONFIG_JFS_STATISTICS is defined 31 * CONFIG_JFS_DEBUG or CONFIG_JFS_STATISTICS is defined
32 */ 32 */
33#if defined(CONFIG_PROC_FS) && (defined(CONFIG_JFS_DEBUG) || defined(CONFIG_JFS_STATISTICS)) 33#if defined(CONFIG_PROC_FS) && (defined(CONFIG_JFS_DEBUG) || defined(CONFIG_JFS_STATISTICS))
34 #define PROC_FS_JFS 34#define PROC_FS_JFS
35extern void jfs_proc_init(void);
36extern void jfs_proc_clean(void);
35#endif 37#endif
36 38
37/* 39/*
@@ -65,8 +67,8 @@
65 67
66extern int jfsloglevel; 68extern int jfsloglevel;
67 69
68/* dump memory contents */
69extern void dump_mem(char *label, void *data, int length); 70extern void dump_mem(char *label, void *data, int length);
71extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
70 72
71/* information message: e.g., configuration, major event */ 73/* information message: e.g., configuration, major event */
72#define jfs_info(fmt, arg...) do { \ 74#define jfs_info(fmt, arg...) do { \
@@ -110,6 +112,11 @@ extern void dump_mem(char *label, void *data, int length);
110 * ---------- 112 * ----------
111 */ 113 */
112#ifdef CONFIG_JFS_STATISTICS 114#ifdef CONFIG_JFS_STATISTICS
115extern int jfs_lmstats_read(char *, char **, off_t, int, int *, void *);
116extern int jfs_txstats_read(char *, char **, off_t, int, int *, void *);
117extern int jfs_mpstat_read(char *, char **, off_t, int, int *, void *);
118extern int jfs_xtstat_read(char *, char **, off_t, int, int *, void *);
119
113#define INCREMENT(x) ((x)++) 120#define INCREMENT(x) ((x)++)
114#define DECREMENT(x) ((x)--) 121#define DECREMENT(x) ((x)--)
115#define HIGHWATERMARK(x,y) ((x) = max((x), (y))) 122#define HIGHWATERMARK(x,y) ((x) = max((x), (y)))
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 69007fd546ef..cced2fed9d0f 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -272,7 +272,6 @@ int dbMount(struct inode *ipbmap)
272int dbUnmount(struct inode *ipbmap, int mounterror) 272int dbUnmount(struct inode *ipbmap, int mounterror)
273{ 273{
274 struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap; 274 struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
275 int i;
276 275
277 if (!(mounterror || isReadOnly(ipbmap))) 276 if (!(mounterror || isReadOnly(ipbmap)))
278 dbSync(ipbmap); 277 dbSync(ipbmap);
@@ -282,14 +281,6 @@ int dbUnmount(struct inode *ipbmap, int mounterror)
282 */ 281 */
283 truncate_inode_pages(ipbmap->i_mapping, 0); 282 truncate_inode_pages(ipbmap->i_mapping, 0);
284 283
285 /*
286 * Sanity Check
287 */
288 for (i = 0; i < bmp->db_numag; i++)
289 if (atomic_read(&bmp->db_active[i]))
290 printk(KERN_ERR "dbUnmount: db_active[%d] = %d\n",
291 i, atomic_read(&bmp->db_active[i]));
292
293 /* free the memory for the in-memory bmap. */ 284 /* free the memory for the in-memory bmap. */
294 kfree(bmp); 285 kfree(bmp);
295 286
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index ac41f72d6d50..8676aee3ae48 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -2931,6 +2931,9 @@ static void add_missing_indices(struct inode *inode, s64 bn)
2931 ASSERT(p->header.flag & BT_LEAF); 2931 ASSERT(p->header.flag & BT_LEAF);
2932 2932
2933 tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY); 2933 tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
2934 if (BT_IS_ROOT(mp))
2935 tlck->type |= tlckBTROOT;
2936
2934 dtlck = (struct dt_lock *) &tlck->lock; 2937 dtlck = (struct dt_lock *) &tlck->lock;
2935 2938
2936 stbl = DT_GETSTBL(p); 2939 stbl = DT_GETSTBL(p);
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 1953acb79266..4879603daa1c 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -19,6 +19,7 @@
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/quotaops.h> 20#include <linux/quotaops.h>
21#include "jfs_incore.h" 21#include "jfs_incore.h"
22#include "jfs_inode.h"
22#include "jfs_superblock.h" 23#include "jfs_superblock.h"
23#include "jfs_dmap.h" 24#include "jfs_dmap.h"
24#include "jfs_extent.h" 25#include "jfs_extent.h"
@@ -33,12 +34,6 @@ static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);
33#endif 34#endif
34static s64 extRoundDown(s64 nb); 35static s64 extRoundDown(s64 nb);
35 36
36/*
37 * external references
38 */
39extern int jfs_commit_inode(struct inode *, int);
40
41
42#define DPD(a) (printk("(a): %d\n",(a))) 37#define DPD(a) (printk("(a): %d\n",(a)))
43#define DPC(a) (printk("(a): %c\n",(a))) 38#define DPC(a) (printk("(a): %c\n",(a)))
44#define DPL1(a) \ 39#define DPL1(a) \
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 7acff2ce3c80..971af2977eff 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -47,6 +47,7 @@
47#include <linux/quotaops.h> 47#include <linux/quotaops.h>
48 48
49#include "jfs_incore.h" 49#include "jfs_incore.h"
50#include "jfs_inode.h"
50#include "jfs_filsys.h" 51#include "jfs_filsys.h"
51#include "jfs_dinode.h" 52#include "jfs_dinode.h"
52#include "jfs_dmap.h" 53#include "jfs_dmap.h"
@@ -69,11 +70,6 @@
69#define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno]) 70#define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno])
70 71
71/* 72/*
72 * external references
73 */
74extern struct address_space_operations jfs_aops;
75
76/*
77 * forward references 73 * forward references
78 */ 74 */
79static int diAllocAG(struct inomap *, int, boolean_t, struct inode *); 75static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 84f2459b2191..2af5efbfd06f 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -19,6 +19,7 @@
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/quotaops.h> 20#include <linux/quotaops.h>
21#include "jfs_incore.h" 21#include "jfs_incore.h"
22#include "jfs_inode.h"
22#include "jfs_filsys.h" 23#include "jfs_filsys.h"
23#include "jfs_imap.h" 24#include "jfs_imap.h"
24#include "jfs_dinode.h" 25#include "jfs_dinode.h"
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 3df91fbfe781..b54bac576cb3 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) International Business Machines Corp., 2000-2001 2 * Copyright (C) International Business Machines Corp., 2000-2001
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
@@ -19,5 +19,22 @@
19#define _H_JFS_INODE 19#define _H_JFS_INODE
20 20
21extern struct inode *ialloc(struct inode *, umode_t); 21extern struct inode *ialloc(struct inode *, umode_t);
22extern int jfs_fsync(struct file *, struct dentry *, int);
23extern void jfs_read_inode(struct inode *);
24extern int jfs_commit_inode(struct inode *, int);
25extern int jfs_write_inode(struct inode*, int);
26extern void jfs_delete_inode(struct inode *);
27extern void jfs_dirty_inode(struct inode *);
28extern void jfs_truncate(struct inode *);
29extern void jfs_truncate_nolock(struct inode *, loff_t);
30extern void jfs_free_zero_link(struct inode *);
31extern struct dentry *jfs_get_parent(struct dentry *dentry);
22 32
33extern struct address_space_operations jfs_aops;
34extern struct inode_operations jfs_dir_inode_operations;
35extern struct file_operations jfs_dir_operations;
36extern struct inode_operations jfs_file_inode_operations;
37extern struct file_operations jfs_file_operations;
38extern struct inode_operations jfs_symlink_inode_operations;
39extern struct dentry_operations jfs_ci_dentry_operations;
23#endif /* _H_JFS_INODE */ 40#endif /* _H_JFS_INODE */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index dfa1200daa61..79d07624bfe1 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -71,6 +71,7 @@
71#include "jfs_incore.h" 71#include "jfs_incore.h"
72#include "jfs_filsys.h" 72#include "jfs_filsys.h"
73#include "jfs_metapage.h" 73#include "jfs_metapage.h"
74#include "jfs_superblock.h"
74#include "jfs_txnmgr.h" 75#include "jfs_txnmgr.h"
75#include "jfs_debug.h" 76#include "jfs_debug.h"
76 77
@@ -167,14 +168,6 @@ static struct jfs_log *dummy_log = NULL;
167static DECLARE_MUTEX(jfs_log_sem); 168static DECLARE_MUTEX(jfs_log_sem);
168 169
169/* 170/*
170 * external references
171 */
172extern void txLazyUnlock(struct tblock * tblk);
173extern int jfs_stop_threads;
174extern struct completion jfsIOwait;
175extern int jfs_tlocks_low;
176
177/*
178 * forward references 171 * forward references
179 */ 172 */
180static int lmWriteRecord(struct jfs_log * log, struct tblock * tblk, 173static int lmWriteRecord(struct jfs_log * log, struct tblock * tblk,
@@ -1624,6 +1617,8 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1624 } 1617 }
1625 } 1618 }
1626 assert(list_empty(&log->cqueue)); 1619 assert(list_empty(&log->cqueue));
1620
1621#ifdef CONFIG_JFS_DEBUG
1627 if (!list_empty(&log->synclist)) { 1622 if (!list_empty(&log->synclist)) {
1628 struct logsyncblk *lp; 1623 struct logsyncblk *lp;
1629 1624
@@ -1638,9 +1633,8 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1638 dump_mem("orphan tblock", lp, 1633 dump_mem("orphan tblock", lp,
1639 sizeof(struct tblock)); 1634 sizeof(struct tblock));
1640 } 1635 }
1641// current->state = TASK_INTERRUPTIBLE;
1642// schedule();
1643 } 1636 }
1637#endif
1644 //assert(list_empty(&log->synclist)); 1638 //assert(list_empty(&log->synclist));
1645 clear_bit(log_FLUSH, &log->flag); 1639 clear_bit(log_FLUSH, &log->flag);
1646} 1640}
@@ -2365,9 +2359,9 @@ int jfsIOWait(void *arg)
2365 lbmStartIO(bp); 2359 lbmStartIO(bp);
2366 spin_lock_irq(&log_redrive_lock); 2360 spin_lock_irq(&log_redrive_lock);
2367 } 2361 }
2368 if (current->flags & PF_FREEZE) { 2362 if (freezing(current)) {
2369 spin_unlock_irq(&log_redrive_lock); 2363 spin_unlock_irq(&log_redrive_lock);
2370 refrigerator(PF_FREEZE); 2364 refrigerator();
2371 } else { 2365 } else {
2372 add_wait_queue(&jfs_IO_thread_wait, &wq); 2366 add_wait_queue(&jfs_IO_thread_wait, &wq);
2373 set_current_state(TASK_INTERRUPTIBLE); 2367 set_current_state(TASK_INTERRUPTIBLE);
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 51291fbc420c..747114cd38b8 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -507,6 +507,8 @@ extern int lmLogClose(struct super_block *sb);
507extern int lmLogShutdown(struct jfs_log * log); 507extern int lmLogShutdown(struct jfs_log * log);
508extern int lmLogInit(struct jfs_log * log); 508extern int lmLogInit(struct jfs_log * log);
509extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize); 509extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
510extern int lmGroupCommit(struct jfs_log *, struct tblock *);
511extern int jfsIOWait(void *);
510extern void jfs_flush_journal(struct jfs_log * log, int wait); 512extern void jfs_flush_journal(struct jfs_log * log, int wait);
511extern void jfs_syncpt(struct jfs_log *log); 513extern void jfs_syncpt(struct jfs_log *log);
512 514
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 41bf078dce05..6c5485d16c39 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -198,7 +198,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
198 } 198 }
199} 199}
200 200
201static inline struct metapage *alloc_metapage(int gfp_mask) 201static inline struct metapage *alloc_metapage(unsigned int gfp_mask)
202{ 202{
203 return mempool_alloc(metapage_mempool, gfp_mask); 203 return mempool_alloc(metapage_mempool, gfp_mask);
204} 204}
@@ -726,12 +726,12 @@ void force_metapage(struct metapage *mp)
726 page_cache_release(page); 726 page_cache_release(page);
727} 727}
728 728
729extern void hold_metapage(struct metapage *mp) 729void hold_metapage(struct metapage *mp)
730{ 730{
731 lock_page(mp->page); 731 lock_page(mp->page);
732} 732}
733 733
734extern void put_metapage(struct metapage *mp) 734void put_metapage(struct metapage *mp)
735{ 735{
736 if (mp->count || mp->nohomeok) { 736 if (mp->count || mp->nohomeok) {
737 /* Someone else will release this */ 737 /* Someone else will release this */
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index 991e9fb84c75..f0b7d3282b07 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) International Business Machines Corp., 2000-2002 2 * Copyright (C) International Business Machines Corp., 2000-2002
3 * Portions Copyright (c) Christoph Hellwig, 2001-2002 3 * Portions Copyright (C) Christoph Hellwig, 2001-2002
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -58,6 +58,8 @@ struct metapage {
58#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag) 58#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
59 59
60/* function prototypes */ 60/* function prototypes */
61extern int metapage_init(void);
62extern void metapage_exit(void);
61extern struct metapage *__get_metapage(struct inode *inode, 63extern struct metapage *__get_metapage(struct inode *inode,
62 unsigned long lblock, unsigned int size, 64 unsigned long lblock, unsigned int size,
63 int absolute, unsigned long new); 65 int absolute, unsigned long new);
diff --git a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
index ab0566f70cfa..fcf781bf31cb 100644
--- a/fs/jfs/jfs_superblock.h
+++ b/fs/jfs/jfs_superblock.h
@@ -109,5 +109,16 @@ struct jfs_superblock {
109extern int readSuper(struct super_block *, struct buffer_head **); 109extern int readSuper(struct super_block *, struct buffer_head **);
110extern int updateSuper(struct super_block *, uint); 110extern int updateSuper(struct super_block *, uint);
111extern void jfs_error(struct super_block *, const char *, ...); 111extern void jfs_error(struct super_block *, const char *, ...);
112extern int jfs_mount(struct super_block *);
113extern int jfs_mount_rw(struct super_block *, int);
114extern int jfs_umount(struct super_block *);
115extern int jfs_umount_rw(struct super_block *);
116
117extern int jfs_stop_threads;
118extern struct completion jfsIOwait;
119extern wait_queue_head_t jfs_IO_thread_wait;
120extern wait_queue_head_t jfs_commit_thread_wait;
121extern wait_queue_head_t jfs_sync_thread_wait;
122extern int jfs_extendfs(struct super_block *, s64, int);
112 123
113#endif /*_H_JFS_SUPERBLOCK */ 124#endif /*_H_JFS_SUPERBLOCK */
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index e93d01aa12c4..121c981ff453 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -42,7 +42,6 @@
42 * hold on to mp+lock thru update of maps 42 * hold on to mp+lock thru update of maps
43 */ 43 */
44 44
45
46#include <linux/fs.h> 45#include <linux/fs.h>
47#include <linux/vmalloc.h> 46#include <linux/vmalloc.h>
48#include <linux/smp_lock.h> 47#include <linux/smp_lock.h>
@@ -51,6 +50,7 @@
51#include <linux/module.h> 50#include <linux/module.h>
52#include <linux/moduleparam.h> 51#include <linux/moduleparam.h>
53#include "jfs_incore.h" 52#include "jfs_incore.h"
53#include "jfs_inode.h"
54#include "jfs_filsys.h" 54#include "jfs_filsys.h"
55#include "jfs_metapage.h" 55#include "jfs_metapage.h"
56#include "jfs_dinode.h" 56#include "jfs_dinode.h"
@@ -109,7 +109,6 @@ static int TxLockHWM; /* High water mark for number of txLocks used */
109static int TxLockVHWM; /* Very High water mark */ 109static int TxLockVHWM; /* Very High water mark */
110struct tlock *TxLock; /* transaction lock table */ 110struct tlock *TxLock; /* transaction lock table */
111 111
112
113/* 112/*
114 * transaction management lock 113 * transaction management lock
115 */ 114 */
@@ -149,7 +148,6 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event)
149 148
150#define TXN_WAKEUP(event) wake_up_all(event) 149#define TXN_WAKEUP(event) wake_up_all(event)
151 150
152
153/* 151/*
154 * statistics 152 * statistics
155 */ 153 */
@@ -161,16 +159,6 @@ static struct {
161 int waitlock; /* 4: # of tlock wait */ 159 int waitlock; /* 4: # of tlock wait */
162} stattx; 160} stattx;
163 161
164
165/*
166 * external references
167 */
168extern int lmGroupCommit(struct jfs_log *, struct tblock *);
169extern int jfs_commit_inode(struct inode *, int);
170extern int jfs_stop_threads;
171
172extern struct completion jfsIOwait;
173
174/* 162/*
175 * forward references 163 * forward references
176 */ 164 */
@@ -358,7 +346,6 @@ void txExit(void)
358 TxBlock = NULL; 346 TxBlock = NULL;
359} 347}
360 348
361
362/* 349/*
363 * NAME: txBegin() 350 * NAME: txBegin()
364 * 351 *
@@ -460,7 +447,6 @@ tid_t txBegin(struct super_block *sb, int flag)
460 return t; 447 return t;
461} 448}
462 449
463
464/* 450/*
465 * NAME: txBeginAnon() 451 * NAME: txBeginAnon()
466 * 452 *
@@ -503,7 +489,6 @@ void txBeginAnon(struct super_block *sb)
503 TXN_UNLOCK(); 489 TXN_UNLOCK();
504} 490}
505 491
506
507/* 492/*
508 * txEnd() 493 * txEnd()
509 * 494 *
@@ -592,7 +577,6 @@ wakeup:
592 TXN_WAKEUP(&TxAnchor.freewait); 577 TXN_WAKEUP(&TxAnchor.freewait);
593} 578}
594 579
595
596/* 580/*
597 * txLock() 581 * txLock()
598 * 582 *
@@ -868,7 +852,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
868 return NULL; 852 return NULL;
869} 853}
870 854
871
872/* 855/*
873 * NAME: txRelease() 856 * NAME: txRelease()
874 * 857 *
@@ -908,7 +891,6 @@ static void txRelease(struct tblock * tblk)
908 TXN_UNLOCK(); 891 TXN_UNLOCK();
909} 892}
910 893
911
912/* 894/*
913 * NAME: txUnlock() 895 * NAME: txUnlock()
914 * 896 *
@@ -996,7 +978,6 @@ static void txUnlock(struct tblock * tblk)
996 } 978 }
997} 979}
998 980
999
1000/* 981/*
1001 * txMaplock() 982 * txMaplock()
1002 * 983 *
@@ -1069,7 +1050,6 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
1069 return tlck; 1050 return tlck;
1070} 1051}
1071 1052
1072
1073/* 1053/*
1074 * txLinelock() 1054 * txLinelock()
1075 * 1055 *
@@ -1103,8 +1083,6 @@ struct linelock *txLinelock(struct linelock * tlock)
1103 return linelock; 1083 return linelock;
1104} 1084}
1105 1085
1106
1107
1108/* 1086/*
1109 * transaction commit management 1087 * transaction commit management
1110 * ----------------------------- 1088 * -----------------------------
@@ -1373,7 +1351,6 @@ int txCommit(tid_t tid, /* transaction identifier */
1373 return rc; 1351 return rc;
1374} 1352}
1375 1353
1376
1377/* 1354/*
1378 * NAME: txLog() 1355 * NAME: txLog()
1379 * 1356 *
@@ -1437,7 +1414,6 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
1437 return rc; 1414 return rc;
1438} 1415}
1439 1416
1440
1441/* 1417/*
1442 * diLog() 1418 * diLog()
1443 * 1419 *
@@ -1465,7 +1441,6 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1465 if (tlck->type & tlckENTRY) { 1441 if (tlck->type & tlckENTRY) {
1466 /* log after-image for logredo(): */ 1442 /* log after-image for logredo(): */
1467 lrd->type = cpu_to_le16(LOG_REDOPAGE); 1443 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1468// *pxd = mp->cm_pxd;
1469 PXDaddress(pxd, mp->index); 1444 PXDaddress(pxd, mp->index);
1470 PXDlength(pxd, 1445 PXDlength(pxd,
1471 mp->logical_size >> tblk->sb->s_blocksize_bits); 1446 mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1552,7 +1527,6 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1552 return rc; 1527 return rc;
1553} 1528}
1554 1529
1555
1556/* 1530/*
1557 * dataLog() 1531 * dataLog()
1558 * 1532 *
@@ -1599,7 +1573,6 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1599 return 0; 1573 return 0;
1600} 1574}
1601 1575
1602
1603/* 1576/*
1604 * dtLog() 1577 * dtLog()
1605 * 1578 *
@@ -1639,7 +1612,6 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1639 lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND); 1612 lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND);
1640 else 1613 else
1641 lrd->log.redopage.type |= cpu_to_le16(LOG_NEW); 1614 lrd->log.redopage.type |= cpu_to_le16(LOG_NEW);
1642// *pxd = mp->cm_pxd;
1643 PXDaddress(pxd, mp->index); 1615 PXDaddress(pxd, mp->index);
1644 PXDlength(pxd, 1616 PXDlength(pxd,
1645 mp->logical_size >> tblk->sb->s_blocksize_bits); 1617 mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1704,7 +1676,6 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1704 return; 1676 return;
1705} 1677}
1706 1678
1707
1708/* 1679/*
1709 * xtLog() 1680 * xtLog()
1710 * 1681 *
@@ -1760,7 +1731,6 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1760 * applying the after-image to the meta-data page. 1731 * applying the after-image to the meta-data page.
1761 */ 1732 */
1762 lrd->type = cpu_to_le16(LOG_REDOPAGE); 1733 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1763// *page_pxd = mp->cm_pxd;
1764 PXDaddress(page_pxd, mp->index); 1734 PXDaddress(page_pxd, mp->index);
1765 PXDlength(page_pxd, 1735 PXDlength(page_pxd,
1766 mp->logical_size >> tblk->sb->s_blocksize_bits); 1736 mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -2093,7 +2063,6 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
2093 return; 2063 return;
2094} 2064}
2095 2065
2096
2097/* 2066/*
2098 * mapLog() 2067 * mapLog()
2099 * 2068 *
@@ -2180,7 +2149,6 @@ void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
2180 } 2149 }
2181} 2150}
2182 2151
2183
2184/* 2152/*
2185 * txEA() 2153 * txEA()
2186 * 2154 *
@@ -2233,7 +2201,6 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
2233 } 2201 }
2234} 2202}
2235 2203
2236
2237/* 2204/*
2238 * txForce() 2205 * txForce()
2239 * 2206 *
@@ -2300,7 +2267,6 @@ void txForce(struct tblock * tblk)
2300 } 2267 }
2301} 2268}
2302 2269
2303
2304/* 2270/*
2305 * txUpdateMap() 2271 * txUpdateMap()
2306 * 2272 *
@@ -2437,7 +2403,6 @@ static void txUpdateMap(struct tblock * tblk)
2437 } 2403 }
2438} 2404}
2439 2405
2440
2441/* 2406/*
2442 * txAllocPMap() 2407 * txAllocPMap()
2443 * 2408 *
@@ -2509,7 +2474,6 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
2509 } 2474 }
2510} 2475}
2511 2476
2512
2513/* 2477/*
2514 * txFreeMap() 2478 * txFreeMap()
2515 * 2479 *
@@ -2611,7 +2575,6 @@ void txFreeMap(struct inode *ip,
2611 } 2575 }
2612} 2576}
2613 2577
2614
2615/* 2578/*
2616 * txFreelock() 2579 * txFreelock()
2617 * 2580 *
@@ -2652,7 +2615,6 @@ void txFreelock(struct inode *ip)
2652 TXN_UNLOCK(); 2615 TXN_UNLOCK();
2653} 2616}
2654 2617
2655
2656/* 2618/*
2657 * txAbort() 2619 * txAbort()
2658 * 2620 *
@@ -2826,9 +2788,9 @@ int jfs_lazycommit(void *arg)
2826 /* In case a wakeup came while all threads were active */ 2788 /* In case a wakeup came while all threads were active */
2827 jfs_commit_thread_waking = 0; 2789 jfs_commit_thread_waking = 0;
2828 2790
2829 if (current->flags & PF_FREEZE) { 2791 if (freezing(current)) {
2830 LAZY_UNLOCK(flags); 2792 LAZY_UNLOCK(flags);
2831 refrigerator(PF_FREEZE); 2793 refrigerator();
2832 } else { 2794 } else {
2833 DECLARE_WAITQUEUE(wq, current); 2795 DECLARE_WAITQUEUE(wq, current);
2834 2796
@@ -3025,9 +2987,9 @@ int jfs_sync(void *arg)
3025 /* Add anon_list2 back to anon_list */ 2987 /* Add anon_list2 back to anon_list */
3026 list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list); 2988 list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list);
3027 2989
3028 if (current->flags & PF_FREEZE) { 2990 if (freezing(current)) {
3029 TXN_UNLOCK(); 2991 TXN_UNLOCK();
3030 refrigerator(PF_FREEZE); 2992 refrigerator();
3031 } else { 2993 } else {
3032 DECLARE_WAITQUEUE(wq, current); 2994 DECLARE_WAITQUEUE(wq, current);
3033 2995
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index b71b82c2df04..59ad0f6b7231 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -285,34 +285,26 @@ struct commit {
285/* 285/*
286 * external declarations 286 * external declarations
287 */ 287 */
288extern struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage *mp, 288extern int jfs_tlocks_low;
289 int flag); 289
290 290extern int txInit(void);
291extern struct tlock *txMaplock(tid_t tid, struct inode *ip, int flag); 291extern void txExit(void);
292 292extern struct tlock *txLock(tid_t, struct inode *, struct metapage *, int);
293extern int txCommit(tid_t tid, int nip, struct inode **iplist, int flag); 293extern struct tlock *txMaplock(tid_t, struct inode *, int);
294 294extern int txCommit(tid_t, int, struct inode **, int);
295extern tid_t txBegin(struct super_block *sb, int flag); 295extern tid_t txBegin(struct super_block *, int);
296 296extern void txBeginAnon(struct super_block *);
297extern void txBeginAnon(struct super_block *sb); 297extern void txEnd(tid_t);
298 298extern void txAbort(tid_t, int);
299extern void txEnd(tid_t tid); 299extern struct linelock *txLinelock(struct linelock *);
300 300extern void txFreeMap(struct inode *, struct maplock *, struct tblock *, int);
301extern void txAbort(tid_t tid, int dirty); 301extern void txEA(tid_t, struct inode *, dxd_t *, dxd_t *);
302 302extern void txFreelock(struct inode *);
303extern struct linelock *txLinelock(struct linelock * tlock); 303extern int lmLog(struct jfs_log *, struct tblock *, struct lrd *,
304 304 struct tlock *);
305extern void txFreeMap(struct inode *ip, struct maplock * maplock, 305extern void txQuiesce(struct super_block *);
306 struct tblock * tblk, int maptype); 306extern void txResume(struct super_block *);
307 307extern void txLazyUnlock(struct tblock *);
308extern void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea); 308extern int jfs_lazycommit(void *);
309 309extern int jfs_sync(void *);
310extern void txFreelock(struct inode *ip);
311
312extern int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
313 struct tlock * tlck);
314
315extern void txQuiesce(struct super_block *sb);
316
317extern void txResume(struct super_block *sb);
318#endif /* _H_JFS_TXNMGR */ 310#endif /* _H_JFS_TXNMGR */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 8413a368f449..1cae14e741eb 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -31,20 +31,9 @@
31#include "jfs_acl.h" 31#include "jfs_acl.h"
32#include "jfs_debug.h" 32#include "jfs_debug.h"
33 33
34extern struct inode_operations jfs_file_inode_operations;
35extern struct inode_operations jfs_symlink_inode_operations;
36extern struct file_operations jfs_file_operations;
37extern struct address_space_operations jfs_aops;
38
39extern int jfs_fsync(struct file *, struct dentry *, int);
40extern void jfs_truncate_nolock(struct inode *, loff_t);
41extern int jfs_init_acl(struct inode *, struct inode *);
42
43/* 34/*
44 * forward references 35 * forward references
45 */ 36 */
46struct inode_operations jfs_dir_inode_operations;
47struct file_operations jfs_dir_operations;
48struct dentry_operations jfs_ci_dentry_operations; 37struct dentry_operations jfs_ci_dentry_operations;
49 38
50static s64 commitZeroLink(tid_t, struct inode *); 39static s64 commitZeroLink(tid_t, struct inode *);
@@ -655,7 +644,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
655 644
656 645
657/* 646/*
658 * NAME: freeZeroLink() 647 * NAME: jfs_free_zero_link()
659 * 648 *
660 * FUNCTION: for non-directory, called by iClose(), 649 * FUNCTION: for non-directory, called by iClose(),
661 * free resources of a file from cache and WORKING map 650 * free resources of a file from cache and WORKING map
@@ -663,15 +652,12 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
663 * while associated with a pager object, 652 * while associated with a pager object,
664 * 653 *
665 * PARAMETER: ip - pointer to inode of file. 654 * PARAMETER: ip - pointer to inode of file.
666 *
667 * RETURN: 0 -ok
668 */ 655 */
669int freeZeroLink(struct inode *ip) 656void jfs_free_zero_link(struct inode *ip)
670{ 657{
671 int rc = 0;
672 int type; 658 int type;
673 659
674 jfs_info("freeZeroLink: ip = 0x%p", ip); 660 jfs_info("jfs_free_zero_link: ip = 0x%p", ip);
675 661
676 /* return if not reg or symbolic link or if size is 662 /* return if not reg or symbolic link or if size is
677 * already ok. 663 * already ok.
@@ -684,10 +670,10 @@ int freeZeroLink(struct inode *ip)
684 case S_IFLNK: 670 case S_IFLNK:
685 /* if its contained in inode nothing to do */ 671 /* if its contained in inode nothing to do */
686 if (ip->i_size < IDATASIZE) 672 if (ip->i_size < IDATASIZE)
687 return 0; 673 return;
688 break; 674 break;
689 default: 675 default:
690 return 0; 676 return;
691 } 677 }
692 678
693 /* 679 /*
@@ -737,9 +723,7 @@ int freeZeroLink(struct inode *ip)
737 * free xtree/data blocks from working block map; 723 * free xtree/data blocks from working block map;
738 */ 724 */
739 if (ip->i_size) 725 if (ip->i_size)
740 rc = xtTruncate(0, ip, 0, COMMIT_WMAP); 726 xtTruncate(0, ip, 0, COMMIT_WMAP);
741
742 return rc;
743} 727}
744 728
745/* 729/*
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 5e774ed7fb64..ee32211288ce 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -24,10 +24,12 @@
24#include <linux/completion.h> 24#include <linux/completion.h>
25#include <linux/vfs.h> 25#include <linux/vfs.h>
26#include <linux/moduleparam.h> 26#include <linux/moduleparam.h>
27#include <linux/posix_acl.h>
27#include <asm/uaccess.h> 28#include <asm/uaccess.h>
28 29
29#include "jfs_incore.h" 30#include "jfs_incore.h"
30#include "jfs_filsys.h" 31#include "jfs_filsys.h"
32#include "jfs_inode.h"
31#include "jfs_metapage.h" 33#include "jfs_metapage.h"
32#include "jfs_superblock.h" 34#include "jfs_superblock.h"
33#include "jfs_dmap.h" 35#include "jfs_dmap.h"
@@ -62,37 +64,6 @@ module_param(jfsloglevel, int, 0644);
62MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)"); 64MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
63#endif 65#endif
64 66
65/*
66 * External declarations
67 */
68extern int jfs_mount(struct super_block *);
69extern int jfs_mount_rw(struct super_block *, int);
70extern int jfs_umount(struct super_block *);
71extern int jfs_umount_rw(struct super_block *);
72
73extern int jfsIOWait(void *);
74extern int jfs_lazycommit(void *);
75extern int jfs_sync(void *);
76
77extern void jfs_read_inode(struct inode *inode);
78extern void jfs_dirty_inode(struct inode *inode);
79extern void jfs_delete_inode(struct inode *inode);
80extern int jfs_write_inode(struct inode *inode, int wait);
81
82extern struct dentry *jfs_get_parent(struct dentry *dentry);
83extern int jfs_extendfs(struct super_block *, s64, int);
84
85extern struct dentry_operations jfs_ci_dentry_operations;
86
87#ifdef PROC_FS_JFS /* see jfs_debug.h */
88extern void jfs_proc_init(void);
89extern void jfs_proc_clean(void);
90#endif
91
92extern wait_queue_head_t jfs_IO_thread_wait;
93extern wait_queue_head_t jfs_commit_thread_wait;
94extern wait_queue_head_t jfs_sync_thread_wait;
95
96static void jfs_handle_error(struct super_block *sb) 67static void jfs_handle_error(struct super_block *sb)
97{ 68{
98 struct jfs_sb_info *sbi = JFS_SBI(sb); 69 struct jfs_sb_info *sbi = JFS_SBI(sb);
@@ -593,11 +564,6 @@ static struct file_system_type jfs_fs_type = {
593 .fs_flags = FS_REQUIRES_DEV, 564 .fs_flags = FS_REQUIRES_DEV,
594}; 565};
595 566
596extern int metapage_init(void);
597extern int txInit(void);
598extern void txExit(void);
599extern void metapage_exit(void);
600
601static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) 567static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
602{ 568{
603 struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; 569 struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index ef4c07ee92b2..287d8d6c3cfd 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) Christoph Hellwig, 2001-2002 2 * Copyright (C) Christoph Hellwig, 2001-2002
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include "jfs_incore.h" 21#include "jfs_incore.h"
22#include "jfs_inode.h"
22#include "jfs_xattr.h" 23#include "jfs_xattr.h"
23 24
24static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd) 25static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 7a9ffd5d03dc..ee438d429d45 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/xattr.h> 21#include <linux/xattr.h>
22#include <linux/posix_acl_xattr.h>
22#include <linux/quotaops.h> 23#include <linux/quotaops.h>
23#include "jfs_incore.h" 24#include "jfs_incore.h"
24#include "jfs_superblock.h" 25#include "jfs_superblock.h"
@@ -718,9 +719,9 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
718 return -EPERM; 719 return -EPERM;
719 720
720 /* 721 /*
721 * XATTR_NAME_ACL_ACCESS is tied to i_mode 722 * POSIX_ACL_XATTR_ACCESS is tied to i_mode
722 */ 723 */
723 if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) { 724 if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
724 acl = posix_acl_from_xattr(value, value_len); 725 acl = posix_acl_from_xattr(value, value_len);
725 if (IS_ERR(acl)) { 726 if (IS_ERR(acl)) {
726 rc = PTR_ERR(acl); 727 rc = PTR_ERR(acl);
@@ -750,7 +751,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
750 JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED; 751 JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED;
751 752
752 return 0; 753 return 0;
753 } else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) { 754 } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
754 acl = posix_acl_from_xattr(value, value_len); 755 acl = posix_acl_from_xattr(value, value_len);
755 if (IS_ERR(acl)) { 756 if (IS_ERR(acl)) {
756 rc = PTR_ERR(acl); 757 rc = PTR_ERR(acl);
@@ -946,8 +947,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
946 out: 947 out:
947 up_write(&JFS_IP(inode)->xattr_sem); 948 up_write(&JFS_IP(inode)->xattr_sem);
948 949
949 if (os2name) 950 kfree(os2name);
950 kfree(os2name);
951 951
952 return rc; 952 return rc;
953} 953}
@@ -1042,8 +1042,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
1042 out: 1042 out:
1043 up_read(&JFS_IP(inode)->xattr_sem); 1043 up_read(&JFS_IP(inode)->xattr_sem);
1044 1044
1045 if (os2name) 1045 kfree(os2name);
1046 kfree(os2name);
1047 1046
1048 return size; 1047 return size;
1049} 1048}
diff --git a/fs/libfs.c b/fs/libfs.c
index f90b29595927..58101dff2c66 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -183,6 +183,7 @@ struct file_operations simple_dir_operations = {
183 .llseek = dcache_dir_lseek, 183 .llseek = dcache_dir_lseek,
184 .read = generic_read_dir, 184 .read = generic_read_dir,
185 .readdir = dcache_readdir, 185 .readdir = dcache_readdir,
186 .fsync = simple_sync_file,
186}; 187};
187 188
188struct inode_operations simple_dir_inode_operations = { 189struct inode_operations simple_dir_inode_operations = {
@@ -519,6 +520,102 @@ int simple_transaction_release(struct inode *inode, struct file *file)
519 return 0; 520 return 0;
520} 521}
521 522
523/* Simple attribute files */
524
525struct simple_attr {
526 u64 (*get)(void *);
527 void (*set)(void *, u64);
528 char get_buf[24]; /* enough to store a u64 and "\n\0" */
529 char set_buf[24];
530 void *data;
531 const char *fmt; /* format for read operation */
532 struct semaphore sem; /* protects access to these buffers */
533};
534
535/* simple_attr_open is called by an actual attribute open file operation
536 * to set the attribute specific access operations. */
537int simple_attr_open(struct inode *inode, struct file *file,
538 u64 (*get)(void *), void (*set)(void *, u64),
539 const char *fmt)
540{
541 struct simple_attr *attr;
542
543 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
544 if (!attr)
545 return -ENOMEM;
546
547 attr->get = get;
548 attr->set = set;
549 attr->data = inode->u.generic_ip;
550 attr->fmt = fmt;
551 init_MUTEX(&attr->sem);
552
553 file->private_data = attr;
554
555 return nonseekable_open(inode, file);
556}
557
558int simple_attr_close(struct inode *inode, struct file *file)
559{
560 kfree(file->private_data);
561 return 0;
562}
563
564/* read from the buffer that is filled with the get function */
565ssize_t simple_attr_read(struct file *file, char __user *buf,
566 size_t len, loff_t *ppos)
567{
568 struct simple_attr *attr;
569 size_t size;
570 ssize_t ret;
571
572 attr = file->private_data;
573
574 if (!attr->get)
575 return -EACCES;
576
577 down(&attr->sem);
578 if (*ppos) /* continued read */
579 size = strlen(attr->get_buf);
580 else /* first read */
581 size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
582 attr->fmt,
583 (unsigned long long)attr->get(attr->data));
584
585 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
586 up(&attr->sem);
587 return ret;
588}
589
590/* interpret the buffer as a number to call the set function with */
591ssize_t simple_attr_write(struct file *file, const char __user *buf,
592 size_t len, loff_t *ppos)
593{
594 struct simple_attr *attr;
595 u64 val;
596 size_t size;
597 ssize_t ret;
598
599 attr = file->private_data;
600
601 if (!attr->set)
602 return -EACCES;
603
604 down(&attr->sem);
605 ret = -EFAULT;
606 size = min(sizeof(attr->set_buf) - 1, len);
607 if (copy_from_user(attr->set_buf, buf, size))
608 goto out;
609
610 ret = len; /* claim we got the whole input */
611 attr->set_buf[size] = '\0';
612 val = simple_strtol(attr->set_buf, NULL, 0);
613 attr->set(attr->data, val);
614out:
615 up(&attr->sem);
616 return ret;
617}
618
522EXPORT_SYMBOL(dcache_dir_close); 619EXPORT_SYMBOL(dcache_dir_close);
523EXPORT_SYMBOL(dcache_dir_lseek); 620EXPORT_SYMBOL(dcache_dir_lseek);
524EXPORT_SYMBOL(dcache_dir_open); 621EXPORT_SYMBOL(dcache_dir_open);
@@ -547,3 +644,7 @@ EXPORT_SYMBOL(simple_read_from_buffer);
547EXPORT_SYMBOL(simple_transaction_get); 644EXPORT_SYMBOL(simple_transaction_get);
548EXPORT_SYMBOL(simple_transaction_read); 645EXPORT_SYMBOL(simple_transaction_read);
549EXPORT_SYMBOL(simple_transaction_release); 646EXPORT_SYMBOL(simple_transaction_release);
647EXPORT_SYMBOL_GPL(simple_attr_open);
648EXPORT_SYMBOL_GPL(simple_attr_close);
649EXPORT_SYMBOL_GPL(simple_attr_read);
650EXPORT_SYMBOL_GPL(simple_attr_write);
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index ef7103b8c5bd..006bb9e14579 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -31,7 +31,7 @@ static int reclaimer(void *ptr);
31 * This is the representation of a blocked client lock. 31 * This is the representation of a blocked client lock.
32 */ 32 */
33struct nlm_wait { 33struct nlm_wait {
34 struct nlm_wait * b_next; /* linked list */ 34 struct list_head b_list; /* linked list */
35 wait_queue_head_t b_wait; /* where to wait on */ 35 wait_queue_head_t b_wait; /* where to wait on */
36 struct nlm_host * b_host; 36 struct nlm_host * b_host;
37 struct file_lock * b_lock; /* local file lock */ 37 struct file_lock * b_lock; /* local file lock */
@@ -39,27 +39,54 @@ struct nlm_wait {
39 u32 b_status; /* grant callback status */ 39 u32 b_status; /* grant callback status */
40}; 40};
41 41
42static struct nlm_wait * nlm_blocked; 42static LIST_HEAD(nlm_blocked);
43 43
44/* 44/*
45 * Block on a lock 45 * Queue up a lock for blocking so that the GRANTED request can see it
46 */ 46 */
47int 47int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl)
48nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp) 48{
49 struct nlm_wait *block;
50
51 BUG_ON(req->a_block != NULL);
52 block = kmalloc(sizeof(*block), GFP_KERNEL);
53 if (block == NULL)
54 return -ENOMEM;
55 block->b_host = host;
56 block->b_lock = fl;
57 init_waitqueue_head(&block->b_wait);
58 block->b_status = NLM_LCK_BLOCKED;
59
60 list_add(&block->b_list, &nlm_blocked);
61 req->a_block = block;
62
63 return 0;
64}
65
66void nlmclnt_finish_block(struct nlm_rqst *req)
49{ 67{
50 struct nlm_wait block, **head; 68 struct nlm_wait *block = req->a_block;
51 int err;
52 u32 pstate;
53 69
54 block.b_host = host; 70 if (block == NULL)
55 block.b_lock = fl; 71 return;
56 init_waitqueue_head(&block.b_wait); 72 req->a_block = NULL;
57 block.b_status = NLM_LCK_BLOCKED; 73 list_del(&block->b_list);
58 block.b_next = nlm_blocked; 74 kfree(block);
59 nlm_blocked = &block; 75}
76
77/*
78 * Block on a lock
79 */
80long nlmclnt_block(struct nlm_rqst *req, long timeout)
81{
82 struct nlm_wait *block = req->a_block;
83 long ret;
60 84
61 /* Remember pseudo nsm state */ 85 /* A borken server might ask us to block even if we didn't
62 pstate = host->h_state; 86 * request it. Just say no!
87 */
88 if (!req->a_args.block)
89 return -EAGAIN;
63 90
64 /* Go to sleep waiting for GRANT callback. Some servers seem 91 /* Go to sleep waiting for GRANT callback. Some servers seem
65 * to lose callbacks, however, so we're going to poll from 92 * to lose callbacks, however, so we're going to poll from
@@ -69,28 +96,16 @@ nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp)
69 * a 1 minute timeout would do. See the comment before 96 * a 1 minute timeout would do. See the comment before
70 * nlmclnt_lock for an explanation. 97 * nlmclnt_lock for an explanation.
71 */ 98 */
72 sleep_on_timeout(&block.b_wait, 30*HZ); 99 ret = wait_event_interruptible_timeout(block->b_wait,
73 100 block->b_status != NLM_LCK_BLOCKED,
74 for (head = &nlm_blocked; *head; head = &(*head)->b_next) { 101 timeout);
75 if (*head == &block) {
76 *head = block.b_next;
77 break;
78 }
79 }
80 102
81 if (!signalled()) { 103 if (block->b_status != NLM_LCK_BLOCKED) {
82 *statp = block.b_status; 104 req->a_res.status = block->b_status;
83 return 0; 105 block->b_status = NLM_LCK_BLOCKED;
84 } 106 }
85 107
86 /* Okay, we were interrupted. Cancel the pending request 108 return ret;
87 * unless the server has rebooted.
88 */
89 if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0)
90 printk(KERN_NOTICE
91 "lockd: CANCEL call failed (errno %d)\n", -err);
92
93 return -ERESTARTSYS;
94} 109}
95 110
96/* 111/*
@@ -100,27 +115,23 @@ u32
100nlmclnt_grant(struct nlm_lock *lock) 115nlmclnt_grant(struct nlm_lock *lock)
101{ 116{
102 struct nlm_wait *block; 117 struct nlm_wait *block;
118 u32 res = nlm_lck_denied;
103 119
104 /* 120 /*
105 * Look up blocked request based on arguments. 121 * Look up blocked request based on arguments.
106 * Warning: must not use cookie to match it! 122 * Warning: must not use cookie to match it!
107 */ 123 */
108 for (block = nlm_blocked; block; block = block->b_next) { 124 list_for_each_entry(block, &nlm_blocked, b_list) {
109 if (nlm_compare_locks(block->b_lock, &lock->fl)) 125 if (nlm_compare_locks(block->b_lock, &lock->fl)) {
110 break; 126 /* Alright, we found a lock. Set the return status
127 * and wake up the caller
128 */
129 block->b_status = NLM_LCK_GRANTED;
130 wake_up(&block->b_wait);
131 res = nlm_granted;
132 }
111 } 133 }
112 134 return res;
113 /* Ooops, no blocked request found. */
114 if (block == NULL)
115 return nlm_lck_denied;
116
117 /* Alright, we found the lock. Set the return status and
118 * wake up the caller.
119 */
120 block->b_status = NLM_LCK_GRANTED;
121 wake_up(&block->b_wait);
122
123 return nlm_granted;
124} 135}
125 136
126/* 137/*
@@ -230,7 +241,7 @@ restart:
230 host->h_reclaiming = 0; 241 host->h_reclaiming = 0;
231 242
232 /* Now, wake up all processes that sleep on a blocked lock */ 243 /* Now, wake up all processes that sleep on a blocked lock */
233 for (block = nlm_blocked; block; block = block->b_next) { 244 list_for_each_entry(block, &nlm_blocked, b_list) {
234 if (block->b_host == host) { 245 if (block->b_host == host) {
235 block->b_status = NLM_LCK_DENIED_GRACE_PERIOD; 246 block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
236 wake_up(&block->b_wait); 247 wake_up(&block->b_wait);
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index a4407619b1f1..14b3ce87fa29 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -21,6 +21,7 @@
21 21
22#define NLMDBG_FACILITY NLMDBG_CLIENT 22#define NLMDBG_FACILITY NLMDBG_CLIENT
23#define NLMCLNT_GRACE_WAIT (5*HZ) 23#define NLMCLNT_GRACE_WAIT (5*HZ)
24#define NLMCLNT_POLL_TIMEOUT (30*HZ)
24 25
25static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); 26static int nlmclnt_test(struct nlm_rqst *, struct file_lock *);
26static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); 27static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
@@ -312,7 +313,7 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
312 prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE); 313 prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE);
313 if (!signalled ()) { 314 if (!signalled ()) {
314 schedule_timeout(NLMCLNT_GRACE_WAIT); 315 schedule_timeout(NLMCLNT_GRACE_WAIT);
315 try_to_freeze(PF_FREEZE); 316 try_to_freeze();
316 if (!signalled ()) 317 if (!signalled ())
317 status = 0; 318 status = 0;
318 } 319 }
@@ -553,7 +554,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
553{ 554{
554 struct nlm_host *host = req->a_host; 555 struct nlm_host *host = req->a_host;
555 struct nlm_res *resp = &req->a_res; 556 struct nlm_res *resp = &req->a_res;
556 int status; 557 long timeout;
558 int status;
557 559
558 if (!host->h_monitored && nsm_monitor(host) < 0) { 560 if (!host->h_monitored && nsm_monitor(host) < 0) {
559 printk(KERN_NOTICE "lockd: failed to monitor %s\n", 561 printk(KERN_NOTICE "lockd: failed to monitor %s\n",
@@ -562,15 +564,32 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
562 goto out; 564 goto out;
563 } 565 }
564 566
565 do { 567 if (req->a_args.block) {
566 if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) { 568 status = nlmclnt_prepare_block(req, host, fl);
567 if (resp->status != NLM_LCK_BLOCKED)
568 break;
569 status = nlmclnt_block(host, fl, &resp->status);
570 }
571 if (status < 0) 569 if (status < 0)
572 goto out; 570 goto out;
573 } while (resp->status == NLM_LCK_BLOCKED && req->a_args.block); 571 }
572 for(;;) {
573 status = nlmclnt_call(req, NLMPROC_LOCK);
574 if (status < 0)
575 goto out_unblock;
576 if (resp->status != NLM_LCK_BLOCKED)
577 break;
578 /* Wait on an NLM blocking lock */
579 timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT);
580 /* Did a reclaimer thread notify us of a server reboot? */
581 if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD)
582 continue;
583 if (resp->status != NLM_LCK_BLOCKED)
584 break;
585 if (timeout >= 0)
586 continue;
587 /* We were interrupted. Send a CANCEL request to the server
588 * and exit
589 */
590 status = (int)timeout;
591 goto out_unblock;
592 }
574 593
575 if (resp->status == NLM_LCK_GRANTED) { 594 if (resp->status == NLM_LCK_GRANTED) {
576 fl->fl_u.nfs_fl.state = host->h_state; 595 fl->fl_u.nfs_fl.state = host->h_state;
@@ -579,6 +598,11 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
579 do_vfs_lock(fl); 598 do_vfs_lock(fl);
580 } 599 }
581 status = nlm_stat_to_errno(resp->status); 600 status = nlm_stat_to_errno(resp->status);
601out_unblock:
602 nlmclnt_finish_block(req);
603 /* Cancel the blocked request if it is still pending */
604 if (resp->status == NLM_LCK_BLOCKED)
605 nlmclnt_cancel(host, fl);
582out: 606out:
583 nlmclnt_release_lockargs(req); 607 nlmclnt_release_lockargs(req);
584 return status; 608 return status;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 52707c5ad6ea..82c77df81c5f 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -189,17 +189,15 @@ nlm_bind_host(struct nlm_host *host)
189 goto forgetit; 189 goto forgetit;
190 190
191 xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); 191 xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
192 xprt->nocong = 1; /* No congestion control for NLM */
193 xprt->resvport = 1; /* NLM requires a reserved port */
192 194
193 /* Existing NLM servers accept AUTH_UNIX only */ 195 /* Existing NLM servers accept AUTH_UNIX only */
194 clnt = rpc_create_client(xprt, host->h_name, &nlm_program, 196 clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
195 host->h_version, RPC_AUTH_UNIX); 197 host->h_version, RPC_AUTH_UNIX);
196 if (IS_ERR(clnt)) { 198 if (IS_ERR(clnt))
197 xprt_destroy(xprt);
198 goto forgetit; 199 goto forgetit;
199 }
200 clnt->cl_autobind = 1; /* turn on pmap queries */ 200 clnt->cl_autobind = 1; /* turn on pmap queries */
201 xprt->nocong = 1; /* No congestion control for NLM */
202 xprt->resvport = 1; /* NLM requires a reserved port */
203 201
204 host->h_rpcclnt = clnt; 202 host->h_rpcclnt = clnt;
205 } 203 }
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 6fc1bebeec1d..2d144abe84ad 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -115,20 +115,19 @@ nsm_create(void)
115 xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); 115 xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL);
116 if (IS_ERR(xprt)) 116 if (IS_ERR(xprt))
117 return (struct rpc_clnt *)xprt; 117 return (struct rpc_clnt *)xprt;
118 xprt->resvport = 1; /* NSM requires a reserved port */
118 119
119 clnt = rpc_create_client(xprt, "localhost", 120 clnt = rpc_create_client(xprt, "localhost",
120 &nsm_program, SM_VERSION, 121 &nsm_program, SM_VERSION,
121 RPC_AUTH_NULL); 122 RPC_AUTH_NULL);
122 if (IS_ERR(clnt)) 123 if (IS_ERR(clnt))
123 goto out_destroy; 124 goto out_err;
124 clnt->cl_softrtry = 1; 125 clnt->cl_softrtry = 1;
125 clnt->cl_chatty = 1; 126 clnt->cl_chatty = 1;
126 clnt->cl_oneshot = 1; 127 clnt->cl_oneshot = 1;
127 xprt->resvport = 1; /* NSM requires a reserved port */
128 return clnt; 128 return clnt;
129 129
130out_destroy: 130out_err:
131 xprt_destroy(xprt);
132 return clnt; 131 return clnt;
133} 132}
134 133
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index b82e470912e8..6e242556b903 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -191,7 +191,9 @@ lockd(struct svc_rqst *rqstp)
191 printk(KERN_DEBUG 191 printk(KERN_DEBUG
192 "lockd: new process, skipping host shutdown\n"); 192 "lockd: new process, skipping host shutdown\n");
193 wake_up(&lockd_exit); 193 wake_up(&lockd_exit);
194 194
195 flush_signals(current);
196
195 /* Exit the RPC thread */ 197 /* Exit the RPC thread */
196 svc_exit_thread(rqstp); 198 svc_exit_thread(rqstp);
197 199
diff --git a/fs/locks.c b/fs/locks.c
index 3fa6a7ce57a7..a0bc03495bd4 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1548,6 +1548,8 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
1548 1548
1549 if (filp->f_op && filp->f_op->lock) { 1549 if (filp->f_op && filp->f_op->lock) {
1550 error = filp->f_op->lock(filp, F_GETLK, &file_lock); 1550 error = filp->f_op->lock(filp, F_GETLK, &file_lock);
1551 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
1552 file_lock.fl_ops->fl_release_private(&file_lock);
1551 if (error < 0) 1553 if (error < 0)
1552 goto out; 1554 goto out;
1553 else 1555 else
@@ -1690,6 +1692,8 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
1690 1692
1691 if (filp->f_op && filp->f_op->lock) { 1693 if (filp->f_op && filp->f_op->lock) {
1692 error = filp->f_op->lock(filp, F_GETLK, &file_lock); 1694 error = filp->f_op->lock(filp, F_GETLK, &file_lock);
1695 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
1696 file_lock.fl_ops->fl_release_private(&file_lock);
1693 if (error < 0) 1697 if (error < 0)
1694 goto out; 1698 goto out;
1695 else 1699 else
@@ -1873,6 +1877,8 @@ void locks_remove_flock(struct file *filp)
1873 .fl_end = OFFSET_MAX, 1877 .fl_end = OFFSET_MAX,
1874 }; 1878 };
1875 filp->f_op->flock(filp, F_SETLKW, &fl); 1879 filp->f_op->flock(filp, F_SETLKW, &fl);
1880 if (fl.fl_ops && fl.fl_ops->fl_release_private)
1881 fl.fl_ops->fl_release_private(&fl);
1876 } 1882 }
1877 1883
1878 lock_kernel(); 1884 lock_kernel();
diff --git a/fs/mpage.c b/fs/mpage.c
index b92c0e64aefa..bb9aebe93862 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -79,8 +79,11 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err)
79 if (--bvec >= bio->bi_io_vec) 79 if (--bvec >= bio->bi_io_vec)
80 prefetchw(&bvec->bv_page->flags); 80 prefetchw(&bvec->bv_page->flags);
81 81
82 if (!uptodate) 82 if (!uptodate){
83 SetPageError(page); 83 SetPageError(page);
84 if (page->mapping)
85 set_bit(AS_EIO, &page->mapping->flags);
86 }
84 end_page_writeback(page); 87 end_page_writeback(page);
85 } while (bvec >= bio->bi_io_vec); 88 } while (bvec >= bio->bi_io_vec);
86 bio_put(bio); 89 bio_put(bio);
diff --git a/fs/namei.c b/fs/namei.c
index dd78f01b6de8..fa8df81ce8ca 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -493,12 +493,21 @@ fail:
493 return PTR_ERR(link); 493 return PTR_ERR(link);
494} 494}
495 495
496static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) 496struct path {
497 struct vfsmount *mnt;
498 struct dentry *dentry;
499};
500
501static inline int __do_follow_link(struct path *path, struct nameidata *nd)
497{ 502{
498 int error; 503 int error;
504 struct dentry *dentry = path->dentry;
499 505
500 touch_atime(nd->mnt, dentry); 506 touch_atime(path->mnt, dentry);
501 nd_set_link(nd, NULL); 507 nd_set_link(nd, NULL);
508
509 if (path->mnt == nd->mnt)
510 mntget(path->mnt);
502 error = dentry->d_inode->i_op->follow_link(dentry, nd); 511 error = dentry->d_inode->i_op->follow_link(dentry, nd);
503 if (!error) { 512 if (!error) {
504 char *s = nd_get_link(nd); 513 char *s = nd_get_link(nd);
@@ -507,6 +516,8 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
507 if (dentry->d_inode->i_op->put_link) 516 if (dentry->d_inode->i_op->put_link)
508 dentry->d_inode->i_op->put_link(dentry, nd); 517 dentry->d_inode->i_op->put_link(dentry, nd);
509 } 518 }
519 dput(dentry);
520 mntput(path->mnt);
510 521
511 return error; 522 return error;
512} 523}
@@ -518,7 +529,7 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
518 * Without that kind of total limit, nasty chains of consecutive 529 * Without that kind of total limit, nasty chains of consecutive
519 * symlinks can cause almost arbitrarily long lookups. 530 * symlinks can cause almost arbitrarily long lookups.
520 */ 531 */
521static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) 532static inline int do_follow_link(struct path *path, struct nameidata *nd)
522{ 533{
523 int err = -ELOOP; 534 int err = -ELOOP;
524 if (current->link_count >= MAX_NESTED_LINKS) 535 if (current->link_count >= MAX_NESTED_LINKS)
@@ -527,17 +538,20 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
527 goto loop; 538 goto loop;
528 BUG_ON(nd->depth >= MAX_NESTED_LINKS); 539 BUG_ON(nd->depth >= MAX_NESTED_LINKS);
529 cond_resched(); 540 cond_resched();
530 err = security_inode_follow_link(dentry, nd); 541 err = security_inode_follow_link(path->dentry, nd);
531 if (err) 542 if (err)
532 goto loop; 543 goto loop;
533 current->link_count++; 544 current->link_count++;
534 current->total_link_count++; 545 current->total_link_count++;
535 nd->depth++; 546 nd->depth++;
536 err = __do_follow_link(dentry, nd); 547 err = __do_follow_link(path, nd);
537 current->link_count--; 548 current->link_count--;
538 nd->depth--; 549 nd->depth--;
539 return err; 550 return err;
540loop: 551loop:
552 dput(path->dentry);
553 if (path->mnt != nd->mnt)
554 mntput(path->mnt);
541 path_release(nd); 555 path_release(nd);
542 return err; 556 return err;
543} 557}
@@ -565,87 +579,91 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry)
565/* no need for dcache_lock, as serialization is taken care in 579/* no need for dcache_lock, as serialization is taken care in
566 * namespace.c 580 * namespace.c
567 */ 581 */
568static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) 582static int __follow_mount(struct path *path)
569{ 583{
570 int res = 0; 584 int res = 0;
585 while (d_mountpoint(path->dentry)) {
586 struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry);
587 if (!mounted)
588 break;
589 dput(path->dentry);
590 if (res)
591 mntput(path->mnt);
592 path->mnt = mounted;
593 path->dentry = dget(mounted->mnt_root);
594 res = 1;
595 }
596 return res;
597}
598
599static void follow_mount(struct vfsmount **mnt, struct dentry **dentry)
600{
571 while (d_mountpoint(*dentry)) { 601 while (d_mountpoint(*dentry)) {
572 struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); 602 struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
573 if (!mounted) 603 if (!mounted)
574 break; 604 break;
605 dput(*dentry);
575 mntput(*mnt); 606 mntput(*mnt);
576 *mnt = mounted; 607 *mnt = mounted;
577 dput(*dentry);
578 *dentry = dget(mounted->mnt_root); 608 *dentry = dget(mounted->mnt_root);
579 res = 1;
580 } 609 }
581 return res;
582} 610}
583 611
584/* no need for dcache_lock, as serialization is taken care in 612/* no need for dcache_lock, as serialization is taken care in
585 * namespace.c 613 * namespace.c
586 */ 614 */
587static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) 615int follow_down(struct vfsmount **mnt, struct dentry **dentry)
588{ 616{
589 struct vfsmount *mounted; 617 struct vfsmount *mounted;
590 618
591 mounted = lookup_mnt(*mnt, *dentry); 619 mounted = lookup_mnt(*mnt, *dentry);
592 if (mounted) { 620 if (mounted) {
621 dput(*dentry);
593 mntput(*mnt); 622 mntput(*mnt);
594 *mnt = mounted; 623 *mnt = mounted;
595 dput(*dentry);
596 *dentry = dget(mounted->mnt_root); 624 *dentry = dget(mounted->mnt_root);
597 return 1; 625 return 1;
598 } 626 }
599 return 0; 627 return 0;
600} 628}
601 629
602int follow_down(struct vfsmount **mnt, struct dentry **dentry) 630static inline void follow_dotdot(struct nameidata *nd)
603{
604 return __follow_down(mnt,dentry);
605}
606
607static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
608{ 631{
609 while(1) { 632 while(1) {
610 struct vfsmount *parent; 633 struct vfsmount *parent;
611 struct dentry *old = *dentry; 634 struct dentry *old = nd->dentry;
612 635
613 read_lock(&current->fs->lock); 636 read_lock(&current->fs->lock);
614 if (*dentry == current->fs->root && 637 if (nd->dentry == current->fs->root &&
615 *mnt == current->fs->rootmnt) { 638 nd->mnt == current->fs->rootmnt) {
616 read_unlock(&current->fs->lock); 639 read_unlock(&current->fs->lock);
617 break; 640 break;
618 } 641 }
619 read_unlock(&current->fs->lock); 642 read_unlock(&current->fs->lock);
620 spin_lock(&dcache_lock); 643 spin_lock(&dcache_lock);
621 if (*dentry != (*mnt)->mnt_root) { 644 if (nd->dentry != nd->mnt->mnt_root) {
622 *dentry = dget((*dentry)->d_parent); 645 nd->dentry = dget(nd->dentry->d_parent);
623 spin_unlock(&dcache_lock); 646 spin_unlock(&dcache_lock);
624 dput(old); 647 dput(old);
625 break; 648 break;
626 } 649 }
627 spin_unlock(&dcache_lock); 650 spin_unlock(&dcache_lock);
628 spin_lock(&vfsmount_lock); 651 spin_lock(&vfsmount_lock);
629 parent = (*mnt)->mnt_parent; 652 parent = nd->mnt->mnt_parent;
630 if (parent == *mnt) { 653 if (parent == nd->mnt) {
631 spin_unlock(&vfsmount_lock); 654 spin_unlock(&vfsmount_lock);
632 break; 655 break;
633 } 656 }
634 mntget(parent); 657 mntget(parent);
635 *dentry = dget((*mnt)->mnt_mountpoint); 658 nd->dentry = dget(nd->mnt->mnt_mountpoint);
636 spin_unlock(&vfsmount_lock); 659 spin_unlock(&vfsmount_lock);
637 dput(old); 660 dput(old);
638 mntput(*mnt); 661 mntput(nd->mnt);
639 *mnt = parent; 662 nd->mnt = parent;
640 } 663 }
641 follow_mount(mnt, dentry); 664 follow_mount(&nd->mnt, &nd->dentry);
642} 665}
643 666
644struct path {
645 struct vfsmount *mnt;
646 struct dentry *dentry;
647};
648
649/* 667/*
650 * It's more convoluted than I'd like it to be, but... it's still fairly 668 * It's more convoluted than I'd like it to be, but... it's still fairly
651 * small and for now I'd prefer to have fast path as straight as possible. 669 * small and for now I'd prefer to have fast path as straight as possible.
@@ -664,6 +682,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
664done: 682done:
665 path->mnt = mnt; 683 path->mnt = mnt;
666 path->dentry = dentry; 684 path->dentry = dentry;
685 __follow_mount(path);
667 return 0; 686 return 0;
668 687
669need_lookup: 688need_lookup:
@@ -751,7 +770,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
751 case 2: 770 case 2:
752 if (this.name[1] != '.') 771 if (this.name[1] != '.')
753 break; 772 break;
754 follow_dotdot(&nd->mnt, &nd->dentry); 773 follow_dotdot(nd);
755 inode = nd->dentry->d_inode; 774 inode = nd->dentry->d_inode;
756 /* fallthrough */ 775 /* fallthrough */
757 case 1: 776 case 1:
@@ -771,8 +790,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
771 err = do_lookup(nd, &this, &next); 790 err = do_lookup(nd, &this, &next);
772 if (err) 791 if (err)
773 break; 792 break;
774 /* Check mountpoints.. */
775 follow_mount(&next.mnt, &next.dentry);
776 793
777 err = -ENOENT; 794 err = -ENOENT;
778 inode = next.dentry->d_inode; 795 inode = next.dentry->d_inode;
@@ -783,10 +800,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
783 goto out_dput; 800 goto out_dput;
784 801
785 if (inode->i_op->follow_link) { 802 if (inode->i_op->follow_link) {
786 mntget(next.mnt); 803 err = do_follow_link(&next, nd);
787 err = do_follow_link(next.dentry, nd);
788 dput(next.dentry);
789 mntput(next.mnt);
790 if (err) 804 if (err)
791 goto return_err; 805 goto return_err;
792 err = -ENOENT; 806 err = -ENOENT;
@@ -798,6 +812,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
798 break; 812 break;
799 } else { 813 } else {
800 dput(nd->dentry); 814 dput(nd->dentry);
815 if (nd->mnt != next.mnt)
816 mntput(nd->mnt);
801 nd->mnt = next.mnt; 817 nd->mnt = next.mnt;
802 nd->dentry = next.dentry; 818 nd->dentry = next.dentry;
803 } 819 }
@@ -819,7 +835,7 @@ last_component:
819 case 2: 835 case 2:
820 if (this.name[1] != '.') 836 if (this.name[1] != '.')
821 break; 837 break;
822 follow_dotdot(&nd->mnt, &nd->dentry); 838 follow_dotdot(nd);
823 inode = nd->dentry->d_inode; 839 inode = nd->dentry->d_inode;
824 /* fallthrough */ 840 /* fallthrough */
825 case 1: 841 case 1:
@@ -833,19 +849,17 @@ last_component:
833 err = do_lookup(nd, &this, &next); 849 err = do_lookup(nd, &this, &next);
834 if (err) 850 if (err)
835 break; 851 break;
836 follow_mount(&next.mnt, &next.dentry);
837 inode = next.dentry->d_inode; 852 inode = next.dentry->d_inode;
838 if ((lookup_flags & LOOKUP_FOLLOW) 853 if ((lookup_flags & LOOKUP_FOLLOW)
839 && inode && inode->i_op && inode->i_op->follow_link) { 854 && inode && inode->i_op && inode->i_op->follow_link) {
840 mntget(next.mnt); 855 err = do_follow_link(&next, nd);
841 err = do_follow_link(next.dentry, nd);
842 dput(next.dentry);
843 mntput(next.mnt);
844 if (err) 856 if (err)
845 goto return_err; 857 goto return_err;
846 inode = nd->dentry->d_inode; 858 inode = nd->dentry->d_inode;
847 } else { 859 } else {
848 dput(nd->dentry); 860 dput(nd->dentry);
861 if (nd->mnt != next.mnt)
862 mntput(nd->mnt);
849 nd->mnt = next.mnt; 863 nd->mnt = next.mnt;
850 nd->dentry = next.dentry; 864 nd->dentry = next.dentry;
851 } 865 }
@@ -885,6 +899,8 @@ return_base:
885 return 0; 899 return 0;
886out_dput: 900out_dput:
887 dput(next.dentry); 901 dput(next.dentry);
902 if (nd->mnt != next.mnt)
903 mntput(next.mnt);
888 break; 904 break;
889 } 905 }
890 path_release(nd); 906 path_release(nd);
@@ -1398,7 +1414,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
1398int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) 1414int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1399{ 1415{
1400 int acc_mode, error = 0; 1416 int acc_mode, error = 0;
1401 struct dentry *dentry; 1417 struct path path;
1402 struct dentry *dir; 1418 struct dentry *dir;
1403 int count = 0; 1419 int count = 0;
1404 1420
@@ -1442,23 +1458,24 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1442 dir = nd->dentry; 1458 dir = nd->dentry;
1443 nd->flags &= ~LOOKUP_PARENT; 1459 nd->flags &= ~LOOKUP_PARENT;
1444 down(&dir->d_inode->i_sem); 1460 down(&dir->d_inode->i_sem);
1445 dentry = __lookup_hash(&nd->last, nd->dentry, nd); 1461 path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
1462 path.mnt = nd->mnt;
1446 1463
1447do_last: 1464do_last:
1448 error = PTR_ERR(dentry); 1465 error = PTR_ERR(path.dentry);
1449 if (IS_ERR(dentry)) { 1466 if (IS_ERR(path.dentry)) {
1450 up(&dir->d_inode->i_sem); 1467 up(&dir->d_inode->i_sem);
1451 goto exit; 1468 goto exit;
1452 } 1469 }
1453 1470
1454 /* Negative dentry, just create the file */ 1471 /* Negative dentry, just create the file */
1455 if (!dentry->d_inode) { 1472 if (!path.dentry->d_inode) {
1456 if (!IS_POSIXACL(dir->d_inode)) 1473 if (!IS_POSIXACL(dir->d_inode))
1457 mode &= ~current->fs->umask; 1474 mode &= ~current->fs->umask;
1458 error = vfs_create(dir->d_inode, dentry, mode, nd); 1475 error = vfs_create(dir->d_inode, path.dentry, mode, nd);
1459 up(&dir->d_inode->i_sem); 1476 up(&dir->d_inode->i_sem);
1460 dput(nd->dentry); 1477 dput(nd->dentry);
1461 nd->dentry = dentry; 1478 nd->dentry = path.dentry;
1462 if (error) 1479 if (error)
1463 goto exit; 1480 goto exit;
1464 /* Don't check for write permission, don't truncate */ 1481 /* Don't check for write permission, don't truncate */
@@ -1476,22 +1493,24 @@ do_last:
1476 if (flag & O_EXCL) 1493 if (flag & O_EXCL)
1477 goto exit_dput; 1494 goto exit_dput;
1478 1495
1479 if (d_mountpoint(dentry)) { 1496 if (__follow_mount(&path)) {
1480 error = -ELOOP; 1497 error = -ELOOP;
1481 if (flag & O_NOFOLLOW) 1498 if (flag & O_NOFOLLOW)
1482 goto exit_dput; 1499 goto exit_dput;
1483 while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
1484 } 1500 }
1485 error = -ENOENT; 1501 error = -ENOENT;
1486 if (!dentry->d_inode) 1502 if (!path.dentry->d_inode)
1487 goto exit_dput; 1503 goto exit_dput;
1488 if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) 1504 if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
1489 goto do_link; 1505 goto do_link;
1490 1506
1491 dput(nd->dentry); 1507 dput(nd->dentry);
1492 nd->dentry = dentry; 1508 nd->dentry = path.dentry;
1509 if (nd->mnt != path.mnt)
1510 mntput(nd->mnt);
1511 nd->mnt = path.mnt;
1493 error = -EISDIR; 1512 error = -EISDIR;
1494 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) 1513 if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
1495 goto exit; 1514 goto exit;
1496ok: 1515ok:
1497 error = may_open(nd, acc_mode, flag); 1516 error = may_open(nd, acc_mode, flag);
@@ -1500,7 +1519,9 @@ ok:
1500 return 0; 1519 return 0;
1501 1520
1502exit_dput: 1521exit_dput:
1503 dput(dentry); 1522 dput(path.dentry);
1523 if (nd->mnt != path.mnt)
1524 mntput(path.mnt);
1504exit: 1525exit:
1505 path_release(nd); 1526 path_release(nd);
1506 return error; 1527 return error;
@@ -1520,18 +1541,15 @@ do_link:
1520 * are done. Procfs-like symlinks just set LAST_BIND. 1541 * are done. Procfs-like symlinks just set LAST_BIND.
1521 */ 1542 */
1522 nd->flags |= LOOKUP_PARENT; 1543 nd->flags |= LOOKUP_PARENT;
1523 error = security_inode_follow_link(dentry, nd); 1544 error = security_inode_follow_link(path.dentry, nd);
1524 if (error) 1545 if (error)
1525 goto exit_dput; 1546 goto exit_dput;
1526 error = __do_follow_link(dentry, nd); 1547 error = __do_follow_link(&path, nd);
1527 dput(dentry);
1528 if (error) 1548 if (error)
1529 return error; 1549 return error;
1530 nd->flags &= ~LOOKUP_PARENT; 1550 nd->flags &= ~LOOKUP_PARENT;
1531 if (nd->last_type == LAST_BIND) { 1551 if (nd->last_type == LAST_BIND)
1532 dentry = nd->dentry;
1533 goto ok; 1552 goto ok;
1534 }
1535 error = -EISDIR; 1553 error = -EISDIR;
1536 if (nd->last_type != LAST_NORM) 1554 if (nd->last_type != LAST_NORM)
1537 goto exit; 1555 goto exit;
@@ -1546,7 +1564,8 @@ do_link:
1546 } 1564 }
1547 dir = nd->dentry; 1565 dir = nd->dentry;
1548 down(&dir->d_inode->i_sem); 1566 down(&dir->d_inode->i_sem);
1549 dentry = __lookup_hash(&nd->last, nd->dentry, nd); 1567 path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
1568 path.mnt = nd->mnt;
1550 putname(nd->last.name); 1569 putname(nd->last.name);
1551 goto do_last; 1570 goto do_last;
1552} 1571}
@@ -1558,19 +1577,35 @@ do_link:
1558 * 1577 *
1559 * Simple function to lookup and return a dentry and create it 1578 * Simple function to lookup and return a dentry and create it
1560 * if it doesn't exist. Is SMP-safe. 1579 * if it doesn't exist. Is SMP-safe.
1580 *
1581 * Returns with nd->dentry->d_inode->i_sem locked.
1561 */ 1582 */
1562struct dentry *lookup_create(struct nameidata *nd, int is_dir) 1583struct dentry *lookup_create(struct nameidata *nd, int is_dir)
1563{ 1584{
1564 struct dentry *dentry; 1585 struct dentry *dentry = ERR_PTR(-EEXIST);
1565 1586
1566 down(&nd->dentry->d_inode->i_sem); 1587 down(&nd->dentry->d_inode->i_sem);
1567 dentry = ERR_PTR(-EEXIST); 1588 /*
1589 * Yucky last component or no last component at all?
1590 * (foo/., foo/.., /////)
1591 */
1568 if (nd->last_type != LAST_NORM) 1592 if (nd->last_type != LAST_NORM)
1569 goto fail; 1593 goto fail;
1570 nd->flags &= ~LOOKUP_PARENT; 1594 nd->flags &= ~LOOKUP_PARENT;
1595
1596 /*
1597 * Do the final lookup.
1598 */
1571 dentry = lookup_hash(&nd->last, nd->dentry); 1599 dentry = lookup_hash(&nd->last, nd->dentry);
1572 if (IS_ERR(dentry)) 1600 if (IS_ERR(dentry))
1573 goto fail; 1601 goto fail;
1602
1603 /*
1604 * Special case - lookup gave negative, but... we had foo/bar/
1605 * From the vfs_mknod() POV we just have a negative dentry -
1606 * all is fine. Let's be bastards - you had / on the end, you've
1607 * been asking for (non-existent) directory. -ENOENT for you.
1608 */
1574 if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) 1609 if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
1575 goto enoent; 1610 goto enoent;
1576 return dentry; 1611 return dentry;
diff --git a/fs/namespace.c b/fs/namespace.c
index 3b93e5d750eb..208c079e9fdb 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -337,7 +337,7 @@ int may_umount(struct vfsmount *mnt)
337 337
338EXPORT_SYMBOL(may_umount); 338EXPORT_SYMBOL(may_umount);
339 339
340void umount_tree(struct vfsmount *mnt) 340static void umount_tree(struct vfsmount *mnt)
341{ 341{
342 struct vfsmount *p; 342 struct vfsmount *p;
343 LIST_HEAD(kill); 343 LIST_HEAD(kill);
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 2dc2d8693968..a9f7a8ab1d59 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -705,18 +705,6 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
705 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err); 705 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
706 return; 706 return;
707 } 707 }
708#ifdef USE_OLD_SLOW_DIRECTORY_LISTING
709 for (;;) {
710 err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
711 if (err) {
712 DPRINTK("ncp_do_readdir: search failed, err=%d\n", err);
713 break;
714 }
715 entry.volume = entry.i.volNumber;
716 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
717 break;
718 }
719#else
720 /* We MUST NOT use server->buffer_size handshaked with server if we are 708 /* We MUST NOT use server->buffer_size handshaked with server if we are
721 using UDP, as for UDP server uses max. buffer size determined by 709 using UDP, as for UDP server uses max. buffer size determined by
722 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 710 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
@@ -754,7 +742,6 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
754 } 742 }
755 } while (more); 743 } while (more);
756 vfree(buf); 744 vfree(buf);
757#endif
758 return; 745 return;
759} 746}
760 747
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index e4eb5ed4bee4..c755e1848a42 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -845,46 +845,6 @@ out:
845 return result; 845 return result;
846} 846}
847 847
848/* Search for everything */
849int ncp_search_for_file_or_subdir(struct ncp_server *server,
850 struct nw_search_sequence *seq,
851 struct nw_info_struct *target)
852{
853 int result;
854
855 ncp_init_request(server);
856 ncp_add_byte(server, 3); /* subfunction */
857 ncp_add_byte(server, server->name_space[seq->volNumber]);
858 ncp_add_byte(server, 0); /* data stream (???) */
859 ncp_add_word(server, cpu_to_le16(0x8006)); /* Search attribs */
860 ncp_add_dword(server, RIM_ALL); /* return info mask */
861 ncp_add_mem(server, seq, 9);
862#ifdef CONFIG_NCPFS_NFS_NS
863 if (server->name_space[seq->volNumber] == NW_NS_NFS) {
864 ncp_add_byte(server, 0); /* 0 byte pattern */
865 } else
866#endif
867 {
868 ncp_add_byte(server, 2); /* 2 byte pattern */
869 ncp_add_byte(server, 0xff); /* following is a wildcard */
870 ncp_add_byte(server, '*');
871 }
872
873 if ((result = ncp_request(server, 87)) != 0)
874 goto out;
875 memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
876 ncp_extract_file_info(ncp_reply_data(server, 10), target);
877
878 ncp_unlock_server(server);
879
880 result = ncp_obtain_nfs_info(server, target);
881 return result;
882
883out:
884 ncp_unlock_server(server);
885 return result;
886}
887
888int ncp_search_for_fileset(struct ncp_server *server, 848int ncp_search_for_fileset(struct ncp_server *server,
889 struct nw_search_sequence *seq, 849 struct nw_search_sequence *seq,
890 int* more, 850 int* more,
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 05ec2e9d90c6..9e4dc30c2435 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -87,9 +87,6 @@ int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *,
87 87
88int ncp_initialize_search(struct ncp_server *, struct inode *, 88int ncp_initialize_search(struct ncp_server *, struct inode *,
89 struct nw_search_sequence *target); 89 struct nw_search_sequence *target);
90int ncp_search_for_file_or_subdir(struct ncp_server *server,
91 struct nw_search_sequence *seq,
92 struct nw_info_struct *target);
93int ncp_search_for_fileset(struct ncp_server *server, 90int ncp_search_for_fileset(struct ncp_server *server,
94 struct nw_search_sequence *seq, 91 struct nw_search_sequence *seq,
95 int* more, int* cnt, 92 int* more, int* cnt,
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index b4baa031edf4..8b3bb715d177 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -8,6 +8,7 @@ nfs-y := dir.o file.o inode.o nfs2xdr.o pagelist.o \
8 proc.o read.o symlink.o unlink.o write.o 8 proc.o read.o symlink.o unlink.o write.o
9nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o 9nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
10nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o 10nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
11nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
11nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ 12nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
12 delegation.o idmap.o \ 13 delegation.o idmap.o \
13 callback.o callback_xdr.o callback_proc.o 14 callback.o callback_xdr.o callback_proc.o
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 560d6175dd58..f2ca782aba33 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,7 @@
14#include <linux/sunrpc/svc.h> 14#include <linux/sunrpc/svc.h>
15#include <linux/sunrpc/svcsock.h> 15#include <linux/sunrpc/svcsock.h>
16#include <linux/nfs_fs.h> 16#include <linux/nfs_fs.h>
17#include "nfs4_fs.h"
17#include "callback.h" 18#include "callback.h"
18 19
19#define NFSDBG_FACILITY NFSDBG_CALLBACK 20#define NFSDBG_FACILITY NFSDBG_CALLBACK
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index ece27e42b93b..65f1e19e4d19 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -8,6 +8,7 @@
8#include <linux/config.h> 8#include <linux/config.h>
9#include <linux/nfs4.h> 9#include <linux/nfs4.h>
10#include <linux/nfs_fs.h> 10#include <linux/nfs_fs.h>
11#include "nfs4_fs.h"
11#include "callback.h" 12#include "callback.h"
12#include "delegation.h" 13#include "delegation.h"
13 14
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index d271df9df2b2..7c33b9a81a94 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -10,6 +10,7 @@
10#include <linux/sunrpc/svc.h> 10#include <linux/sunrpc/svc.h>
11#include <linux/nfs4.h> 11#include <linux/nfs4.h>
12#include <linux/nfs_fs.h> 12#include <linux/nfs_fs.h>
13#include "nfs4_fs.h"
13#include "callback.h" 14#include "callback.h"
14 15
15#define CB_OP_TAGLEN_MAXSZ (512) 16#define CB_OP_TAGLEN_MAXSZ (512)
@@ -410,7 +411,6 @@ static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp
410 xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); 411 xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
411 412
412 p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); 413 p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
413 rqstp->rq_res.head[0].iov_len = PAGE_SIZE;
414 xdr_init_encode(&xdr_out, &rqstp->rq_res, p); 414 xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
415 415
416 decode_compound_hdr_arg(&xdr_in, &hdr_arg); 416 decode_compound_hdr_arg(&xdr_in, &hdr_arg);
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 5b9c60f97791..d7f7eb669d03 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -16,6 +16,7 @@
16#include <linux/nfs_fs.h> 16#include <linux/nfs_fs.h>
17#include <linux/nfs_xdr.h> 17#include <linux/nfs_xdr.h>
18 18
19#include "nfs4_fs.h"
19#include "delegation.h" 20#include "delegation.h"
20 21
21static struct nfs_delegation *nfs_alloc_delegation(void) 22static struct nfs_delegation *nfs_alloc_delegation(void)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f96acd5d37..b38a57e78a63 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -32,6 +32,7 @@
32#include <linux/smp_lock.h> 32#include <linux/smp_lock.h>
33#include <linux/namei.h> 33#include <linux/namei.h>
34 34
35#include "nfs4_fs.h"
35#include "delegation.h" 36#include "delegation.h"
36 37
37#define NFS_PARANOIA 1 38#define NFS_PARANOIA 1
@@ -50,8 +51,10 @@ static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
50static int nfs_rename(struct inode *, struct dentry *, 51static int nfs_rename(struct inode *, struct dentry *,
51 struct inode *, struct dentry *); 52 struct inode *, struct dentry *);
52static int nfs_fsync_dir(struct file *, struct dentry *, int); 53static int nfs_fsync_dir(struct file *, struct dentry *, int);
54static loff_t nfs_llseek_dir(struct file *, loff_t, int);
53 55
54struct file_operations nfs_dir_operations = { 56struct file_operations nfs_dir_operations = {
57 .llseek = nfs_llseek_dir,
55 .read = generic_read_dir, 58 .read = generic_read_dir,
56 .readdir = nfs_readdir, 59 .readdir = nfs_readdir,
57 .open = nfs_opendir, 60 .open = nfs_opendir,
@@ -74,6 +77,27 @@ struct inode_operations nfs_dir_inode_operations = {
74 .setattr = nfs_setattr, 77 .setattr = nfs_setattr,
75}; 78};
76 79
80#ifdef CONFIG_NFS_V3
81struct inode_operations nfs3_dir_inode_operations = {
82 .create = nfs_create,
83 .lookup = nfs_lookup,
84 .link = nfs_link,
85 .unlink = nfs_unlink,
86 .symlink = nfs_symlink,
87 .mkdir = nfs_mkdir,
88 .rmdir = nfs_rmdir,
89 .mknod = nfs_mknod,
90 .rename = nfs_rename,
91 .permission = nfs_permission,
92 .getattr = nfs_getattr,
93 .setattr = nfs_setattr,
94 .listxattr = nfs3_listxattr,
95 .getxattr = nfs3_getxattr,
96 .setxattr = nfs3_setxattr,
97 .removexattr = nfs3_removexattr,
98};
99#endif /* CONFIG_NFS_V3 */
100
77#ifdef CONFIG_NFS_V4 101#ifdef CONFIG_NFS_V4
78 102
79static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); 103static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
@@ -90,6 +114,9 @@ struct inode_operations nfs4_dir_inode_operations = {
90 .permission = nfs_permission, 114 .permission = nfs_permission,
91 .getattr = nfs_getattr, 115 .getattr = nfs_getattr,
92 .setattr = nfs_setattr, 116 .setattr = nfs_setattr,
117 .getxattr = nfs4_getxattr,
118 .setxattr = nfs4_setxattr,
119 .listxattr = nfs4_listxattr,
93}; 120};
94 121
95#endif /* CONFIG_NFS_V4 */ 122#endif /* CONFIG_NFS_V4 */
@@ -116,7 +143,8 @@ typedef struct {
116 struct page *page; 143 struct page *page;
117 unsigned long page_index; 144 unsigned long page_index;
118 u32 *ptr; 145 u32 *ptr;
119 u64 target; 146 u64 *dir_cookie;
147 loff_t current_index;
120 struct nfs_entry *entry; 148 struct nfs_entry *entry;
121 decode_dirent_t decode; 149 decode_dirent_t decode;
122 int plus; 150 int plus;
@@ -164,12 +192,10 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
164 NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; 192 NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
165 /* Ensure consistent page alignment of the data. 193 /* Ensure consistent page alignment of the data.
166 * Note: assumes we have exclusive access to this mapping either 194 * Note: assumes we have exclusive access to this mapping either
167 * throught inode->i_sem or some other mechanism. 195 * through inode->i_sem or some other mechanism.
168 */ 196 */
169 if (page->index == 0) { 197 if (page->index == 0)
170 invalidate_inode_pages(inode->i_mapping); 198 invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1);
171 NFS_I(inode)->readdir_timestamp = timestamp;
172 }
173 unlock_page(page); 199 unlock_page(page);
174 return 0; 200 return 0;
175 error: 201 error:
@@ -202,22 +228,22 @@ void dir_page_release(nfs_readdir_descriptor_t *desc)
202 228
203/* 229/*
204 * Given a pointer to a buffer that has already been filled by a call 230 * Given a pointer to a buffer that has already been filled by a call
205 * to readdir, find the next entry. 231 * to readdir, find the next entry with cookie '*desc->dir_cookie'.
206 * 232 *
207 * If the end of the buffer has been reached, return -EAGAIN, if not, 233 * If the end of the buffer has been reached, return -EAGAIN, if not,
208 * return the offset within the buffer of the next entry to be 234 * return the offset within the buffer of the next entry to be
209 * read. 235 * read.
210 */ 236 */
211static inline 237static inline
212int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page) 238int find_dirent(nfs_readdir_descriptor_t *desc)
213{ 239{
214 struct nfs_entry *entry = desc->entry; 240 struct nfs_entry *entry = desc->entry;
215 int loop_count = 0, 241 int loop_count = 0,
216 status; 242 status;
217 243
218 while((status = dir_decode(desc)) == 0) { 244 while((status = dir_decode(desc)) == 0) {
219 dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie); 245 dfprintk(VFS, "NFS: found cookie %Lu\n", (unsigned long long)entry->cookie);
220 if (entry->prev_cookie == desc->target) 246 if (entry->prev_cookie == *desc->dir_cookie)
221 break; 247 break;
222 if (loop_count++ > 200) { 248 if (loop_count++ > 200) {
223 loop_count = 0; 249 loop_count = 0;
@@ -229,8 +255,44 @@ int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page)
229} 255}
230 256
231/* 257/*
232 * Find the given page, and call find_dirent() in order to try to 258 * Given a pointer to a buffer that has already been filled by a call
233 * return the next entry. 259 * to readdir, find the entry at offset 'desc->file->f_pos'.
260 *
261 * If the end of the buffer has been reached, return -EAGAIN, if not,
262 * return the offset within the buffer of the next entry to be
263 * read.
264 */
265static inline
266int find_dirent_index(nfs_readdir_descriptor_t *desc)
267{
268 struct nfs_entry *entry = desc->entry;
269 int loop_count = 0,
270 status;
271
272 for(;;) {
273 status = dir_decode(desc);
274 if (status)
275 break;
276
277 dfprintk(VFS, "NFS: found cookie %Lu at index %Ld\n", (unsigned long long)entry->cookie, desc->current_index);
278
279 if (desc->file->f_pos == desc->current_index) {
280 *desc->dir_cookie = entry->cookie;
281 break;
282 }
283 desc->current_index++;
284 if (loop_count++ > 200) {
285 loop_count = 0;
286 schedule();
287 }
288 }
289 dfprintk(VFS, "NFS: find_dirent_index() returns %d\n", status);
290 return status;
291}
292
293/*
294 * Find the given page, and call find_dirent() or find_dirent_index in
295 * order to try to return the next entry.
234 */ 296 */
235static inline 297static inline
236int find_dirent_page(nfs_readdir_descriptor_t *desc) 298int find_dirent_page(nfs_readdir_descriptor_t *desc)
@@ -253,7 +315,10 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
253 /* NOTE: Someone else may have changed the READDIRPLUS flag */ 315 /* NOTE: Someone else may have changed the READDIRPLUS flag */
254 desc->page = page; 316 desc->page = page;
255 desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ 317 desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */
256 status = find_dirent(desc, page); 318 if (*desc->dir_cookie != 0)
319 status = find_dirent(desc);
320 else
321 status = find_dirent_index(desc);
257 if (status < 0) 322 if (status < 0)
258 dir_page_release(desc); 323 dir_page_release(desc);
259 out: 324 out:
@@ -268,7 +333,8 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
268 * Recurse through the page cache pages, and return a 333 * Recurse through the page cache pages, and return a
269 * filled nfs_entry structure of the next directory entry if possible. 334 * filled nfs_entry structure of the next directory entry if possible.
270 * 335 *
271 * The target for the search is 'desc->target'. 336 * The target for the search is '*desc->dir_cookie' if non-0,
337 * 'desc->file->f_pos' otherwise
272 */ 338 */
273static inline 339static inline
274int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) 340int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
@@ -276,7 +342,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
276 int loop_count = 0; 342 int loop_count = 0;
277 int res; 343 int res;
278 344
279 dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target); 345 /* Always search-by-index from the beginning of the cache */
346 if (*desc->dir_cookie == 0) {
347 dfprintk(VFS, "NFS: readdir_search_pagecache() searching for offset %Ld\n", (long long)desc->file->f_pos);
348 desc->page_index = 0;
349 desc->entry->cookie = desc->entry->prev_cookie = 0;
350 desc->entry->eof = 0;
351 desc->current_index = 0;
352 } else
353 dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
354
280 for (;;) { 355 for (;;) {
281 res = find_dirent_page(desc); 356 res = find_dirent_page(desc);
282 if (res != -EAGAIN) 357 if (res != -EAGAIN)
@@ -313,7 +388,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
313 int loop_count = 0, 388 int loop_count = 0,
314 res; 389 res;
315 390
316 dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target); 391 dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)entry->cookie);
317 392
318 for(;;) { 393 for(;;) {
319 unsigned d_type = DT_UNKNOWN; 394 unsigned d_type = DT_UNKNOWN;
@@ -333,10 +408,11 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
333 } 408 }
334 409
335 res = filldir(dirent, entry->name, entry->len, 410 res = filldir(dirent, entry->name, entry->len,
336 entry->prev_cookie, fileid, d_type); 411 file->f_pos, fileid, d_type);
337 if (res < 0) 412 if (res < 0)
338 break; 413 break;
339 file->f_pos = desc->target = entry->cookie; 414 file->f_pos++;
415 *desc->dir_cookie = entry->cookie;
340 if (dir_decode(desc) != 0) { 416 if (dir_decode(desc) != 0) {
341 desc->page_index ++; 417 desc->page_index ++;
342 break; 418 break;
@@ -349,7 +425,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
349 dir_page_release(desc); 425 dir_page_release(desc);
350 if (dentry != NULL) 426 if (dentry != NULL)
351 dput(dentry); 427 dput(dentry);
352 dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res); 428 dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (unsigned long long)*desc->dir_cookie, res);
353 return res; 429 return res;
354} 430}
355 431
@@ -375,14 +451,14 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
375 struct page *page = NULL; 451 struct page *page = NULL;
376 int status; 452 int status;
377 453
378 dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target); 454 dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
379 455
380 page = alloc_page(GFP_HIGHUSER); 456 page = alloc_page(GFP_HIGHUSER);
381 if (!page) { 457 if (!page) {
382 status = -ENOMEM; 458 status = -ENOMEM;
383 goto out; 459 goto out;
384 } 460 }
385 desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target, 461 desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie,
386 page, 462 page,
387 NFS_SERVER(inode)->dtsize, 463 NFS_SERVER(inode)->dtsize,
388 desc->plus); 464 desc->plus);
@@ -391,7 +467,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
391 desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ 467 desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */
392 if (desc->error >= 0) { 468 if (desc->error >= 0) {
393 if ((status = dir_decode(desc)) == 0) 469 if ((status = dir_decode(desc)) == 0)
394 desc->entry->prev_cookie = desc->target; 470 desc->entry->prev_cookie = *desc->dir_cookie;
395 } else 471 } else
396 status = -EIO; 472 status = -EIO;
397 if (status < 0) 473 if (status < 0)
@@ -412,8 +488,9 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
412 goto out; 488 goto out;
413} 489}
414 490
415/* The file offset position is now represented as a true offset into the 491/* The file offset position represents the dirent entry number. A
416 * page cache as is the case in most of the other filesystems. 492 last cookie cache takes care of the common case of reading the
493 whole directory.
417 */ 494 */
418static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) 495static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
419{ 496{
@@ -435,15 +512,15 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
435 } 512 }
436 513
437 /* 514 /*
438 * filp->f_pos points to the file offset in the page cache. 515 * filp->f_pos points to the dirent entry number.
439 * but if the cache has meanwhile been zapped, we need to 516 * *desc->dir_cookie has the cookie for the next entry. We have
440 * read from the last dirent to revalidate f_pos 517 * to either find the entry with the appropriate number or
441 * itself. 518 * revalidate the cookie.
442 */ 519 */
443 memset(desc, 0, sizeof(*desc)); 520 memset(desc, 0, sizeof(*desc));
444 521
445 desc->file = filp; 522 desc->file = filp;
446 desc->target = filp->f_pos; 523 desc->dir_cookie = &((struct nfs_open_context *)filp->private_data)->dir_cookie;
447 desc->decode = NFS_PROTO(inode)->decode_dirent; 524 desc->decode = NFS_PROTO(inode)->decode_dirent;
448 desc->plus = NFS_USE_READDIRPLUS(inode); 525 desc->plus = NFS_USE_READDIRPLUS(inode);
449 526
@@ -455,9 +532,10 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
455 532
456 while(!desc->entry->eof) { 533 while(!desc->entry->eof) {
457 res = readdir_search_pagecache(desc); 534 res = readdir_search_pagecache(desc);
535
458 if (res == -EBADCOOKIE) { 536 if (res == -EBADCOOKIE) {
459 /* This means either end of directory */ 537 /* This means either end of directory */
460 if (desc->entry->cookie != desc->target) { 538 if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) {
461 /* Or that the server has 'lost' a cookie */ 539 /* Or that the server has 'lost' a cookie */
462 res = uncached_readdir(desc, dirent, filldir); 540 res = uncached_readdir(desc, dirent, filldir);
463 if (res >= 0) 541 if (res >= 0)
@@ -490,6 +568,28 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
490 return 0; 568 return 0;
491} 569}
492 570
571loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
572{
573 down(&filp->f_dentry->d_inode->i_sem);
574 switch (origin) {
575 case 1:
576 offset += filp->f_pos;
577 case 0:
578 if (offset >= 0)
579 break;
580 default:
581 offset = -EINVAL;
582 goto out;
583 }
584 if (offset != filp->f_pos) {
585 filp->f_pos = offset;
586 ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0;
587 }
588out:
589 up(&filp->f_dentry->d_inode->i_sem);
590 return offset;
591}
592
493/* 593/*
494 * All directory operations under NFS are synchronous, so fsync() 594 * All directory operations under NFS are synchronous, so fsync()
495 * is a dummy operation. 595 * is a dummy operation.
@@ -528,19 +628,39 @@ static inline void nfs_renew_times(struct dentry * dentry)
528 dentry->d_time = jiffies; 628 dentry->d_time = jiffies;
529} 629}
530 630
631/*
632 * Return the intent data that applies to this particular path component
633 *
634 * Note that the current set of intents only apply to the very last
635 * component of the path.
636 * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
637 */
638static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
639{
640 if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
641 return 0;
642 return nd->flags & mask;
643}
644
645/*
646 * Inode and filehandle revalidation for lookups.
647 *
648 * We force revalidation in the cases where the VFS sets LOOKUP_REVAL,
649 * or if the intent information indicates that we're about to open this
650 * particular file and the "nocto" mount flag is not set.
651 *
652 */
531static inline 653static inline
532int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) 654int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
533{ 655{
534 struct nfs_server *server = NFS_SERVER(inode); 656 struct nfs_server *server = NFS_SERVER(inode);
535 657
536 if (nd != NULL) { 658 if (nd != NULL) {
537 int ndflags = nd->flags;
538 /* VFS wants an on-the-wire revalidation */ 659 /* VFS wants an on-the-wire revalidation */
539 if (ndflags & LOOKUP_REVAL) 660 if (nd->flags & LOOKUP_REVAL)
540 goto out_force; 661 goto out_force;
541 /* This is an open(2) */ 662 /* This is an open(2) */
542 if ((ndflags & LOOKUP_OPEN) && 663 if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
543 !(ndflags & LOOKUP_CONTINUE) &&
544 !(server->flags & NFS_MOUNT_NOCTO)) 664 !(server->flags & NFS_MOUNT_NOCTO))
545 goto out_force; 665 goto out_force;
546 } 666 }
@@ -560,12 +680,8 @@ static inline
560int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, 680int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
561 struct nameidata *nd) 681 struct nameidata *nd)
562{ 682{
563 int ndflags = 0;
564
565 if (nd)
566 ndflags = nd->flags;
567 /* Don't revalidate a negative dentry if we're creating a new file */ 683 /* Don't revalidate a negative dentry if we're creating a new file */
568 if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE)) 684 if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
569 return 0; 685 return 0;
570 return !nfs_check_verifier(dir, dentry); 686 return !nfs_check_verifier(dir, dentry);
571} 687}
@@ -700,12 +816,16 @@ struct dentry_operations nfs_dentry_operations = {
700 .d_iput = nfs_dentry_iput, 816 .d_iput = nfs_dentry_iput,
701}; 817};
702 818
819/*
820 * Use intent information to check whether or not we're going to do
821 * an O_EXCL create using this path component.
822 */
703static inline 823static inline
704int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) 824int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
705{ 825{
706 if (NFS_PROTO(dir)->version == 2) 826 if (NFS_PROTO(dir)->version == 2)
707 return 0; 827 return 0;
708 if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE)) 828 if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
709 return 0; 829 return 0;
710 return (nd->intent.open.flags & O_EXCL) != 0; 830 return (nd->intent.open.flags & O_EXCL) != 0;
711} 831}
@@ -772,12 +892,13 @@ struct dentry_operations nfs4_dentry_operations = {
772 .d_iput = nfs_dentry_iput, 892 .d_iput = nfs_dentry_iput,
773}; 893};
774 894
895/*
896 * Use intent information to determine whether we need to substitute
897 * the NFSv4-style stateful OPEN for the LOOKUP call
898 */
775static int is_atomic_open(struct inode *dir, struct nameidata *nd) 899static int is_atomic_open(struct inode *dir, struct nameidata *nd)
776{ 900{
777 if (!nd) 901 if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
778 return 0;
779 /* Check that we are indeed trying to open this file */
780 if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN))
781 return 0; 902 return 0;
782 /* NFS does not (yet) have a stateful open for directories */ 903 /* NFS does not (yet) have a stateful open for directories */
783 if (nd->flags & LOOKUP_DIRECTORY) 904 if (nd->flags & LOOKUP_DIRECTORY)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 68df803f27ca..6537f2c4ae44 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -517,7 +517,7 @@ retry:
517 result = tot_bytes; 517 result = tot_bytes;
518 518
519out: 519out:
520 nfs_end_data_update_defer(inode); 520 nfs_end_data_update(inode);
521 nfs_writedata_free(wdata); 521 nfs_writedata_free(wdata);
522 return result; 522 return result;
523 523
@@ -751,11 +751,6 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
751 retval = -EFAULT; 751 retval = -EFAULT;
752 if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len)) 752 if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
753 goto out; 753 goto out;
754 if (file->f_error) {
755 retval = file->f_error;
756 file->f_error = 0;
757 goto out;
758 }
759 retval = -EFBIG; 754 retval = -EFBIG;
760 if (limit != RLIM_INFINITY) { 755 if (limit != RLIM_INFINITY) {
761 if (pos >= limit) { 756 if (pos >= limit) {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f06eee6dcff5..5621ba9885f4 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -37,6 +37,7 @@
37 37
38static int nfs_file_open(struct inode *, struct file *); 38static int nfs_file_open(struct inode *, struct file *);
39static int nfs_file_release(struct inode *, struct file *); 39static int nfs_file_release(struct inode *, struct file *);
40static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
40static int nfs_file_mmap(struct file *, struct vm_area_struct *); 41static int nfs_file_mmap(struct file *, struct vm_area_struct *);
41static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); 42static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
42static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); 43static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
@@ -48,7 +49,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
48static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); 49static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
49 50
50struct file_operations nfs_file_operations = { 51struct file_operations nfs_file_operations = {
51 .llseek = remote_llseek, 52 .llseek = nfs_file_llseek,
52 .read = do_sync_read, 53 .read = do_sync_read,
53 .write = do_sync_write, 54 .write = do_sync_write,
54 .aio_read = nfs_file_read, 55 .aio_read = nfs_file_read,
@@ -70,6 +71,18 @@ struct inode_operations nfs_file_inode_operations = {
70 .setattr = nfs_setattr, 71 .setattr = nfs_setattr,
71}; 72};
72 73
74#ifdef CONFIG_NFS_V3
75struct inode_operations nfs3_file_inode_operations = {
76 .permission = nfs_permission,
77 .getattr = nfs_getattr,
78 .setattr = nfs_setattr,
79 .listxattr = nfs3_listxattr,
80 .getxattr = nfs3_getxattr,
81 .setxattr = nfs3_setxattr,
82 .removexattr = nfs3_removexattr,
83};
84#endif /* CONFIG_NFS_v3 */
85
73/* Hack for future NFS swap support */ 86/* Hack for future NFS swap support */
74#ifndef IS_SWAPFILE 87#ifndef IS_SWAPFILE
75# define IS_SWAPFILE(inode) (0) 88# define IS_SWAPFILE(inode) (0)
@@ -114,6 +127,61 @@ nfs_file_release(struct inode *inode, struct file *filp)
114 return NFS_PROTO(inode)->file_release(inode, filp); 127 return NFS_PROTO(inode)->file_release(inode, filp);
115} 128}
116 129
130/**
131 * nfs_revalidate_file - Revalidate the page cache & related metadata
132 * @inode - pointer to inode struct
133 * @file - pointer to file
134 */
135static int nfs_revalidate_file(struct inode *inode, struct file *filp)
136{
137 int retval = 0;
138
139 if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
140 retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
141 nfs_revalidate_mapping(inode, filp->f_mapping);
142 return 0;
143}
144
145/**
146 * nfs_revalidate_size - Revalidate the file size
147 * @inode - pointer to inode struct
148 * @file - pointer to struct file
149 *
150 * Revalidates the file length. This is basically a wrapper around
151 * nfs_revalidate_inode() that takes into account the fact that we may
152 * have cached writes (in which case we don't care about the server's
153 * idea of what the file length is), or O_DIRECT (in which case we
154 * shouldn't trust the cache).
155 */
156static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
157{
158 struct nfs_server *server = NFS_SERVER(inode);
159 struct nfs_inode *nfsi = NFS_I(inode);
160
161 if (server->flags & NFS_MOUNT_NOAC)
162 goto force_reval;
163 if (filp->f_flags & O_DIRECT)
164 goto force_reval;
165 if (nfsi->npages != 0)
166 return 0;
167 if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
168 return 0;
169force_reval:
170 return __nfs_revalidate_inode(server, inode);
171}
172
173static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
174{
175 /* origin == SEEK_END => we must revalidate the cached file length */
176 if (origin == 2) {
177 struct inode *inode = filp->f_mapping->host;
178 int retval = nfs_revalidate_file_size(inode, filp);
179 if (retval < 0)
180 return (loff_t)retval;
181 }
182 return remote_llseek(filp, offset, origin);
183}
184
117/* 185/*
118 * Flush all dirty pages, and check for write errors. 186 * Flush all dirty pages, and check for write errors.
119 * 187 *
@@ -158,7 +226,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
158 dentry->d_parent->d_name.name, dentry->d_name.name, 226 dentry->d_parent->d_name.name, dentry->d_name.name,
159 (unsigned long) count, (unsigned long) pos); 227 (unsigned long) count, (unsigned long) pos);
160 228
161 result = nfs_revalidate_inode(NFS_SERVER(inode), inode); 229 result = nfs_revalidate_file(inode, iocb->ki_filp);
162 if (!result) 230 if (!result)
163 result = generic_file_aio_read(iocb, buf, count, pos); 231 result = generic_file_aio_read(iocb, buf, count, pos);
164 return result; 232 return result;
@@ -176,7 +244,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
176 dentry->d_parent->d_name.name, dentry->d_name.name, 244 dentry->d_parent->d_name.name, dentry->d_name.name,
177 (unsigned long) count, (unsigned long long) *ppos); 245 (unsigned long) count, (unsigned long long) *ppos);
178 246
179 res = nfs_revalidate_inode(NFS_SERVER(inode), inode); 247 res = nfs_revalidate_file(inode, filp);
180 if (!res) 248 if (!res)
181 res = generic_file_sendfile(filp, ppos, count, actor, target); 249 res = generic_file_sendfile(filp, ppos, count, actor, target);
182 return res; 250 return res;
@@ -192,7 +260,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
192 dfprintk(VFS, "nfs: mmap(%s/%s)\n", 260 dfprintk(VFS, "nfs: mmap(%s/%s)\n",
193 dentry->d_parent->d_name.name, dentry->d_name.name); 261 dentry->d_parent->d_name.name, dentry->d_name.name);
194 262
195 status = nfs_revalidate_inode(NFS_SERVER(inode), inode); 263 status = nfs_revalidate_file(inode, file);
196 if (!status) 264 if (!status)
197 status = generic_file_mmap(file, vma); 265 status = generic_file_mmap(file, vma);
198 return status; 266 return status;
@@ -281,9 +349,15 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
281 result = -EBUSY; 349 result = -EBUSY;
282 if (IS_SWAPFILE(inode)) 350 if (IS_SWAPFILE(inode))
283 goto out_swapfile; 351 goto out_swapfile;
284 result = nfs_revalidate_inode(NFS_SERVER(inode), inode); 352 /*
285 if (result) 353 * O_APPEND implies that we must revalidate the file length.
286 goto out; 354 */
355 if (iocb->ki_filp->f_flags & O_APPEND) {
356 result = nfs_revalidate_file_size(inode, iocb->ki_filp);
357 if (result)
358 goto out;
359 }
360 nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
287 361
288 result = count; 362 result = count;
289 if (!count) 363 if (!count)
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 87f4f9aeac86..ffb8df91dc34 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -50,6 +50,7 @@
50#include <linux/nfs_fs.h> 50#include <linux/nfs_fs.h>
51 51
52#include <linux/nfs_idmap.h> 52#include <linux/nfs_idmap.h>
53#include "nfs4_fs.h"
53 54
54#define IDMAP_HASH_SZ 128 55#define IDMAP_HASH_SZ 128
55 56
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f2317f3e29f9..4845911f1c63 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -39,6 +39,7 @@
39#include <asm/system.h> 39#include <asm/system.h>
40#include <asm/uaccess.h> 40#include <asm/uaccess.h>
41 41
42#include "nfs4_fs.h"
42#include "delegation.h" 43#include "delegation.h"
43 44
44#define NFSDBG_FACILITY NFSDBG_VFS 45#define NFSDBG_FACILITY NFSDBG_VFS
@@ -63,6 +64,7 @@ static void nfs_clear_inode(struct inode *);
63static void nfs_umount_begin(struct super_block *); 64static void nfs_umount_begin(struct super_block *);
64static int nfs_statfs(struct super_block *, struct kstatfs *); 65static int nfs_statfs(struct super_block *, struct kstatfs *);
65static int nfs_show_options(struct seq_file *, struct vfsmount *); 66static int nfs_show_options(struct seq_file *, struct vfsmount *);
67static void nfs_zap_acl_cache(struct inode *);
66 68
67static struct rpc_program nfs_program; 69static struct rpc_program nfs_program;
68 70
@@ -106,6 +108,21 @@ static struct rpc_program nfs_program = {
106 .pipe_dir_name = "/nfs", 108 .pipe_dir_name = "/nfs",
107}; 109};
108 110
111#ifdef CONFIG_NFS_V3_ACL
112static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
113static struct rpc_version * nfsacl_version[] = {
114 [3] = &nfsacl_version3,
115};
116
117struct rpc_program nfsacl_program = {
118 .name = "nfsacl",
119 .number = NFS_ACL_PROGRAM,
120 .nrvers = sizeof(nfsacl_version) / sizeof(nfsacl_version[0]),
121 .version = nfsacl_version,
122 .stats = &nfsacl_rpcstat,
123};
124#endif /* CONFIG_NFS_V3_ACL */
125
109static inline unsigned long 126static inline unsigned long
110nfs_fattr_to_ino_t(struct nfs_fattr *fattr) 127nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
111{ 128{
@@ -118,7 +135,7 @@ nfs_write_inode(struct inode *inode, int sync)
118 int flags = sync ? FLUSH_WAIT : 0; 135 int flags = sync ? FLUSH_WAIT : 0;
119 int ret; 136 int ret;
120 137
121 ret = nfs_commit_inode(inode, 0, 0, flags); 138 ret = nfs_commit_inode(inode, flags);
122 if (ret < 0) 139 if (ret < 0)
123 return ret; 140 return ret;
124 return 0; 141 return 0;
@@ -140,10 +157,6 @@ nfs_delete_inode(struct inode * inode)
140 clear_inode(inode); 157 clear_inode(inode);
141} 158}
142 159
143/*
144 * For the moment, the only task for the NFS clear_inode method is to
145 * release the mmap credential
146 */
147static void 160static void
148nfs_clear_inode(struct inode *inode) 161nfs_clear_inode(struct inode *inode)
149{ 162{
@@ -152,6 +165,7 @@ nfs_clear_inode(struct inode *inode)
152 165
153 nfs_wb_all(inode); 166 nfs_wb_all(inode);
154 BUG_ON (!list_empty(&nfsi->open_files)); 167 BUG_ON (!list_empty(&nfsi->open_files));
168 nfs_zap_acl_cache(inode);
155 cred = nfsi->cache_access.cred; 169 cred = nfsi->cache_access.cred;
156 if (cred) 170 if (cred)
157 put_rpccred(cred); 171 put_rpccred(cred);
@@ -161,11 +175,13 @@ nfs_clear_inode(struct inode *inode)
161void 175void
162nfs_umount_begin(struct super_block *sb) 176nfs_umount_begin(struct super_block *sb)
163{ 177{
164 struct nfs_server *server = NFS_SB(sb); 178 struct rpc_clnt *rpc = NFS_SB(sb)->client;
165 struct rpc_clnt *rpc;
166 179
167 /* -EIO all pending I/O */ 180 /* -EIO all pending I/O */
168 if ((rpc = server->client) != NULL) 181 if (!IS_ERR(rpc))
182 rpc_killall_tasks(rpc);
183 rpc = NFS_SB(sb)->client_acl;
184 if (!IS_ERR(rpc))
169 rpc_killall_tasks(rpc); 185 rpc_killall_tasks(rpc);
170} 186}
171 187
@@ -366,13 +382,15 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
366 xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, 382 xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
367 &server->addr, &timeparms); 383 &server->addr, &timeparms);
368 if (IS_ERR(xprt)) { 384 if (IS_ERR(xprt)) {
369 printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); 385 dprintk("%s: cannot create RPC transport. Error = %ld\n",
386 __FUNCTION__, PTR_ERR(xprt));
370 return (struct rpc_clnt *)xprt; 387 return (struct rpc_clnt *)xprt;
371 } 388 }
372 clnt = rpc_create_client(xprt, server->hostname, &nfs_program, 389 clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
373 server->rpc_ops->version, data->pseudoflavor); 390 server->rpc_ops->version, data->pseudoflavor);
374 if (IS_ERR(clnt)) { 391 if (IS_ERR(clnt)) {
375 printk(KERN_WARNING "NFS: cannot create RPC client.\n"); 392 dprintk("%s: cannot create RPC client. Error = %ld\n",
393 __FUNCTION__, PTR_ERR(xprt));
376 goto out_fail; 394 goto out_fail;
377 } 395 }
378 396
@@ -383,7 +401,6 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
383 return clnt; 401 return clnt;
384 402
385out_fail: 403out_fail:
386 xprt_destroy(xprt);
387 return clnt; 404 return clnt;
388} 405}
389 406
@@ -427,21 +444,16 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
427 444
428 /* Check NFS protocol revision and initialize RPC op vector 445 /* Check NFS protocol revision and initialize RPC op vector
429 * and file handle pool. */ 446 * and file handle pool. */
430 if (server->flags & NFS_MOUNT_VER3) {
431#ifdef CONFIG_NFS_V3 447#ifdef CONFIG_NFS_V3
448 if (server->flags & NFS_MOUNT_VER3) {
432 server->rpc_ops = &nfs_v3_clientops; 449 server->rpc_ops = &nfs_v3_clientops;
433 server->caps |= NFS_CAP_READDIRPLUS; 450 server->caps |= NFS_CAP_READDIRPLUS;
434 if (data->version < 4) {
435 printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");
436 return -EIO;
437 }
438#else
439 printk(KERN_NOTICE "NFS: NFSv3 not supported.\n");
440 return -EIO;
441#endif
442 } else { 451 } else {
443 server->rpc_ops = &nfs_v2_clientops; 452 server->rpc_ops = &nfs_v2_clientops;
444 } 453 }
454#else
455 server->rpc_ops = &nfs_v2_clientops;
456#endif
445 457
446 /* Fill in pseudoflavor for mount version < 5 */ 458 /* Fill in pseudoflavor for mount version < 5 */
447 if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) 459 if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
@@ -455,17 +467,34 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
455 return PTR_ERR(server->client); 467 return PTR_ERR(server->client);
456 /* RFC 2623, sec 2.3.2 */ 468 /* RFC 2623, sec 2.3.2 */
457 if (authflavor != RPC_AUTH_UNIX) { 469 if (authflavor != RPC_AUTH_UNIX) {
470 struct rpc_auth *auth;
471
458 server->client_sys = rpc_clone_client(server->client); 472 server->client_sys = rpc_clone_client(server->client);
459 if (IS_ERR(server->client_sys)) 473 if (IS_ERR(server->client_sys))
460 return PTR_ERR(server->client_sys); 474 return PTR_ERR(server->client_sys);
461 if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys)) 475 auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
462 return -ENOMEM; 476 if (IS_ERR(auth))
477 return PTR_ERR(auth);
463 } else { 478 } else {
464 atomic_inc(&server->client->cl_count); 479 atomic_inc(&server->client->cl_count);
465 server->client_sys = server->client; 480 server->client_sys = server->client;
466 } 481 }
467
468 if (server->flags & NFS_MOUNT_VER3) { 482 if (server->flags & NFS_MOUNT_VER3) {
483#ifdef CONFIG_NFS_V3_ACL
484 if (!(server->flags & NFS_MOUNT_NOACL)) {
485 server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
486 /* No errors! Assume that Sun nfsacls are supported */
487 if (!IS_ERR(server->client_acl))
488 server->caps |= NFS_CAP_ACLS;
489 }
490#else
491 server->flags &= ~NFS_MOUNT_NOACL;
492#endif /* CONFIG_NFS_V3_ACL */
493 /*
494 * The VFS shouldn't apply the umask to mode bits. We will
495 * do so ourselves when necessary.
496 */
497 sb->s_flags |= MS_POSIXACL;
469 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) 498 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
470 server->namelen = NFS3_MAXNAMLEN; 499 server->namelen = NFS3_MAXNAMLEN;
471 sb->s_time_gran = 1; 500 sb->s_time_gran = 1;
@@ -549,6 +578,7 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
549 { NFS_MOUNT_NOCTO, ",nocto", "" }, 578 { NFS_MOUNT_NOCTO, ",nocto", "" },
550 { NFS_MOUNT_NOAC, ",noac", "" }, 579 { NFS_MOUNT_NOAC, ",noac", "" },
551 { NFS_MOUNT_NONLM, ",nolock", ",lock" }, 580 { NFS_MOUNT_NONLM, ",nolock", ",lock" },
581 { NFS_MOUNT_NOACL, ",noacl", "" },
552 { 0, NULL, NULL } 582 { 0, NULL, NULL }
553 }; 583 };
554 struct proc_nfs_info *nfs_infop; 584 struct proc_nfs_info *nfs_infop;
@@ -590,9 +620,19 @@ nfs_zap_caches(struct inode *inode)
590 620
591 memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); 621 memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
592 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) 622 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
593 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS; 623 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
594 else 624 else
595 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS; 625 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
626}
627
628static void nfs_zap_acl_cache(struct inode *inode)
629{
630 void (*clear_acl_cache)(struct inode *);
631
632 clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
633 if (clear_acl_cache != NULL)
634 clear_acl_cache(inode);
635 NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
596} 636}
597 637
598/* 638/*
@@ -689,7 +729,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
689 /* Why so? Because we want revalidate for devices/FIFOs, and 729 /* Why so? Because we want revalidate for devices/FIFOs, and
690 * that's precisely what we have in nfs_file_inode_operations. 730 * that's precisely what we have in nfs_file_inode_operations.
691 */ 731 */
692 inode->i_op = &nfs_file_inode_operations; 732 inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops;
693 if (S_ISREG(inode->i_mode)) { 733 if (S_ISREG(inode->i_mode)) {
694 inode->i_fop = &nfs_file_operations; 734 inode->i_fop = &nfs_file_operations;
695 inode->i_data.a_ops = &nfs_file_aops; 735 inode->i_data.a_ops = &nfs_file_aops;
@@ -792,7 +832,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
792 } 832 }
793 } 833 }
794 if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) 834 if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
795 NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS; 835 NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
796 nfs_end_data_update(inode); 836 nfs_end_data_update(inode);
797 unlock_kernel(); 837 unlock_kernel();
798 return error; 838 return error;
@@ -851,7 +891,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
851 ctx->state = NULL; 891 ctx->state = NULL;
852 ctx->lockowner = current->files; 892 ctx->lockowner = current->files;
853 ctx->error = 0; 893 ctx->error = 0;
854 init_waitqueue_head(&ctx->waitq); 894 ctx->dir_cookie = 0;
855 } 895 }
856 return ctx; 896 return ctx;
857} 897}
@@ -1015,6 +1055,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1015 goto out; 1055 goto out;
1016 } 1056 }
1017 flags = nfsi->flags; 1057 flags = nfsi->flags;
1058 nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE;
1018 /* 1059 /*
1019 * We may need to keep the attributes marked as invalid if 1060 * We may need to keep the attributes marked as invalid if
1020 * we raced with nfs_end_attr_update(). 1061 * we raced with nfs_end_attr_update().
@@ -1022,21 +1063,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1022 if (verifier == nfsi->cache_change_attribute) 1063 if (verifier == nfsi->cache_change_attribute)
1023 nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); 1064 nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
1024 /* Do the page cache invalidation */ 1065 /* Do the page cache invalidation */
1025 if (flags & NFS_INO_INVALID_DATA) { 1066 nfs_revalidate_mapping(inode, inode->i_mapping);
1026 if (S_ISREG(inode->i_mode)) { 1067 if (flags & NFS_INO_INVALID_ACL)
1027 if (filemap_fdatawrite(inode->i_mapping) == 0) 1068 nfs_zap_acl_cache(inode);
1028 filemap_fdatawait(inode->i_mapping);
1029 nfs_wb_all(inode);
1030 }
1031 nfsi->flags &= ~NFS_INO_INVALID_DATA;
1032 invalidate_inode_pages2(inode->i_mapping);
1033 memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
1034 dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
1035 inode->i_sb->s_id,
1036 (long long)NFS_FILEID(inode));
1037 /* This ensures we revalidate dentries */
1038 nfsi->cache_change_attribute++;
1039 }
1040 dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", 1069 dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
1041 inode->i_sb->s_id, 1070 inode->i_sb->s_id,
1042 (long long)NFS_FILEID(inode)); 1071 (long long)NFS_FILEID(inode));
@@ -1074,6 +1103,34 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1074} 1103}
1075 1104
1076/** 1105/**
1106 * nfs_revalidate_mapping - Revalidate the pagecache
1107 * @inode - pointer to host inode
1108 * @mapping - pointer to mapping
1109 */
1110void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
1111{
1112 struct nfs_inode *nfsi = NFS_I(inode);
1113
1114 if (nfsi->flags & NFS_INO_INVALID_DATA) {
1115 if (S_ISREG(inode->i_mode)) {
1116 if (filemap_fdatawrite(mapping) == 0)
1117 filemap_fdatawait(mapping);
1118 nfs_wb_all(inode);
1119 }
1120 invalidate_inode_pages2(mapping);
1121 nfsi->flags &= ~NFS_INO_INVALID_DATA;
1122 if (S_ISDIR(inode->i_mode)) {
1123 memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
1124 /* This ensures we revalidate child dentries */
1125 nfsi->cache_change_attribute++;
1126 }
1127 dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
1128 inode->i_sb->s_id,
1129 (long long)NFS_FILEID(inode));
1130 }
1131}
1132
1133/**
1077 * nfs_begin_data_update 1134 * nfs_begin_data_update
1078 * @inode - pointer to inode 1135 * @inode - pointer to inode
1079 * Declare that a set of operations will update file data on the server 1136 * Declare that a set of operations will update file data on the server
@@ -1106,27 +1163,6 @@ void nfs_end_data_update(struct inode *inode)
1106} 1163}
1107 1164
1108/** 1165/**
1109 * nfs_end_data_update_defer
1110 * @inode - pointer to inode
1111 * Declare end of the operations that will update file data
1112 * This will defer marking the inode as needing revalidation
1113 * unless there are no other pending updates.
1114 */
1115void nfs_end_data_update_defer(struct inode *inode)
1116{
1117 struct nfs_inode *nfsi = NFS_I(inode);
1118
1119 if (atomic_dec_and_test(&nfsi->data_updates)) {
1120 /* Mark the attribute cache for revalidation */
1121 nfsi->flags |= NFS_INO_INVALID_ATTR;
1122 /* Directories and symlinks: invalidate page cache too */
1123 if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
1124 nfsi->flags |= NFS_INO_INVALID_DATA;
1125 nfsi->cache_change_attribute ++;
1126 }
1127}
1128
1129/**
1130 * nfs_refresh_inode - verify consistency of the inode attribute cache 1166 * nfs_refresh_inode - verify consistency of the inode attribute cache
1131 * @inode - pointer to inode 1167 * @inode - pointer to inode
1132 * @fattr - updated attributes 1168 * @fattr - updated attributes
@@ -1152,8 +1188,11 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1152 if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0 1188 if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
1153 && nfsi->change_attr == fattr->pre_change_attr) 1189 && nfsi->change_attr == fattr->pre_change_attr)
1154 nfsi->change_attr = fattr->change_attr; 1190 nfsi->change_attr = fattr->change_attr;
1155 if (!data_unstable && nfsi->change_attr != fattr->change_attr) 1191 if (nfsi->change_attr != fattr->change_attr) {
1156 nfsi->flags |= NFS_INO_INVALID_ATTR; 1192 nfsi->flags |= NFS_INO_INVALID_ATTR;
1193 if (!data_unstable)
1194 nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
1195 }
1157 } 1196 }
1158 1197
1159 if ((fattr->valid & NFS_ATTR_FATTR) == 0) 1198 if ((fattr->valid & NFS_ATTR_FATTR) == 0)
@@ -1176,18 +1215,22 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1176 } 1215 }
1177 1216
1178 /* Verify a few of the more important attributes */ 1217 /* Verify a few of the more important attributes */
1179 if (!data_unstable) { 1218 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
1180 if (!timespec_equal(&inode->i_mtime, &fattr->mtime) 1219 nfsi->flags |= NFS_INO_INVALID_ATTR;
1181 || cur_size != new_isize) 1220 if (!data_unstable)
1182 nfsi->flags |= NFS_INO_INVALID_ATTR; 1221 nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
1183 } else if (S_ISREG(inode->i_mode) && new_isize > cur_size) 1222 }
1184 nfsi->flags |= NFS_INO_INVALID_ATTR; 1223 if (cur_size != new_isize) {
1224 nfsi->flags |= NFS_INO_INVALID_ATTR;
1225 if (nfsi->npages == 0)
1226 nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
1227 }
1185 1228
1186 /* Have any file permissions changed? */ 1229 /* Have any file permissions changed? */
1187 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) 1230 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
1188 || inode->i_uid != fattr->uid 1231 || inode->i_uid != fattr->uid
1189 || inode->i_gid != fattr->gid) 1232 || inode->i_gid != fattr->gid)
1190 nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; 1233 nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
1191 1234
1192 /* Has the link count changed? */ 1235 /* Has the link count changed? */
1193 if (inode->i_nlink != fattr->nlink) 1236 if (inode->i_nlink != fattr->nlink)
@@ -1215,10 +1258,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1215static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) 1258static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier)
1216{ 1259{
1217 struct nfs_inode *nfsi = NFS_I(inode); 1260 struct nfs_inode *nfsi = NFS_I(inode);
1218 __u64 new_size; 1261 loff_t cur_isize, new_isize;
1219 loff_t new_isize;
1220 unsigned int invalid = 0; 1262 unsigned int invalid = 0;
1221 loff_t cur_isize;
1222 int data_unstable; 1263 int data_unstable;
1223 1264
1224 dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", 1265 dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
@@ -1251,61 +1292,56 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1251 /* Are we racing with known updates of the metadata on the server? */ 1292 /* Are we racing with known updates of the metadata on the server? */
1252 data_unstable = ! nfs_verify_change_attribute(inode, verifier); 1293 data_unstable = ! nfs_verify_change_attribute(inode, verifier);
1253 1294
1254 /* Check if the file size agrees */ 1295 /* Check if our cached file size is stale */
1255 new_size = fattr->size;
1256 new_isize = nfs_size_to_loff_t(fattr->size); 1296 new_isize = nfs_size_to_loff_t(fattr->size);
1257 cur_isize = i_size_read(inode); 1297 cur_isize = i_size_read(inode);
1258 if (cur_isize != new_size) { 1298 if (new_isize != cur_isize) {
1259#ifdef NFS_DEBUG_VERBOSE 1299 /* Do we perhaps have any outstanding writes? */
1260 printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); 1300 if (nfsi->npages == 0) {
1261#endif 1301 /* No, but did we race with nfs_end_data_update()? */
1262 /* 1302 if (verifier == nfsi->cache_change_attribute) {
1263 * If we have pending writebacks, things can get
1264 * messy.
1265 */
1266 if (S_ISREG(inode->i_mode) && data_unstable) {
1267 if (new_isize > cur_isize) {
1268 inode->i_size = new_isize; 1303 inode->i_size = new_isize;
1269 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1304 invalid |= NFS_INO_INVALID_DATA;
1270 } 1305 }
1271 } else { 1306 invalid |= NFS_INO_INVALID_ATTR;
1307 } else if (new_isize > cur_isize) {
1272 inode->i_size = new_isize; 1308 inode->i_size = new_isize;
1273 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1309 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
1274 } 1310 }
1311 dprintk("NFS: isize change on server for file %s/%ld\n",
1312 inode->i_sb->s_id, inode->i_ino);
1275 } 1313 }
1276 1314
1277 /* 1315 /* Check if the mtime agrees */
1278 * Note: we don't check inode->i_mtime since pipes etc.
1279 * can change this value in VFS without requiring a
1280 * cache revalidation.
1281 */
1282 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { 1316 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
1283 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); 1317 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
1284#ifdef NFS_DEBUG_VERBOSE 1318 dprintk("NFS: mtime change on server for file %s/%ld\n",
1285 printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); 1319 inode->i_sb->s_id, inode->i_ino);
1286#endif
1287 if (!data_unstable) 1320 if (!data_unstable)
1288 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1321 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
1289 } 1322 }
1290 1323
1291 if ((fattr->valid & NFS_ATTR_FATTR_V4) 1324 if ((fattr->valid & NFS_ATTR_FATTR_V4)
1292 && nfsi->change_attr != fattr->change_attr) { 1325 && nfsi->change_attr != fattr->change_attr) {
1293#ifdef NFS_DEBUG_VERBOSE 1326 dprintk("NFS: change_attr change on server for file %s/%ld\n",
1294 printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",
1295 inode->i_sb->s_id, inode->i_ino); 1327 inode->i_sb->s_id, inode->i_ino);
1296#endif
1297 nfsi->change_attr = fattr->change_attr; 1328 nfsi->change_attr = fattr->change_attr;
1298 if (!data_unstable) 1329 if (!data_unstable)
1299 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS; 1330 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1300 } 1331 }
1301 1332
1302 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); 1333 /* If ctime has changed we should definitely clear access+acl caches */
1334 if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
1335 if (!data_unstable)
1336 invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1337 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
1338 }
1303 memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); 1339 memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
1304 1340
1305 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || 1341 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||
1306 inode->i_uid != fattr->uid || 1342 inode->i_uid != fattr->uid ||
1307 inode->i_gid != fattr->gid) 1343 inode->i_gid != fattr->gid)
1308 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS; 1344 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1309 1345
1310 inode->i_mode = fattr->mode; 1346 inode->i_mode = fattr->mode;
1311 inode->i_nlink = fattr->nlink; 1347 inode->i_nlink = fattr->nlink;
@@ -1385,74 +1421,95 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1385 int flags, const char *dev_name, void *raw_data) 1421 int flags, const char *dev_name, void *raw_data)
1386{ 1422{
1387 int error; 1423 int error;
1388 struct nfs_server *server; 1424 struct nfs_server *server = NULL;
1389 struct super_block *s; 1425 struct super_block *s;
1390 struct nfs_fh *root; 1426 struct nfs_fh *root;
1391 struct nfs_mount_data *data = raw_data; 1427 struct nfs_mount_data *data = raw_data;
1392 1428
1393 if (!data) { 1429 s = ERR_PTR(-EINVAL);
1394 printk("nfs_read_super: missing data argument\n"); 1430 if (data == NULL) {
1395 return ERR_PTR(-EINVAL); 1431 dprintk("%s: missing data argument\n", __FUNCTION__);
1432 goto out_err;
1433 }
1434 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
1435 dprintk("%s: bad mount version\n", __FUNCTION__);
1436 goto out_err;
1396 } 1437 }
1438 switch (data->version) {
1439 case 1:
1440 data->namlen = 0;
1441 case 2:
1442 data->bsize = 0;
1443 case 3:
1444 if (data->flags & NFS_MOUNT_VER3) {
1445 dprintk("%s: mount structure version %d does not support NFSv3\n",
1446 __FUNCTION__,
1447 data->version);
1448 goto out_err;
1449 }
1450 data->root.size = NFS2_FHSIZE;
1451 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
1452 case 4:
1453 if (data->flags & NFS_MOUNT_SECFLAVOUR) {
1454 dprintk("%s: mount structure version %d does not support strong security\n",
1455 __FUNCTION__,
1456 data->version);
1457 goto out_err;
1458 }
1459 case 5:
1460 memset(data->context, 0, sizeof(data->context));
1461 }
1462#ifndef CONFIG_NFS_V3
1463 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
1464 s = ERR_PTR(-EPROTONOSUPPORT);
1465 if (data->flags & NFS_MOUNT_VER3) {
1466 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
1467 goto out_err;
1468 }
1469#endif /* CONFIG_NFS_V3 */
1397 1470
1471 s = ERR_PTR(-ENOMEM);
1398 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); 1472 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
1399 if (!server) 1473 if (!server)
1400 return ERR_PTR(-ENOMEM); 1474 goto out_err;
1401 memset(server, 0, sizeof(struct nfs_server)); 1475 memset(server, 0, sizeof(struct nfs_server));
1402 /* Zero out the NFS state stuff */ 1476 /* Zero out the NFS state stuff */
1403 init_nfsv4_state(server); 1477 init_nfsv4_state(server);
1404 1478 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
1405 if (data->version != NFS_MOUNT_VERSION) {
1406 printk("nfs warning: mount version %s than kernel\n",
1407 data->version < NFS_MOUNT_VERSION ? "older" : "newer");
1408 if (data->version < 2)
1409 data->namlen = 0;
1410 if (data->version < 3)
1411 data->bsize = 0;
1412 if (data->version < 4) {
1413 data->flags &= ~NFS_MOUNT_VER3;
1414 data->root.size = NFS2_FHSIZE;
1415 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
1416 }
1417 if (data->version < 5)
1418 data->flags &= ~NFS_MOUNT_SECFLAVOUR;
1419 }
1420 1479
1421 root = &server->fh; 1480 root = &server->fh;
1422 if (data->flags & NFS_MOUNT_VER3) 1481 if (data->flags & NFS_MOUNT_VER3)
1423 root->size = data->root.size; 1482 root->size = data->root.size;
1424 else 1483 else
1425 root->size = NFS2_FHSIZE; 1484 root->size = NFS2_FHSIZE;
1485 s = ERR_PTR(-EINVAL);
1426 if (root->size > sizeof(root->data)) { 1486 if (root->size > sizeof(root->data)) {
1427 printk("nfs_get_sb: invalid root filehandle\n"); 1487 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
1428 kfree(server); 1488 goto out_err;
1429 return ERR_PTR(-EINVAL);
1430 } 1489 }
1431 memcpy(root->data, data->root.data, root->size); 1490 memcpy(root->data, data->root.data, root->size);
1432 1491
1433 /* We now require that the mount process passes the remote address */ 1492 /* We now require that the mount process passes the remote address */
1434 memcpy(&server->addr, &data->addr, sizeof(server->addr)); 1493 memcpy(&server->addr, &data->addr, sizeof(server->addr));
1435 if (server->addr.sin_addr.s_addr == INADDR_ANY) { 1494 if (server->addr.sin_addr.s_addr == INADDR_ANY) {
1436 printk("NFS: mount program didn't pass remote address!\n"); 1495 dprintk("%s: mount program didn't pass remote address!\n",
1437 kfree(server); 1496 __FUNCTION__);
1438 return ERR_PTR(-EINVAL); 1497 goto out_err;
1439 } 1498 }
1440 1499
1441 s = sget(fs_type, nfs_compare_super, nfs_set_super, server); 1500 /* Fire up rpciod if not yet running */
1442 1501 s = ERR_PTR(rpciod_up());
1443 if (IS_ERR(s) || s->s_root) { 1502 if (IS_ERR(s)) {
1444 kfree(server); 1503 dprintk("%s: couldn't start rpciod! Error = %ld\n",
1445 return s; 1504 __FUNCTION__, PTR_ERR(s));
1505 goto out_err;
1446 } 1506 }
1447 1507
1448 s->s_flags = flags; 1508 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
1509 if (IS_ERR(s) || s->s_root)
1510 goto out_rpciod_down;
1449 1511
1450 /* Fire up rpciod if not yet running */ 1512 s->s_flags = flags;
1451 if (rpciod_up() != 0) {
1452 printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
1453 kfree(server);
1454 return ERR_PTR(-EIO);
1455 }
1456 1513
1457 error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); 1514 error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
1458 if (error) { 1515 if (error) {
@@ -1462,6 +1519,11 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
1462 } 1519 }
1463 s->s_flags |= MS_ACTIVE; 1520 s->s_flags |= MS_ACTIVE;
1464 return s; 1521 return s;
1522out_rpciod_down:
1523 rpciod_down();
1524out_err:
1525 kfree(server);
1526 return s;
1465} 1527}
1466 1528
1467static void nfs_kill_super(struct super_block *s) 1529static void nfs_kill_super(struct super_block *s)
@@ -1470,10 +1532,12 @@ static void nfs_kill_super(struct super_block *s)
1470 1532
1471 kill_anon_super(s); 1533 kill_anon_super(s);
1472 1534
1473 if (server->client != NULL && !IS_ERR(server->client)) 1535 if (!IS_ERR(server->client))
1474 rpc_shutdown_client(server->client); 1536 rpc_shutdown_client(server->client);
1475 if (server->client_sys != NULL && !IS_ERR(server->client_sys)) 1537 if (!IS_ERR(server->client_sys))
1476 rpc_shutdown_client(server->client_sys); 1538 rpc_shutdown_client(server->client_sys);
1539 if (!IS_ERR(server->client_acl))
1540 rpc_shutdown_client(server->client_acl);
1477 1541
1478 if (!(server->flags & NFS_MOUNT_NONLM)) 1542 if (!(server->flags & NFS_MOUNT_NONLM))
1479 lockd_down(); /* release rpc.lockd */ 1543 lockd_down(); /* release rpc.lockd */
@@ -1594,15 +1658,19 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
1594 1658
1595 clp = nfs4_get_client(&server->addr.sin_addr); 1659 clp = nfs4_get_client(&server->addr.sin_addr);
1596 if (!clp) { 1660 if (!clp) {
1597 printk(KERN_WARNING "NFS: failed to create NFS4 client.\n"); 1661 dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
1598 return -EIO; 1662 return -EIO;
1599 } 1663 }
1600 1664
1601 /* Now create transport and client */ 1665 /* Now create transport and client */
1602 authflavour = RPC_AUTH_UNIX; 1666 authflavour = RPC_AUTH_UNIX;
1603 if (data->auth_flavourlen != 0) { 1667 if (data->auth_flavourlen != 0) {
1604 if (data->auth_flavourlen > 1) 1668 if (data->auth_flavourlen != 1) {
1605 printk(KERN_INFO "NFS: cannot yet deal with multiple auth flavours.\n"); 1669 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
1670 __FUNCTION__, data->auth_flavourlen);
1671 err = -EINVAL;
1672 goto out_fail;
1673 }
1606 if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { 1674 if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
1607 err = -EFAULT; 1675 err = -EFAULT;
1608 goto out_fail; 1676 goto out_fail;
@@ -1610,21 +1678,22 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
1610 } 1678 }
1611 1679
1612 down_write(&clp->cl_sem); 1680 down_write(&clp->cl_sem);
1613 if (clp->cl_rpcclient == NULL) { 1681 if (IS_ERR(clp->cl_rpcclient)) {
1614 xprt = xprt_create_proto(proto, &server->addr, &timeparms); 1682 xprt = xprt_create_proto(proto, &server->addr, &timeparms);
1615 if (IS_ERR(xprt)) { 1683 if (IS_ERR(xprt)) {
1616 up_write(&clp->cl_sem); 1684 up_write(&clp->cl_sem);
1617 printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
1618 err = PTR_ERR(xprt); 1685 err = PTR_ERR(xprt);
1686 dprintk("%s: cannot create RPC transport. Error = %d\n",
1687 __FUNCTION__, err);
1619 goto out_fail; 1688 goto out_fail;
1620 } 1689 }
1621 clnt = rpc_create_client(xprt, server->hostname, &nfs_program, 1690 clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
1622 server->rpc_ops->version, authflavour); 1691 server->rpc_ops->version, authflavour);
1623 if (IS_ERR(clnt)) { 1692 if (IS_ERR(clnt)) {
1624 up_write(&clp->cl_sem); 1693 up_write(&clp->cl_sem);
1625 printk(KERN_WARNING "NFS: cannot create RPC client.\n");
1626 xprt_destroy(xprt);
1627 err = PTR_ERR(clnt); 1694 err = PTR_ERR(clnt);
1695 dprintk("%s: cannot create RPC client. Error = %d\n",
1696 __FUNCTION__, err);
1628 goto out_fail; 1697 goto out_fail;
1629 } 1698 }
1630 clnt->cl_intr = 1; 1699 clnt->cl_intr = 1;
@@ -1656,21 +1725,26 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
1656 clp = NULL; 1725 clp = NULL;
1657 1726
1658 if (IS_ERR(clnt)) { 1727 if (IS_ERR(clnt)) {
1659 printk(KERN_WARNING "NFS: cannot create RPC client.\n"); 1728 err = PTR_ERR(clnt);
1660 return PTR_ERR(clnt); 1729 dprintk("%s: cannot create RPC client. Error = %d\n",
1730 __FUNCTION__, err);
1731 return err;
1661 } 1732 }
1662 1733
1663 server->client = clnt; 1734 server->client = clnt;
1664 1735
1665 if (server->nfs4_state->cl_idmap == NULL) { 1736 if (server->nfs4_state->cl_idmap == NULL) {
1666 printk(KERN_WARNING "NFS: failed to create idmapper.\n"); 1737 dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
1667 return -ENOMEM; 1738 return -ENOMEM;
1668 } 1739 }
1669 1740
1670 if (clnt->cl_auth->au_flavor != authflavour) { 1741 if (clnt->cl_auth->au_flavor != authflavour) {
1671 if (rpcauth_create(authflavour, clnt) == NULL) { 1742 struct rpc_auth *auth;
1672 printk(KERN_WARNING "NFS: couldn't create credcache!\n"); 1743
1673 return -ENOMEM; 1744 auth = rpcauth_create(authflavour, clnt);
1745 if (IS_ERR(auth)) {
1746 dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
1747 return PTR_ERR(auth);
1674 } 1748 }
1675 } 1749 }
1676 1750
@@ -1730,8 +1804,12 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1730 struct nfs4_mount_data *data = raw_data; 1804 struct nfs4_mount_data *data = raw_data;
1731 void *p; 1805 void *p;
1732 1806
1733 if (!data) { 1807 if (data == NULL) {
1734 printk("nfs_read_super: missing data argument\n"); 1808 dprintk("%s: missing data argument\n", __FUNCTION__);
1809 return ERR_PTR(-EINVAL);
1810 }
1811 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
1812 dprintk("%s: bad mount version\n", __FUNCTION__);
1735 return ERR_PTR(-EINVAL); 1813 return ERR_PTR(-EINVAL);
1736 } 1814 }
1737 1815
@@ -1741,11 +1819,7 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1741 memset(server, 0, sizeof(struct nfs_server)); 1819 memset(server, 0, sizeof(struct nfs_server));
1742 /* Zero out the NFS state stuff */ 1820 /* Zero out the NFS state stuff */
1743 init_nfsv4_state(server); 1821 init_nfsv4_state(server);
1744 1822 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
1745 if (data->version != NFS4_MOUNT_VERSION) {
1746 printk("nfs warning: mount version %s than kernel\n",
1747 data->version < NFS4_MOUNT_VERSION ? "older" : "newer");
1748 }
1749 1823
1750 p = nfs_copy_user_string(NULL, &data->hostname, 256); 1824 p = nfs_copy_user_string(NULL, &data->hostname, 256);
1751 if (IS_ERR(p)) 1825 if (IS_ERR(p))
@@ -1773,11 +1847,20 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1773 } 1847 }
1774 if (server->addr.sin_family != AF_INET || 1848 if (server->addr.sin_family != AF_INET ||
1775 server->addr.sin_addr.s_addr == INADDR_ANY) { 1849 server->addr.sin_addr.s_addr == INADDR_ANY) {
1776 printk("NFS: mount program didn't pass remote IP address!\n"); 1850 dprintk("%s: mount program didn't pass remote IP address!\n",
1851 __FUNCTION__);
1777 s = ERR_PTR(-EINVAL); 1852 s = ERR_PTR(-EINVAL);
1778 goto out_free; 1853 goto out_free;
1779 } 1854 }
1780 1855
1856 /* Fire up rpciod if not yet running */
1857 s = ERR_PTR(rpciod_up());
1858 if (IS_ERR(s)) {
1859 dprintk("%s: couldn't start rpciod! Error = %ld\n",
1860 __FUNCTION__, PTR_ERR(s));
1861 goto out_free;
1862 }
1863
1781 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); 1864 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
1782 1865
1783 if (IS_ERR(s) || s->s_root) 1866 if (IS_ERR(s) || s->s_root)
@@ -1785,13 +1868,6 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1785 1868
1786 s->s_flags = flags; 1869 s->s_flags = flags;
1787 1870
1788 /* Fire up rpciod if not yet running */
1789 if (rpciod_up() != 0) {
1790 printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
1791 s = ERR_PTR(-EIO);
1792 goto out_free;
1793 }
1794
1795 error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); 1871 error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
1796 if (error) { 1872 if (error) {
1797 up_write(&s->s_umount); 1873 up_write(&s->s_umount);
@@ -1875,6 +1951,13 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
1875 if (!nfsi) 1951 if (!nfsi)
1876 return NULL; 1952 return NULL;
1877 nfsi->flags = 0; 1953 nfsi->flags = 0;
1954#ifdef CONFIG_NFS_V3_ACL
1955 nfsi->acl_access = ERR_PTR(-EAGAIN);
1956 nfsi->acl_default = ERR_PTR(-EAGAIN);
1957#endif
1958#ifdef CONFIG_NFS_V4
1959 nfsi->nfs4_acl = NULL;
1960#endif /* CONFIG_NFS_V4 */
1878 return &nfsi->vfs_inode; 1961 return &nfsi->vfs_inode;
1879} 1962}
1880 1963
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 9d3ddad96d9e..0e82617f2de0 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -80,9 +80,7 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
80 clnt = rpc_create_client(xprt, hostname, 80 clnt = rpc_create_client(xprt, hostname,
81 &mnt_program, version, 81 &mnt_program, version,
82 RPC_AUTH_UNIX); 82 RPC_AUTH_UNIX);
83 if (IS_ERR(clnt)) { 83 if (!IS_ERR(clnt)) {
84 xprt_destroy(xprt);
85 } else {
86 clnt->cl_softrtry = 1; 84 clnt->cl_softrtry = 1;
87 clnt->cl_chatty = 1; 85 clnt->cl_chatty = 1;
88 clnt->cl_oneshot = 1; 86 clnt->cl_oneshot = 1;
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
new file mode 100644
index 000000000000..ee3536fc84a3
--- /dev/null
+++ b/fs/nfs/nfs3acl.c
@@ -0,0 +1,403 @@
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#include <linux/nfsacl.h>
7
8#define NFSDBG_FACILITY NFSDBG_PROC
9
10ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
11{
12 struct inode *inode = dentry->d_inode;
13 struct posix_acl *acl;
14 int pos=0, len=0;
15
16# define output(s) do { \
17 if (pos + sizeof(s) <= size) { \
18 memcpy(buffer + pos, s, sizeof(s)); \
19 pos += sizeof(s); \
20 } \
21 len += sizeof(s); \
22 } while(0)
23
24 acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
25 if (IS_ERR(acl))
26 return PTR_ERR(acl);
27 if (acl) {
28 output("system.posix_acl_access");
29 posix_acl_release(acl);
30 }
31
32 if (S_ISDIR(inode->i_mode)) {
33 acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
34 if (IS_ERR(acl))
35 return PTR_ERR(acl);
36 if (acl) {
37 output("system.posix_acl_default");
38 posix_acl_release(acl);
39 }
40 }
41
42# undef output
43
44 if (!buffer || len <= size)
45 return len;
46 return -ERANGE;
47}
48
49ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
50 void *buffer, size_t size)
51{
52 struct inode *inode = dentry->d_inode;
53 struct posix_acl *acl;
54 int type, error = 0;
55
56 if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
57 type = ACL_TYPE_ACCESS;
58 else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
59 type = ACL_TYPE_DEFAULT;
60 else
61 return -EOPNOTSUPP;
62
63 acl = nfs3_proc_getacl(inode, type);
64 if (IS_ERR(acl))
65 return PTR_ERR(acl);
66 else if (acl) {
67 if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
68 error = -ENODATA;
69 else
70 error = posix_acl_to_xattr(acl, buffer, size);
71 posix_acl_release(acl);
72 } else
73 error = -ENODATA;
74
75 return error;
76}
77
78int nfs3_setxattr(struct dentry *dentry, const char *name,
79 const void *value, size_t size, int flags)
80{
81 struct inode *inode = dentry->d_inode;
82 struct posix_acl *acl;
83 int type, error;
84
85 if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
86 type = ACL_TYPE_ACCESS;
87 else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
88 type = ACL_TYPE_DEFAULT;
89 else
90 return -EOPNOTSUPP;
91
92 acl = posix_acl_from_xattr(value, size);
93 if (IS_ERR(acl))
94 return PTR_ERR(acl);
95 error = nfs3_proc_setacl(inode, type, acl);
96 posix_acl_release(acl);
97
98 return error;
99}
100
101int nfs3_removexattr(struct dentry *dentry, const char *name)
102{
103 struct inode *inode = dentry->d_inode;
104 int type;
105
106 if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
107 type = ACL_TYPE_ACCESS;
108 else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
109 type = ACL_TYPE_DEFAULT;
110 else
111 return -EOPNOTSUPP;
112
113 return nfs3_proc_setacl(inode, type, NULL);
114}
115
116static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
117{
118 if (!IS_ERR(nfsi->acl_access)) {
119 posix_acl_release(nfsi->acl_access);
120 nfsi->acl_access = ERR_PTR(-EAGAIN);
121 }
122 if (!IS_ERR(nfsi->acl_default)) {
123 posix_acl_release(nfsi->acl_default);
124 nfsi->acl_default = ERR_PTR(-EAGAIN);
125 }
126}
127
128void nfs3_forget_cached_acls(struct inode *inode)
129{
130 dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
131 inode->i_ino);
132 spin_lock(&inode->i_lock);
133 __nfs3_forget_cached_acls(NFS_I(inode));
134 spin_unlock(&inode->i_lock);
135}
136
137static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
138{
139 struct nfs_inode *nfsi = NFS_I(inode);
140 struct posix_acl *acl = ERR_PTR(-EINVAL);
141
142 spin_lock(&inode->i_lock);
143 switch(type) {
144 case ACL_TYPE_ACCESS:
145 acl = nfsi->acl_access;
146 break;
147
148 case ACL_TYPE_DEFAULT:
149 acl = nfsi->acl_default;
150 break;
151
152 default:
153 goto out;
154 }
155 if (IS_ERR(acl))
156 acl = ERR_PTR(-EAGAIN);
157 else
158 acl = posix_acl_dup(acl);
159out:
160 spin_unlock(&inode->i_lock);
161 dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
162 inode->i_ino, type, acl);
163 return acl;
164}
165
166static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
167 struct posix_acl *dfacl)
168{
169 struct nfs_inode *nfsi = NFS_I(inode);
170
171 dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
172 inode->i_ino, acl, dfacl);
173 spin_lock(&inode->i_lock);
174 __nfs3_forget_cached_acls(NFS_I(inode));
175 nfsi->acl_access = posix_acl_dup(acl);
176 nfsi->acl_default = posix_acl_dup(dfacl);
177 spin_unlock(&inode->i_lock);
178}
179
180struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
181{
182 struct nfs_server *server = NFS_SERVER(inode);
183 struct nfs_fattr fattr;
184 struct page *pages[NFSACL_MAXPAGES] = { };
185 struct nfs3_getaclargs args = {
186 .fh = NFS_FH(inode),
187 /* The xdr layer may allocate pages here. */
188 .pages = pages,
189 };
190 struct nfs3_getaclres res = {
191 .fattr = &fattr,
192 };
193 struct posix_acl *acl;
194 int status, count;
195
196 if (!nfs_server_capable(inode, NFS_CAP_ACLS))
197 return ERR_PTR(-EOPNOTSUPP);
198
199 status = nfs_revalidate_inode(server, inode);
200 if (status < 0)
201 return ERR_PTR(status);
202 acl = nfs3_get_cached_acl(inode, type);
203 if (acl != ERR_PTR(-EAGAIN))
204 return acl;
205 acl = NULL;
206
207 /*
208 * Only get the access acl when explicitly requested: We don't
209 * need it for access decisions, and only some applications use
210 * it. Applications which request the access acl first are not
211 * penalized from this optimization.
212 */
213 if (type == ACL_TYPE_ACCESS)
214 args.mask |= NFS_ACLCNT|NFS_ACL;
215 if (S_ISDIR(inode->i_mode))
216 args.mask |= NFS_DFACLCNT|NFS_DFACL;
217 if (args.mask == 0)
218 return NULL;
219
220 dprintk("NFS call getacl\n");
221 status = rpc_call(server->client_acl, ACLPROC3_GETACL,
222 &args, &res, 0);
223 dprintk("NFS reply getacl: %d\n", status);
224
225 /* pages may have been allocated at the xdr layer. */
226 for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
227 __free_page(args.pages[count]);
228
229 switch (status) {
230 case 0:
231 status = nfs_refresh_inode(inode, &fattr);
232 break;
233 case -EPFNOSUPPORT:
234 case -EPROTONOSUPPORT:
235 dprintk("NFS_V3_ACL extension not supported; disabling\n");
236 server->caps &= ~NFS_CAP_ACLS;
237 case -ENOTSUPP:
238 status = -EOPNOTSUPP;
239 default:
240 goto getout;
241 }
242 if ((args.mask & res.mask) != args.mask) {
243 status = -EIO;
244 goto getout;
245 }
246
247 if (res.acl_access != NULL) {
248 if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) {
249 posix_acl_release(res.acl_access);
250 res.acl_access = NULL;
251 }
252 }
253 nfs3_cache_acls(inode, res.acl_access, res.acl_default);
254
255 switch(type) {
256 case ACL_TYPE_ACCESS:
257 acl = res.acl_access;
258 res.acl_access = NULL;
259 break;
260
261 case ACL_TYPE_DEFAULT:
262 acl = res.acl_default;
263 res.acl_default = NULL;
264 }
265
266getout:
267 posix_acl_release(res.acl_access);
268 posix_acl_release(res.acl_default);
269
270 if (status != 0) {
271 posix_acl_release(acl);
272 acl = ERR_PTR(status);
273 }
274 return acl;
275}
276
277static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
278 struct posix_acl *dfacl)
279{
280 struct nfs_server *server = NFS_SERVER(inode);
281 struct nfs_fattr fattr;
282 struct page *pages[NFSACL_MAXPAGES] = { };
283 struct nfs3_setaclargs args = {
284 .inode = inode,
285 .mask = NFS_ACL,
286 .acl_access = acl,
287 .pages = pages,
288 };
289 int status, count;
290
291 status = -EOPNOTSUPP;
292 if (!nfs_server_capable(inode, NFS_CAP_ACLS))
293 goto out;
294
295 /* We are doing this here, because XDR marshalling can only
296 return -ENOMEM. */
297 status = -ENOSPC;
298 if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
299 goto out;
300 if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES)
301 goto out;
302 if (S_ISDIR(inode->i_mode)) {
303 args.mask |= NFS_DFACL;
304 args.acl_default = dfacl;
305 }
306
307 dprintk("NFS call setacl\n");
308 nfs_begin_data_update(inode);
309 status = rpc_call(server->client_acl, ACLPROC3_SETACL,
310 &args, &fattr, 0);
311 NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
312 nfs_end_data_update(inode);
313 dprintk("NFS reply setacl: %d\n", status);
314
315 /* pages may have been allocated at the xdr layer. */
316 for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
317 __free_page(args.pages[count]);
318
319 switch (status) {
320 case 0:
321 status = nfs_refresh_inode(inode, &fattr);
322 break;
323 case -EPFNOSUPPORT:
324 case -EPROTONOSUPPORT:
325 dprintk("NFS_V3_ACL SETACL RPC not supported"
326 "(will not retry)\n");
327 server->caps &= ~NFS_CAP_ACLS;
328 case -ENOTSUPP:
329 status = -EOPNOTSUPP;
330 }
331out:
332 return status;
333}
334
335int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
336{
337 struct posix_acl *alloc = NULL, *dfacl = NULL;
338 int status;
339
340 if (S_ISDIR(inode->i_mode)) {
341 switch(type) {
342 case ACL_TYPE_ACCESS:
343 alloc = dfacl = nfs3_proc_getacl(inode,
344 ACL_TYPE_DEFAULT);
345 if (IS_ERR(alloc))
346 goto fail;
347 break;
348
349 case ACL_TYPE_DEFAULT:
350 dfacl = acl;
351 alloc = acl = nfs3_proc_getacl(inode,
352 ACL_TYPE_ACCESS);
353 if (IS_ERR(alloc))
354 goto fail;
355 break;
356
357 default:
358 return -EINVAL;
359 }
360 } else if (type != ACL_TYPE_ACCESS)
361 return -EINVAL;
362
363 if (acl == NULL) {
364 alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
365 if (IS_ERR(alloc))
366 goto fail;
367 }
368 status = nfs3_proc_setacls(inode, acl, dfacl);
369 posix_acl_release(alloc);
370 return status;
371
372fail:
373 return PTR_ERR(alloc);
374}
375
376int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
377 mode_t mode)
378{
379 struct posix_acl *dfacl, *acl;
380 int error = 0;
381
382 dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT);
383 if (IS_ERR(dfacl)) {
384 error = PTR_ERR(dfacl);
385 return (error == -EOPNOTSUPP) ? 0 : error;
386 }
387 if (!dfacl)
388 return 0;
389 acl = posix_acl_clone(dfacl, GFP_KERNEL);
390 error = -ENOMEM;
391 if (!acl)
392 goto out_release_dfacl;
393 error = posix_acl_create_masq(acl, &mode);
394 if (error < 0)
395 goto out_release_acl;
396 error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
397 dfacl : NULL);
398out_release_acl:
399 posix_acl_release(acl);
400out_release_dfacl:
401 posix_acl_release(dfacl);
402 return error;
403}
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 3878494dfc2c..7851569b31c6 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -17,6 +17,7 @@
17#include <linux/nfs_page.h> 17#include <linux/nfs_page.h>
18#include <linux/lockd/bind.h> 18#include <linux/lockd/bind.h>
19#include <linux/smp_lock.h> 19#include <linux/smp_lock.h>
20#include <linux/nfs_mount.h>
20 21
21#define NFSDBG_FACILITY NFSDBG_PROC 22#define NFSDBG_FACILITY NFSDBG_PROC
22 23
@@ -45,7 +46,7 @@ static inline int
45nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags) 46nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
46{ 47{
47 struct rpc_message msg = { 48 struct rpc_message msg = {
48 .rpc_proc = &nfs3_procedures[proc], 49 .rpc_proc = &clnt->cl_procinfo[proc],
49 .rpc_argp = argp, 50 .rpc_argp = argp,
50 .rpc_resp = resp, 51 .rpc_resp = resp,
51 }; 52 };
@@ -313,7 +314,8 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
313 .fh = &fhandle, 314 .fh = &fhandle,
314 .fattr = &fattr 315 .fattr = &fattr
315 }; 316 };
316 int status; 317 mode_t mode = sattr->ia_mode;
318 int status;
317 319
318 dprintk("NFS call create %s\n", dentry->d_name.name); 320 dprintk("NFS call create %s\n", dentry->d_name.name);
319 arg.createmode = NFS3_CREATE_UNCHECKED; 321 arg.createmode = NFS3_CREATE_UNCHECKED;
@@ -323,6 +325,8 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
323 arg.verifier[1] = current->pid; 325 arg.verifier[1] = current->pid;
324 } 326 }
325 327
328 sattr->ia_mode &= ~current->fs->umask;
329
326again: 330again:
327 dir_attr.valid = 0; 331 dir_attr.valid = 0;
328 fattr.valid = 0; 332 fattr.valid = 0;
@@ -369,6 +373,9 @@ again:
369 nfs_refresh_inode(dentry->d_inode, &fattr); 373 nfs_refresh_inode(dentry->d_inode, &fattr);
370 dprintk("NFS reply setattr (post-create): %d\n", status); 374 dprintk("NFS reply setattr (post-create): %d\n", status);
371 } 375 }
376 if (status != 0)
377 goto out;
378 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
372out: 379out:
373 dprintk("NFS reply create: %d\n", status); 380 dprintk("NFS reply create: %d\n", status);
374 return status; 381 return status;
@@ -538,15 +545,24 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
538 .fh = &fhandle, 545 .fh = &fhandle,
539 .fattr = &fattr 546 .fattr = &fattr
540 }; 547 };
541 int status; 548 int mode = sattr->ia_mode;
549 int status;
542 550
543 dprintk("NFS call mkdir %s\n", dentry->d_name.name); 551 dprintk("NFS call mkdir %s\n", dentry->d_name.name);
544 dir_attr.valid = 0; 552 dir_attr.valid = 0;
545 fattr.valid = 0; 553 fattr.valid = 0;
554
555 sattr->ia_mode &= ~current->fs->umask;
556
546 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0); 557 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
547 nfs_refresh_inode(dir, &dir_attr); 558 nfs_refresh_inode(dir, &dir_attr);
548 if (status == 0) 559 if (status != 0)
549 status = nfs_instantiate(dentry, &fhandle, &fattr); 560 goto out;
561 status = nfs_instantiate(dentry, &fhandle, &fattr);
562 if (status != 0)
563 goto out;
564 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
565out:
550 dprintk("NFS reply mkdir: %d\n", status); 566 dprintk("NFS reply mkdir: %d\n", status);
551 return status; 567 return status;
552} 568}
@@ -641,6 +657,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
641 .fh = &fh, 657 .fh = &fh,
642 .fattr = &fattr 658 .fattr = &fattr
643 }; 659 };
660 mode_t mode = sattr->ia_mode;
644 int status; 661 int status;
645 662
646 switch (sattr->ia_mode & S_IFMT) { 663 switch (sattr->ia_mode & S_IFMT) {
@@ -653,12 +670,20 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
653 670
654 dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, 671 dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
655 MAJOR(rdev), MINOR(rdev)); 672 MAJOR(rdev), MINOR(rdev));
673
674 sattr->ia_mode &= ~current->fs->umask;
675
656 dir_attr.valid = 0; 676 dir_attr.valid = 0;
657 fattr.valid = 0; 677 fattr.valid = 0;
658 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0); 678 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
659 nfs_refresh_inode(dir, &dir_attr); 679 nfs_refresh_inode(dir, &dir_attr);
660 if (status == 0) 680 if (status != 0)
661 status = nfs_instantiate(dentry, &fh, &fattr); 681 goto out;
682 status = nfs_instantiate(dentry, &fh, &fattr);
683 if (status != 0)
684 goto out;
685 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
686out:
662 dprintk("NFS reply mknod: %d\n", status); 687 dprintk("NFS reply mknod: %d\n", status);
663 return status; 688 return status;
664} 689}
@@ -825,7 +850,8 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
825struct nfs_rpc_ops nfs_v3_clientops = { 850struct nfs_rpc_ops nfs_v3_clientops = {
826 .version = 3, /* protocol version */ 851 .version = 3, /* protocol version */
827 .dentry_ops = &nfs_dentry_operations, 852 .dentry_ops = &nfs_dentry_operations,
828 .dir_inode_ops = &nfs_dir_inode_operations, 853 .dir_inode_ops = &nfs3_dir_inode_operations,
854 .file_inode_ops = &nfs3_file_inode_operations,
829 .getroot = nfs3_proc_get_root, 855 .getroot = nfs3_proc_get_root,
830 .getattr = nfs3_proc_getattr, 856 .getattr = nfs3_proc_getattr,
831 .setattr = nfs3_proc_setattr, 857 .setattr = nfs3_proc_setattr,
@@ -856,4 +882,5 @@ struct nfs_rpc_ops nfs_v3_clientops = {
856 .file_open = nfs_open, 882 .file_open = nfs_open,
857 .file_release = nfs_release, 883 .file_release = nfs_release,
858 .lock = nfs3_proc_lock, 884 .lock = nfs3_proc_lock,
885 .clear_acl_cache = nfs3_forget_cached_acls,
859}; 886};
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index a3593d47e5ab..db4a904810a4 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -21,6 +21,7 @@
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/nfsacl.h>
24 25
25#define NFSDBG_FACILITY NFSDBG_XDR 26#define NFSDBG_FACILITY NFSDBG_XDR
26 27
@@ -79,6 +80,11 @@ extern int nfs_stat_to_errno(int);
79#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) 80#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
80#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) 81#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
81 82
83#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
84#define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3))
85#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
86#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
87
82/* 88/*
83 * Map file type to S_IFMT bits 89 * Map file type to S_IFMT bits
84 */ 90 */
@@ -627,6 +633,74 @@ nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
627 return 0; 633 return 0;
628} 634}
629 635
636#ifdef CONFIG_NFS_V3_ACL
637/*
638 * Encode GETACL arguments
639 */
640static int
641nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
642 struct nfs3_getaclargs *args)
643{
644 struct rpc_auth *auth = req->rq_task->tk_auth;
645 unsigned int replen;
646
647 p = xdr_encode_fhandle(p, args->fh);
648 *p++ = htonl(args->mask);
649 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
650
651 if (args->mask & (NFS_ACL | NFS_DFACL)) {
652 /* Inline the page array */
653 replen = (RPC_REPHDRSIZE + auth->au_rslack +
654 ACL3_getaclres_sz) << 2;
655 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
656 NFSACL_MAXPAGES << PAGE_SHIFT);
657 }
658 return 0;
659}
660
661/*
662 * Encode SETACL arguments
663 */
664static int
665nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
666 struct nfs3_setaclargs *args)
667{
668 struct xdr_buf *buf = &req->rq_snd_buf;
669 unsigned int base, len_in_head, len = nfsacl_size(
670 (args->mask & NFS_ACL) ? args->acl_access : NULL,
671 (args->mask & NFS_DFACL) ? args->acl_default : NULL);
672 int count, err;
673
674 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
675 *p++ = htonl(args->mask);
676 base = (char *)p - (char *)buf->head->iov_base;
677 /* put as much of the acls into head as possible. */
678 len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
679 len -= len_in_head;
680 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
681
682 for (count = 0; (count << PAGE_SHIFT) < len; count++) {
683 args->pages[count] = alloc_page(GFP_KERNEL);
684 if (!args->pages[count]) {
685 while (count)
686 __free_page(args->pages[--count]);
687 return -ENOMEM;
688 }
689 }
690 xdr_encode_pages(buf, args->pages, 0, len);
691
692 err = nfsacl_encode(buf, base, args->inode,
693 (args->mask & NFS_ACL) ?
694 args->acl_access : NULL, 1, 0);
695 if (err > 0)
696 err = nfsacl_encode(buf, base + err, args->inode,
697 (args->mask & NFS_DFACL) ?
698 args->acl_default : NULL, 1,
699 NFS_ACL_DEFAULT);
700 return (err > 0) ? 0 : err;
701}
702#endif /* CONFIG_NFS_V3_ACL */
703
630/* 704/*
631 * NFS XDR decode functions 705 * NFS XDR decode functions
632 */ 706 */
@@ -978,6 +1052,54 @@ nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
978 return 0; 1052 return 0;
979} 1053}
980 1054
1055#ifdef CONFIG_NFS_V3_ACL
1056/*
1057 * Decode GETACL reply
1058 */
1059static int
1060nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
1061 struct nfs3_getaclres *res)
1062{
1063 struct xdr_buf *buf = &req->rq_rcv_buf;
1064 int status = ntohl(*p++);
1065 struct posix_acl **acl;
1066 unsigned int *aclcnt;
1067 int err, base;
1068
1069 if (status != 0)
1070 return -nfs_stat_to_errno(status);
1071 p = xdr_decode_post_op_attr(p, res->fattr);
1072 res->mask = ntohl(*p++);
1073 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1074 return -EINVAL;
1075 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1076
1077 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1078 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1079 err = nfsacl_decode(buf, base, aclcnt, acl);
1080
1081 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1082 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1083 if (err > 0)
1084 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1085 return (err > 0) ? 0 : err;
1086}
1087
1088/*
1089 * Decode setacl reply.
1090 */
1091static int
1092nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
1093{
1094 int status = ntohl(*p++);
1095
1096 if (status)
1097 return -nfs_stat_to_errno(status);
1098 xdr_decode_post_op_attr(p, fattr);
1099 return 0;
1100}
1101#endif /* CONFIG_NFS_V3_ACL */
1102
981#ifndef MAX 1103#ifndef MAX
982# define MAX(a, b) (((a) > (b))? (a) : (b)) 1104# define MAX(a, b) (((a) > (b))? (a) : (b))
983#endif 1105#endif
@@ -1021,3 +1143,28 @@ struct rpc_version nfs_version3 = {
1021 .procs = nfs3_procedures 1143 .procs = nfs3_procedures
1022}; 1144};
1023 1145
1146#ifdef CONFIG_NFS_V3_ACL
1147static struct rpc_procinfo nfs3_acl_procedures[] = {
1148 [ACLPROC3_GETACL] = {
1149 .p_proc = ACLPROC3_GETACL,
1150 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1151 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1152 .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
1153 .p_timer = 1,
1154 },
1155 [ACLPROC3_SETACL] = {
1156 .p_proc = ACLPROC3_SETACL,
1157 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1158 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1159 .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
1160 .p_timer = 0,
1161 },
1162};
1163
1164struct rpc_version nfsacl_version3 = {
1165 .number = 3,
1166 .nrprocs = sizeof(nfs3_acl_procedures)/
1167 sizeof(nfs3_acl_procedures[0]),
1168 .procs = nfs3_acl_procedures,
1169};
1170#endif /* CONFIG_NFS_V3_ACL */
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
new file mode 100644
index 000000000000..ec1a22d7b876
--- /dev/null
+++ b/fs/nfs/nfs4_fs.h
@@ -0,0 +1,253 @@
1/*
2 * linux/fs/nfs/nfs4_fs.h
3 *
4 * Copyright (C) 2005 Trond Myklebust
5 *
6 * NFSv4-specific filesystem definitions and declarations
7 */
8
9#ifndef __LINUX_FS_NFS_NFS4_FS_H
10#define __LINUX_FS_NFS_NFS4_FS_H
11
12#ifdef CONFIG_NFS_V4
13
14struct idmap;
15
16/*
17 * In a seqid-mutating op, this macro controls which error return
18 * values trigger incrementation of the seqid.
19 *
20 * from rfc 3010:
21 * The client MUST monotonically increment the sequence number for the
22 * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE
23 * operations. This is true even in the event that the previous
24 * operation that used the sequence number received an error. The only
25 * exception to this rule is if the previous operation received one of
26 * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID,
27 * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR,
28 * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE.
29 *
30 */
31#define seqid_mutating_err(err) \
32(((err) != NFSERR_STALE_CLIENTID) && \
33 ((err) != NFSERR_STALE_STATEID) && \
34 ((err) != NFSERR_BAD_STATEID) && \
35 ((err) != NFSERR_BAD_SEQID) && \
36 ((err) != NFSERR_BAD_XDR) && \
37 ((err) != NFSERR_RESOURCE) && \
38 ((err) != NFSERR_NOFILEHANDLE))
39
40enum nfs4_client_state {
41 NFS4CLNT_OK = 0,
42};
43
44/*
45 * The nfs4_client identifies our client state to the server.
46 */
47struct nfs4_client {
48 struct list_head cl_servers; /* Global list of servers */
49 struct in_addr cl_addr; /* Server identifier */
50 u64 cl_clientid; /* constant */
51 nfs4_verifier cl_confirm;
52 unsigned long cl_state;
53
54 u32 cl_lockowner_id;
55
56 /*
57 * The following rwsem ensures exclusive access to the server
58 * while we recover the state following a lease expiration.
59 */
60 struct rw_semaphore cl_sem;
61
62 struct list_head cl_delegations;
63 struct list_head cl_state_owners;
64 struct list_head cl_unused;
65 int cl_nunused;
66 spinlock_t cl_lock;
67 atomic_t cl_count;
68
69 struct rpc_clnt * cl_rpcclient;
70 struct rpc_cred * cl_cred;
71
72 struct list_head cl_superblocks; /* List of nfs_server structs */
73
74 unsigned long cl_lease_time;
75 unsigned long cl_last_renewal;
76 struct work_struct cl_renewd;
77 struct work_struct cl_recoverd;
78
79 wait_queue_head_t cl_waitq;
80 struct rpc_wait_queue cl_rpcwaitq;
81
82 /* used for the setclientid verifier */
83 struct timespec cl_boot_time;
84
85 /* idmapper */
86 struct idmap * cl_idmap;
87
88 /* Our own IP address, as a null-terminated string.
89 * This is used to generate the clientid, and the callback address.
90 */
91 char cl_ipaddr[16];
92 unsigned char cl_id_uniquifier;
93};
94
95/*
96 * NFS4 state_owners and lock_owners are simply labels for ordered
97 * sequences of RPC calls. Their sole purpose is to provide once-only
98 * semantics by allowing the server to identify replayed requests.
99 *
100 * The ->so_sema is held during all state_owner seqid-mutating operations:
101 * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize
102 * so_seqid.
103 */
104struct nfs4_state_owner {
105 struct list_head so_list; /* per-clientid list of state_owners */
106 struct nfs4_client *so_client;
107 u32 so_id; /* 32-bit identifier, unique */
108 struct semaphore so_sema;
109 u32 so_seqid; /* protected by so_sema */
110 atomic_t so_count;
111
112 struct rpc_cred *so_cred; /* Associated cred */
113 struct list_head so_states;
114 struct list_head so_delegations;
115};
116
117/*
118 * struct nfs4_state maintains the client-side state for a given
119 * (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
120 *
121 * OPEN:
122 * In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server,
123 * we need to know how many files are open for reading or writing on a
124 * given inode. This information too is stored here.
125 *
126 * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
127 */
128
129struct nfs4_lock_state {
130 struct list_head ls_locks; /* Other lock stateids */
131 struct nfs4_state * ls_state; /* Pointer to open state */
132 fl_owner_t ls_owner; /* POSIX lock owner */
133#define NFS_LOCK_INITIALIZED 1
134 int ls_flags;
135 u32 ls_seqid;
136 u32 ls_id;
137 nfs4_stateid ls_stateid;
138 atomic_t ls_count;
139};
140
141/* bits for nfs4_state->flags */
142enum {
143 LK_STATE_IN_USE,
144 NFS_DELEGATED_STATE,
145};
146
147struct nfs4_state {
148 struct list_head open_states; /* List of states for the same state_owner */
149 struct list_head inode_states; /* List of states for the same inode */
150 struct list_head lock_states; /* List of subservient lock stateids */
151
152 struct nfs4_state_owner *owner; /* Pointer to the open owner */
153 struct inode *inode; /* Pointer to the inode */
154
155 unsigned long flags; /* Do we hold any locks? */
156 struct semaphore lock_sema; /* Serializes file locking operations */
157 spinlock_t state_lock; /* Protects the lock_states list */
158
159 nfs4_stateid stateid;
160
161 unsigned int nreaders;
162 unsigned int nwriters;
163 int state; /* State on the server (R,W, or RW) */
164 atomic_t count;
165};
166
167
168struct nfs4_exception {
169 long timeout;
170 int retry;
171};
172
173struct nfs4_state_recovery_ops {
174 int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
175 int (*recover_lock)(struct nfs4_state *, struct file_lock *);
176};
177
178extern struct dentry_operations nfs4_dentry_operations;
179extern struct inode_operations nfs4_dir_inode_operations;
180
181/* inode.c */
182extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
183extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t, int);
184extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
185
186
187/* nfs4proc.c */
188extern int nfs4_map_errors(int err);
189extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
190extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
191extern int nfs4_proc_async_renew(struct nfs4_client *);
192extern int nfs4_proc_renew(struct nfs4_client *);
193extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
194extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
195extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
196
197extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
198extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
199
200extern const u32 nfs4_fattr_bitmap[2];
201extern const u32 nfs4_statfs_bitmap[2];
202extern const u32 nfs4_pathconf_bitmap[2];
203extern const u32 nfs4_fsinfo_bitmap[2];
204
205/* nfs4renewd.c */
206extern void nfs4_schedule_state_renewal(struct nfs4_client *);
207extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
208extern void nfs4_kill_renewd(struct nfs4_client *);
209extern void nfs4_renew_state(void *);
210
211/* nfs4state.c */
212extern void init_nfsv4_state(struct nfs_server *);
213extern void destroy_nfsv4_state(struct nfs_server *);
214extern struct nfs4_client *nfs4_get_client(struct in_addr *);
215extern void nfs4_put_client(struct nfs4_client *clp);
216extern int nfs4_init_client(struct nfs4_client *clp);
217extern struct nfs4_client *nfs4_find_client(struct in_addr *);
218extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
219
220extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
221extern void nfs4_put_state_owner(struct nfs4_state_owner *);
222extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
223extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
224extern void nfs4_put_open_state(struct nfs4_state *);
225extern void nfs4_close_state(struct nfs4_state *, mode_t);
226extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
227extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
228extern void nfs4_schedule_state_recovery(struct nfs4_client *);
229extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
230extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
231extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
232
233extern const nfs4_stateid zero_stateid;
234
235/* nfs4xdr.c */
236extern uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus);
237extern struct rpc_procinfo nfs4_procedures[];
238
239struct nfs4_mount_data;
240
241/* callback_xdr.c */
242extern struct svc_version nfs4_callback_version1;
243
244#else
245
246#define init_nfsv4_state(server) do { } while (0)
247#define destroy_nfsv4_state(server) do { } while (0)
248#define nfs4_put_state_owner(inode, owner) do { } while (0)
249#define nfs4_put_open_state(state) do { } while (0)
250#define nfs4_close_state(a, b) do { } while (0)
251
252#endif /* CONFIG_NFS_V4 */
253#endif /* __LINUX_FS_NFS_NFS4_FS.H */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1d5cb3e80c3e..1b76f80aedb9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -48,6 +48,7 @@
48#include <linux/smp_lock.h> 48#include <linux/smp_lock.h>
49#include <linux/namei.h> 49#include <linux/namei.h>
50 50
51#include "nfs4_fs.h"
51#include "delegation.h" 52#include "delegation.h"
52 53
53#define NFSDBG_FACILITY NFSDBG_PROC 54#define NFSDBG_FACILITY NFSDBG_PROC
@@ -62,8 +63,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
62extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); 63extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
63extern struct rpc_procinfo nfs4_procedures[]; 64extern struct rpc_procinfo nfs4_procedures[];
64 65
65extern nfs4_stateid zero_stateid;
66
67/* Prevent leaks of NFSv4 errors into userland */ 66/* Prevent leaks of NFSv4 errors into userland */
68int nfs4_map_errors(int err) 67int nfs4_map_errors(int err)
69{ 68{
@@ -104,7 +103,7 @@ const u32 nfs4_statfs_bitmap[2] = {
104 | FATTR4_WORD1_SPACE_TOTAL 103 | FATTR4_WORD1_SPACE_TOTAL
105}; 104};
106 105
107u32 nfs4_pathconf_bitmap[2] = { 106const u32 nfs4_pathconf_bitmap[2] = {
108 FATTR4_WORD0_MAXLINK 107 FATTR4_WORD0_MAXLINK
109 | FATTR4_WORD0_MAXNAME, 108 | FATTR4_WORD0_MAXNAME,
110 0 109 0
@@ -124,7 +123,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
124 123
125 BUG_ON(readdir->count < 80); 124 BUG_ON(readdir->count < 80);
126 if (cookie > 2) { 125 if (cookie > 2) {
127 readdir->cookie = (cookie > 2) ? cookie : 0; 126 readdir->cookie = cookie;
128 memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); 127 memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
129 return; 128 return;
130 } 129 }
@@ -270,14 +269,9 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
270 int err; 269 int err;
271 do { 270 do {
272 err = _nfs4_open_reclaim(sp, state); 271 err = _nfs4_open_reclaim(sp, state);
273 switch (err) { 272 if (err != -NFS4ERR_DELAY)
274 case 0: 273 break;
275 case -NFS4ERR_STALE_CLIENTID: 274 nfs4_handle_exception(server, err, &exception);
276 case -NFS4ERR_STALE_STATEID:
277 case -NFS4ERR_EXPIRED:
278 return err;
279 }
280 err = nfs4_handle_exception(server, err, &exception);
281 } while (exception.retry); 275 } while (exception.retry);
282 return err; 276 return err;
283} 277}
@@ -509,6 +503,20 @@ out_stale:
509 goto out_nodeleg; 503 goto out_nodeleg;
510} 504}
511 505
506static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
507{
508 struct nfs_server *server = NFS_SERVER(dentry->d_inode);
509 struct nfs4_exception exception = { };
510 int err;
511
512 do {
513 err = _nfs4_open_expired(sp, state, dentry);
514 if (err == -NFS4ERR_DELAY)
515 nfs4_handle_exception(server, err, &exception);
516 } while (exception.retry);
517 return err;
518}
519
512static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) 520static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
513{ 521{
514 struct nfs_inode *nfsi = NFS_I(state->inode); 522 struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -521,7 +529,7 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
521 continue; 529 continue;
522 get_nfs_open_context(ctx); 530 get_nfs_open_context(ctx);
523 spin_unlock(&state->inode->i_lock); 531 spin_unlock(&state->inode->i_lock);
524 status = _nfs4_open_expired(sp, state, ctx->dentry); 532 status = nfs4_do_open_expired(sp, state, ctx->dentry);
525 put_nfs_open_context(ctx); 533 put_nfs_open_context(ctx);
526 return status; 534 return status;
527 } 535 }
@@ -748,11 +756,10 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
748 756
749 fattr->valid = 0; 757 fattr->valid = 0;
750 758
751 if (state != NULL) 759 if (state != NULL) {
752 msg.rpc_cred = state->owner->so_cred; 760 msg.rpc_cred = state->owner->so_cred;
753 if (sattr->ia_valid & ATTR_SIZE) 761 nfs4_copy_stateid(&arg.stateid, state, current->files);
754 nfs4_copy_stateid(&arg.stateid, state, NULL); 762 } else
755 else
756 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); 763 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
757 764
758 return rpc_call_sync(server->client, &msg, 0); 765 return rpc_call_sync(server->client, &msg, 0);
@@ -1116,47 +1123,31 @@ static int
1116nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, 1123nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1117 struct iattr *sattr) 1124 struct iattr *sattr)
1118{ 1125{
1119 struct inode * inode = dentry->d_inode; 1126 struct rpc_cred *cred;
1120 int size_change = sattr->ia_valid & ATTR_SIZE; 1127 struct inode *inode = dentry->d_inode;
1121 struct nfs4_state *state = NULL; 1128 struct nfs4_state *state;
1122 int need_iput = 0;
1123 int status; 1129 int status;
1124 1130
1125 fattr->valid = 0; 1131 fattr->valid = 0;
1126 1132
1127 if (size_change) { 1133 cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
1128 struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); 1134 if (IS_ERR(cred))
1129 if (IS_ERR(cred)) 1135 return PTR_ERR(cred);
1130 return PTR_ERR(cred); 1136 /* Search for an existing WRITE delegation first */
1137 state = nfs4_open_delegated(inode, FMODE_WRITE, cred);
1138 if (!IS_ERR(state)) {
1139 /* NB: nfs4_open_delegated() bumps the inode->i_count */
1140 iput(inode);
1141 } else {
1142 /* Search for an existing open(O_WRITE) stateid */
1131 state = nfs4_find_state(inode, cred, FMODE_WRITE); 1143 state = nfs4_find_state(inode, cred, FMODE_WRITE);
1132 if (state == NULL) {
1133 state = nfs4_open_delegated(dentry->d_inode,
1134 FMODE_WRITE, cred);
1135 if (IS_ERR(state))
1136 state = nfs4_do_open(dentry->d_parent->d_inode,
1137 dentry, FMODE_WRITE,
1138 NULL, cred);
1139 need_iput = 1;
1140 }
1141 put_rpccred(cred);
1142 if (IS_ERR(state))
1143 return PTR_ERR(state);
1144
1145 if (state->inode != inode) {
1146 printk(KERN_WARNING "nfs: raced in setattr (%p != %p), returning -EIO\n", inode, state->inode);
1147 status = -EIO;
1148 goto out;
1149 }
1150 } 1144 }
1145
1151 status = nfs4_do_setattr(NFS_SERVER(inode), fattr, 1146 status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
1152 NFS_FH(inode), sattr, state); 1147 NFS_FH(inode), sattr, state);
1153out: 1148 if (state != NULL)
1154 if (state) {
1155 inode = state->inode;
1156 nfs4_close_state(state, FMODE_WRITE); 1149 nfs4_close_state(state, FMODE_WRITE);
1157 if (need_iput) 1150 put_rpccred(cred);
1158 iput(inode);
1159 }
1160 return status; 1151 return status;
1161} 1152}
1162 1153
@@ -1731,6 +1722,10 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
1731 }; 1722 };
1732 int status; 1723 int status;
1733 1724
1725 dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __FUNCTION__,
1726 dentry->d_parent->d_name.name,
1727 dentry->d_name.name,
1728 (unsigned long long)cookie);
1734 lock_kernel(); 1729 lock_kernel();
1735 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); 1730 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
1736 res.pgbase = args.pgbase; 1731 res.pgbase = args.pgbase;
@@ -1738,6 +1733,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
1738 if (status == 0) 1733 if (status == 0)
1739 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); 1734 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
1740 unlock_kernel(); 1735 unlock_kernel();
1736 dprintk("%s: returns %d\n", __FUNCTION__, status);
1741 return status; 1737 return status;
1742} 1738}
1743 1739
@@ -2163,6 +2159,193 @@ nfs4_proc_file_release(struct inode *inode, struct file *filp)
2163 return 0; 2159 return 0;
2164} 2160}
2165 2161
2162static inline int nfs4_server_supports_acls(struct nfs_server *server)
2163{
2164 return (server->caps & NFS_CAP_ACLS)
2165 && (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
2166 && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
2167}
2168
2169/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
2170 * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
2171 * the stack.
2172 */
2173#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
2174
2175static void buf_to_pages(const void *buf, size_t buflen,
2176 struct page **pages, unsigned int *pgbase)
2177{
2178 const void *p = buf;
2179
2180 *pgbase = offset_in_page(buf);
2181 p -= *pgbase;
2182 while (p < buf + buflen) {
2183 *(pages++) = virt_to_page(p);
2184 p += PAGE_CACHE_SIZE;
2185 }
2186}
2187
2188struct nfs4_cached_acl {
2189 int cached;
2190 size_t len;
2191 char data[0];
2192};
2193
2194static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl)
2195{
2196 struct nfs_inode *nfsi = NFS_I(inode);
2197
2198 spin_lock(&inode->i_lock);
2199 kfree(nfsi->nfs4_acl);
2200 nfsi->nfs4_acl = acl;
2201 spin_unlock(&inode->i_lock);
2202}
2203
2204static void nfs4_zap_acl_attr(struct inode *inode)
2205{
2206 nfs4_set_cached_acl(inode, NULL);
2207}
2208
2209static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
2210{
2211 struct nfs_inode *nfsi = NFS_I(inode);
2212 struct nfs4_cached_acl *acl;
2213 int ret = -ENOENT;
2214
2215 spin_lock(&inode->i_lock);
2216 acl = nfsi->nfs4_acl;
2217 if (acl == NULL)
2218 goto out;
2219 if (buf == NULL) /* user is just asking for length */
2220 goto out_len;
2221 if (acl->cached == 0)
2222 goto out;
2223 ret = -ERANGE; /* see getxattr(2) man page */
2224 if (acl->len > buflen)
2225 goto out;
2226 memcpy(buf, acl->data, acl->len);
2227out_len:
2228 ret = acl->len;
2229out:
2230 spin_unlock(&inode->i_lock);
2231 return ret;
2232}
2233
2234static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
2235{
2236 struct nfs4_cached_acl *acl;
2237
2238 if (buf && acl_len <= PAGE_SIZE) {
2239 acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
2240 if (acl == NULL)
2241 goto out;
2242 acl->cached = 1;
2243 memcpy(acl->data, buf, acl_len);
2244 } else {
2245 acl = kmalloc(sizeof(*acl), GFP_KERNEL);
2246 if (acl == NULL)
2247 goto out;
2248 acl->cached = 0;
2249 }
2250 acl->len = acl_len;
2251out:
2252 nfs4_set_cached_acl(inode, acl);
2253}
2254
2255static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
2256{
2257 struct page *pages[NFS4ACL_MAXPAGES];
2258 struct nfs_getaclargs args = {
2259 .fh = NFS_FH(inode),
2260 .acl_pages = pages,
2261 .acl_len = buflen,
2262 };
2263 size_t resp_len = buflen;
2264 void *resp_buf;
2265 struct rpc_message msg = {
2266 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
2267 .rpc_argp = &args,
2268 .rpc_resp = &resp_len,
2269 };
2270 struct page *localpage = NULL;
2271 int ret;
2272
2273 if (buflen < PAGE_SIZE) {
2274 /* As long as we're doing a round trip to the server anyway,
2275 * let's be prepared for a page of acl data. */
2276 localpage = alloc_page(GFP_KERNEL);
2277 resp_buf = page_address(localpage);
2278 if (localpage == NULL)
2279 return -ENOMEM;
2280 args.acl_pages[0] = localpage;
2281 args.acl_pgbase = 0;
2282 args.acl_len = PAGE_SIZE;
2283 } else {
2284 resp_buf = buf;
2285 buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
2286 }
2287 ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
2288 if (ret)
2289 goto out_free;
2290 if (resp_len > args.acl_len)
2291 nfs4_write_cached_acl(inode, NULL, resp_len);
2292 else
2293 nfs4_write_cached_acl(inode, resp_buf, resp_len);
2294 if (buf) {
2295 ret = -ERANGE;
2296 if (resp_len > buflen)
2297 goto out_free;
2298 if (localpage)
2299 memcpy(buf, resp_buf, resp_len);
2300 }
2301 ret = resp_len;
2302out_free:
2303 if (localpage)
2304 __free_page(localpage);
2305 return ret;
2306}
2307
2308static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
2309{
2310 struct nfs_server *server = NFS_SERVER(inode);
2311 int ret;
2312
2313 if (!nfs4_server_supports_acls(server))
2314 return -EOPNOTSUPP;
2315 ret = nfs_revalidate_inode(server, inode);
2316 if (ret < 0)
2317 return ret;
2318 ret = nfs4_read_cached_acl(inode, buf, buflen);
2319 if (ret != -ENOENT)
2320 return ret;
2321 return nfs4_get_acl_uncached(inode, buf, buflen);
2322}
2323
2324static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
2325{
2326 struct nfs_server *server = NFS_SERVER(inode);
2327 struct page *pages[NFS4ACL_MAXPAGES];
2328 struct nfs_setaclargs arg = {
2329 .fh = NFS_FH(inode),
2330 .acl_pages = pages,
2331 .acl_len = buflen,
2332 };
2333 struct rpc_message msg = {
2334 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
2335 .rpc_argp = &arg,
2336 .rpc_resp = NULL,
2337 };
2338 int ret;
2339
2340 if (!nfs4_server_supports_acls(server))
2341 return -EOPNOTSUPP;
2342 buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
2343 ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
2344 if (ret == 0)
2345 nfs4_write_cached_acl(inode, buf, buflen);
2346 return ret;
2347}
2348
2166static int 2349static int
2167nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server) 2350nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
2168{ 2351{
@@ -2448,14 +2631,11 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
2448 down_read(&clp->cl_sem); 2631 down_read(&clp->cl_sem);
2449 nlo.clientid = clp->cl_clientid; 2632 nlo.clientid = clp->cl_clientid;
2450 down(&state->lock_sema); 2633 down(&state->lock_sema);
2451 lsp = nfs4_find_lock_state(state, request->fl_owner); 2634 status = nfs4_set_lock_state(state, request);
2452 if (lsp) 2635 if (status != 0)
2453 nlo.id = lsp->ls_id; 2636 goto out;
2454 else { 2637 lsp = request->fl_u.nfs4_fl.owner;
2455 spin_lock(&clp->cl_lock); 2638 nlo.id = lsp->ls_id;
2456 nlo.id = nfs4_alloc_lockowner_id(clp);
2457 spin_unlock(&clp->cl_lock);
2458 }
2459 arg.u.lockt = &nlo; 2639 arg.u.lockt = &nlo;
2460 status = rpc_call_sync(server->client, &msg, 0); 2640 status = rpc_call_sync(server->client, &msg, 0);
2461 if (!status) { 2641 if (!status) {
@@ -2476,8 +2656,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
2476 request->fl_pid = 0; 2656 request->fl_pid = 0;
2477 status = 0; 2657 status = 0;
2478 } 2658 }
2479 if (lsp) 2659out:
2480 nfs4_put_lock_state(lsp);
2481 up(&state->lock_sema); 2660 up(&state->lock_sema);
2482 up_read(&clp->cl_sem); 2661 up_read(&clp->cl_sem);
2483 return status; 2662 return status;
@@ -2537,28 +2716,26 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock
2537 }; 2716 };
2538 struct nfs4_lock_state *lsp; 2717 struct nfs4_lock_state *lsp;
2539 struct nfs_locku_opargs luargs; 2718 struct nfs_locku_opargs luargs;
2540 int status = 0; 2719 int status;
2541 2720
2542 down_read(&clp->cl_sem); 2721 down_read(&clp->cl_sem);
2543 down(&state->lock_sema); 2722 down(&state->lock_sema);
2544 lsp = nfs4_find_lock_state(state, request->fl_owner); 2723 status = nfs4_set_lock_state(state, request);
2545 if (!lsp) 2724 if (status != 0)
2546 goto out; 2725 goto out;
2726 lsp = request->fl_u.nfs4_fl.owner;
2547 /* We might have lost the locks! */ 2727 /* We might have lost the locks! */
2548 if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) { 2728 if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
2549 luargs.seqid = lsp->ls_seqid; 2729 goto out;
2550 memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid)); 2730 luargs.seqid = lsp->ls_seqid;
2551 arg.u.locku = &luargs; 2731 memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
2552 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); 2732 arg.u.locku = &luargs;
2553 nfs4_increment_lock_seqid(status, lsp); 2733 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
2554 } 2734 nfs4_increment_lock_seqid(status, lsp);
2555 2735
2556 if (status == 0) { 2736 if (status == 0)
2557 memcpy(&lsp->ls_stateid, &res.u.stateid, 2737 memcpy(&lsp->ls_stateid, &res.u.stateid,
2558 sizeof(lsp->ls_stateid)); 2738 sizeof(lsp->ls_stateid));
2559 nfs4_notify_unlck(state, request, lsp);
2560 }
2561 nfs4_put_lock_state(lsp);
2562out: 2739out:
2563 up(&state->lock_sema); 2740 up(&state->lock_sema);
2564 if (status == 0) 2741 if (status == 0)
@@ -2584,7 +2761,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
2584{ 2761{
2585 struct inode *inode = state->inode; 2762 struct inode *inode = state->inode;
2586 struct nfs_server *server = NFS_SERVER(inode); 2763 struct nfs_server *server = NFS_SERVER(inode);
2587 struct nfs4_lock_state *lsp; 2764 struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
2588 struct nfs_lockargs arg = { 2765 struct nfs_lockargs arg = {
2589 .fh = NFS_FH(inode), 2766 .fh = NFS_FH(inode),
2590 .type = nfs4_lck_type(cmd, request), 2767 .type = nfs4_lck_type(cmd, request),
@@ -2606,9 +2783,6 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
2606 }; 2783 };
2607 int status; 2784 int status;
2608 2785
2609 lsp = nfs4_get_lock_state(state, request->fl_owner);
2610 if (lsp == NULL)
2611 return -ENOMEM;
2612 if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) { 2786 if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
2613 struct nfs4_state_owner *owner = state->owner; 2787 struct nfs4_state_owner *owner = state->owner;
2614 struct nfs_open_to_lock otl = { 2788 struct nfs_open_to_lock otl = {
@@ -2630,38 +2804,57 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
2630 * seqid mutating errors */ 2804 * seqid mutating errors */
2631 nfs4_increment_seqid(status, owner); 2805 nfs4_increment_seqid(status, owner);
2632 up(&owner->so_sema); 2806 up(&owner->so_sema);
2807 if (status == 0) {
2808 lsp->ls_flags |= NFS_LOCK_INITIALIZED;
2809 lsp->ls_seqid++;
2810 }
2633 } else { 2811 } else {
2634 struct nfs_exist_lock el = { 2812 struct nfs_exist_lock el = {
2635 .seqid = lsp->ls_seqid, 2813 .seqid = lsp->ls_seqid,
2636 }; 2814 };
2637 memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid)); 2815 memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
2638 largs.u.exist_lock = &el; 2816 largs.u.exist_lock = &el;
2639 largs.new_lock_owner = 0;
2640 arg.u.lock = &largs; 2817 arg.u.lock = &largs;
2641 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); 2818 status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
2819 /* increment seqid on success, and * seqid mutating errors*/
2820 nfs4_increment_lock_seqid(status, lsp);
2642 } 2821 }
2643 /* increment seqid on success, and * seqid mutating errors*/
2644 nfs4_increment_lock_seqid(status, lsp);
2645 /* save the returned stateid. */ 2822 /* save the returned stateid. */
2646 if (status == 0) { 2823 if (status == 0)
2647 memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid)); 2824 memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
2648 lsp->ls_flags |= NFS_LOCK_INITIALIZED; 2825 else if (status == -NFS4ERR_DENIED)
2649 if (!reclaim)
2650 nfs4_notify_setlk(state, request, lsp);
2651 } else if (status == -NFS4ERR_DENIED)
2652 status = -EAGAIN; 2826 status = -EAGAIN;
2653 nfs4_put_lock_state(lsp);
2654 return status; 2827 return status;
2655} 2828}
2656 2829
2657static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) 2830static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
2658{ 2831{
2659 return _nfs4_do_setlk(state, F_SETLK, request, 1); 2832 struct nfs_server *server = NFS_SERVER(state->inode);
2833 struct nfs4_exception exception = { };
2834 int err;
2835
2836 do {
2837 err = _nfs4_do_setlk(state, F_SETLK, request, 1);
2838 if (err != -NFS4ERR_DELAY)
2839 break;
2840 nfs4_handle_exception(server, err, &exception);
2841 } while (exception.retry);
2842 return err;
2660} 2843}
2661 2844
2662static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) 2845static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
2663{ 2846{
2664 return _nfs4_do_setlk(state, F_SETLK, request, 0); 2847 struct nfs_server *server = NFS_SERVER(state->inode);
2848 struct nfs4_exception exception = { };
2849 int err;
2850
2851 do {
2852 err = _nfs4_do_setlk(state, F_SETLK, request, 0);
2853 if (err != -NFS4ERR_DELAY)
2854 break;
2855 nfs4_handle_exception(server, err, &exception);
2856 } while (exception.retry);
2857 return err;
2665} 2858}
2666 2859
2667static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) 2860static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -2671,7 +2864,9 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
2671 2864
2672 down_read(&clp->cl_sem); 2865 down_read(&clp->cl_sem);
2673 down(&state->lock_sema); 2866 down(&state->lock_sema);
2674 status = _nfs4_do_setlk(state, cmd, request, 0); 2867 status = nfs4_set_lock_state(state, request);
2868 if (status == 0)
2869 status = _nfs4_do_setlk(state, cmd, request, 0);
2675 up(&state->lock_sema); 2870 up(&state->lock_sema);
2676 if (status == 0) { 2871 if (status == 0) {
2677 /* Note: we always want to sleep here! */ 2872 /* Note: we always want to sleep here! */
@@ -2729,10 +2924,53 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
2729 if (signalled()) 2924 if (signalled())
2730 break; 2925 break;
2731 } while(status < 0); 2926 } while(status < 0);
2732
2733 return status; 2927 return status;
2734} 2928}
2735 2929
2930
2931#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
2932
2933int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
2934 size_t buflen, int flags)
2935{
2936 struct inode *inode = dentry->d_inode;
2937
2938 if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
2939 return -EOPNOTSUPP;
2940
2941 if (!S_ISREG(inode->i_mode) &&
2942 (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
2943 return -EPERM;
2944
2945 return nfs4_proc_set_acl(inode, buf, buflen);
2946}
2947
2948/* The getxattr man page suggests returning -ENODATA for unknown attributes,
2949 * and that's what we'll do for e.g. user attributes that haven't been set.
2950 * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
2951 * attributes in kernel-managed attribute namespaces. */
2952ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
2953 size_t buflen)
2954{
2955 struct inode *inode = dentry->d_inode;
2956
2957 if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
2958 return -EOPNOTSUPP;
2959
2960 return nfs4_proc_get_acl(inode, buf, buflen);
2961}
2962
2963ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
2964{
2965 size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
2966
2967 if (buf && buflen < len)
2968 return -ERANGE;
2969 if (buf)
2970 memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
2971 return len;
2972}
2973
2736struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { 2974struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
2737 .recover_open = nfs4_open_reclaim, 2975 .recover_open = nfs4_open_reclaim,
2738 .recover_lock = nfs4_lock_reclaim, 2976 .recover_lock = nfs4_lock_reclaim,
@@ -2743,10 +2981,20 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
2743 .recover_lock = nfs4_lock_expired, 2981 .recover_lock = nfs4_lock_expired,
2744}; 2982};
2745 2983
2984static struct inode_operations nfs4_file_inode_operations = {
2985 .permission = nfs_permission,
2986 .getattr = nfs_getattr,
2987 .setattr = nfs_setattr,
2988 .getxattr = nfs4_getxattr,
2989 .setxattr = nfs4_setxattr,
2990 .listxattr = nfs4_listxattr,
2991};
2992
2746struct nfs_rpc_ops nfs_v4_clientops = { 2993struct nfs_rpc_ops nfs_v4_clientops = {
2747 .version = 4, /* protocol version */ 2994 .version = 4, /* protocol version */
2748 .dentry_ops = &nfs4_dentry_operations, 2995 .dentry_ops = &nfs4_dentry_operations,
2749 .dir_inode_ops = &nfs4_dir_inode_operations, 2996 .dir_inode_ops = &nfs4_dir_inode_operations,
2997 .file_inode_ops = &nfs4_file_inode_operations,
2750 .getroot = nfs4_proc_get_root, 2998 .getroot = nfs4_proc_get_root,
2751 .getattr = nfs4_proc_getattr, 2999 .getattr = nfs4_proc_getattr,
2752 .setattr = nfs4_proc_setattr, 3000 .setattr = nfs4_proc_setattr,
@@ -2777,6 +3025,7 @@ struct nfs_rpc_ops nfs_v4_clientops = {
2777 .file_open = nfs4_proc_file_open, 3025 .file_open = nfs4_proc_file_open,
2778 .file_release = nfs4_proc_file_release, 3026 .file_release = nfs4_proc_file_release,
2779 .lock = nfs4_proc_lock, 3027 .lock = nfs4_proc_lock,
3028 .clear_acl_cache = nfs4_zap_acl_attr,
2780}; 3029};
2781 3030
2782/* 3031/*
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 667e06f1c647..a3001628ad32 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -53,6 +53,7 @@
53#include <linux/nfs.h> 53#include <linux/nfs.h>
54#include <linux/nfs4.h> 54#include <linux/nfs4.h>
55#include <linux/nfs_fs.h> 55#include <linux/nfs_fs.h>
56#include "nfs4_fs.h"
56 57
57#define NFSDBG_FACILITY NFSDBG_PROC 58#define NFSDBG_FACILITY NFSDBG_PROC
58 59
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 231cebce3c87..afe587d82f1e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -46,24 +46,18 @@
46#include <linux/workqueue.h> 46#include <linux/workqueue.h>
47#include <linux/bitops.h> 47#include <linux/bitops.h>
48 48
49#include "nfs4_fs.h"
49#include "callback.h" 50#include "callback.h"
50#include "delegation.h" 51#include "delegation.h"
51 52
52#define OPENOWNER_POOL_SIZE 8 53#define OPENOWNER_POOL_SIZE 8
53 54
54static DEFINE_SPINLOCK(state_spinlock); 55const nfs4_stateid zero_stateid;
55
56nfs4_stateid zero_stateid;
57
58#if 0
59nfs4_stateid one_stateid =
60 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
61#endif
62 56
57static DEFINE_SPINLOCK(state_spinlock);
63static LIST_HEAD(nfs4_clientid_list); 58static LIST_HEAD(nfs4_clientid_list);
64 59
65static void nfs4_recover_state(void *); 60static void nfs4_recover_state(void *);
66extern void nfs4_renew_state(void *);
67 61
68void 62void
69init_nfsv4_state(struct nfs_server *server) 63init_nfsv4_state(struct nfs_server *server)
@@ -116,6 +110,7 @@ nfs4_alloc_client(struct in_addr *addr)
116 INIT_LIST_HEAD(&clp->cl_superblocks); 110 INIT_LIST_HEAD(&clp->cl_superblocks);
117 init_waitqueue_head(&clp->cl_waitq); 111 init_waitqueue_head(&clp->cl_waitq);
118 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); 112 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
113 clp->cl_rpcclient = ERR_PTR(-EINVAL);
119 clp->cl_boot_time = CURRENT_TIME; 114 clp->cl_boot_time = CURRENT_TIME;
120 clp->cl_state = 1 << NFS4CLNT_OK; 115 clp->cl_state = 1 << NFS4CLNT_OK;
121 return clp; 116 return clp;
@@ -137,7 +132,7 @@ nfs4_free_client(struct nfs4_client *clp)
137 if (clp->cl_cred) 132 if (clp->cl_cred)
138 put_rpccred(clp->cl_cred); 133 put_rpccred(clp->cl_cred);
139 nfs_idmap_delete(clp); 134 nfs_idmap_delete(clp);
140 if (clp->cl_rpcclient) 135 if (!IS_ERR(clp->cl_rpcclient))
141 rpc_shutdown_client(clp->cl_rpcclient); 136 rpc_shutdown_client(clp->cl_rpcclient);
142 kfree(clp); 137 kfree(clp);
143 nfs_callback_down(); 138 nfs_callback_down();
@@ -365,7 +360,7 @@ nfs4_alloc_open_state(void)
365 atomic_set(&state->count, 1); 360 atomic_set(&state->count, 1);
366 INIT_LIST_HEAD(&state->lock_states); 361 INIT_LIST_HEAD(&state->lock_states);
367 init_MUTEX(&state->lock_sema); 362 init_MUTEX(&state->lock_sema);
368 rwlock_init(&state->state_lock); 363 spin_lock_init(&state->state_lock);
369 return state; 364 return state;
370} 365}
371 366
@@ -547,16 +542,6 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
547 return NULL; 542 return NULL;
548} 543}
549 544
550struct nfs4_lock_state *
551nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
552{
553 struct nfs4_lock_state *lsp;
554 read_lock(&state->state_lock);
555 lsp = __nfs4_find_lock_state(state, fl_owner);
556 read_unlock(&state->state_lock);
557 return lsp;
558}
559
560/* 545/*
561 * Return a compatible lock_state. If no initialized lock_state structure 546 * Return a compatible lock_state. If no initialized lock_state structure
562 * exists, return an uninitialized one. 547 * exists, return an uninitialized one.
@@ -573,14 +558,13 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
573 return NULL; 558 return NULL;
574 lsp->ls_flags = 0; 559 lsp->ls_flags = 0;
575 lsp->ls_seqid = 0; /* arbitrary */ 560 lsp->ls_seqid = 0; /* arbitrary */
576 lsp->ls_id = -1;
577 memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data)); 561 memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
578 atomic_set(&lsp->ls_count, 1); 562 atomic_set(&lsp->ls_count, 1);
579 lsp->ls_owner = fl_owner; 563 lsp->ls_owner = fl_owner;
580 INIT_LIST_HEAD(&lsp->ls_locks);
581 spin_lock(&clp->cl_lock); 564 spin_lock(&clp->cl_lock);
582 lsp->ls_id = nfs4_alloc_lockowner_id(clp); 565 lsp->ls_id = nfs4_alloc_lockowner_id(clp);
583 spin_unlock(&clp->cl_lock); 566 spin_unlock(&clp->cl_lock);
567 INIT_LIST_HEAD(&lsp->ls_locks);
584 return lsp; 568 return lsp;
585} 569}
586 570
@@ -590,121 +574,112 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
590 * 574 *
591 * The caller must be holding state->lock_sema and clp->cl_sem 575 * The caller must be holding state->lock_sema and clp->cl_sem
592 */ 576 */
593struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) 577static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
594{ 578{
595 struct nfs4_lock_state * lsp; 579 struct nfs4_lock_state *lsp, *new = NULL;
596 580
597 lsp = nfs4_find_lock_state(state, owner); 581 for(;;) {
598 if (lsp == NULL) 582 spin_lock(&state->state_lock);
599 lsp = nfs4_alloc_lock_state(state, owner); 583 lsp = __nfs4_find_lock_state(state, owner);
584 if (lsp != NULL)
585 break;
586 if (new != NULL) {
587 new->ls_state = state;
588 list_add(&new->ls_locks, &state->lock_states);
589 set_bit(LK_STATE_IN_USE, &state->flags);
590 lsp = new;
591 new = NULL;
592 break;
593 }
594 spin_unlock(&state->state_lock);
595 new = nfs4_alloc_lock_state(state, owner);
596 if (new == NULL)
597 return NULL;
598 }
599 spin_unlock(&state->state_lock);
600 kfree(new);
600 return lsp; 601 return lsp;
601} 602}
602 603
603/* 604/*
604 * Byte-range lock aware utility to initialize the stateid of read/write 605 * Release reference to lock_state, and free it if we see that
605 * requests. 606 * it is no longer in use
606 */ 607 */
607void 608static void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
608nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
609{ 609{
610 if (test_bit(LK_STATE_IN_USE, &state->flags)) { 610 struct nfs4_state *state;
611 struct nfs4_lock_state *lsp;
612 611
613 lsp = nfs4_find_lock_state(state, fl_owner); 612 if (lsp == NULL)
614 if (lsp) { 613 return;
615 memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); 614 state = lsp->ls_state;
616 nfs4_put_lock_state(lsp); 615 if (!atomic_dec_and_lock(&lsp->ls_count, &state->state_lock))
617 return; 616 return;
618 } 617 list_del(&lsp->ls_locks);
619 } 618 if (list_empty(&state->lock_states))
620 memcpy(dst, &state->stateid, sizeof(*dst)); 619 clear_bit(LK_STATE_IN_USE, &state->flags);
620 spin_unlock(&state->state_lock);
621 kfree(lsp);
621} 622}
622 623
623/* 624static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
624* Called with state->lock_sema and clp->cl_sem held.
625*/
626void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
627{ 625{
628 if (status == NFS_OK || seqid_mutating_err(-status)) 626 struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner;
629 lsp->ls_seqid++;
630}
631 627
632/* 628 dst->fl_u.nfs4_fl.owner = lsp;
633* Check to see if the request lock (type FL_UNLK) effects the fl lock. 629 atomic_inc(&lsp->ls_count);
634* 630}
635* fl and request must have the same posix owner
636*
637* return:
638* 0 -> fl not effected by request
639* 1 -> fl consumed by request
640*/
641 631
642static int 632static void nfs4_fl_release_lock(struct file_lock *fl)
643nfs4_check_unlock(struct file_lock *fl, struct file_lock *request)
644{ 633{
645 if (fl->fl_start >= request->fl_start && fl->fl_end <= request->fl_end) 634 nfs4_put_lock_state(fl->fl_u.nfs4_fl.owner);
646 return 1;
647 return 0;
648} 635}
649 636
650/* 637static struct file_lock_operations nfs4_fl_lock_ops = {
651 * Post an initialized lock_state on the state->lock_states list. 638 .fl_copy_lock = nfs4_fl_copy_lock,
652 */ 639 .fl_release_private = nfs4_fl_release_lock,
653void nfs4_notify_setlk(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp) 640};
641
642int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
654{ 643{
655 if (!list_empty(&lsp->ls_locks)) 644 struct nfs4_lock_state *lsp;
656 return; 645
657 atomic_inc(&lsp->ls_count); 646 if (fl->fl_ops != NULL)
658 write_lock(&state->state_lock); 647 return 0;
659 list_add(&lsp->ls_locks, &state->lock_states); 648 lsp = nfs4_get_lock_state(state, fl->fl_owner);
660 set_bit(LK_STATE_IN_USE, &state->flags); 649 if (lsp == NULL)
661 write_unlock(&state->state_lock); 650 return -ENOMEM;
651 fl->fl_u.nfs4_fl.owner = lsp;
652 fl->fl_ops = &nfs4_fl_lock_ops;
653 return 0;
662} 654}
663 655
664/* 656/*
665 * to decide to 'reap' lock state: 657 * Byte-range lock aware utility to initialize the stateid of read/write
666 * 1) search i_flock for file_locks with fl.lock_state = to ls. 658 * requests.
667 * 2) determine if unlock will consume found lock.
668 * if so, reap
669 *
670 * else, don't reap.
671 *
672 */ 659 */
673void 660void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
674nfs4_notify_unlck(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
675{ 661{
676 struct inode *inode = state->inode; 662 struct nfs4_lock_state *lsp;
677 struct file_lock *fl;
678 663
679 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 664 memcpy(dst, &state->stateid, sizeof(*dst));
680 if (!(fl->fl_flags & FL_POSIX)) 665 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
681 continue; 666 return;
682 if (fl->fl_owner != lsp->ls_owner)
683 continue;
684 /* Exit if we find at least one lock which is not consumed */
685 if (nfs4_check_unlock(fl,request) == 0)
686 return;
687 }
688 667
689 write_lock(&state->state_lock); 668 spin_lock(&state->state_lock);
690 list_del_init(&lsp->ls_locks); 669 lsp = __nfs4_find_lock_state(state, fl_owner);
691 if (list_empty(&state->lock_states)) 670 if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
692 clear_bit(LK_STATE_IN_USE, &state->flags); 671 memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
693 write_unlock(&state->state_lock); 672 spin_unlock(&state->state_lock);
694 nfs4_put_lock_state(lsp); 673 nfs4_put_lock_state(lsp);
695} 674}
696 675
697/* 676/*
698 * Release reference to lock_state, and free it if we see that 677* Called with state->lock_sema and clp->cl_sem held.
699 * it is no longer in use 678*/
700 */ 679void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
701void
702nfs4_put_lock_state(struct nfs4_lock_state *lsp)
703{ 680{
704 if (!atomic_dec_and_test(&lsp->ls_count)) 681 if (status == NFS_OK || seqid_mutating_err(-status))
705 return; 682 lsp->ls_seqid++;
706 BUG_ON (!list_empty(&lsp->ls_locks));
707 kfree(lsp);
708} 683}
709 684
710/* 685/*
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 5f4de05763c9..6c564ef9489e 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -51,6 +51,7 @@
51#include <linux/nfs4.h> 51#include <linux/nfs4.h>
52#include <linux/nfs_fs.h> 52#include <linux/nfs_fs.h>
53#include <linux/nfs_idmap.h> 53#include <linux/nfs_idmap.h>
54#include "nfs4_fs.h"
54 55
55#define NFSDBG_FACILITY NFSDBG_XDR 56#define NFSDBG_FACILITY NFSDBG_XDR
56 57
@@ -82,12 +83,16 @@ static int nfs_stat_to_errno(int);
82#define encode_getfh_maxsz (op_encode_hdr_maxsz) 83#define encode_getfh_maxsz (op_encode_hdr_maxsz)
83#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ 84#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
84 ((3+NFS4_FHSIZE) >> 2)) 85 ((3+NFS4_FHSIZE) >> 2))
85#define encode_getattr_maxsz (op_encode_hdr_maxsz + 3) 86#define nfs4_fattr_bitmap_maxsz 3
87#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
86#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) 88#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
87#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) 89#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
88#define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz) 90/* This is based on getfattr, which uses the most attributes: */
89#define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \ 91#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
90 nfs4_fattr_bitmap_maxsz) 92 3 + 3 + 3 + 2 * nfs4_name_maxsz))
93#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
94 nfs4_fattr_value_maxsz)
95#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
91#define encode_savefh_maxsz (op_encode_hdr_maxsz) 96#define encode_savefh_maxsz (op_encode_hdr_maxsz)
92#define decode_savefh_maxsz (op_decode_hdr_maxsz) 97#define decode_savefh_maxsz (op_decode_hdr_maxsz)
93#define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) 98#define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2)
@@ -122,11 +127,11 @@ static int nfs_stat_to_errno(int);
122#define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 127#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
123 1 + nfs4_name_maxsz + \ 128 1 + nfs4_name_maxsz + \
124 nfs4_path_maxsz + \ 129 nfs4_path_maxsz + \
125 nfs4_fattr_bitmap_maxsz) 130 nfs4_fattr_maxsz)
126#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) 131#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
127#define encode_create_maxsz (op_encode_hdr_maxsz + \ 132#define encode_create_maxsz (op_encode_hdr_maxsz + \
128 2 + nfs4_name_maxsz + \ 133 2 + nfs4_name_maxsz + \
129 nfs4_fattr_bitmap_maxsz) 134 nfs4_fattr_maxsz)
130#define decode_create_maxsz (op_decode_hdr_maxsz + 8) 135#define decode_create_maxsz (op_decode_hdr_maxsz + 8)
131#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) 136#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
132#define decode_delegreturn_maxsz (op_decode_hdr_maxsz) 137#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
@@ -205,7 +210,7 @@ static int nfs_stat_to_errno(int);
205#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ 210#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
206 encode_putfh_maxsz + \ 211 encode_putfh_maxsz + \
207 op_encode_hdr_maxsz + 4 + \ 212 op_encode_hdr_maxsz + 4 + \
208 nfs4_fattr_bitmap_maxsz + \ 213 nfs4_fattr_maxsz + \
209 encode_getattr_maxsz) 214 encode_getattr_maxsz)
210#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ 215#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
211 decode_putfh_maxsz + \ 216 decode_putfh_maxsz + \
@@ -360,6 +365,20 @@ static int nfs_stat_to_errno(int);
360 encode_delegreturn_maxsz) 365 encode_delegreturn_maxsz)
361#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ 366#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
362 decode_delegreturn_maxsz) 367 decode_delegreturn_maxsz)
368#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
369 encode_putfh_maxsz + \
370 encode_getattr_maxsz)
371#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
372 decode_putfh_maxsz + \
373 op_decode_hdr_maxsz + \
374 nfs4_fattr_bitmap_maxsz + 1)
375#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
376 encode_putfh_maxsz + \
377 op_encode_hdr_maxsz + 4 + \
378 nfs4_fattr_bitmap_maxsz + 1)
379#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
380 decode_putfh_maxsz + \
381 op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
363 382
364static struct { 383static struct {
365 unsigned int mode; 384 unsigned int mode;
@@ -459,7 +478,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
459 * In the worst-case, this would be 478 * In the worst-case, this would be
460 * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) 479 * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
461 * = 36 bytes, plus any contribution from variable-length fields 480 * = 36 bytes, plus any contribution from variable-length fields
462 * such as owner/group/acl's. 481 * such as owner/group.
463 */ 482 */
464 len = 16; 483 len = 16;
465 484
@@ -660,8 +679,6 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1
660 679
661static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask) 680static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
662{ 681{
663 extern u32 nfs4_fattr_bitmap[];
664
665 return encode_getattr_two(xdr, 682 return encode_getattr_two(xdr,
666 bitmask[0] & nfs4_fattr_bitmap[0], 683 bitmask[0] & nfs4_fattr_bitmap[0],
667 bitmask[1] & nfs4_fattr_bitmap[1]); 684 bitmask[1] & nfs4_fattr_bitmap[1]);
@@ -669,8 +686,6 @@ static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
669 686
670static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask) 687static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
671{ 688{
672 extern u32 nfs4_fsinfo_bitmap[];
673
674 return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], 689 return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
675 bitmask[1] & nfs4_fsinfo_bitmap[1]); 690 bitmask[1] & nfs4_fsinfo_bitmap[1]);
676} 691}
@@ -969,7 +984,6 @@ static int encode_putrootfh(struct xdr_stream *xdr)
969 984
970static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) 985static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
971{ 986{
972 extern nfs4_stateid zero_stateid;
973 nfs4_stateid stateid; 987 nfs4_stateid stateid;
974 uint32_t *p; 988 uint32_t *p;
975 989
@@ -1000,6 +1014,10 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
1000static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req) 1014static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
1001{ 1015{
1002 struct rpc_auth *auth = req->rq_task->tk_auth; 1016 struct rpc_auth *auth = req->rq_task->tk_auth;
1017 uint32_t attrs[2] = {
1018 FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
1019 FATTR4_WORD1_MOUNTED_ON_FILEID,
1020 };
1003 int replen; 1021 int replen;
1004 uint32_t *p; 1022 uint32_t *p;
1005 1023
@@ -1010,13 +1028,20 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1010 WRITE32(readdir->count >> 1); /* We're not doing readdirplus */ 1028 WRITE32(readdir->count >> 1); /* We're not doing readdirplus */
1011 WRITE32(readdir->count); 1029 WRITE32(readdir->count);
1012 WRITE32(2); 1030 WRITE32(2);
1013 if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) { 1031 /* Switch to mounted_on_fileid if the server supports it */
1014 WRITE32(0); 1032 if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
1015 WRITE32(FATTR4_WORD1_MOUNTED_ON_FILEID); 1033 attrs[0] &= ~FATTR4_WORD0_FILEID;
1016 } else { 1034 else
1017 WRITE32(FATTR4_WORD0_FILEID); 1035 attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
1018 WRITE32(0); 1036 WRITE32(attrs[0] & readdir->bitmask[0]);
1019 } 1037 WRITE32(attrs[1] & readdir->bitmask[1]);
1038 dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
1039 __FUNCTION__,
1040 (unsigned long long)readdir->cookie,
1041 ((u32 *)readdir->verifier.data)[0],
1042 ((u32 *)readdir->verifier.data)[1],
1043 attrs[0] & readdir->bitmask[0],
1044 attrs[1] & readdir->bitmask[1]);
1020 1045
1021 /* set up reply kvec 1046 /* set up reply kvec
1022 * toplevel_status + taglen + rescount + OP_PUTFH + status 1047 * toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -1025,6 +1050,9 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1025 replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2; 1050 replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
1026 xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages, 1051 xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages,
1027 readdir->pgbase, readdir->count); 1052 readdir->pgbase, readdir->count);
1053 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
1054 __FUNCTION__, replen, readdir->pages,
1055 readdir->pgbase, readdir->count);
1028 1056
1029 return 0; 1057 return 0;
1030} 1058}
@@ -1089,6 +1117,25 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client
1089} 1117}
1090 1118
1091static int 1119static int
1120encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
1121{
1122 uint32_t *p;
1123
1124 RESERVE_SPACE(4+sizeof(zero_stateid.data));
1125 WRITE32(OP_SETATTR);
1126 WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
1127 RESERVE_SPACE(2*4);
1128 WRITE32(1);
1129 WRITE32(FATTR4_WORD0_ACL);
1130 if (arg->acl_len % 4)
1131 return -EINVAL;
1132 RESERVE_SPACE(4);
1133 WRITE32(arg->acl_len);
1134 xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
1135 return 0;
1136}
1137
1138static int
1092encode_savefh(struct xdr_stream *xdr) 1139encode_savefh(struct xdr_stream *xdr)
1093{ 1140{
1094 uint32_t *p; 1141 uint32_t *p;
@@ -1632,6 +1679,34 @@ out:
1632} 1679}
1633 1680
1634/* 1681/*
1682 * Encode a GETACL request
1683 */
1684static int
1685nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p,
1686 struct nfs_getaclargs *args)
1687{
1688 struct xdr_stream xdr;
1689 struct rpc_auth *auth = req->rq_task->tk_auth;
1690 struct compound_hdr hdr = {
1691 .nops = 2,
1692 };
1693 int replen, status;
1694
1695 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1696 encode_compound_hdr(&xdr, &hdr);
1697 status = encode_putfh(&xdr, args->fh);
1698 if (status)
1699 goto out;
1700 status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0);
1701 /* set up reply buffer: */
1702 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
1703 xdr_inline_pages(&req->rq_rcv_buf, replen,
1704 args->acl_pages, args->acl_pgbase, args->acl_len);
1705out:
1706 return status;
1707}
1708
1709/*
1635 * Encode a WRITE request 1710 * Encode a WRITE request
1636 */ 1711 */
1637static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args) 1712static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
@@ -1697,7 +1772,6 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs
1697 */ 1772 */
1698static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args) 1773static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args)
1699{ 1774{
1700 extern u32 nfs4_pathconf_bitmap[2];
1701 struct xdr_stream xdr; 1775 struct xdr_stream xdr;
1702 struct compound_hdr hdr = { 1776 struct compound_hdr hdr = {
1703 .nops = 2, 1777 .nops = 2,
@@ -1718,7 +1792,6 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct
1718 */ 1792 */
1719static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args) 1793static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args)
1720{ 1794{
1721 extern u32 nfs4_statfs_bitmap[];
1722 struct xdr_stream xdr; 1795 struct xdr_stream xdr;
1723 struct compound_hdr hdr = { 1796 struct compound_hdr hdr = {
1724 .nops = 2, 1797 .nops = 2,
@@ -3003,6 +3076,11 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
3003 return status; 3076 return status;
3004 READ_BUF(8); 3077 READ_BUF(8);
3005 COPYMEM(readdir->verifier.data, 8); 3078 COPYMEM(readdir->verifier.data, 8);
3079 dprintk("%s: verifier = 0x%x%x\n",
3080 __FUNCTION__,
3081 ((u32 *)readdir->verifier.data)[0],
3082 ((u32 *)readdir->verifier.data)[1]);
3083
3006 3084
3007 hdrlen = (char *) p - (char *) iov->iov_base; 3085 hdrlen = (char *) p - (char *) iov->iov_base;
3008 recvd = rcvbuf->len - hdrlen; 3086 recvd = rcvbuf->len - hdrlen;
@@ -3017,12 +3095,14 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
3017 for (nr = 0; *p++; nr++) { 3095 for (nr = 0; *p++; nr++) {
3018 if (p + 3 > end) 3096 if (p + 3 > end)
3019 goto short_pkt; 3097 goto short_pkt;
3098 dprintk("cookie = %Lu, ", *((unsigned long long *)p));
3020 p += 2; /* cookie */ 3099 p += 2; /* cookie */
3021 len = ntohl(*p++); /* filename length */ 3100 len = ntohl(*p++); /* filename length */
3022 if (len > NFS4_MAXNAMLEN) { 3101 if (len > NFS4_MAXNAMLEN) {
3023 printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); 3102 printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
3024 goto err_unmap; 3103 goto err_unmap;
3025 } 3104 }
3105 dprintk("filename = %*s\n", len, (char *)p);
3026 p += XDR_QUADLEN(len); 3106 p += XDR_QUADLEN(len);
3027 if (p + 1 > end) 3107 if (p + 1 > end)
3028 goto short_pkt; 3108 goto short_pkt;
@@ -3042,6 +3122,7 @@ out:
3042 kunmap_atomic(kaddr, KM_USER0); 3122 kunmap_atomic(kaddr, KM_USER0);
3043 return 0; 3123 return 0;
3044short_pkt: 3124short_pkt:
3125 dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
3045 entry[0] = entry[1] = 0; 3126 entry[0] = entry[1] = 0;
3046 /* truncate listing ? */ 3127 /* truncate listing ? */
3047 if (!nr) { 3128 if (!nr) {
@@ -3127,6 +3208,47 @@ static int decode_renew(struct xdr_stream *xdr)
3127 return decode_op_hdr(xdr, OP_RENEW); 3208 return decode_op_hdr(xdr, OP_RENEW);
3128} 3209}
3129 3210
3211static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
3212 size_t *acl_len)
3213{
3214 uint32_t *savep;
3215 uint32_t attrlen,
3216 bitmap[2] = {0};
3217 struct kvec *iov = req->rq_rcv_buf.head;
3218 int status;
3219
3220 *acl_len = 0;
3221 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
3222 goto out;
3223 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
3224 goto out;
3225 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
3226 goto out;
3227
3228 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
3229 return -EIO;
3230 if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
3231 int hdrlen, recvd;
3232
3233 /* We ignore &savep and don't do consistency checks on
3234 * the attr length. Let userspace figure it out.... */
3235 hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
3236 recvd = req->rq_rcv_buf.len - hdrlen;
3237 if (attrlen > recvd) {
3238 printk(KERN_WARNING "NFS: server cheating in getattr"
3239 " acl reply: attrlen %u > recvd %u\n",
3240 attrlen, recvd);
3241 return -EINVAL;
3242 }
3243 if (attrlen <= *acl_len)
3244 xdr_read_pages(xdr, attrlen);
3245 *acl_len = attrlen;
3246 }
3247
3248out:
3249 return status;
3250}
3251
3130static int 3252static int
3131decode_savefh(struct xdr_stream *xdr) 3253decode_savefh(struct xdr_stream *xdr)
3132{ 3254{
@@ -3418,6 +3540,71 @@ out:
3418 3540
3419} 3541}
3420 3542
3543/*
3544 * Encode an SETACL request
3545 */
3546static int
3547nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args)
3548{
3549 struct xdr_stream xdr;
3550 struct compound_hdr hdr = {
3551 .nops = 2,
3552 };
3553 int status;
3554
3555 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
3556 encode_compound_hdr(&xdr, &hdr);
3557 status = encode_putfh(&xdr, args->fh);
3558 if (status)
3559 goto out;
3560 status = encode_setacl(&xdr, args);
3561out:
3562 return status;
3563}
3564/*
3565 * Decode SETACL response
3566 */
3567static int
3568nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res)
3569{
3570 struct xdr_stream xdr;
3571 struct compound_hdr hdr;
3572 int status;
3573
3574 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3575 status = decode_compound_hdr(&xdr, &hdr);
3576 if (status)
3577 goto out;
3578 status = decode_putfh(&xdr);
3579 if (status)
3580 goto out;
3581 status = decode_setattr(&xdr, res);
3582out:
3583 return status;
3584}
3585
3586/*
3587 * Decode GETACL response
3588 */
3589static int
3590nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len)
3591{
3592 struct xdr_stream xdr;
3593 struct compound_hdr hdr;
3594 int status;
3595
3596 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3597 status = decode_compound_hdr(&xdr, &hdr);
3598 if (status)
3599 goto out;
3600 status = decode_putfh(&xdr);
3601 if (status)
3602 goto out;
3603 status = decode_getacl(&xdr, rqstp, acl_len);
3604
3605out:
3606 return status;
3607}
3421 3608
3422/* 3609/*
3423 * Decode CLOSE response 3610 * Decode CLOSE response
@@ -3895,6 +4082,12 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
3895 } 4082 }
3896 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */ 4083 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
3897 if (len > 0) { 4084 if (len > 0) {
4085 if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
4086 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
4087 /* Ignore the return value of rdattr_error for now */
4088 p++;
4089 len--;
4090 }
3898 if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID) 4091 if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
3899 xdr_decode_hyper(p, &entry->ino); 4092 xdr_decode_hyper(p, &entry->ino);
3900 else if (bitmap[0] == FATTR4_WORD0_FILEID) 4093 else if (bitmap[0] == FATTR4_WORD0_FILEID)
@@ -3934,6 +4127,8 @@ static struct {
3934 { NFS4ERR_DQUOT, EDQUOT }, 4127 { NFS4ERR_DQUOT, EDQUOT },
3935 { NFS4ERR_STALE, ESTALE }, 4128 { NFS4ERR_STALE, ESTALE },
3936 { NFS4ERR_BADHANDLE, EBADHANDLE }, 4129 { NFS4ERR_BADHANDLE, EBADHANDLE },
4130 { NFS4ERR_BADOWNER, EINVAL },
4131 { NFS4ERR_BADNAME, EINVAL },
3937 { NFS4ERR_BAD_COOKIE, EBADCOOKIE }, 4132 { NFS4ERR_BAD_COOKIE, EBADCOOKIE },
3938 { NFS4ERR_NOTSUPP, ENOTSUPP }, 4133 { NFS4ERR_NOTSUPP, ENOTSUPP },
3939 { NFS4ERR_TOOSMALL, ETOOSMALL }, 4134 { NFS4ERR_TOOSMALL, ETOOSMALL },
@@ -4019,6 +4214,8 @@ struct rpc_procinfo nfs4_procedures[] = {
4019 PROC(READDIR, enc_readdir, dec_readdir), 4214 PROC(READDIR, enc_readdir, dec_readdir),
4020 PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), 4215 PROC(SERVER_CAPS, enc_server_caps, dec_server_caps),
4021 PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), 4216 PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn),
4217 PROC(GETACL, enc_getacl, dec_getacl),
4218 PROC(SETACL, enc_setacl, dec_setacl),
4022}; 4219};
4023 4220
4024struct rpc_version nfs_version4 = { 4221struct rpc_version nfs_version4 = {
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index fd5bc596fe8a..1b272a135a31 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -124,6 +124,7 @@ enum {
124 Opt_soft, Opt_hard, Opt_intr, 124 Opt_soft, Opt_hard, Opt_intr,
125 Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, 125 Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac,
126 Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp, 126 Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
127 Opt_acl, Opt_noacl,
127 /* Error token */ 128 /* Error token */
128 Opt_err 129 Opt_err
129}; 130};
@@ -158,6 +159,8 @@ static match_table_t __initdata tokens = {
158 {Opt_udp, "udp"}, 159 {Opt_udp, "udp"},
159 {Opt_tcp, "proto=tcp"}, 160 {Opt_tcp, "proto=tcp"},
160 {Opt_tcp, "tcp"}, 161 {Opt_tcp, "tcp"},
162 {Opt_acl, "acl"},
163 {Opt_noacl, "noacl"},
161 {Opt_err, NULL} 164 {Opt_err, NULL}
162 165
163}; 166};
@@ -266,6 +269,12 @@ static int __init root_nfs_parse(char *name, char *buf)
266 case Opt_tcp: 269 case Opt_tcp:
267 nfs_data.flags |= NFS_MOUNT_TCP; 270 nfs_data.flags |= NFS_MOUNT_TCP;
268 break; 271 break;
272 case Opt_acl:
273 nfs_data.flags &= ~NFS_MOUNT_NOACL;
274 break;
275 case Opt_noacl:
276 nfs_data.flags |= NFS_MOUNT_NOACL;
277 break;
269 default : 278 default :
270 return 0; 279 return 0;
271 } 280 }
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 4f1ba723848d..d53857b148e2 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -107,11 +107,38 @@ void nfs_unlock_request(struct nfs_page *req)
107 smp_mb__before_clear_bit(); 107 smp_mb__before_clear_bit();
108 clear_bit(PG_BUSY, &req->wb_flags); 108 clear_bit(PG_BUSY, &req->wb_flags);
109 smp_mb__after_clear_bit(); 109 smp_mb__after_clear_bit();
110 wake_up_all(&req->wb_context->waitq); 110 wake_up_bit(&req->wb_flags, PG_BUSY);
111 nfs_release_request(req); 111 nfs_release_request(req);
112} 112}
113 113
114/** 114/**
115 * nfs_set_page_writeback_locked - Lock a request for writeback
116 * @req:
117 */
118int nfs_set_page_writeback_locked(struct nfs_page *req)
119{
120 struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
121
122 if (!nfs_lock_request(req))
123 return 0;
124 radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
125 return 1;
126}
127
128/**
129 * nfs_clear_page_writeback - Unlock request and wake up sleepers
130 */
131void nfs_clear_page_writeback(struct nfs_page *req)
132{
133 struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
134
135 spin_lock(&nfsi->req_lock);
136 radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
137 spin_unlock(&nfsi->req_lock);
138 nfs_unlock_request(req);
139}
140
141/**
115 * nfs_clear_request - Free up all resources allocated to the request 142 * nfs_clear_request - Free up all resources allocated to the request
116 * @req: 143 * @req:
117 * 144 *
@@ -150,34 +177,15 @@ nfs_release_request(struct nfs_page *req)
150 nfs_page_free(req); 177 nfs_page_free(req);
151} 178}
152 179
153/** 180static int nfs_wait_bit_interruptible(void *word)
154 * nfs_list_add_request - Insert a request into a sorted list
155 * @req: request
156 * @head: head of list into which to insert the request.
157 *
158 * Note that the wb_list is sorted by page index in order to facilitate
159 * coalescing of requests.
160 * We use an insertion sort that is optimized for the case of appended
161 * writes.
162 */
163void
164nfs_list_add_request(struct nfs_page *req, struct list_head *head)
165{ 181{
166 struct list_head *pos; 182 int ret = 0;
167 183
168#ifdef NFS_PARANOIA 184 if (signal_pending(current))
169 if (!list_empty(&req->wb_list)) { 185 ret = -ERESTARTSYS;
170 printk(KERN_ERR "NFS: Add to list failed!\n"); 186 else
171 BUG(); 187 schedule();
172 } 188 return ret;
173#endif
174 list_for_each_prev(pos, head) {
175 struct nfs_page *p = nfs_list_entry(pos);
176 if (p->wb_index < req->wb_index)
177 break;
178 }
179 list_add(&req->wb_list, pos);
180 req->wb_list_head = head;
181} 189}
182 190
183/** 191/**
@@ -190,12 +198,22 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
190int 198int
191nfs_wait_on_request(struct nfs_page *req) 199nfs_wait_on_request(struct nfs_page *req)
192{ 200{
193 struct inode *inode = req->wb_context->dentry->d_inode; 201 struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
194 struct rpc_clnt *clnt = NFS_CLIENT(inode); 202 sigset_t oldmask;
195 203 int ret = 0;
196 if (!NFS_WBACK_BUSY(req)) 204
197 return 0; 205 if (!test_bit(PG_BUSY, &req->wb_flags))
198 return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req)); 206 goto out;
207 /*
208 * Note: the call to rpc_clnt_sigmask() suffices to ensure that we
209 * are not interrupted if intr flag is not set
210 */
211 rpc_clnt_sigmask(clnt, &oldmask);
212 ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY,
213 nfs_wait_bit_interruptible, TASK_INTERRUPTIBLE);
214 rpc_clnt_sigunmask(clnt, &oldmask);
215out:
216 return ret;
199} 217}
200 218
201/** 219/**
@@ -243,6 +261,62 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
243 return npages; 261 return npages;
244} 262}
245 263
264#define NFS_SCAN_MAXENTRIES 16
265/**
266 * nfs_scan_lock_dirty - Scan the radix tree for dirty requests
267 * @nfsi: NFS inode
268 * @dst: Destination list
269 * @idx_start: lower bound of page->index to scan
270 * @npages: idx_start + npages sets the upper bound to scan.
271 *
272 * Moves elements from one of the inode request lists.
273 * If the number of requests is set to 0, the entire address_space
274 * starting at index idx_start, is scanned.
275 * The requests are *not* checked to ensure that they form a contiguous set.
276 * You must be holding the inode's req_lock when calling this function
277 */
278int
279nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
280 unsigned long idx_start, unsigned int npages)
281{
282 struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
283 struct nfs_page *req;
284 unsigned long idx_end;
285 int found, i;
286 int res;
287
288 res = 0;
289 if (npages == 0)
290 idx_end = ~0;
291 else
292 idx_end = idx_start + npages - 1;
293
294 for (;;) {
295 found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
296 (void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES,
297 NFS_PAGE_TAG_DIRTY);
298 if (found <= 0)
299 break;
300 for (i = 0; i < found; i++) {
301 req = pgvec[i];
302 if (req->wb_index > idx_end)
303 goto out;
304
305 idx_start = req->wb_index + 1;
306
307 if (nfs_set_page_writeback_locked(req)) {
308 radix_tree_tag_clear(&nfsi->nfs_page_tree,
309 req->wb_index, NFS_PAGE_TAG_DIRTY);
310 nfs_list_remove_request(req);
311 nfs_list_add_request(req, dst);
312 res++;
313 }
314 }
315 }
316out:
317 return res;
318}
319
246/** 320/**
247 * nfs_scan_list - Scan a list for matching requests 321 * nfs_scan_list - Scan a list for matching requests
248 * @head: One of the NFS inode request lists 322 * @head: One of the NFS inode request lists
@@ -280,7 +354,7 @@ nfs_scan_list(struct list_head *head, struct list_head *dst,
280 if (req->wb_index > idx_end) 354 if (req->wb_index > idx_end)
281 break; 355 break;
282 356
283 if (!nfs_lock_request(req)) 357 if (!nfs_set_page_writeback_locked(req))
284 continue; 358 continue;
285 nfs_list_remove_request(req); 359 nfs_list_remove_request(req);
286 nfs_list_add_request(req, dst); 360 nfs_list_add_request(req, dst);
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index d31b4d6e5a5e..cedf636bcf3c 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -622,6 +622,7 @@ struct nfs_rpc_ops nfs_v2_clientops = {
622 .version = 2, /* protocol version */ 622 .version = 2, /* protocol version */
623 .dentry_ops = &nfs_dentry_operations, 623 .dentry_ops = &nfs_dentry_operations,
624 .dir_inode_ops = &nfs_dir_inode_operations, 624 .dir_inode_ops = &nfs_dir_inode_operations,
625 .file_inode_ops = &nfs_file_inode_operations,
625 .getroot = nfs_proc_get_root, 626 .getroot = nfs_proc_get_root,
626 .getattr = nfs_proc_getattr, 627 .getattr = nfs_proc_getattr,
627 .setattr = nfs_proc_setattr, 628 .setattr = nfs_proc_setattr,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index a0042fb58634..6f866b8aa2d5 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -173,7 +173,6 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
173 if (len < PAGE_CACHE_SIZE) 173 if (len < PAGE_CACHE_SIZE)
174 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); 174 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
175 175
176 nfs_lock_request(new);
177 nfs_list_add_request(new, &one_request); 176 nfs_list_add_request(new, &one_request);
178 nfs_pagein_one(&one_request, inode); 177 nfs_pagein_one(&one_request, inode);
179 return 0; 178 return 0;
@@ -185,7 +184,6 @@ static void nfs_readpage_release(struct nfs_page *req)
185 184
186 nfs_clear_request(req); 185 nfs_clear_request(req);
187 nfs_release_request(req); 186 nfs_release_request(req);
188 nfs_unlock_request(req);
189 187
190 dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", 188 dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
191 req->wb_context->dentry->d_inode->i_sb->s_id, 189 req->wb_context->dentry->d_inode->i_sb->s_id,
@@ -553,7 +551,6 @@ readpage_async_filler(void *data, struct page *page)
553 } 551 }
554 if (len < PAGE_CACHE_SIZE) 552 if (len < PAGE_CACHE_SIZE)
555 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); 553 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
556 nfs_lock_request(new);
557 nfs_list_add_request(new, desc->head); 554 nfs_list_add_request(new, desc->head);
558 return 0; 555 return 0;
559} 556}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 6f7a4af3bc46..5130eda231d7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -220,7 +220,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
220 ClearPageError(page); 220 ClearPageError(page);
221 221
222io_error: 222io_error:
223 nfs_end_data_update_defer(inode); 223 nfs_end_data_update(inode);
224 nfs_writedata_free(wdata); 224 nfs_writedata_free(wdata);
225 return written ? written : result; 225 return written ? written : result;
226} 226}
@@ -352,7 +352,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
352 if (err < 0) 352 if (err < 0)
353 goto out; 353 goto out;
354 } 354 }
355 err = nfs_commit_inode(inode, 0, 0, wb_priority(wbc)); 355 err = nfs_commit_inode(inode, wb_priority(wbc));
356 if (err > 0) { 356 if (err > 0) {
357 wbc->nr_to_write -= err; 357 wbc->nr_to_write -= err;
358 err = 0; 358 err = 0;
@@ -401,7 +401,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
401 nfsi->npages--; 401 nfsi->npages--;
402 if (!nfsi->npages) { 402 if (!nfsi->npages) {
403 spin_unlock(&nfsi->req_lock); 403 spin_unlock(&nfsi->req_lock);
404 nfs_end_data_update_defer(inode); 404 nfs_end_data_update(inode);
405 iput(inode); 405 iput(inode);
406 } else 406 } else
407 spin_unlock(&nfsi->req_lock); 407 spin_unlock(&nfsi->req_lock);
@@ -446,6 +446,8 @@ nfs_mark_request_dirty(struct nfs_page *req)
446 struct nfs_inode *nfsi = NFS_I(inode); 446 struct nfs_inode *nfsi = NFS_I(inode);
447 447
448 spin_lock(&nfsi->req_lock); 448 spin_lock(&nfsi->req_lock);
449 radix_tree_tag_set(&nfsi->nfs_page_tree,
450 req->wb_index, NFS_PAGE_TAG_DIRTY);
449 nfs_list_add_request(req, &nfsi->dirty); 451 nfs_list_add_request(req, &nfsi->dirty);
450 nfsi->ndirty++; 452 nfsi->ndirty++;
451 spin_unlock(&nfsi->req_lock); 453 spin_unlock(&nfsi->req_lock);
@@ -503,13 +505,12 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
503 505
504 spin_lock(&nfsi->req_lock); 506 spin_lock(&nfsi->req_lock);
505 next = idx_start; 507 next = idx_start;
506 while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) { 508 while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
507 if (req->wb_index > idx_end) 509 if (req->wb_index > idx_end)
508 break; 510 break;
509 511
510 next = req->wb_index + 1; 512 next = req->wb_index + 1;
511 if (!NFS_WBACK_BUSY(req)) 513 BUG_ON(!NFS_WBACK_BUSY(req));
512 continue;
513 514
514 atomic_inc(&req->wb_count); 515 atomic_inc(&req->wb_count);
515 spin_unlock(&nfsi->req_lock); 516 spin_unlock(&nfsi->req_lock);
@@ -538,12 +539,15 @@ static int
538nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) 539nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
539{ 540{
540 struct nfs_inode *nfsi = NFS_I(inode); 541 struct nfs_inode *nfsi = NFS_I(inode);
541 int res; 542 int res = 0;
542 res = nfs_scan_list(&nfsi->dirty, dst, idx_start, npages); 543
543 nfsi->ndirty -= res; 544 if (nfsi->ndirty != 0) {
544 sub_page_state(nr_dirty,res); 545 res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages);
545 if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty)) 546 nfsi->ndirty -= res;
546 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n"); 547 sub_page_state(nr_dirty,res);
548 if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
549 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
550 }
547 return res; 551 return res;
548} 552}
549 553
@@ -562,11 +566,14 @@ static int
562nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) 566nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
563{ 567{
564 struct nfs_inode *nfsi = NFS_I(inode); 568 struct nfs_inode *nfsi = NFS_I(inode);
565 int res; 569 int res = 0;
566 res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages); 570
567 nfsi->ncommit -= res; 571 if (nfsi->ncommit != 0) {
568 if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) 572 res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);
569 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); 573 nfsi->ncommit -= res;
574 if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
575 printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
576 }
570 return res; 577 return res;
571} 578}
572#endif 579#endif
@@ -750,7 +757,7 @@ int nfs_updatepage(struct file *file, struct page *page,
750 * is entirely in cache, it may be more efficient to avoid 757 * is entirely in cache, it may be more efficient to avoid
751 * fragmenting write requests. 758 * fragmenting write requests.
752 */ 759 */
753 if (PageUptodate(page) && inode->i_flock == NULL) { 760 if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
754 loff_t end_offs = i_size_read(inode) - 1; 761 loff_t end_offs = i_size_read(inode) - 1;
755 unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT; 762 unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
756 763
@@ -821,7 +828,7 @@ out:
821#else 828#else
822 nfs_inode_remove_request(req); 829 nfs_inode_remove_request(req);
823#endif 830#endif
824 nfs_unlock_request(req); 831 nfs_clear_page_writeback(req);
825} 832}
826 833
827static inline int flush_task_priority(int how) 834static inline int flush_task_priority(int how)
@@ -952,7 +959,7 @@ out_bad:
952 nfs_writedata_free(data); 959 nfs_writedata_free(data);
953 } 960 }
954 nfs_mark_request_dirty(req); 961 nfs_mark_request_dirty(req);
955 nfs_unlock_request(req); 962 nfs_clear_page_writeback(req);
956 return -ENOMEM; 963 return -ENOMEM;
957} 964}
958 965
@@ -1002,7 +1009,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
1002 struct nfs_page *req = nfs_list_entry(head->next); 1009 struct nfs_page *req = nfs_list_entry(head->next);
1003 nfs_list_remove_request(req); 1010 nfs_list_remove_request(req);
1004 nfs_mark_request_dirty(req); 1011 nfs_mark_request_dirty(req);
1005 nfs_unlock_request(req); 1012 nfs_clear_page_writeback(req);
1006 } 1013 }
1007 return -ENOMEM; 1014 return -ENOMEM;
1008} 1015}
@@ -1029,7 +1036,7 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
1029 req = nfs_list_entry(head->next); 1036 req = nfs_list_entry(head->next);
1030 nfs_list_remove_request(req); 1037 nfs_list_remove_request(req);
1031 nfs_mark_request_dirty(req); 1038 nfs_mark_request_dirty(req);
1032 nfs_unlock_request(req); 1039 nfs_clear_page_writeback(req);
1033 } 1040 }
1034 return error; 1041 return error;
1035} 1042}
@@ -1121,7 +1128,7 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
1121 nfs_inode_remove_request(req); 1128 nfs_inode_remove_request(req);
1122#endif 1129#endif
1123 next: 1130 next:
1124 nfs_unlock_request(req); 1131 nfs_clear_page_writeback(req);
1125 } 1132 }
1126} 1133}
1127 1134
@@ -1210,36 +1217,24 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1210 struct nfs_write_data *data, int how) 1217 struct nfs_write_data *data, int how)
1211{ 1218{
1212 struct rpc_task *task = &data->task; 1219 struct rpc_task *task = &data->task;
1213 struct nfs_page *first, *last; 1220 struct nfs_page *first;
1214 struct inode *inode; 1221 struct inode *inode;
1215 loff_t start, end, len;
1216 1222
1217 /* Set up the RPC argument and reply structs 1223 /* Set up the RPC argument and reply structs
1218 * NB: take care not to mess about with data->commit et al. */ 1224 * NB: take care not to mess about with data->commit et al. */
1219 1225
1220 list_splice_init(head, &data->pages); 1226 list_splice_init(head, &data->pages);
1221 first = nfs_list_entry(data->pages.next); 1227 first = nfs_list_entry(data->pages.next);
1222 last = nfs_list_entry(data->pages.prev);
1223 inode = first->wb_context->dentry->d_inode; 1228 inode = first->wb_context->dentry->d_inode;
1224 1229
1225 /*
1226 * Determine the offset range of requests in the COMMIT call.
1227 * We rely on the fact that data->pages is an ordered list...
1228 */
1229 start = req_offset(first);
1230 end = req_offset(last) + last->wb_bytes;
1231 len = end - start;
1232 /* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */
1233 if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1))
1234 len = 0;
1235
1236 data->inode = inode; 1230 data->inode = inode;
1237 data->cred = first->wb_context->cred; 1231 data->cred = first->wb_context->cred;
1238 1232
1239 data->args.fh = NFS_FH(data->inode); 1233 data->args.fh = NFS_FH(data->inode);
1240 data->args.offset = start; 1234 /* Note: we always request a commit of the entire inode */
1241 data->args.count = len; 1235 data->args.offset = 0;
1242 data->res.count = len; 1236 data->args.count = 0;
1237 data->res.count = 0;
1243 data->res.fattr = &data->fattr; 1238 data->res.fattr = &data->fattr;
1244 data->res.verf = &data->verf; 1239 data->res.verf = &data->verf;
1245 1240
@@ -1278,7 +1273,7 @@ nfs_commit_list(struct list_head *head, int how)
1278 req = nfs_list_entry(head->next); 1273 req = nfs_list_entry(head->next);
1279 nfs_list_remove_request(req); 1274 nfs_list_remove_request(req);
1280 nfs_mark_request_commit(req); 1275 nfs_mark_request_commit(req);
1281 nfs_unlock_request(req); 1276 nfs_clear_page_writeback(req);
1282 } 1277 }
1283 return -ENOMEM; 1278 return -ENOMEM;
1284} 1279}
@@ -1324,7 +1319,7 @@ nfs_commit_done(struct rpc_task *task)
1324 dprintk(" mismatch\n"); 1319 dprintk(" mismatch\n");
1325 nfs_mark_request_dirty(req); 1320 nfs_mark_request_dirty(req);
1326 next: 1321 next:
1327 nfs_unlock_request(req); 1322 nfs_clear_page_writeback(req);
1328 res++; 1323 res++;
1329 } 1324 }
1330 sub_page_state(nr_unstable,res); 1325 sub_page_state(nr_unstable,res);
@@ -1342,16 +1337,23 @@ static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
1342 spin_lock(&nfsi->req_lock); 1337 spin_lock(&nfsi->req_lock);
1343 res = nfs_scan_dirty(inode, &head, idx_start, npages); 1338 res = nfs_scan_dirty(inode, &head, idx_start, npages);
1344 spin_unlock(&nfsi->req_lock); 1339 spin_unlock(&nfsi->req_lock);
1345 if (res) 1340 if (res) {
1346 error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how); 1341 struct nfs_server *server = NFS_SERVER(inode);
1342
1343 /* For single writes, FLUSH_STABLE is more efficient */
1344 if (res == nfsi->npages && nfsi->npages <= server->wpages) {
1345 if (res > 1 || nfs_list_entry(head.next)->wb_bytes <= server->wsize)
1346 how |= FLUSH_STABLE;
1347 }
1348 error = nfs_flush_list(&head, server->wpages, how);
1349 }
1347 if (error < 0) 1350 if (error < 0)
1348 return error; 1351 return error;
1349 return res; 1352 return res;
1350} 1353}
1351 1354
1352#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1355#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1353int nfs_commit_inode(struct inode *inode, unsigned long idx_start, 1356int nfs_commit_inode(struct inode *inode, int how)
1354 unsigned int npages, int how)
1355{ 1357{
1356 struct nfs_inode *nfsi = NFS_I(inode); 1358 struct nfs_inode *nfsi = NFS_I(inode);
1357 LIST_HEAD(head); 1359 LIST_HEAD(head);
@@ -1359,15 +1361,13 @@ int nfs_commit_inode(struct inode *inode, unsigned long idx_start,
1359 error = 0; 1361 error = 0;
1360 1362
1361 spin_lock(&nfsi->req_lock); 1363 spin_lock(&nfsi->req_lock);
1362 res = nfs_scan_commit(inode, &head, idx_start, npages); 1364 res = nfs_scan_commit(inode, &head, 0, 0);
1365 spin_unlock(&nfsi->req_lock);
1363 if (res) { 1366 if (res) {
1364 res += nfs_scan_commit(inode, &head, 0, 0);
1365 spin_unlock(&nfsi->req_lock);
1366 error = nfs_commit_list(&head, how); 1367 error = nfs_commit_list(&head, how);
1367 } else 1368 if (error < 0)
1368 spin_unlock(&nfsi->req_lock); 1369 return error;
1369 if (error < 0) 1370 }
1370 return error;
1371 return res; 1371 return res;
1372} 1372}
1373#endif 1373#endif
@@ -1389,7 +1389,7 @@ int nfs_sync_inode(struct inode *inode, unsigned long idx_start,
1389 error = nfs_flush_inode(inode, idx_start, npages, how); 1389 error = nfs_flush_inode(inode, idx_start, npages, how);
1390#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1390#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
1391 if (error == 0) 1391 if (error == 0)
1392 error = nfs_commit_inode(inode, idx_start, npages, how); 1392 error = nfs_commit_inode(inode, how);
1393#endif 1393#endif
1394 } while (error > 0); 1394 } while (error > 0);
1395 return error; 1395 return error;
diff --git a/fs/nfs_common/Makefile b/fs/nfs_common/Makefile
new file mode 100644
index 000000000000..f689ed82af3a
--- /dev/null
+++ b/fs/nfs_common/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for Linux filesystem routines that are shared by client and server.
3#
4
5obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o
6
7nfs_acl-objs := nfsacl.o
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
new file mode 100644
index 000000000000..18c58c32e326
--- /dev/null
+++ b/fs/nfs_common/nfsacl.c
@@ -0,0 +1,257 @@
1/*
2 * fs/nfs_common/nfsacl.c
3 *
4 * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
5 */
6
7/*
8 * The Solaris nfsacl 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/fs.h>
25#include <linux/sunrpc/xdr.h>
26#include <linux/nfsacl.h>
27#include <linux/nfs3.h>
28#include <linux/sort.h>
29
30MODULE_LICENSE("GPL");
31
32EXPORT_SYMBOL(nfsacl_encode);
33EXPORT_SYMBOL(nfsacl_decode);
34
35struct nfsacl_encode_desc {
36 struct xdr_array2_desc desc;
37 unsigned int count;
38 struct posix_acl *acl;
39 int typeflag;
40 uid_t uid;
41 gid_t gid;
42};
43
44static int
45xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
46{
47 struct nfsacl_encode_desc *nfsacl_desc =
48 (struct nfsacl_encode_desc *) desc;
49 u32 *p = (u32 *) elem;
50
51 if (nfsacl_desc->count < nfsacl_desc->acl->a_count) {
52 struct posix_acl_entry *entry =
53 &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
54
55 *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
56 switch(entry->e_tag) {
57 case ACL_USER_OBJ:
58 *p++ = htonl(nfsacl_desc->uid);
59 break;
60 case ACL_GROUP_OBJ:
61 *p++ = htonl(nfsacl_desc->gid);
62 break;
63 case ACL_USER:
64 case ACL_GROUP:
65 *p++ = htonl(entry->e_id);
66 break;
67 default: /* Solaris depends on that! */
68 *p++ = 0;
69 break;
70 }
71 *p++ = htonl(entry->e_perm & S_IRWXO);
72 } else {
73 const struct posix_acl_entry *pa, *pe;
74 int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE;
75
76 FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) {
77 if (pa->e_tag == ACL_GROUP_OBJ) {
78 group_obj_perm = pa->e_perm & S_IRWXO;
79 break;
80 }
81 }
82 /* fake up ACL_MASK entry */
83 *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag);
84 *p++ = htonl(0);
85 *p++ = htonl(group_obj_perm);
86 }
87
88 return 0;
89}
90
91unsigned int
92nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
93 struct posix_acl *acl, int encode_entries, int typeflag)
94{
95 int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0;
96 struct nfsacl_encode_desc nfsacl_desc = {
97 .desc = {
98 .elem_size = 12,
99 .array_len = encode_entries ? entries : 0,
100 .xcode = xdr_nfsace_encode,
101 },
102 .acl = acl,
103 .typeflag = typeflag,
104 .uid = inode->i_uid,
105 .gid = inode->i_gid,
106 };
107 int err;
108
109 if (entries > NFS_ACL_MAX_ENTRIES ||
110 xdr_encode_word(buf, base, entries))
111 return -EINVAL;
112 err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc);
113 if (!err)
114 err = 8 + nfsacl_desc.desc.elem_size *
115 nfsacl_desc.desc.array_len;
116 return err;
117}
118
119struct nfsacl_decode_desc {
120 struct xdr_array2_desc desc;
121 unsigned int count;
122 struct posix_acl *acl;
123};
124
125static int
126xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
127{
128 struct nfsacl_decode_desc *nfsacl_desc =
129 (struct nfsacl_decode_desc *) desc;
130 u32 *p = (u32 *) elem;
131 struct posix_acl_entry *entry;
132
133 if (!nfsacl_desc->acl) {
134 if (desc->array_len > NFS_ACL_MAX_ENTRIES)
135 return -EINVAL;
136 nfsacl_desc->acl = posix_acl_alloc(desc->array_len, GFP_KERNEL);
137 if (!nfsacl_desc->acl)
138 return -ENOMEM;
139 nfsacl_desc->count = 0;
140 }
141
142 entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
143 entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT;
144 entry->e_id = ntohl(*p++);
145 entry->e_perm = ntohl(*p++);
146
147 switch(entry->e_tag) {
148 case ACL_USER_OBJ:
149 case ACL_USER:
150 case ACL_GROUP_OBJ:
151 case ACL_GROUP:
152 case ACL_OTHER:
153 if (entry->e_perm & ~S_IRWXO)
154 return -EINVAL;
155 break;
156 case ACL_MASK:
157 /* Solaris sometimes sets additonal bits in the mask */
158 entry->e_perm &= S_IRWXO;
159 break;
160 default:
161 return -EINVAL;
162 }
163
164 return 0;
165}
166
167static int
168cmp_acl_entry(const void *x, const void *y)
169{
170 const struct posix_acl_entry *a = x, *b = y;
171
172 if (a->e_tag != b->e_tag)
173 return a->e_tag - b->e_tag;
174 else if (a->e_id > b->e_id)
175 return 1;
176 else if (a->e_id < b->e_id)
177 return -1;
178 else
179 return 0;
180}
181
182/*
183 * Convert from a Solaris ACL to a POSIX 1003.1e draft 17 ACL.
184 */
185static int
186posix_acl_from_nfsacl(struct posix_acl *acl)
187{
188 struct posix_acl_entry *pa, *pe,
189 *group_obj = NULL, *mask = NULL;
190
191 if (!acl)
192 return 0;
193
194 sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry),
195 cmp_acl_entry, NULL);
196
197 /* Clear undefined identifier fields and find the ACL_GROUP_OBJ
198 and ACL_MASK entries. */
199 FOREACH_ACL_ENTRY(pa, acl, pe) {
200 switch(pa->e_tag) {
201 case ACL_USER_OBJ:
202 pa->e_id = ACL_UNDEFINED_ID;
203 break;
204 case ACL_GROUP_OBJ:
205 pa->e_id = ACL_UNDEFINED_ID;
206 group_obj = pa;
207 break;
208 case ACL_MASK:
209 mask = pa;
210 /* fall through */
211 case ACL_OTHER:
212 pa->e_id = ACL_UNDEFINED_ID;
213 break;
214 }
215 }
216 if (acl->a_count == 4 && group_obj && mask &&
217 mask->e_perm == group_obj->e_perm) {
218 /* remove bogus ACL_MASK entry */
219 memmove(mask, mask+1, (3 - (mask - acl->a_entries)) *
220 sizeof(struct posix_acl_entry));
221 acl->a_count = 3;
222 }
223 return 0;
224}
225
226unsigned int
227nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
228 struct posix_acl **pacl)
229{
230 struct nfsacl_decode_desc nfsacl_desc = {
231 .desc = {
232 .elem_size = 12,
233 .xcode = pacl ? xdr_nfsace_decode : NULL,
234 },
235 };
236 u32 entries;
237 int err;
238
239 if (xdr_decode_word(buf, base, &entries) ||
240 entries > NFS_ACL_MAX_ENTRIES)
241 return -EINVAL;
242 err = xdr_decode_array2(buf, base + 4, &nfsacl_desc.desc);
243 if (err)
244 return err;
245 if (pacl) {
246 if (entries != nfsacl_desc.desc.array_len ||
247 posix_acl_from_nfsacl(nfsacl_desc.acl) != 0) {
248 posix_acl_release(nfsacl_desc.acl);
249 return -EINVAL;
250 }
251 *pacl = nfsacl_desc.acl;
252 }
253 if (aclcnt)
254 *aclcnt = entries;
255 return 8 + nfsacl_desc.desc.elem_size *
256 nfsacl_desc.desc.array_len;
257}
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index b8680a247f8b..ce341dc76d5e 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -6,7 +6,9 @@ obj-$(CONFIG_NFSD) += nfsd.o
6 6
7nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \ 7nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
8 export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o 8 export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
9nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
9nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o 10nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
11nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
10nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ 12nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
11 nfs4acl.o nfs4callback.o 13 nfs4acl.o nfs4callback.o nfs4recover.o
12nfsd-objs := $(nfsd-y) 14nfsd-objs := $(nfsd-y)
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
new file mode 100644
index 000000000000..7cbf0682b2f0
--- /dev/null
+++ b/fs/nfsd/nfs2acl.c
@@ -0,0 +1,336 @@
1/*
2 * linux/fs/nfsd/nfsacl.c
3 *
4 * Process version 2 NFSACL requests.
5 *
6 * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
7 */
8
9#include <linux/sunrpc/svc.h>
10#include <linux/nfs.h>
11#include <linux/nfsd/nfsd.h>
12#include <linux/nfsd/cache.h>
13#include <linux/nfsd/xdr.h>
14#include <linux/nfsd/xdr3.h>
15#include <linux/posix_acl.h>
16#include <linux/nfsacl.h>
17
18#define NFSDDBG_FACILITY NFSDDBG_PROC
19#define RETURN_STATUS(st) { resp->status = (st); return (st); }
20
21/*
22 * NULL call.
23 */
24static int
25nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
26{
27 return nfs_ok;
28}
29
30/*
31 * Get the Access and/or Default ACL of a file.
32 */
33static int nfsacld_proc_getacl(struct svc_rqst * rqstp,
34 struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
35{
36 svc_fh *fh;
37 struct posix_acl *acl;
38 int nfserr = 0;
39
40 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
41
42 fh = fh_copy(&resp->fh, &argp->fh);
43 if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
44 RETURN_STATUS(nfserr_inval);
45
46 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
47 RETURN_STATUS(nfserr_inval);
48 resp->mask = argp->mask;
49
50 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
51 acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
52 if (IS_ERR(acl)) {
53 int err = PTR_ERR(acl);
54
55 if (err == -ENODATA || err == -EOPNOTSUPP)
56 acl = NULL;
57 else {
58 nfserr = nfserrno(err);
59 goto fail;
60 }
61 }
62 if (acl == NULL) {
63 /* Solaris returns the inode's minimum ACL. */
64
65 struct inode *inode = fh->fh_dentry->d_inode;
66 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
67 }
68 resp->acl_access = acl;
69 }
70 if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
71 /* Check how Solaris handles requests for the Default ACL
72 of a non-directory! */
73
74 acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
75 if (IS_ERR(acl)) {
76 int err = PTR_ERR(acl);
77
78 if (err == -ENODATA || err == -EOPNOTSUPP)
79 acl = NULL;
80 else {
81 nfserr = nfserrno(err);
82 goto fail;
83 }
84 }
85 resp->acl_default = acl;
86 }
87
88 /* resp->acl_{access,default} are released in nfssvc_release_getacl. */
89 RETURN_STATUS(0);
90
91fail:
92 posix_acl_release(resp->acl_access);
93 posix_acl_release(resp->acl_default);
94 RETURN_STATUS(nfserr);
95}
96
97/*
98 * Set the Access and/or Default ACL of a file.
99 */
100static int nfsacld_proc_setacl(struct svc_rqst * rqstp,
101 struct nfsd3_setaclargs *argp,
102 struct nfsd_attrstat *resp)
103{
104 svc_fh *fh;
105 int nfserr = 0;
106
107 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
108
109 fh = fh_copy(&resp->fh, &argp->fh);
110 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
111
112 if (!nfserr) {
113 nfserr = nfserrno( nfsd_set_posix_acl(
114 fh, ACL_TYPE_ACCESS, argp->acl_access) );
115 }
116 if (!nfserr) {
117 nfserr = nfserrno( nfsd_set_posix_acl(
118 fh, ACL_TYPE_DEFAULT, argp->acl_default) );
119 }
120
121 /* argp->acl_{access,default} may have been allocated in
122 nfssvc_decode_setaclargs. */
123 posix_acl_release(argp->acl_access);
124 posix_acl_release(argp->acl_default);
125 return nfserr;
126}
127
128/*
129 * Check file attributes
130 */
131static int nfsacld_proc_getattr(struct svc_rqst * rqstp,
132 struct nfsd_fhandle *argp, struct nfsd_attrstat *resp)
133{
134 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
135
136 fh_copy(&resp->fh, &argp->fh);
137 return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
138}
139
140/*
141 * Check file access
142 */
143static int nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
144 struct nfsd3_accessres *resp)
145{
146 int nfserr;
147
148 dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",
149 SVCFH_fmt(&argp->fh),
150 argp->access);
151
152 fh_copy(&resp->fh, &argp->fh);
153 resp->access = argp->access;
154 nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
155 return nfserr;
156}
157
158/*
159 * XDR decode functions
160 */
161static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
162 struct nfsd3_getaclargs *argp)
163{
164 if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
165 return 0;
166 argp->mask = ntohl(*p); p++;
167
168 return xdr_argsize_check(rqstp, p);
169}
170
171
172static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
173 struct nfsd3_setaclargs *argp)
174{
175 struct kvec *head = rqstp->rq_arg.head;
176 unsigned int base;
177 int n;
178
179 if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
180 return 0;
181 argp->mask = ntohl(*p++);
182 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) ||
183 !xdr_argsize_check(rqstp, p))
184 return 0;
185
186 base = (char *)p - (char *)head->iov_base;
187 n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
188 (argp->mask & NFS_ACL) ?
189 &argp->acl_access : NULL);
190 if (n > 0)
191 n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
192 (argp->mask & NFS_DFACL) ?
193 &argp->acl_default : NULL);
194 return (n > 0);
195}
196
197static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, u32 *p,
198 struct nfsd_fhandle *argp)
199{
200 if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
201 return 0;
202 return xdr_argsize_check(rqstp, p);
203}
204
205static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
206 struct nfsd3_accessargs *argp)
207{
208 if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
209 return 0;
210 argp->access = ntohl(*p++);
211
212 return xdr_argsize_check(rqstp, p);
213}
214
215/*
216 * XDR encode functions
217 */
218
219/* GETACL */
220static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
221 struct nfsd3_getaclres *resp)
222{
223 struct dentry *dentry = resp->fh.fh_dentry;
224 struct inode *inode = dentry->d_inode;
225 int w = nfsacl_size(
226 (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
227 (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
228 struct kvec *head = rqstp->rq_res.head;
229 unsigned int base;
230 int n;
231
232 if (dentry == NULL || dentry->d_inode == NULL)
233 return 0;
234 inode = dentry->d_inode;
235
236 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
237 *p++ = htonl(resp->mask);
238 if (!xdr_ressize_check(rqstp, p))
239 return 0;
240 base = (char *)p - (char *)head->iov_base;
241
242 rqstp->rq_res.page_len = w;
243 while (w > 0) {
244 if (!svc_take_res_page(rqstp))
245 return 0;
246 w -= PAGE_SIZE;
247 }
248
249 n = nfsacl_encode(&rqstp->rq_res, base, inode,
250 resp->acl_access,
251 resp->mask & NFS_ACL, 0);
252 if (n > 0)
253 n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
254 resp->acl_default,
255 resp->mask & NFS_DFACL,
256 NFS_ACL_DEFAULT);
257 if (n <= 0)
258 return 0;
259 return 1;
260}
261
262static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, u32 *p,
263 struct nfsd_attrstat *resp)
264{
265 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
266 return xdr_ressize_check(rqstp, p);
267}
268
269/* ACCESS */
270static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
271 struct nfsd3_accessres *resp)
272{
273 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
274 *p++ = htonl(resp->access);
275 return xdr_ressize_check(rqstp, p);
276}
277
278/*
279 * XDR release functions
280 */
281static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, u32 *p,
282 struct nfsd3_getaclres *resp)
283{
284 fh_put(&resp->fh);
285 posix_acl_release(resp->acl_access);
286 posix_acl_release(resp->acl_default);
287 return 1;
288}
289
290static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
291 struct nfsd_fhandle *resp)
292{
293 fh_put(&resp->fh);
294 return 1;
295}
296
297#define nfsaclsvc_decode_voidargs NULL
298#define nfsaclsvc_encode_voidres NULL
299#define nfsaclsvc_release_void NULL
300#define nfsd3_fhandleargs nfsd_fhandle
301#define nfsd3_attrstatres nfsd_attrstat
302#define nfsd3_voidres nfsd3_voidargs
303struct nfsd3_voidargs { int dummy; };
304
305#define PROC(name, argt, rest, relt, cache, respsize) \
306 { (svc_procfunc) nfsacld_proc_##name, \
307 (kxdrproc_t) nfsaclsvc_decode_##argt##args, \
308 (kxdrproc_t) nfsaclsvc_encode_##rest##res, \
309 (kxdrproc_t) nfsaclsvc_release_##relt, \
310 sizeof(struct nfsd3_##argt##args), \
311 sizeof(struct nfsd3_##rest##res), \
312 0, \
313 cache, \
314 respsize, \
315 }
316
317#define ST 1 /* status*/
318#define AT 21 /* attributes */
319#define pAT (1+AT) /* post attributes - conditional */
320#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
321
322static struct svc_procedure nfsd_acl_procedures2[] = {
323 PROC(null, void, void, void, RC_NOCACHE, ST),
324 PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
325 PROC(setacl, setacl, attrstat, fhandle, RC_NOCACHE, ST+AT),
326 PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
327 PROC(access, access, access, fhandle, RC_NOCACHE, ST+AT+1),
328};
329
330struct svc_version nfsd_acl_version2 = {
331 .vs_vers = 2,
332 .vs_nproc = 5,
333 .vs_proc = nfsd_acl_procedures2,
334 .vs_dispatch = nfsd_dispatch,
335 .vs_xdrsize = NFS3_SVC_XDRSIZE,
336};
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
new file mode 100644
index 000000000000..64ba40572fea
--- /dev/null
+++ b/fs/nfsd/nfs3acl.c
@@ -0,0 +1,267 @@
1/*
2 * linux/fs/nfsd/nfs3acl.c
3 *
4 * Process version 3 NFSACL requests.
5 *
6 * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
7 */
8
9#include <linux/sunrpc/svc.h>
10#include <linux/nfs3.h>
11#include <linux/nfsd/nfsd.h>
12#include <linux/nfsd/cache.h>
13#include <linux/nfsd/xdr3.h>
14#include <linux/posix_acl.h>
15#include <linux/nfsacl.h>
16
17#define RETURN_STATUS(st) { resp->status = (st); return (st); }
18
19/*
20 * NULL call.
21 */
22static int
23nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
24{
25 return nfs_ok;
26}
27
28/*
29 * Get the Access and/or Default ACL of a file.
30 */
31static int nfsd3_proc_getacl(struct svc_rqst * rqstp,
32 struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
33{
34 svc_fh *fh;
35 struct posix_acl *acl;
36 int nfserr = 0;
37
38 fh = fh_copy(&resp->fh, &argp->fh);
39 if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
40 RETURN_STATUS(nfserr_inval);
41
42 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
43 RETURN_STATUS(nfserr_inval);
44 resp->mask = argp->mask;
45
46 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
47 acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
48 if (IS_ERR(acl)) {
49 int err = PTR_ERR(acl);
50
51 if (err == -ENODATA || err == -EOPNOTSUPP)
52 acl = NULL;
53 else {
54 nfserr = nfserrno(err);
55 goto fail;
56 }
57 }
58 if (acl == NULL) {
59 /* Solaris returns the inode's minimum ACL. */
60
61 struct inode *inode = fh->fh_dentry->d_inode;
62 acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
63 }
64 resp->acl_access = acl;
65 }
66 if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
67 /* Check how Solaris handles requests for the Default ACL
68 of a non-directory! */
69
70 acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
71 if (IS_ERR(acl)) {
72 int err = PTR_ERR(acl);
73
74 if (err == -ENODATA || err == -EOPNOTSUPP)
75 acl = NULL;
76 else {
77 nfserr = nfserrno(err);
78 goto fail;
79 }
80 }
81 resp->acl_default = acl;
82 }
83
84 /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
85 RETURN_STATUS(0);
86
87fail:
88 posix_acl_release(resp->acl_access);
89 posix_acl_release(resp->acl_default);
90 RETURN_STATUS(nfserr);
91}
92
93/*
94 * Set the Access and/or Default ACL of a file.
95 */
96static int nfsd3_proc_setacl(struct svc_rqst * rqstp,
97 struct nfsd3_setaclargs *argp,
98 struct nfsd3_attrstat *resp)
99{
100 svc_fh *fh;
101 int nfserr = 0;
102
103 fh = fh_copy(&resp->fh, &argp->fh);
104 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
105
106 if (!nfserr) {
107 nfserr = nfserrno( nfsd_set_posix_acl(
108 fh, ACL_TYPE_ACCESS, argp->acl_access) );
109 }
110 if (!nfserr) {
111 nfserr = nfserrno( nfsd_set_posix_acl(
112 fh, ACL_TYPE_DEFAULT, argp->acl_default) );
113 }
114
115 /* argp->acl_{access,default} may have been allocated in
116 nfs3svc_decode_setaclargs. */
117 posix_acl_release(argp->acl_access);
118 posix_acl_release(argp->acl_default);
119 RETURN_STATUS(nfserr);
120}
121
122/*
123 * XDR decode functions
124 */
125static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
126 struct nfsd3_getaclargs *args)
127{
128 if (!(p = nfs3svc_decode_fh(p, &args->fh)))
129 return 0;
130 args->mask = ntohl(*p); p++;
131
132 return xdr_argsize_check(rqstp, p);
133}
134
135
136static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
137 struct nfsd3_setaclargs *args)
138{
139 struct kvec *head = rqstp->rq_arg.head;
140 unsigned int base;
141 int n;
142
143 if (!(p = nfs3svc_decode_fh(p, &args->fh)))
144 return 0;
145 args->mask = ntohl(*p++);
146 if (args->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) ||
147 !xdr_argsize_check(rqstp, p))
148 return 0;
149
150 base = (char *)p - (char *)head->iov_base;
151 n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
152 (args->mask & NFS_ACL) ?
153 &args->acl_access : NULL);
154 if (n > 0)
155 n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
156 (args->mask & NFS_DFACL) ?
157 &args->acl_default : NULL);
158 return (n > 0);
159}
160
161/*
162 * XDR encode functions
163 */
164
165/* GETACL */
166static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
167 struct nfsd3_getaclres *resp)
168{
169 struct dentry *dentry = resp->fh.fh_dentry;
170
171 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
172 if (resp->status == 0 && dentry && dentry->d_inode) {
173 struct inode *inode = dentry->d_inode;
174 int w = nfsacl_size(
175 (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
176 (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
177 struct kvec *head = rqstp->rq_res.head;
178 unsigned int base;
179 int n;
180
181 *p++ = htonl(resp->mask);
182 if (!xdr_ressize_check(rqstp, p))
183 return 0;
184 base = (char *)p - (char *)head->iov_base;
185
186 rqstp->rq_res.page_len = w;
187 while (w > 0) {
188 if (!svc_take_res_page(rqstp))
189 return 0;
190 w -= PAGE_SIZE;
191 }
192
193 n = nfsacl_encode(&rqstp->rq_res, base, inode,
194 resp->acl_access,
195 resp->mask & NFS_ACL, 0);
196 if (n > 0)
197 n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
198 resp->acl_default,
199 resp->mask & NFS_DFACL,
200 NFS_ACL_DEFAULT);
201 if (n <= 0)
202 return 0;
203 } else
204 if (!xdr_ressize_check(rqstp, p))
205 return 0;
206
207 return 1;
208}
209
210/* SETACL */
211static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p,
212 struct nfsd3_attrstat *resp)
213{
214 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
215
216 return xdr_ressize_check(rqstp, p);
217}
218
219/*
220 * XDR release functions
221 */
222static int nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p,
223 struct nfsd3_getaclres *resp)
224{
225 fh_put(&resp->fh);
226 posix_acl_release(resp->acl_access);
227 posix_acl_release(resp->acl_default);
228 return 1;
229}
230
231#define nfs3svc_decode_voidargs NULL
232#define nfs3svc_release_void NULL
233#define nfsd3_setaclres nfsd3_attrstat
234#define nfsd3_voidres nfsd3_voidargs
235struct nfsd3_voidargs { int dummy; };
236
237#define PROC(name, argt, rest, relt, cache, respsize) \
238 { (svc_procfunc) nfsd3_proc_##name, \
239 (kxdrproc_t) nfs3svc_decode_##argt##args, \
240 (kxdrproc_t) nfs3svc_encode_##rest##res, \
241 (kxdrproc_t) nfs3svc_release_##relt, \
242 sizeof(struct nfsd3_##argt##args), \
243 sizeof(struct nfsd3_##rest##res), \
244 0, \
245 cache, \
246 respsize, \
247 }
248
249#define ST 1 /* status*/
250#define AT 21 /* attributes */
251#define pAT (1+AT) /* post attributes - conditional */
252#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
253
254static struct svc_procedure nfsd_acl_procedures3[] = {
255 PROC(null, void, void, void, RC_NOCACHE, ST),
256 PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
257 PROC(setacl, setacl, setacl, fhandle, RC_NOCACHE, ST+pAT),
258};
259
260struct svc_version nfsd_acl_version3 = {
261 .vs_vers = 3,
262 .vs_nproc = 3,
263 .vs_proc = nfsd_acl_procedures3,
264 .vs_dispatch = nfsd_dispatch,
265 .vs_xdrsize = NFS3_SVC_XDRSIZE,
266};
267
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 11f806835c5a..e0e134d6baba 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -71,6 +71,12 @@ decode_fh(u32 *p, struct svc_fh *fhp)
71 return p + XDR_QUADLEN(size); 71 return p + XDR_QUADLEN(size);
72} 72}
73 73
74/* Helper function for NFSv3 ACL code */
75u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp)
76{
77 return decode_fh(p, fhp);
78}
79
74static inline u32 * 80static inline u32 *
75encode_fh(u32 *p, struct svc_fh *fhp) 81encode_fh(u32 *p, struct svc_fh *fhp)
76{ 82{
@@ -233,6 +239,13 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
233 return p; 239 return p;
234} 240}
235 241
242/* Helper for NFSv3 ACLs */
243u32 *
244nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
245{
246 return encode_post_op_attr(rqstp, p, fhp);
247}
248
236/* 249/*
237 * Enocde weak cache consistency data 250 * Enocde weak cache consistency data
238 */ 251 */
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 11ebf6c4aa54..4a2105552ac4 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -125,7 +125,7 @@ static short ace2type(struct nfs4_ace *);
125static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); 125static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
126static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int); 126static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
127int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); 127int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
128int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *); 128static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
129 129
130struct nfs4_acl * 130struct nfs4_acl *
131nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, 131nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
@@ -775,7 +775,7 @@ out_err:
775 return pacl; 775 return pacl;
776} 776}
777 777
778int 778static int
779nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl) 779nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
780{ 780{
781 struct list_head *h, *n; 781 struct list_head *h, *n;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 1a55dfcb74bc..583c0710e45e 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -54,7 +54,6 @@
54 54
55/* declarations */ 55/* declarations */
56static void nfs4_cb_null(struct rpc_task *task); 56static void nfs4_cb_null(struct rpc_task *task);
57extern spinlock_t recall_lock;
58 57
59/* Index of predefined Linux callback client operations */ 58/* Index of predefined Linux callback client operations */
60 59
@@ -329,12 +328,12 @@ out:
329 .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \ 328 .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \
330} 329}
331 330
332struct rpc_procinfo nfs4_cb_procedures[] = { 331static struct rpc_procinfo nfs4_cb_procedures[] = {
333 PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null), 332 PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null),
334 PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall), 333 PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall),
335}; 334};
336 335
337struct rpc_version nfs_cb_version4 = { 336static struct rpc_version nfs_cb_version4 = {
338 .number = 1, 337 .number = 1,
339 .nrprocs = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]), 338 .nrprocs = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]),
340 .procs = nfs4_cb_procedures 339 .procs = nfs4_cb_procedures
@@ -348,7 +347,7 @@ static struct rpc_version * nfs_cb_version[] = {
348/* 347/*
349 * Use the SETCLIENTID credential 348 * Use the SETCLIENTID credential
350 */ 349 */
351struct rpc_cred * 350static struct rpc_cred *
352nfsd4_lookupcred(struct nfs4_client *clp, int taskflags) 351nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
353{ 352{
354 struct auth_cred acred; 353 struct auth_cred acred;
@@ -387,9 +386,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
387 char hostname[32]; 386 char hostname[32];
388 int status; 387 int status;
389 388
390 dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n", 389 if (atomic_read(&cb->cb_set))
391 cb->cb_parsed, atomic_read(&cb->cb_set));
392 if (!cb->cb_parsed || atomic_read(&cb->cb_set))
393 return; 390 return;
394 391
395 /* Initialize address */ 392 /* Initialize address */
@@ -427,10 +424,10 @@ nfsd4_probe_callback(struct nfs4_client *clp)
427 * XXX AUTH_UNIX only - need AUTH_GSS.... 424 * XXX AUTH_UNIX only - need AUTH_GSS....
428 */ 425 */
429 sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr)); 426 sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
430 clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); 427 clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
431 if (IS_ERR(clnt)) { 428 if (IS_ERR(clnt)) {
432 dprintk("NFSD: couldn't create callback client\n"); 429 dprintk("NFSD: couldn't create callback client\n");
433 goto out_xprt; 430 goto out_err;
434 } 431 }
435 clnt->cl_intr = 0; 432 clnt->cl_intr = 0;
436 clnt->cl_softrtry = 1; 433 clnt->cl_softrtry = 1;
@@ -465,8 +462,6 @@ out_rpciod:
465out_clnt: 462out_clnt:
466 rpc_shutdown_client(clnt); 463 rpc_shutdown_client(clnt);
467 goto out_err; 464 goto out_err;
468out_xprt:
469 xprt_destroy(xprt);
470out_err: 465out_err:
471 dprintk("NFSD: warning: no callback path to client %.*s\n", 466 dprintk("NFSD: warning: no callback path to client %.*s\n",
472 (int)clp->cl_name.len, clp->cl_name.data); 467 (int)clp->cl_name.len, clp->cl_name.data);
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 4ba540841cf6..5605a26efc57 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -104,7 +104,7 @@ ent_update(struct ent *new, struct ent *itm)
104 ent_init(new, itm); 104 ent_init(new, itm);
105} 105}
106 106
107void 107static void
108ent_put(struct cache_head *ch, struct cache_detail *cd) 108ent_put(struct cache_head *ch, struct cache_detail *cd)
109{ 109{
110 if (cache_put(ch, cd)) { 110 if (cache_put(ch, cd)) {
@@ -186,7 +186,7 @@ warn_no_idmapd(struct cache_detail *detail)
186static int idtoname_parse(struct cache_detail *, char *, int); 186static int idtoname_parse(struct cache_detail *, char *, int);
187static struct ent *idtoname_lookup(struct ent *, int); 187static struct ent *idtoname_lookup(struct ent *, int);
188 188
189struct cache_detail idtoname_cache = { 189static struct cache_detail idtoname_cache = {
190 .hash_size = ENT_HASHMAX, 190 .hash_size = ENT_HASHMAX,
191 .hash_table = idtoname_table, 191 .hash_table = idtoname_table,
192 .name = "nfs4.idtoname", 192 .name = "nfs4.idtoname",
@@ -277,7 +277,7 @@ nametoid_hash(struct ent *ent)
277 return hash_str(ent->name, ENT_HASHBITS); 277 return hash_str(ent->name, ENT_HASHBITS);
278} 278}
279 279
280void 280static void
281nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, 281nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
282 int *blen) 282 int *blen)
283{ 283{
@@ -317,9 +317,9 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
317} 317}
318 318
319static struct ent *nametoid_lookup(struct ent *, int); 319static struct ent *nametoid_lookup(struct ent *, int);
320int nametoid_parse(struct cache_detail *, char *, int); 320static int nametoid_parse(struct cache_detail *, char *, int);
321 321
322struct cache_detail nametoid_cache = { 322static struct cache_detail nametoid_cache = {
323 .hash_size = ENT_HASHMAX, 323 .hash_size = ENT_HASHMAX,
324 .hash_table = nametoid_table, 324 .hash_table = nametoid_table,
325 .name = "nfs4.nametoid", 325 .name = "nfs4.nametoid",
@@ -330,7 +330,7 @@ struct cache_detail nametoid_cache = {
330 .warn_no_listener = warn_no_idmapd, 330 .warn_no_listener = warn_no_idmapd,
331}; 331};
332 332
333int 333static int
334nametoid_parse(struct cache_detail *cd, char *buf, int buflen) 334nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
335{ 335{
336 struct ent ent, *res; 336 struct ent ent, *res;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e8158741e8b5..d71f14517b9c 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -45,6 +45,7 @@
45#include <linux/param.h> 45#include <linux/param.h>
46#include <linux/major.h> 46#include <linux/major.h>
47#include <linux/slab.h> 47#include <linux/slab.h>
48#include <linux/file.h>
48 49
49#include <linux/sunrpc/svc.h> 50#include <linux/sunrpc/svc.h>
50#include <linux/nfsd/nfsd.h> 51#include <linux/nfsd/nfsd.h>
@@ -198,6 +199,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
198 if (status) 199 if (status)
199 goto out; 200 goto out;
200 switch (open->op_claim_type) { 201 switch (open->op_claim_type) {
202 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
203 status = nfserr_inval;
204 if (open->op_create)
205 goto out;
206 /* fall through */
201 case NFS4_OPEN_CLAIM_NULL: 207 case NFS4_OPEN_CLAIM_NULL:
202 /* 208 /*
203 * (1) set CURRENT_FH to the file being opened, 209 * (1) set CURRENT_FH to the file being opened,
@@ -220,7 +226,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
220 if (status) 226 if (status)
221 goto out; 227 goto out;
222 break; 228 break;
223 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
224 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 229 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
225 printk("NFSD: unsupported OPEN claim type %d\n", 230 printk("NFSD: unsupported OPEN claim type %d\n",
226 open->op_claim_type); 231 open->op_claim_type);
@@ -473,26 +478,27 @@ static inline int
473nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) 478nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
474{ 479{
475 int status; 480 int status;
476 struct file *filp = NULL;
477 481
478 /* no need to check permission - this will be done in nfsd_read() */ 482 /* no need to check permission - this will be done in nfsd_read() */
479 483
484 read->rd_filp = NULL;
480 if (read->rd_offset >= OFFSET_MAX) 485 if (read->rd_offset >= OFFSET_MAX)
481 return nfserr_inval; 486 return nfserr_inval;
482 487
483 nfs4_lock_state(); 488 nfs4_lock_state();
484 /* check stateid */ 489 /* check stateid */
485 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 490 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
486 CHECK_FH | RD_STATE, &filp))) { 491 CHECK_FH | RD_STATE, &read->rd_filp))) {
487 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 492 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
488 goto out; 493 goto out;
489 } 494 }
495 if (read->rd_filp)
496 get_file(read->rd_filp);
490 status = nfs_ok; 497 status = nfs_ok;
491out: 498out:
492 nfs4_unlock_state(); 499 nfs4_unlock_state();
493 read->rd_rqstp = rqstp; 500 read->rd_rqstp = rqstp;
494 read->rd_fhp = current_fh; 501 read->rd_fhp = current_fh;
495 read->rd_filp = filp;
496 return status; 502 return status;
497} 503}
498 504
@@ -532,6 +538,8 @@ nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_rem
532{ 538{
533 int status; 539 int status;
534 540
541 if (nfs4_in_grace())
542 return nfserr_grace;
535 status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen); 543 status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
536 if (status == nfserr_symlink) 544 if (status == nfserr_symlink)
537 return nfserr_notdir; 545 return nfserr_notdir;
@@ -550,6 +558,9 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
550 558
551 if (!save_fh->fh_dentry) 559 if (!save_fh->fh_dentry)
552 return status; 560 return status;
561 if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
562 & NFSEXP_NOSUBTREECHECK))
563 return nfserr_grace;
553 status = nfsd_rename(rqstp, save_fh, rename->rn_sname, 564 status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
554 rename->rn_snamelen, current_fh, 565 rename->rn_snamelen, current_fh,
555 rename->rn_tname, rename->rn_tnamelen); 566 rename->rn_tname, rename->rn_tnamelen);
@@ -624,6 +635,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
624 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 635 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
625 goto out; 636 goto out;
626 } 637 }
638 if (filp)
639 get_file(filp);
627 nfs4_unlock_state(); 640 nfs4_unlock_state();
628 641
629 write->wr_bytes_written = write->wr_buflen; 642 write->wr_bytes_written = write->wr_buflen;
@@ -635,6 +648,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
635 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, 648 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
636 write->wr_vec, write->wr_vlen, write->wr_buflen, 649 write->wr_vec, write->wr_vlen, write->wr_buflen,
637 &write->wr_how_written); 650 &write->wr_how_written);
651 if (filp)
652 fput(filp);
638 653
639 if (status == nfserr_symlink) 654 if (status == nfserr_symlink)
640 status = nfserr_inval; 655 status = nfserr_inval;
@@ -923,6 +938,9 @@ encode_op:
923 nfs4_put_stateowner(replay_owner); 938 nfs4_put_stateowner(replay_owner);
924 replay_owner = NULL; 939 replay_owner = NULL;
925 } 940 }
941 /* XXX Ugh, we need to get rid of this kind of special case: */
942 if (op->opnum == OP_READ && op->u.read.rd_filp)
943 fput(op->u.read.rd_filp);
926 } 944 }
927 945
928out: 946out:
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
new file mode 100644
index 000000000000..095f1740f3ae
--- /dev/null
+++ b/fs/nfsd/nfs4recover.c
@@ -0,0 +1,431 @@
1/*
2* linux/fs/nfsd/nfs4recover.c
3*
4* Copyright (c) 2004 The Regents of the University of Michigan.
5* All rights reserved.
6*
7* Andy Adamson <andros@citi.umich.edu>
8*
9* Redistribution and use in source and binary forms, with or without
10* modification, are permitted provided that the following conditions
11* are met:
12*
13* 1. Redistributions of source code must retain the above copyright
14* notice, this list of conditions and the following disclaimer.
15* 2. Redistributions in binary form must reproduce the above copyright
16* notice, this list of conditions and the following disclaimer in the
17* documentation and/or other materials provided with the distribution.
18* 3. Neither the name of the University nor the names of its
19* contributors may be used to endorse or promote products derived
20* from this software without specific prior written permission.
21*
22* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*
34*/
35
36
37#include <linux/sunrpc/svc.h>
38#include <linux/nfsd/nfsd.h>
39#include <linux/nfs4.h>
40#include <linux/nfsd/state.h>
41#include <linux/nfsd/xdr4.h>
42#include <linux/param.h>
43#include <linux/file.h>
44#include <linux/namei.h>
45#include <asm/uaccess.h>
46#include <asm/scatterlist.h>
47#include <linux/crypto.h>
48
49
50#define NFSDDBG_FACILITY NFSDDBG_PROC
51
52/* Globals */
53static struct nameidata rec_dir;
54static int rec_dir_init = 0;
55
56static void
57nfs4_save_user(uid_t *saveuid, gid_t *savegid)
58{
59 *saveuid = current->fsuid;
60 *savegid = current->fsgid;
61 current->fsuid = 0;
62 current->fsgid = 0;
63}
64
65static void
66nfs4_reset_user(uid_t saveuid, gid_t savegid)
67{
68 current->fsuid = saveuid;
69 current->fsgid = savegid;
70}
71
72static void
73md5_to_hex(char *out, char *md5)
74{
75 int i;
76
77 for (i=0; i<16; i++) {
78 unsigned char c = md5[i];
79
80 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
81 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
82 }
83 *out = '\0';
84}
85
86int
87nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
88{
89 struct xdr_netobj cksum;
90 struct crypto_tfm *tfm;
91 struct scatterlist sg[1];
92 int status = nfserr_resource;
93
94 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
95 clname->len, clname->data);
96 tfm = crypto_alloc_tfm("md5", 0);
97 if (tfm == NULL)
98 goto out;
99 cksum.len = crypto_tfm_alg_digestsize(tfm);
100 cksum.data = kmalloc(cksum.len, GFP_KERNEL);
101 if (cksum.data == NULL)
102 goto out;
103 crypto_digest_init(tfm);
104
105 sg[0].page = virt_to_page(clname->data);
106 sg[0].offset = offset_in_page(clname->data);
107 sg[0].length = clname->len;
108
109 crypto_digest_update(tfm, sg, 1);
110 crypto_digest_final(tfm, cksum.data);
111
112 md5_to_hex(dname, cksum.data);
113
114 kfree(cksum.data);
115 status = nfs_ok;
116out:
117 if (tfm)
118 crypto_free_tfm(tfm);
119 return status;
120}
121
122static int
123nfsd4_rec_fsync(struct dentry *dentry)
124{
125 struct file *filp;
126 int status = nfs_ok;
127
128 dprintk("NFSD: nfs4_fsync_rec_dir\n");
129 filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR);
130 if (IS_ERR(filp)) {
131 status = PTR_ERR(filp);
132 goto out;
133 }
134 if (filp->f_op && filp->f_op->fsync)
135 status = filp->f_op->fsync(filp, filp->f_dentry, 0);
136 fput(filp);
137out:
138 if (status)
139 printk("nfsd4: unable to sync recovery directory\n");
140 return status;
141}
142
143int
144nfsd4_create_clid_dir(struct nfs4_client *clp)
145{
146 char *dname = clp->cl_recdir;
147 struct dentry *dentry;
148 uid_t uid;
149 gid_t gid;
150 int status;
151
152 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
153
154 if (!rec_dir_init || clp->cl_firststate)
155 return 0;
156
157 nfs4_save_user(&uid, &gid);
158
159 /* lock the parent */
160 down(&rec_dir.dentry->d_inode->i_sem);
161
162 dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
163 if (IS_ERR(dentry)) {
164 status = PTR_ERR(dentry);
165 goto out_unlock;
166 }
167 status = -EEXIST;
168 if (dentry->d_inode) {
169 dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
170 goto out_put;
171 }
172 status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
173out_put:
174 dput(dentry);
175out_unlock:
176 up(&rec_dir.dentry->d_inode->i_sem);
177 if (status == 0) {
178 clp->cl_firststate = 1;
179 status = nfsd4_rec_fsync(rec_dir.dentry);
180 }
181 nfs4_reset_user(uid, gid);
182 dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
183 return status;
184}
185
186typedef int (recdir_func)(struct dentry *, struct dentry *);
187
188struct dentry_list {
189 struct dentry *dentry;
190 struct list_head list;
191};
192
193struct dentry_list_arg {
194 struct list_head dentries;
195 struct dentry *parent;
196};
197
198static int
199nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
200 loff_t offset, ino_t ino, unsigned int d_type)
201{
202 struct dentry_list_arg *dla = arg;
203 struct list_head *dentries = &dla->dentries;
204 struct dentry *parent = dla->parent;
205 struct dentry *dentry;
206 struct dentry_list *child;
207
208 if (name && isdotent(name, namlen))
209 return nfs_ok;
210 dentry = lookup_one_len(name, parent, namlen);
211 if (IS_ERR(dentry))
212 return PTR_ERR(dentry);
213 child = kmalloc(sizeof(*child), GFP_KERNEL);
214 if (child == NULL)
215 return -ENOMEM;
216 child->dentry = dentry;
217 list_add(&child->list, dentries);
218 return 0;
219}
220
221static int
222nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
223{
224 struct file *filp;
225 struct dentry_list_arg dla = {
226 .parent = dir,
227 };
228 struct list_head *dentries = &dla.dentries;
229 struct dentry_list *child;
230 uid_t uid;
231 gid_t gid;
232 int status;
233
234 if (!rec_dir_init)
235 return 0;
236
237 nfs4_save_user(&uid, &gid);
238
239 filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
240 O_RDWR);
241 status = PTR_ERR(filp);
242 if (IS_ERR(filp))
243 goto out;
244 INIT_LIST_HEAD(dentries);
245 status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
246 fput(filp);
247 while (!list_empty(dentries)) {
248 child = list_entry(dentries->next, struct dentry_list, list);
249 status = f(dir, child->dentry);
250 if (status)
251 goto out;
252 list_del(&child->list);
253 dput(child->dentry);
254 kfree(child);
255 }
256out:
257 while (!list_empty(dentries)) {
258 child = list_entry(dentries->next, struct dentry_list, list);
259 list_del(&child->list);
260 dput(child->dentry);
261 kfree(child);
262 }
263 nfs4_reset_user(uid, gid);
264 return status;
265}
266
267static int
268nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
269{
270 int status;
271
272 if (!S_ISREG(dir->d_inode->i_mode)) {
273 printk("nfsd4: non-file found in client recovery directory\n");
274 return -EINVAL;
275 }
276 down(&dir->d_inode->i_sem);
277 status = vfs_unlink(dir->d_inode, dentry);
278 up(&dir->d_inode->i_sem);
279 return status;
280}
281
282static int
283nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
284{
285 int status;
286
287 /* For now this directory should already be empty, but we empty it of
288 * any regular files anyway, just in case the directory was created by
289 * a kernel from the future.... */
290 nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
291 down(&dir->d_inode->i_sem);
292 status = vfs_rmdir(dir->d_inode, dentry);
293 up(&dir->d_inode->i_sem);
294 return status;
295}
296
297static int
298nfsd4_unlink_clid_dir(char *name, int namlen)
299{
300 struct dentry *dentry;
301 int status;
302
303 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
304
305 dentry = lookup_one_len(name, rec_dir.dentry, namlen);
306 if (IS_ERR(dentry)) {
307 status = PTR_ERR(dentry);
308 return status;
309 }
310 status = -ENOENT;
311 if (!dentry->d_inode)
312 goto out;
313
314 status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
315out:
316 dput(dentry);
317 return status;
318}
319
320void
321nfsd4_remove_clid_dir(struct nfs4_client *clp)
322{
323 uid_t uid;
324 gid_t gid;
325 int status;
326
327 if (!rec_dir_init || !clp->cl_firststate)
328 return;
329
330 nfs4_save_user(&uid, &gid);
331 status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
332 nfs4_reset_user(uid, gid);
333 if (status == 0)
334 status = nfsd4_rec_fsync(rec_dir.dentry);
335 if (status)
336 printk("NFSD: Failed to remove expired client state directory"
337 " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
338 return;
339}
340
341static int
342purge_old(struct dentry *parent, struct dentry *child)
343{
344 int status;
345
346 if (nfs4_has_reclaimed_state(child->d_name.name))
347 return nfs_ok;
348
349 status = nfsd4_clear_clid_dir(parent, child);
350 if (status)
351 printk("failed to remove client recovery directory %s\n",
352 child->d_name.name);
353 /* Keep trying, success or failure: */
354 return nfs_ok;
355}
356
357void
358nfsd4_recdir_purge_old(void) {
359 int status;
360
361 if (!rec_dir_init)
362 return;
363 status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
364 if (status == 0)
365 status = nfsd4_rec_fsync(rec_dir.dentry);
366 if (status)
367 printk("nfsd4: failed to purge old clients from recovery"
368 " directory %s\n", rec_dir.dentry->d_name.name);
369 return;
370}
371
372static int
373load_recdir(struct dentry *parent, struct dentry *child)
374{
375 if (child->d_name.len != HEXDIR_LEN - 1) {
376 printk("nfsd4: illegal name %s in recovery directory\n",
377 child->d_name.name);
378 /* Keep trying; maybe the others are OK: */
379 return nfs_ok;
380 }
381 nfs4_client_to_reclaim(child->d_name.name);
382 return nfs_ok;
383}
384
385int
386nfsd4_recdir_load(void) {
387 int status;
388
389 status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir);
390 if (status)
391 printk("nfsd4: failed loading clients from recovery"
392 " directory %s\n", rec_dir.dentry->d_name.name);
393 return status;
394}
395
396/*
397 * Hold reference to the recovery directory.
398 */
399
400void
401nfsd4_init_recdir(char *rec_dirname)
402{
403 uid_t uid = 0;
404 gid_t gid = 0;
405 int status;
406
407 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
408 rec_dirname);
409
410 BUG_ON(rec_dir_init);
411
412 nfs4_save_user(&uid, &gid);
413
414 status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
415 if (status == -ENOENT)
416 printk("NFSD: recovery directory %s doesn't exist\n",
417 rec_dirname);
418
419 if (!status)
420 rec_dir_init = 1;
421 nfs4_reset_user(uid, gid);
422}
423
424void
425nfsd4_shutdown_recdir(void)
426{
427 if (!rec_dir_init)
428 return;
429 rec_dir_init = 0;
430 path_release(&rec_dir);
431}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 75e8b137580c..89e36526d7f2 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -48,39 +48,32 @@
48#include <linux/nfs4.h> 48#include <linux/nfs4.h>
49#include <linux/nfsd/state.h> 49#include <linux/nfsd/state.h>
50#include <linux/nfsd/xdr4.h> 50#include <linux/nfsd/xdr4.h>
51#include <linux/namei.h>
51 52
52#define NFSDDBG_FACILITY NFSDDBG_PROC 53#define NFSDDBG_FACILITY NFSDDBG_PROC
53 54
54/* Globals */ 55/* Globals */
55static time_t lease_time = 90; /* default lease time */ 56static time_t lease_time = 90; /* default lease time */
56static time_t old_lease_time = 90; /* past incarnation lease time */ 57static time_t user_lease_time = 90;
57static u32 nfs4_reclaim_init = 0; 58static time_t boot_time;
58time_t boot_time; 59static int in_grace = 1;
59static time_t grace_end = 0;
60static u32 current_clientid = 1; 60static u32 current_clientid = 1;
61static u32 current_ownerid = 1; 61static u32 current_ownerid = 1;
62static u32 current_fileid = 1; 62static u32 current_fileid = 1;
63static u32 current_delegid = 1; 63static u32 current_delegid = 1;
64static u32 nfs4_init; 64static u32 nfs4_init;
65stateid_t zerostateid; /* bits all 0 */ 65static stateid_t zerostateid; /* bits all 0 */
66stateid_t onestateid; /* bits all 1 */ 66static stateid_t onestateid; /* bits all 1 */
67 67
68/* debug counters */ 68#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
69u32 list_add_perfile = 0; 69#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
70u32 list_del_perfile = 0;
71u32 add_perclient = 0;
72u32 del_perclient = 0;
73u32 alloc_file = 0;
74u32 free_file = 0;
75u32 vfsopen = 0;
76u32 vfsclose = 0;
77u32 alloc_delegation= 0;
78u32 free_delegation= 0;
79 70
80/* forward declarations */ 71/* forward declarations */
81struct nfs4_stateid * find_stateid(stateid_t *stid, int flags); 72static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
82static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid); 73static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
83static void release_stateid_lockowners(struct nfs4_stateid *open_stp); 74static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
75static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
76static void nfs4_set_recdir(char *recdir);
84 77
85/* Locking: 78/* Locking:
86 * 79 *
@@ -90,6 +83,11 @@ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
90 */ 83 */
91static DECLARE_MUTEX(client_sema); 84static DECLARE_MUTEX(client_sema);
92 85
86static kmem_cache_t *stateowner_slab = NULL;
87static kmem_cache_t *file_slab = NULL;
88static kmem_cache_t *stateid_slab = NULL;
89static kmem_cache_t *deleg_slab = NULL;
90
93void 91void
94nfs4_lock_state(void) 92nfs4_lock_state(void)
95{ 93{
@@ -118,16 +116,36 @@ opaque_hashval(const void *ptr, int nbytes)
118/* forward declarations */ 116/* forward declarations */
119static void release_stateowner(struct nfs4_stateowner *sop); 117static void release_stateowner(struct nfs4_stateowner *sop);
120static void release_stateid(struct nfs4_stateid *stp, int flags); 118static void release_stateid(struct nfs4_stateid *stp, int flags);
121static void release_file(struct nfs4_file *fp);
122 119
123/* 120/*
124 * Delegation state 121 * Delegation state
125 */ 122 */
126 123
127/* recall_lock protects the del_recall_lru */ 124/* recall_lock protects the del_recall_lru */
128spinlock_t recall_lock; 125static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
129static struct list_head del_recall_lru; 126static struct list_head del_recall_lru;
130 127
128static void
129free_nfs4_file(struct kref *kref)
130{
131 struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
132 list_del(&fp->fi_hash);
133 iput(fp->fi_inode);
134 kmem_cache_free(file_slab, fp);
135}
136
137static inline void
138put_nfs4_file(struct nfs4_file *fi)
139{
140 kref_put(&fi->fi_ref, free_nfs4_file);
141}
142
143static inline void
144get_nfs4_file(struct nfs4_file *fi)
145{
146 kref_get(&fi->fi_ref);
147}
148
131static struct nfs4_delegation * 149static struct nfs4_delegation *
132alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) 150alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
133{ 151{
@@ -136,13 +154,14 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
136 struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback; 154 struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
137 155
138 dprintk("NFSD alloc_init_deleg\n"); 156 dprintk("NFSD alloc_init_deleg\n");
139 if ((dp = kmalloc(sizeof(struct nfs4_delegation), 157 dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
140 GFP_KERNEL)) == NULL) 158 if (dp == NULL)
141 return dp; 159 return dp;
142 INIT_LIST_HEAD(&dp->dl_del_perfile); 160 INIT_LIST_HEAD(&dp->dl_perfile);
143 INIT_LIST_HEAD(&dp->dl_del_perclnt); 161 INIT_LIST_HEAD(&dp->dl_perclnt);
144 INIT_LIST_HEAD(&dp->dl_recall_lru); 162 INIT_LIST_HEAD(&dp->dl_recall_lru);
145 dp->dl_client = clp; 163 dp->dl_client = clp;
164 get_nfs4_file(fp);
146 dp->dl_file = fp; 165 dp->dl_file = fp;
147 dp->dl_flock = NULL; 166 dp->dl_flock = NULL;
148 get_file(stp->st_vfs_file); 167 get_file(stp->st_vfs_file);
@@ -160,9 +179,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
160 current_fh->fh_handle.fh_size); 179 current_fh->fh_handle.fh_size);
161 dp->dl_time = 0; 180 dp->dl_time = 0;
162 atomic_set(&dp->dl_count, 1); 181 atomic_set(&dp->dl_count, 1);
163 list_add(&dp->dl_del_perfile, &fp->fi_del_perfile); 182 list_add(&dp->dl_perfile, &fp->fi_delegations);
164 list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt); 183 list_add(&dp->dl_perclnt, &clp->cl_delegations);
165 alloc_delegation++;
166 return dp; 184 return dp;
167} 185}
168 186
@@ -171,8 +189,8 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
171{ 189{
172 if (atomic_dec_and_test(&dp->dl_count)) { 190 if (atomic_dec_and_test(&dp->dl_count)) {
173 dprintk("NFSD: freeing dp %p\n",dp); 191 dprintk("NFSD: freeing dp %p\n",dp);
174 kfree(dp); 192 put_nfs4_file(dp->dl_file);
175 free_delegation++; 193 kmem_cache_free(deleg_slab, dp);
176 } 194 }
177} 195}
178 196
@@ -193,15 +211,14 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
193 if (dp->dl_flock) 211 if (dp->dl_flock)
194 setlease(filp, F_UNLCK, &dp->dl_flock); 212 setlease(filp, F_UNLCK, &dp->dl_flock);
195 nfsd_close(filp); 213 nfsd_close(filp);
196 vfsclose++;
197} 214}
198 215
199/* Called under the state lock. */ 216/* Called under the state lock. */
200static void 217static void
201unhash_delegation(struct nfs4_delegation *dp) 218unhash_delegation(struct nfs4_delegation *dp)
202{ 219{
203 list_del_init(&dp->dl_del_perfile); 220 list_del_init(&dp->dl_perfile);
204 list_del_init(&dp->dl_del_perclnt); 221 list_del_init(&dp->dl_perclnt);
205 spin_lock(&recall_lock); 222 spin_lock(&recall_lock);
206 list_del_init(&dp->dl_recall_lru); 223 list_del_init(&dp->dl_recall_lru);
207 spin_unlock(&recall_lock); 224 spin_unlock(&recall_lock);
@@ -220,8 +237,8 @@ unhash_delegation(struct nfs4_delegation *dp)
220 237
221#define clientid_hashval(id) \ 238#define clientid_hashval(id) \
222 ((id) & CLIENT_HASH_MASK) 239 ((id) & CLIENT_HASH_MASK)
223#define clientstr_hashval(name, namelen) \ 240#define clientstr_hashval(name) \
224 (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK) 241 (opaque_hashval((name), 8) & CLIENT_HASH_MASK)
225/* 242/*
226 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot 243 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
227 * used in reboot/reset lease grace period processing 244 * used in reboot/reset lease grace period processing
@@ -331,11 +348,11 @@ expire_client(struct nfs4_client *clp)
331 348
332 INIT_LIST_HEAD(&reaplist); 349 INIT_LIST_HEAD(&reaplist);
333 spin_lock(&recall_lock); 350 spin_lock(&recall_lock);
334 while (!list_empty(&clp->cl_del_perclnt)) { 351 while (!list_empty(&clp->cl_delegations)) {
335 dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt); 352 dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
336 dprintk("NFSD: expire client. dp %p, fp %p\n", dp, 353 dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
337 dp->dl_flock); 354 dp->dl_flock);
338 list_del_init(&dp->dl_del_perclnt); 355 list_del_init(&dp->dl_perclnt);
339 list_move(&dp->dl_recall_lru, &reaplist); 356 list_move(&dp->dl_recall_lru, &reaplist);
340 } 357 }
341 spin_unlock(&recall_lock); 358 spin_unlock(&recall_lock);
@@ -347,26 +364,26 @@ expire_client(struct nfs4_client *clp)
347 list_del(&clp->cl_idhash); 364 list_del(&clp->cl_idhash);
348 list_del(&clp->cl_strhash); 365 list_del(&clp->cl_strhash);
349 list_del(&clp->cl_lru); 366 list_del(&clp->cl_lru);
350 while (!list_empty(&clp->cl_perclient)) { 367 while (!list_empty(&clp->cl_openowners)) {
351 sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient); 368 sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
352 release_stateowner(sop); 369 release_stateowner(sop);
353 } 370 }
354 put_nfs4_client(clp); 371 put_nfs4_client(clp);
355} 372}
356 373
357static struct nfs4_client * 374static struct nfs4_client *
358create_client(struct xdr_netobj name) { 375create_client(struct xdr_netobj name, char *recdir) {
359 struct nfs4_client *clp; 376 struct nfs4_client *clp;
360 377
361 if (!(clp = alloc_client(name))) 378 if (!(clp = alloc_client(name)))
362 goto out; 379 goto out;
380 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
363 atomic_set(&clp->cl_count, 1); 381 atomic_set(&clp->cl_count, 1);
364 atomic_set(&clp->cl_callback.cb_set, 0); 382 atomic_set(&clp->cl_callback.cb_set, 0);
365 clp->cl_callback.cb_parsed = 0;
366 INIT_LIST_HEAD(&clp->cl_idhash); 383 INIT_LIST_HEAD(&clp->cl_idhash);
367 INIT_LIST_HEAD(&clp->cl_strhash); 384 INIT_LIST_HEAD(&clp->cl_strhash);
368 INIT_LIST_HEAD(&clp->cl_perclient); 385 INIT_LIST_HEAD(&clp->cl_openowners);
369 INIT_LIST_HEAD(&clp->cl_del_perclnt); 386 INIT_LIST_HEAD(&clp->cl_delegations);
370 INIT_LIST_HEAD(&clp->cl_lru); 387 INIT_LIST_HEAD(&clp->cl_lru);
371out: 388out:
372 return clp; 389 return clp;
@@ -392,11 +409,9 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
392 get_group_info(target->cr_group_info); 409 get_group_info(target->cr_group_info);
393} 410}
394 411
395static int 412static inline int
396cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) { 413same_name(const char *n1, const char *n2) {
397 if (!n1 || !n2) 414 return 0 == memcmp(n1, n2, HEXDIR_LEN);
398 return 0;
399 return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
400} 415}
401 416
402static int 417static int
@@ -446,7 +461,7 @@ check_name(struct xdr_netobj name) {
446 return 1; 461 return 1;
447} 462}
448 463
449void 464static void
450add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval) 465add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
451{ 466{
452 unsigned int idhashval; 467 unsigned int idhashval;
@@ -458,7 +473,7 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
458 clp->cl_time = get_seconds(); 473 clp->cl_time = get_seconds();
459} 474}
460 475
461void 476static void
462move_to_confirmed(struct nfs4_client *clp) 477move_to_confirmed(struct nfs4_client *clp)
463{ 478{
464 unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id); 479 unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
@@ -468,8 +483,7 @@ move_to_confirmed(struct nfs4_client *clp)
468 list_del_init(&clp->cl_strhash); 483 list_del_init(&clp->cl_strhash);
469 list_del_init(&clp->cl_idhash); 484 list_del_init(&clp->cl_idhash);
470 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); 485 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
471 strhashval = clientstr_hashval(clp->cl_name.data, 486 strhashval = clientstr_hashval(clp->cl_recdir);
472 clp->cl_name.len);
473 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); 487 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
474 renew_client(clp); 488 renew_client(clp);
475} 489}
@@ -500,6 +514,30 @@ find_unconfirmed_client(clientid_t *clid)
500 return NULL; 514 return NULL;
501} 515}
502 516
517static struct nfs4_client *
518find_confirmed_client_by_str(const char *dname, unsigned int hashval)
519{
520 struct nfs4_client *clp;
521
522 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
523 if (same_name(clp->cl_recdir, dname))
524 return clp;
525 }
526 return NULL;
527}
528
529static struct nfs4_client *
530find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
531{
532 struct nfs4_client *clp;
533
534 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
535 if (same_name(clp->cl_recdir, dname))
536 return clp;
537 }
538 return NULL;
539}
540
503/* a helper function for parse_callback */ 541/* a helper function for parse_callback */
504static int 542static int
505parse_octet(unsigned int *lenp, char **addrp) 543parse_octet(unsigned int *lenp, char **addrp)
@@ -534,7 +572,7 @@ parse_octet(unsigned int *lenp, char **addrp)
534} 572}
535 573
536/* parse and set the setclientid ipv4 callback address */ 574/* parse and set the setclientid ipv4 callback address */
537int 575static int
538parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp) 576parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
539{ 577{
540 int temp = 0; 578 int temp = 0;
@@ -570,7 +608,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
570 return 1; 608 return 1;
571} 609}
572 610
573void 611static void
574gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) 612gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
575{ 613{
576 struct nfs4_callback *cb = &clp->cl_callback; 614 struct nfs4_callback *cb = &clp->cl_callback;
@@ -584,14 +622,12 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
584 goto out_err; 622 goto out_err;
585 cb->cb_prog = se->se_callback_prog; 623 cb->cb_prog = se->se_callback_prog;
586 cb->cb_ident = se->se_callback_ident; 624 cb->cb_ident = se->se_callback_ident;
587 cb->cb_parsed = 1;
588 return; 625 return;
589out_err: 626out_err:
590 printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " 627 printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
591 "will not receive delegations\n", 628 "will not receive delegations\n",
592 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); 629 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
593 630
594 cb->cb_parsed = 0;
595 return; 631 return;
596} 632}
597 633
@@ -638,59 +674,43 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
638 }; 674 };
639 nfs4_verifier clverifier = setclid->se_verf; 675 nfs4_verifier clverifier = setclid->se_verf;
640 unsigned int strhashval; 676 unsigned int strhashval;
641 struct nfs4_client * conf, * unconf, * new, * clp; 677 struct nfs4_client *conf, *unconf, *new;
642 int status; 678 int status;
679 char dname[HEXDIR_LEN];
643 680
644 status = nfserr_inval; 681 status = nfserr_inval;
645 if (!check_name(clname)) 682 if (!check_name(clname))
646 goto out; 683 goto out;
647 684
685 status = nfs4_make_rec_clidname(dname, &clname);
686 if (status)
687 goto out;
688
648 /* 689 /*
649 * XXX The Duplicate Request Cache (DRC) has been checked (??) 690 * XXX The Duplicate Request Cache (DRC) has been checked (??)
650 * We get here on a DRC miss. 691 * We get here on a DRC miss.
651 */ 692 */
652 693
653 strhashval = clientstr_hashval(clname.data, clname.len); 694 strhashval = clientstr_hashval(dname);
654 695
655 conf = NULL;
656 nfs4_lock_state(); 696 nfs4_lock_state();
657 list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) { 697 conf = find_confirmed_client_by_str(dname, strhashval);
658 if (!cmp_name(&clp->cl_name, &clname)) 698 if (conf) {
659 continue;
660 /* 699 /*
661 * CASE 0: 700 * CASE 0:
662 * clname match, confirmed, different principal 701 * clname match, confirmed, different principal
663 * or different ip_address 702 * or different ip_address
664 */ 703 */
665 status = nfserr_clid_inuse; 704 status = nfserr_clid_inuse;
666 if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) { 705 if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
667 printk("NFSD: setclientid: string in use by client" 706 || conf->cl_addr != ip_addr) {
668 "(clientid %08x/%08x)\n",
669 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
670 goto out;
671 }
672 if (clp->cl_addr != ip_addr) {
673 printk("NFSD: setclientid: string in use by client" 707 printk("NFSD: setclientid: string in use by client"
674 "(clientid %08x/%08x)\n", 708 "(clientid %08x/%08x)\n",
675 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); 709 conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
676 goto out; 710 goto out;
677 } 711 }
678
679 /*
680 * cl_name match from a previous SETCLIENTID operation
681 * XXX check for additional matches?
682 */
683 conf = clp;
684 break;
685 }
686 unconf = NULL;
687 list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
688 if (!cmp_name(&clp->cl_name, &clname))
689 continue;
690 /* cl_name match from a previous SETCLIENTID operation */
691 unconf = clp;
692 break;
693 } 712 }
713 unconf = find_unconfirmed_client_by_str(dname, strhashval);
694 status = nfserr_resource; 714 status = nfserr_resource;
695 if (!conf) { 715 if (!conf) {
696 /* 716 /*
@@ -699,7 +719,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
699 */ 719 */
700 if (unconf) 720 if (unconf)
701 expire_client(unconf); 721 expire_client(unconf);
702 if (!(new = create_client(clname))) 722 new = create_client(clname, dname);
723 if (new == NULL)
703 goto out; 724 goto out;
704 copy_verf(new, &clverifier); 725 copy_verf(new, &clverifier);
705 new->cl_addr = ip_addr; 726 new->cl_addr = ip_addr;
@@ -722,12 +743,16 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
722 * nfs4_client, but with the new callback info and a 743 * nfs4_client, but with the new callback info and a
723 * new cl_confirm 744 * new cl_confirm
724 */ 745 */
725 if ((unconf) && 746 if (unconf) {
726 cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) && 747 /* Note this is removing unconfirmed {*x***},
727 cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) { 748 * which is stronger than RFC recommended {vxc**}.
728 expire_client(unconf); 749 * This has the advantage that there is at most
750 * one {*x***} in either list at any time.
751 */
752 expire_client(unconf);
729 } 753 }
730 if (!(new = create_client(clname))) 754 new = create_client(clname, dname);
755 if (new == NULL)
731 goto out; 756 goto out;
732 copy_verf(new,&conf->cl_verifier); 757 copy_verf(new,&conf->cl_verifier);
733 new->cl_addr = ip_addr; 758 new->cl_addr = ip_addr;
@@ -745,7 +770,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
745 * using input clverifier, clname, and callback info 770 * using input clverifier, clname, and callback info
746 * and generate a new cl_clientid and cl_confirm. 771 * and generate a new cl_clientid and cl_confirm.
747 */ 772 */
748 if (!(new = create_client(clname))) 773 new = create_client(clname, dname);
774 if (new == NULL)
749 goto out; 775 goto out;
750 copy_verf(new,&clverifier); 776 copy_verf(new,&clverifier);
751 new->cl_addr = ip_addr; 777 new->cl_addr = ip_addr;
@@ -771,7 +797,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
771 * new cl_verifier and a new cl_confirm 797 * new cl_verifier and a new cl_confirm
772 */ 798 */
773 expire_client(unconf); 799 expire_client(unconf);
774 if (!(new = create_client(clname))) 800 new = create_client(clname, dname);
801 if (new == NULL)
775 goto out; 802 goto out;
776 copy_verf(new,&clverifier); 803 copy_verf(new,&clverifier);
777 new->cl_addr = ip_addr; 804 new->cl_addr = ip_addr;
@@ -807,7 +834,7 @@ int
807nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm) 834nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
808{ 835{
809 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; 836 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
810 struct nfs4_client *clp, *conf = NULL, *unconf = NULL; 837 struct nfs4_client *conf, *unconf;
811 nfs4_verifier confirm = setclientid_confirm->sc_confirm; 838 nfs4_verifier confirm = setclientid_confirm->sc_confirm;
812 clientid_t * clid = &setclientid_confirm->sc_clientid; 839 clientid_t * clid = &setclientid_confirm->sc_clientid;
813 int status; 840 int status;
@@ -820,102 +847,90 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
820 */ 847 */
821 848
822 nfs4_lock_state(); 849 nfs4_lock_state();
823 clp = find_confirmed_client(clid); 850
824 if (clp) { 851 conf = find_confirmed_client(clid);
825 status = nfserr_inval; 852 unconf = find_unconfirmed_client(clid);
826 /* 853
827 * Found a record for this clientid. If the IP addresses 854 status = nfserr_clid_inuse;
828 * don't match, return ERR_INVAL just as if the record had 855 if (conf && conf->cl_addr != ip_addr)
829 * not been found. 856 goto out;
830 */ 857 if (unconf && unconf->cl_addr != ip_addr)
831 if (clp->cl_addr != ip_addr) { 858 goto out;
832 printk("NFSD: setclientid: string in use by client" 859
833 "(clientid %08x/%08x)\n",
834 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
835 goto out;
836 }
837 conf = clp;
838 }
839 clp = find_unconfirmed_client(clid);
840 if (clp) {
841 status = nfserr_inval;
842 if (clp->cl_addr != ip_addr) {
843 printk("NFSD: setclientid: string in use by client"
844 "(clientid %08x/%08x)\n",
845 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
846 goto out;
847 }
848 unconf = clp;
849 }
850 /* CASE 1:
851 * unconf record that matches input clientid and input confirm.
852 * conf record that matches input clientid.
853 * conf and unconf records match names, verifiers
854 */
855 if ((conf && unconf) && 860 if ((conf && unconf) &&
856 (cmp_verf(&unconf->cl_confirm, &confirm)) && 861 (cmp_verf(&unconf->cl_confirm, &confirm)) &&
857 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && 862 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
858 (cmp_name(&conf->cl_name,&unconf->cl_name)) && 863 (same_name(conf->cl_recdir,unconf->cl_recdir)) &&
859 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) { 864 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
865 /* CASE 1:
866 * unconf record that matches input clientid and input confirm.
867 * conf record that matches input clientid.
868 * conf and unconf records match names, verifiers
869 */
860 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 870 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred))
861 status = nfserr_clid_inuse; 871 status = nfserr_clid_inuse;
862 else { 872 else {
863 expire_client(conf); 873 /* XXX: We just turn off callbacks until we can handle
864 clp = unconf; 874 * change request correctly. */
865 move_to_confirmed(unconf); 875 atomic_set(&conf->cl_callback.cb_set, 0);
876 gen_confirm(conf);
877 expire_client(unconf);
866 status = nfs_ok; 878 status = nfs_ok;
879
867 } 880 }
868 goto out; 881 } else if ((conf && !unconf) ||
869 }
870 /* CASE 2:
871 * conf record that matches input clientid.
872 * if unconf record that matches input clientid, then unconf->cl_name
873 * or unconf->cl_verifier don't match the conf record.
874 */
875 if ((conf && !unconf) ||
876 ((conf && unconf) && 882 ((conf && unconf) &&
877 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || 883 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
878 !cmp_name(&conf->cl_name, &unconf->cl_name)))) { 884 !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
879 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) { 885 /* CASE 2:
886 * conf record that matches input clientid.
887 * if unconf record matches input clientid, then
888 * unconf->cl_name or unconf->cl_verifier don't match the
889 * conf record.
890 */
891 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred))
880 status = nfserr_clid_inuse; 892 status = nfserr_clid_inuse;
881 } else { 893 else
882 clp = conf;
883 status = nfs_ok; 894 status = nfs_ok;
884 } 895 } else if (!conf && unconf
885 goto out; 896 && cmp_verf(&unconf->cl_confirm, &confirm)) {
886 } 897 /* CASE 3:
887 /* CASE 3: 898 * conf record not found.
888 * conf record not found. 899 * unconf record found.
889 * unconf record found. 900 * unconf->cl_confirm matches input confirm
890 * unconf->cl_confirm matches input confirm 901 */
891 */
892 if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
893 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) { 902 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
894 status = nfserr_clid_inuse; 903 status = nfserr_clid_inuse;
895 } else { 904 } else {
896 status = nfs_ok; 905 unsigned int hash =
897 clp = unconf; 906 clientstr_hashval(unconf->cl_recdir);
907 conf = find_confirmed_client_by_str(unconf->cl_recdir,
908 hash);
909 if (conf) {
910 nfsd4_remove_clid_dir(conf);
911 expire_client(conf);
912 }
898 move_to_confirmed(unconf); 913 move_to_confirmed(unconf);
914 conf = unconf;
915 status = nfs_ok;
899 } 916 }
900 goto out; 917 } else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
901 } 918 && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm,
902 /* CASE 4: 919 &confirm)))) {
903 * conf record not found, or if conf, then conf->cl_confirm does not 920 /* CASE 4:
904 * match input confirm. 921 * conf record not found, or if conf, conf->cl_confirm does not
905 * unconf record not found, or if unconf, then unconf->cl_confirm 922 * match input confirm.
906 * does not match input confirm. 923 * unconf record not found, or if unconf, unconf->cl_confirm
907 */ 924 * does not match input confirm.
908 if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) && 925 */
909 (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
910 status = nfserr_stale_clientid; 926 status = nfserr_stale_clientid;
911 goto out; 927 } else {
928 /* check that we have hit one of the cases...*/
929 status = nfserr_clid_inuse;
912 } 930 }
913 /* check that we have hit one of the cases...*/
914 status = nfserr_inval;
915 goto out;
916out: 931out:
917 if (!status) 932 if (!status)
918 nfsd4_probe_callback(clp); 933 nfsd4_probe_callback(conf);
919 nfs4_unlock_state(); 934 nfs4_unlock_state();
920 return status; 935 return status;
921} 936}
@@ -961,60 +976,65 @@ alloc_init_file(struct inode *ino)
961 struct nfs4_file *fp; 976 struct nfs4_file *fp;
962 unsigned int hashval = file_hashval(ino); 977 unsigned int hashval = file_hashval(ino);
963 978
964 if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) { 979 fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
980 if (fp) {
981 kref_init(&fp->fi_ref);
965 INIT_LIST_HEAD(&fp->fi_hash); 982 INIT_LIST_HEAD(&fp->fi_hash);
966 INIT_LIST_HEAD(&fp->fi_perfile); 983 INIT_LIST_HEAD(&fp->fi_stateids);
967 INIT_LIST_HEAD(&fp->fi_del_perfile); 984 INIT_LIST_HEAD(&fp->fi_delegations);
968 list_add(&fp->fi_hash, &file_hashtbl[hashval]); 985 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
969 fp->fi_inode = igrab(ino); 986 fp->fi_inode = igrab(ino);
970 fp->fi_id = current_fileid++; 987 fp->fi_id = current_fileid++;
971 alloc_file++;
972 return fp; 988 return fp;
973 } 989 }
974 return NULL; 990 return NULL;
975} 991}
976 992
977static void 993static void
978release_all_files(void) 994nfsd4_free_slab(kmem_cache_t **slab)
979{ 995{
980 int i; 996 int status;
981 struct nfs4_file *fp;
982 997
983 for (i=0;i<FILE_HASH_SIZE;i++) { 998 if (*slab == NULL)
984 while (!list_empty(&file_hashtbl[i])) { 999 return;
985 fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash); 1000 status = kmem_cache_destroy(*slab);
986 /* this should never be more than once... */ 1001 *slab = NULL;
987 if (!list_empty(&fp->fi_perfile) || !list_empty(&fp->fi_del_perfile)) { 1002 WARN_ON(status);
988 printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
989 }
990 release_file(fp);
991 }
992 }
993} 1003}
994 1004
995kmem_cache_t *stateowner_slab = NULL; 1005static void
1006nfsd4_free_slabs(void)
1007{
1008 nfsd4_free_slab(&stateowner_slab);
1009 nfsd4_free_slab(&file_slab);
1010 nfsd4_free_slab(&stateid_slab);
1011 nfsd4_free_slab(&deleg_slab);
1012}
996 1013
997static int 1014static int
998nfsd4_init_slabs(void) 1015nfsd4_init_slabs(void)
999{ 1016{
1000 stateowner_slab = kmem_cache_create("nfsd4_stateowners", 1017 stateowner_slab = kmem_cache_create("nfsd4_stateowners",
1001 sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL); 1018 sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
1002 if (stateowner_slab == NULL) { 1019 if (stateowner_slab == NULL)
1003 dprintk("nfsd4: out of memory while initializing nfsv4\n"); 1020 goto out_nomem;
1004 return -ENOMEM; 1021 file_slab = kmem_cache_create("nfsd4_files",
1005 } 1022 sizeof(struct nfs4_file), 0, 0, NULL, NULL);
1023 if (file_slab == NULL)
1024 goto out_nomem;
1025 stateid_slab = kmem_cache_create("nfsd4_stateids",
1026 sizeof(struct nfs4_stateid), 0, 0, NULL, NULL);
1027 if (stateid_slab == NULL)
1028 goto out_nomem;
1029 deleg_slab = kmem_cache_create("nfsd4_delegations",
1030 sizeof(struct nfs4_delegation), 0, 0, NULL, NULL);
1031 if (deleg_slab == NULL)
1032 goto out_nomem;
1006 return 0; 1033 return 0;
1007} 1034out_nomem:
1008 1035 nfsd4_free_slabs();
1009static void 1036 dprintk("nfsd4: out of memory while initializing nfsv4\n");
1010nfsd4_free_slabs(void) 1037 return -ENOMEM;
1011{
1012 int status = 0;
1013
1014 if (stateowner_slab)
1015 status = kmem_cache_destroy(stateowner_slab);
1016 stateowner_slab = NULL;
1017 BUG_ON(status);
1018} 1038}
1019 1039
1020void 1040void
@@ -1055,14 +1075,13 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
1055 INIT_LIST_HEAD(&sop->so_idhash); 1075 INIT_LIST_HEAD(&sop->so_idhash);
1056 INIT_LIST_HEAD(&sop->so_strhash); 1076 INIT_LIST_HEAD(&sop->so_strhash);
1057 INIT_LIST_HEAD(&sop->so_perclient); 1077 INIT_LIST_HEAD(&sop->so_perclient);
1058 INIT_LIST_HEAD(&sop->so_perfilestate); 1078 INIT_LIST_HEAD(&sop->so_stateids);
1059 INIT_LIST_HEAD(&sop->so_perlockowner); /* not used */ 1079 INIT_LIST_HEAD(&sop->so_perstateid); /* not used */
1060 INIT_LIST_HEAD(&sop->so_close_lru); 1080 INIT_LIST_HEAD(&sop->so_close_lru);
1061 sop->so_time = 0; 1081 sop->so_time = 0;
1062 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]); 1082 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
1063 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]); 1083 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
1064 list_add(&sop->so_perclient, &clp->cl_perclient); 1084 list_add(&sop->so_perclient, &clp->cl_openowners);
1065 add_perclient++;
1066 sop->so_is_open_owner = 1; 1085 sop->so_is_open_owner = 1;
1067 sop->so_id = current_ownerid++; 1086 sop->so_id = current_ownerid++;
1068 sop->so_client = clp; 1087 sop->so_client = clp;
@@ -1080,10 +1099,10 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
1080{ 1099{
1081 struct nfs4_stateowner *lock_sop; 1100 struct nfs4_stateowner *lock_sop;
1082 1101
1083 while (!list_empty(&open_stp->st_perlockowner)) { 1102 while (!list_empty(&open_stp->st_lockowners)) {
1084 lock_sop = list_entry(open_stp->st_perlockowner.next, 1103 lock_sop = list_entry(open_stp->st_lockowners.next,
1085 struct nfs4_stateowner, so_perlockowner); 1104 struct nfs4_stateowner, so_perstateid);
1086 /* list_del(&open_stp->st_perlockowner); */ 1105 /* list_del(&open_stp->st_lockowners); */
1087 BUG_ON(lock_sop->so_is_open_owner); 1106 BUG_ON(lock_sop->so_is_open_owner);
1088 release_stateowner(lock_sop); 1107 release_stateowner(lock_sop);
1089 } 1108 }
@@ -1096,14 +1115,12 @@ unhash_stateowner(struct nfs4_stateowner *sop)
1096 1115
1097 list_del(&sop->so_idhash); 1116 list_del(&sop->so_idhash);
1098 list_del(&sop->so_strhash); 1117 list_del(&sop->so_strhash);
1099 if (sop->so_is_open_owner) { 1118 if (sop->so_is_open_owner)
1100 list_del(&sop->so_perclient); 1119 list_del(&sop->so_perclient);
1101 del_perclient++; 1120 list_del(&sop->so_perstateid);
1102 } 1121 while (!list_empty(&sop->so_stateids)) {
1103 list_del(&sop->so_perlockowner); 1122 stp = list_entry(sop->so_stateids.next,
1104 while (!list_empty(&sop->so_perfilestate)) { 1123 struct nfs4_stateid, st_perstateowner);
1105 stp = list_entry(sop->so_perfilestate.next,
1106 struct nfs4_stateid, st_perfilestate);
1107 if (sop->so_is_open_owner) 1124 if (sop->so_is_open_owner)
1108 release_stateid(stp, OPEN_STATE); 1125 release_stateid(stp, OPEN_STATE);
1109 else 1126 else
@@ -1125,14 +1142,14 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
1125 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id); 1142 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
1126 1143
1127 INIT_LIST_HEAD(&stp->st_hash); 1144 INIT_LIST_HEAD(&stp->st_hash);
1128 INIT_LIST_HEAD(&stp->st_perfilestate); 1145 INIT_LIST_HEAD(&stp->st_perstateowner);
1129 INIT_LIST_HEAD(&stp->st_perlockowner); 1146 INIT_LIST_HEAD(&stp->st_lockowners);
1130 INIT_LIST_HEAD(&stp->st_perfile); 1147 INIT_LIST_HEAD(&stp->st_perfile);
1131 list_add(&stp->st_hash, &stateid_hashtbl[hashval]); 1148 list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
1132 list_add(&stp->st_perfilestate, &sop->so_perfilestate); 1149 list_add(&stp->st_perstateowner, &sop->so_stateids);
1133 list_add_perfile++; 1150 list_add(&stp->st_perfile, &fp->fi_stateids);
1134 list_add(&stp->st_perfile, &fp->fi_perfile);
1135 stp->st_stateowner = sop; 1151 stp->st_stateowner = sop;
1152 get_nfs4_file(fp);
1136 stp->st_file = fp; 1153 stp->st_file = fp;
1137 stp->st_stateid.si_boot = boot_time; 1154 stp->st_stateid.si_boot = boot_time;
1138 stp->st_stateid.si_stateownerid = sop->so_id; 1155 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -1150,30 +1167,20 @@ release_stateid(struct nfs4_stateid *stp, int flags)
1150 struct file *filp = stp->st_vfs_file; 1167 struct file *filp = stp->st_vfs_file;
1151 1168
1152 list_del(&stp->st_hash); 1169 list_del(&stp->st_hash);
1153 list_del_perfile++;
1154 list_del(&stp->st_perfile); 1170 list_del(&stp->st_perfile);
1155 list_del(&stp->st_perfilestate); 1171 list_del(&stp->st_perstateowner);
1156 if (flags & OPEN_STATE) { 1172 if (flags & OPEN_STATE) {
1157 release_stateid_lockowners(stp); 1173 release_stateid_lockowners(stp);
1158 stp->st_vfs_file = NULL; 1174 stp->st_vfs_file = NULL;
1159 nfsd_close(filp); 1175 nfsd_close(filp);
1160 vfsclose++;
1161 } else if (flags & LOCK_STATE) 1176 } else if (flags & LOCK_STATE)
1162 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); 1177 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1163 kfree(stp); 1178 put_nfs4_file(stp->st_file);
1179 kmem_cache_free(stateid_slab, stp);
1164 stp = NULL; 1180 stp = NULL;
1165} 1181}
1166 1182
1167static void 1183static void
1168release_file(struct nfs4_file *fp)
1169{
1170 free_file++;
1171 list_del(&fp->fi_hash);
1172 iput(fp->fi_inode);
1173 kfree(fp);
1174}
1175
1176void
1177move_to_close_lru(struct nfs4_stateowner *sop) 1184move_to_close_lru(struct nfs4_stateowner *sop)
1178{ 1185{
1179 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop); 1186 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
@@ -1183,11 +1190,10 @@ move_to_close_lru(struct nfs4_stateowner *sop)
1183 sop->so_time = get_seconds(); 1190 sop->so_time = get_seconds();
1184} 1191}
1185 1192
1186void 1193static void
1187release_state_owner(struct nfs4_stateid *stp, int flag) 1194release_state_owner(struct nfs4_stateid *stp, int flag)
1188{ 1195{
1189 struct nfs4_stateowner *sop = stp->st_stateowner; 1196 struct nfs4_stateowner *sop = stp->st_stateowner;
1190 struct nfs4_file *fp = stp->st_file;
1191 1197
1192 dprintk("NFSD: release_state_owner\n"); 1198 dprintk("NFSD: release_state_owner\n");
1193 release_stateid(stp, flag); 1199 release_stateid(stp, flag);
@@ -1196,12 +1202,8 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
1196 * released by the laundromat service after the lease period 1202 * released by the laundromat service after the lease period
1197 * to enable us to handle CLOSE replay 1203 * to enable us to handle CLOSE replay
1198 */ 1204 */
1199 if (sop->so_confirmed && list_empty(&sop->so_perfilestate)) 1205 if (sop->so_confirmed && list_empty(&sop->so_stateids))
1200 move_to_close_lru(sop); 1206 move_to_close_lru(sop);
1201 /* unused nfs4_file's are releseed. XXX slab cache? */
1202 if (list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) {
1203 release_file(fp);
1204 }
1205} 1207}
1206 1208
1207static int 1209static int
@@ -1231,8 +1233,10 @@ find_file(struct inode *ino)
1231 struct nfs4_file *fp; 1233 struct nfs4_file *fp;
1232 1234
1233 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { 1235 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
1234 if (fp->fi_inode == ino) 1236 if (fp->fi_inode == ino) {
1237 get_nfs4_file(fp);
1235 return fp; 1238 return fp;
1239 }
1236 } 1240 }
1237 return NULL; 1241 return NULL;
1238} 1242}
@@ -1240,7 +1244,7 @@ find_file(struct inode *ino)
1240#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0) 1244#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
1241#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0) 1245#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
1242 1246
1243void 1247static void
1244set_access(unsigned int *access, unsigned long bmap) { 1248set_access(unsigned int *access, unsigned long bmap) {
1245 int i; 1249 int i;
1246 1250
@@ -1251,7 +1255,7 @@ set_access(unsigned int *access, unsigned long bmap) {
1251 } 1255 }
1252} 1256}
1253 1257
1254void 1258static void
1255set_deny(unsigned int *deny, unsigned long bmap) { 1259set_deny(unsigned int *deny, unsigned long bmap) {
1256 int i; 1260 int i;
1257 1261
@@ -1277,25 +1281,30 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
1277 * Called to check deny when READ with all zero stateid or 1281 * Called to check deny when READ with all zero stateid or
1278 * WRITE with all zero or all one stateid 1282 * WRITE with all zero or all one stateid
1279 */ 1283 */
1280int 1284static int
1281nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) 1285nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
1282{ 1286{
1283 struct inode *ino = current_fh->fh_dentry->d_inode; 1287 struct inode *ino = current_fh->fh_dentry->d_inode;
1284 struct nfs4_file *fp; 1288 struct nfs4_file *fp;
1285 struct nfs4_stateid *stp; 1289 struct nfs4_stateid *stp;
1290 int ret;
1286 1291
1287 dprintk("NFSD: nfs4_share_conflict\n"); 1292 dprintk("NFSD: nfs4_share_conflict\n");
1288 1293
1289 fp = find_file(ino); 1294 fp = find_file(ino);
1290 if (fp) { 1295 if (!fp)
1296 return nfs_ok;
1297 ret = nfserr_share_denied;
1291 /* Search for conflicting share reservations */ 1298 /* Search for conflicting share reservations */
1292 list_for_each_entry(stp, &fp->fi_perfile, st_perfile) { 1299 list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
1293 if (test_bit(deny_type, &stp->st_deny_bmap) || 1300 if (test_bit(deny_type, &stp->st_deny_bmap) ||
1294 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap)) 1301 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
1295 return nfserr_share_denied; 1302 goto out;
1296 }
1297 } 1303 }
1298 return nfs_ok; 1304 ret = nfs_ok;
1305out:
1306 put_nfs4_file(fp);
1307 return ret;
1299} 1308}
1300 1309
1301static inline void 1310static inline void
@@ -1427,7 +1436,7 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
1427 return -EAGAIN; 1436 return -EAGAIN;
1428} 1437}
1429 1438
1430struct lock_manager_operations nfsd_lease_mng_ops = { 1439static struct lock_manager_operations nfsd_lease_mng_ops = {
1431 .fl_break = nfsd_break_deleg_cb, 1440 .fl_break = nfsd_break_deleg_cb,
1432 .fl_release_private = nfsd_release_deleg_cb, 1441 .fl_release_private = nfsd_release_deleg_cb,
1433 .fl_copy_lock = nfsd_copy_lock_deleg_cb, 1442 .fl_copy_lock = nfsd_copy_lock_deleg_cb,
@@ -1526,6 +1535,51 @@ out:
1526 return status; 1535 return status;
1527} 1536}
1528 1537
1538static inline int
1539nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
1540{
1541 if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
1542 return nfserr_openmode;
1543 else
1544 return nfs_ok;
1545}
1546
1547static struct nfs4_delegation *
1548find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
1549{
1550 struct nfs4_delegation *dp;
1551
1552 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) {
1553 if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
1554 return dp;
1555 }
1556 return NULL;
1557}
1558
1559static int
1560nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
1561 struct nfs4_delegation **dp)
1562{
1563 int flags;
1564 int status = nfserr_bad_stateid;
1565
1566 *dp = find_delegation_file(fp, &open->op_delegate_stateid);
1567 if (*dp == NULL)
1568 goto out;
1569 flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
1570 RD_STATE : WR_STATE;
1571 status = nfs4_check_delegmode(*dp, flags);
1572 if (status)
1573 *dp = NULL;
1574out:
1575 if (open->op_claim_type != NFS4_OPEN_CLAIM_DELEGATE_CUR)
1576 return nfs_ok;
1577 if (status)
1578 return status;
1579 open->op_stateowner->so_confirmed = 1;
1580 return nfs_ok;
1581}
1582
1529static int 1583static int
1530nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp) 1584nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
1531{ 1585{
@@ -1533,7 +1587,7 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_state
1533 int status = nfserr_share_denied; 1587 int status = nfserr_share_denied;
1534 struct nfs4_stateowner *sop = open->op_stateowner; 1588 struct nfs4_stateowner *sop = open->op_stateowner;
1535 1589
1536 list_for_each_entry(local, &fp->fi_perfile, st_perfile) { 1590 list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
1537 /* ignore lock owners */ 1591 /* ignore lock owners */
1538 if (local->st_stateowner->so_is_open_owner == 0) 1592 if (local->st_stateowner->so_is_open_owner == 0)
1539 continue; 1593 continue;
@@ -1549,25 +1603,37 @@ out:
1549 return status; 1603 return status;
1550} 1604}
1551 1605
1606static inline struct nfs4_stateid *
1607nfs4_alloc_stateid(void)
1608{
1609 return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
1610}
1611
1552static int 1612static int
1553nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, 1613nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
1614 struct nfs4_delegation *dp,
1554 struct svc_fh *cur_fh, int flags) 1615 struct svc_fh *cur_fh, int flags)
1555{ 1616{
1556 struct nfs4_stateid *stp; 1617 struct nfs4_stateid *stp;
1557 int status;
1558 1618
1559 stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL); 1619 stp = nfs4_alloc_stateid();
1560 if (stp == NULL) 1620 if (stp == NULL)
1561 return nfserr_resource; 1621 return nfserr_resource;
1562 1622
1563 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file); 1623 if (dp) {
1564 if (status) { 1624 get_file(dp->dl_vfs_file);
1565 if (status == nfserr_dropit) 1625 stp->st_vfs_file = dp->dl_vfs_file;
1566 status = nfserr_jukebox; 1626 } else {
1567 kfree(stp); 1627 int status;
1568 return status; 1628 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
1629 &stp->st_vfs_file);
1630 if (status) {
1631 if (status == nfserr_dropit)
1632 status = nfserr_jukebox;
1633 kmem_cache_free(stateid_slab, stp);
1634 return status;
1635 }
1569 } 1636 }
1570 vfsopen++;
1571 *stpp = stp; 1637 *stpp = stp;
1572 return 0; 1638 return 0;
1573} 1639}
@@ -1628,6 +1694,7 @@ nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
1628 *status = nfserr_reclaim_bad; 1694 *status = nfserr_reclaim_bad;
1629 else { 1695 else {
1630 open->op_stateowner->so_confirmed = 1; 1696 open->op_stateowner->so_confirmed = 1;
1697 open->op_stateowner->so_client->cl_firststate = 1;
1631 open->op_stateowner->so_seqid--; 1698 open->op_stateowner->so_seqid--;
1632 } 1699 }
1633 } 1700 }
@@ -1646,14 +1713,30 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1646 int status, flag = 0; 1713 int status, flag = 0;
1647 1714
1648 flag = NFS4_OPEN_DELEGATE_NONE; 1715 flag = NFS4_OPEN_DELEGATE_NONE;
1649 if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL 1716 open->op_recall = 0;
1650 || !atomic_read(&cb->cb_set) || !sop->so_confirmed) 1717 switch (open->op_claim_type) {
1651 goto out; 1718 case NFS4_OPEN_CLAIM_PREVIOUS:
1652 1719 if (!atomic_read(&cb->cb_set))
1653 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 1720 open->op_recall = 1;
1654 flag = NFS4_OPEN_DELEGATE_WRITE; 1721 flag = open->op_delegate_type;
1655 else 1722 if (flag == NFS4_OPEN_DELEGATE_NONE)
1656 flag = NFS4_OPEN_DELEGATE_READ; 1723 goto out;
1724 break;
1725 case NFS4_OPEN_CLAIM_NULL:
1726 /* Let's not give out any delegations till everyone's
1727 * had the chance to reclaim theirs.... */
1728 if (nfs4_in_grace())
1729 goto out;
1730 if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
1731 goto out;
1732 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1733 flag = NFS4_OPEN_DELEGATE_WRITE;
1734 else
1735 flag = NFS4_OPEN_DELEGATE_READ;
1736 break;
1737 default:
1738 goto out;
1739 }
1657 1740
1658 dp = alloc_init_deleg(sop->so_client, stp, fh, flag); 1741 dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
1659 if (dp == NULL) { 1742 if (dp == NULL) {
@@ -1687,6 +1770,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1687 dp->dl_stateid.si_fileid, 1770 dp->dl_stateid.si_fileid,
1688 dp->dl_stateid.si_generation); 1771 dp->dl_stateid.si_generation);
1689out: 1772out:
1773 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
1774 && flag == NFS4_OPEN_DELEGATE_NONE
1775 && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
1776 printk("NFSD: WARNING: refusing delegation reclaim\n");
1690 open->op_delegate_type = flag; 1777 open->op_delegate_type = flag;
1691} 1778}
1692 1779
@@ -1699,6 +1786,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1699 struct nfs4_file *fp = NULL; 1786 struct nfs4_file *fp = NULL;
1700 struct inode *ino = current_fh->fh_dentry->d_inode; 1787 struct inode *ino = current_fh->fh_dentry->d_inode;
1701 struct nfs4_stateid *stp = NULL; 1788 struct nfs4_stateid *stp = NULL;
1789 struct nfs4_delegation *dp = NULL;
1702 int status; 1790 int status;
1703 1791
1704 status = nfserr_inval; 1792 status = nfserr_inval;
@@ -1713,7 +1801,13 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1713 if (fp) { 1801 if (fp) {
1714 if ((status = nfs4_check_open(fp, open, &stp))) 1802 if ((status = nfs4_check_open(fp, open, &stp)))
1715 goto out; 1803 goto out;
1804 status = nfs4_check_deleg(fp, open, &dp);
1805 if (status)
1806 goto out;
1716 } else { 1807 } else {
1808 status = nfserr_bad_stateid;
1809 if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
1810 goto out;
1717 status = nfserr_resource; 1811 status = nfserr_resource;
1718 fp = alloc_init_file(ino); 1812 fp = alloc_init_file(ino);
1719 if (fp == NULL) 1813 if (fp == NULL)
@@ -1736,7 +1830,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1736 flags = MAY_WRITE; 1830 flags = MAY_WRITE;
1737 else 1831 else
1738 flags = MAY_READ; 1832 flags = MAY_READ;
1739 if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags))) 1833 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
1834 if (status)
1740 goto out; 1835 goto out;
1741 init_stateid(stp, fp, open); 1836 init_stateid(stp, fp, open);
1742 status = nfsd4_truncate(rqstp, current_fh, open); 1837 status = nfsd4_truncate(rqstp, current_fh, open);
@@ -1759,10 +1854,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1759 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid, 1854 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
1760 stp->st_stateid.si_fileid, stp->st_stateid.si_generation); 1855 stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
1761out: 1856out:
1762 /* take the opportunity to clean up unused state */ 1857 if (fp)
1763 if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) 1858 put_nfs4_file(fp);
1764 release_file(fp);
1765
1766 /* CLAIM_PREVIOUS has different error returns */ 1859 /* CLAIM_PREVIOUS has different error returns */
1767 nfs4_set_claim_prev(open, &status); 1860 nfs4_set_claim_prev(open, &status);
1768 /* 1861 /*
@@ -1775,6 +1868,7 @@ out:
1775 return status; 1868 return status;
1776} 1869}
1777 1870
1871static struct workqueue_struct *laundry_wq;
1778static struct work_struct laundromat_work; 1872static struct work_struct laundromat_work;
1779static void laundromat_main(void *); 1873static void laundromat_main(void *);
1780static DECLARE_WORK(laundromat_work, laundromat_main, NULL); 1874static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
@@ -1800,7 +1894,7 @@ nfsd4_renew(clientid_t *clid)
1800 } 1894 }
1801 renew_client(clp); 1895 renew_client(clp);
1802 status = nfserr_cb_path_down; 1896 status = nfserr_cb_path_down;
1803 if (!list_empty(&clp->cl_del_perclnt) 1897 if (!list_empty(&clp->cl_delegations)
1804 && !atomic_read(&clp->cl_callback.cb_set)) 1898 && !atomic_read(&clp->cl_callback.cb_set))
1805 goto out; 1899 goto out;
1806 status = nfs_ok; 1900 status = nfs_ok;
@@ -1809,7 +1903,15 @@ out:
1809 return status; 1903 return status;
1810} 1904}
1811 1905
1812time_t 1906static void
1907end_grace(void)
1908{
1909 dprintk("NFSD: end of grace period\n");
1910 nfsd4_recdir_purge_old();
1911 in_grace = 0;
1912}
1913
1914static time_t
1813nfs4_laundromat(void) 1915nfs4_laundromat(void)
1814{ 1916{
1815 struct nfs4_client *clp; 1917 struct nfs4_client *clp;
@@ -1823,6 +1925,8 @@ nfs4_laundromat(void)
1823 nfs4_lock_state(); 1925 nfs4_lock_state();
1824 1926
1825 dprintk("NFSD: laundromat service - starting\n"); 1927 dprintk("NFSD: laundromat service - starting\n");
1928 if (in_grace)
1929 end_grace();
1826 list_for_each_safe(pos, next, &client_lru) { 1930 list_for_each_safe(pos, next, &client_lru) {
1827 clp = list_entry(pos, struct nfs4_client, cl_lru); 1931 clp = list_entry(pos, struct nfs4_client, cl_lru);
1828 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { 1932 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
@@ -1833,6 +1937,7 @@ nfs4_laundromat(void)
1833 } 1937 }
1834 dprintk("NFSD: purging unused client (clientid %08x)\n", 1938 dprintk("NFSD: purging unused client (clientid %08x)\n",
1835 clp->cl_clientid.cl_id); 1939 clp->cl_clientid.cl_id);
1940 nfsd4_remove_clid_dir(clp);
1836 expire_client(clp); 1941 expire_client(clp);
1837 } 1942 }
1838 INIT_LIST_HEAD(&reaplist); 1943 INIT_LIST_HEAD(&reaplist);
@@ -1882,13 +1987,13 @@ laundromat_main(void *not_used)
1882 1987
1883 t = nfs4_laundromat(); 1988 t = nfs4_laundromat();
1884 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t); 1989 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
1885 schedule_delayed_work(&laundromat_work, t*HZ); 1990 queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
1886} 1991}
1887 1992
1888/* search ownerid_hashtbl[] and close_lru for stateid owner 1993/* search ownerid_hashtbl[] and close_lru for stateid owner
1889 * (stateid->si_stateownerid) 1994 * (stateid->si_stateownerid)
1890 */ 1995 */
1891struct nfs4_stateowner * 1996static struct nfs4_stateowner *
1892find_openstateowner_id(u32 st_id, int flags) { 1997find_openstateowner_id(u32 st_id, int flags) {
1893 struct nfs4_stateowner *local = NULL; 1998 struct nfs4_stateowner *local = NULL;
1894 1999
@@ -1949,15 +2054,6 @@ out:
1949} 2054}
1950 2055
1951static inline int 2056static inline int
1952nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
1953{
1954 if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
1955 return nfserr_openmode;
1956 else
1957 return nfs_ok;
1958}
1959
1960static inline int
1961check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) 2057check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
1962{ 2058{
1963 /* Trying to call delegreturn with a special stateid? Yuch: */ 2059 /* Trying to call delegreturn with a special stateid? Yuch: */
@@ -2071,7 +2167,7 @@ out:
2071/* 2167/*
2072 * Checks for sequence id mutating operations. 2168 * Checks for sequence id mutating operations.
2073 */ 2169 */
2074int 2170static int
2075nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid) 2171nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
2076{ 2172{
2077 int status; 2173 int status;
@@ -2230,6 +2326,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
2230 stp->st_stateid.si_stateownerid, 2326 stp->st_stateid.si_stateownerid,
2231 stp->st_stateid.si_fileid, 2327 stp->st_stateid.si_fileid,
2232 stp->st_stateid.si_generation); 2328 stp->st_stateid.si_generation);
2329
2330 nfsd4_create_clid_dir(sop->so_client);
2233out: 2331out:
2234 if (oc->oc_stateowner) 2332 if (oc->oc_stateowner)
2235 nfs4_get_stateowner(oc->oc_stateowner); 2333 nfs4_get_stateowner(oc->oc_stateowner);
@@ -2387,7 +2485,7 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
2387static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; 2485static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
2388static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE]; 2486static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
2389 2487
2390struct nfs4_stateid * 2488static struct nfs4_stateid *
2391find_stateid(stateid_t *stid, int flags) 2489find_stateid(stateid_t *stid, int flags)
2392{ 2490{
2393 struct nfs4_stateid *local = NULL; 2491 struct nfs4_stateid *local = NULL;
@@ -2419,25 +2517,19 @@ find_stateid(stateid_t *stid, int flags)
2419static struct nfs4_delegation * 2517static struct nfs4_delegation *
2420find_delegation_stateid(struct inode *ino, stateid_t *stid) 2518find_delegation_stateid(struct inode *ino, stateid_t *stid)
2421{ 2519{
2422 struct nfs4_delegation *dp = NULL; 2520 struct nfs4_file *fp;
2423 struct nfs4_file *fp = NULL; 2521 struct nfs4_delegation *dl;
2424 u32 st_id;
2425 2522
2426 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n", 2523 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
2427 stid->si_boot, stid->si_stateownerid, 2524 stid->si_boot, stid->si_stateownerid,
2428 stid->si_fileid, stid->si_generation); 2525 stid->si_fileid, stid->si_generation);
2429 2526
2430 st_id = stid->si_stateownerid;
2431 fp = find_file(ino); 2527 fp = find_file(ino);
2432 if (fp) { 2528 if (!fp)
2433 list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) { 2529 return NULL;
2434 if(dp->dl_stateid.si_stateownerid == st_id) { 2530 dl = find_delegation_file(fp, stid);
2435 dprintk("NFSD: find_delegation dp %p\n",dp); 2531 put_nfs4_file(fp);
2436 return dp; 2532 return dl;
2437 }
2438 }
2439 }
2440 return NULL;
2441} 2533}
2442 2534
2443/* 2535/*
@@ -2457,7 +2549,7 @@ nfs4_transform_lock_offset(struct file_lock *lock)
2457 lock->fl_end = OFFSET_MAX; 2549 lock->fl_end = OFFSET_MAX;
2458} 2550}
2459 2551
2460int 2552static int
2461nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval) 2553nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
2462{ 2554{
2463 struct nfs4_stateowner *local = NULL; 2555 struct nfs4_stateowner *local = NULL;
@@ -2498,22 +2590,6 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
2498} 2590}
2499 2591
2500static struct nfs4_stateowner * 2592static struct nfs4_stateowner *
2501find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
2502{
2503 struct nfs4_stateowner *local = NULL;
2504 int i;
2505
2506 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2507 list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
2508 if (!cmp_owner_str(local, owner, clid))
2509 continue;
2510 return local;
2511 }
2512 }
2513 return NULL;
2514}
2515
2516static struct nfs4_stateowner *
2517find_lockstateowner_str(struct inode *inode, clientid_t *clid, 2593find_lockstateowner_str(struct inode *inode, clientid_t *clid,
2518 struct xdr_netobj *owner) 2594 struct xdr_netobj *owner)
2519{ 2595{
@@ -2548,13 +2624,13 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2548 INIT_LIST_HEAD(&sop->so_idhash); 2624 INIT_LIST_HEAD(&sop->so_idhash);
2549 INIT_LIST_HEAD(&sop->so_strhash); 2625 INIT_LIST_HEAD(&sop->so_strhash);
2550 INIT_LIST_HEAD(&sop->so_perclient); 2626 INIT_LIST_HEAD(&sop->so_perclient);
2551 INIT_LIST_HEAD(&sop->so_perfilestate); 2627 INIT_LIST_HEAD(&sop->so_stateids);
2552 INIT_LIST_HEAD(&sop->so_perlockowner); 2628 INIT_LIST_HEAD(&sop->so_perstateid);
2553 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */ 2629 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
2554 sop->so_time = 0; 2630 sop->so_time = 0;
2555 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]); 2631 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
2556 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]); 2632 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
2557 list_add(&sop->so_perlockowner, &open_stp->st_perlockowner); 2633 list_add(&sop->so_perstateid, &open_stp->st_lockowners);
2558 sop->so_is_open_owner = 0; 2634 sop->so_is_open_owner = 0;
2559 sop->so_id = current_ownerid++; 2635 sop->so_id = current_ownerid++;
2560 sop->so_client = clp; 2636 sop->so_client = clp;
@@ -2567,24 +2643,24 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2567 return sop; 2643 return sop;
2568} 2644}
2569 2645
2570struct nfs4_stateid * 2646static struct nfs4_stateid *
2571alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp) 2647alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
2572{ 2648{
2573 struct nfs4_stateid *stp; 2649 struct nfs4_stateid *stp;
2574 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id); 2650 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
2575 2651
2576 if ((stp = kmalloc(sizeof(struct nfs4_stateid), 2652 stp = nfs4_alloc_stateid();
2577 GFP_KERNEL)) == NULL) 2653 if (stp == NULL)
2578 goto out; 2654 goto out;
2579 INIT_LIST_HEAD(&stp->st_hash); 2655 INIT_LIST_HEAD(&stp->st_hash);
2580 INIT_LIST_HEAD(&stp->st_perfile); 2656 INIT_LIST_HEAD(&stp->st_perfile);
2581 INIT_LIST_HEAD(&stp->st_perfilestate); 2657 INIT_LIST_HEAD(&stp->st_perstateowner);
2582 INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */ 2658 INIT_LIST_HEAD(&stp->st_lockowners); /* not used */
2583 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]); 2659 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
2584 list_add(&stp->st_perfile, &fp->fi_perfile); 2660 list_add(&stp->st_perfile, &fp->fi_stateids);
2585 list_add_perfile++; 2661 list_add(&stp->st_perstateowner, &sop->so_stateids);
2586 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
2587 stp->st_stateowner = sop; 2662 stp->st_stateowner = sop;
2663 get_nfs4_file(fp);
2588 stp->st_file = fp; 2664 stp->st_file = fp;
2589 stp->st_stateid.si_boot = boot_time; 2665 stp->st_stateid.si_boot = boot_time;
2590 stp->st_stateid.si_stateownerid = sop->so_id; 2666 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -2598,7 +2674,7 @@ out:
2598 return stp; 2674 return stp;
2599} 2675}
2600 2676
2601int 2677static int
2602check_lock_length(u64 offset, u64 length) 2678check_lock_length(u64 offset, u64 length)
2603{ 2679{
2604 return ((length == 0) || ((length != ~(u64)0) && 2680 return ((length == 0) || ((length != ~(u64)0) &&
@@ -2611,7 +2687,7 @@ check_lock_length(u64 offset, u64 length)
2611int 2687int
2612nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock) 2688nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
2613{ 2689{
2614 struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL; 2690 struct nfs4_stateowner *open_sop = NULL;
2615 struct nfs4_stateid *lock_stp; 2691 struct nfs4_stateid *lock_stp;
2616 struct file *filp; 2692 struct file *filp;
2617 struct file_lock file_lock; 2693 struct file_lock file_lock;
@@ -2670,16 +2746,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2670 strhashval = lock_ownerstr_hashval(fp->fi_inode, 2746 strhashval = lock_ownerstr_hashval(fp->fi_inode,
2671 open_sop->so_client->cl_clientid.cl_id, 2747 open_sop->so_client->cl_clientid.cl_id,
2672 &lock->v.new.owner); 2748 &lock->v.new.owner);
2673 /* 2749 /* XXX: Do we need to check for duplicate stateowners on
2674 * If we already have this lock owner, the client is in 2750 * the same file, or should they just be allowed (and
2675 * error (or our bookeeping is wrong!) 2751 * create new stateids)? */
2676 * for asking for a 'new lock'.
2677 */
2678 status = nfserr_bad_stateid;
2679 lock_sop = find_lockstateowner(&lock->v.new.owner,
2680 &lock->v.new.clientid);
2681 if (lock_sop)
2682 goto out;
2683 status = nfserr_resource; 2752 status = nfserr_resource;
2684 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock))) 2753 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
2685 goto out; 2754 goto out;
@@ -2970,8 +3039,11 @@ int
2970nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner) 3039nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
2971{ 3040{
2972 clientid_t *clid = &rlockowner->rl_clientid; 3041 clientid_t *clid = &rlockowner->rl_clientid;
2973 struct nfs4_stateowner *local = NULL; 3042 struct nfs4_stateowner *sop;
3043 struct nfs4_stateid *stp;
2974 struct xdr_netobj *owner = &rlockowner->rl_owner; 3044 struct xdr_netobj *owner = &rlockowner->rl_owner;
3045 struct list_head matches;
3046 int i;
2975 int status; 3047 int status;
2976 3048
2977 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", 3049 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
@@ -2987,22 +3059,32 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
2987 3059
2988 nfs4_lock_state(); 3060 nfs4_lock_state();
2989 3061
2990 status = nfs_ok; 3062 status = nfserr_locks_held;
2991 local = find_lockstateowner(owner, clid); 3063 /* XXX: we're doing a linear search through all the lockowners.
2992 if (local) { 3064 * Yipes! For now we'll just hope clients aren't really using
2993 struct nfs4_stateid *stp; 3065 * release_lockowner much, but eventually we have to fix these
2994 3066 * data structures. */
2995 /* check for any locks held by any stateid 3067 INIT_LIST_HEAD(&matches);
2996 * associated with the (lock) stateowner */ 3068 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2997 status = nfserr_locks_held; 3069 list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
2998 list_for_each_entry(stp, &local->so_perfilestate, 3070 if (!cmp_owner_str(sop, owner, clid))
2999 st_perfilestate) { 3071 continue;
3000 if (check_for_locks(stp->st_vfs_file, local)) 3072 list_for_each_entry(stp, &sop->so_stateids,
3001 goto out; 3073 st_perstateowner) {
3074 if (check_for_locks(stp->st_vfs_file, sop))
3075 goto out;
3076 /* Note: so_perclient unused for lockowners,
3077 * so it's OK to fool with here. */
3078 list_add(&sop->so_perclient, &matches);
3079 }
3002 } 3080 }
3003 /* no locks held by (lock) stateowner */ 3081 }
3004 status = nfs_ok; 3082 /* Clients probably won't expect us to return with some (but not all)
3005 release_stateowner(local); 3083 * of the lockowner state released; so don't release any until all
3084 * have been checked. */
3085 status = nfs_ok;
3086 list_for_each_entry(sop, &matches, so_perclient) {
3087 release_stateowner(sop);
3006 } 3088 }
3007out: 3089out:
3008 nfs4_unlock_state(); 3090 nfs4_unlock_state();
@@ -3010,39 +3092,38 @@ out:
3010} 3092}
3011 3093
3012static inline struct nfs4_client_reclaim * 3094static inline struct nfs4_client_reclaim *
3013alloc_reclaim(int namelen) 3095alloc_reclaim(void)
3014{ 3096{
3015 struct nfs4_client_reclaim *crp = NULL; 3097 return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
3098}
3016 3099
3017 crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL); 3100int
3018 if (!crp) 3101nfs4_has_reclaimed_state(const char *name)
3019 return NULL; 3102{
3020 crp->cr_name.data = kmalloc(namelen, GFP_KERNEL); 3103 unsigned int strhashval = clientstr_hashval(name);
3021 if (!crp->cr_name.data) { 3104 struct nfs4_client *clp;
3022 kfree(crp); 3105
3023 return NULL; 3106 clp = find_confirmed_client_by_str(name, strhashval);
3024 } 3107 return clp ? 1 : 0;
3025 return crp;
3026} 3108}
3027 3109
3028/* 3110/*
3029 * failure => all reset bets are off, nfserr_no_grace... 3111 * failure => all reset bets are off, nfserr_no_grace...
3030 */ 3112 */
3031static int 3113int
3032nfs4_client_to_reclaim(char *name, int namlen) 3114nfs4_client_to_reclaim(const char *name)
3033{ 3115{
3034 unsigned int strhashval; 3116 unsigned int strhashval;
3035 struct nfs4_client_reclaim *crp = NULL; 3117 struct nfs4_client_reclaim *crp = NULL;
3036 3118
3037 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name); 3119 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
3038 crp = alloc_reclaim(namlen); 3120 crp = alloc_reclaim();
3039 if (!crp) 3121 if (!crp)
3040 return 0; 3122 return 0;
3041 strhashval = clientstr_hashval(name, namlen); 3123 strhashval = clientstr_hashval(name);
3042 INIT_LIST_HEAD(&crp->cr_strhash); 3124 INIT_LIST_HEAD(&crp->cr_strhash);
3043 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]); 3125 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
3044 memcpy(crp->cr_name.data, name, namlen); 3126 memcpy(crp->cr_recdir, name, HEXDIR_LEN);
3045 crp->cr_name.len = namlen;
3046 reclaim_str_hashtbl_size++; 3127 reclaim_str_hashtbl_size++;
3047 return 1; 3128 return 1;
3048} 3129}
@@ -3053,13 +3134,11 @@ nfs4_release_reclaim(void)
3053 struct nfs4_client_reclaim *crp = NULL; 3134 struct nfs4_client_reclaim *crp = NULL;
3054 int i; 3135 int i;
3055 3136
3056 BUG_ON(!nfs4_reclaim_init);
3057 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 3137 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3058 while (!list_empty(&reclaim_str_hashtbl[i])) { 3138 while (!list_empty(&reclaim_str_hashtbl[i])) {
3059 crp = list_entry(reclaim_str_hashtbl[i].next, 3139 crp = list_entry(reclaim_str_hashtbl[i].next,
3060 struct nfs4_client_reclaim, cr_strhash); 3140 struct nfs4_client_reclaim, cr_strhash);
3061 list_del(&crp->cr_strhash); 3141 list_del(&crp->cr_strhash);
3062 kfree(crp->cr_name.data);
3063 kfree(crp); 3142 kfree(crp);
3064 reclaim_str_hashtbl_size--; 3143 reclaim_str_hashtbl_size--;
3065 } 3144 }
@@ -3069,7 +3148,7 @@ nfs4_release_reclaim(void)
3069 3148
3070/* 3149/*
3071 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ 3150 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
3072struct nfs4_client_reclaim * 3151static struct nfs4_client_reclaim *
3073nfs4_find_reclaim_client(clientid_t *clid) 3152nfs4_find_reclaim_client(clientid_t *clid)
3074{ 3153{
3075 unsigned int strhashval; 3154 unsigned int strhashval;
@@ -3082,13 +3161,14 @@ nfs4_find_reclaim_client(clientid_t *clid)
3082 if (clp == NULL) 3161 if (clp == NULL)
3083 return NULL; 3162 return NULL;
3084 3163
3085 dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n", 3164 dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
3086 clp->cl_name.len, clp->cl_name.data); 3165 clp->cl_name.len, clp->cl_name.data,
3166 clp->cl_recdir);
3087 3167
3088 /* find clp->cl_name in reclaim_str_hashtbl */ 3168 /* find clp->cl_name in reclaim_str_hashtbl */
3089 strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len); 3169 strhashval = clientstr_hashval(clp->cl_recdir);
3090 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) { 3170 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
3091 if (cmp_name(&crp->cr_name, &clp->cl_name)) { 3171 if (same_name(crp->cr_recdir, clp->cl_recdir)) {
3092 return crp; 3172 return crp;
3093 } 3173 }
3094 } 3174 }
@@ -3101,30 +3181,16 @@ nfs4_find_reclaim_client(clientid_t *clid)
3101int 3181int
3102nfs4_check_open_reclaim(clientid_t *clid) 3182nfs4_check_open_reclaim(clientid_t *clid)
3103{ 3183{
3104 struct nfs4_client_reclaim *crp; 3184 return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
3105
3106 if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
3107 return nfserr_reclaim_bad;
3108 return nfs_ok;
3109} 3185}
3110 3186
3187/* initialization to perform at module load time: */
3111 3188
3112/* 3189void
3113 * Start and stop routines 3190nfs4_state_init(void)
3114 */
3115
3116static void
3117__nfs4_state_init(void)
3118{ 3191{
3119 int i; 3192 int i;
3120 time_t grace_time;
3121 3193
3122 if (!nfs4_reclaim_init) {
3123 for (i = 0; i < CLIENT_HASH_SIZE; i++)
3124 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
3125 reclaim_str_hashtbl_size = 0;
3126 nfs4_reclaim_init = 1;
3127 }
3128 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 3194 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3129 INIT_LIST_HEAD(&conf_id_hashtbl[i]); 3195 INIT_LIST_HEAD(&conf_id_hashtbl[i]);
3130 INIT_LIST_HEAD(&conf_str_hashtbl[i]); 3196 INIT_LIST_HEAD(&conf_str_hashtbl[i]);
@@ -3146,26 +3212,46 @@ __nfs4_state_init(void)
3146 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]); 3212 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
3147 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]); 3213 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
3148 } 3214 }
3149 memset(&zerostateid, 0, sizeof(stateid_t));
3150 memset(&onestateid, ~0, sizeof(stateid_t)); 3215 memset(&onestateid, ~0, sizeof(stateid_t));
3151
3152 INIT_LIST_HEAD(&close_lru); 3216 INIT_LIST_HEAD(&close_lru);
3153 INIT_LIST_HEAD(&client_lru); 3217 INIT_LIST_HEAD(&client_lru);
3154 INIT_LIST_HEAD(&del_recall_lru); 3218 INIT_LIST_HEAD(&del_recall_lru);
3155 spin_lock_init(&recall_lock); 3219 for (i = 0; i < CLIENT_HASH_SIZE; i++)
3220 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
3221 reclaim_str_hashtbl_size = 0;
3222}
3223
3224static void
3225nfsd4_load_reboot_recovery_data(void)
3226{
3227 int status;
3228
3229 nfs4_lock_state();
3230 nfsd4_init_recdir(user_recovery_dirname);
3231 status = nfsd4_recdir_load();
3232 nfs4_unlock_state();
3233 if (status)
3234 printk("NFSD: Failure reading reboot recovery data\n");
3235}
3236
3237/* initialization to perform when the nfsd service is started: */
3238
3239static void
3240__nfs4_state_start(void)
3241{
3242 time_t grace_time;
3243
3156 boot_time = get_seconds(); 3244 boot_time = get_seconds();
3157 grace_time = max(old_lease_time, lease_time); 3245 grace_time = max(user_lease_time, lease_time);
3158 if (reclaim_str_hashtbl_size == 0) 3246 lease_time = user_lease_time;
3159 grace_time = 0; 3247 in_grace = 1;
3160 if (grace_time) 3248 printk("NFSD: starting %ld-second grace period\n", grace_time);
3161 printk("NFSD: starting %ld-second grace period\n", grace_time); 3249 laundry_wq = create_singlethread_workqueue("nfsd4");
3162 grace_end = boot_time + grace_time; 3250 queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
3163 INIT_WORK(&laundromat_work,laundromat_main, NULL);
3164 schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
3165} 3251}
3166 3252
3167int 3253int
3168nfs4_state_init(void) 3254nfs4_state_start(void)
3169{ 3255{
3170 int status; 3256 int status;
3171 3257
@@ -3174,7 +3260,8 @@ nfs4_state_init(void)
3174 status = nfsd4_init_slabs(); 3260 status = nfsd4_init_slabs();
3175 if (status) 3261 if (status)
3176 return status; 3262 return status;
3177 __nfs4_state_init(); 3263 nfsd4_load_reboot_recovery_data();
3264 __nfs4_state_start();
3178 nfs4_init = 1; 3265 nfs4_init = 1;
3179 return 0; 3266 return 0;
3180} 3267}
@@ -3182,14 +3269,7 @@ nfs4_state_init(void)
3182int 3269int
3183nfs4_in_grace(void) 3270nfs4_in_grace(void)
3184{ 3271{
3185 return get_seconds() < grace_end; 3272 return in_grace;
3186}
3187
3188void
3189set_no_grace(void)
3190{
3191 printk("NFSD: ERROR in reboot recovery. State reclaims will fail.\n");
3192 grace_end = get_seconds();
3193} 3273}
3194 3274
3195time_t 3275time_t
@@ -3236,21 +3316,11 @@ __nfs4_state_shutdown(void)
3236 unhash_delegation(dp); 3316 unhash_delegation(dp);
3237 } 3317 }
3238 3318
3239 release_all_files();
3240 cancel_delayed_work(&laundromat_work); 3319 cancel_delayed_work(&laundromat_work);
3241 flush_scheduled_work(); 3320 flush_workqueue(laundry_wq);
3321 destroy_workqueue(laundry_wq);
3322 nfsd4_shutdown_recdir();
3242 nfs4_init = 0; 3323 nfs4_init = 0;
3243 dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
3244 list_add_perfile, list_del_perfile);
3245 dprintk("NFSD: add_perclient %d del_perclient %d\n",
3246 add_perclient, del_perclient);
3247 dprintk("NFSD: alloc_file %d free_file %d\n",
3248 alloc_file, free_file);
3249 dprintk("NFSD: vfsopen %d vfsclose %d\n",
3250 vfsopen, vfsclose);
3251 dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
3252 alloc_delegation, free_delegation);
3253
3254} 3324}
3255 3325
3256void 3326void
@@ -3263,56 +3333,48 @@ nfs4_state_shutdown(void)
3263 nfs4_unlock_state(); 3333 nfs4_unlock_state();
3264} 3334}
3265 3335
3336static void
3337nfs4_set_recdir(char *recdir)
3338{
3339 nfs4_lock_state();
3340 strcpy(user_recovery_dirname, recdir);
3341 nfs4_unlock_state();
3342}
3343
3344/*
3345 * Change the NFSv4 recovery directory to recdir.
3346 */
3347int
3348nfs4_reset_recoverydir(char *recdir)
3349{
3350 int status;
3351 struct nameidata nd;
3352
3353 status = path_lookup(recdir, LOOKUP_FOLLOW, &nd);
3354 if (status)
3355 return status;
3356 status = -ENOTDIR;
3357 if (S_ISDIR(nd.dentry->d_inode->i_mode)) {
3358 nfs4_set_recdir(recdir);
3359 status = 0;
3360 }
3361 path_release(&nd);
3362 return status;
3363}
3364
3266/* 3365/*
3267 * Called when leasetime is changed. 3366 * Called when leasetime is changed.
3268 * 3367 *
3269 * if nfsd is not started, simply set the global lease. 3368 * The only way the protocol gives us to handle on-the-fly lease changes is to
3270 * 3369 * simulate a reboot. Instead of doing that, we just wait till the next time
3271 * if nfsd(s) are running, lease change requires nfsv4 state to be reset. 3370 * we start to register any changes in lease time. If the administrator
3272 * e.g: boot_time is reset, existing nfs4_client structs are 3371 * really wants to change the lease time *now*, they can go ahead and bring
3273 * used to fill reclaim_str_hashtbl, then all state (except for the 3372 * nfsd down and then back up again after changing the lease time.
3274 * reclaim_str_hashtbl) is re-initialized.
3275 *
3276 * if the old lease time is greater than the new lease time, the grace
3277 * period needs to be set to the old lease time to allow clients to reclaim
3278 * their state. XXX - we may want to set the grace period == lease time
3279 * after an initial grace period == old lease time
3280 *
3281 * if an error occurs in this process, the new lease is set, but the server
3282 * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
3283 * which means OPEN/LOCK/READ/WRITE will fail during grace period.
3284 *
3285 * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
3286 * OPEN and LOCK reclaims.
3287 */ 3373 */
3288void 3374void
3289nfs4_reset_lease(time_t leasetime) 3375nfs4_reset_lease(time_t leasetime)
3290{ 3376{
3291 struct nfs4_client *clp; 3377 lock_kernel();
3292 int i; 3378 user_lease_time = leasetime;
3293 3379 unlock_kernel();
3294 printk("NFSD: New leasetime %ld\n",leasetime);
3295 if (!nfs4_init)
3296 return;
3297 nfs4_lock_state();
3298 old_lease_time = lease_time;
3299 lease_time = leasetime;
3300
3301 nfs4_release_reclaim();
3302
3303 /* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
3304 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3305 list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
3306 if (!nfs4_client_to_reclaim(clp->cl_name.data,
3307 clp->cl_name.len)) {
3308 nfs4_release_reclaim();
3309 goto init_state;
3310 }
3311 }
3312 }
3313init_state:
3314 __nfs4_state_shutdown();
3315 __nfs4_state_init();
3316 nfs4_unlock_state();
3317} 3380}
3318
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 36a058a112d5..91fb171d2ace 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -136,7 +136,7 @@ xdr_error: \
136 } \ 136 } \
137} while (0) 137} while (0)
138 138
139u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) 139static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
140{ 140{
141 /* We want more bytes than seem to be available. 141 /* We want more bytes than seem to be available.
142 * Maybe we need a new page, maybe we have just run out 142 * Maybe we need a new page, maybe we have just run out
@@ -190,7 +190,7 @@ defer_free(struct nfsd4_compoundargs *argp,
190 return 0; 190 return 0;
191} 191}
192 192
193char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes) 193static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
194{ 194{
195 void *new = NULL; 195 void *new = NULL;
196 if (p == argp->tmp) { 196 if (p == argp->tmp) {
@@ -1366,7 +1366,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1366 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { 1366 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1367 if ((buflen -= 4) < 0) 1367 if ((buflen -= 4) < 0)
1368 goto out_resource; 1368 goto out_resource;
1369 WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME ); 1369 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
1370 WRITE32(NFS4_FH_VOLATILE_ANY);
1371 else
1372 WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME);
1370 } 1373 }
1371 if (bmval0 & FATTR4_WORD0_CHANGE) { 1374 if (bmval0 & FATTR4_WORD0_CHANGE) {
1372 /* 1375 /*
@@ -1969,7 +1972,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open
1969 case NFS4_OPEN_DELEGATE_READ: 1972 case NFS4_OPEN_DELEGATE_READ:
1970 RESERVE_SPACE(20 + sizeof(stateid_t)); 1973 RESERVE_SPACE(20 + sizeof(stateid_t));
1971 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t)); 1974 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
1972 WRITE32(0); 1975 WRITE32(open->op_recall);
1973 1976
1974 /* 1977 /*
1975 * TODO: ACE's in delegations 1978 * TODO: ACE's in delegations
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 161afdcb8f7d..841c562991e8 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -51,6 +51,7 @@ enum {
51 NFSD_Fh, 51 NFSD_Fh,
52 NFSD_Threads, 52 NFSD_Threads,
53 NFSD_Leasetime, 53 NFSD_Leasetime,
54 NFSD_RecoveryDir,
54}; 55};
55 56
56/* 57/*
@@ -66,6 +67,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size);
66static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 67static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
67static ssize_t write_threads(struct file *file, char *buf, size_t size); 68static ssize_t write_threads(struct file *file, char *buf, size_t size);
68static ssize_t write_leasetime(struct file *file, char *buf, size_t size); 69static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
70static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
69 71
70static ssize_t (*write_op[])(struct file *, char *, size_t) = { 72static ssize_t (*write_op[])(struct file *, char *, size_t) = {
71 [NFSD_Svc] = write_svc, 73 [NFSD_Svc] = write_svc,
@@ -78,6 +80,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
78 [NFSD_Fh] = write_filehandle, 80 [NFSD_Fh] = write_filehandle,
79 [NFSD_Threads] = write_threads, 81 [NFSD_Threads] = write_threads,
80 [NFSD_Leasetime] = write_leasetime, 82 [NFSD_Leasetime] = write_leasetime,
83 [NFSD_RecoveryDir] = write_recoverydir,
81}; 84};
82 85
83static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) 86static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -349,6 +352,25 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
349 return strlen(buf); 352 return strlen(buf);
350} 353}
351 354
355static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
356{
357 char *mesg = buf;
358 char *recdir;
359 int len, status;
360
361 if (size > PATH_MAX || buf[size-1] != '\n')
362 return -EINVAL;
363 buf[size-1] = 0;
364
365 recdir = mesg;
366 len = qword_get(&mesg, recdir, size);
367 if (len <= 0)
368 return -EINVAL;
369
370 status = nfs4_reset_recoverydir(recdir);
371 return strlen(buf);
372}
373
352/*----------------------------------------------------------------------------*/ 374/*----------------------------------------------------------------------------*/
353/* 375/*
354 * populating the filesystem. 376 * populating the filesystem.
@@ -369,6 +391,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
369 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 391 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
370#ifdef CONFIG_NFSD_V4 392#ifdef CONFIG_NFSD_V4
371 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 393 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
394 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
372#endif 395#endif
373 /* last one */ {""} 396 /* last one */ {""}
374 }; 397 };
@@ -397,9 +420,8 @@ static int __init init_nfsd(void)
397 nfsd_cache_init(); /* RPC reply cache */ 420 nfsd_cache_init(); /* RPC reply cache */
398 nfsd_export_init(); /* Exports table */ 421 nfsd_export_init(); /* Exports table */
399 nfsd_lockd_init(); /* lockd->nfsd callbacks */ 422 nfsd_lockd_init(); /* lockd->nfsd callbacks */
400#ifdef CONFIG_NFSD_V4 423 nfs4_state_init(); /* NFSv4 locking state */
401 nfsd_idmap_init(); /* Name to ID mapping */ 424 nfsd_idmap_init(); /* Name to ID mapping */
402#endif /* CONFIG_NFSD_V4 */
403 if (proc_mkdir("fs/nfs", NULL)) { 425 if (proc_mkdir("fs/nfs", NULL)) {
404 struct proc_dir_entry *entry; 426 struct proc_dir_entry *entry;
405 entry = create_proc_entry("fs/nfs/exports", 0, NULL); 427 entry = create_proc_entry("fs/nfs/exports", 0, NULL);
@@ -426,9 +448,7 @@ static void __exit exit_nfsd(void)
426 remove_proc_entry("fs/nfs", NULL); 448 remove_proc_entry("fs/nfs", NULL);
427 nfsd_stat_shutdown(); 449 nfsd_stat_shutdown();
428 nfsd_lockd_shutdown(); 450 nfsd_lockd_shutdown();
429#ifdef CONFIG_NFSD_V4
430 nfsd_idmap_shutdown(); 451 nfsd_idmap_shutdown();
431#endif /* CONFIG_NFSD_V4 */
432 unregister_filesystem(&nfsd_fs_type); 452 unregister_filesystem(&nfsd_fs_type);
433} 453}
434 454
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 757f9d208034..0aa1b9603d7f 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -591,6 +591,7 @@ nfserrno (int errno)
591 { nfserr_dropit, -ENOMEM }, 591 { nfserr_dropit, -ENOMEM },
592 { nfserr_badname, -ESRCH }, 592 { nfserr_badname, -ESRCH },
593 { nfserr_io, -ETXTBSY }, 593 { nfserr_io, -ETXTBSY },
594 { nfserr_notsupp, -EOPNOTSUPP },
594 { -1, -EIO } 595 { -1, -EIO }
595 }; 596 };
596 int i; 597 int i;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 02ded7cfbdcf..07b9a065e9da 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -31,6 +31,7 @@
31#include <linux/nfsd/stats.h> 31#include <linux/nfsd/stats.h>
32#include <linux/nfsd/cache.h> 32#include <linux/nfsd/cache.h>
33#include <linux/lockd/bind.h> 33#include <linux/lockd/bind.h>
34#include <linux/nfsacl.h>
34 35
35#define NFSDDBG_FACILITY NFSDDBG_SVC 36#define NFSDDBG_FACILITY NFSDDBG_SVC
36 37
@@ -94,7 +95,7 @@ nfsd_svc(unsigned short port, int nrservs)
94 error = nfsd_racache_init(2*nrservs); 95 error = nfsd_racache_init(2*nrservs);
95 if (error<0) 96 if (error<0)
96 goto out; 97 goto out;
97 error = nfs4_state_init(); 98 error = nfs4_state_start();
98 if (error<0) 99 if (error<0)
99 goto out; 100 goto out;
100 if (!nfsd_serv) { 101 if (!nfsd_serv) {
@@ -362,6 +363,32 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
362 return 1; 363 return 1;
363} 364}
364 365
366#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
367static struct svc_stat nfsd_acl_svcstats;
368static struct svc_version * nfsd_acl_version[] = {
369 [2] = &nfsd_acl_version2,
370 [3] = &nfsd_acl_version3,
371};
372
373#define NFSD_ACL_NRVERS (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
374static struct svc_program nfsd_acl_program = {
375 .pg_prog = NFS_ACL_PROGRAM,
376 .pg_nvers = NFSD_ACL_NRVERS,
377 .pg_vers = nfsd_acl_version,
378 .pg_name = "nfsd",
379 .pg_class = "nfsd",
380 .pg_stats = &nfsd_acl_svcstats,
381};
382
383static struct svc_stat nfsd_acl_svcstats = {
384 .program = &nfsd_acl_program,
385};
386
387#define nfsd_acl_program_p &nfsd_acl_program
388#else
389#define nfsd_acl_program_p NULL
390#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
391
365extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; 392extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
366 393
367static struct svc_version * nfsd_version[] = { 394static struct svc_version * nfsd_version[] = {
@@ -376,6 +403,7 @@ static struct svc_version * nfsd_version[] = {
376 403
377#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) 404#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0]))
378struct svc_program nfsd_program = { 405struct svc_program nfsd_program = {
406 .pg_next = nfsd_acl_program_p,
379 .pg_prog = NFS_PROGRAM, /* program number */ 407 .pg_prog = NFS_PROGRAM, /* program number */
380 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ 408 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
381 .pg_vers = nfsd_version, /* version table */ 409 .pg_vers = nfsd_version, /* version table */
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 948b08287c99..b45999ff33e6 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -49,6 +49,12 @@ decode_fh(u32 *p, struct svc_fh *fhp)
49 return p + (NFS_FHSIZE >> 2); 49 return p + (NFS_FHSIZE >> 2);
50} 50}
51 51
52/* Helper function for NFSv2 ACL code */
53u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp)
54{
55 return decode_fh(p, fhp);
56}
57
52static inline u32 * 58static inline u32 *
53encode_fh(u32 *p, struct svc_fh *fhp) 59encode_fh(u32 *p, struct svc_fh *fhp)
54{ 60{
@@ -190,6 +196,11 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
190 return p; 196 return p;
191} 197}
192 198
199/* Helper function for NFSv2 ACL code */
200u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
201{
202 return encode_fattr(rqstp, p, fhp);
203}
193 204
194/* 205/*
195 * XDR decode functions 206 * XDR decode functions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index e3e9d217236e..de340ffd33c3 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -46,10 +46,10 @@
46#include <linux/nfsd/nfsfh.h> 46#include <linux/nfsd/nfsfh.h>
47#include <linux/quotaops.h> 47#include <linux/quotaops.h>
48#include <linux/dnotify.h> 48#include <linux/dnotify.h>
49#ifdef CONFIG_NFSD_V4 49#include <linux/xattr_acl.h>
50#include <linux/posix_acl.h> 50#include <linux/posix_acl.h>
51#ifdef CONFIG_NFSD_V4
51#include <linux/posix_acl_xattr.h> 52#include <linux/posix_acl_xattr.h>
52#include <linux/xattr_acl.h>
53#include <linux/xattr.h> 53#include <linux/xattr.h>
54#include <linux/nfs4.h> 54#include <linux/nfs4.h>
55#include <linux/nfs4_acl.h> 55#include <linux/nfs4_acl.h>
@@ -424,13 +424,13 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
424 goto out_nfserr; 424 goto out_nfserr;
425 425
426 if (pacl) { 426 if (pacl) {
427 error = set_nfsv4_acl_one(dentry, pacl, XATTR_NAME_ACL_ACCESS); 427 error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
428 if (error < 0) 428 if (error < 0)
429 goto out_nfserr; 429 goto out_nfserr;
430 } 430 }
431 431
432 if (dpacl) { 432 if (dpacl) {
433 error = set_nfsv4_acl_one(dentry, dpacl, XATTR_NAME_ACL_DEFAULT); 433 error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
434 if (error < 0) 434 if (error < 0)
435 goto out_nfserr; 435 goto out_nfserr;
436 } 436 }
@@ -497,7 +497,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
497 struct posix_acl *pacl = NULL, *dpacl = NULL; 497 struct posix_acl *pacl = NULL, *dpacl = NULL;
498 unsigned int flags = 0; 498 unsigned int flags = 0;
499 499
500 pacl = _get_posix_acl(dentry, XATTR_NAME_ACL_ACCESS); 500 pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
501 if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA) 501 if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
502 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); 502 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
503 if (IS_ERR(pacl)) { 503 if (IS_ERR(pacl)) {
@@ -507,7 +507,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
507 } 507 }
508 508
509 if (S_ISDIR(inode->i_mode)) { 509 if (S_ISDIR(inode->i_mode)) {
510 dpacl = _get_posix_acl(dentry, XATTR_NAME_ACL_DEFAULT); 510 dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
511 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA) 511 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
512 dpacl = NULL; 512 dpacl = NULL;
513 else if (IS_ERR(dpacl)) { 513 else if (IS_ERR(dpacl)) {
@@ -1857,3 +1857,107 @@ nfsd_racache_init(int cache_size)
1857 nfsdstats.ra_size = cache_size; 1857 nfsdstats.ra_size = cache_size;
1858 return 0; 1858 return 0;
1859} 1859}
1860
1861#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
1862struct posix_acl *
1863nfsd_get_posix_acl(struct svc_fh *fhp, int type)
1864{
1865 struct inode *inode = fhp->fh_dentry->d_inode;
1866 char *name;
1867 void *value = NULL;
1868 ssize_t size;
1869 struct posix_acl *acl;
1870
1871 if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
1872 return ERR_PTR(-EOPNOTSUPP);
1873 switch(type) {
1874 case ACL_TYPE_ACCESS:
1875 name = XATTR_NAME_ACL_ACCESS;
1876 break;
1877 case ACL_TYPE_DEFAULT:
1878 name = XATTR_NAME_ACL_DEFAULT;
1879 break;
1880 default:
1881 return ERR_PTR(-EOPNOTSUPP);
1882 }
1883
1884 size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
1885
1886 if (size < 0) {
1887 acl = ERR_PTR(size);
1888 goto getout;
1889 } else if (size > 0) {
1890 value = kmalloc(size, GFP_KERNEL);
1891 if (!value) {
1892 acl = ERR_PTR(-ENOMEM);
1893 goto getout;
1894 }
1895 size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
1896 if (size < 0) {
1897 acl = ERR_PTR(size);
1898 goto getout;
1899 }
1900 }
1901 acl = posix_acl_from_xattr(value, size);
1902
1903getout:
1904 kfree(value);
1905 return acl;
1906}
1907
1908int
1909nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1910{
1911 struct inode *inode = fhp->fh_dentry->d_inode;
1912 char *name;
1913 void *value = NULL;
1914 size_t size;
1915 int error;
1916
1917 if (!IS_POSIXACL(inode) || !inode->i_op ||
1918 !inode->i_op->setxattr || !inode->i_op->removexattr)
1919 return -EOPNOTSUPP;
1920 switch(type) {
1921 case ACL_TYPE_ACCESS:
1922 name = XATTR_NAME_ACL_ACCESS;
1923 break;
1924 case ACL_TYPE_DEFAULT:
1925 name = XATTR_NAME_ACL_DEFAULT;
1926 break;
1927 default:
1928 return -EOPNOTSUPP;
1929 }
1930
1931 if (acl && acl->a_count) {
1932 size = xattr_acl_size(acl->a_count);
1933 value = kmalloc(size, GFP_KERNEL);
1934 if (!value)
1935 return -ENOMEM;
1936 size = posix_acl_to_xattr(acl, value, size);
1937 if (size < 0) {
1938 error = size;
1939 goto getout;
1940 }
1941 } else
1942 size = 0;
1943
1944 if (!fhp->fh_locked)
1945 fh_lock(fhp); /* unlocking is done automatically */
1946 if (size)
1947 error = inode->i_op->setxattr(fhp->fh_dentry, name,
1948 value, size, 0);
1949 else {
1950 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1951 error = 0;
1952 else {
1953 error = inode->i_op->removexattr(fhp->fh_dentry, name);
1954 if (error == -ENODATA)
1955 error = 0;
1956 }
1957 }
1958
1959getout:
1960 kfree(value);
1961 return error;
1962}
1963#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
diff --git a/fs/open.c b/fs/open.c
index 963bd81a44c8..3f4a4286fdc4 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -21,6 +21,7 @@
21#include <linux/vfs.h> 21#include <linux/vfs.h>
22#include <asm/uaccess.h> 22#include <asm/uaccess.h>
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/personality.h>
24#include <linux/pagemap.h> 25#include <linux/pagemap.h>
25#include <linux/syscalls.h> 26#include <linux/syscalls.h>
26 27
@@ -807,7 +808,9 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
807 808
808 /* NB: we're sure to have correct a_ops only after f_op->open */ 809 /* NB: we're sure to have correct a_ops only after f_op->open */
809 if (f->f_flags & O_DIRECT) { 810 if (f->f_flags & O_DIRECT) {
810 if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO) { 811 if (!f->f_mapping->a_ops ||
812 ((!f->f_mapping->a_ops->direct_IO) &&
813 (!f->f_mapping->a_ops->get_xip_page))) {
811 fput(f); 814 fput(f);
812 f = ERR_PTR(-EINVAL); 815 f = ERR_PTR(-EINVAL);
813 } 816 }
@@ -933,31 +936,27 @@ EXPORT_SYMBOL(fd_install);
933asmlinkage long sys_open(const char __user * filename, int flags, int mode) 936asmlinkage long sys_open(const char __user * filename, int flags, int mode)
934{ 937{
935 char * tmp; 938 char * tmp;
936 int fd, error; 939 int fd;
940
941 if (force_o_largefile())
942 flags |= O_LARGEFILE;
937 943
938#if BITS_PER_LONG != 32
939 flags |= O_LARGEFILE;
940#endif
941 tmp = getname(filename); 944 tmp = getname(filename);
942 fd = PTR_ERR(tmp); 945 fd = PTR_ERR(tmp);
943 if (!IS_ERR(tmp)) { 946 if (!IS_ERR(tmp)) {
944 fd = get_unused_fd(); 947 fd = get_unused_fd();
945 if (fd >= 0) { 948 if (fd >= 0) {
946 struct file *f = filp_open(tmp, flags, mode); 949 struct file *f = filp_open(tmp, flags, mode);
947 error = PTR_ERR(f); 950 if (IS_ERR(f)) {
948 if (IS_ERR(f)) 951 put_unused_fd(fd);
949 goto out_error; 952 fd = PTR_ERR(f);
950 fd_install(fd, f); 953 } else {
954 fd_install(fd, f);
955 }
951 } 956 }
952out:
953 putname(tmp); 957 putname(tmp);
954 } 958 }
955 return fd; 959 return fd;
956
957out_error:
958 put_unused_fd(fd);
959 fd = error;
960 goto out;
961} 960}
962EXPORT_SYMBOL_GPL(sys_open); 961EXPORT_SYMBOL_GPL(sys_open);
963 962
@@ -980,23 +979,15 @@ asmlinkage long sys_creat(const char __user * pathname, int mode)
980 */ 979 */
981int filp_close(struct file *filp, fl_owner_t id) 980int filp_close(struct file *filp, fl_owner_t id)
982{ 981{
983 int retval; 982 int retval = 0;
984
985 /* Report and clear outstanding errors */
986 retval = filp->f_error;
987 if (retval)
988 filp->f_error = 0;
989 983
990 if (!file_count(filp)) { 984 if (!file_count(filp)) {
991 printk(KERN_ERR "VFS: Close: file count is 0\n"); 985 printk(KERN_ERR "VFS: Close: file count is 0\n");
992 return retval; 986 return 0;
993 } 987 }
994 988
995 if (filp->f_op && filp->f_op->flush) { 989 if (filp->f_op && filp->f_op->flush)
996 int err = filp->f_op->flush(filp); 990 retval = filp->f_op->flush(filp);
997 if (!retval)
998 retval = err;
999 }
1000 991
1001 dnotify_flush(filp, id); 992 dnotify_flush(filp, id);
1002 locks_remove_posix(filp, id); 993 locks_remove_posix(filp, id);
diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile
index 4c83c17969e1..66d5cc26fafb 100644
--- a/fs/partitions/Makefile
+++ b/fs/partitions/Makefile
@@ -17,4 +17,3 @@ obj-$(CONFIG_SUN_PARTITION) += sun.o
17obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o 17obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
18obj-$(CONFIG_IBM_PARTITION) += ibm.o 18obj-$(CONFIG_IBM_PARTITION) += ibm.o
19obj-$(CONFIG_EFI_PARTITION) += efi.o 19obj-$(CONFIG_EFI_PARTITION) += efi.o
20obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 2cab98a9a621..77e178f13162 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -79,9 +79,6 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) =
79#ifdef CONFIG_LDM_PARTITION 79#ifdef CONFIG_LDM_PARTITION
80 ldm_partition, /* this must come before msdos */ 80 ldm_partition, /* this must come before msdos */
81#endif 81#endif
82#ifdef CONFIG_NEC98_PARTITION
83 nec98_partition, /* must be come before `msdos_partition' */
84#endif
85#ifdef CONFIG_MSDOS_PARTITION 82#ifdef CONFIG_MSDOS_PARTITION
86 msdos_partition, 83 msdos_partition,
87#endif 84#endif
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index 43adcc68e471..17ae8ecd9e8b 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -30,7 +30,3 @@ put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
30 30
31extern int warn_no_part; 31extern int warn_no_part;
32 32
33extern void parse_bsd(struct parsed_partitions *state,
34 struct block_device *bdev, u32 offset, u32 size,
35 int origin, char *flavour, int max_partitions);
36
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 584a27b2bbd5..9935d254186e 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -202,12 +202,12 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
202#endif 202#endif
203} 203}
204 204
205#if defined(CONFIG_BSD_DISKLABEL) || defined(CONFIG_NEC98_PARTITION) 205#if defined(CONFIG_BSD_DISKLABEL)
206/* 206/*
207 * Create devices for BSD partitions listed in a disklabel, under a 207 * Create devices for BSD partitions listed in a disklabel, under a
208 * dos-like partition. See parse_extended() for more information. 208 * dos-like partition. See parse_extended() for more information.
209 */ 209 */
210void 210static void
211parse_bsd(struct parsed_partitions *state, struct block_device *bdev, 211parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
212 u32 offset, u32 size, int origin, char *flavour, 212 u32 offset, u32 size, int origin, char *flavour,
213 int max_partitions) 213 int max_partitions)
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 738b9b602932..7431d7ba2d09 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -11,4 +11,5 @@ proc-y += inode.o root.o base.o generic.o array.o \
11 kmsg.o proc_tty.o proc_misc.o 11 kmsg.o proc_tty.o proc_misc.o
12 12
13proc-$(CONFIG_PROC_KCORE) += kcore.o 13proc-$(CONFIG_PROC_KCORE) += kcore.o
14proc-$(CONFIG_PROC_VMCORE) += vmcore.o
14proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o 15proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e31903aadd96..ace151fa4878 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -314,7 +314,7 @@ static int may_ptrace_attach(struct task_struct *task)
314 (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) 314 (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
315 goto out; 315 goto out;
316 rmb(); 316 rmb();
317 if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) 317 if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
318 goto out; 318 goto out;
319 if (security_ptrace(current, task)) 319 if (security_ptrace(current, task))
320 goto out; 320 goto out;
@@ -1113,7 +1113,9 @@ static int task_dumpable(struct task_struct *task)
1113 if (mm) 1113 if (mm)
1114 dumpable = mm->dumpable; 1114 dumpable = mm->dumpable;
1115 task_unlock(task); 1115 task_unlock(task);
1116 return dumpable; 1116 if(dumpable == 1)
1117 return 1;
1118 return 0;
1117} 1119}
1118 1120
1119 1121
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 67423c696c0a..6fd57f154197 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -12,15 +12,8 @@
12#include <asm/uaccess.h> 12#include <asm/uaccess.h>
13 13
14#ifndef HAVE_ARCH_DEVTREE_FIXUPS 14#ifndef HAVE_ARCH_DEVTREE_FIXUPS
15static inline void set_node_proc_entry(struct device_node *np, struct proc_dir_entry *de) 15static inline void set_node_proc_entry(struct device_node *np,
16{ 16 struct proc_dir_entry *de)
17}
18
19static void inline set_node_name_link(struct device_node *np, struct proc_dir_entry *de)
20{
21}
22
23static void inline set_node_addr_link(struct device_node *np, struct proc_dir_entry *de)
24{ 17{
25} 18}
26#endif 19#endif
@@ -58,89 +51,67 @@ static int property_read_proc(char *page, char **start, off_t off,
58/* 51/*
59 * Process a node, adding entries for its children and its properties. 52 * Process a node, adding entries for its children and its properties.
60 */ 53 */
61void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *de) 54void proc_device_tree_add_node(struct device_node *np,
55 struct proc_dir_entry *de)
62{ 56{
63 struct property *pp; 57 struct property *pp;
64 struct proc_dir_entry *ent; 58 struct proc_dir_entry *ent;
65 struct device_node *child, *sib; 59 struct device_node *child;
66 const char *p, *at; 60 struct proc_dir_entry *list = NULL, **lastp;
67 int l; 61 const char *p;
68 struct proc_dir_entry *list, **lastp, *al;
69 62
70 set_node_proc_entry(np, de); 63 set_node_proc_entry(np, de);
71 lastp = &list; 64 lastp = &list;
72 for (pp = np->properties; pp != 0; pp = pp->next) { 65 for (child = NULL; (child = of_get_next_child(np, child));) {
73 /*
74 * Unfortunately proc_register puts each new entry
75 * at the beginning of the list. So we rearrange them.
76 */
77 ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ?
78 S_IRUGO : S_IRUSR, de, property_read_proc, pp);
79 if (ent == 0)
80 break;
81 if (!strncmp(pp->name, "security-", 9))
82 ent->size = 0; /* don't leak number of password chars */
83 else
84 ent->size = pp->length;
85 *lastp = ent;
86 lastp = &ent->next;
87 }
88 child = NULL;
89 while ((child = of_get_next_child(np, child))) {
90 p = strrchr(child->full_name, '/'); 66 p = strrchr(child->full_name, '/');
91 if (!p) 67 if (!p)
92 p = child->full_name; 68 p = child->full_name;
93 else 69 else
94 ++p; 70 ++p;
95 /* chop off '@0' if the name ends with that */
96 l = strlen(p);
97 if (l > 2 && p[l-2] == '@' && p[l-1] == '0')
98 l -= 2;
99 ent = proc_mkdir(p, de); 71 ent = proc_mkdir(p, de);
100 if (ent == 0) 72 if (ent == 0)
101 break; 73 break;
102 *lastp = ent; 74 *lastp = ent;
75 ent->next = NULL;
103 lastp = &ent->next; 76 lastp = &ent->next;
104 proc_device_tree_add_node(child, ent); 77 proc_device_tree_add_node(child, ent);
105 78 }
106 /* 79 of_node_put(child);
107 * If we left the address part on the name, consider 80 for (pp = np->properties; pp != 0; pp = pp->next) {
108 * adding symlinks from the name and address parts.
109 */
110 if (p[l] != 0 || (at = strchr(p, '@')) == 0)
111 continue;
112
113 /* 81 /*
114 * If this is the first node with a given name property, 82 * Yet another Apple device-tree bogosity: on some machines,
115 * add a symlink with the name property as its name. 83 * they have properties & nodes with the same name. Those
84 * properties are quite unimportant for us though, thus we
85 * simply "skip" them here, but we do have to check.
116 */ 86 */
117 sib = NULL; 87 for (ent = list; ent != NULL; ent = ent->next)
118 while ((sib = of_get_next_child(np, sib)) && sib != child) 88 if (!strcmp(ent->name, pp->name))
119 if (sib->name && strcmp(sib->name, child->name) == 0)
120 break;
121 if (sib == child && strncmp(p, child->name, l) != 0) {
122 al = proc_symlink(child->name, de, ent->name);
123 if (al == 0) {
124 of_node_put(sib);
125 break; 89 break;
126 } 90 if (ent != NULL) {
127 set_node_name_link(child, al); 91 printk(KERN_WARNING "device-tree: property \"%s\" name"
128 *lastp = al; 92 " conflicts with node in %s\n", pp->name,
129 lastp = &al->next; 93 np->full_name);
94 continue;
130 } 95 }
131 of_node_put(sib); 96
132 /* 97 /*
133 * Add another directory with the @address part as its name. 98 * Unfortunately proc_register puts each new entry
99 * at the beginning of the list. So we rearrange them.
134 */ 100 */
135 al = proc_symlink(at, de, ent->name); 101 ent = create_proc_read_entry(pp->name,
136 if (al == 0) 102 strncmp(pp->name, "security-", 9)
103 ? S_IRUGO : S_IRUSR, de,
104 property_read_proc, pp);
105 if (ent == 0)
137 break; 106 break;
138 set_node_addr_link(child, al); 107 if (!strncmp(pp->name, "security-", 9))
139 *lastp = al; 108 ent->size = 0; /* don't leak number of password chars */
140 lastp = &al->next; 109 else
110 ent->size = pp->length;
111 ent->next = NULL;
112 *lastp = ent;
113 lastp = &ent->next;
141 } 114 }
142 of_node_put(child);
143 *lastp = NULL;
144 de->subdir = list; 115 de->subdir = list;
145} 116}
146 117
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index a60a3b3d8a7b..a3453555a94e 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -44,6 +44,7 @@
44#include <linux/jiffies.h> 44#include <linux/jiffies.h>
45#include <linux/sysrq.h> 45#include <linux/sysrq.h>
46#include <linux/vmalloc.h> 46#include <linux/vmalloc.h>
47#include <linux/crash_dump.h>
47#include <asm/uaccess.h> 48#include <asm/uaccess.h>
48#include <asm/pgtable.h> 49#include <asm/pgtable.h>
49#include <asm/io.h> 50#include <asm/io.h>
@@ -219,6 +220,19 @@ static struct file_operations fragmentation_file_operations = {
219 .release = seq_release, 220 .release = seq_release,
220}; 221};
221 222
223extern struct seq_operations zoneinfo_op;
224static int zoneinfo_open(struct inode *inode, struct file *file)
225{
226 return seq_open(file, &zoneinfo_op);
227}
228
229static struct file_operations proc_zoneinfo_file_operations = {
230 .open = zoneinfo_open,
231 .read = seq_read,
232 .llseek = seq_lseek,
233 .release = seq_release,
234};
235
222static int version_read_proc(char *page, char **start, off_t off, 236static int version_read_proc(char *page, char **start, off_t off,
223 int count, int *eof, void *data) 237 int count, int *eof, void *data)
224{ 238{
@@ -438,7 +452,7 @@ static int devices_read_proc(char *page, char **start, off_t off,
438 int count, int *eof, void *data) 452 int count, int *eof, void *data)
439{ 453{
440 int len = get_chrdev_list(page); 454 int len = get_chrdev_list(page);
441 len += get_blkdev_list(page+len); 455 len += get_blkdev_list(page+len, len);
442 return proc_calc_metrics(page, start, off, count, eof, len); 456 return proc_calc_metrics(page, start, off, count, eof, len);
443} 457}
444 458
@@ -589,6 +603,7 @@ void __init proc_misc_init(void)
589 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); 603 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
590 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); 604 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
591 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); 605 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
606 create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
592 create_seq_entry("diskstats", 0, &proc_diskstats_operations); 607 create_seq_entry("diskstats", 0, &proc_diskstats_operations);
593#ifdef CONFIG_MODULES 608#ifdef CONFIG_MODULES
594 create_seq_entry("modules", 0, &proc_modules_operations); 609 create_seq_entry("modules", 0, &proc_modules_operations);
@@ -604,6 +619,11 @@ void __init proc_misc_init(void)
604 (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE; 619 (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
605 } 620 }
606#endif 621#endif
622#ifdef CONFIG_PROC_VMCORE
623 proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
624 if (proc_vmcore)
625 proc_vmcore->proc_fops = &proc_vmcore_operations;
626#endif
607#ifdef CONFIG_MAGIC_SYSRQ 627#ifdef CONFIG_MAGIC_SYSRQ
608 entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL); 628 entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
609 if (entry) 629 if (entry)
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
new file mode 100644
index 000000000000..3b2e7b69e63a
--- /dev/null
+++ b/fs/proc/vmcore.c
@@ -0,0 +1,669 @@
1/*
2 * fs/proc/vmcore.c Interface for accessing the crash
3 * dump from the system's previous life.
4 * Heavily borrowed from fs/proc/kcore.c
5 * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
6 * Copyright (C) IBM Corporation, 2004. All rights reserved
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/mm.h>
12#include <linux/proc_fs.h>
13#include <linux/user.h>
14#include <linux/a.out.h>
15#include <linux/elf.h>
16#include <linux/elfcore.h>
17#include <linux/proc_fs.h>
18#include <linux/highmem.h>
19#include <linux/bootmem.h>
20#include <linux/init.h>
21#include <linux/crash_dump.h>
22#include <linux/list.h>
23#include <asm/uaccess.h>
24#include <asm/io.h>
25
26/* List representing chunks of contiguous memory areas and their offsets in
27 * vmcore file.
28 */
29static LIST_HEAD(vmcore_list);
30
31/* Stores the pointer to the buffer containing kernel elf core headers. */
32static char *elfcorebuf;
33static size_t elfcorebuf_sz;
34
35/* Total size of vmcore file. */
36static u64 vmcore_size;
37
38struct proc_dir_entry *proc_vmcore = NULL;
39
40/* Reads a page from the oldmem device from given offset. */
41static ssize_t read_from_oldmem(char *buf, size_t count,
42 loff_t *ppos, int userbuf)
43{
44 unsigned long pfn, offset;
45 size_t nr_bytes;
46 ssize_t read = 0, tmp;
47
48 if (!count)
49 return 0;
50
51 offset = (unsigned long)(*ppos % PAGE_SIZE);
52 pfn = (unsigned long)(*ppos / PAGE_SIZE);
53 if (pfn > saved_max_pfn)
54 return -EINVAL;
55
56 do {
57 if (count > (PAGE_SIZE - offset))
58 nr_bytes = PAGE_SIZE - offset;
59 else
60 nr_bytes = count;
61
62 tmp = copy_oldmem_page(pfn, buf, nr_bytes, offset, userbuf);
63 if (tmp < 0)
64 return tmp;
65 *ppos += nr_bytes;
66 count -= nr_bytes;
67 buf += nr_bytes;
68 read += nr_bytes;
69 ++pfn;
70 offset = 0;
71 } while (count);
72
73 return read;
74}
75
76/* Maps vmcore file offset to respective physical address in memroy. */
77static u64 map_offset_to_paddr(loff_t offset, struct list_head *vc_list,
78 struct vmcore **m_ptr)
79{
80 struct vmcore *m;
81 u64 paddr;
82
83 list_for_each_entry(m, vc_list, list) {
84 u64 start, end;
85 start = m->offset;
86 end = m->offset + m->size - 1;
87 if (offset >= start && offset <= end) {
88 paddr = m->paddr + offset - start;
89 *m_ptr = m;
90 return paddr;
91 }
92 }
93 *m_ptr = NULL;
94 return 0;
95}
96
97/* Read from the ELF header and then the crash dump. On error, negative value is
98 * returned otherwise number of bytes read are returned.
99 */
100static ssize_t read_vmcore(struct file *file, char __user *buffer,
101 size_t buflen, loff_t *fpos)
102{
103 ssize_t acc = 0, tmp;
104 size_t tsz, nr_bytes;
105 u64 start;
106 struct vmcore *curr_m = NULL;
107
108 if (buflen == 0 || *fpos >= vmcore_size)
109 return 0;
110
111 /* trim buflen to not go beyond EOF */
112 if (buflen > vmcore_size - *fpos)
113 buflen = vmcore_size - *fpos;
114
115 /* Read ELF core header */
116 if (*fpos < elfcorebuf_sz) {
117 tsz = elfcorebuf_sz - *fpos;
118 if (buflen < tsz)
119 tsz = buflen;
120 if (copy_to_user(buffer, elfcorebuf + *fpos, tsz))
121 return -EFAULT;
122 buflen -= tsz;
123 *fpos += tsz;
124 buffer += tsz;
125 acc += tsz;
126
127 /* leave now if filled buffer already */
128 if (buflen == 0)
129 return acc;
130 }
131
132 start = map_offset_to_paddr(*fpos, &vmcore_list, &curr_m);
133 if (!curr_m)
134 return -EINVAL;
135 if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
136 tsz = buflen;
137
138 /* Calculate left bytes in current memory segment. */
139 nr_bytes = (curr_m->size - (start - curr_m->paddr));
140 if (tsz > nr_bytes)
141 tsz = nr_bytes;
142
143 while (buflen) {
144 tmp = read_from_oldmem(buffer, tsz, &start, 1);
145 if (tmp < 0)
146 return tmp;
147 buflen -= tsz;
148 *fpos += tsz;
149 buffer += tsz;
150 acc += tsz;
151 if (start >= (curr_m->paddr + curr_m->size)) {
152 if (curr_m->list.next == &vmcore_list)
153 return acc; /*EOF*/
154 curr_m = list_entry(curr_m->list.next,
155 struct vmcore, list);
156 start = curr_m->paddr;
157 }
158 if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
159 tsz = buflen;
160 /* Calculate left bytes in current memory segment. */
161 nr_bytes = (curr_m->size - (start - curr_m->paddr));
162 if (tsz > nr_bytes)
163 tsz = nr_bytes;
164 }
165 return acc;
166}
167
168static int open_vmcore(struct inode *inode, struct file *filp)
169{
170 return 0;
171}
172
173struct file_operations proc_vmcore_operations = {
174 .read = read_vmcore,
175 .open = open_vmcore,
176};
177
178static struct vmcore* __init get_new_element(void)
179{
180 struct vmcore *p;
181
182 p = kmalloc(sizeof(*p), GFP_KERNEL);
183 if (p)
184 memset(p, 0, sizeof(*p));
185 return p;
186}
187
188static u64 __init get_vmcore_size_elf64(char *elfptr)
189{
190 int i;
191 u64 size;
192 Elf64_Ehdr *ehdr_ptr;
193 Elf64_Phdr *phdr_ptr;
194
195 ehdr_ptr = (Elf64_Ehdr *)elfptr;
196 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
197 size = sizeof(Elf64_Ehdr) + ((ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr));
198 for (i = 0; i < ehdr_ptr->e_phnum; i++) {
199 size += phdr_ptr->p_memsz;
200 phdr_ptr++;
201 }
202 return size;
203}
204
205static u64 __init get_vmcore_size_elf32(char *elfptr)
206{
207 int i;
208 u64 size;
209 Elf32_Ehdr *ehdr_ptr;
210 Elf32_Phdr *phdr_ptr;
211
212 ehdr_ptr = (Elf32_Ehdr *)elfptr;
213 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
214 size = sizeof(Elf32_Ehdr) + ((ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr));
215 for (i = 0; i < ehdr_ptr->e_phnum; i++) {
216 size += phdr_ptr->p_memsz;
217 phdr_ptr++;
218 }
219 return size;
220}
221
222/* Merges all the PT_NOTE headers into one. */
223static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
224 struct list_head *vc_list)
225{
226 int i, nr_ptnote=0, rc=0;
227 char *tmp;
228 Elf64_Ehdr *ehdr_ptr;
229 Elf64_Phdr phdr, *phdr_ptr;
230 Elf64_Nhdr *nhdr_ptr;
231 u64 phdr_sz = 0, note_off;
232
233 ehdr_ptr = (Elf64_Ehdr *)elfptr;
234 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
235 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
236 int j;
237 void *notes_section;
238 struct vmcore *new;
239 u64 offset, max_sz, sz, real_sz = 0;
240 if (phdr_ptr->p_type != PT_NOTE)
241 continue;
242 nr_ptnote++;
243 max_sz = phdr_ptr->p_memsz;
244 offset = phdr_ptr->p_offset;
245 notes_section = kmalloc(max_sz, GFP_KERNEL);
246 if (!notes_section)
247 return -ENOMEM;
248 rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
249 if (rc < 0) {
250 kfree(notes_section);
251 return rc;
252 }
253 nhdr_ptr = notes_section;
254 for (j = 0; j < max_sz; j += sz) {
255 if (nhdr_ptr->n_namesz == 0)
256 break;
257 sz = sizeof(Elf64_Nhdr) +
258 ((nhdr_ptr->n_namesz + 3) & ~3) +
259 ((nhdr_ptr->n_descsz + 3) & ~3);
260 real_sz += sz;
261 nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
262 }
263
264 /* Add this contiguous chunk of notes section to vmcore list.*/
265 new = get_new_element();
266 if (!new) {
267 kfree(notes_section);
268 return -ENOMEM;
269 }
270 new->paddr = phdr_ptr->p_offset;
271 new->size = real_sz;
272 list_add_tail(&new->list, vc_list);
273 phdr_sz += real_sz;
274 kfree(notes_section);
275 }
276
277 /* Prepare merged PT_NOTE program header. */
278 phdr.p_type = PT_NOTE;
279 phdr.p_flags = 0;
280 note_off = sizeof(Elf64_Ehdr) +
281 (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf64_Phdr);
282 phdr.p_offset = note_off;
283 phdr.p_vaddr = phdr.p_paddr = 0;
284 phdr.p_filesz = phdr.p_memsz = phdr_sz;
285 phdr.p_align = 0;
286
287 /* Add merged PT_NOTE program header*/
288 tmp = elfptr + sizeof(Elf64_Ehdr);
289 memcpy(tmp, &phdr, sizeof(phdr));
290 tmp += sizeof(phdr);
291
292 /* Remove unwanted PT_NOTE program headers. */
293 i = (nr_ptnote - 1) * sizeof(Elf64_Phdr);
294 *elfsz = *elfsz - i;
295 memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf64_Ehdr)-sizeof(Elf64_Phdr)));
296
297 /* Modify e_phnum to reflect merged headers. */
298 ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
299
300 return 0;
301}
302
303/* Merges all the PT_NOTE headers into one. */
304static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
305 struct list_head *vc_list)
306{
307 int i, nr_ptnote=0, rc=0;
308 char *tmp;
309 Elf32_Ehdr *ehdr_ptr;
310 Elf32_Phdr phdr, *phdr_ptr;
311 Elf32_Nhdr *nhdr_ptr;
312 u64 phdr_sz = 0, note_off;
313
314 ehdr_ptr = (Elf32_Ehdr *)elfptr;
315 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
316 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
317 int j;
318 void *notes_section;
319 struct vmcore *new;
320 u64 offset, max_sz, sz, real_sz = 0;
321 if (phdr_ptr->p_type != PT_NOTE)
322 continue;
323 nr_ptnote++;
324 max_sz = phdr_ptr->p_memsz;
325 offset = phdr_ptr->p_offset;
326 notes_section = kmalloc(max_sz, GFP_KERNEL);
327 if (!notes_section)
328 return -ENOMEM;
329 rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
330 if (rc < 0) {
331 kfree(notes_section);
332 return rc;
333 }
334 nhdr_ptr = notes_section;
335 for (j = 0; j < max_sz; j += sz) {
336 if (nhdr_ptr->n_namesz == 0)
337 break;
338 sz = sizeof(Elf32_Nhdr) +
339 ((nhdr_ptr->n_namesz + 3) & ~3) +
340 ((nhdr_ptr->n_descsz + 3) & ~3);
341 real_sz += sz;
342 nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
343 }
344
345 /* Add this contiguous chunk of notes section to vmcore list.*/
346 new = get_new_element();
347 if (!new) {
348 kfree(notes_section);
349 return -ENOMEM;
350 }
351 new->paddr = phdr_ptr->p_offset;
352 new->size = real_sz;
353 list_add_tail(&new->list, vc_list);
354 phdr_sz += real_sz;
355 kfree(notes_section);
356 }
357
358 /* Prepare merged PT_NOTE program header. */
359 phdr.p_type = PT_NOTE;
360 phdr.p_flags = 0;
361 note_off = sizeof(Elf32_Ehdr) +
362 (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf32_Phdr);
363 phdr.p_offset = note_off;
364 phdr.p_vaddr = phdr.p_paddr = 0;
365 phdr.p_filesz = phdr.p_memsz = phdr_sz;
366 phdr.p_align = 0;
367
368 /* Add merged PT_NOTE program header*/
369 tmp = elfptr + sizeof(Elf32_Ehdr);
370 memcpy(tmp, &phdr, sizeof(phdr));
371 tmp += sizeof(phdr);
372
373 /* Remove unwanted PT_NOTE program headers. */
374 i = (nr_ptnote - 1) * sizeof(Elf32_Phdr);
375 *elfsz = *elfsz - i;
376 memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf32_Ehdr)-sizeof(Elf32_Phdr)));
377
378 /* Modify e_phnum to reflect merged headers. */
379 ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
380
381 return 0;
382}
383
384/* Add memory chunks represented by program headers to vmcore list. Also update
385 * the new offset fields of exported program headers. */
386static int __init process_ptload_program_headers_elf64(char *elfptr,
387 size_t elfsz,
388 struct list_head *vc_list)
389{
390 int i;
391 Elf64_Ehdr *ehdr_ptr;
392 Elf64_Phdr *phdr_ptr;
393 loff_t vmcore_off;
394 struct vmcore *new;
395
396 ehdr_ptr = (Elf64_Ehdr *)elfptr;
397 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */
398
399 /* First program header is PT_NOTE header. */
400 vmcore_off = sizeof(Elf64_Ehdr) +
401 (ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr) +
402 phdr_ptr->p_memsz; /* Note sections */
403
404 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
405 if (phdr_ptr->p_type != PT_LOAD)
406 continue;
407
408 /* Add this contiguous chunk of memory to vmcore list.*/
409 new = get_new_element();
410 if (!new)
411 return -ENOMEM;
412 new->paddr = phdr_ptr->p_offset;
413 new->size = phdr_ptr->p_memsz;
414 list_add_tail(&new->list, vc_list);
415
416 /* Update the program header offset. */
417 phdr_ptr->p_offset = vmcore_off;
418 vmcore_off = vmcore_off + phdr_ptr->p_memsz;
419 }
420 return 0;
421}
422
423static int __init process_ptload_program_headers_elf32(char *elfptr,
424 size_t elfsz,
425 struct list_head *vc_list)
426{
427 int i;
428 Elf32_Ehdr *ehdr_ptr;
429 Elf32_Phdr *phdr_ptr;
430 loff_t vmcore_off;
431 struct vmcore *new;
432
433 ehdr_ptr = (Elf32_Ehdr *)elfptr;
434 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */
435
436 /* First program header is PT_NOTE header. */
437 vmcore_off = sizeof(Elf32_Ehdr) +
438 (ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr) +
439 phdr_ptr->p_memsz; /* Note sections */
440
441 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
442 if (phdr_ptr->p_type != PT_LOAD)
443 continue;
444
445 /* Add this contiguous chunk of memory to vmcore list.*/
446 new = get_new_element();
447 if (!new)
448 return -ENOMEM;
449 new->paddr = phdr_ptr->p_offset;
450 new->size = phdr_ptr->p_memsz;
451 list_add_tail(&new->list, vc_list);
452
453 /* Update the program header offset */
454 phdr_ptr->p_offset = vmcore_off;
455 vmcore_off = vmcore_off + phdr_ptr->p_memsz;
456 }
457 return 0;
458}
459
460/* Sets offset fields of vmcore elements. */
461static void __init set_vmcore_list_offsets_elf64(char *elfptr,
462 struct list_head *vc_list)
463{
464 loff_t vmcore_off;
465 Elf64_Ehdr *ehdr_ptr;
466 struct vmcore *m;
467
468 ehdr_ptr = (Elf64_Ehdr *)elfptr;
469
470 /* Skip Elf header and program headers. */
471 vmcore_off = sizeof(Elf64_Ehdr) +
472 (ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr);
473
474 list_for_each_entry(m, vc_list, list) {
475 m->offset = vmcore_off;
476 vmcore_off += m->size;
477 }
478}
479
480/* Sets offset fields of vmcore elements. */
481static void __init set_vmcore_list_offsets_elf32(char *elfptr,
482 struct list_head *vc_list)
483{
484 loff_t vmcore_off;
485 Elf32_Ehdr *ehdr_ptr;
486 struct vmcore *m;
487
488 ehdr_ptr = (Elf32_Ehdr *)elfptr;
489
490 /* Skip Elf header and program headers. */
491 vmcore_off = sizeof(Elf32_Ehdr) +
492 (ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr);
493
494 list_for_each_entry(m, vc_list, list) {
495 m->offset = vmcore_off;
496 vmcore_off += m->size;
497 }
498}
499
500static int __init parse_crash_elf64_headers(void)
501{
502 int rc=0;
503 Elf64_Ehdr ehdr;
504 u64 addr;
505
506 addr = elfcorehdr_addr;
507
508 /* Read Elf header */
509 rc = read_from_oldmem((char*)&ehdr, sizeof(Elf64_Ehdr), &addr, 0);
510 if (rc < 0)
511 return rc;
512
513 /* Do some basic Verification. */
514 if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
515 (ehdr.e_type != ET_CORE) ||
516 !elf_check_arch(&ehdr) ||
517 ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
518 ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
519 ehdr.e_version != EV_CURRENT ||
520 ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
521 ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
522 ehdr.e_phnum == 0) {
523 printk(KERN_WARNING "Warning: Core image elf header is not"
524 "sane\n");
525 return -EINVAL;
526 }
527
528 /* Read in all elf headers. */
529 elfcorebuf_sz = sizeof(Elf64_Ehdr) + ehdr.e_phnum * sizeof(Elf64_Phdr);
530 elfcorebuf = kmalloc(elfcorebuf_sz, GFP_KERNEL);
531 if (!elfcorebuf)
532 return -ENOMEM;
533 addr = elfcorehdr_addr;
534 rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz, &addr, 0);
535 if (rc < 0) {
536 kfree(elfcorebuf);
537 return rc;
538 }
539
540 /* Merge all PT_NOTE headers into one. */
541 rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz, &vmcore_list);
542 if (rc) {
543 kfree(elfcorebuf);
544 return rc;
545 }
546 rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz,
547 &vmcore_list);
548 if (rc) {
549 kfree(elfcorebuf);
550 return rc;
551 }
552 set_vmcore_list_offsets_elf64(elfcorebuf, &vmcore_list);
553 return 0;
554}
555
556static int __init parse_crash_elf32_headers(void)
557{
558 int rc=0;
559 Elf32_Ehdr ehdr;
560 u64 addr;
561
562 addr = elfcorehdr_addr;
563
564 /* Read Elf header */
565 rc = read_from_oldmem((char*)&ehdr, sizeof(Elf32_Ehdr), &addr, 0);
566 if (rc < 0)
567 return rc;
568
569 /* Do some basic Verification. */
570 if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
571 (ehdr.e_type != ET_CORE) ||
572 !elf_check_arch(&ehdr) ||
573 ehdr.e_ident[EI_CLASS] != ELFCLASS32||
574 ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
575 ehdr.e_version != EV_CURRENT ||
576 ehdr.e_ehsize != sizeof(Elf32_Ehdr) ||
577 ehdr.e_phentsize != sizeof(Elf32_Phdr) ||
578 ehdr.e_phnum == 0) {
579 printk(KERN_WARNING "Warning: Core image elf header is not"
580 "sane\n");
581 return -EINVAL;
582 }
583
584 /* Read in all elf headers. */
585 elfcorebuf_sz = sizeof(Elf32_Ehdr) + ehdr.e_phnum * sizeof(Elf32_Phdr);
586 elfcorebuf = kmalloc(elfcorebuf_sz, GFP_KERNEL);
587 if (!elfcorebuf)
588 return -ENOMEM;
589 addr = elfcorehdr_addr;
590 rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz, &addr, 0);
591 if (rc < 0) {
592 kfree(elfcorebuf);
593 return rc;
594 }
595
596 /* Merge all PT_NOTE headers into one. */
597 rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz, &vmcore_list);
598 if (rc) {
599 kfree(elfcorebuf);
600 return rc;
601 }
602 rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz,
603 &vmcore_list);
604 if (rc) {
605 kfree(elfcorebuf);
606 return rc;
607 }
608 set_vmcore_list_offsets_elf32(elfcorebuf, &vmcore_list);
609 return 0;
610}
611
612static int __init parse_crash_elf_headers(void)
613{
614 unsigned char e_ident[EI_NIDENT];
615 u64 addr;
616 int rc=0;
617
618 addr = elfcorehdr_addr;
619 rc = read_from_oldmem(e_ident, EI_NIDENT, &addr, 0);
620 if (rc < 0)
621 return rc;
622 if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
623 printk(KERN_WARNING "Warning: Core image elf header"
624 " not found\n");
625 return -EINVAL;
626 }
627
628 if (e_ident[EI_CLASS] == ELFCLASS64) {
629 rc = parse_crash_elf64_headers();
630 if (rc)
631 return rc;
632
633 /* Determine vmcore size. */
634 vmcore_size = get_vmcore_size_elf64(elfcorebuf);
635 } else if (e_ident[EI_CLASS] == ELFCLASS32) {
636 rc = parse_crash_elf32_headers();
637 if (rc)
638 return rc;
639
640 /* Determine vmcore size. */
641 vmcore_size = get_vmcore_size_elf32(elfcorebuf);
642 } else {
643 printk(KERN_WARNING "Warning: Core image elf header is not"
644 " sane\n");
645 return -EINVAL;
646 }
647 return 0;
648}
649
650/* Init function for vmcore module. */
651static int __init vmcore_init(void)
652{
653 int rc = 0;
654
655 /* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
656 if (!(elfcorehdr_addr < ELFCORE_ADDR_MAX))
657 return rc;
658 rc = parse_crash_elf_headers();
659 if (rc) {
660 printk(KERN_WARNING "Kdump: vmcore not initialized\n");
661 return rc;
662 }
663
664 /* Initialize /proc/vmcore size if proc is already up. */
665 if (proc_vmcore)
666 proc_vmcore->size = vmcore_size;
667 return 0;
668}
669module_init(vmcore_init)
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index cd66147cca04..7a8f5595c26f 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -61,7 +61,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
61 ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; 61 ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
62 else { 62 else {
63 le = (struct qnx4_link_info*)de; 63 le = (struct qnx4_link_info*)de;
64 ino = ( le->dl_inode_blk - 1 ) * 64 ino = ( le32_to_cpu(le->dl_inode_blk) - 1 ) *
65 QNX4_INODES_PER_BLOCK + 65 QNX4_INODES_PER_BLOCK +
66 le->dl_inode_ndx; 66 le->dl_inode_ndx;
67 } 67 }
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index aa92d6b76a9a..b79162a35478 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -236,7 +236,7 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
236 struct buffer_head *bh = NULL; 236 struct buffer_head *bh = NULL;
237 struct qnx4_xblk *xblk = NULL; 237 struct qnx4_xblk *xblk = NULL;
238 struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode); 238 struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);
239 qnx4_nxtnt_t nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts); 239 u16 nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);
240 240
241 if ( iblock < le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size) ) { 241 if ( iblock < le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size) ) {
242 // iblock is in the first extent. This is easy. 242 // iblock is in the first extent. This is easy.
@@ -372,7 +372,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
372 printk("qnx4: unable to read the superblock\n"); 372 printk("qnx4: unable to read the superblock\n");
373 goto outnobh; 373 goto outnobh;
374 } 374 }
375 if ( le32_to_cpu( *(__u32*)bh->b_data ) != QNX4_SUPER_MAGIC ) { 375 if ( le32_to_cpup((__le32*) bh->b_data) != QNX4_SUPER_MAGIC ) {
376 if (!silent) 376 if (!silent)
377 printk("qnx4: wrong fsid in superblock.\n"); 377 printk("qnx4: wrong fsid in superblock.\n");
378 goto out; 378 goto out;
diff --git a/fs/quota.c b/fs/quota.c
index 3f0333a51a23..f5d1cff55196 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -149,36 +149,6 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
149 return error; 149 return error;
150} 150}
151 151
152static struct super_block *get_super_to_sync(int type)
153{
154 struct list_head *head;
155 int cnt, dirty;
156
157restart:
158 spin_lock(&sb_lock);
159 list_for_each(head, &super_blocks) {
160 struct super_block *sb = list_entry(head, struct super_block, s_list);
161
162 /* This test just improves performance so it needn't be reliable... */
163 for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
164 if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
165 && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
166 dirty = 1;
167 if (!dirty)
168 continue;
169 sb->s_count++;
170 spin_unlock(&sb_lock);
171 down_read(&sb->s_umount);
172 if (!sb->s_root) {
173 drop_super(sb);
174 goto restart;
175 }
176 return sb;
177 }
178 spin_unlock(&sb_lock);
179 return NULL;
180}
181
182static void quota_sync_sb(struct super_block *sb, int type) 152static void quota_sync_sb(struct super_block *sb, int type)
183{ 153{
184 int cnt; 154 int cnt;
@@ -219,17 +189,35 @@ static void quota_sync_sb(struct super_block *sb, int type)
219 189
220void sync_dquots(struct super_block *sb, int type) 190void sync_dquots(struct super_block *sb, int type)
221{ 191{
192 int cnt, dirty;
193
222 if (sb) { 194 if (sb) {
223 if (sb->s_qcop->quota_sync) 195 if (sb->s_qcop->quota_sync)
224 quota_sync_sb(sb, type); 196 quota_sync_sb(sb, type);
197 return;
225 } 198 }
226 else { 199
227 while ((sb = get_super_to_sync(type)) != NULL) { 200 spin_lock(&sb_lock);
228 if (sb->s_qcop->quota_sync) 201restart:
229 quota_sync_sb(sb, type); 202 list_for_each_entry(sb, &super_blocks, s_list) {
230 drop_super(sb); 203 /* This test just improves performance so it needn't be reliable... */
231 } 204 for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
205 if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
206 && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
207 dirty = 1;
208 if (!dirty)
209 continue;
210 sb->s_count++;
211 spin_unlock(&sb_lock);
212 down_read(&sb->s_umount);
213 if (sb->s_root && sb->s_qcop->quota_sync)
214 quota_sync_sb(sb, type);
215 up_read(&sb->s_umount);
216 spin_lock(&sb_lock);
217 if (__put_super_and_need_restart(sb))
218 goto restart;
232 } 219 }
220 spin_unlock(&sb_lock);
233} 221}
234 222
235/* Copy parameters and call proper function */ 223/* Copy parameters and call proper function */
diff --git a/fs/read_write.c b/fs/read_write.c
index c4c2bee373ed..9292f5fa4d62 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -203,6 +203,16 @@ Einval:
203 return -EINVAL; 203 return -EINVAL;
204} 204}
205 205
206static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
207{
208 set_current_state(TASK_UNINTERRUPTIBLE);
209 if (!kiocbIsKicked(iocb))
210 schedule();
211 else
212 kiocbClearKicked(iocb);
213 __set_current_state(TASK_RUNNING);
214}
215
206ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 216ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
207{ 217{
208 struct kiocb kiocb; 218 struct kiocb kiocb;
@@ -210,7 +220,10 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
210 220
211 init_sync_kiocb(&kiocb, filp); 221 init_sync_kiocb(&kiocb, filp);
212 kiocb.ki_pos = *ppos; 222 kiocb.ki_pos = *ppos;
213 ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos); 223 while (-EIOCBRETRY ==
224 (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos)))
225 wait_on_retry_sync_kiocb(&kiocb);
226
214 if (-EIOCBQUEUED == ret) 227 if (-EIOCBQUEUED == ret)
215 ret = wait_on_sync_kiocb(&kiocb); 228 ret = wait_on_sync_kiocb(&kiocb);
216 *ppos = kiocb.ki_pos; 229 *ppos = kiocb.ki_pos;
@@ -258,7 +271,10 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
258 271
259 init_sync_kiocb(&kiocb, filp); 272 init_sync_kiocb(&kiocb, filp);
260 kiocb.ki_pos = *ppos; 273 kiocb.ki_pos = *ppos;
261 ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos); 274 while (-EIOCBRETRY ==
275 (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos)))
276 wait_on_retry_sync_kiocb(&kiocb);
277
262 if (-EIOCBQUEUED == ret) 278 if (-EIOCBQUEUED == ret)
263 ret = wait_on_sync_kiocb(&kiocb); 279 ret = wait_on_sync_kiocb(&kiocb);
264 *ppos = kiocb.ki_pos; 280 *ppos = kiocb.ki_pos;
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 2230afff1870..12e91209544e 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -201,7 +201,7 @@ static int reiserfs_allocate_blocks_for_region(
201 /* If we came here, it means we absolutely need to open a transaction, 201 /* If we came here, it means we absolutely need to open a transaction,
202 since we need to allocate some blocks */ 202 since we need to allocate some blocks */
203 reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that. 203 reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that.
204 res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); // Wish I know if this number enough 204 res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); // Wish I know if this number enough
205 if (res) 205 if (res)
206 goto error_exit; 206 goto error_exit;
207 reiserfs_update_inode_transaction(inode) ; 207 reiserfs_update_inode_transaction(inode) ;
@@ -576,7 +576,7 @@ error_exit:
576 int err; 576 int err;
577 // update any changes we made to blk count 577 // update any changes we made to blk count
578 reiserfs_update_sd(th, inode); 578 reiserfs_update_sd(th, inode);
579 err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); 579 err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb));
580 if (err) 580 if (err)
581 res = err; 581 res = err;
582 } 582 }
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 2711dff1b7b4..289d864fe731 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -28,7 +28,7 @@ static int reiserfs_prepare_write(struct file *f, struct page *page,
28void reiserfs_delete_inode (struct inode * inode) 28void reiserfs_delete_inode (struct inode * inode)
29{ 29{
30 /* We need blocks for transaction + (user+group) quota update (possibly delete) */ 30 /* We need blocks for transaction + (user+group) quota update (possibly delete) */
31 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS; 31 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
32 struct reiserfs_transaction_handle th ; 32 struct reiserfs_transaction_handle th ;
33 33
34 reiserfs_write_lock(inode->i_sb); 34 reiserfs_write_lock(inode->i_sb);
@@ -254,6 +254,7 @@ static int _get_block_create_0 (struct inode * inode, long block,
254 char * p = NULL; 254 char * p = NULL;
255 int chars; 255 int chars;
256 int ret ; 256 int ret ;
257 int result ;
257 int done = 0 ; 258 int done = 0 ;
258 unsigned long offset ; 259 unsigned long offset ;
259 260
@@ -262,10 +263,13 @@ static int _get_block_create_0 (struct inode * inode, long block,
262 (loff_t)block * inode->i_sb->s_blocksize + 1, TYPE_ANY, 3); 263 (loff_t)block * inode->i_sb->s_blocksize + 1, TYPE_ANY, 3);
263 264
264research: 265research:
265 if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND) { 266 result = search_for_position_by_key (inode->i_sb, &key, &path) ;
267 if (result != POSITION_FOUND) {
266 pathrelse (&path); 268 pathrelse (&path);
267 if (p) 269 if (p)
268 kunmap(bh_result->b_page) ; 270 kunmap(bh_result->b_page) ;
271 if (result == IO_ERROR)
272 return -EIO;
269 // We do not return -ENOENT if there is a hole but page is uptodate, because it means 273 // We do not return -ENOENT if there is a hole but page is uptodate, because it means
270 // That there is some MMAPED data associated with it that is yet to be written to disk. 274 // That there is some MMAPED data associated with it that is yet to be written to disk.
271 if ((args & GET_BLOCK_NO_HOLE) && !PageUptodate(bh_result->b_page) ) { 275 if ((args & GET_BLOCK_NO_HOLE) && !PageUptodate(bh_result->b_page) ) {
@@ -382,8 +386,9 @@ research:
382 386
383 // update key to look for the next piece 387 // update key to look for the next piece
384 set_cpu_key_k_offset (&key, cpu_key_k_offset (&key) + chars); 388 set_cpu_key_k_offset (&key, cpu_key_k_offset (&key) + chars);
385 if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND) 389 result = search_for_position_by_key (inode->i_sb, &key, &path);
386 // we read something from tail, even if now we got IO_ERROR 390 if (result != POSITION_FOUND)
391 // i/o error most likely
387 break; 392 break;
388 bh = get_last_bh (&path); 393 bh = get_last_bh (&path);
389 ih = get_ih (&path); 394 ih = get_ih (&path);
@@ -394,6 +399,10 @@ research:
394 399
395finished: 400finished:
396 pathrelse (&path); 401 pathrelse (&path);
402
403 if (result == IO_ERROR)
404 return -EIO;
405
397 /* this buffer has valid data, but isn't valid for io. mapping it to 406 /* this buffer has valid data, but isn't valid for io. mapping it to
398 * block #0 tells the rest of reiserfs it just has a tail in it 407 * block #0 tells the rest of reiserfs it just has a tail in it
399 */ 408 */
@@ -591,7 +600,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
591 XXX in practically impossible worst case direct2indirect() 600 XXX in practically impossible worst case direct2indirect()
592 can incur (much) more than 3 balancings. 601 can incur (much) more than 3 balancings.
593 quota update for user, group */ 602 quota update for user, group */
594 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS; 603 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
595 int version; 604 int version;
596 int dangle = 1; 605 int dangle = 1;
597 loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ; 606 loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
@@ -2796,12 +2805,15 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
2796 2805
2797 if (!error) { 2806 if (!error) {
2798 struct reiserfs_transaction_handle th; 2807 struct reiserfs_transaction_handle th;
2808 int jbegin_count = 2*(REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb)+REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb))+2;
2799 2809
2800 /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ 2810 /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
2801 journal_begin(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2); 2811 error = journal_begin(&th, inode->i_sb, jbegin_count);
2812 if (error)
2813 goto out;
2802 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; 2814 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
2803 if (error) { 2815 if (error) {
2804 journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2); 2816 journal_end(&th, inode->i_sb, jbegin_count);
2805 goto out; 2817 goto out;
2806 } 2818 }
2807 /* Update corresponding info in inode so that everything is in 2819 /* Update corresponding info in inode so that everything is in
@@ -2811,7 +2823,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
2811 if (attr->ia_valid & ATTR_GID) 2823 if (attr->ia_valid & ATTR_GID)
2812 inode->i_gid = attr->ia_gid; 2824 inode->i_gid = attr->ia_gid;
2813 mark_inode_dirty(inode); 2825 mark_inode_dirty(inode);
2814 journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2); 2826 error = journal_end(&th, inode->i_sb, jbegin_count);
2815 } 2827 }
2816 } 2828 }
2817 if (!error) 2829 if (!error)
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 3072cfdee959..7b87707acc36 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2631,6 +2631,8 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, struct sup
2631 int retval; 2631 int retval;
2632 2632
2633 reiserfs_check_lock_depth(p_s_sb, "journal_begin") ; 2633 reiserfs_check_lock_depth(p_s_sb, "journal_begin") ;
2634 if (nblocks > journal->j_trans_max)
2635 BUG();
2634 2636
2635 PROC_INFO_INC( p_s_sb, journal.journal_being ); 2637 PROC_INFO_INC( p_s_sb, journal.journal_being );
2636 /* set here for journal_join */ 2638 /* set here for journal_join */
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 7d4dc5f5aa8b..4a333255f27a 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -586,7 +586,7 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
586 int retval; 586 int retval;
587 struct inode * inode; 587 struct inode * inode;
588 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 588 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
589 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 589 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
590 struct reiserfs_transaction_handle th ; 590 struct reiserfs_transaction_handle th ;
591 int locked; 591 int locked;
592 592
@@ -653,7 +653,7 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
653 struct inode * inode; 653 struct inode * inode;
654 struct reiserfs_transaction_handle th ; 654 struct reiserfs_transaction_handle th ;
655 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 655 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
656 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 656 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
657 int locked; 657 int locked;
658 658
659 if (!new_valid_dev(rdev)) 659 if (!new_valid_dev(rdev))
@@ -727,7 +727,7 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
727 struct inode * inode; 727 struct inode * inode;
728 struct reiserfs_transaction_handle th ; 728 struct reiserfs_transaction_handle th ;
729 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 729 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
730 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 730 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
731 int locked; 731 int locked;
732 732
733#ifdef DISPLACE_NEW_PACKING_LOCALITIES 733#ifdef DISPLACE_NEW_PACKING_LOCALITIES
@@ -829,8 +829,10 @@ static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
829 829
830 830
831 /* we will be doing 2 balancings and update 2 stat data, we change quotas 831 /* we will be doing 2 balancings and update 2 stat data, we change quotas
832 * of the owner of the directory and of the owner of the parent directory */ 832 * of the owner of the directory and of the owner of the parent directory.
833 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 833 * The quota structure is possibly deleted only on last iput => outside
834 * of this transaction */
835 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
834 836
835 reiserfs_write_lock(dir->i_sb); 837 reiserfs_write_lock(dir->i_sb);
836 retval = journal_begin(&th, dir->i_sb, jbegin_count) ; 838 retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -913,9 +915,10 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
913 inode = dentry->d_inode; 915 inode = dentry->d_inode;
914 916
915 /* in this transaction we can be doing at max two balancings and update 917 /* in this transaction we can be doing at max two balancings and update
916 two stat datas, we change quotas of the owner of the directory and of 918 * two stat datas, we change quotas of the owner of the directory and of
917 the owner of the parent directory */ 919 * the owner of the parent directory. The quota structure is possibly
918 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 920 * deleted only on iput => outside of this transaction */
921 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
919 922
920 reiserfs_write_lock(dir->i_sb); 923 reiserfs_write_lock(dir->i_sb);
921 retval = journal_begin(&th, dir->i_sb, jbegin_count) ; 924 retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -1000,7 +1003,7 @@ static int reiserfs_symlink (struct inode * parent_dir,
1000 struct reiserfs_transaction_handle th ; 1003 struct reiserfs_transaction_handle th ;
1001 int mode = S_IFLNK | S_IRWXUGO; 1004 int mode = S_IFLNK | S_IRWXUGO;
1002 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 1005 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
1003 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 1006 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
1004 1007
1005 if (!(inode = new_inode(parent_dir->i_sb))) { 1008 if (!(inode = new_inode(parent_dir->i_sb))) {
1006 return -ENOMEM ; 1009 return -ENOMEM ;
@@ -1076,7 +1079,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
1076 struct inode *inode = old_dentry->d_inode; 1079 struct inode *inode = old_dentry->d_inode;
1077 struct reiserfs_transaction_handle th ; 1080 struct reiserfs_transaction_handle th ;
1078 /* We need blocks for transaction + update of quotas for the owners of the directory */ 1081 /* We need blocks for transaction + update of quotas for the owners of the directory */
1079 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS; 1082 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
1080 1083
1081 reiserfs_write_lock(dir->i_sb); 1084 reiserfs_write_lock(dir->i_sb);
1082 if (inode->i_nlink >= REISERFS_LINK_MAX) { 1085 if (inode->i_nlink >= REISERFS_LINK_MAX) {
@@ -1196,7 +1199,7 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
1196 pointed initially and (5) maybe block containing ".." of 1199 pointed initially and (5) maybe block containing ".." of
1197 renamed directory 1200 renamed directory
1198 quota updates: two parent directories */ 1201 quota updates: two parent directories */
1199 jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS; 1202 jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
1200 1203
1201 old_inode = old_dentry->d_inode; 1204 old_inode = old_dentry->d_inode;
1202 new_dentry_inode = new_dentry->d_inode; 1205 new_dentry_inode = new_dentry->d_inode;
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index c47f8fd31a2d..63158491e152 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -223,7 +223,7 @@ extern struct tree_balance * cur_tb;
223const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; 223const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}};
224 224
225/* Maximal possible key. It is never in the tree. */ 225/* Maximal possible key. It is never in the tree. */
226const struct reiserfs_key MAX_KEY = { 226static const struct reiserfs_key MAX_KEY = {
227 __constant_cpu_to_le32(0xffffffff), 227 __constant_cpu_to_le32(0xffffffff),
228 __constant_cpu_to_le32(0xffffffff), 228 __constant_cpu_to_le32(0xffffffff),
229 {{__constant_cpu_to_le32(0xffffffff), 229 {{__constant_cpu_to_le32(0xffffffff),
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b35b87744983..660aefca1fd2 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -866,8 +866,9 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
866 {"jdev", .arg_required = 'j', .values = NULL}, 866 {"jdev", .arg_required = 'j', .values = NULL},
867 {"nolargeio", .arg_required = 'w', .values = NULL}, 867 {"nolargeio", .arg_required = 'w', .values = NULL},
868 {"commit", .arg_required = 'c', .values = NULL}, 868 {"commit", .arg_required = 'c', .values = NULL},
869 {"usrquota",}, 869 {"usrquota", .setmask = 1<<REISERFS_QUOTA},
870 {"grpquota",}, 870 {"grpquota", .setmask = 1<<REISERFS_QUOTA},
871 {"noquota", .clrmask = 1<<REISERFS_QUOTA},
871 {"errors", .arg_required = 'e', .values = error_actions}, 872 {"errors", .arg_required = 'e', .values = error_actions},
872 {"usrjquota", .arg_required = 'u'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL}, 873 {"usrjquota", .arg_required = 'u'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
873 {"grpjquota", .arg_required = 'g'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL}, 874 {"grpjquota", .arg_required = 'g'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
@@ -964,6 +965,7 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
964 return 0; 965 return 0;
965 } 966 }
966 strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg); 967 strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
968 *mount_options |= 1<<REISERFS_QUOTA;
967 } 969 }
968 else { 970 else {
969 if (REISERFS_SB(s)->s_qf_names[qtype]) { 971 if (REISERFS_SB(s)->s_qf_names[qtype]) {
@@ -995,7 +997,13 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
995 reiserfs_warning(s, "reiserfs_parse_options: journalled quota format not specified."); 997 reiserfs_warning(s, "reiserfs_parse_options: journalled quota format not specified.");
996 return 0; 998 return 0;
997 } 999 }
1000 /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
1001 if (!(*mount_options & (1<<REISERFS_QUOTA)) && sb_any_quota_enabled(s)) {
1002 reiserfs_warning(s, "reiserfs_parse_options: quota options must be present when quota is turned on.");
1003 return 0;
1004 }
998#endif 1005#endif
1006
999 return 1; 1007 return 1;
1000} 1008}
1001 1009
@@ -1105,6 +1113,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
1105 safe_mask |= 1 << REISERFS_ERROR_RO; 1113 safe_mask |= 1 << REISERFS_ERROR_RO;
1106 safe_mask |= 1 << REISERFS_ERROR_CONTINUE; 1114 safe_mask |= 1 << REISERFS_ERROR_CONTINUE;
1107 safe_mask |= 1 << REISERFS_ERROR_PANIC; 1115 safe_mask |= 1 << REISERFS_ERROR_PANIC;
1116 safe_mask |= 1 << REISERFS_QUOTA;
1108 1117
1109 /* Update the bitmask, taking care to keep 1118 /* Update the bitmask, taking care to keep
1110 * the bits we're not allowed to change here */ 1119 * the bits we're not allowed to change here */
@@ -1841,13 +1850,18 @@ static int reiserfs_statfs (struct super_block * s, struct kstatfs * buf)
1841static int reiserfs_dquot_initialize(struct inode *inode, int type) 1850static int reiserfs_dquot_initialize(struct inode *inode, int type)
1842{ 1851{
1843 struct reiserfs_transaction_handle th; 1852 struct reiserfs_transaction_handle th;
1844 int ret; 1853 int ret, err;
1845 1854
1846 /* We may create quota structure so we need to reserve enough blocks */ 1855 /* We may create quota structure so we need to reserve enough blocks */
1847 reiserfs_write_lock(inode->i_sb); 1856 reiserfs_write_lock(inode->i_sb);
1848 journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1857 ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
1858 if (ret)
1859 goto out;
1849 ret = dquot_initialize(inode, type); 1860 ret = dquot_initialize(inode, type);
1850 journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1861 err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
1862 if (!ret && err)
1863 ret = err;
1864out:
1851 reiserfs_write_unlock(inode->i_sb); 1865 reiserfs_write_unlock(inode->i_sb);
1852 return ret; 1866 return ret;
1853} 1867}
@@ -1855,13 +1869,18 @@ static int reiserfs_dquot_initialize(struct inode *inode, int type)
1855static int reiserfs_dquot_drop(struct inode *inode) 1869static int reiserfs_dquot_drop(struct inode *inode)
1856{ 1870{
1857 struct reiserfs_transaction_handle th; 1871 struct reiserfs_transaction_handle th;
1858 int ret; 1872 int ret, err;
1859 1873
1860 /* We may delete quota structure so we need to reserve enough blocks */ 1874 /* We may delete quota structure so we need to reserve enough blocks */
1861 reiserfs_write_lock(inode->i_sb); 1875 reiserfs_write_lock(inode->i_sb);
1862 journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1876 ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
1877 if (ret)
1878 goto out;
1863 ret = dquot_drop(inode); 1879 ret = dquot_drop(inode);
1864 journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1880 err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
1881 if (!ret && err)
1882 ret = err;
1883out:
1865 reiserfs_write_unlock(inode->i_sb); 1884 reiserfs_write_unlock(inode->i_sb);
1866 return ret; 1885 return ret;
1867} 1886}
@@ -1869,12 +1888,17 @@ static int reiserfs_dquot_drop(struct inode *inode)
1869static int reiserfs_write_dquot(struct dquot *dquot) 1888static int reiserfs_write_dquot(struct dquot *dquot)
1870{ 1889{
1871 struct reiserfs_transaction_handle th; 1890 struct reiserfs_transaction_handle th;
1872 int ret; 1891 int ret, err;
1873 1892
1874 reiserfs_write_lock(dquot->dq_sb); 1893 reiserfs_write_lock(dquot->dq_sb);
1875 journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS); 1894 ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
1895 if (ret)
1896 goto out;
1876 ret = dquot_commit(dquot); 1897 ret = dquot_commit(dquot);
1877 journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS); 1898 err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
1899 if (!ret && err)
1900 ret = err;
1901out:
1878 reiserfs_write_unlock(dquot->dq_sb); 1902 reiserfs_write_unlock(dquot->dq_sb);
1879 return ret; 1903 return ret;
1880} 1904}
@@ -1882,12 +1906,17 @@ static int reiserfs_write_dquot(struct dquot *dquot)
1882static int reiserfs_acquire_dquot(struct dquot *dquot) 1906static int reiserfs_acquire_dquot(struct dquot *dquot)
1883{ 1907{
1884 struct reiserfs_transaction_handle th; 1908 struct reiserfs_transaction_handle th;
1885 int ret; 1909 int ret, err;
1886 1910
1887 reiserfs_write_lock(dquot->dq_sb); 1911 reiserfs_write_lock(dquot->dq_sb);
1888 journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1912 ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
1913 if (ret)
1914 goto out;
1889 ret = dquot_acquire(dquot); 1915 ret = dquot_acquire(dquot);
1890 journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1916 err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
1917 if (!ret && err)
1918 ret = err;
1919out:
1891 reiserfs_write_unlock(dquot->dq_sb); 1920 reiserfs_write_unlock(dquot->dq_sb);
1892 return ret; 1921 return ret;
1893} 1922}
@@ -1895,12 +1924,17 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
1895static int reiserfs_release_dquot(struct dquot *dquot) 1924static int reiserfs_release_dquot(struct dquot *dquot)
1896{ 1925{
1897 struct reiserfs_transaction_handle th; 1926 struct reiserfs_transaction_handle th;
1898 int ret; 1927 int ret, err;
1899 1928
1900 reiserfs_write_lock(dquot->dq_sb); 1929 reiserfs_write_lock(dquot->dq_sb);
1901 journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1930 ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
1931 if (ret)
1932 goto out;
1902 ret = dquot_release(dquot); 1933 ret = dquot_release(dquot);
1903 journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1934 err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
1935 if (!ret && err)
1936 ret = err;
1937out:
1904 reiserfs_write_unlock(dquot->dq_sb); 1938 reiserfs_write_unlock(dquot->dq_sb);
1905 return ret; 1939 return ret;
1906} 1940}
@@ -1920,39 +1954,29 @@ static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
1920static int reiserfs_write_info(struct super_block *sb, int type) 1954static int reiserfs_write_info(struct super_block *sb, int type)
1921{ 1955{
1922 struct reiserfs_transaction_handle th; 1956 struct reiserfs_transaction_handle th;
1923 int ret; 1957 int ret, err;
1924 1958
1925 /* Data block + inode block */ 1959 /* Data block + inode block */
1926 reiserfs_write_lock(sb); 1960 reiserfs_write_lock(sb);
1927 journal_begin(&th, sb, 2); 1961 ret = journal_begin(&th, sb, 2);
1962 if (ret)
1963 goto out;
1928 ret = dquot_commit_info(sb, type); 1964 ret = dquot_commit_info(sb, type);
1929 journal_end(&th, sb, 2); 1965 err = journal_end(&th, sb, 2);
1966 if (!ret && err)
1967 ret = err;
1968out:
1930 reiserfs_write_unlock(sb); 1969 reiserfs_write_unlock(sb);
1931 return ret; 1970 return ret;
1932} 1971}
1933 1972
1934/* 1973/*
1935 * Turn on quotas during mount time - we need to find 1974 * Turn on quotas during mount time - we need to find the quota file and such...
1936 * the quota file and such...
1937 */ 1975 */
1938static int reiserfs_quota_on_mount(struct super_block *sb, int type) 1976static int reiserfs_quota_on_mount(struct super_block *sb, int type)
1939{ 1977{
1940 int err; 1978 return vfs_quota_on_mount(sb, REISERFS_SB(sb)->s_qf_names[type],
1941 struct dentry *dentry; 1979 REISERFS_SB(sb)->s_jquota_fmt, type);
1942 struct qstr name = { .name = REISERFS_SB(sb)->s_qf_names[type],
1943 .hash = 0,
1944 .len = strlen(REISERFS_SB(sb)->s_qf_names[type])};
1945
1946 dentry = lookup_hash(&name, sb->s_root);
1947 if (IS_ERR(dentry))
1948 return PTR_ERR(dentry);
1949 err = vfs_quota_on_mount(type, REISERFS_SB(sb)->s_jquota_fmt, dentry);
1950 /* Now invalidate and put the dentry - quota got its own reference
1951 * to inode and dentry has at least wrong hash so we had better
1952 * throw it away */
1953 d_invalidate(dentry);
1954 dput(dentry);
1955 return err;
1956} 1980}
1957 1981
1958/* 1982/*
@@ -1963,6 +1987,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, ch
1963 int err; 1987 int err;
1964 struct nameidata nd; 1988 struct nameidata nd;
1965 1989
1990 if (!(REISERFS_SB(sb)->s_mount_opt & (1<<REISERFS_QUOTA)))
1991 return -EINVAL;
1966 err = path_lookup(path, LOOKUP_FOLLOW, &nd); 1992 err = path_lookup(path, LOOKUP_FOLLOW, &nd);
1967 if (err) 1993 if (err)
1968 return err; 1994 return err;
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index e302071903a1..c312881c5f53 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -4,7 +4,7 @@
4#include <linux/errno.h> 4#include <linux/errno.h>
5#include <linux/pagemap.h> 5#include <linux/pagemap.h>
6#include <linux/xattr.h> 6#include <linux/xattr.h>
7#include <linux/xattr_acl.h> 7#include <linux/posix_acl_xattr.h>
8#include <linux/reiserfs_xattr.h> 8#include <linux/reiserfs_xattr.h>
9#include <linux/reiserfs_acl.h> 9#include <linux/reiserfs_acl.h>
10#include <asm/uaccess.h> 10#include <asm/uaccess.h>
@@ -192,11 +192,11 @@ reiserfs_get_acl(struct inode *inode, int type)
192 192
193 switch (type) { 193 switch (type) {
194 case ACL_TYPE_ACCESS: 194 case ACL_TYPE_ACCESS:
195 name = XATTR_NAME_ACL_ACCESS; 195 name = POSIX_ACL_XATTR_ACCESS;
196 p_acl = &reiserfs_i->i_acl_access; 196 p_acl = &reiserfs_i->i_acl_access;
197 break; 197 break;
198 case ACL_TYPE_DEFAULT: 198 case ACL_TYPE_DEFAULT:
199 name = XATTR_NAME_ACL_DEFAULT; 199 name = POSIX_ACL_XATTR_DEFAULT;
200 p_acl = &reiserfs_i->i_acl_default; 200 p_acl = &reiserfs_i->i_acl_default;
201 break; 201 break;
202 default: 202 default:
@@ -260,7 +260,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
260 260
261 switch (type) { 261 switch (type) {
262 case ACL_TYPE_ACCESS: 262 case ACL_TYPE_ACCESS:
263 name = XATTR_NAME_ACL_ACCESS; 263 name = POSIX_ACL_XATTR_ACCESS;
264 p_acl = &reiserfs_i->i_acl_access; 264 p_acl = &reiserfs_i->i_acl_access;
265 if (acl) { 265 if (acl) {
266 mode_t mode = inode->i_mode; 266 mode_t mode = inode->i_mode;
@@ -275,7 +275,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
275 } 275 }
276 break; 276 break;
277 case ACL_TYPE_DEFAULT: 277 case ACL_TYPE_DEFAULT:
278 name = XATTR_NAME_ACL_DEFAULT; 278 name = POSIX_ACL_XATTR_DEFAULT;
279 p_acl = &reiserfs_i->i_acl_default; 279 p_acl = &reiserfs_i->i_acl_default;
280 if (!S_ISDIR (inode->i_mode)) 280 if (!S_ISDIR (inode->i_mode))
281 return acl ? -EACCES : 0; 281 return acl ? -EACCES : 0;
@@ -468,7 +468,7 @@ static int
468posix_acl_access_get(struct inode *inode, const char *name, 468posix_acl_access_get(struct inode *inode, const char *name,
469 void *buffer, size_t size) 469 void *buffer, size_t size)
470{ 470{
471 if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) 471 if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
472 return -EINVAL; 472 return -EINVAL;
473 return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); 473 return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
474} 474}
@@ -477,7 +477,7 @@ static int
477posix_acl_access_set(struct inode *inode, const char *name, 477posix_acl_access_set(struct inode *inode, const char *name,
478 const void *value, size_t size, int flags) 478 const void *value, size_t size, int flags)
479{ 479{
480 if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) 480 if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
481 return -EINVAL; 481 return -EINVAL;
482 return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); 482 return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
483} 483}
@@ -487,7 +487,7 @@ posix_acl_access_del (struct inode *inode, const char *name)
487{ 487{
488 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 488 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
489 struct posix_acl **acl = &reiserfs_i->i_acl_access; 489 struct posix_acl **acl = &reiserfs_i->i_acl_access;
490 if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1) 490 if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
491 return -EINVAL; 491 return -EINVAL;
492 if (!IS_ERR (*acl) && *acl) { 492 if (!IS_ERR (*acl) && *acl) {
493 posix_acl_release (*acl); 493 posix_acl_release (*acl);
@@ -510,7 +510,7 @@ posix_acl_access_list (struct inode *inode, const char *name, int namelen, char
510} 510}
511 511
512struct reiserfs_xattr_handler posix_acl_access_handler = { 512struct reiserfs_xattr_handler posix_acl_access_handler = {
513 .prefix = XATTR_NAME_ACL_ACCESS, 513 .prefix = POSIX_ACL_XATTR_ACCESS,
514 .get = posix_acl_access_get, 514 .get = posix_acl_access_get,
515 .set = posix_acl_access_set, 515 .set = posix_acl_access_set,
516 .del = posix_acl_access_del, 516 .del = posix_acl_access_del,
@@ -521,7 +521,7 @@ static int
521posix_acl_default_get (struct inode *inode, const char *name, 521posix_acl_default_get (struct inode *inode, const char *name,
522 void *buffer, size_t size) 522 void *buffer, size_t size)
523{ 523{
524 if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) 524 if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
525 return -EINVAL; 525 return -EINVAL;
526 return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size); 526 return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
527} 527}
@@ -530,7 +530,7 @@ static int
530posix_acl_default_set(struct inode *inode, const char *name, 530posix_acl_default_set(struct inode *inode, const char *name,
531 const void *value, size_t size, int flags) 531 const void *value, size_t size, int flags)
532{ 532{
533 if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) 533 if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
534 return -EINVAL; 534 return -EINVAL;
535 return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); 535 return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
536} 536}
@@ -540,7 +540,7 @@ posix_acl_default_del (struct inode *inode, const char *name)
540{ 540{
541 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 541 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
542 struct posix_acl **acl = &reiserfs_i->i_acl_default; 542 struct posix_acl **acl = &reiserfs_i->i_acl_default;
543 if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1) 543 if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
544 return -EINVAL; 544 return -EINVAL;
545 if (!IS_ERR (*acl) && *acl) { 545 if (!IS_ERR (*acl) && *acl) {
546 posix_acl_release (*acl); 546 posix_acl_release (*acl);
@@ -563,7 +563,7 @@ posix_acl_default_list (struct inode *inode, const char *name, int namelen, char
563} 563}
564 564
565struct reiserfs_xattr_handler posix_acl_default_handler = { 565struct reiserfs_xattr_handler posix_acl_default_handler = {
566 .prefix = XATTR_NAME_ACL_DEFAULT, 566 .prefix = POSIX_ACL_XATTR_DEFAULT,
567 .get = posix_acl_default_get, 567 .get = posix_acl_default_get,
568 .set = posix_acl_default_set, 568 .set = posix_acl_default_set,
569 .del = posix_acl_default_del, 569 .del = posix_acl_default_del,
diff --git a/fs/super.c b/fs/super.c
index 3a1b8ca04ba6..25bc1ec6bc5d 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -341,20 +341,22 @@ static inline void write_super(struct super_block *sb)
341 */ 341 */
342void sync_supers(void) 342void sync_supers(void)
343{ 343{
344 struct super_block * sb; 344 struct super_block *sb;
345restart: 345
346 spin_lock(&sb_lock); 346 spin_lock(&sb_lock);
347 sb = sb_entry(super_blocks.next); 347restart:
348 while (sb != sb_entry(&super_blocks)) 348 list_for_each_entry(sb, &super_blocks, s_list) {
349 if (sb->s_dirt) { 349 if (sb->s_dirt) {
350 sb->s_count++; 350 sb->s_count++;
351 spin_unlock(&sb_lock); 351 spin_unlock(&sb_lock);
352 down_read(&sb->s_umount); 352 down_read(&sb->s_umount);
353 write_super(sb); 353 write_super(sb);
354 drop_super(sb); 354 up_read(&sb->s_umount);
355 goto restart; 355 spin_lock(&sb_lock);
356 } else 356 if (__put_super_and_need_restart(sb))
357 sb = sb_entry(sb->s_list.next); 357 goto restart;
358 }
359 }
358 spin_unlock(&sb_lock); 360 spin_unlock(&sb_lock);
359} 361}
360 362
@@ -381,20 +383,16 @@ void sync_filesystems(int wait)
381 383
382 down(&mutex); /* Could be down_interruptible */ 384 down(&mutex); /* Could be down_interruptible */
383 spin_lock(&sb_lock); 385 spin_lock(&sb_lock);
384 for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks); 386 list_for_each_entry(sb, &super_blocks, s_list) {
385 sb = sb_entry(sb->s_list.next)) {
386 if (!sb->s_op->sync_fs) 387 if (!sb->s_op->sync_fs)
387 continue; 388 continue;
388 if (sb->s_flags & MS_RDONLY) 389 if (sb->s_flags & MS_RDONLY)
389 continue; 390 continue;
390 sb->s_need_sync_fs = 1; 391 sb->s_need_sync_fs = 1;
391 } 392 }
392 spin_unlock(&sb_lock);
393 393
394restart: 394restart:
395 spin_lock(&sb_lock); 395 list_for_each_entry(sb, &super_blocks, s_list) {
396 for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks);
397 sb = sb_entry(sb->s_list.next)) {
398 if (!sb->s_need_sync_fs) 396 if (!sb->s_need_sync_fs)
399 continue; 397 continue;
400 sb->s_need_sync_fs = 0; 398 sb->s_need_sync_fs = 0;
@@ -405,8 +403,11 @@ restart:
405 down_read(&sb->s_umount); 403 down_read(&sb->s_umount);
406 if (sb->s_root && (wait || sb->s_dirt)) 404 if (sb->s_root && (wait || sb->s_dirt))
407 sb->s_op->sync_fs(sb, wait); 405 sb->s_op->sync_fs(sb, wait);
408 drop_super(sb); 406 up_read(&sb->s_umount);
409 goto restart; 407 /* restart only when sb is no longer on the list */
408 spin_lock(&sb_lock);
409 if (__put_super_and_need_restart(sb))
410 goto restart;
410 } 411 }
411 spin_unlock(&sb_lock); 412 spin_unlock(&sb_lock);
412 up(&mutex); 413 up(&mutex);
@@ -422,21 +423,25 @@ restart:
422 423
423struct super_block * get_super(struct block_device *bdev) 424struct super_block * get_super(struct block_device *bdev)
424{ 425{
425 struct list_head *p; 426 struct super_block *sb;
427
426 if (!bdev) 428 if (!bdev)
427 return NULL; 429 return NULL;
428rescan: 430
429 spin_lock(&sb_lock); 431 spin_lock(&sb_lock);
430 list_for_each(p, &super_blocks) { 432rescan:
431 struct super_block *s = sb_entry(p); 433 list_for_each_entry(sb, &super_blocks, s_list) {
432 if (s->s_bdev == bdev) { 434 if (sb->s_bdev == bdev) {
433 s->s_count++; 435 sb->s_count++;
434 spin_unlock(&sb_lock); 436 spin_unlock(&sb_lock);
435 down_read(&s->s_umount); 437 down_read(&sb->s_umount);
436 if (s->s_root) 438 if (sb->s_root)
437 return s; 439 return sb;
438 drop_super(s); 440 up_read(&sb->s_umount);
439 goto rescan; 441 /* restart only when sb is no longer on the list */
442 spin_lock(&sb_lock);
443 if (__put_super_and_need_restart(sb))
444 goto rescan;
440 } 445 }
441 } 446 }
442 spin_unlock(&sb_lock); 447 spin_unlock(&sb_lock);
@@ -447,20 +452,22 @@ EXPORT_SYMBOL(get_super);
447 452
448struct super_block * user_get_super(dev_t dev) 453struct super_block * user_get_super(dev_t dev)
449{ 454{
450 struct list_head *p; 455 struct super_block *sb;
451 456
452rescan:
453 spin_lock(&sb_lock); 457 spin_lock(&sb_lock);
454 list_for_each(p, &super_blocks) { 458rescan:
455 struct super_block *s = sb_entry(p); 459 list_for_each_entry(sb, &super_blocks, s_list) {
456 if (s->s_dev == dev) { 460 if (sb->s_dev == dev) {
457 s->s_count++; 461 sb->s_count++;
458 spin_unlock(&sb_lock); 462 spin_unlock(&sb_lock);
459 down_read(&s->s_umount); 463 down_read(&sb->s_umount);
460 if (s->s_root) 464 if (sb->s_root)
461 return s; 465 return sb;
462 drop_super(s); 466 up_read(&sb->s_umount);
463 goto rescan; 467 /* restart only when sb is no longer on the list */
468 spin_lock(&sb_lock);
469 if (__put_super_and_need_restart(sb))
470 goto rescan;
464 } 471 }
465 } 472 }
466 spin_unlock(&sb_lock); 473 spin_unlock(&sb_lock);
@@ -835,6 +842,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
835 mnt->mnt_parent = mnt; 842 mnt->mnt_parent = mnt;
836 mnt->mnt_namespace = current->namespace; 843 mnt->mnt_namespace = current->namespace;
837 up_write(&sb->s_umount); 844 up_write(&sb->s_umount);
845 free_secdata(secdata);
838 put_filesystem(type); 846 put_filesystem(type);
839 return mnt; 847 return mnt;
840out_sb: 848out_sb:
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d4aaa88d0214..78899eeab974 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -25,7 +25,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
25 struct kobject * kobj = to_kobj(dentry->d_parent); 25 struct kobject * kobj = to_kobj(dentry->d_parent);
26 26
27 if (!attr->read) 27 if (!attr->read)
28 return -EINVAL; 28 return -EIO;
29 29
30 return attr->read(kobj, buffer, off, count); 30 return attr->read(kobj, buffer, off, count);
31} 31}
@@ -71,7 +71,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
71 struct kobject *kobj = to_kobj(dentry->d_parent); 71 struct kobject *kobj = to_kobj(dentry->d_parent);
72 72
73 if (!attr->write) 73 if (!attr->write)
74 return -EINVAL; 74 return -EIO;
75 75
76 return attr->write(kobj, buffer, offset, count); 76 return attr->write(kobj, buffer, offset, count);
77} 77}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index fe198210bc2d..59734ba1ee60 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -8,6 +8,7 @@
8#include <linux/mount.h> 8#include <linux/mount.h>
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/kobject.h> 10#include <linux/kobject.h>
11#include <linux/namei.h>
11#include "sysfs.h" 12#include "sysfs.h"
12 13
13DECLARE_RWSEM(sysfs_rename_sem); 14DECLARE_RWSEM(sysfs_rename_sem);
@@ -99,20 +100,21 @@ static int create_dir(struct kobject * k, struct dentry * p,
99 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 100 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
100 101
101 down(&p->d_inode->i_sem); 102 down(&p->d_inode->i_sem);
102 *d = sysfs_get_dentry(p,n); 103 *d = lookup_one_len(n, p, strlen(n));
103 if (!IS_ERR(*d)) { 104 if (!IS_ERR(*d)) {
104 error = sysfs_create(*d, mode, init_dir); 105 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
105 if (!error) { 106 if (!error) {
106 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, 107 error = sysfs_create(*d, mode, init_dir);
107 SYSFS_DIR);
108 if (!error) { 108 if (!error) {
109 p->d_inode->i_nlink++; 109 p->d_inode->i_nlink++;
110 (*d)->d_op = &sysfs_dentry_ops; 110 (*d)->d_op = &sysfs_dentry_ops;
111 d_rehash(*d); 111 d_rehash(*d);
112 } 112 }
113 } 113 }
114 if (error && (error != -EEXIST)) 114 if (error && (error != -EEXIST)) {
115 sysfs_put((*d)->d_fsdata);
115 d_drop(*d); 116 d_drop(*d);
117 }
116 dput(*d); 118 dput(*d);
117 } else 119 } else
118 error = PTR_ERR(*d); 120 error = PTR_ERR(*d);
@@ -171,17 +173,19 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
171 init = init_file; 173 init = init_file;
172 } 174 }
173 175
176 dentry->d_fsdata = sysfs_get(sd);
177 sd->s_dentry = dentry;
174 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); 178 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
175 if (error) 179 if (error) {
180 sysfs_put(sd);
176 return error; 181 return error;
182 }
177 183
178 if (bin_attr) { 184 if (bin_attr) {
179 dentry->d_inode->i_size = bin_attr->size; 185 dentry->d_inode->i_size = bin_attr->size;
180 dentry->d_inode->i_fop = &bin_fops; 186 dentry->d_inode->i_fop = &bin_fops;
181 } 187 }
182 dentry->d_op = &sysfs_dentry_ops; 188 dentry->d_op = &sysfs_dentry_ops;
183 dentry->d_fsdata = sysfs_get(sd);
184 sd->s_dentry = dentry;
185 d_rehash(dentry); 189 d_rehash(dentry);
186 190
187 return 0; 191 return 0;
@@ -191,13 +195,15 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
191{ 195{
192 int err = 0; 196 int err = 0;
193 197
198 dentry->d_fsdata = sysfs_get(sd);
199 sd->s_dentry = dentry;
194 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); 200 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
195 if (!err) { 201 if (!err) {
196 dentry->d_op = &sysfs_dentry_ops; 202 dentry->d_op = &sysfs_dentry_ops;
197 dentry->d_fsdata = sysfs_get(sd);
198 sd->s_dentry = dentry;
199 d_rehash(dentry); 203 d_rehash(dentry);
200 } 204 } else
205 sysfs_put(sd);
206
201 return err; 207 return err;
202} 208}
203 209
@@ -228,6 +234,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
228 234
229struct inode_operations sysfs_dir_inode_operations = { 235struct inode_operations sysfs_dir_inode_operations = {
230 .lookup = sysfs_lookup, 236 .lookup = sysfs_lookup,
237 .setattr = sysfs_setattr,
231}; 238};
232 239
233static void remove_dir(struct dentry * d) 240static void remove_dir(struct dentry * d)
@@ -309,7 +316,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
309 316
310 down(&parent->d_inode->i_sem); 317 down(&parent->d_inode->i_sem);
311 318
312 new_dentry = sysfs_get_dentry(parent, new_name); 319 new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
313 if (!IS_ERR(new_dentry)) { 320 if (!IS_ERR(new_dentry)) {
314 if (!new_dentry->d_inode) { 321 if (!new_dentry->d_inode) {
315 error = kobject_set_name(kobj, "%s", new_name); 322 error = kobject_set_name(kobj, "%s", new_name);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 364208071e17..d72c1ce48559 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -5,6 +5,7 @@
5#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/dnotify.h> 6#include <linux/dnotify.h>
7#include <linux/kobject.h> 7#include <linux/kobject.h>
8#include <linux/namei.h>
8#include <asm/uaccess.h> 9#include <asm/uaccess.h>
9#include <asm/semaphore.h> 10#include <asm/semaphore.h>
10 11
@@ -13,7 +14,7 @@
13#define to_subsys(k) container_of(k,struct subsystem,kset.kobj) 14#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
14#define to_sattr(a) container_of(a,struct subsys_attribute,attr) 15#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
15 16
16/** 17/*
17 * Subsystem file operations. 18 * Subsystem file operations.
18 * These operations allow subsystems to have files that can be 19 * These operations allow subsystems to have files that can be
19 * read/written. 20 * read/written.
@@ -23,7 +24,7 @@ subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
23{ 24{
24 struct subsystem * s = to_subsys(kobj); 25 struct subsystem * s = to_subsys(kobj);
25 struct subsys_attribute * sattr = to_sattr(attr); 26 struct subsys_attribute * sattr = to_sattr(attr);
26 ssize_t ret = 0; 27 ssize_t ret = -EIO;
27 28
28 if (sattr->show) 29 if (sattr->show)
29 ret = sattr->show(s,page); 30 ret = sattr->show(s,page);
@@ -36,7 +37,7 @@ subsys_attr_store(struct kobject * kobj, struct attribute * attr,
36{ 37{
37 struct subsystem * s = to_subsys(kobj); 38 struct subsystem * s = to_subsys(kobj);
38 struct subsys_attribute * sattr = to_sattr(attr); 39 struct subsys_attribute * sattr = to_sattr(attr);
39 ssize_t ret = 0; 40 ssize_t ret = -EIO;
40 41
41 if (sattr->store) 42 if (sattr->store)
42 ret = sattr->store(s,page,count); 43 ret = sattr->store(s,page,count);
@@ -182,7 +183,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
182 return -ENOMEM; 183 return -ENOMEM;
183 184
184 if (count >= PAGE_SIZE) 185 if (count >= PAGE_SIZE)
185 count = PAGE_SIZE - 1; 186 count = PAGE_SIZE;
186 error = copy_from_user(buffer->page,buf,count); 187 error = copy_from_user(buffer->page,buf,count);
187 buffer->needs_read_fill = 1; 188 buffer->needs_read_fill = 1;
188 return error ? -EFAULT : count; 189 return error ? -EFAULT : count;
@@ -191,8 +192,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
191 192
192/** 193/**
193 * flush_write_buffer - push buffer to kobject. 194 * flush_write_buffer - push buffer to kobject.
194 * @file: file pointer. 195 * @dentry: dentry to the attribute
195 * @buffer: data buffer for file. 196 * @buffer: data buffer for file.
197 * @count: number of bytes
196 * 198 *
197 * Get the correct pointers for the kobject and the attribute we're 199 * Get the correct pointers for the kobject and the attribute we're
198 * dealing with, then call the store() method for the attribute, 200 * dealing with, then call the store() method for the attribute,
@@ -400,7 +402,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
400 int res = -ENOENT; 402 int res = -ENOENT;
401 403
402 down(&dir->d_inode->i_sem); 404 down(&dir->d_inode->i_sem);
403 victim = sysfs_get_dentry(dir, attr->name); 405 victim = lookup_one_len(attr->name, dir, strlen(attr->name));
404 if (!IS_ERR(victim)) { 406 if (!IS_ERR(victim)) {
405 /* make sure dentry is really there */ 407 /* make sure dentry is really there */
406 if (victim->d_inode && 408 if (victim->d_inode &&
@@ -443,7 +445,7 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
443 int res = -ENOENT; 445 int res = -ENOENT;
444 446
445 down(&dir->d_inode->i_sem); 447 down(&dir->d_inode->i_sem);
446 victim = sysfs_get_dentry(dir, attr->name); 448 victim = lookup_one_len(attr->name, dir, strlen(attr->name));
447 if (!IS_ERR(victim)) { 449 if (!IS_ERR(victim)) {
448 if (victim->d_inode && 450 if (victim->d_inode &&
449 (victim->d_parent->d_inode == dir->d_inode)) { 451 (victim->d_parent->d_inode == dir->d_inode)) {
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index f11ac5ea7021..122145b0895c 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -11,6 +11,7 @@
11#include <linux/kobject.h> 11#include <linux/kobject.h>
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/dcache.h> 13#include <linux/dcache.h>
14#include <linux/namei.h>
14#include <linux/err.h> 15#include <linux/err.h>
15#include "sysfs.h" 16#include "sysfs.h"
16 17
@@ -68,7 +69,8 @@ void sysfs_remove_group(struct kobject * kobj,
68 struct dentry * dir; 69 struct dentry * dir;
69 70
70 if (grp->name) 71 if (grp->name)
71 dir = sysfs_get_dentry(kobj->dentry,grp->name); 72 dir = lookup_one_len(grp->name, kobj->dentry,
73 strlen(grp->name));
72 else 74 else
73 dir = dget(kobj->dentry); 75 dir = dget(kobj->dentry);
74 76
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index aff7b2dfa8ee..8de13bafaa76 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -26,18 +26,107 @@ static struct backing_dev_info sysfs_backing_dev_info = {
26 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, 26 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
27}; 27};
28 28
29struct inode * sysfs_new_inode(mode_t mode) 29static struct inode_operations sysfs_inode_operations ={
30 .setattr = sysfs_setattr,
31};
32
33int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
34{
35 struct inode * inode = dentry->d_inode;
36 struct sysfs_dirent * sd = dentry->d_fsdata;
37 struct iattr * sd_iattr;
38 unsigned int ia_valid = iattr->ia_valid;
39 int error;
40
41 if (!sd)
42 return -EINVAL;
43
44 sd_iattr = sd->s_iattr;
45
46 error = inode_change_ok(inode, iattr);
47 if (error)
48 return error;
49
50 error = inode_setattr(inode, iattr);
51 if (error)
52 return error;
53
54 if (!sd_iattr) {
55 /* setting attributes for the first time, allocate now */
56 sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
57 if (!sd_iattr)
58 return -ENOMEM;
59 /* assign default attributes */
60 memset(sd_iattr, 0, sizeof(struct iattr));
61 sd_iattr->ia_mode = sd->s_mode;
62 sd_iattr->ia_uid = 0;
63 sd_iattr->ia_gid = 0;
64 sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
65 sd->s_iattr = sd_iattr;
66 }
67
68 /* attributes were changed atleast once in past */
69
70 if (ia_valid & ATTR_UID)
71 sd_iattr->ia_uid = iattr->ia_uid;
72 if (ia_valid & ATTR_GID)
73 sd_iattr->ia_gid = iattr->ia_gid;
74 if (ia_valid & ATTR_ATIME)
75 sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
76 inode->i_sb->s_time_gran);
77 if (ia_valid & ATTR_MTIME)
78 sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
79 inode->i_sb->s_time_gran);
80 if (ia_valid & ATTR_CTIME)
81 sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
82 inode->i_sb->s_time_gran);
83 if (ia_valid & ATTR_MODE) {
84 umode_t mode = iattr->ia_mode;
85
86 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
87 mode &= ~S_ISGID;
88 sd_iattr->ia_mode = mode;
89 }
90
91 return error;
92}
93
94static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
95{
96 inode->i_mode = mode;
97 inode->i_uid = 0;
98 inode->i_gid = 0;
99 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
100}
101
102static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
103{
104 inode->i_mode = iattr->ia_mode;
105 inode->i_uid = iattr->ia_uid;
106 inode->i_gid = iattr->ia_gid;
107 inode->i_atime = iattr->ia_atime;
108 inode->i_mtime = iattr->ia_mtime;
109 inode->i_ctime = iattr->ia_ctime;
110}
111
112struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
30{ 113{
31 struct inode * inode = new_inode(sysfs_sb); 114 struct inode * inode = new_inode(sysfs_sb);
32 if (inode) { 115 if (inode) {
33 inode->i_mode = mode;
34 inode->i_uid = 0;
35 inode->i_gid = 0;
36 inode->i_blksize = PAGE_CACHE_SIZE; 116 inode->i_blksize = PAGE_CACHE_SIZE;
37 inode->i_blocks = 0; 117 inode->i_blocks = 0;
38 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
39 inode->i_mapping->a_ops = &sysfs_aops; 118 inode->i_mapping->a_ops = &sysfs_aops;
40 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; 119 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
120 inode->i_op = &sysfs_inode_operations;
121
122 if (sd->s_iattr) {
123 /* sysfs_dirent has non-default attributes
124 * get them for the new inode from persistent copy
125 * in sysfs_dirent
126 */
127 set_inode_attr(inode, sd->s_iattr);
128 } else
129 set_default_inode_attr(inode, mode);
41 } 130 }
42 return inode; 131 return inode;
43} 132}
@@ -48,7 +137,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
48 struct inode * inode = NULL; 137 struct inode * inode = NULL;
49 if (dentry) { 138 if (dentry) {
50 if (!dentry->d_inode) { 139 if (!dentry->d_inode) {
51 if ((inode = sysfs_new_inode(mode))) { 140 struct sysfs_dirent * sd = dentry->d_fsdata;
141 if ((inode = sysfs_new_inode(mode, sd))) {
52 if (dentry->d_parent && dentry->d_parent->d_inode) { 142 if (dentry->d_parent && dentry->d_parent->d_inode) {
53 struct inode *p_inode = dentry->d_parent->d_inode; 143 struct inode *p_inode = dentry->d_parent->d_inode;
54 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 144 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
@@ -76,16 +166,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
76 return error; 166 return error;
77} 167}
78 168
79struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name)
80{
81 struct qstr qstr;
82
83 qstr.name = name;
84 qstr.len = strlen(name);
85 qstr.hash = full_name_hash(name,qstr.len);
86 return lookup_hash(&qstr,parent);
87}
88
89/* 169/*
90 * Get the name for corresponding element represented by the given sysfs_dirent 170 * Get the name for corresponding element represented by the given sysfs_dirent
91 */ 171 */
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 5c805bb1a4b7..f1117e885bd6 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -28,6 +28,7 @@ static struct sysfs_dirent sysfs_root = {
28 .s_children = LIST_HEAD_INIT(sysfs_root.s_children), 28 .s_children = LIST_HEAD_INIT(sysfs_root.s_children),
29 .s_element = NULL, 29 .s_element = NULL,
30 .s_type = SYSFS_ROOT, 30 .s_type = SYSFS_ROOT,
31 .s_iattr = NULL,
31}; 32};
32 33
33static int sysfs_fill_super(struct super_block *sb, void *data, int silent) 34static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -42,7 +43,8 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
42 sb->s_time_gran = 1; 43 sb->s_time_gran = 1;
43 sysfs_sb = sb; 44 sysfs_sb = sb;
44 45
45 inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); 46 inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
47 &sysfs_root);
46 if (inode) { 48 if (inode) {
47 inode->i_op = &sysfs_dir_inode_operations; 49 inode->i_op = &sysfs_dir_inode_operations;
48 inode->i_fop = &sysfs_dir_operations; 50 inode->i_fop = &sysfs_dir_operations;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index dfdf70174354..fae57c83a722 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -43,7 +43,7 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length)
43 } 43 }
44} 44}
45 45
46static int sysfs_add_link(struct dentry * parent, char * name, struct kobject * target) 46static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
47{ 47{
48 struct sysfs_dirent * parent_sd = parent->d_fsdata; 48 struct sysfs_dirent * parent_sd = parent->d_fsdata;
49 struct sysfs_symlink * sl; 49 struct sysfs_symlink * sl;
@@ -79,7 +79,7 @@ exit1:
79 * @target: object we're pointing to. 79 * @target: object we're pointing to.
80 * @name: name of the symlink. 80 * @name: name of the symlink.
81 */ 81 */
82int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name) 82int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
83{ 83{
84 struct dentry * dentry = kobj->dentry; 84 struct dentry * dentry = kobj->dentry;
85 int error = 0; 85 int error = 0;
@@ -99,13 +99,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam
99 * @name: name of the symlink to remove. 99 * @name: name of the symlink to remove.
100 */ 100 */
101 101
102void sysfs_remove_link(struct kobject * kobj, char * name) 102void sysfs_remove_link(struct kobject * kobj, const char * name)
103{ 103{
104 sysfs_hash_and_remove(kobj->dentry,name); 104 sysfs_hash_and_remove(kobj->dentry,name);
105} 105}
106 106
107static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, 107static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
108 char *path) 108 char *path)
109{ 109{
110 char * s; 110 char * s;
111 int depth, size; 111 int depth, size;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a8a24a0c0b3b..3f8953e0e5d0 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,12 +2,11 @@
2extern struct vfsmount * sysfs_mount; 2extern struct vfsmount * sysfs_mount;
3extern kmem_cache_t *sysfs_dir_cachep; 3extern kmem_cache_t *sysfs_dir_cachep;
4 4
5extern struct inode * sysfs_new_inode(mode_t mode); 5extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); 6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
7 7
8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, 8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
9 umode_t, int); 9 umode_t, int);
10extern struct dentry * sysfs_get_dentry(struct dentry *, const char *);
11 10
12extern int sysfs_add_file(struct dentry *, const struct attribute *, int); 11extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
13extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); 12extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
@@ -17,6 +16,7 @@ extern void sysfs_remove_subdir(struct dentry *);
17 16
18extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); 17extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
19extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); 18extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
19extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
20 20
21extern struct rw_semaphore sysfs_rename_sem; 21extern struct rw_semaphore sysfs_rename_sem;
22extern struct super_block * sysfs_sb; 22extern struct super_block * sysfs_sb;
@@ -75,6 +75,7 @@ static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
75 kobject_put(sl->target_kobj); 75 kobject_put(sl->target_kobj);
76 kfree(sl); 76 kfree(sl);
77 } 77 }
78 kfree(sd->s_iattr);
78 kmem_cache_free(sysfs_dir_cachep, sd); 79 kmem_cache_free(sysfs_dir_cachep, sd);
79} 80}
80 81
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index 457a8fe28575..85d8dbe843f1 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -46,7 +46,7 @@
46#endif 46#endif
47 47
48/* How many days come before each month (0-12). */ 48/* How many days come before each month (0-12). */
49const unsigned short int __mon_yday[2][13] = 49static const unsigned short int __mon_yday[2][13] =
50{ 50{
51 /* Normal years. */ 51 /* Normal years. */
52 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 52 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 9278e9aba9ba..a3a4b5aaf5d9 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -149,11 +149,12 @@ linvfs_unwritten_convert(
149 */ 149 */
150STATIC void 150STATIC void
151linvfs_unwritten_convert_direct( 151linvfs_unwritten_convert_direct(
152 struct inode *inode, 152 struct kiocb *iocb,
153 loff_t offset, 153 loff_t offset,
154 ssize_t size, 154 ssize_t size,
155 void *private) 155 void *private)
156{ 156{
157 struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
157 ASSERT(!private || inode == (struct inode *)private); 158 ASSERT(!private || inode == (struct inode *)private);
158 159
159 /* private indicates an unwritten extent lay beneath this IO */ 160 /* private indicates an unwritten extent lay beneath this IO */
@@ -886,7 +887,6 @@ xfs_page_state_convert(
886 SetPageUptodate(page); 887 SetPageUptodate(page);
887 888
888 if (startio) { 889 if (startio) {
889 WARN_ON(page_dirty);
890 xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty); 890 xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty);
891 } 891 }
892 892
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 997963e53622..df0cba239dd5 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -61,12 +61,13 @@
61 * File wide globals 61 * File wide globals
62 */ 62 */
63 63
64STATIC kmem_cache_t *pagebuf_cache; 64STATIC kmem_cache_t *pagebuf_zone;
65STATIC kmem_shaker_t pagebuf_shake; 65STATIC kmem_shaker_t pagebuf_shake;
66STATIC int pagebuf_daemon_wakeup(int, unsigned int); 66STATIC int xfsbufd_wakeup(int, unsigned int);
67STATIC void pagebuf_delwri_queue(xfs_buf_t *, int); 67STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
68STATIC struct workqueue_struct *pagebuf_logio_workqueue; 68
69STATIC struct workqueue_struct *pagebuf_dataio_workqueue; 69STATIC struct workqueue_struct *xfslogd_workqueue;
70STATIC struct workqueue_struct *xfsdatad_workqueue;
70 71
71/* 72/*
72 * Pagebuf debugging 73 * Pagebuf debugging
@@ -123,9 +124,9 @@ ktrace_t *pagebuf_trace_buf;
123 124
124 125
125#define pagebuf_allocate(flags) \ 126#define pagebuf_allocate(flags) \
126 kmem_zone_alloc(pagebuf_cache, pb_to_km(flags)) 127 kmem_zone_alloc(pagebuf_zone, pb_to_km(flags))
127#define pagebuf_deallocate(pb) \ 128#define pagebuf_deallocate(pb) \
128 kmem_zone_free(pagebuf_cache, (pb)); 129 kmem_zone_free(pagebuf_zone, (pb));
129 130
130/* 131/*
131 * Page Region interfaces. 132 * Page Region interfaces.
@@ -425,7 +426,7 @@ _pagebuf_lookup_pages(
425 __FUNCTION__, gfp_mask); 426 __FUNCTION__, gfp_mask);
426 427
427 XFS_STATS_INC(pb_page_retries); 428 XFS_STATS_INC(pb_page_retries);
428 pagebuf_daemon_wakeup(0, gfp_mask); 429 xfsbufd_wakeup(0, gfp_mask);
429 blk_congestion_wait(WRITE, HZ/50); 430 blk_congestion_wait(WRITE, HZ/50);
430 goto retry; 431 goto retry;
431 } 432 }
@@ -1136,8 +1137,8 @@ pagebuf_iodone(
1136 if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { 1137 if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
1137 if (schedule) { 1138 if (schedule) {
1138 INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); 1139 INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb);
1139 queue_work(dataio ? pagebuf_dataio_workqueue : 1140 queue_work(dataio ? xfsdatad_workqueue :
1140 pagebuf_logio_workqueue, &pb->pb_iodone_work); 1141 xfslogd_workqueue, &pb->pb_iodone_work);
1141 } else { 1142 } else {
1142 pagebuf_iodone_work(pb); 1143 pagebuf_iodone_work(pb);
1143 } 1144 }
@@ -1562,16 +1563,6 @@ xfs_free_buftarg(
1562 kmem_free(btp, sizeof(*btp)); 1563 kmem_free(btp, sizeof(*btp));
1563} 1564}
1564 1565
1565void
1566xfs_incore_relse(
1567 xfs_buftarg_t *btp,
1568 int delwri_only,
1569 int wait)
1570{
1571 invalidate_bdev(btp->pbr_bdev, 1);
1572 truncate_inode_pages(btp->pbr_mapping, 0LL);
1573}
1574
1575STATIC int 1566STATIC int
1576xfs_setsize_buftarg_flags( 1567xfs_setsize_buftarg_flags(
1577 xfs_buftarg_t *btp, 1568 xfs_buftarg_t *btp,
@@ -1742,27 +1733,27 @@ pagebuf_runall_queues(
1742} 1733}
1743 1734
1744/* Defines for pagebuf daemon */ 1735/* Defines for pagebuf daemon */
1745STATIC DECLARE_COMPLETION(pagebuf_daemon_done); 1736STATIC DECLARE_COMPLETION(xfsbufd_done);
1746STATIC struct task_struct *pagebuf_daemon_task; 1737STATIC struct task_struct *xfsbufd_task;
1747STATIC int pagebuf_daemon_active; 1738STATIC int xfsbufd_active;
1748STATIC int force_flush; 1739STATIC int xfsbufd_force_flush;
1749STATIC int force_sleep; 1740STATIC int xfsbufd_force_sleep;
1750 1741
1751STATIC int 1742STATIC int
1752pagebuf_daemon_wakeup( 1743xfsbufd_wakeup(
1753 int priority, 1744 int priority,
1754 unsigned int mask) 1745 unsigned int mask)
1755{ 1746{
1756 if (force_sleep) 1747 if (xfsbufd_force_sleep)
1757 return 0; 1748 return 0;
1758 force_flush = 1; 1749 xfsbufd_force_flush = 1;
1759 barrier(); 1750 barrier();
1760 wake_up_process(pagebuf_daemon_task); 1751 wake_up_process(xfsbufd_task);
1761 return 0; 1752 return 0;
1762} 1753}
1763 1754
1764STATIC int 1755STATIC int
1765pagebuf_daemon( 1756xfsbufd(
1766 void *data) 1757 void *data)
1767{ 1758{
1768 struct list_head tmp; 1759 struct list_head tmp;
@@ -1774,17 +1765,17 @@ pagebuf_daemon(
1774 daemonize("xfsbufd"); 1765 daemonize("xfsbufd");
1775 current->flags |= PF_MEMALLOC; 1766 current->flags |= PF_MEMALLOC;
1776 1767
1777 pagebuf_daemon_task = current; 1768 xfsbufd_task = current;
1778 pagebuf_daemon_active = 1; 1769 xfsbufd_active = 1;
1779 barrier(); 1770 barrier();
1780 1771
1781 INIT_LIST_HEAD(&tmp); 1772 INIT_LIST_HEAD(&tmp);
1782 do { 1773 do {
1783 if (unlikely(current->flags & PF_FREEZE)) { 1774 if (unlikely(freezing(current))) {
1784 force_sleep = 1; 1775 xfsbufd_force_sleep = 1;
1785 refrigerator(PF_FREEZE); 1776 refrigerator();
1786 } else { 1777 } else {
1787 force_sleep = 0; 1778 xfsbufd_force_sleep = 0;
1788 } 1779 }
1789 1780
1790 set_current_state(TASK_INTERRUPTIBLE); 1781 set_current_state(TASK_INTERRUPTIBLE);
@@ -1797,7 +1788,7 @@ pagebuf_daemon(
1797 ASSERT(pb->pb_flags & PBF_DELWRI); 1788 ASSERT(pb->pb_flags & PBF_DELWRI);
1798 1789
1799 if (!pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) { 1790 if (!pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) {
1800 if (!force_flush && 1791 if (!xfsbufd_force_flush &&
1801 time_before(jiffies, 1792 time_before(jiffies,
1802 pb->pb_queuetime + age)) { 1793 pb->pb_queuetime + age)) {
1803 pagebuf_unlock(pb); 1794 pagebuf_unlock(pb);
@@ -1824,10 +1815,10 @@ pagebuf_daemon(
1824 if (as_list_len > 0) 1815 if (as_list_len > 0)
1825 purge_addresses(); 1816 purge_addresses();
1826 1817
1827 force_flush = 0; 1818 xfsbufd_force_flush = 0;
1828 } while (pagebuf_daemon_active); 1819 } while (xfsbufd_active);
1829 1820
1830 complete_and_exit(&pagebuf_daemon_done, 0); 1821 complete_and_exit(&xfsbufd_done, 0);
1831} 1822}
1832 1823
1833/* 1824/*
@@ -1844,8 +1835,8 @@ xfs_flush_buftarg(
1844 xfs_buf_t *pb, *n; 1835 xfs_buf_t *pb, *n;
1845 int pincount = 0; 1836 int pincount = 0;
1846 1837
1847 pagebuf_runall_queues(pagebuf_dataio_workqueue); 1838 pagebuf_runall_queues(xfsdatad_workqueue);
1848 pagebuf_runall_queues(pagebuf_logio_workqueue); 1839 pagebuf_runall_queues(xfslogd_workqueue);
1849 1840
1850 INIT_LIST_HEAD(&tmp); 1841 INIT_LIST_HEAD(&tmp);
1851 spin_lock(&pbd_delwrite_lock); 1842 spin_lock(&pbd_delwrite_lock);
@@ -1898,43 +1889,43 @@ xfs_flush_buftarg(
1898} 1889}
1899 1890
1900STATIC int 1891STATIC int
1901pagebuf_daemon_start(void) 1892xfs_buf_daemons_start(void)
1902{ 1893{
1903 int rval; 1894 int error = -ENOMEM;
1904 1895
1905 pagebuf_logio_workqueue = create_workqueue("xfslogd"); 1896 xfslogd_workqueue = create_workqueue("xfslogd");
1906 if (!pagebuf_logio_workqueue) 1897 if (!xfslogd_workqueue)
1907 return -ENOMEM; 1898 goto out;
1908 1899
1909 pagebuf_dataio_workqueue = create_workqueue("xfsdatad"); 1900 xfsdatad_workqueue = create_workqueue("xfsdatad");
1910 if (!pagebuf_dataio_workqueue) { 1901 if (!xfsdatad_workqueue)
1911 destroy_workqueue(pagebuf_logio_workqueue); 1902 goto out_destroy_xfslogd_workqueue;
1912 return -ENOMEM;
1913 }
1914 1903
1915 rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES); 1904 error = kernel_thread(xfsbufd, NULL, CLONE_FS|CLONE_FILES);
1916 if (rval < 0) { 1905 if (error < 0)
1917 destroy_workqueue(pagebuf_logio_workqueue); 1906 goto out_destroy_xfsdatad_workqueue;
1918 destroy_workqueue(pagebuf_dataio_workqueue); 1907 return 0;
1919 }
1920 1908
1921 return rval; 1909 out_destroy_xfsdatad_workqueue:
1910 destroy_workqueue(xfsdatad_workqueue);
1911 out_destroy_xfslogd_workqueue:
1912 destroy_workqueue(xfslogd_workqueue);
1913 out:
1914 return error;
1922} 1915}
1923 1916
1924/* 1917/*
1925 * pagebuf_daemon_stop
1926 *
1927 * Note: do not mark as __exit, it is called from pagebuf_terminate. 1918 * Note: do not mark as __exit, it is called from pagebuf_terminate.
1928 */ 1919 */
1929STATIC void 1920STATIC void
1930pagebuf_daemon_stop(void) 1921xfs_buf_daemons_stop(void)
1931{ 1922{
1932 pagebuf_daemon_active = 0; 1923 xfsbufd_active = 0;
1933 barrier(); 1924 barrier();
1934 wait_for_completion(&pagebuf_daemon_done); 1925 wait_for_completion(&xfsbufd_done);
1935 1926
1936 destroy_workqueue(pagebuf_logio_workqueue); 1927 destroy_workqueue(xfslogd_workqueue);
1937 destroy_workqueue(pagebuf_dataio_workqueue); 1928 destroy_workqueue(xfsdatad_workqueue);
1938} 1929}
1939 1930
1940/* 1931/*
@@ -1944,27 +1935,37 @@ pagebuf_daemon_stop(void)
1944int __init 1935int __init
1945pagebuf_init(void) 1936pagebuf_init(void)
1946{ 1937{
1947 pagebuf_cache = kmem_cache_create("xfs_buf_t", sizeof(xfs_buf_t), 0, 1938 int error = -ENOMEM;
1948 SLAB_HWCACHE_ALIGN, NULL, NULL); 1939
1949 if (pagebuf_cache == NULL) { 1940 pagebuf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf");
1950 printk("XFS: couldn't init xfs_buf_t cache\n"); 1941 if (!pagebuf_zone)
1951 pagebuf_terminate(); 1942 goto out;
1952 return -ENOMEM;
1953 }
1954 1943
1955#ifdef PAGEBUF_TRACE 1944#ifdef PAGEBUF_TRACE
1956 pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP); 1945 pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
1957#endif 1946#endif
1958 1947
1959 pagebuf_daemon_start(); 1948 error = xfs_buf_daemons_start();
1949 if (error)
1950 goto out_free_buf_zone;
1960 1951
1961 pagebuf_shake = kmem_shake_register(pagebuf_daemon_wakeup); 1952 pagebuf_shake = kmem_shake_register(xfsbufd_wakeup);
1962 if (pagebuf_shake == NULL) { 1953 if (!pagebuf_shake) {
1963 pagebuf_terminate(); 1954 error = -ENOMEM;
1964 return -ENOMEM; 1955 goto out_stop_daemons;
1965 } 1956 }
1966 1957
1967 return 0; 1958 return 0;
1959
1960 out_stop_daemons:
1961 xfs_buf_daemons_stop();
1962 out_free_buf_zone:
1963#ifdef PAGEBUF_TRACE
1964 ktrace_free(pagebuf_trace_buf);
1965#endif
1966 kmem_zone_destroy(pagebuf_zone);
1967 out:
1968 return error;
1968} 1969}
1969 1970
1970 1971
@@ -1976,12 +1977,12 @@ pagebuf_init(void)
1976void 1977void
1977pagebuf_terminate(void) 1978pagebuf_terminate(void)
1978{ 1979{
1979 pagebuf_daemon_stop(); 1980 xfs_buf_daemons_stop();
1980 1981
1981#ifdef PAGEBUF_TRACE 1982#ifdef PAGEBUF_TRACE
1982 ktrace_free(pagebuf_trace_buf); 1983 ktrace_free(pagebuf_trace_buf);
1983#endif 1984#endif
1984 1985
1985 kmem_zone_destroy(pagebuf_cache); 1986 kmem_zone_destroy(pagebuf_zone);
1986 kmem_shake_deregister(pagebuf_shake); 1987 kmem_shake_deregister(pagebuf_shake);
1987} 1988}
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 74deed8e6d90..3f8f69a66aea 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -576,7 +576,6 @@ extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
576extern void xfs_free_buftarg(xfs_buftarg_t *, int); 576extern void xfs_free_buftarg(xfs_buftarg_t *, int);
577extern void xfs_wait_buftarg(xfs_buftarg_t *); 577extern void xfs_wait_buftarg(xfs_buftarg_t *);
578extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); 578extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
579extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
580extern int xfs_flush_buftarg(xfs_buftarg_t *, int); 579extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
581 580
582#define xfs_getsize_buftarg(buftarg) \ 581#define xfs_getsize_buftarg(buftarg) \
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index d0d412afd261..f1ce4323f56e 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -57,7 +57,9 @@
57#include <linux/smp_lock.h> 57#include <linux/smp_lock.h>
58 58
59static struct vm_operations_struct linvfs_file_vm_ops; 59static struct vm_operations_struct linvfs_file_vm_ops;
60 60#ifdef CONFIG_XFS_DMAPI
61static struct vm_operations_struct linvfs_dmapi_file_vm_ops;
62#endif
61 63
62STATIC inline ssize_t 64STATIC inline ssize_t
63__linvfs_read( 65__linvfs_read(
@@ -388,6 +390,14 @@ done:
388 return -error; 390 return -error;
389} 391}
390 392
393#ifdef CONFIG_XFS_DMAPI
394STATIC void
395linvfs_mmap_close(
396 struct vm_area_struct *vma)
397{
398 xfs_dm_mm_put(vma);
399}
400#endif /* CONFIG_XFS_DMAPI */
391 401
392STATIC int 402STATIC int
393linvfs_file_mmap( 403linvfs_file_mmap(
@@ -399,16 +409,19 @@ linvfs_file_mmap(
399 vattr_t va = { .va_mask = XFS_AT_UPDATIME }; 409 vattr_t va = { .va_mask = XFS_AT_UPDATIME };
400 int error; 410 int error;
401 411
412 vma->vm_ops = &linvfs_file_vm_ops;
413
402 if (vp->v_vfsp->vfs_flag & VFS_DMI) { 414 if (vp->v_vfsp->vfs_flag & VFS_DMI) {
403 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); 415 xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
404 416
405 error = -XFS_SEND_MMAP(mp, vma, 0); 417 error = -XFS_SEND_MMAP(mp, vma, 0);
406 if (error) 418 if (error)
407 return error; 419 return error;
420#ifdef CONFIG_XFS_DMAPI
421 vma->vm_ops = &linvfs_dmapi_file_vm_ops;
422#endif
408 } 423 }
409 424
410 vma->vm_ops = &linvfs_file_vm_ops;
411
412 VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error); 425 VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
413 if (!error) 426 if (!error)
414 vn_revalidate(vp); /* update Linux inode flags */ 427 vn_revalidate(vp); /* update Linux inode flags */
@@ -565,7 +578,7 @@ struct file_operations linvfs_file_operations = {
565 .sendfile = linvfs_sendfile, 578 .sendfile = linvfs_sendfile,
566 .unlocked_ioctl = linvfs_ioctl, 579 .unlocked_ioctl = linvfs_ioctl,
567#ifdef CONFIG_COMPAT 580#ifdef CONFIG_COMPAT
568 .compat_ioctl = xfs_compat_ioctl, 581 .compat_ioctl = linvfs_compat_ioctl,
569#endif 582#endif
570 .mmap = linvfs_file_mmap, 583 .mmap = linvfs_file_mmap,
571 .open = linvfs_open, 584 .open = linvfs_open,
@@ -587,7 +600,7 @@ struct file_operations linvfs_invis_file_operations = {
587 .sendfile = linvfs_sendfile, 600 .sendfile = linvfs_sendfile,
588 .unlocked_ioctl = linvfs_ioctl_invis, 601 .unlocked_ioctl = linvfs_ioctl_invis,
589#ifdef CONFIG_COMPAT 602#ifdef CONFIG_COMPAT
590 .compat_ioctl = xfs_compat_invis_ioctl, 603 .compat_ioctl = linvfs_compat_invis_ioctl,
591#endif 604#endif
592 .mmap = linvfs_file_mmap, 605 .mmap = linvfs_file_mmap,
593 .open = linvfs_open, 606 .open = linvfs_open,
@@ -600,13 +613,24 @@ struct file_operations linvfs_dir_operations = {
600 .read = generic_read_dir, 613 .read = generic_read_dir,
601 .readdir = linvfs_readdir, 614 .readdir = linvfs_readdir,
602 .unlocked_ioctl = linvfs_ioctl, 615 .unlocked_ioctl = linvfs_ioctl,
616#ifdef CONFIG_COMPAT
617 .compat_ioctl = linvfs_compat_ioctl,
618#endif
603 .fsync = linvfs_fsync, 619 .fsync = linvfs_fsync,
604}; 620};
605 621
606static struct vm_operations_struct linvfs_file_vm_ops = { 622static struct vm_operations_struct linvfs_file_vm_ops = {
607 .nopage = filemap_nopage, 623 .nopage = filemap_nopage,
608 .populate = filemap_populate, 624 .populate = filemap_populate,
625};
626
627#ifdef CONFIG_XFS_DMAPI
628static struct vm_operations_struct linvfs_dmapi_file_vm_ops = {
629 .close = linvfs_mmap_close,
630 .nopage = filemap_nopage,
631 .populate = filemap_populate,
609#ifdef HAVE_VMOP_MPROTECT 632#ifdef HAVE_VMOP_MPROTECT
610 .mprotect = linvfs_mprotect, 633 .mprotect = linvfs_mprotect,
611#endif 634#endif
612}; 635};
636#endif /* CONFIG_XFS_DMAPI */
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 69809eef8a54..05a447e51cc0 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1174,7 +1174,8 @@ xfs_ioc_xattr(
1174 1174
1175 switch (cmd) { 1175 switch (cmd) {
1176 case XFS_IOC_FSGETXATTR: { 1176 case XFS_IOC_FSGETXATTR: {
1177 va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS; 1177 va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
1178 XFS_AT_NEXTENTS | XFS_AT_PROJID;
1178 VOP_GETATTR(vp, &va, 0, NULL, error); 1179 VOP_GETATTR(vp, &va, 0, NULL, error);
1179 if (error) 1180 if (error)
1180 return -error; 1181 return -error;
@@ -1182,6 +1183,7 @@ xfs_ioc_xattr(
1182 fa.fsx_xflags = va.va_xflags; 1183 fa.fsx_xflags = va.va_xflags;
1183 fa.fsx_extsize = va.va_extsize; 1184 fa.fsx_extsize = va.va_extsize;
1184 fa.fsx_nextents = va.va_nextents; 1185 fa.fsx_nextents = va.va_nextents;
1186 fa.fsx_projid = va.va_projid;
1185 1187
1186 if (copy_to_user(arg, &fa, sizeof(fa))) 1188 if (copy_to_user(arg, &fa, sizeof(fa)))
1187 return -XFS_ERROR(EFAULT); 1189 return -XFS_ERROR(EFAULT);
@@ -1196,9 +1198,10 @@ xfs_ioc_xattr(
1196 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1198 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1197 attr_flags |= ATTR_NONBLOCK; 1199 attr_flags |= ATTR_NONBLOCK;
1198 1200
1199 va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE; 1201 va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
1200 va.va_xflags = fa.fsx_xflags; 1202 va.va_xflags = fa.fsx_xflags;
1201 va.va_extsize = fa.fsx_extsize; 1203 va.va_extsize = fa.fsx_extsize;
1204 va.va_projid = fa.fsx_projid;
1202 1205
1203 VOP_SETATTR(vp, &va, attr_flags, NULL, error); 1206 VOP_SETATTR(vp, &va, attr_flags, NULL, error);
1204 if (!error) 1207 if (!error)
@@ -1207,7 +1210,8 @@ xfs_ioc_xattr(
1207 } 1210 }
1208 1211
1209 case XFS_IOC_FSGETXATTRA: { 1212 case XFS_IOC_FSGETXATTRA: {
1210 va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS; 1213 va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
1214 XFS_AT_ANEXTENTS | XFS_AT_PROJID;
1211 VOP_GETATTR(vp, &va, 0, NULL, error); 1215 VOP_GETATTR(vp, &va, 0, NULL, error);
1212 if (error) 1216 if (error)
1213 return -error; 1217 return -error;
@@ -1215,6 +1219,7 @@ xfs_ioc_xattr(
1215 fa.fsx_xflags = va.va_xflags; 1219 fa.fsx_xflags = va.va_xflags;
1216 fa.fsx_extsize = va.va_extsize; 1220 fa.fsx_extsize = va.va_extsize;
1217 fa.fsx_nextents = va.va_anextents; 1221 fa.fsx_nextents = va.va_anextents;
1222 fa.fsx_projid = va.va_projid;
1218 1223
1219 if (copy_to_user(arg, &fa, sizeof(fa))) 1224 if (copy_to_user(arg, &fa, sizeof(fa)))
1220 return -XFS_ERROR(EFAULT); 1225 return -XFS_ERROR(EFAULT);
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 7a12c83184f5..0f8f1384eb36 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -58,8 +58,9 @@ typedef struct xfs_fsop_bulkreq32 {
58 __s32 ocount; /* output count pointer */ 58 __s32 ocount; /* output count pointer */
59} xfs_fsop_bulkreq32_t; 59} xfs_fsop_bulkreq32_t;
60 60
61static unsigned long 61STATIC unsigned long
62xfs_ioctl32_bulkstat(unsigned long arg) 62xfs_ioctl32_bulkstat(
63 unsigned long arg)
63{ 64{
64 xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg; 65 xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg;
65 xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p)); 66 xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p));
@@ -78,11 +79,11 @@ xfs_ioctl32_bulkstat(unsigned long arg)
78} 79}
79#endif 80#endif
80 81
81static long 82STATIC long
82__xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) 83__linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
83{ 84{
84 int error; 85 int error;
85 struct inode *inode = f->f_dentry->d_inode; 86 struct inode *inode = f->f_dentry->d_inode;
86 vnode_t *vp = LINVFS_GET_VP(inode); 87 vnode_t *vp = LINVFS_GET_VP(inode);
87 88
88 switch (cmd) { 89 switch (cmd) {
@@ -152,12 +153,20 @@ __xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
152 return error; 153 return error;
153} 154}
154 155
155long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg) 156long
157linvfs_compat_ioctl(
158 struct file *f,
159 unsigned cmd,
160 unsigned long arg)
156{ 161{
157 return __xfs_compat_ioctl(0, f, cmd, arg); 162 return __linvfs_compat_ioctl(0, f, cmd, arg);
158} 163}
159 164
160long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg) 165long
166linvfs_compat_invis_ioctl(
167 struct file *f,
168 unsigned cmd,
169 unsigned long arg)
161{ 170{
162 return __xfs_compat_ioctl(IO_INVIS, f, cmd, arg); 171 return __linvfs_compat_ioctl(IO_INVIS, f, cmd, arg);
163} 172}
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
index 779f69a48116..c874793a1dc9 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.h
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -30,5 +30,5 @@
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */ 31 */
32 32
33long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); 33long linvfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
34long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg); 34long linvfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg);
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 71bb41019a12..42dc5e4662ed 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -145,10 +145,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
145#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val 145#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
146#define xfs_rotorstep xfs_params.rotorstep.val 146#define xfs_rotorstep xfs_params.rotorstep.val
147 147
148#ifndef __smp_processor_id 148#ifndef raw_smp_processor_id
149#define __smp_processor_id() smp_processor_id() 149#define raw_smp_processor_id() smp_processor_id()
150#endif 150#endif
151#define current_cpu() __smp_processor_id() 151#define current_cpu() raw_smp_processor_id()
152#define current_pid() (current->pid) 152#define current_pid() (current->pid)
153#define current_fsuid(cred) (current->fsuid) 153#define current_fsuid(cred) (current->fsuid)
154#define current_fsgid(cred) (current->fsgid) 154#define current_fsgid(cred) (current->fsgid)
@@ -230,8 +230,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
230 * field (see the QCMD macro in quota.h). These macros help keep the 230 * field (see the QCMD macro in quota.h). These macros help keep the
231 * code portable - they are not visible from the syscall interface. 231 * code portable - they are not visible from the syscall interface.
232 */ 232 */
233#define Q_XSETGQLIM XQM_CMD(0x8) /* set groups disk limits */ 233#define Q_XSETGQLIM XQM_CMD(8) /* set groups disk limits */
234#define Q_XGETGQUOTA XQM_CMD(0x9) /* get groups disk limits */ 234#define Q_XGETGQUOTA XQM_CMD(9) /* get groups disk limits */
235#define Q_XSETPQLIM XQM_CMD(10) /* set projects disk limits */
236#define Q_XGETPQUOTA XQM_CMD(11) /* get projects disk limits */
235 237
236/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */ 238/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
237/* we may well need to fine-tune this if it ever becomes an issue. */ 239/* we may well need to fine-tune this if it ever becomes an issue. */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index aa9daaea6c34..acab58c48043 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -209,30 +209,6 @@ unlock:
209 return (-status); 209 return (-status);
210} 210}
211 211
212/*
213 * xfs_inval_cached_pages
214 *
215 * This routine is responsible for keeping direct I/O and buffered I/O
216 * somewhat coherent. From here we make sure that we're at least
217 * temporarily holding the inode I/O lock exclusively and then call
218 * the page cache to flush and invalidate any cached pages. If there
219 * are no cached pages this routine will be very quick.
220 */
221void
222xfs_inval_cached_pages(
223 vnode_t *vp,
224 xfs_iocore_t *io,
225 xfs_off_t offset,
226 int write,
227 int relock)
228{
229 if (VN_CACHED(vp)) {
230 xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
231 VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
232 }
233
234}
235
236ssize_t /* bytes read, or (-) error */ 212ssize_t /* bytes read, or (-) error */
237xfs_read( 213xfs_read(
238 bhv_desc_t *bdp, 214 bhv_desc_t *bdp,
@@ -304,10 +280,11 @@ xfs_read(
304 if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && 280 if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
305 !(ioflags & IO_INVIS)) { 281 !(ioflags & IO_INVIS)) {
306 vrwlock_t locktype = VRWLOCK_READ; 282 vrwlock_t locktype = VRWLOCK_READ;
283 int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
307 284
308 ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, 285 ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
309 BHV_TO_VNODE(bdp), *offset, size, 286 BHV_TO_VNODE(bdp), *offset, size,
310 FILP_DELAY_FLAG(file), &locktype); 287 dmflags, &locktype);
311 if (ret) { 288 if (ret) {
312 xfs_iunlock(ip, XFS_IOLOCK_SHARED); 289 xfs_iunlock(ip, XFS_IOLOCK_SHARED);
313 goto unlock_isem; 290 goto unlock_isem;
@@ -867,11 +844,15 @@ retry:
867 !(ioflags & IO_INVIS)) { 844 !(ioflags & IO_INVIS)) {
868 845
869 xfs_rwunlock(bdp, locktype); 846 xfs_rwunlock(bdp, locktype);
847 if (need_isem)
848 up(&inode->i_sem);
870 error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp, 849 error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
871 DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL, 850 DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
872 0, 0, 0); /* Delay flag intentionally unused */ 851 0, 0, 0); /* Delay flag intentionally unused */
873 if (error) 852 if (error)
874 goto out_unlock_isem; 853 goto out_nounlocks;
854 if (need_isem)
855 down(&inode->i_sem);
875 xfs_rwlock(bdp, locktype); 856 xfs_rwlock(bdp, locktype);
876 pos = xip->i_d.di_size; 857 pos = xip->i_d.di_size;
877 ret = 0; 858 ret = 0;
@@ -986,6 +967,7 @@ retry:
986 out_unlock_isem: 967 out_unlock_isem:
987 if (need_isem) 968 if (need_isem)
988 up(&inode->i_sem); 969 up(&inode->i_sem);
970 out_nounlocks:
989 return -error; 971 return -error;
990} 972}
991 973
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index d723e35254a0..f197a720e394 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -94,8 +94,6 @@ extern int xfs_bdstrat_cb(struct xfs_buf *);
94 94
95extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, 95extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
96 xfs_fsize_t, xfs_fsize_t); 96 xfs_fsize_t, xfs_fsize_t);
97extern void xfs_inval_cached_pages(struct vnode *, struct xfs_iocore *,
98 xfs_off_t, int, int);
99extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, 97extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
100 const struct iovec *, unsigned int, 98 const struct iovec *, unsigned int,
101 loff_t *, int, struct cred *); 99 loff_t *, int, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 53dc658cafa6..f6dd7de25927 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -66,7 +66,6 @@
66#include "xfs_buf_item.h" 66#include "xfs_buf_item.h"
67#include "xfs_utils.h" 67#include "xfs_utils.h"
68#include "xfs_version.h" 68#include "xfs_version.h"
69#include "xfs_ioctl32.h"
70 69
71#include <linux/namei.h> 70#include <linux/namei.h>
72#include <linux/init.h> 71#include <linux/init.h>
@@ -484,7 +483,7 @@ xfssyncd(
484 set_current_state(TASK_INTERRUPTIBLE); 483 set_current_state(TASK_INTERRUPTIBLE);
485 timeleft = schedule_timeout(timeleft); 484 timeleft = schedule_timeout(timeleft);
486 /* swsusp */ 485 /* swsusp */
487 try_to_freeze(PF_FREEZE); 486 try_to_freeze();
488 if (vfsp->vfs_flag & VFS_UMOUNT) 487 if (vfsp->vfs_flag & VFS_UMOUNT)
489 break; 488 break;
490 489
@@ -591,8 +590,10 @@ linvfs_sync_super(
591 int error; 590 int error;
592 int flags = SYNC_FSDATA; 591 int flags = SYNC_FSDATA;
593 592
594 if (wait) 593 if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
595 flags |= SYNC_WAIT; 594 flags = SYNC_QUIESCE;
595 else
596 flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
596 597
597 VFS_SYNC(vfsp, flags, NULL, error); 598 VFS_SYNC(vfsp, flags, NULL, error);
598 sb->s_dirt = 0; 599 sb->s_dirt = 0;
@@ -702,7 +703,8 @@ linvfs_getxquota(
702 struct vfs *vfsp = LINVFS_GET_VFS(sb); 703 struct vfs *vfsp = LINVFS_GET_VFS(sb);
703 int error, getmode; 704 int error, getmode;
704 705
705 getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA; 706 getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
707 ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
706 VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error); 708 VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
707 return -error; 709 return -error;
708} 710}
@@ -717,7 +719,8 @@ linvfs_setxquota(
717 struct vfs *vfsp = LINVFS_GET_VFS(sb); 719 struct vfs *vfsp = LINVFS_GET_VFS(sb);
718 int error, setmode; 720 int error, setmode;
719 721
720 setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM; 722 setmode = (type == USRQUOTA) ? Q_XSETQLIM :
723 ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
721 VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error); 724 VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
722 return -error; 725 return -error;
723} 726}
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 76493991578f..7ee1f714e9ba 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -107,6 +107,7 @@ typedef enum {
107#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ 107#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
108#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ 108#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
109#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ 109#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
110#define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */
110 111
111typedef int (*vfs_mount_t)(bhv_desc_t *, 112typedef int (*vfs_mount_t)(bhv_desc_t *,
112 struct xfs_mount_args *, struct cred *); 113 struct xfs_mount_args *, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index a832d165f24f..250cad54e892 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -411,13 +411,13 @@ vn_remove(
411/* 0 */ (void *)(__psint_t)(vk), \ 411/* 0 */ (void *)(__psint_t)(vk), \
412/* 1 */ (void *)(s), \ 412/* 1 */ (void *)(s), \
413/* 2 */ (void *)(__psint_t) line, \ 413/* 2 */ (void *)(__psint_t) line, \
414/* 3 */ (void *)(vn_count(vp)), \ 414/* 3 */ (void *)(__psint_t)(vn_count(vp)), \
415/* 4 */ (void *)(ra), \ 415/* 4 */ (void *)(ra), \
416/* 5 */ (void *)(__psunsigned_t)(vp)->v_flag, \ 416/* 5 */ (void *)(__psunsigned_t)(vp)->v_flag, \
417/* 6 */ (void *)(__psint_t)current_cpu(), \ 417/* 6 */ (void *)(__psint_t)current_cpu(), \
418/* 7 */ (void *)(__psint_t)current_pid(), \ 418/* 7 */ (void *)(__psint_t)current_pid(), \
419/* 8 */ (void *)__return_address, \ 419/* 8 */ (void *)__return_address, \
420/* 9 */ 0, 0, 0, 0, 0, 0, 0) 420/* 9 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL)
421 421
422/* 422/*
423 * Vnode tracing code. 423 * Vnode tracing code.
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 00466c3194ac..a6e57c647be4 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -426,7 +426,7 @@ typedef struct vattr {
426 u_long va_extsize; /* file extent size */ 426 u_long va_extsize; /* file extent size */
427 u_long va_nextents; /* number of extents in file */ 427 u_long va_nextents; /* number of extents in file */
428 u_long va_anextents; /* number of attr extents in file */ 428 u_long va_anextents; /* number of attr extents in file */
429 int va_projid; /* project id */ 429 prid_t va_projid; /* project id */
430} vattr_t; 430} vattr_t;
431 431
432/* 432/*
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 740d20d33187..46ce1e3ce1d6 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -101,7 +101,7 @@ int xfs_dqerror_mod = 33;
101 * is the d_id field. The idea is to fill in the entire q_core 101 * is the d_id field. The idea is to fill in the entire q_core
102 * when we read in the on disk dquot. 102 * when we read in the on disk dquot.
103 */ 103 */
104xfs_dquot_t * 104STATIC xfs_dquot_t *
105xfs_qm_dqinit( 105xfs_qm_dqinit(
106 xfs_mount_t *mp, 106 xfs_mount_t *mp,
107 xfs_dqid_t id, 107 xfs_dqid_t id,
@@ -286,7 +286,9 @@ xfs_qm_adjust_dqlimits(
286 * We also return 0 as the values of the timers in Q_GETQUOTA calls, when 286 * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
287 * enforcement's off. 287 * enforcement's off.
288 * In contrast, warnings are a little different in that they don't 288 * In contrast, warnings are a little different in that they don't
289 * 'automatically' get started when limits get exceeded. 289 * 'automatically' get started when limits get exceeded. They do
290 * get reset to zero, however, when we find the count to be under
291 * the soft limit (they are only ever set non-zero via userspace).
290 */ 292 */
291void 293void
292xfs_qm_adjust_dqtimers( 294xfs_qm_adjust_dqtimers(
@@ -315,6 +317,8 @@ xfs_qm_adjust_dqtimers(
315 INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) { 317 INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
316 INT_SET(d->d_btimer, ARCH_CONVERT, 318 INT_SET(d->d_btimer, ARCH_CONVERT,
317 get_seconds() + XFS_QI_BTIMELIMIT(mp)); 319 get_seconds() + XFS_QI_BTIMELIMIT(mp));
320 } else {
321 d->d_bwarns = 0;
318 } 322 }
319 } else { 323 } else {
320 if ((!d->d_blk_softlimit || 324 if ((!d->d_blk_softlimit ||
@@ -336,6 +340,8 @@ xfs_qm_adjust_dqtimers(
336 INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) { 340 INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
337 INT_SET(d->d_itimer, ARCH_CONVERT, 341 INT_SET(d->d_itimer, ARCH_CONVERT,
338 get_seconds() + XFS_QI_ITIMELIMIT(mp)); 342 get_seconds() + XFS_QI_ITIMELIMIT(mp));
343 } else {
344 d->d_iwarns = 0;
339 } 345 }
340 } else { 346 } else {
341 if ((!d->d_ino_softlimit || 347 if ((!d->d_ino_softlimit ||
@@ -357,6 +363,8 @@ xfs_qm_adjust_dqtimers(
357 INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) { 363 INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
358 INT_SET(d->d_rtbtimer, ARCH_CONVERT, 364 INT_SET(d->d_rtbtimer, ARCH_CONVERT,
359 get_seconds() + XFS_QI_RTBTIMELIMIT(mp)); 365 get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
366 } else {
367 d->d_rtbwarns = 0;
360 } 368 }
361 } else { 369 } else {
362 if ((!d->d_rtb_softlimit || 370 if ((!d->d_rtb_softlimit ||
@@ -371,68 +379,6 @@ xfs_qm_adjust_dqtimers(
371} 379}
372 380
373/* 381/*
374 * Increment or reset warnings of a given dquot.
375 */
376int
377xfs_qm_dqwarn(
378 xfs_disk_dquot_t *d,
379 uint flags)
380{
381 int warned;
382
383 /*
384 * root's limits are not real limits.
385 */
386 if (!d->d_id)
387 return (0);
388
389 warned = 0;
390 if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
391 (INT_GET(d->d_bcount, ARCH_CONVERT) >=
392 INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
393 if (flags & XFS_QMOPT_DOWARN) {
394 INT_MOD(d->d_bwarns, ARCH_CONVERT, +1);
395 warned++;
396 }
397 } else {
398 if (!d->d_blk_softlimit ||
399 (INT_GET(d->d_bcount, ARCH_CONVERT) <
400 INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
401 d->d_bwarns = 0;
402 }
403 }
404
405 if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 &&
406 (INT_GET(d->d_icount, ARCH_CONVERT) >=
407 INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
408 if (flags & XFS_QMOPT_DOWARN) {
409 INT_MOD(d->d_iwarns, ARCH_CONVERT, +1);
410 warned++;
411 }
412 } else {
413 if (!d->d_ino_softlimit ||
414 (INT_GET(d->d_icount, ARCH_CONVERT) <
415 INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
416 d->d_iwarns = 0;
417 }
418 }
419#ifdef QUOTADEBUG
420 if (INT_GET(d->d_iwarns, ARCH_CONVERT))
421 cmn_err(CE_DEBUG,
422 "--------@@Inode warnings running : %Lu >= %Lu",
423 INT_GET(d->d_icount, ARCH_CONVERT),
424 INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
425 if (INT_GET(d->d_bwarns, ARCH_CONVERT))
426 cmn_err(CE_DEBUG,
427 "--------@@Blks warnings running : %Lu >= %Lu",
428 INT_GET(d->d_bcount, ARCH_CONVERT),
429 INT_GET(d->d_blk_softlimit, ARCH_CONVERT));
430#endif
431 return (warned);
432}
433
434
435/*
436 * initialize a buffer full of dquots and log the whole thing 382 * initialize a buffer full of dquots and log the whole thing
437 */ 383 */
438STATIC void 384STATIC void
@@ -461,9 +407,9 @@ xfs_qm_init_dquot_blk(
461 for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++) 407 for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++)
462 xfs_qm_dqinit_core(curid, type, d); 408 xfs_qm_dqinit_core(curid, type, d);
463 xfs_trans_dquot_buf(tp, bp, 409 xfs_trans_dquot_buf(tp, bp,
464 type & XFS_DQ_USER ? 410 (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF :
465 XFS_BLI_UDQUOT_BUF : 411 ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF :
466 XFS_BLI_GDQUOT_BUF); 412 XFS_BLI_GDQUOT_BUF)));
467 xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1); 413 xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1);
468} 414}
469 415
@@ -544,8 +490,7 @@ xfs_qm_dqalloc(
544 * the entire thing. 490 * the entire thing.
545 */ 491 */
546 xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT), 492 xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
547 dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP), 493 dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
548 bp);
549 494
550 if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) { 495 if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
551 goto error1; 496 goto error1;
@@ -675,8 +620,7 @@ xfs_qm_dqtobp(
675 /* 620 /*
676 * A simple sanity check in case we got a corrupted dquot... 621 * A simple sanity check in case we got a corrupted dquot...
677 */ 622 */
678 if (xfs_qm_dqcheck(ddq, id, 623 if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
679 dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
680 flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN), 624 flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
681 "dqtobp")) { 625 "dqtobp")) {
682 if (!(flags & XFS_QMOPT_DQREPAIR)) { 626 if (!(flags & XFS_QMOPT_DQREPAIR)) {
@@ -953,8 +897,8 @@ int
953xfs_qm_dqget( 897xfs_qm_dqget(
954 xfs_mount_t *mp, 898 xfs_mount_t *mp,
955 xfs_inode_t *ip, /* locked inode (optional) */ 899 xfs_inode_t *ip, /* locked inode (optional) */
956 xfs_dqid_t id, /* gid or uid, depending on type */ 900 xfs_dqid_t id, /* uid/projid/gid depending on type */
957 uint type, /* UDQUOT or GDQUOT */ 901 uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
958 uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ 902 uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
959 xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ 903 xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
960{ 904{
@@ -965,6 +909,7 @@ xfs_qm_dqget(
965 909
966 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 910 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
967 if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) || 911 if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
912 (! XFS_IS_PQUOTA_ON(mp) && type == XFS_DQ_PROJ) ||
968 (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) { 913 (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
969 return (ESRCH); 914 return (ESRCH);
970 } 915 }
@@ -983,7 +928,9 @@ xfs_qm_dqget(
983 again: 928 again:
984 929
985#ifdef DEBUG 930#ifdef DEBUG
986 ASSERT(type == XFS_DQ_USER || type == XFS_DQ_GROUP); 931 ASSERT(type == XFS_DQ_USER ||
932 type == XFS_DQ_PROJ ||
933 type == XFS_DQ_GROUP);
987 if (ip) { 934 if (ip) {
988 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); 935 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
989 if (type == XFS_DQ_USER) 936 if (type == XFS_DQ_USER)
@@ -1306,8 +1253,8 @@ xfs_qm_dqflush(
1306 return (error); 1253 return (error);
1307 } 1254 }
1308 1255
1309 if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT), 0, XFS_QMOPT_DOWARN, 1256 if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT),
1310 "dqflush (incore copy)")) { 1257 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
1311 xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE); 1258 xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
1312 return XFS_ERROR(EIO); 1259 return XFS_ERROR(EIO);
1313 } 1260 }
@@ -1459,7 +1406,8 @@ xfs_dqlock2(
1459{ 1406{
1460 if (d1 && d2) { 1407 if (d1 && d2) {
1461 ASSERT(d1 != d2); 1408 ASSERT(d1 != d2);
1462 if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) > INT_GET(d2->q_core.d_id, ARCH_CONVERT)) { 1409 if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) >
1410 INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
1463 xfs_dqlock(d2); 1411 xfs_dqlock(d2);
1464 xfs_dqlock(d1); 1412 xfs_dqlock(d1);
1465 } else { 1413 } else {
@@ -1582,8 +1530,7 @@ xfs_qm_dqprint(xfs_dquot_t *dqp)
1582 cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------"); 1530 cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
1583 cmn_err(CE_DEBUG, "---- dquotID = %d", 1531 cmn_err(CE_DEBUG, "---- dquotID = %d",
1584 (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); 1532 (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT));
1585 cmn_err(CE_DEBUG, "---- type = %s", 1533 cmn_err(CE_DEBUG, "---- type = %s", DQFLAGTO_TYPESTR(dqp));
1586 XFS_QM_ISUDQ(dqp) ? "USR" : "GRP");
1587 cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount); 1534 cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount);
1588 cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno); 1535 cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno);
1589 cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset); 1536 cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset);
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 0c3fe3175baa..39175103c8e0 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -114,25 +114,18 @@ typedef struct xfs_dquot {
114#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) 114#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++)
115 115
116/* 116/*
117 * Quota Accounting flags 117 * Quota Accounting/Enforcement flags
118 */ 118 */
119#define XFS_ALL_QUOTA_ACCT (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT) 119#define XFS_ALL_QUOTA_ACCT \
120#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD) 120 (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
121#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD) 121#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
122#define XFS_ALL_QUOTA_ACTV (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE) 122#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
123#define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
124 XFS_GQUOTA_ACCT|XFS_GQUOTA_ENFD)
125 123
126#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT) 124#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
127#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
128#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
129
130/*
131 * Quota Limit Enforcement flags
132 */
133#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD) 125#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
134#define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD) 126#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
135#define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD) 127#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
128#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
136 129
137#ifdef DEBUG 130#ifdef DEBUG
138static inline int 131static inline int
@@ -167,6 +160,8 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
167#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) 160#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp))
168#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) 161#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY)
169#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) 162#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)
163#define XFS_QM_ISPDQ(dqp) ((dqp)->dq_flags & XFS_DQ_PROJ)
164#define XFS_QM_ISGDQ(dqp) ((dqp)->dq_flags & XFS_DQ_GROUP)
170#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo) 165#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo)
171#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \ 166#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \
172 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \ 167 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
@@ -174,7 +169,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
174 169
175#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \ 170#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
176 (XFS_IS_UQUOTA_ON((d)->q_mount)) : \ 171 (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
177 (XFS_IS_GQUOTA_ON((d)->q_mount)))) 172 (XFS_IS_OQUOTA_ON((d)->q_mount))))
178 173
179#ifdef XFS_DQUOT_TRACE 174#ifdef XFS_DQUOT_TRACE
180/* 175/*
@@ -211,7 +206,6 @@ extern void xfs_qm_adjust_dqtimers(xfs_mount_t *,
211 xfs_disk_dquot_t *); 206 xfs_disk_dquot_t *);
212extern void xfs_qm_adjust_dqlimits(xfs_mount_t *, 207extern void xfs_qm_adjust_dqlimits(xfs_mount_t *,
213 xfs_disk_dquot_t *); 208 xfs_disk_dquot_t *);
214extern int xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
215extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *, 209extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
216 xfs_dqid_t, uint, uint, xfs_dquot_t **); 210 xfs_dqid_t, uint, uint, xfs_dquot_t **);
217extern void xfs_qm_dqput(xfs_dquot_t *); 211extern void xfs_qm_dqput(xfs_dquot_t *);
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index a5425ee6e7bd..f5271b7b1e84 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -428,7 +428,7 @@ xfs_qm_dquot_logitem_committing(
428/* 428/*
429 * This is the ops vector for dquots 429 * This is the ops vector for dquots
430 */ 430 */
431struct xfs_item_ops xfs_dquot_item_ops = { 431STATIC struct xfs_item_ops xfs_dquot_item_ops = {
432 .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size, 432 .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size,
433 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 433 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
434 xfs_qm_dquot_logitem_format, 434 xfs_qm_dquot_logitem_format,
@@ -646,7 +646,7 @@ xfs_qm_qoffend_logitem_committing(xfs_qoff_logitem_t *qip, xfs_lsn_t commit_lsn)
646 return; 646 return;
647} 647}
648 648
649struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { 649STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
650 .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, 650 .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
651 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 651 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
652 xfs_qm_qoff_logitem_format, 652 xfs_qm_qoff_logitem_format,
@@ -669,7 +669,7 @@ struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
669/* 669/*
670 * This is the ops vector shared by all quotaoff-start log items. 670 * This is the ops vector shared by all quotaoff-start log items.
671 */ 671 */
672struct xfs_item_ops xfs_qm_qoff_logitem_ops = { 672STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
673 .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, 673 .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
674 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 674 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
675 xfs_qm_qoff_logitem_format, 675 xfs_qm_qoff_logitem_format,
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 89f2cd656ebf..f665ca8f9e96 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -81,12 +81,18 @@ struct xfs_qm *xfs_Gqm;
81 81
82kmem_zone_t *qm_dqzone; 82kmem_zone_t *qm_dqzone;
83kmem_zone_t *qm_dqtrxzone; 83kmem_zone_t *qm_dqtrxzone;
84kmem_shaker_t xfs_qm_shaker; 84STATIC kmem_shaker_t xfs_qm_shaker;
85 85
86STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); 86STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
87STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); 87STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
88 88
89STATIC void xfs_qm_freelist_init(xfs_frlist_t *);
90STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *);
91STATIC int xfs_qm_mplist_nowait(xfs_mount_t *);
92STATIC int xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
93
89STATIC int xfs_qm_init_quotainos(xfs_mount_t *); 94STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
95STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
90STATIC int xfs_qm_shake(int, unsigned int); 96STATIC int xfs_qm_shake(int, unsigned int);
91 97
92#ifdef DEBUG 98#ifdef DEBUG
@@ -184,7 +190,7 @@ xfs_Gqm_init(void)
184/* 190/*
185 * Destroy the global quota manager when its reference count goes to zero. 191 * Destroy the global quota manager when its reference count goes to zero.
186 */ 192 */
187void 193STATIC void
188xfs_qm_destroy( 194xfs_qm_destroy(
189 struct xfs_qm *xqm) 195 struct xfs_qm *xqm)
190{ 196{
@@ -304,9 +310,9 @@ xfs_qm_mount_quotainit(
304 uint flags) 310 uint flags)
305{ 311{
306 /* 312 /*
307 * User or group quotas has to be on. 313 * User, projects or group quotas has to be on.
308 */ 314 */
309 ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)); 315 ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
310 316
311 /* 317 /*
312 * Initialize the flags in the mount structure. From this point 318 * Initialize the flags in the mount structure. From this point
@@ -324,7 +330,11 @@ xfs_qm_mount_quotainit(
324 if (flags & XFSMNT_GQUOTA) { 330 if (flags & XFSMNT_GQUOTA) {
325 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE); 331 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
326 if (flags & XFSMNT_GQUOTAENF) 332 if (flags & XFSMNT_GQUOTAENF)
327 mp->m_qflags |= XFS_GQUOTA_ENFD; 333 mp->m_qflags |= XFS_OQUOTA_ENFD;
334 } else if (flags & XFSMNT_PQUOTA) {
335 mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
336 if (flags & XFSMNT_PQUOTAENF)
337 mp->m_qflags |= XFS_OQUOTA_ENFD;
328 } 338 }
329} 339}
330 340
@@ -357,11 +367,11 @@ xfs_qm_mount_quotas(
357 367
358 /* 368 /*
359 * If a file system had quotas running earlier, but decided to 369 * If a file system had quotas running earlier, but decided to
360 * mount without -o quota/uquota/gquota options, revoke the 370 * mount without -o uquota/pquota/gquota options, revoke the
361 * quotachecked license, and bail out. 371 * quotachecked license, and bail out.
362 */ 372 */
363 if (! XFS_IS_QUOTA_ON(mp) && 373 if (! XFS_IS_QUOTA_ON(mp) &&
364 (mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) { 374 (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT)) {
365 mp->m_qflags = 0; 375 mp->m_qflags = 0;
366 goto write_changes; 376 goto write_changes;
367 } 377 }
@@ -509,7 +519,7 @@ out:
509 * Flush all dquots of the given file system to disk. The dquots are 519 * Flush all dquots of the given file system to disk. The dquots are
510 * _not_ purged from memory here, just their data written to disk. 520 * _not_ purged from memory here, just their data written to disk.
511 */ 521 */
512int 522STATIC int
513xfs_qm_dqflush_all( 523xfs_qm_dqflush_all(
514 xfs_mount_t *mp, 524 xfs_mount_t *mp,
515 int flags) 525 int flags)
@@ -613,7 +623,7 @@ xfs_qm_detach_gdquots(
613STATIC int 623STATIC int
614xfs_qm_dqpurge_int( 624xfs_qm_dqpurge_int(
615 xfs_mount_t *mp, 625 xfs_mount_t *mp,
616 uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */ 626 uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */
617{ 627{
618 xfs_dquot_t *dqp; 628 xfs_dquot_t *dqp;
619 uint dqtype; 629 uint dqtype;
@@ -625,6 +635,7 @@ xfs_qm_dqpurge_int(
625 return (0); 635 return (0);
626 636
627 dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0; 637 dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0;
638 dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
628 dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0; 639 dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0;
629 640
630 xfs_qm_mplist_lock(mp); 641 xfs_qm_mplist_lock(mp);
@@ -734,11 +745,11 @@ xfs_qm_dqattach_one(
734 745
735 /* 746 /*
736 * udqhint is the i_udquot field in inode, and is non-NULL only 747 * udqhint is the i_udquot field in inode, and is non-NULL only
737 * when the type arg is XFS_DQ_GROUP. Its purpose is to save a 748 * when the type arg is group/project. Its purpose is to save a
738 * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside 749 * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
739 * the user dquot. 750 * the user dquot.
740 */ 751 */
741 ASSERT(!udqhint || type == XFS_DQ_GROUP); 752 ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
742 if (udqhint && !dolock) 753 if (udqhint && !dolock)
743 xfs_dqlock(udqhint); 754 xfs_dqlock(udqhint);
744 755
@@ -897,8 +908,8 @@ xfs_qm_dqattach_grouphint(
897 908
898 909
899/* 910/*
900 * Given a locked inode, attach dquot(s) to it, taking UQUOTAON / GQUOTAON 911 * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
901 * in to account. 912 * into account.
902 * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. 913 * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
903 * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty 914 * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
904 * much made this code a complete mess, but it has been pretty useful. 915 * much made this code a complete mess, but it has been pretty useful.
@@ -937,8 +948,13 @@ xfs_qm_dqattach(
937 nquotas++; 948 nquotas++;
938 } 949 }
939 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); 950 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
940 if (XFS_IS_GQUOTA_ON(mp)) { 951 if (XFS_IS_OQUOTA_ON(mp)) {
941 error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, 952 error = XFS_IS_GQUOTA_ON(mp) ?
953 xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
954 flags & XFS_QMOPT_DQALLOC,
955 flags & XFS_QMOPT_DQLOCK,
956 ip->i_udquot, &ip->i_gdquot) :
957 xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
942 flags & XFS_QMOPT_DQALLOC, 958 flags & XFS_QMOPT_DQALLOC,
943 flags & XFS_QMOPT_DQLOCK, 959 flags & XFS_QMOPT_DQLOCK,
944 ip->i_udquot, &ip->i_gdquot); 960 ip->i_udquot, &ip->i_gdquot);
@@ -989,7 +1005,7 @@ xfs_qm_dqattach(
989 } 1005 }
990 if (XFS_IS_UQUOTA_ON(mp)) 1006 if (XFS_IS_UQUOTA_ON(mp))
991 ASSERT(ip->i_udquot); 1007 ASSERT(ip->i_udquot);
992 if (XFS_IS_GQUOTA_ON(mp)) 1008 if (XFS_IS_OQUOTA_ON(mp))
993 ASSERT(ip->i_gdquot); 1009 ASSERT(ip->i_gdquot);
994 } 1010 }
995#endif 1011#endif
@@ -1018,13 +1034,13 @@ xfs_qm_dqdetach(
1018 1034
1019 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino); 1035 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
1020 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino); 1036 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
1021 if (ip->i_udquot)
1022 xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
1023 if (ip->i_udquot) { 1037 if (ip->i_udquot) {
1038 xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
1024 xfs_qm_dqrele(ip->i_udquot); 1039 xfs_qm_dqrele(ip->i_udquot);
1025 ip->i_udquot = NULL; 1040 ip->i_udquot = NULL;
1026 } 1041 }
1027 if (ip->i_gdquot) { 1042 if (ip->i_gdquot) {
1043 xfs_dqtrace_entry_ino(ip->i_gdquot, "DQDETTACH", ip);
1028 xfs_qm_dqrele(ip->i_gdquot); 1044 xfs_qm_dqrele(ip->i_gdquot);
1029 ip->i_gdquot = NULL; 1045 ip->i_gdquot = NULL;
1030 } 1046 }
@@ -1149,7 +1165,7 @@ xfs_qm_sync(
1149 * This initializes all the quota information that's kept in the 1165 * This initializes all the quota information that's kept in the
1150 * mount structure 1166 * mount structure
1151 */ 1167 */
1152int 1168STATIC int
1153xfs_qm_init_quotainfo( 1169xfs_qm_init_quotainfo(
1154 xfs_mount_t *mp) 1170 xfs_mount_t *mp)
1155{ 1171{
@@ -1202,8 +1218,9 @@ xfs_qm_init_quotainfo(
1202 * and group quotas, at least not at this point. 1218 * and group quotas, at least not at this point.
1203 */ 1219 */
1204 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0, 1220 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0,
1205 (XFS_IS_UQUOTA_RUNNING(mp)) ? 1221 XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER :
1206 XFS_DQ_USER : XFS_DQ_GROUP, 1222 (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
1223 XFS_DQ_PROJ),
1207 XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN, 1224 XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
1208 &dqp); 1225 &dqp);
1209 if (! error) { 1226 if (! error) {
@@ -1234,6 +1251,10 @@ xfs_qm_init_quotainfo(
1234 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ? 1251 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
1235 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) : 1252 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
1236 XFS_QM_IWARNLIMIT; 1253 XFS_QM_IWARNLIMIT;
1254 qinf->qi_rtbwarnlimit =
1255 INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) ?
1256 INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) :
1257 XFS_QM_RTBWARNLIMIT;
1237 qinf->qi_bhardlimit = 1258 qinf->qi_bhardlimit =
1238 INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT); 1259 INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
1239 qinf->qi_bsoftlimit = 1260 qinf->qi_bsoftlimit =
@@ -1259,6 +1280,7 @@ xfs_qm_init_quotainfo(
1259 qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT; 1280 qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT;
1260 qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT; 1281 qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT;
1261 qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT; 1282 qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT;
1283 qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
1262 } 1284 }
1263 1285
1264 return (0); 1286 return (0);
@@ -1366,13 +1388,20 @@ xfs_qm_dqget_noattach(
1366 ASSERT(udqp); 1388 ASSERT(udqp);
1367 } 1389 }
1368 1390
1369 if (XFS_IS_GQUOTA_ON(mp)) { 1391 if (XFS_IS_OQUOTA_ON(mp)) {
1370 ASSERT(ip->i_gdquot == NULL); 1392 ASSERT(ip->i_gdquot == NULL);
1371 if (udqp) 1393 if (udqp)
1372 xfs_dqunlock(udqp); 1394 xfs_dqunlock(udqp);
1373 if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_gid, XFS_DQ_GROUP, 1395 error = XFS_IS_GQUOTA_ON(mp) ?
1374 XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN, 1396 xfs_qm_dqget(mp, ip,
1375 &gdqp))) { 1397 ip->i_d.di_gid, XFS_DQ_GROUP,
1398 XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
1399 &gdqp) :
1400 xfs_qm_dqget(mp, ip,
1401 ip->i_d.di_projid, XFS_DQ_PROJ,
1402 XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
1403 &gdqp);
1404 if (error) {
1376 if (udqp) 1405 if (udqp)
1377 xfs_qm_dqrele(udqp); 1406 xfs_qm_dqrele(udqp);
1378 ASSERT(error != ESRCH); 1407 ASSERT(error != ESRCH);
@@ -1521,8 +1550,10 @@ xfs_qm_reset_dqcounts(
1521 INT_SET(ddq->d_rtbcount, ARCH_CONVERT, 0ULL); 1550 INT_SET(ddq->d_rtbcount, ARCH_CONVERT, 0ULL);
1522 INT_SET(ddq->d_btimer, ARCH_CONVERT, (time_t)0); 1551 INT_SET(ddq->d_btimer, ARCH_CONVERT, (time_t)0);
1523 INT_SET(ddq->d_itimer, ARCH_CONVERT, (time_t)0); 1552 INT_SET(ddq->d_itimer, ARCH_CONVERT, (time_t)0);
1553 INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, (time_t)0);
1524 INT_SET(ddq->d_bwarns, ARCH_CONVERT, 0UL); 1554 INT_SET(ddq->d_bwarns, ARCH_CONVERT, 0UL);
1525 INT_SET(ddq->d_iwarns, ARCH_CONVERT, 0UL); 1555 INT_SET(ddq->d_iwarns, ARCH_CONVERT, 0UL);
1556 INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, 0UL);
1526 ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1); 1557 ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
1527 } 1558 }
1528 1559
@@ -1541,11 +1572,14 @@ xfs_qm_dqiter_bufs(
1541 int error; 1572 int error;
1542 int notcommitted; 1573 int notcommitted;
1543 int incr; 1574 int incr;
1575 int type;
1544 1576
1545 ASSERT(blkcnt > 0); 1577 ASSERT(blkcnt > 0);
1546 notcommitted = 0; 1578 notcommitted = 0;
1547 incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ? 1579 incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ?
1548 XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt; 1580 XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;
1581 type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :
1582 (flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);
1549 error = 0; 1583 error = 0;
1550 1584
1551 /* 1585 /*
@@ -1564,9 +1598,7 @@ xfs_qm_dqiter_bufs(
1564 if (error) 1598 if (error)
1565 break; 1599 break;
1566 1600
1567 (void) xfs_qm_reset_dqcounts(mp, bp, firstid, 1601 (void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
1568 flags & XFS_QMOPT_UQUOTA ?
1569 XFS_DQ_USER : XFS_DQ_GROUP);
1570 xfs_bdwrite(mp, bp); 1602 xfs_bdwrite(mp, bp);
1571 /* 1603 /*
1572 * goto the next block. 1604 * goto the next block.
@@ -1578,7 +1610,7 @@ xfs_qm_dqiter_bufs(
1578} 1610}
1579 1611
1580/* 1612/*
1581 * Iterate over all allocated USR/GRP dquots in the system, calling a 1613 * Iterate over all allocated USR/GRP/PRJ dquots in the system, calling a
1582 * caller supplied function for every chunk of dquots that we find. 1614 * caller supplied function for every chunk of dquots that we find.
1583 */ 1615 */
1584STATIC int 1616STATIC int
@@ -1849,7 +1881,7 @@ xfs_qm_dqusage_adjust(
1849 xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks); 1881 xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
1850 xfs_qm_dqput(udqp); 1882 xfs_qm_dqput(udqp);
1851 } 1883 }
1852 if (XFS_IS_GQUOTA_ON(mp)) { 1884 if (XFS_IS_OQUOTA_ON(mp)) {
1853 ASSERT(gdqp); 1885 ASSERT(gdqp);
1854 xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks); 1886 xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
1855 xfs_qm_dqput(gdqp); 1887 xfs_qm_dqput(gdqp);
@@ -1898,7 +1930,7 @@ xfs_qm_quotacheck(
1898 cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname); 1930 cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
1899 1931
1900 /* 1932 /*
1901 * First we go thru all the dquots on disk, USR and GRP, and reset 1933 * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
1902 * their counters to zero. We need a clean slate. 1934 * their counters to zero. We need a clean slate.
1903 * We don't log our changes till later. 1935 * We don't log our changes till later.
1904 */ 1936 */
@@ -1909,9 +1941,10 @@ xfs_qm_quotacheck(
1909 } 1941 }
1910 1942
1911 if ((gip = XFS_QI_GQIP(mp))) { 1943 if ((gip = XFS_QI_GQIP(mp))) {
1912 if ((error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA))) 1944 if ((error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
1945 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA)))
1913 goto error_return; 1946 goto error_return;
1914 flags |= XFS_GQUOTA_CHKD; 1947 flags |= XFS_OQUOTA_CHKD;
1915 } 1948 }
1916 1949
1917 do { 1950 do {
@@ -1938,7 +1971,7 @@ xfs_qm_quotacheck(
1938 if (error) { 1971 if (error) {
1939 xfs_qm_dqpurge_all(mp, 1972 xfs_qm_dqpurge_all(mp,
1940 XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA| 1973 XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA|
1941 XFS_QMOPT_QUOTAOFF); 1974 XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF);
1942 goto error_return; 1975 goto error_return;
1943 } 1976 }
1944 /* 1977 /*
@@ -1961,7 +1994,7 @@ xfs_qm_quotacheck(
1961 * quotachecked status, since we won't be doing accounting for 1994 * quotachecked status, since we won't be doing accounting for
1962 * that type anymore. 1995 * that type anymore.
1963 */ 1996 */
1964 mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_UQUOTA_CHKD); 1997 mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
1965 mp->m_qflags |= flags; 1998 mp->m_qflags |= flags;
1966 1999
1967 XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++"); 2000 XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++");
@@ -2013,7 +2046,7 @@ xfs_qm_init_quotainos(
2013 0, 0, &uip, 0))) 2046 0, 0, &uip, 0)))
2014 return XFS_ERROR(error); 2047 return XFS_ERROR(error);
2015 } 2048 }
2016 if (XFS_IS_GQUOTA_ON(mp) && 2049 if (XFS_IS_OQUOTA_ON(mp) &&
2017 mp->m_sb.sb_gquotino != NULLFSINO) { 2050 mp->m_sb.sb_gquotino != NULLFSINO) {
2018 ASSERT(mp->m_sb.sb_gquotino > 0); 2051 ASSERT(mp->m_sb.sb_gquotino > 0);
2019 if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 2052 if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -2043,10 +2076,12 @@ xfs_qm_init_quotainos(
2043 2076
2044 flags &= ~XFS_QMOPT_SBVERSION; 2077 flags &= ~XFS_QMOPT_SBVERSION;
2045 } 2078 }
2046 if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) { 2079 if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
2047 if ((error = xfs_qm_qino_alloc(mp, &gip, 2080 flags |= (XFS_IS_GQUOTA_ON(mp) ?
2048 sbflags | XFS_SB_GQUOTINO, 2081 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
2049 flags | XFS_QMOPT_GQUOTA))) { 2082 error = xfs_qm_qino_alloc(mp, &gip,
2083 sbflags | XFS_SB_GQUOTINO, flags);
2084 if (error) {
2050 if (uip) 2085 if (uip)
2051 VN_RELE(XFS_ITOV(uip)); 2086 VN_RELE(XFS_ITOV(uip));
2052 2087
@@ -2452,6 +2487,7 @@ xfs_qm_vop_dqalloc(
2452 xfs_inode_t *ip, 2487 xfs_inode_t *ip,
2453 uid_t uid, 2488 uid_t uid,
2454 gid_t gid, 2489 gid_t gid,
2490 prid_t prid,
2455 uint flags, 2491 uint flags,
2456 xfs_dquot_t **O_udqpp, 2492 xfs_dquot_t **O_udqpp,
2457 xfs_dquot_t **O_gdqpp) 2493 xfs_dquot_t **O_gdqpp)
@@ -2483,8 +2519,7 @@ xfs_qm_vop_dqalloc(
2483 } 2519 }
2484 2520
2485 uq = gq = NULL; 2521 uq = gq = NULL;
2486 if ((flags & XFS_QMOPT_UQUOTA) && 2522 if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
2487 XFS_IS_UQUOTA_ON(mp)) {
2488 if (ip->i_d.di_uid != uid) { 2523 if (ip->i_d.di_uid != uid) {
2489 /* 2524 /*
2490 * What we need is the dquot that has this uid, and 2525 * What we need is the dquot that has this uid, and
@@ -2522,8 +2557,7 @@ xfs_qm_vop_dqalloc(
2522 xfs_dqunlock(uq); 2557 xfs_dqunlock(uq);
2523 } 2558 }
2524 } 2559 }
2525 if ((flags & XFS_QMOPT_GQUOTA) && 2560 if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
2526 XFS_IS_GQUOTA_ON(mp)) {
2527 if (ip->i_d.di_gid != gid) { 2561 if (ip->i_d.di_gid != gid) {
2528 xfs_iunlock(ip, lockflags); 2562 xfs_iunlock(ip, lockflags);
2529 if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid, 2563 if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
@@ -2546,6 +2580,29 @@ xfs_qm_vop_dqalloc(
2546 XFS_DQHOLD(gq); 2580 XFS_DQHOLD(gq);
2547 xfs_dqunlock(gq); 2581 xfs_dqunlock(gq);
2548 } 2582 }
2583 } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
2584 if (ip->i_d.di_projid != prid) {
2585 xfs_iunlock(ip, lockflags);
2586 if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
2587 XFS_DQ_PROJ,
2588 XFS_QMOPT_DQALLOC |
2589 XFS_QMOPT_DOWARN,
2590 &gq))) {
2591 if (uq)
2592 xfs_qm_dqrele(uq);
2593 ASSERT(error != ENOENT);
2594 return (error);
2595 }
2596 xfs_dqunlock(gq);
2597 lockflags = XFS_ILOCK_SHARED;
2598 xfs_ilock(ip, lockflags);
2599 } else {
2600 ASSERT(ip->i_gdquot);
2601 gq = ip->i_gdquot;
2602 xfs_dqlock(gq);
2603 XFS_DQHOLD(gq);
2604 xfs_dqunlock(gq);
2605 }
2549 } 2606 }
2550 if (uq) 2607 if (uq)
2551 xfs_dqtrace_entry_ino(uq, "DQALLOC", ip); 2608 xfs_dqtrace_entry_ino(uq, "DQALLOC", ip);
@@ -2574,6 +2631,9 @@ xfs_qm_vop_chown(
2574 xfs_dquot_t *newdq) 2631 xfs_dquot_t *newdq)
2575{ 2632{
2576 xfs_dquot_t *prevdq; 2633 xfs_dquot_t *prevdq;
2634 uint bfield = XFS_IS_REALTIME_INODE(ip) ?
2635 XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
2636
2577 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); 2637 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
2578 ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); 2638 ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
2579 2639
@@ -2582,20 +2642,12 @@ xfs_qm_vop_chown(
2582 ASSERT(prevdq); 2642 ASSERT(prevdq);
2583 ASSERT(prevdq != newdq); 2643 ASSERT(prevdq != newdq);
2584 2644
2585 xfs_trans_mod_dquot(tp, prevdq, 2645 xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_d.di_nblocks));
2586 XFS_TRANS_DQ_BCOUNT, 2646 xfs_trans_mod_dquot(tp, prevdq, XFS_TRANS_DQ_ICOUNT, -1);
2587 -(ip->i_d.di_nblocks));
2588 xfs_trans_mod_dquot(tp, prevdq,
2589 XFS_TRANS_DQ_ICOUNT,
2590 -1);
2591 2647
2592 /* the sparkling new dquot */ 2648 /* the sparkling new dquot */
2593 xfs_trans_mod_dquot(tp, newdq, 2649 xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks);
2594 XFS_TRANS_DQ_BCOUNT, 2650 xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
2595 ip->i_d.di_nblocks);
2596 xfs_trans_mod_dquot(tp, newdq,
2597 XFS_TRANS_DQ_ICOUNT,
2598 1);
2599 2651
2600 /* 2652 /*
2601 * Take an extra reference, because the inode 2653 * Take an extra reference, because the inode
@@ -2611,7 +2663,7 @@ xfs_qm_vop_chown(
2611} 2663}
2612 2664
2613/* 2665/*
2614 * Quota reservations for setattr(AT_UID|AT_GID). 2666 * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
2615 */ 2667 */
2616int 2668int
2617xfs_qm_vop_chown_reserve( 2669xfs_qm_vop_chown_reserve(
@@ -2623,7 +2675,7 @@ xfs_qm_vop_chown_reserve(
2623{ 2675{
2624 int error; 2676 int error;
2625 xfs_mount_t *mp; 2677 xfs_mount_t *mp;
2626 uint delblks; 2678 uint delblks, blkflags;
2627 xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; 2679 xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
2628 2680
2629 ASSERT(XFS_ISLOCKED_INODE(ip)); 2681 ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2632,6 +2684,8 @@ xfs_qm_vop_chown_reserve(
2632 2684
2633 delblks = ip->i_delayed_blks; 2685 delblks = ip->i_delayed_blks;
2634 delblksudq = delblksgdq = unresudq = unresgdq = NULL; 2686 delblksudq = delblksgdq = unresudq = unresgdq = NULL;
2687 blkflags = XFS_IS_REALTIME_INODE(ip) ?
2688 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
2635 2689
2636 if (XFS_IS_UQUOTA_ON(mp) && udqp && 2690 if (XFS_IS_UQUOTA_ON(mp) && udqp &&
2637 ip->i_d.di_uid != (uid_t)INT_GET(udqp->q_core.d_id, ARCH_CONVERT)) { 2691 ip->i_d.di_uid != (uid_t)INT_GET(udqp->q_core.d_id, ARCH_CONVERT)) {
@@ -2646,18 +2700,22 @@ xfs_qm_vop_chown_reserve(
2646 unresudq = ip->i_udquot; 2700 unresudq = ip->i_udquot;
2647 } 2701 }
2648 } 2702 }
2649 if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp && 2703 if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
2650 ip->i_d.di_gid != INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) { 2704 if ((XFS_IS_GQUOTA_ON(ip->i_mount) && ip->i_d.di_gid !=
2651 delblksgdq = gdqp; 2705 INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) ||
2652 if (delblks) { 2706 (XFS_IS_PQUOTA_ON(ip->i_mount) && ip->i_d.di_projid !=
2653 ASSERT(ip->i_gdquot); 2707 INT_GET(gdqp->q_core.d_id, ARCH_CONVERT))) {
2654 unresgdq = ip->i_gdquot; 2708 delblksgdq = gdqp;
2709 if (delblks) {
2710 ASSERT(ip->i_gdquot);
2711 unresgdq = ip->i_gdquot;
2712 }
2655 } 2713 }
2656 } 2714 }
2657 2715
2658 if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 2716 if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
2659 delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, 2717 delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
2660 flags | XFS_QMOPT_RES_REGBLKS))) 2718 flags | blkflags)))
2661 return (error); 2719 return (error);
2662 2720
2663 /* 2721 /*
@@ -2674,11 +2732,11 @@ xfs_qm_vop_chown_reserve(
2674 ASSERT(unresudq || unresgdq); 2732 ASSERT(unresudq || unresgdq);
2675 if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2733 if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
2676 delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, 2734 delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
2677 flags | XFS_QMOPT_RES_REGBLKS))) 2735 flags | blkflags)))
2678 return (error); 2736 return (error);
2679 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2737 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
2680 unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, 2738 unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
2681 XFS_QMOPT_RES_REGBLKS); 2739 blkflags);
2682 } 2740 }
2683 2741
2684 return (0); 2742 return (0);
@@ -2751,7 +2809,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
2751} 2809}
2752 2810
2753/* ------------- list stuff -----------------*/ 2811/* ------------- list stuff -----------------*/
2754void 2812STATIC void
2755xfs_qm_freelist_init(xfs_frlist_t *ql) 2813xfs_qm_freelist_init(xfs_frlist_t *ql)
2756{ 2814{
2757 ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql; 2815 ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql;
@@ -2760,7 +2818,7 @@ xfs_qm_freelist_init(xfs_frlist_t *ql)
2760 ql->qh_nelems = 0; 2818 ql->qh_nelems = 0;
2761} 2819}
2762 2820
2763void 2821STATIC void
2764xfs_qm_freelist_destroy(xfs_frlist_t *ql) 2822xfs_qm_freelist_destroy(xfs_frlist_t *ql)
2765{ 2823{
2766 xfs_dquot_t *dqp, *nextdqp; 2824 xfs_dquot_t *dqp, *nextdqp;
@@ -2786,7 +2844,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql)
2786 ASSERT(ql->qh_nelems == 0); 2844 ASSERT(ql->qh_nelems == 0);
2787} 2845}
2788 2846
2789void 2847STATIC void
2790xfs_qm_freelist_insert(xfs_frlist_t *ql, xfs_dquot_t *dq) 2848xfs_qm_freelist_insert(xfs_frlist_t *ql, xfs_dquot_t *dq)
2791{ 2849{
2792 dq->dq_flnext = ql->qh_next; 2850 dq->dq_flnext = ql->qh_next;
@@ -2816,7 +2874,7 @@ xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq)
2816 xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq); 2874 xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
2817} 2875}
2818 2876
2819int 2877STATIC int
2820xfs_qm_dqhashlock_nowait( 2878xfs_qm_dqhashlock_nowait(
2821 xfs_dquot_t *dqp) 2879 xfs_dquot_t *dqp)
2822{ 2880{
@@ -2836,7 +2894,7 @@ xfs_qm_freelist_lock_nowait(
2836 return (locked); 2894 return (locked);
2837} 2895}
2838 2896
2839int 2897STATIC int
2840xfs_qm_mplist_nowait( 2898xfs_qm_mplist_nowait(
2841 xfs_mount_t *mp) 2899 xfs_mount_t *mp)
2842{ 2900{
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index dcf1a7a831d8..b03eecf3b6cb 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -133,8 +133,9 @@ typedef struct xfs_quotainfo {
133 time_t qi_btimelimit; /* limit for blks timer */ 133 time_t qi_btimelimit; /* limit for blks timer */
134 time_t qi_itimelimit; /* limit for inodes timer */ 134 time_t qi_itimelimit; /* limit for inodes timer */
135 time_t qi_rtbtimelimit;/* limit for rt blks timer */ 135 time_t qi_rtbtimelimit;/* limit for rt blks timer */
136 xfs_qwarncnt_t qi_bwarnlimit; /* limit for num warnings */ 136 xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
137 xfs_qwarncnt_t qi_iwarnlimit; /* limit for num warnings */ 137 xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
138 xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
138 mutex_t qi_quotaofflock;/* to serialize quotaoff */ 139 mutex_t qi_quotaofflock;/* to serialize quotaoff */
139 xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */ 140 xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
140 uint qi_dqperchunk; /* # ondisk dqs in above chunk */ 141 uint qi_dqperchunk; /* # ondisk dqs in above chunk */
@@ -176,6 +177,7 @@ typedef struct xfs_dquot_acct {
176 177
177#define XFS_QM_BWARNLIMIT 5 178#define XFS_QM_BWARNLIMIT 5
178#define XFS_QM_IWARNLIMIT 5 179#define XFS_QM_IWARNLIMIT 5
180#define XFS_QM_RTBWARNLIMIT 5
179 181
180#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock, PINOD)) 182#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock, PINOD))
181#define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock)) 183#define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock))
@@ -184,7 +186,6 @@ typedef struct xfs_dquot_acct {
184 186
185extern void xfs_mount_reset_sbqflags(xfs_mount_t *); 187extern void xfs_mount_reset_sbqflags(xfs_mount_t *);
186 188
187extern int xfs_qm_init_quotainfo(xfs_mount_t *);
188extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); 189extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
189extern int xfs_qm_mount_quotas(xfs_mount_t *, int); 190extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
190extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint); 191extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
@@ -203,7 +204,7 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
203 204
204/* vop stuff */ 205/* vop stuff */
205extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *, 206extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
206 uid_t, gid_t, uint, 207 uid_t, gid_t, prid_t, uint,
207 xfs_dquot_t **, xfs_dquot_t **); 208 xfs_dquot_t **, xfs_dquot_t **);
208extern void xfs_qm_vop_dqattach_and_dqmod_newinode( 209extern void xfs_qm_vop_dqattach_and_dqmod_newinode(
209 xfs_trans_t *, xfs_inode_t *, 210 xfs_trans_t *, xfs_inode_t *,
@@ -215,14 +216,9 @@ extern int xfs_qm_vop_chown_reserve(xfs_trans_t *, xfs_inode_t *,
215 xfs_dquot_t *, xfs_dquot_t *, uint); 216 xfs_dquot_t *, xfs_dquot_t *, uint);
216 217
217/* list stuff */ 218/* list stuff */
218extern void xfs_qm_freelist_init(xfs_frlist_t *);
219extern void xfs_qm_freelist_destroy(xfs_frlist_t *);
220extern void xfs_qm_freelist_insert(xfs_frlist_t *, xfs_dquot_t *);
221extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *); 219extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *);
222extern void xfs_qm_freelist_unlink(xfs_dquot_t *); 220extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
223extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *); 221extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *);
224extern int xfs_qm_mplist_nowait(xfs_mount_t *);
225extern int xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
226 222
227/* system call interface */ 223/* system call interface */
228extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t); 224extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index be67d9c265f8..dc3c37a1e158 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -71,10 +71,13 @@
71#define MNTOPT_NOQUOTA "noquota" /* no quotas */ 71#define MNTOPT_NOQUOTA "noquota" /* no quotas */
72#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */ 72#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
73#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */ 73#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
74#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
74#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */ 75#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
75#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */ 76#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
77#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
76#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */ 78#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
77#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ 79#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
80#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
78#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ 81#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
79 82
80STATIC int 83STATIC int
@@ -109,6 +112,14 @@ xfs_qm_parseargs(
109 args->flags |= XFSMNT_UQUOTA; 112 args->flags |= XFSMNT_UQUOTA;
110 args->flags &= ~XFSMNT_UQUOTAENF; 113 args->flags &= ~XFSMNT_UQUOTAENF;
111 referenced = 1; 114 referenced = 1;
115 } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
116 !strcmp(this_char, MNTOPT_PRJQUOTA)) {
117 args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
118 referenced = 1;
119 } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
120 args->flags |= XFSMNT_PQUOTA;
121 args->flags &= ~XFSMNT_PQUOTAENF;
122 referenced = 1;
112 } else if (!strcmp(this_char, MNTOPT_GQUOTA) || 123 } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
113 !strcmp(this_char, MNTOPT_GRPQUOTA)) { 124 !strcmp(this_char, MNTOPT_GRPQUOTA)) {
114 args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF; 125 args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
@@ -127,6 +138,12 @@ xfs_qm_parseargs(
127 *this_char++ = ','; 138 *this_char++ = ',';
128 } 139 }
129 140
141 if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
142 cmn_err(CE_WARN,
143 "XFS: cannot mount with both project and group quota");
144 return XFS_ERROR(EINVAL);
145 }
146
130 PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error); 147 PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
131 if (!error && !referenced) 148 if (!error && !referenced)
132 bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); 149 bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
@@ -148,13 +165,19 @@ xfs_qm_showargs(
148 seq_puts(m, "," MNTOPT_UQUOTANOENF); 165 seq_puts(m, "," MNTOPT_UQUOTANOENF);
149 } 166 }
150 167
168 if (mp->m_qflags & XFS_PQUOTA_ACCT) {
169 (mp->m_qflags & XFS_OQUOTA_ENFD) ?
170 seq_puts(m, "," MNTOPT_PRJQUOTA) :
171 seq_puts(m, "," MNTOPT_PQUOTANOENF);
172 }
173
151 if (mp->m_qflags & XFS_GQUOTA_ACCT) { 174 if (mp->m_qflags & XFS_GQUOTA_ACCT) {
152 (mp->m_qflags & XFS_GQUOTA_ENFD) ? 175 (mp->m_qflags & XFS_OQUOTA_ENFD) ?
153 seq_puts(m, "," MNTOPT_GRPQUOTA) : 176 seq_puts(m, "," MNTOPT_GRPQUOTA) :
154 seq_puts(m, "," MNTOPT_GQUOTANOENF); 177 seq_puts(m, "," MNTOPT_GQUOTANOENF);
155 } 178 }
156 179
157 if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) 180 if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
158 seq_puts(m, "," MNTOPT_NOQUOTA); 181 seq_puts(m, "," MNTOPT_NOQUOTA);
159 182
160 PVFS_SHOWARGS(BHV_NEXT(bhv), m, error); 183 PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
@@ -171,7 +194,7 @@ xfs_qm_mount(
171 struct xfs_mount *mp = XFS_VFSTOM(vfsp); 194 struct xfs_mount *mp = XFS_VFSTOM(vfsp);
172 int error; 195 int error;
173 196
174 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)) 197 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
175 xfs_qm_mount_quotainit(mp, args->flags); 198 xfs_qm_mount_quotainit(mp, args->flags);
176 PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error); 199 PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
177 return error; 200 return error;
@@ -255,16 +278,17 @@ xfs_qm_newmount(
255 uint *quotaflags) 278 uint *quotaflags)
256{ 279{
257 uint quotaondisk; 280 uint quotaondisk;
258 uint uquotaondisk = 0, gquotaondisk = 0; 281 uint uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
259 282
260 *quotaflags = 0; 283 *quotaflags = 0;
261 *needquotamount = B_FALSE; 284 *needquotamount = B_FALSE;
262 285
263 quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && 286 quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
264 mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT); 287 (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
265 288
266 if (quotaondisk) { 289 if (quotaondisk) {
267 uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT; 290 uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
291 pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
268 gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT; 292 gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
269 } 293 }
270 294
@@ -277,13 +301,16 @@ xfs_qm_newmount(
277 301
278 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || 302 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
279 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || 303 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) ||
304 (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
305 (!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) ||
280 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || 306 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
281 (!gquotaondisk && XFS_IS_GQUOTA_ON(mp))) && 307 (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) &&
282 xfs_dev_is_read_only(mp, "changing quota state")) { 308 xfs_dev_is_read_only(mp, "changing quota state")) {
283 cmn_err(CE_WARN, 309 cmn_err(CE_WARN,
284 "XFS: please mount with%s%s%s.", 310 "XFS: please mount with%s%s%s%s.",
285 (!quotaondisk ? "out quota" : ""), 311 (!quotaondisk ? "out quota" : ""),
286 (uquotaondisk ? " usrquota" : ""), 312 (uquotaondisk ? " usrquota" : ""),
313 (pquotaondisk ? " prjquota" : ""),
287 (gquotaondisk ? " grpquota" : "")); 314 (gquotaondisk ? " grpquota" : ""));
288 return XFS_ERROR(EPERM); 315 return XFS_ERROR(EPERM);
289 } 316 }
@@ -359,7 +386,7 @@ xfs_qm_dqrele_null(
359} 386}
360 387
361 388
362struct xfs_qmops xfs_qmcore_xfs = { 389STATIC struct xfs_qmops xfs_qmcore_xfs = {
363 .xfs_qminit = xfs_qm_newmount, 390 .xfs_qminit = xfs_qm_newmount,
364 .xfs_qmdone = xfs_qm_unmount_quotadestroy, 391 .xfs_qmdone = xfs_qm_unmount_quotadestroy,
365 .xfs_qmmount = xfs_qm_endmount, 392 .xfs_qmmount = xfs_qm_endmount,
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 229f5b5a2d25..68e98962dbef 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -118,40 +118,41 @@ xfs_qm_quotactl(
118 * The following commands are valid even when quotaoff. 118 * The following commands are valid even when quotaoff.
119 */ 119 */
120 switch (cmd) { 120 switch (cmd) {
121 case Q_XQUOTARM:
121 /* 122 /*
122 * truncate quota files. quota must be off. 123 * Truncate quota files. quota must be off.
123 */ 124 */
124 case Q_XQUOTARM:
125 if (XFS_IS_QUOTA_ON(mp) || addr == NULL) 125 if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
126 return XFS_ERROR(EINVAL); 126 return XFS_ERROR(EINVAL);
127 if (vfsp->vfs_flag & VFS_RDONLY) 127 if (vfsp->vfs_flag & VFS_RDONLY)
128 return XFS_ERROR(EROFS); 128 return XFS_ERROR(EROFS);
129 return (xfs_qm_scall_trunc_qfiles(mp, 129 return (xfs_qm_scall_trunc_qfiles(mp,
130 xfs_qm_import_qtype_flags(*(uint *)addr))); 130 xfs_qm_import_qtype_flags(*(uint *)addr)));
131
132 case Q_XGETQSTAT:
131 /* 133 /*
132 * Get quota status information. 134 * Get quota status information.
133 */ 135 */
134 case Q_XGETQSTAT:
135 return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr)); 136 return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
136 137
138 case Q_XQUOTAON:
137 /* 139 /*
138 * QUOTAON for root f/s and quota enforcement on others.. 140 * QUOTAON - enabling quota enforcement.
139 * Quota accounting for non-root f/s's must be turned on 141 * Quota accounting must be turned on at mount time.
140 * at mount time.
141 */ 142 */
142 case Q_XQUOTAON:
143 if (addr == NULL) 143 if (addr == NULL)
144 return XFS_ERROR(EINVAL); 144 return XFS_ERROR(EINVAL);
145 if (vfsp->vfs_flag & VFS_RDONLY) 145 if (vfsp->vfs_flag & VFS_RDONLY)
146 return XFS_ERROR(EROFS); 146 return XFS_ERROR(EROFS);
147 return (xfs_qm_scall_quotaon(mp, 147 return (xfs_qm_scall_quotaon(mp,
148 xfs_qm_import_flags(*(uint *)addr))); 148 xfs_qm_import_flags(*(uint *)addr)));
149 case Q_XQUOTAOFF: 149
150 case Q_XQUOTAOFF:
150 if (vfsp->vfs_flag & VFS_RDONLY) 151 if (vfsp->vfs_flag & VFS_RDONLY)
151 return XFS_ERROR(EROFS); 152 return XFS_ERROR(EROFS);
152 break; 153 break;
153 154
154 default: 155 default:
155 break; 156 break;
156 } 157 }
157 158
@@ -159,7 +160,7 @@ xfs_qm_quotactl(
159 return XFS_ERROR(ESRCH); 160 return XFS_ERROR(ESRCH);
160 161
161 switch (cmd) { 162 switch (cmd) {
162 case Q_XQUOTAOFF: 163 case Q_XQUOTAOFF:
163 if (vfsp->vfs_flag & VFS_RDONLY) 164 if (vfsp->vfs_flag & VFS_RDONLY)
164 return XFS_ERROR(EROFS); 165 return XFS_ERROR(EROFS);
165 error = xfs_qm_scall_quotaoff(mp, 166 error = xfs_qm_scall_quotaoff(mp,
@@ -167,42 +168,39 @@ xfs_qm_quotactl(
167 B_FALSE); 168 B_FALSE);
168 break; 169 break;
169 170
170 /* 171 case Q_XGETQUOTA:
171 * Defaults to XFS_GETUQUOTA.
172 */
173 case Q_XGETQUOTA:
174 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER, 172 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
175 (fs_disk_quota_t *)addr); 173 (fs_disk_quota_t *)addr);
176 break; 174 break;
177 /* 175 case Q_XGETGQUOTA:
178 * Set limits, both hard and soft. Defaults to Q_SETUQLIM. 176 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
179 */ 177 (fs_disk_quota_t *)addr);
180 case Q_XSETQLIM: 178 break;
179 case Q_XGETPQUOTA:
180 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
181 (fs_disk_quota_t *)addr);
182 break;
183
184 case Q_XSETQLIM:
181 if (vfsp->vfs_flag & VFS_RDONLY) 185 if (vfsp->vfs_flag & VFS_RDONLY)
182 return XFS_ERROR(EROFS); 186 return XFS_ERROR(EROFS);
183 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER, 187 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
184 (fs_disk_quota_t *)addr); 188 (fs_disk_quota_t *)addr);
185 break; 189 break;
186 190 case Q_XSETGQLIM:
187 case Q_XSETGQLIM:
188 if (vfsp->vfs_flag & VFS_RDONLY) 191 if (vfsp->vfs_flag & VFS_RDONLY)
189 return XFS_ERROR(EROFS); 192 return XFS_ERROR(EROFS);
190 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, 193 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
191 (fs_disk_quota_t *)addr); 194 (fs_disk_quota_t *)addr);
192 break; 195 break;
193 196 case Q_XSETPQLIM:
194 197 if (vfsp->vfs_flag & VFS_RDONLY)
195 case Q_XGETGQUOTA: 198 return XFS_ERROR(EROFS);
196 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, 199 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
197 (fs_disk_quota_t *)addr); 200 (fs_disk_quota_t *)addr);
198 break; 201 break;
199 202
200 /* 203 default:
201 * Quotas are entirely undefined after quotaoff in XFS quotas.
202 * For instance, there's no way to set limits when quotaoff.
203 */
204
205 default:
206 error = XFS_ERROR(EINVAL); 204 error = XFS_ERROR(EINVAL);
207 break; 205 break;
208 } 206 }
@@ -286,8 +284,12 @@ xfs_qm_scall_quotaoff(
286 } 284 }
287 if (flags & XFS_GQUOTA_ACCT) { 285 if (flags & XFS_GQUOTA_ACCT) {
288 dqtype |= XFS_QMOPT_GQUOTA; 286 dqtype |= XFS_QMOPT_GQUOTA;
289 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD); 287 flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
290 inactivate_flags |= XFS_GQUOTA_ACTIVE; 288 inactivate_flags |= XFS_GQUOTA_ACTIVE;
289 } else if (flags & XFS_PQUOTA_ACCT) {
290 dqtype |= XFS_QMOPT_PQUOTA;
291 flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
292 inactivate_flags |= XFS_PQUOTA_ACTIVE;
291 } 293 }
292 294
293 /* 295 /*
@@ -364,7 +366,8 @@ xfs_qm_scall_quotaoff(
364 /* 366 /*
365 * If quotas is completely disabled, close shop. 367 * If quotas is completely disabled, close shop.
366 */ 368 */
367 if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) { 369 if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
370 ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
368 mutex_unlock(&(XFS_QI_QOFFLOCK(mp))); 371 mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
369 xfs_qm_destroy_quotainfo(mp); 372 xfs_qm_destroy_quotainfo(mp);
370 return (0); 373 return (0);
@@ -378,7 +381,7 @@ xfs_qm_scall_quotaoff(
378 XFS_PURGE_INODE(XFS_QI_UQIP(mp)); 381 XFS_PURGE_INODE(XFS_QI_UQIP(mp));
379 XFS_QI_UQIP(mp) = NULL; 382 XFS_QI_UQIP(mp) = NULL;
380 } 383 }
381 if ((dqtype & XFS_QMOPT_GQUOTA) && XFS_QI_GQIP(mp)) { 384 if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) {
382 XFS_PURGE_INODE(XFS_QI_GQIP(mp)); 385 XFS_PURGE_INODE(XFS_QI_GQIP(mp));
383 XFS_QI_GQIP(mp) = NULL; 386 XFS_QI_GQIP(mp) = NULL;
384 } 387 }
@@ -411,7 +414,8 @@ xfs_qm_scall_trunc_qfiles(
411 } 414 }
412 } 415 }
413 416
414 if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) { 417 if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
418 mp->m_sb.sb_gquotino != NULLFSINO) {
415 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0); 419 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
416 if (! error) { 420 if (! error) {
417 (void) xfs_truncate_file(mp, qip); 421 (void) xfs_truncate_file(mp, qip);
@@ -434,7 +438,7 @@ xfs_qm_scall_quotaon(
434 uint flags) 438 uint flags)
435{ 439{
436 int error; 440 int error;
437 unsigned long s; 441 unsigned long s;
438 uint qf; 442 uint qf;
439 uint accflags; 443 uint accflags;
440 __int64_t sbflags; 444 __int64_t sbflags;
@@ -468,9 +472,13 @@ xfs_qm_scall_quotaon(
468 (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 && 472 (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
469 (flags & XFS_UQUOTA_ENFD)) 473 (flags & XFS_UQUOTA_ENFD))
470 || 474 ||
475 ((flags & XFS_PQUOTA_ACCT) == 0 &&
476 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
477 (flags & XFS_OQUOTA_ENFD))
478 ||
471 ((flags & XFS_GQUOTA_ACCT) == 0 && 479 ((flags & XFS_GQUOTA_ACCT) == 0 &&
472 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 && 480 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
473 (flags & XFS_GQUOTA_ENFD))) { 481 (flags & XFS_OQUOTA_ENFD))) {
474 qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n", 482 qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
475 flags, mp->m_sb.sb_qflags); 483 flags, mp->m_sb.sb_qflags);
476 return XFS_ERROR(EINVAL); 484 return XFS_ERROR(EINVAL);
@@ -504,6 +512,10 @@ xfs_qm_scall_quotaon(
504 */ 512 */
505 if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) != 513 if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
506 (mp->m_qflags & XFS_UQUOTA_ACCT)) || 514 (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
515 ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
516 (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
517 ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
518 (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
507 (flags & XFS_ALL_QUOTA_ENFD) == 0) 519 (flags & XFS_ALL_QUOTA_ENFD) == 0)
508 return (0); 520 return (0);
509 521
@@ -521,7 +533,6 @@ xfs_qm_scall_quotaon(
521} 533}
522 534
523 535
524
525/* 536/*
526 * Return quota status information, such as uquota-off, enforcements, etc. 537 * Return quota status information, such as uquota-off, enforcements, etc.
527 */ 538 */
@@ -606,7 +617,8 @@ xfs_qm_scall_setqlim(
606 if (!capable(CAP_SYS_ADMIN)) 617 if (!capable(CAP_SYS_ADMIN))
607 return XFS_ERROR(EPERM); 618 return XFS_ERROR(EPERM);
608 619
609 if ((newlim->d_fieldmask & (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK)) == 0) 620 if ((newlim->d_fieldmask &
621 (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0)
610 return (0); 622 return (0);
611 623
612 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); 624 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
@@ -691,12 +703,23 @@ xfs_qm_scall_setqlim(
691 qdprintk("ihard %Ld < isoft %Ld\n", hard, soft); 703 qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
692 } 704 }
693 705
706 /*
707 * Update warnings counter(s) if requested
708 */
709 if (newlim->d_fieldmask & FS_DQ_BWARNS)
710 INT_SET(ddq->d_bwarns, ARCH_CONVERT, newlim->d_bwarns);
711 if (newlim->d_fieldmask & FS_DQ_IWARNS)
712 INT_SET(ddq->d_iwarns, ARCH_CONVERT, newlim->d_iwarns);
713 if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
714 INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, newlim->d_rtbwarns);
715
694 if (id == 0) { 716 if (id == 0) {
695 /* 717 /*
696 * Timelimits for the super user set the relative time 718 * Timelimits for the super user set the relative time
697 * the other users can be over quota for this file system. 719 * the other users can be over quota for this file system.
698 * If it is zero a default is used. Ditto for the default 720 * If it is zero a default is used. Ditto for the default
699 * soft and hard limit values (already done, above). 721 * soft and hard limit values (already done, above), and
722 * for warnings.
700 */ 723 */
701 if (newlim->d_fieldmask & FS_DQ_BTIMER) { 724 if (newlim->d_fieldmask & FS_DQ_BTIMER) {
702 mp->m_quotainfo->qi_btimelimit = newlim->d_btimer; 725 mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
@@ -710,7 +733,13 @@ xfs_qm_scall_setqlim(
710 mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer; 733 mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
711 INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer); 734 INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
712 } 735 }
713 } else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ { 736 if (newlim->d_fieldmask & FS_DQ_BWARNS)
737 mp->m_quotainfo->qi_bwarnlimit = newlim->d_bwarns;
738 if (newlim->d_fieldmask & FS_DQ_IWARNS)
739 mp->m_quotainfo->qi_iwarnlimit = newlim->d_iwarns;
740 if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
741 mp->m_quotainfo->qi_rtbwarnlimit = newlim->d_rtbwarns;
742 } else {
714 /* 743 /*
715 * If the user is now over quota, start the timelimit. 744 * If the user is now over quota, start the timelimit.
716 * The user will not be 'warned'. 745 * The user will not be 'warned'.
@@ -776,9 +805,9 @@ xfs_qm_log_quotaoff_end(
776 xfs_qoff_logitem_t *startqoff, 805 xfs_qoff_logitem_t *startqoff,
777 uint flags) 806 uint flags)
778{ 807{
779 xfs_trans_t *tp; 808 xfs_trans_t *tp;
780 int error; 809 int error;
781 xfs_qoff_logitem_t *qoffi; 810 xfs_qoff_logitem_t *qoffi;
782 811
783 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END); 812 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
784 813
@@ -928,18 +957,26 @@ xfs_qm_export_dquot(
928 957
929STATIC uint 958STATIC uint
930xfs_qm_import_qtype_flags( 959xfs_qm_import_qtype_flags(
931 uint uflags) 960 uint uflags)
932{ 961{
962 uint oflags = 0;
963
933 /* 964 /*
934 * Can't be both at the same time. 965 * Can't be more than one, or none.
935 */ 966 */
936 if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 967 if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
937 (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) || 968 (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
938 ((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 0)) 969 ((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ==
970 (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ||
971 ((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ==
972 (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ||
973 ((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0))
939 return (0); 974 return (0);
940 975
941 return (uflags & XFS_USER_QUOTA) ? 976 oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0;
942 XFS_DQ_USER : XFS_DQ_GROUP; 977 oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0;
978 oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0;
979 return oflags;
943} 980}
944 981
945STATIC uint 982STATIC uint
@@ -947,14 +984,19 @@ xfs_qm_export_qtype_flags(
947 uint flags) 984 uint flags)
948{ 985{
949 /* 986 /*
950 * Can't be both at the same time. 987 * Can't be more than one, or none.
951 */ 988 */
952 ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 989 ASSERT((flags & (XFS_PROJ_QUOTA | XFS_USER_QUOTA)) !=
953 (XFS_GROUP_QUOTA | XFS_USER_QUOTA)); 990 (XFS_PROJ_QUOTA | XFS_USER_QUOTA));
954 ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 0); 991 ASSERT((flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)) !=
992 (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA));
993 ASSERT((flags & (XFS_USER_QUOTA | XFS_GROUP_QUOTA)) !=
994 (XFS_USER_QUOTA | XFS_GROUP_QUOTA));
995 ASSERT((flags & (XFS_PROJ_QUOTA|XFS_USER_QUOTA|XFS_GROUP_QUOTA)) != 0);
955 996
956 return (flags & XFS_DQ_USER) ? 997 return (flags & XFS_DQ_USER) ?
957 XFS_USER_QUOTA : XFS_GROUP_QUOTA; 998 XFS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
999 XFS_PROJ_QUOTA : XFS_GROUP_QUOTA;
958} 1000}
959 1001
960STATIC uint 1002STATIC uint
@@ -965,12 +1007,14 @@ xfs_qm_import_flags(
965 1007
966 if (uflags & XFS_QUOTA_UDQ_ACCT) 1008 if (uflags & XFS_QUOTA_UDQ_ACCT)
967 flags |= XFS_UQUOTA_ACCT; 1009 flags |= XFS_UQUOTA_ACCT;
1010 if (uflags & XFS_QUOTA_PDQ_ACCT)
1011 flags |= XFS_PQUOTA_ACCT;
968 if (uflags & XFS_QUOTA_GDQ_ACCT) 1012 if (uflags & XFS_QUOTA_GDQ_ACCT)
969 flags |= XFS_GQUOTA_ACCT; 1013 flags |= XFS_GQUOTA_ACCT;
970 if (uflags & XFS_QUOTA_UDQ_ENFD) 1014 if (uflags & XFS_QUOTA_UDQ_ENFD)
971 flags |= XFS_UQUOTA_ENFD; 1015 flags |= XFS_UQUOTA_ENFD;
972 if (uflags & XFS_QUOTA_GDQ_ENFD) 1016 if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
973 flags |= XFS_GQUOTA_ENFD; 1017 flags |= XFS_OQUOTA_ENFD;
974 return (flags); 1018 return (flags);
975} 1019}
976 1020
@@ -984,12 +1028,16 @@ xfs_qm_export_flags(
984 uflags = 0; 1028 uflags = 0;
985 if (flags & XFS_UQUOTA_ACCT) 1029 if (flags & XFS_UQUOTA_ACCT)
986 uflags |= XFS_QUOTA_UDQ_ACCT; 1030 uflags |= XFS_QUOTA_UDQ_ACCT;
1031 if (flags & XFS_PQUOTA_ACCT)
1032 uflags |= XFS_QUOTA_PDQ_ACCT;
987 if (flags & XFS_GQUOTA_ACCT) 1033 if (flags & XFS_GQUOTA_ACCT)
988 uflags |= XFS_QUOTA_GDQ_ACCT; 1034 uflags |= XFS_QUOTA_GDQ_ACCT;
989 if (flags & XFS_UQUOTA_ENFD) 1035 if (flags & XFS_UQUOTA_ENFD)
990 uflags |= XFS_QUOTA_UDQ_ENFD; 1036 uflags |= XFS_QUOTA_UDQ_ENFD;
991 if (flags & XFS_GQUOTA_ENFD) 1037 if (flags & (XFS_OQUOTA_ENFD)) {
992 uflags |= XFS_QUOTA_GDQ_ENFD; 1038 uflags |= (flags & XFS_GQUOTA_ACCT) ?
1039 XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD;
1040 }
993 return (uflags); 1041 return (uflags);
994} 1042}
995 1043
@@ -1070,7 +1118,7 @@ again:
1070 xfs_qm_dqrele(ip->i_udquot); 1118 xfs_qm_dqrele(ip->i_udquot);
1071 ip->i_udquot = NULL; 1119 ip->i_udquot = NULL;
1072 } 1120 }
1073 if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) { 1121 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
1074 xfs_qm_dqrele(ip->i_gdquot); 1122 xfs_qm_dqrele(ip->i_gdquot);
1075 ip->i_gdquot = NULL; 1123 ip->i_gdquot = NULL;
1076 } 1124 }
@@ -1160,7 +1208,6 @@ xfs_qm_dqtest_print(
1160{ 1208{
1161 cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------"); 1209 cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
1162 cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id); 1210 cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
1163 cmn_err(CE_DEBUG, "---- type = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
1164 cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount); 1211 cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount);
1165 cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", 1212 cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)",
1166 d->d_bcount, (int)d->d_bcount); 1213 d->d_bcount, (int)d->d_bcount);
@@ -1231,7 +1278,7 @@ xfs_dqtest_cmp2(
1231#ifdef QUOTADEBUG 1278#ifdef QUOTADEBUG
1232 if (!err) { 1279 if (!err) {
1233 cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked", 1280 cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
1234 d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount); 1281 d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
1235 } 1282 }
1236#endif 1283#endif
1237 return (err); 1284 return (err);
@@ -1287,6 +1334,7 @@ STATIC void
1287xfs_qm_internalqcheck_get_dquots( 1334xfs_qm_internalqcheck_get_dquots(
1288 xfs_mount_t *mp, 1335 xfs_mount_t *mp,
1289 xfs_dqid_t uid, 1336 xfs_dqid_t uid,
1337 xfs_dqid_t projid,
1290 xfs_dqid_t gid, 1338 xfs_dqid_t gid,
1291 xfs_dqtest_t **ud, 1339 xfs_dqtest_t **ud,
1292 xfs_dqtest_t **gd) 1340 xfs_dqtest_t **gd)
@@ -1295,6 +1343,8 @@ xfs_qm_internalqcheck_get_dquots(
1295 xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud); 1343 xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
1296 if (XFS_IS_GQUOTA_ON(mp)) 1344 if (XFS_IS_GQUOTA_ON(mp))
1297 xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd); 1345 xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
1346 else if (XFS_IS_PQUOTA_ON(mp))
1347 xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
1298} 1348}
1299 1349
1300 1350
@@ -1362,13 +1412,14 @@ xfs_qm_internalqcheck_adjust(
1362 } 1412 }
1363 xfs_qm_internalqcheck_get_dquots(mp, 1413 xfs_qm_internalqcheck_get_dquots(mp,
1364 (xfs_dqid_t) ip->i_d.di_uid, 1414 (xfs_dqid_t) ip->i_d.di_uid,
1415 (xfs_dqid_t) ip->i_d.di_projid,
1365 (xfs_dqid_t) ip->i_d.di_gid, 1416 (xfs_dqid_t) ip->i_d.di_gid,
1366 &ud, &gd); 1417 &ud, &gd);
1367 if (XFS_IS_UQUOTA_ON(mp)) { 1418 if (XFS_IS_UQUOTA_ON(mp)) {
1368 ASSERT(ud); 1419 ASSERT(ud);
1369 xfs_qm_internalqcheck_dqadjust(ip, ud); 1420 xfs_qm_internalqcheck_dqadjust(ip, ud);
1370 } 1421 }
1371 if (XFS_IS_GQUOTA_ON(mp)) { 1422 if (XFS_IS_OQUOTA_ON(mp)) {
1372 ASSERT(gd); 1423 ASSERT(gd);
1373 xfs_qm_internalqcheck_dqadjust(ip, gd); 1424 xfs_qm_internalqcheck_dqadjust(ip, gd);
1374 } 1425 }
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 414b6004af21..bf413e70ec07 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -56,6 +56,7 @@
56#define XFS_QI_RTBTIMELIMIT(mp) ((mp)->m_quotainfo->qi_rtbtimelimit) 56#define XFS_QI_RTBTIMELIMIT(mp) ((mp)->m_quotainfo->qi_rtbtimelimit)
57#define XFS_QI_ITIMELIMIT(mp) ((mp)->m_quotainfo->qi_itimelimit) 57#define XFS_QI_ITIMELIMIT(mp) ((mp)->m_quotainfo->qi_itimelimit)
58#define XFS_QI_BWARNLIMIT(mp) ((mp)->m_quotainfo->qi_bwarnlimit) 58#define XFS_QI_BWARNLIMIT(mp) ((mp)->m_quotainfo->qi_bwarnlimit)
59#define XFS_QI_RTBWARNLIMIT(mp) ((mp)->m_quotainfo->qi_rtbwarnlimit)
59#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit) 60#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit)
60#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock) 61#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
61 62
@@ -102,7 +103,8 @@ static inline int XQMISLCKD(struct xfs_dqhash *h)
102 (xfs_Gqm->qm_grp_dqhtable + \ 103 (xfs_Gqm->qm_grp_dqhtable + \
103 XFS_DQ_HASHVAL(mp, id))) 104 XFS_DQ_HASHVAL(mp, id)))
104#define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \ 105#define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \
105 XFS_IS_UQUOTA_ON(mp):XFS_IS_GQUOTA_ON(mp)) 106 XFS_IS_UQUOTA_ON(mp) : \
107 XFS_IS_OQUOTA_ON(mp))
106#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \ 108#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
107 !dqp->q_core.d_blk_hardlimit && \ 109 !dqp->q_core.d_blk_hardlimit && \
108 !dqp->q_core.d_blk_softlimit && \ 110 !dqp->q_core.d_blk_softlimit && \
@@ -177,16 +179,11 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
177 (!((dqp)->q_core.d_id)) 179 (!((dqp)->q_core.d_id))
178 180
179#define XFS_PURGE_INODE(ip) \ 181#define XFS_PURGE_INODE(ip) \
180 { \ 182 IRELE(ip);
181 vmap_t dqvmap; \
182 vnode_t *dqvp; \
183 dqvp = XFS_ITOV(ip); \
184 VMAP(dqvp, dqvmap); \
185 VN_RELE(dqvp); \
186 }
187 183
188#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \ 184#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
189 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : "???")) 185 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
186 (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
190#define DQFLAGTO_DIRTYSTR(d) (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY") 187#define DQFLAGTO_DIRTYSTR(d) (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
191 188
192#endif /* __XFS_QUOTA_PRIV_H__ */ 189#endif /* __XFS_QUOTA_PRIV_H__ */
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 149b2a1fd949..3b99daf8a640 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -187,7 +187,7 @@ xfs_trans_dup_dqinfo(
187/* 187/*
188 * Wrap around mod_dquot to account for both user and group quotas. 188 * Wrap around mod_dquot to account for both user and group quotas.
189 */ 189 */
190void 190STATIC void
191xfs_trans_mod_dquot_byino( 191xfs_trans_mod_dquot_byino(
192 xfs_trans_t *tp, 192 xfs_trans_t *tp,
193 xfs_inode_t *ip, 193 xfs_inode_t *ip,
@@ -207,12 +207,10 @@ xfs_trans_mod_dquot_byino(
207 if (tp->t_dqinfo == NULL) 207 if (tp->t_dqinfo == NULL)
208 xfs_trans_alloc_dqinfo(tp); 208 xfs_trans_alloc_dqinfo(tp);
209 209
210 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) { 210 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
211 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); 211 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
212 } 212 if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
213 if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
214 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); 213 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
215 }
216} 214}
217 215
218STATIC xfs_dqtrx_t * 216STATIC xfs_dqtrx_t *
@@ -368,7 +366,7 @@ xfs_trans_dqlockedjoin(
368 * Unreserve just the reservations done by this transaction. 366 * Unreserve just the reservations done by this transaction.
369 * dquot is still left locked at exit. 367 * dquot is still left locked at exit.
370 */ 368 */
371void 369STATIC void
372xfs_trans_apply_dquot_deltas( 370xfs_trans_apply_dquot_deltas(
373 xfs_trans_t *tp) 371 xfs_trans_t *tp)
374{ 372{
@@ -499,7 +497,7 @@ xfs_trans_apply_dquot_deltas(
499 * Adjust the RT reservation. 497 * Adjust the RT reservation.
500 */ 498 */
501 if (qtrx->qt_rtblk_res != 0) { 499 if (qtrx->qt_rtblk_res != 0) {
502 if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) { 500 if (qtrx->qt_rtblk_res != qtrx->qt_rtblk_res_used) {
503 if (qtrx->qt_rtblk_res > 501 if (qtrx->qt_rtblk_res >
504 qtrx->qt_rtblk_res_used) 502 qtrx->qt_rtblk_res_used)
505 dqp->q_res_rtbcount -= (xfs_qcnt_t) 503 dqp->q_res_rtbcount -= (xfs_qcnt_t)
@@ -532,12 +530,6 @@ xfs_trans_apply_dquot_deltas(
532 (xfs_qcnt_t)qtrx->qt_icount_delta; 530 (xfs_qcnt_t)qtrx->qt_icount_delta;
533 } 531 }
534 532
535
536#ifdef QUOTADEBUG
537 if (qtrx->qt_rtblk_res != 0)
538 cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
539 (int) qtrx->qt_rtblk_res, dqp);
540#endif
541 ASSERT(dqp->q_res_bcount >= 533 ASSERT(dqp->q_res_bcount >=
542 INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT)); 534 INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
543 ASSERT(dqp->q_res_icount >= 535 ASSERT(dqp->q_res_icount >=
@@ -638,7 +630,10 @@ xfs_trans_dqresv(
638 int error; 630 int error;
639 xfs_qcnt_t hardlimit; 631 xfs_qcnt_t hardlimit;
640 xfs_qcnt_t softlimit; 632 xfs_qcnt_t softlimit;
641 time_t btimer; 633 time_t timer;
634 xfs_qwarncnt_t warns;
635 xfs_qwarncnt_t warnlimit;
636 xfs_qcnt_t count;
642 xfs_qcnt_t *resbcountp; 637 xfs_qcnt_t *resbcountp;
643 xfs_quotainfo_t *q = mp->m_quotainfo; 638 xfs_quotainfo_t *q = mp->m_quotainfo;
644 639
@@ -653,7 +648,9 @@ xfs_trans_dqresv(
653 softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT); 648 softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
654 if (!softlimit) 649 if (!softlimit)
655 softlimit = q->qi_bsoftlimit; 650 softlimit = q->qi_bsoftlimit;
656 btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT); 651 timer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
652 warns = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT);
653 warnlimit = XFS_QI_BWARNLIMIT(dqp->q_mount);
657 resbcountp = &dqp->q_res_bcount; 654 resbcountp = &dqp->q_res_bcount;
658 } else { 655 } else {
659 ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS); 656 ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
@@ -663,7 +660,9 @@ xfs_trans_dqresv(
663 softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT); 660 softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
664 if (!softlimit) 661 if (!softlimit)
665 softlimit = q->qi_rtbsoftlimit; 662 softlimit = q->qi_rtbsoftlimit;
666 btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT); 663 timer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
664 warns = INT_GET(dqp->q_core.d_rtbwarns, ARCH_CONVERT);
665 warnlimit = XFS_QI_RTBWARNLIMIT(dqp->q_mount);
667 resbcountp = &dqp->q_res_rtbcount; 666 resbcountp = &dqp->q_res_rtbcount;
668 } 667 }
669 error = 0; 668 error = 0;
@@ -693,37 +692,36 @@ xfs_trans_dqresv(
693 * If timer or warnings has expired, 692 * If timer or warnings has expired,
694 * return EDQUOT 693 * return EDQUOT
695 */ 694 */
696 if ((btimer != 0 && get_seconds() > btimer) || 695 if ((timer != 0 && get_seconds() > timer) ||
697 (dqp->q_core.d_bwarns && 696 (warns != 0 && warns >= warnlimit)) {
698 INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
699 XFS_QI_BWARNLIMIT(dqp->q_mount))) {
700 error = EDQUOT; 697 error = EDQUOT;
701 goto error_return; 698 goto error_return;
702 } 699 }
703 } 700 }
704 } 701 }
705 if (ninos > 0) { 702 if (ninos > 0) {
706 hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT); 703 count = INT_GET(dqp->q_core.d_icount, ARCH_CONVERT);
704 timer = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT);
705 warns = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT);
706 warnlimit = XFS_QI_IWARNLIMIT(dqp->q_mount);
707 hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit,
708 ARCH_CONVERT);
707 if (!hardlimit) 709 if (!hardlimit)
708 hardlimit = q->qi_ihardlimit; 710 hardlimit = q->qi_ihardlimit;
709 softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT); 711 softlimit = INT_GET(dqp->q_core.d_ino_softlimit,
712 ARCH_CONVERT);
710 if (!softlimit) 713 if (!softlimit)
711 softlimit = q->qi_isoftlimit; 714 softlimit = q->qi_isoftlimit;
712 if (hardlimit > 0ULL && 715 if (hardlimit > 0ULL && count >= hardlimit) {
713 INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
714 error = EDQUOT; 716 error = EDQUOT;
715 goto error_return; 717 goto error_return;
716 } else if (softlimit > 0ULL && 718 } else if (softlimit > 0ULL && count >= softlimit) {
717 INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
718 /* 719 /*
719 * If timer or warnings has expired, 720 * If timer or warnings has expired,
720 * return EDQUOT 721 * return EDQUOT
721 */ 722 */
722 if ((dqp->q_core.d_itimer && 723 if ((timer != 0 && get_seconds() > timer) ||
723 get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) || 724 (warns != 0 && warns >= warnlimit)) {
724 (dqp->q_core.d_iwarns &&
725 INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
726 XFS_QI_IWARNLIMIT(dqp->q_mount))) {
727 error = EDQUOT; 725 error = EDQUOT;
728 goto error_return; 726 goto error_return;
729 } 727 }
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index 7d6e1f37df10..4ed7b6928cd7 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -36,7 +36,6 @@
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <linux/kernel.h> 37#include <linux/kernel.h>
38 38
39int doass = 1;
40static char message[256]; /* keep it off the stack */ 39static char message[256]; /* keep it off the stack */
41static DEFINE_SPINLOCK(xfs_err_lock); 40static DEFINE_SPINLOCK(xfs_err_lock);
42 41
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index 40b0f4c54d9e..c5b9365a7e2a 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -50,16 +50,11 @@ extern void cmn_err(int, char *, ...);
50#endif 50#endif
51 51
52#ifdef DEBUG 52#ifdef DEBUG
53# ifdef lint 53# define ASSERT(EX) ((EX) ? ((void)0) : assfail(#EX, __FILE__, __LINE__))
54# define ASSERT(EX) ((void)0) /* avoid "constant in conditional" babble */
55# else
56# define ASSERT(EX) ((!doass||(EX))?((void)0):assfail(#EX, __FILE__, __LINE__))
57# endif /* lint */
58#else 54#else
59# define ASSERT(x) ((void)0) 55# define ASSERT(x) ((void)0)
60#endif 56#endif
61 57
62extern int doass; /* dynamically turn off asserts */
63extern void assfail(char *, char *, int); 58extern void assfail(char *, char *, int);
64#ifdef DEBUG 59#ifdef DEBUG
65extern unsigned long random(void); 60extern unsigned long random(void);
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 36603db10fe9..dcfe19703620 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -59,7 +59,7 @@
59#define XFSA_FIXUP_BNO_OK 1 59#define XFSA_FIXUP_BNO_OK 1
60#define XFSA_FIXUP_CNT_OK 2 60#define XFSA_FIXUP_CNT_OK 2
61 61
62int 62STATIC int
63xfs_alloc_search_busy(xfs_trans_t *tp, 63xfs_alloc_search_busy(xfs_trans_t *tp,
64 xfs_agnumber_t agno, 64 xfs_agnumber_t agno,
65 xfs_agblock_t bno, 65 xfs_agblock_t bno,
@@ -2562,7 +2562,7 @@ xfs_alloc_clear_busy(xfs_trans_t *tp,
2562/* 2562/*
2563 * returns non-zero if any of (agno,bno):len is in a busy list 2563 * returns non-zero if any of (agno,bno):len is in a busy list
2564 */ 2564 */
2565int 2565STATIC int
2566xfs_alloc_search_busy(xfs_trans_t *tp, 2566xfs_alloc_search_busy(xfs_trans_t *tp,
2567 xfs_agnumber_t agno, 2567 xfs_agnumber_t agno,
2568 xfs_agblock_t bno, 2568 xfs_agblock_t bno,
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index ee8b5904ec7c..a41ad3a5e554 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -71,6 +71,11 @@
71 * Provide the external interfaces to manage attribute lists. 71 * Provide the external interfaces to manage attribute lists.
72 */ 72 */
73 73
74#define ATTR_SYSCOUNT 2
75STATIC struct attrnames posix_acl_access;
76STATIC struct attrnames posix_acl_default;
77STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT];
78
74/*======================================================================== 79/*========================================================================
75 * Function prototypes for the kernel. 80 * Function prototypes for the kernel.
76 *========================================================================*/ 81 *========================================================================*/
@@ -83,6 +88,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
83/* 88/*
84 * Internal routines when attribute list is one block. 89 * Internal routines when attribute list is one block.
85 */ 90 */
91STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
86STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args); 92STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
87STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args); 93STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
88STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context); 94STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
@@ -90,6 +96,7 @@ STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
90/* 96/*
91 * Internal routines when attribute list is more than one block. 97 * Internal routines when attribute list is more than one block.
92 */ 98 */
99STATIC int xfs_attr_node_get(xfs_da_args_t *args);
93STATIC int xfs_attr_node_addname(xfs_da_args_t *args); 100STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
94STATIC int xfs_attr_node_removename(xfs_da_args_t *args); 101STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
95STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context); 102STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
@@ -1102,7 +1109,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
1102 * This leaf block cannot have a "remote" value, we only call this routine 1109 * This leaf block cannot have a "remote" value, we only call this routine
1103 * if bmap_one_block() says there is only one block (ie: no remote blks). 1110 * if bmap_one_block() says there is only one block (ie: no remote blks).
1104 */ 1111 */
1105int 1112STATIC int
1106xfs_attr_leaf_get(xfs_da_args_t *args) 1113xfs_attr_leaf_get(xfs_da_args_t *args)
1107{ 1114{
1108 xfs_dabuf_t *bp; 1115 xfs_dabuf_t *bp;
@@ -1707,7 +1714,7 @@ xfs_attr_refillstate(xfs_da_state_t *state)
1707 * block, ie: both true Btree attr lists and for single-leaf-blocks with 1714 * block, ie: both true Btree attr lists and for single-leaf-blocks with
1708 * "remote" values taking up more blocks. 1715 * "remote" values taking up more blocks.
1709 */ 1716 */
1710int 1717STATIC int
1711xfs_attr_node_get(xfs_da_args_t *args) 1718xfs_attr_node_get(xfs_da_args_t *args)
1712{ 1719{
1713 xfs_da_state_t *state; 1720 xfs_da_state_t *state;
@@ -2398,7 +2405,7 @@ posix_acl_default_exists(
2398 return xfs_acl_vhasacl_default(vp); 2405 return xfs_acl_vhasacl_default(vp);
2399} 2406}
2400 2407
2401struct attrnames posix_acl_access = { 2408STATIC struct attrnames posix_acl_access = {
2402 .attr_name = "posix_acl_access", 2409 .attr_name = "posix_acl_access",
2403 .attr_namelen = sizeof("posix_acl_access") - 1, 2410 .attr_namelen = sizeof("posix_acl_access") - 1,
2404 .attr_get = posix_acl_access_get, 2411 .attr_get = posix_acl_access_get,
@@ -2407,7 +2414,7 @@ struct attrnames posix_acl_access = {
2407 .attr_exists = posix_acl_access_exists, 2414 .attr_exists = posix_acl_access_exists,
2408}; 2415};
2409 2416
2410struct attrnames posix_acl_default = { 2417STATIC struct attrnames posix_acl_default = {
2411 .attr_name = "posix_acl_default", 2418 .attr_name = "posix_acl_default",
2412 .attr_namelen = sizeof("posix_acl_default") - 1, 2419 .attr_namelen = sizeof("posix_acl_default") - 1,
2413 .attr_get = posix_acl_default_get, 2420 .attr_get = posix_acl_default_get,
@@ -2416,7 +2423,7 @@ struct attrnames posix_acl_default = {
2416 .attr_exists = posix_acl_default_exists, 2423 .attr_exists = posix_acl_default_exists,
2417}; 2424};
2418 2425
2419struct attrnames *attr_system_names[] = 2426STATIC struct attrnames *attr_system_names[] =
2420 { &posix_acl_access, &posix_acl_default }; 2427 { &posix_acl_access, &posix_acl_default };
2421 2428
2422 2429
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index 67cd0f5ac1a7..45ab1c542baf 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -76,11 +76,6 @@ extern struct attrnames attr_system;
76extern struct attrnames attr_trusted; 76extern struct attrnames attr_trusted;
77extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; 77extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
78 78
79#define ATTR_SYSCOUNT 2
80extern struct attrnames posix_acl_access;
81extern struct attrnames posix_acl_default;
82extern struct attrnames *attr_system_names[ATTR_SYSCOUNT];
83
84extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int); 79extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
85extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *); 80extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
86 81
@@ -184,8 +179,6 @@ int xfs_attr_list(bhv_desc_t *, char *, int, int,
184 struct attrlist_cursor_kern *, struct cred *); 179 struct attrlist_cursor_kern *, struct cred *);
185int xfs_attr_inactive(struct xfs_inode *dp); 180int xfs_attr_inactive(struct xfs_inode *dp);
186 181
187int xfs_attr_node_get(struct xfs_da_args *);
188int xfs_attr_leaf_get(struct xfs_da_args *);
189int xfs_attr_shortform_getvalue(struct xfs_da_args *); 182int xfs_attr_shortform_getvalue(struct xfs_da_args *);
190int xfs_attr_fetch(struct xfs_inode *, char *, int, 183int xfs_attr_fetch(struct xfs_inode *, char *, int,
191 char *, int *, int, struct cred *); 184 char *, int *, int, struct cred *);
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index b11256e58bf4..1cdd574c63a9 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -79,6 +79,8 @@
79/* 79/*
80 * Routines used for growing the Btree. 80 * Routines used for growing the Btree.
81 */ 81 */
82STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
83 xfs_dabuf_t **bpp);
82STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args, 84STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
83 int freemap_index); 85 int freemap_index);
84STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer); 86STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer);
@@ -92,6 +94,16 @@ STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
92 int *number_usedbytes_in_blk1); 94 int *number_usedbytes_in_blk1);
93 95
94/* 96/*
97 * Routines used for shrinking the Btree.
98 */
99STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
100 xfs_dabuf_t *bp, int level);
101STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
102 xfs_dabuf_t *bp);
103STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
104 xfs_dablk_t blkno, int blkcnt);
105
106/*
95 * Utility routines. 107 * Utility routines.
96 */ 108 */
97STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf, 109STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
@@ -99,6 +111,10 @@ STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
99 xfs_attr_leafblock_t *dst_leaf, 111 xfs_attr_leafblock_t *dst_leaf,
100 int dst_start, int move_count, 112 int dst_start, int move_count,
101 xfs_mount_t *mp); 113 xfs_mount_t *mp);
114STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
115STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
116 attrnames_t *, char *name, int namelen,
117 int valuelen);
102 118
103 119
104/*======================================================================== 120/*========================================================================
@@ -774,7 +790,7 @@ out:
774 * Create the initial contents of a leaf attribute list 790 * Create the initial contents of a leaf attribute list
775 * or a leaf in a node attribute list. 791 * or a leaf in a node attribute list.
776 */ 792 */
777int 793STATIC int
778xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) 794xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
779{ 795{
780 xfs_attr_leafblock_t *leaf; 796 xfs_attr_leafblock_t *leaf;
@@ -2209,7 +2225,7 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
2209 * Calculate the number of bytes used to store the indicated attribute 2225 * Calculate the number of bytes used to store the indicated attribute
2210 * (whether local or remote only calculate bytes in this block). 2226 * (whether local or remote only calculate bytes in this block).
2211 */ 2227 */
2212int 2228STATIC int
2213xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) 2229xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
2214{ 2230{
2215 xfs_attr_leaf_name_local_t *name_loc; 2231 xfs_attr_leaf_name_local_t *name_loc;
@@ -2380,7 +2396,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
2380 * we may be reading them directly out of a user buffer. 2396 * we may be reading them directly out of a user buffer.
2381 */ 2397 */
2382/*ARGSUSED*/ 2398/*ARGSUSED*/
2383int 2399STATIC int
2384xfs_attr_put_listent(xfs_attr_list_context_t *context, 2400xfs_attr_put_listent(xfs_attr_list_context_t *context,
2385 attrnames_t *namesp, char *name, int namelen, int valuelen) 2401 attrnames_t *namesp, char *name, int namelen, int valuelen)
2386{ 2402{
@@ -2740,7 +2756,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
2740 * Recurse (gasp!) through the attribute nodes until we find leaves. 2756 * Recurse (gasp!) through the attribute nodes until we find leaves.
2741 * We're doing a depth-first traversal in order to invalidate everything. 2757 * We're doing a depth-first traversal in order to invalidate everything.
2742 */ 2758 */
2743int 2759STATIC int
2744xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, 2760xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
2745 int level) 2761 int level)
2746{ 2762{
@@ -2849,7 +2865,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
2849 * Note that we must release the lock on the buffer so that we are not 2865 * Note that we must release the lock on the buffer so that we are not
2850 * caught holding something that the logging code wants to flush to disk. 2866 * caught holding something that the logging code wants to flush to disk.
2851 */ 2867 */
2852int 2868STATIC int
2853xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) 2869xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
2854{ 2870{
2855 xfs_attr_leafblock_t *leaf; 2871 xfs_attr_leafblock_t *leaf;
@@ -2934,7 +2950,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
2934 * Look at all the extents for this logical region, 2950 * Look at all the extents for this logical region,
2935 * invalidate any buffers that are incore/in transactions. 2951 * invalidate any buffers that are incore/in transactions.
2936 */ 2952 */
2937int 2953STATIC int
2938xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, 2954xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
2939 xfs_dablk_t blkno, int blkcnt) 2955 xfs_dablk_t blkno, int blkcnt)
2940{ 2956{
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index b1480e0b3349..0a4cfad6df91 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -261,8 +261,6 @@ int xfs_attr_leaf_flipflags(xfs_da_args_t *args);
261/* 261/*
262 * Routines used for growing the Btree. 262 * Routines used for growing the Btree.
263 */ 263 */
264int xfs_attr_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
265 struct xfs_dabuf **bpp);
266int xfs_attr_leaf_split(struct xfs_da_state *state, 264int xfs_attr_leaf_split(struct xfs_da_state *state,
267 struct xfs_da_state_blk *oldblk, 265 struct xfs_da_state_blk *oldblk,
268 struct xfs_da_state_blk *newblk); 266 struct xfs_da_state_blk *newblk);
@@ -284,12 +282,6 @@ void xfs_attr_leaf_unbalance(struct xfs_da_state *state,
284 struct xfs_da_state_blk *drop_blk, 282 struct xfs_da_state_blk *drop_blk,
285 struct xfs_da_state_blk *save_blk); 283 struct xfs_da_state_blk *save_blk);
286int xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp); 284int xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
287int xfs_attr_node_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
288 struct xfs_dabuf *bp, int level);
289int xfs_attr_leaf_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
290 struct xfs_dabuf *bp);
291int xfs_attr_leaf_freextent(struct xfs_trans **trans, struct xfs_inode *dp,
292 xfs_dablk_t blkno, int blkcnt);
293 285
294/* 286/*
295 * Utility routines. 287 * Utility routines.
@@ -299,10 +291,6 @@ int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp,
299 struct xfs_dabuf *leaf2_bp); 291 struct xfs_dabuf *leaf2_bp);
300int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int blocksize, 292int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int blocksize,
301 int *local); 293 int *local);
302int xfs_attr_leaf_entsize(struct xfs_attr_leafblock *leaf, int index);
303int xfs_attr_put_listent(struct xfs_attr_list_context *context,
304 struct attrnames *, char *name, int namelen,
305 int valuelen);
306int xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp); 294int xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
307 295
308#endif /* __XFS_ATTR_LEAF_H__ */ 296#endif /* __XFS_ATTR_LEAF_H__ */
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index a20a6c3dc13e..76c9ad3875ef 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -45,7 +45,7 @@
45/* 45/*
46 * Index of high bit number in byte, -1 for none set, 0..7 otherwise. 46 * Index of high bit number in byte, -1 for none set, 0..7 otherwise.
47 */ 47 */
48const char xfs_highbit[256] = { 48STATIC const char xfs_highbit[256] = {
49 -1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */ 49 -1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */
50 3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */ 50 3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */
51 4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */ 51 4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index de3162418663..6f5d283888aa 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -301,6 +301,19 @@ xfs_bmap_search_extents(
301 xfs_bmbt_irec_t *gotp, /* out: extent entry found */ 301 xfs_bmbt_irec_t *gotp, /* out: extent entry found */
302 xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */ 302 xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */
303 303
304/*
305 * Check the last inode extent to determine whether this allocation will result
306 * in blocks being allocated at the end of the file. When we allocate new data
307 * blocks at the end of the file which do not start at the previous data block,
308 * we will try to align the new blocks at stripe unit boundaries.
309 */
310STATIC int /* error */
311xfs_bmap_isaeof(
312 xfs_inode_t *ip, /* incore inode pointer */
313 xfs_fileoff_t off, /* file offset in fsblocks */
314 int whichfork, /* data or attribute fork */
315 char *aeof); /* return value */
316
304#ifdef XFS_BMAP_TRACE 317#ifdef XFS_BMAP_TRACE
305/* 318/*
306 * Add a bmap trace buffer entry. Base routine for the others. 319 * Add a bmap trace buffer entry. Base routine for the others.
@@ -4532,18 +4545,17 @@ xfs_bmapi(
4532 xfs_extlen_t alen; /* allocated extent length */ 4545 xfs_extlen_t alen; /* allocated extent length */
4533 xfs_fileoff_t aoff; /* allocated file offset */ 4546 xfs_fileoff_t aoff; /* allocated file offset */
4534 xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */ 4547 xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */
4535 char contig; /* allocation must be one extent */
4536 xfs_btree_cur_t *cur; /* bmap btree cursor */ 4548 xfs_btree_cur_t *cur; /* bmap btree cursor */
4537 char delay; /* this request is for delayed alloc */
4538 xfs_fileoff_t end; /* end of mapped file region */ 4549 xfs_fileoff_t end; /* end of mapped file region */
4539 int eof; /* we've hit the end of extent list */ 4550 int eof; /* we've hit the end of extent list */
4551 char contig; /* allocation must be one extent */
4552 char delay; /* this request is for delayed alloc */
4553 char exact; /* don't do all of wasdelayed extent */
4540 xfs_bmbt_rec_t *ep; /* extent list entry pointer */ 4554 xfs_bmbt_rec_t *ep; /* extent list entry pointer */
4541 int error; /* error return */ 4555 int error; /* error return */
4542 char exact; /* don't do all of wasdelayed extent */
4543 xfs_bmbt_irec_t got; /* current extent list record */ 4556 xfs_bmbt_irec_t got; /* current extent list record */
4544 xfs_ifork_t *ifp; /* inode fork pointer */ 4557 xfs_ifork_t *ifp; /* inode fork pointer */
4545 xfs_extlen_t indlen; /* indirect blocks length */ 4558 xfs_extlen_t indlen; /* indirect blocks length */
4546 char inhole; /* current location is hole in file */
4547 xfs_extnum_t lastx; /* last useful extent number */ 4559 xfs_extnum_t lastx; /* last useful extent number */
4548 int logflags; /* flags for transaction logging */ 4560 int logflags; /* flags for transaction logging */
4549 xfs_extlen_t minleft; /* min blocks left after allocation */ 4561 xfs_extlen_t minleft; /* min blocks left after allocation */
@@ -4554,13 +4566,15 @@ xfs_bmapi(
4554 xfs_extnum_t nextents; /* number of extents in file */ 4566 xfs_extnum_t nextents; /* number of extents in file */
4555 xfs_fileoff_t obno; /* old block number (offset) */ 4567 xfs_fileoff_t obno; /* old block number (offset) */
4556 xfs_bmbt_irec_t prev; /* previous extent list record */ 4568 xfs_bmbt_irec_t prev; /* previous extent list record */
4557 char stateless; /* ignore state flag set */
4558 int tmp_logflags; /* temp flags holder */ 4569 int tmp_logflags; /* temp flags holder */
4570 int whichfork; /* data or attr fork */
4571 char inhole; /* current location is hole in file */
4572 char stateless; /* ignore state flag set */
4559 char trim; /* output trimmed to match range */ 4573 char trim; /* output trimmed to match range */
4560 char userdata; /* allocating non-metadata */ 4574 char userdata; /* allocating non-metadata */
4561 char wasdelay; /* old extent was delayed */ 4575 char wasdelay; /* old extent was delayed */
4562 int whichfork; /* data or attr fork */
4563 char wr; /* this is a write request */ 4576 char wr; /* this is a write request */
4577 char rt; /* this is a realtime file */
4564 char rsvd; /* OK to allocate reserved blocks */ 4578 char rsvd; /* OK to allocate reserved blocks */
4565#ifdef DEBUG 4579#ifdef DEBUG
4566 xfs_fileoff_t orig_bno; /* original block number value */ 4580 xfs_fileoff_t orig_bno; /* original block number value */
@@ -4590,6 +4604,7 @@ xfs_bmapi(
4590 } 4604 }
4591 if (XFS_FORCED_SHUTDOWN(mp)) 4605 if (XFS_FORCED_SHUTDOWN(mp))
4592 return XFS_ERROR(EIO); 4606 return XFS_ERROR(EIO);
4607 rt = XFS_IS_REALTIME_INODE(ip);
4593 ifp = XFS_IFORK_PTR(ip, whichfork); 4608 ifp = XFS_IFORK_PTR(ip, whichfork);
4594 ASSERT(ifp->if_ext_max == 4609 ASSERT(ifp->if_ext_max ==
4595 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); 4610 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
@@ -4694,9 +4709,16 @@ xfs_bmapi(
4694 } 4709 }
4695 minlen = contig ? alen : 1; 4710 minlen = contig ? alen : 1;
4696 if (delay) { 4711 if (delay) {
4697 indlen = (xfs_extlen_t) 4712 xfs_extlen_t extsz = 0;
4698 xfs_bmap_worst_indlen(ip, alen); 4713
4699 ASSERT(indlen > 0); 4714 /* Figure out the extent size, adjust alen */
4715 if (rt) {
4716 if (!(extsz = ip->i_d.di_extsize))
4717 extsz = mp->m_sb.sb_rextsize;
4718 alen = roundup(alen, extsz);
4719 extsz = alen / mp->m_sb.sb_rextsize;
4720 }
4721
4700 /* 4722 /*
4701 * Make a transaction-less quota reservation for 4723 * Make a transaction-less quota reservation for
4702 * delayed allocation blocks. This number gets 4724 * delayed allocation blocks. This number gets
@@ -4704,8 +4726,10 @@ xfs_bmapi(
4704 * We return EDQUOT if we haven't allocated 4726 * We return EDQUOT if we haven't allocated
4705 * blks already inside this loop; 4727 * blks already inside this loop;
4706 */ 4728 */
4707 if (XFS_TRANS_RESERVE_BLKQUOTA( 4729 if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
4708 mp, NULL, ip, (long)alen)) { 4730 mp, NULL, ip, (long)alen, 0,
4731 rt ? XFS_QMOPT_RES_RTBLKS :
4732 XFS_QMOPT_RES_REGBLKS)) {
4709 if (n == 0) { 4733 if (n == 0) {
4710 *nmap = 0; 4734 *nmap = 0;
4711 ASSERT(cur == NULL); 4735 ASSERT(cur == NULL);
@@ -4718,40 +4742,34 @@ xfs_bmapi(
4718 * Split changing sb for alen and indlen since 4742 * Split changing sb for alen and indlen since
4719 * they could be coming from different places. 4743 * they could be coming from different places.
4720 */ 4744 */
4721 if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) { 4745 indlen = (xfs_extlen_t)
4722 xfs_extlen_t extsz; 4746 xfs_bmap_worst_indlen(ip, alen);
4723 xfs_extlen_t ralen; 4747 ASSERT(indlen > 0);
4724 if (!(extsz = ip->i_d.di_extsize))
4725 extsz = mp->m_sb.sb_rextsize;
4726 ralen = roundup(alen, extsz);
4727 ralen = ralen / mp->m_sb.sb_rextsize;
4728 if (xfs_mod_incore_sb(mp,
4729 XFS_SBS_FREXTENTS,
4730 -(ralen), rsvd)) {
4731 if (XFS_IS_QUOTA_ON(ip->i_mount))
4732 XFS_TRANS_UNRESERVE_BLKQUOTA(
4733 mp, NULL, ip,
4734 (long)alen);
4735 break;
4736 }
4737 } else {
4738 if (xfs_mod_incore_sb(mp,
4739 XFS_SBS_FDBLOCKS,
4740 -(alen), rsvd)) {
4741 if (XFS_IS_QUOTA_ON(ip->i_mount))
4742 XFS_TRANS_UNRESERVE_BLKQUOTA(
4743 mp, NULL, ip,
4744 (long)alen);
4745 break;
4746 }
4747 }
4748 4748
4749 if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, 4749 if (rt)
4750 -(indlen), rsvd)) { 4750 error = xfs_mod_incore_sb(mp,
4751 XFS_TRANS_UNRESERVE_BLKQUOTA( 4751 XFS_SBS_FREXTENTS,
4752 mp, NULL, ip, (long)alen); 4752 -(extsz), rsvd);
4753 else
4754 error = xfs_mod_incore_sb(mp,
4755 XFS_SBS_FDBLOCKS,
4756 -(alen), rsvd);
4757 if (!error)
4758 error = xfs_mod_incore_sb(mp,
4759 XFS_SBS_FDBLOCKS,
4760 -(indlen), rsvd);
4761
4762 if (error) {
4763 if (XFS_IS_QUOTA_ON(ip->i_mount))
4764 /* unreserve the blocks now */
4765 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
4766 mp, NULL, ip,
4767 (long)alen, 0, rt ?
4768 XFS_QMOPT_RES_RTBLKS :
4769 XFS_QMOPT_RES_REGBLKS);
4753 break; 4770 break;
4754 } 4771 }
4772
4755 ip->i_delayed_blks += alen; 4773 ip->i_delayed_blks += alen;
4756 abno = NULLSTARTBLOCK(indlen); 4774 abno = NULLSTARTBLOCK(indlen);
4757 } else { 4775 } else {
@@ -5376,13 +5394,24 @@ xfs_bunmapi(
5376 } 5394 }
5377 if (wasdel) { 5395 if (wasdel) {
5378 ASSERT(STARTBLOCKVAL(del.br_startblock) > 0); 5396 ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
5379 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, 5397 /* Update realtim/data freespace, unreserve quota */
5380 (int)del.br_blockcount, rsvd); 5398 if (isrt) {
5381 /* Unreserve our quota space */ 5399 xfs_filblks_t rtexts;
5382 XFS_TRANS_RESERVE_QUOTA_NBLKS( 5400
5383 mp, NULL, ip, -((long)del.br_blockcount), 0, 5401 rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
5384 isrt ? XFS_QMOPT_RES_RTBLKS : 5402 do_div(rtexts, mp->m_sb.sb_rextsize);
5403 xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
5404 (int)rtexts, rsvd);
5405 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
5406 -((long)del.br_blockcount), 0,
5407 XFS_QMOPT_RES_RTBLKS);
5408 } else {
5409 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
5410 (int)del.br_blockcount, rsvd);
5411 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
5412 -((long)del.br_blockcount), 0,
5385 XFS_QMOPT_RES_REGBLKS); 5413 XFS_QMOPT_RES_REGBLKS);
5414 }
5386 ip->i_delayed_blks -= del.br_blockcount; 5415 ip->i_delayed_blks -= del.br_blockcount;
5387 if (cur) 5416 if (cur)
5388 cur->bc_private.b.flags |= 5417 cur->bc_private.b.flags |=
@@ -5714,7 +5743,7 @@ unlock_and_return:
5714 * blocks at the end of the file which do not start at the previous data block, 5743 * blocks at the end of the file which do not start at the previous data block,
5715 * we will try to align the new blocks at stripe unit boundaries. 5744 * we will try to align the new blocks at stripe unit boundaries.
5716 */ 5745 */
5717int /* error */ 5746STATIC int /* error */
5718xfs_bmap_isaeof( 5747xfs_bmap_isaeof(
5719 xfs_inode_t *ip, /* incore inode pointer */ 5748 xfs_inode_t *ip, /* incore inode pointer */
5720 xfs_fileoff_t off, /* file offset in fsblocks */ 5749 xfs_fileoff_t off, /* file offset in fsblocks */
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index f1bc22fb26ae..e6d22ec9b2e4 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -332,19 +332,6 @@ xfs_getbmap(
332 int iflags); /* interface flags */ 332 int iflags); /* interface flags */
333 333
334/* 334/*
335 * Check the last inode extent to determine whether this allocation will result
336 * in blocks being allocated at the end of the file. When we allocate new data
337 * blocks at the end of the file which do not start at the previous data block,
338 * we will try to align the new blocks at stripe unit boundaries.
339 */
340int
341xfs_bmap_isaeof(
342 struct xfs_inode *ip,
343 xfs_fileoff_t off,
344 int whichfork,
345 char *aeof);
346
347/*
348 * Check if the endoff is outside the last extent. If so the caller will grow 335 * Check if the endoff is outside the last extent. If so the caller will grow
349 * the allocation to a stripe unit boundary 336 * the allocation to a stripe unit boundary
350 */ 337 */
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 163305a79fcc..09c413576ba8 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2331,20 +2331,6 @@ xfs_bmbt_lookup_ge(
2331 return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat); 2331 return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
2332} 2332}
2333 2333
2334int /* error */
2335xfs_bmbt_lookup_le(
2336 xfs_btree_cur_t *cur,
2337 xfs_fileoff_t off,
2338 xfs_fsblock_t bno,
2339 xfs_filblks_t len,
2340 int *stat) /* success/failure */
2341{
2342 cur->bc_rec.b.br_startoff = off;
2343 cur->bc_rec.b.br_startblock = bno;
2344 cur->bc_rec.b.br_blockcount = len;
2345 return xfs_bmbt_lookup(cur, XFS_LOOKUP_LE, stat);
2346}
2347
2348/* 2334/*
2349 * Give the bmap btree a new root block. Copy the old broot contents 2335 * Give the bmap btree a new root block. Copy the old broot contents
2350 * down into a real block and make the broot point to it. 2336 * down into a real block and make the broot point to it.
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 843ff12b4bf2..0a40cf126c28 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -580,14 +580,6 @@ xfs_bmbt_lookup_ge(
580 xfs_filblks_t, 580 xfs_filblks_t,
581 int *); 581 int *);
582 582
583int
584xfs_bmbt_lookup_le(
585 struct xfs_btree_cur *,
586 xfs_fileoff_t,
587 xfs_fsblock_t,
588 xfs_filblks_t,
589 int *);
590
591/* 583/*
592 * Give the bmap btree a new root block. Copy the old broot contents 584 * Give the bmap btree a new root block. Copy the old broot contents
593 * down into a real block and make the broot point to it. 585 * down into a real block and make the broot point to it.
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 9dd22dd95487..0cc63d657a14 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -90,6 +90,16 @@ xfs_btree_maxrecs(
90 */ 90 */
91 91
92/* 92/*
93 * Retrieve the block pointer from the cursor at the given level.
94 * This may be a bmap btree root or from a buffer.
95 */
96STATIC xfs_btree_block_t * /* generic btree block pointer */
97xfs_btree_get_block(
98 xfs_btree_cur_t *cur, /* btree cursor */
99 int level, /* level in btree */
100 struct xfs_buf **bpp); /* buffer containing the block */
101
102/*
93 * Checking routine: return maxrecs for the block. 103 * Checking routine: return maxrecs for the block.
94 */ 104 */
95STATIC int /* number of records fitting in block */ 105STATIC int /* number of records fitting in block */
@@ -497,7 +507,7 @@ xfs_btree_firstrec(
497 * Retrieve the block pointer from the cursor at the given level. 507 * Retrieve the block pointer from the cursor at the given level.
498 * This may be a bmap btree root or from a buffer. 508 * This may be a bmap btree root or from a buffer.
499 */ 509 */
500xfs_btree_block_t * /* generic btree block pointer */ 510STATIC xfs_btree_block_t * /* generic btree block pointer */
501xfs_btree_get_block( 511xfs_btree_get_block(
502 xfs_btree_cur_t *cur, /* btree cursor */ 512 xfs_btree_cur_t *cur, /* btree cursor */
503 int level, /* level in btree */ 513 int level, /* level in btree */
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 93872bba41f5..09b4e1532a35 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -325,16 +325,6 @@ xfs_btree_firstrec(
325 int level); /* level to change */ 325 int level); /* level to change */
326 326
327/* 327/*
328 * Retrieve the block pointer from the cursor at the given level.
329 * This may be a bmap btree root or from a buffer.
330 */
331xfs_btree_block_t * /* generic btree block pointer */
332xfs_btree_get_block(
333 xfs_btree_cur_t *cur, /* btree cursor */
334 int level, /* level in btree */
335 struct xfs_buf **bpp); /* buffer containing the block */
336
337/*
338 * Get a buffer for the block, return it with no data read. 328 * Get a buffer for the block, return it with no data read.
339 * Long-form addressing. 329 * Long-form addressing.
340 */ 330 */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 9ab0039f07df..30b8285ad476 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -172,7 +172,7 @@ STATIC void xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip);
172 * 172 *
173 * If the XFS_BLI_STALE flag has been set, then log nothing. 173 * If the XFS_BLI_STALE flag has been set, then log nothing.
174 */ 174 */
175uint 175STATIC uint
176xfs_buf_item_size( 176xfs_buf_item_size(
177 xfs_buf_log_item_t *bip) 177 xfs_buf_log_item_t *bip)
178{ 178{
@@ -240,7 +240,7 @@ xfs_buf_item_size(
240 * format structure, and the rest point to contiguous chunks 240 * format structure, and the rest point to contiguous chunks
241 * within the buffer. 241 * within the buffer.
242 */ 242 */
243void 243STATIC void
244xfs_buf_item_format( 244xfs_buf_item_format(
245 xfs_buf_log_item_t *bip, 245 xfs_buf_log_item_t *bip,
246 xfs_log_iovec_t *log_vector) 246 xfs_log_iovec_t *log_vector)
@@ -365,7 +365,7 @@ xfs_buf_item_format(
365 * item in memory so it cannot be written out. Simply call bpin() 365 * item in memory so it cannot be written out. Simply call bpin()
366 * on the buffer to do this. 366 * on the buffer to do this.
367 */ 367 */
368void 368STATIC void
369xfs_buf_item_pin( 369xfs_buf_item_pin(
370 xfs_buf_log_item_t *bip) 370 xfs_buf_log_item_t *bip)
371{ 371{
@@ -391,7 +391,7 @@ xfs_buf_item_pin(
391 * If the XFS_BLI_STALE flag is set and we are the last reference, 391 * If the XFS_BLI_STALE flag is set and we are the last reference,
392 * then free up the buf log item and unlock the buffer. 392 * then free up the buf log item and unlock the buffer.
393 */ 393 */
394void 394STATIC void
395xfs_buf_item_unpin( 395xfs_buf_item_unpin(
396 xfs_buf_log_item_t *bip, 396 xfs_buf_log_item_t *bip,
397 int stale) 397 int stale)
@@ -446,7 +446,7 @@ xfs_buf_item_unpin(
446 * so we need to free the item's descriptor (that points to the item) 446 * so we need to free the item's descriptor (that points to the item)
447 * in the transaction. 447 * in the transaction.
448 */ 448 */
449void 449STATIC void
450xfs_buf_item_unpin_remove( 450xfs_buf_item_unpin_remove(
451 xfs_buf_log_item_t *bip, 451 xfs_buf_log_item_t *bip,
452 xfs_trans_t *tp) 452 xfs_trans_t *tp)
@@ -493,7 +493,7 @@ xfs_buf_item_unpin_remove(
493 * the lock right away, return 0. If we can get the lock, pull the 493 * the lock right away, return 0. If we can get the lock, pull the
494 * buffer from the free list, mark it busy, and return 1. 494 * buffer from the free list, mark it busy, and return 1.
495 */ 495 */
496uint 496STATIC uint
497xfs_buf_item_trylock( 497xfs_buf_item_trylock(
498 xfs_buf_log_item_t *bip) 498 xfs_buf_log_item_t *bip)
499{ 499{
@@ -537,7 +537,7 @@ xfs_buf_item_trylock(
537 * This is for support of xfs_trans_bhold(). Make sure the 537 * This is for support of xfs_trans_bhold(). Make sure the
538 * XFS_BLI_HOLD field is cleared if we don't free the item. 538 * XFS_BLI_HOLD field is cleared if we don't free the item.
539 */ 539 */
540void 540STATIC void
541xfs_buf_item_unlock( 541xfs_buf_item_unlock(
542 xfs_buf_log_item_t *bip) 542 xfs_buf_log_item_t *bip)
543{ 543{
@@ -635,7 +635,7 @@ xfs_buf_item_unlock(
635 * by returning the original lsn of that transaction here rather than 635 * by returning the original lsn of that transaction here rather than
636 * the current one. 636 * the current one.
637 */ 637 */
638xfs_lsn_t 638STATIC xfs_lsn_t
639xfs_buf_item_committed( 639xfs_buf_item_committed(
640 xfs_buf_log_item_t *bip, 640 xfs_buf_log_item_t *bip,
641 xfs_lsn_t lsn) 641 xfs_lsn_t lsn)
@@ -654,7 +654,7 @@ xfs_buf_item_committed(
654 * and have aborted this transaction, we'll trap this buffer when it tries to 654 * and have aborted this transaction, we'll trap this buffer when it tries to
655 * get written out. 655 * get written out.
656 */ 656 */
657void 657STATIC void
658xfs_buf_item_abort( 658xfs_buf_item_abort(
659 xfs_buf_log_item_t *bip) 659 xfs_buf_log_item_t *bip)
660{ 660{
@@ -674,7 +674,7 @@ xfs_buf_item_abort(
674 * B_DELWRI set, then get it going out to disk with a call to bawrite(). 674 * B_DELWRI set, then get it going out to disk with a call to bawrite().
675 * If not, then just release the buffer. 675 * If not, then just release the buffer.
676 */ 676 */
677void 677STATIC void
678xfs_buf_item_push( 678xfs_buf_item_push(
679 xfs_buf_log_item_t *bip) 679 xfs_buf_log_item_t *bip)
680{ 680{
@@ -693,7 +693,7 @@ xfs_buf_item_push(
693} 693}
694 694
695/* ARGSUSED */ 695/* ARGSUSED */
696void 696STATIC void
697xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn) 697xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
698{ 698{
699} 699}
@@ -701,7 +701,7 @@ xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
701/* 701/*
702 * This is the ops vector shared by all buf log items. 702 * This is the ops vector shared by all buf log items.
703 */ 703 */
704struct xfs_item_ops xfs_buf_item_ops = { 704STATIC struct xfs_item_ops xfs_buf_item_ops = {
705 .iop_size = (uint(*)(xfs_log_item_t*))xfs_buf_item_size, 705 .iop_size = (uint(*)(xfs_log_item_t*))xfs_buf_item_size,
706 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 706 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
707 xfs_buf_item_format, 707 xfs_buf_item_format,
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 5f1b0c9308f6..01aed5f2d579 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -80,7 +80,7 @@ typedef struct xfs_buf_log_format_t {
80 * user or group dquots and may require special recovery handling. 80 * user or group dquots and may require special recovery handling.
81 */ 81 */
82#define XFS_BLI_UDQUOT_BUF 0x4 82#define XFS_BLI_UDQUOT_BUF 0x4
83/* #define XFS_BLI_PDQUOT_BUF 0x8 */ 83#define XFS_BLI_PDQUOT_BUF 0x8
84#define XFS_BLI_GDQUOT_BUF 0x10 84#define XFS_BLI_GDQUOT_BUF 0x10
85 85
86#define XFS_BLI_CHUNK 128 86#define XFS_BLI_CHUNK 128
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index d7fe28866764..8b792ddf2164 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -113,7 +113,10 @@ STATIC void xfs_da_node_unbalance(xfs_da_state_t *state,
113STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count); 113STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
114STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp); 114STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
115STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra); 115STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
116 116STATIC int xfs_da_blk_unlink(xfs_da_state_t *state,
117 xfs_da_state_blk_t *drop_blk,
118 xfs_da_state_blk_t *save_blk);
119STATIC void xfs_da_state_kill_altpath(xfs_da_state_t *state);
117 120
118/*======================================================================== 121/*========================================================================
119 * Routines used for growing the Btree. 122 * Routines used for growing the Btree.
@@ -1424,7 +1427,7 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
1424/* 1427/*
1425 * Unlink a block from a doubly linked list of blocks. 1428 * Unlink a block from a doubly linked list of blocks.
1426 */ 1429 */
1427int /* error */ 1430STATIC int /* error */
1428xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, 1431xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
1429 xfs_da_state_blk_t *save_blk) 1432 xfs_da_state_blk_t *save_blk)
1430{ 1433{
@@ -2381,7 +2384,7 @@ xfs_da_state_alloc(void)
2381/* 2384/*
2382 * Kill the altpath contents of a da-state structure. 2385 * Kill the altpath contents of a da-state structure.
2383 */ 2386 */
2384void 2387STATIC void
2385xfs_da_state_kill_altpath(xfs_da_state_t *state) 2388xfs_da_state_kill_altpath(xfs_da_state_t *state)
2386{ 2389{
2387 int i; 2390 int i;
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 9fc699d96995..3a9b9e809c60 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -296,8 +296,6 @@ int xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
296/* 296/*
297 * Utility routines. 297 * Utility routines.
298 */ 298 */
299int xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
300 xfs_da_state_blk_t *save_blk);
301int xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, 299int xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
302 xfs_da_state_blk_t *new_blk); 300 xfs_da_state_blk_t *new_blk);
303 301
@@ -320,7 +318,6 @@ uint xfs_da_hashname(uchar_t *name_string, int name_length);
320uint xfs_da_log2_roundup(uint i); 318uint xfs_da_log2_roundup(uint i);
321xfs_da_state_t *xfs_da_state_alloc(void); 319xfs_da_state_t *xfs_da_state_alloc(void);
322void xfs_da_state_free(xfs_da_state_t *state); 320void xfs_da_state_free(xfs_da_state_t *state);
323void xfs_da_state_kill_altpath(xfs_da_state_t *state);
324 321
325void xfs_da_buf_done(xfs_dabuf_t *dabuf); 322void xfs_da_buf_done(xfs_dabuf_t *dabuf);
326void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first, 323void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first,
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 63abdc2ac7f4..681be5c93af5 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -180,9 +180,10 @@ xfs_swapext(
180 goto error0; 180 goto error0;
181 } 181 }
182 182
183 if (VN_CACHED(tvp) != 0) 183 if (VN_CACHED(tvp) != 0) {
184 xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore), 184 xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
185 (xfs_off_t)0, 0, 0); 185 VOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED);
186 }
186 187
187 /* Verify O_DIRECT for ftmp */ 188 /* Verify O_DIRECT for ftmp */
188 if (VN_CACHED(tvp) != 0) { 189 if (VN_CACHED(tvp) != 0) {
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index db9887a107de..a0aa0e44ff9d 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -304,7 +304,7 @@ xfs_dir2_data_freeinsert(
304/* 304/*
305 * Remove a bestfree entry from the table. 305 * Remove a bestfree entry from the table.
306 */ 306 */
307void 307STATIC void
308xfs_dir2_data_freeremove( 308xfs_dir2_data_freeremove(
309 xfs_dir2_data_t *d, /* data block pointer */ 309 xfs_dir2_data_t *d, /* data block pointer */
310 xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */ 310 xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index 3f02294ccff0..476cac920bf5 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -193,10 +193,6 @@ extern xfs_dir2_data_free_t *
193 xfs_dir2_data_unused_t *dup, int *loghead); 193 xfs_dir2_data_unused_t *dup, int *loghead);
194 194
195extern void 195extern void
196 xfs_dir2_data_freeremove(xfs_dir2_data_t *d,
197 xfs_dir2_data_free_t *dfp, int *loghead);
198
199extern void
200 xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d, 196 xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
201 int *loghead, char *aendp); 197 int *loghead, char *aendp);
202 198
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 262d1e86df30..056f5283904b 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -77,6 +77,10 @@ static void xfs_dir2_leaf_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
77#endif 77#endif
78static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **lbpp, 78static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **lbpp,
79 int *indexp, xfs_dabuf_t **dbpp); 79 int *indexp, xfs_dabuf_t **dbpp);
80static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
81 int first, int last);
82static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
83
80 84
81/* 85/*
82 * Convert a block form directory to a leaf form directory. 86 * Convert a block form directory to a leaf form directory.
@@ -1214,7 +1218,7 @@ xfs_dir2_leaf_init(
1214/* 1218/*
1215 * Log the bests entries indicated from a leaf1 block. 1219 * Log the bests entries indicated from a leaf1 block.
1216 */ 1220 */
1217void 1221static void
1218xfs_dir2_leaf_log_bests( 1222xfs_dir2_leaf_log_bests(
1219 xfs_trans_t *tp, /* transaction pointer */ 1223 xfs_trans_t *tp, /* transaction pointer */
1220 xfs_dabuf_t *bp, /* leaf buffer */ 1224 xfs_dabuf_t *bp, /* leaf buffer */
@@ -1278,7 +1282,7 @@ xfs_dir2_leaf_log_header(
1278/* 1282/*
1279 * Log the tail of the leaf1 block. 1283 * Log the tail of the leaf1 block.
1280 */ 1284 */
1281void 1285STATIC void
1282xfs_dir2_leaf_log_tail( 1286xfs_dir2_leaf_log_tail(
1283 xfs_trans_t *tp, /* transaction pointer */ 1287 xfs_trans_t *tp, /* transaction pointer */
1284 xfs_dabuf_t *bp) /* leaf buffer */ 1288 xfs_dabuf_t *bp) /* leaf buffer */
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index 7f20eee56a52..3303cd6f4c00 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -330,15 +330,8 @@ extern void
330 int first, int last); 330 int first, int last);
331 331
332extern void 332extern void
333 xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
334 int first, int last);
335
336extern void
337 xfs_dir2_leaf_log_header(struct xfs_trans *tp, struct xfs_dabuf *bp); 333 xfs_dir2_leaf_log_header(struct xfs_trans *tp, struct xfs_dabuf *bp);
338 334
339extern void
340 xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
341
342extern int 335extern int
343 xfs_dir2_leaf_lookup(struct xfs_da_args *args); 336 xfs_dir2_leaf_lookup(struct xfs_da_args *args);
344 337
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index 617018d6bbdc..c2ea6171fb0e 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -91,6 +91,10 @@ STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
91 int *number_entries_in_blk1, 91 int *number_entries_in_blk1,
92 int *number_namebytes_in_blk1); 92 int *number_namebytes_in_blk1);
93 93
94STATIC int xfs_dir_leaf_create(struct xfs_da_args *args,
95 xfs_dablk_t which_block,
96 struct xfs_dabuf **bpp);
97
94/* 98/*
95 * Utility routines. 99 * Utility routines.
96 */ 100 */
@@ -781,7 +785,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args)
781 * Create the initial contents of a leaf directory 785 * Create the initial contents of a leaf directory
782 * or a leaf in a node directory. 786 * or a leaf in a node directory.
783 */ 787 */
784int 788STATIC int
785xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) 789xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
786{ 790{
787 xfs_dir_leafblock_t *leaf; 791 xfs_dir_leafblock_t *leaf;
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
index 00d68d33cc7a..dd423ce1bc8d 100644
--- a/fs/xfs/xfs_dir_leaf.h
+++ b/fs/xfs/xfs_dir_leaf.h
@@ -202,8 +202,6 @@ int xfs_dir_leaf_to_shortform(struct xfs_da_args *args);
202/* 202/*
203 * Routines used for growing the Btree. 203 * Routines used for growing the Btree.
204 */ 204 */
205int xfs_dir_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
206 struct xfs_dabuf **bpp);
207int xfs_dir_leaf_split(struct xfs_da_state *state, 205int xfs_dir_leaf_split(struct xfs_da_state *state,
208 struct xfs_da_state_blk *oldblk, 206 struct xfs_da_state_blk *oldblk,
209 struct xfs_da_state_blk *newblk); 207 struct xfs_da_state_blk *newblk);
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 55ae3e67d245..55c17adaaa37 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -166,27 +166,32 @@ typedef enum {
166#define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */ 166#define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */
167#define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */ 167#define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */
168#define DM_FLAGS_ISEM 0x004 /* thread holds i_sem */ 168#define DM_FLAGS_ISEM 0x004 /* thread holds i_sem */
169#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
170#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)
171/* i_alloc_sem was added in 2.4.22-pre1 */
172#define DM_FLAGS_IALLOCSEM_RD 0x010 /* thread holds i_alloc_sem rd */ 169#define DM_FLAGS_IALLOCSEM_RD 0x010 /* thread holds i_alloc_sem rd */
173#define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ 170#define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */
174#endif
175#endif
176 171
177/* 172/*
178 * Based on IO_ISDIRECT, decide which i_ flag is set. 173 * Based on IO_ISDIRECT, decide which i_ flag is set.
179 */ 174 */
180#ifdef DM_FLAGS_IALLOCSEM_RD 175#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
176#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
177 DM_FLAGS_ISEM : 0)
178#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
179#endif
180
181#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \
182 (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22))
181#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ 183#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
182 DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM) 184 DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM)
183#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM) 185#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
184#else 186#endif
187
188#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21)
185#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ 189#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
186 0 : DM_FLAGS_ISEM) 190 0 : DM_FLAGS_ISEM)
187#define DM_SEM_FLAG_WR (DM_FLAGS_ISEM) 191#define DM_SEM_FLAG_WR (DM_FLAGS_ISEM)
188#endif 192#endif
189 193
194
190/* 195/*
191 * Macros to turn caller specified delay/block flags into 196 * Macros to turn caller specified delay/block flags into
192 * dm_send_xxxx_event flag DM_FLAGS_NDELAY. 197 * dm_send_xxxx_event flag DM_FLAGS_NDELAY.
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index bbe1dea11c08..dcd3fdd5c1f7 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -280,7 +280,7 @@ xfs_error_report(
280 } 280 }
281} 281}
282 282
283void 283STATIC void
284xfs_hex_dump(void *p, int length) 284xfs_hex_dump(void *p, int length)
285{ 285{
286 __uint8_t *uip = (__uint8_t*)p; 286 __uint8_t *uip = (__uint8_t*)p;
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 6bc0535c0a65..52ee2b90b5ed 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -73,9 +73,6 @@ xfs_corruption_error(
73 int linenum, 73 int linenum,
74 inst_t *ra); 74 inst_t *ra);
75 75
76extern void
77xfs_hex_dump(void *p, int length);
78
79#define XFS_ERROR_REPORT(e, lvl, mp) \ 76#define XFS_ERROR_REPORT(e, lvl, mp) \
80 xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address) 77 xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
81#define XFS_CORRUPTION_ERROR(e, lvl, mp, mem) \ 78#define XFS_CORRUPTION_ERROR(e, lvl, mp, mem) \
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 5eafd5b63211..db7cbd1bc857 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -59,6 +59,18 @@ STATIC void xfs_efi_item_abort(xfs_efi_log_item_t *);
59STATIC void xfs_efd_item_abort(xfs_efd_log_item_t *); 59STATIC void xfs_efd_item_abort(xfs_efd_log_item_t *);
60 60
61 61
62void
63xfs_efi_item_free(xfs_efi_log_item_t *efip)
64{
65 int nexts = efip->efi_format.efi_nextents;
66
67 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
68 kmem_free(efip, sizeof(xfs_efi_log_item_t) +
69 (nexts - 1) * sizeof(xfs_extent_t));
70 } else {
71 kmem_zone_free(xfs_efi_zone, efip);
72 }
73}
62 74
63/* 75/*
64 * This returns the number of iovecs needed to log the given efi item. 76 * This returns the number of iovecs needed to log the given efi item.
@@ -120,8 +132,6 @@ xfs_efi_item_pin(xfs_efi_log_item_t *efip)
120STATIC void 132STATIC void
121xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale) 133xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
122{ 134{
123 int nexts;
124 int size;
125 xfs_mount_t *mp; 135 xfs_mount_t *mp;
126 SPLDECL(s); 136 SPLDECL(s);
127 137
@@ -132,21 +142,11 @@ xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
132 * xfs_trans_delete_ail() drops the AIL lock. 142 * xfs_trans_delete_ail() drops the AIL lock.
133 */ 143 */
134 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); 144 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
135 145 xfs_efi_item_free(efip);
136 nexts = efip->efi_format.efi_nextents;
137 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
138 size = sizeof(xfs_efi_log_item_t);
139 size += (nexts - 1) * sizeof(xfs_extent_t);
140 kmem_free(efip, size);
141 } else {
142 kmem_zone_free(xfs_efi_zone, efip);
143 }
144 } else { 146 } else {
145 efip->efi_flags |= XFS_EFI_COMMITTED; 147 efip->efi_flags |= XFS_EFI_COMMITTED;
146 AIL_UNLOCK(mp, s); 148 AIL_UNLOCK(mp, s);
147 } 149 }
148
149 return;
150} 150}
151 151
152/* 152/*
@@ -159,8 +159,6 @@ xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
159STATIC void 159STATIC void
160xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp) 160xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
161{ 161{
162 int nexts;
163 int size;
164 xfs_mount_t *mp; 162 xfs_mount_t *mp;
165 xfs_log_item_desc_t *lidp; 163 xfs_log_item_desc_t *lidp;
166 SPLDECL(s); 164 SPLDECL(s);
@@ -178,23 +176,11 @@ xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
178 * xfs_trans_delete_ail() drops the AIL lock. 176 * xfs_trans_delete_ail() drops the AIL lock.
179 */ 177 */
180 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); 178 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
181 /* 179 xfs_efi_item_free(efip);
182 * now free the item itself
183 */
184 nexts = efip->efi_format.efi_nextents;
185 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
186 size = sizeof(xfs_efi_log_item_t);
187 size += (nexts - 1) * sizeof(xfs_extent_t);
188 kmem_free(efip, size);
189 } else {
190 kmem_zone_free(xfs_efi_zone, efip);
191 }
192 } else { 180 } else {
193 efip->efi_flags |= XFS_EFI_COMMITTED; 181 efip->efi_flags |= XFS_EFI_COMMITTED;
194 AIL_UNLOCK(mp, s); 182 AIL_UNLOCK(mp, s);
195 } 183 }
196
197 return;
198} 184}
199 185
200/* 186/*
@@ -245,18 +231,7 @@ xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
245STATIC void 231STATIC void
246xfs_efi_item_abort(xfs_efi_log_item_t *efip) 232xfs_efi_item_abort(xfs_efi_log_item_t *efip)
247{ 233{
248 int nexts; 234 xfs_efi_item_free(efip);
249 int size;
250
251 nexts = efip->efi_format.efi_nextents;
252 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
253 size = sizeof(xfs_efi_log_item_t);
254 size += (nexts - 1) * sizeof(xfs_extent_t);
255 kmem_free(efip, size);
256 } else {
257 kmem_zone_free(xfs_efi_zone, efip);
258 }
259 return;
260} 235}
261 236
262/* 237/*
@@ -288,7 +263,7 @@ xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
288/* 263/*
289 * This is the ops vector shared by all efi log items. 264 * This is the ops vector shared by all efi log items.
290 */ 265 */
291struct xfs_item_ops xfs_efi_item_ops = { 266STATIC struct xfs_item_ops xfs_efi_item_ops = {
292 .iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size, 267 .iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size,
293 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 268 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
294 xfs_efi_item_format, 269 xfs_efi_item_format,
@@ -355,8 +330,6 @@ xfs_efi_release(xfs_efi_log_item_t *efip,
355{ 330{
356 xfs_mount_t *mp; 331 xfs_mount_t *mp;
357 int extents_left; 332 int extents_left;
358 uint size;
359 int nexts;
360 SPLDECL(s); 333 SPLDECL(s);
361 334
362 mp = efip->efi_item.li_mountp; 335 mp = efip->efi_item.li_mountp;
@@ -372,20 +345,10 @@ xfs_efi_release(xfs_efi_log_item_t *efip,
372 * xfs_trans_delete_ail() drops the AIL lock. 345 * xfs_trans_delete_ail() drops the AIL lock.
373 */ 346 */
374 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); 347 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
348 xfs_efi_item_free(efip);
375 } else { 349 } else {
376 AIL_UNLOCK(mp, s); 350 AIL_UNLOCK(mp, s);
377 } 351 }
378
379 if (extents_left == 0) {
380 nexts = efip->efi_format.efi_nextents;
381 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
382 size = sizeof(xfs_efi_log_item_t);
383 size += (nexts - 1) * sizeof(xfs_extent_t);
384 kmem_free(efip, size);
385 } else {
386 kmem_zone_free(xfs_efi_zone, efip);
387 }
388 }
389} 352}
390 353
391/* 354/*
@@ -398,8 +361,6 @@ STATIC void
398xfs_efi_cancel( 361xfs_efi_cancel(
399 xfs_efi_log_item_t *efip) 362 xfs_efi_log_item_t *efip)
400{ 363{
401 int nexts;
402 int size;
403 xfs_mount_t *mp; 364 xfs_mount_t *mp;
404 SPLDECL(s); 365 SPLDECL(s);
405 366
@@ -410,26 +371,25 @@ xfs_efi_cancel(
410 * xfs_trans_delete_ail() drops the AIL lock. 371 * xfs_trans_delete_ail() drops the AIL lock.
411 */ 372 */
412 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); 373 xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
413 374 xfs_efi_item_free(efip);
414 nexts = efip->efi_format.efi_nextents;
415 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
416 size = sizeof(xfs_efi_log_item_t);
417 size += (nexts - 1) * sizeof(xfs_extent_t);
418 kmem_free(efip, size);
419 } else {
420 kmem_zone_free(xfs_efi_zone, efip);
421 }
422 } else { 375 } else {
423 efip->efi_flags |= XFS_EFI_CANCELED; 376 efip->efi_flags |= XFS_EFI_CANCELED;
424 AIL_UNLOCK(mp, s); 377 AIL_UNLOCK(mp, s);
425 } 378 }
426
427 return;
428} 379}
429 380
381STATIC void
382xfs_efd_item_free(xfs_efd_log_item_t *efdp)
383{
384 int nexts = efdp->efd_format.efd_nextents;
430 385
431 386 if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
432 387 kmem_free(efdp, sizeof(xfs_efd_log_item_t) +
388 (nexts - 1) * sizeof(xfs_extent_t));
389 } else {
390 kmem_zone_free(xfs_efd_zone, efdp);
391 }
392}
433 393
434/* 394/*
435 * This returns the number of iovecs needed to log the given efd item. 395 * This returns the number of iovecs needed to log the given efd item.
@@ -533,9 +493,6 @@ xfs_efd_item_unlock(xfs_efd_log_item_t *efdp)
533STATIC xfs_lsn_t 493STATIC xfs_lsn_t
534xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn) 494xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
535{ 495{
536 uint size;
537 int nexts;
538
539 /* 496 /*
540 * If we got a log I/O error, it's always the case that the LR with the 497 * If we got a log I/O error, it's always the case that the LR with the
541 * EFI got unpinned and freed before the EFD got aborted. 498 * EFI got unpinned and freed before the EFD got aborted.
@@ -543,15 +500,7 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
543 if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0) 500 if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
544 xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents); 501 xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents);
545 502
546 nexts = efdp->efd_format.efd_nextents; 503 xfs_efd_item_free(efdp);
547 if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
548 size = sizeof(xfs_efd_log_item_t);
549 size += (nexts - 1) * sizeof(xfs_extent_t);
550 kmem_free(efdp, size);
551 } else {
552 kmem_zone_free(xfs_efd_zone, efdp);
553 }
554
555 return (xfs_lsn_t)-1; 504 return (xfs_lsn_t)-1;
556} 505}
557 506
@@ -565,9 +514,6 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
565STATIC void 514STATIC void
566xfs_efd_item_abort(xfs_efd_log_item_t *efdp) 515xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
567{ 516{
568 int nexts;
569 int size;
570
571 /* 517 /*
572 * If we got a log I/O error, it's always the case that the LR with the 518 * If we got a log I/O error, it's always the case that the LR with the
573 * EFI got unpinned and freed before the EFD got aborted. So don't 519 * EFI got unpinned and freed before the EFD got aborted. So don't
@@ -576,15 +522,7 @@ xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
576 if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0) 522 if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
577 xfs_efi_cancel(efdp->efd_efip); 523 xfs_efi_cancel(efdp->efd_efip);
578 524
579 nexts = efdp->efd_format.efd_nextents; 525 xfs_efd_item_free(efdp);
580 if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
581 size = sizeof(xfs_efd_log_item_t);
582 size += (nexts - 1) * sizeof(xfs_extent_t);
583 kmem_free(efdp, size);
584 } else {
585 kmem_zone_free(xfs_efd_zone, efdp);
586 }
587 return;
588} 526}
589 527
590/* 528/*
@@ -615,7 +553,7 @@ xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn)
615/* 553/*
616 * This is the ops vector shared by all efd log items. 554 * This is the ops vector shared by all efd log items.
617 */ 555 */
618struct xfs_item_ops xfs_efd_item_ops = { 556STATIC struct xfs_item_ops xfs_efd_item_ops = {
619 .iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size, 557 .iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size,
620 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 558 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
621 xfs_efd_item_format, 559 xfs_efd_item_format,
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 7122d6101d15..d433bac9f59d 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -118,6 +118,8 @@ xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint);
118xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, 118xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
119 uint); 119 uint);
120 120
121void xfs_efi_item_free(xfs_efi_log_item_t *);
122
121#endif /* __KERNEL__ */ 123#endif /* __KERNEL__ */
122 124
123#endif /* __XFS_EXTFREE_ITEM_H__ */ 125#endif /* __XFS_EXTFREE_ITEM_H__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 6ee8443bf9d3..095af0a5cff3 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -60,7 +60,8 @@ struct fsxattr {
60 __u32 fsx_xflags; /* xflags field value (get/set) */ 60 __u32 fsx_xflags; /* xflags field value (get/set) */
61 __u32 fsx_extsize; /* extsize field value (get/set)*/ 61 __u32 fsx_extsize; /* extsize field value (get/set)*/
62 __u32 fsx_nextents; /* nextents field value (get) */ 62 __u32 fsx_nextents; /* nextents field value (get) */
63 unsigned char fsx_pad[16]; 63 __u32 fsx_projid; /* project identifier (get/set) */
64 unsigned char fsx_pad[12];
64}; 65};
65#endif 66#endif
66 67
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 21213057c27f..ca535d613190 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -559,32 +559,6 @@ xfs_reserve_blocks(
559 return(0); 559 return(0);
560} 560}
561 561
562void
563xfs_fs_log_dummy(xfs_mount_t *mp)
564{
565 xfs_trans_t *tp;
566 xfs_inode_t *ip;
567
568
569 tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
570 atomic_inc(&mp->m_active_trans);
571 if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
572 xfs_trans_cancel(tp, 0);
573 return;
574 }
575
576 ip = mp->m_rootip;
577 xfs_ilock(ip, XFS_ILOCK_EXCL);
578
579 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
580 xfs_trans_ihold(tp, ip);
581 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
582 xfs_trans_set_sync(tp);
583 xfs_trans_commit(tp, 0, NULL);
584
585 xfs_iunlock(ip, XFS_ILOCK_EXCL);
586}
587
588int 562int
589xfs_fs_goingdown( 563xfs_fs_goingdown(
590 xfs_mount_t *mp, 564 xfs_mount_t *mp,
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 803c4d17a057..44be188674a6 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -100,9 +100,13 @@ xfs_inofree_t xfs_inobt_mask(int i);
100#endif 100#endif
101#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_IS_FREE) 101#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_IS_FREE)
102int xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i); 102int xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i);
103#define XFS_INOBT_IS_FREE(rp,i) xfs_inobt_is_free(rp,i) 103#define XFS_INOBT_IS_FREE(rp,i) xfs_inobt_is_free(rp,i)
104#define XFS_INOBT_IS_FREE_DISK(rp,i) xfs_inobt_is_free_disk(rp,i)
104#else 105#else
105#define XFS_INOBT_IS_FREE(rp,i) (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0) 106#define XFS_INOBT_IS_FREE(rp,i) \
107 (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
108#define XFS_INOBT_IS_FREE_DISK(rp,i) \
109 ((INT_GET((rp)->ir_free, ARCH_CONVERT) & XFS_INOBT_MASK(i)) != 0)
106#endif 110#endif
107#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_SET_FREE) 111#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_SET_FREE)
108void xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i); 112void xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index bc8c8c7f9039..34bdf5909687 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -146,51 +146,6 @@ xfs_inobp_check(
146#endif 146#endif
147 147
148/* 148/*
149 * called from bwrite on xfs inode buffers
150 */
151void
152xfs_inobp_bwcheck(xfs_buf_t *bp)
153{
154 xfs_mount_t *mp;
155 int i;
156 int j;
157 xfs_dinode_t *dip;
158
159 ASSERT(XFS_BUF_FSPRIVATE3(bp, void *) != NULL);
160
161 mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
162
163
164 j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog;
165
166 for (i = 0; i < j; i++) {
167 dip = (xfs_dinode_t *) xfs_buf_offset(bp,
168 i * mp->m_sb.sb_inodesize);
169 if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
170 cmn_err(CE_WARN,
171"Bad magic # 0x%x in XFS inode buffer 0x%Lx, starting blockno %Ld, offset 0x%x",
172 INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
173 (__uint64_t)(__psunsigned_t) bp,
174 (__int64_t) XFS_BUF_ADDR(bp),
175 xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
176 xfs_fs_cmn_err(CE_WARN, mp,
177 "corrupt, unmount and run xfs_repair");
178 }
179 if (!dip->di_next_unlinked) {
180 cmn_err(CE_WARN,
181"Bad next_unlinked field (0) in XFS inode buffer 0x%p, starting blockno %Ld, offset 0x%x",
182 (__uint64_t)(__psunsigned_t) bp,
183 (__int64_t) XFS_BUF_ADDR(bp),
184 xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
185 xfs_fs_cmn_err(CE_WARN, mp,
186 "corrupt, unmount and run xfs_repair");
187 }
188 }
189
190 return;
191}
192
193/*
194 * This routine is called to map an inode number within a file 149 * This routine is called to map an inode number within a file
195 * system to the buffer containing the on-disk version of the 150 * system to the buffer containing the on-disk version of the
196 * inode. It returns a pointer to the buffer containing the 151 * inode. It returns a pointer to the buffer containing the
@@ -203,7 +158,7 @@ xfs_inobp_bwcheck(xfs_buf_t *bp)
203 * Use xfs_imap() to determine the size and location of the 158 * Use xfs_imap() to determine the size and location of the
204 * buffer to read from disk. 159 * buffer to read from disk.
205 */ 160 */
206int 161STATIC int
207xfs_inotobp( 162xfs_inotobp(
208 xfs_mount_t *mp, 163 xfs_mount_t *mp,
209 xfs_trans_t *tp, 164 xfs_trans_t *tp,
@@ -1247,26 +1202,32 @@ xfs_ialloc(
1247 case S_IFREG: 1202 case S_IFREG:
1248 case S_IFDIR: 1203 case S_IFDIR:
1249 if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) { 1204 if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
1250 if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) { 1205 uint di_flags = 0;
1251 if ((mode & S_IFMT) == S_IFDIR) { 1206
1252 ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT; 1207 if ((mode & S_IFMT) == S_IFDIR) {
1253 } else { 1208 if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
1254 ip->i_d.di_flags |= XFS_DIFLAG_REALTIME; 1209 di_flags |= XFS_DIFLAG_RTINHERIT;
1210 } else {
1211 if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
1212 di_flags |= XFS_DIFLAG_REALTIME;
1255 ip->i_iocore.io_flags |= XFS_IOCORE_RT; 1213 ip->i_iocore.io_flags |= XFS_IOCORE_RT;
1256 } 1214 }
1257 } 1215 }
1258 if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) && 1216 if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
1259 xfs_inherit_noatime) 1217 xfs_inherit_noatime)
1260 ip->i_d.di_flags |= XFS_DIFLAG_NOATIME; 1218 di_flags |= XFS_DIFLAG_NOATIME;
1261 if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) && 1219 if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) &&
1262 xfs_inherit_nodump) 1220 xfs_inherit_nodump)
1263 ip->i_d.di_flags |= XFS_DIFLAG_NODUMP; 1221 di_flags |= XFS_DIFLAG_NODUMP;
1264 if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) && 1222 if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
1265 xfs_inherit_sync) 1223 xfs_inherit_sync)
1266 ip->i_d.di_flags |= XFS_DIFLAG_SYNC; 1224 di_flags |= XFS_DIFLAG_SYNC;
1267 if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) && 1225 if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
1268 xfs_inherit_nosymlinks) 1226 xfs_inherit_nosymlinks)
1269 ip->i_d.di_flags |= XFS_DIFLAG_NOSYMLINKS; 1227 di_flags |= XFS_DIFLAG_NOSYMLINKS;
1228 if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
1229 di_flags |= XFS_DIFLAG_PROJINHERIT;
1230 ip->i_d.di_flags |= di_flags;
1270 } 1231 }
1271 /* FALLTHROUGH */ 1232 /* FALLTHROUGH */
1272 case S_IFLNK: 1233 case S_IFLNK:
@@ -2156,7 +2117,7 @@ static __inline__ int xfs_inode_clean(xfs_inode_t *ip)
2156 (ip->i_update_core == 0)); 2117 (ip->i_update_core == 0));
2157} 2118}
2158 2119
2159void 2120STATIC void
2160xfs_ifree_cluster( 2121xfs_ifree_cluster(
2161 xfs_inode_t *free_ip, 2122 xfs_inode_t *free_ip,
2162 xfs_trans_t *tp, 2123 xfs_trans_t *tp,
@@ -2875,7 +2836,7 @@ xfs_iunpin(
2875 * be subsequently pinned once someone is waiting for it to be 2836 * be subsequently pinned once someone is waiting for it to be
2876 * unpinned. 2837 * unpinned.
2877 */ 2838 */
2878void 2839STATIC void
2879xfs_iunpin_wait( 2840xfs_iunpin_wait(
2880 xfs_inode_t *ip) 2841 xfs_inode_t *ip)
2881{ 2842{
@@ -3601,107 +3562,43 @@ corrupt_out:
3601 3562
3602 3563
3603/* 3564/*
3604 * Flush all inactive inodes in mp. Return true if no user references 3565 * Flush all inactive inodes in mp.
3605 * were found, false otherwise.
3606 */ 3566 */
3607int 3567void
3608xfs_iflush_all( 3568xfs_iflush_all(
3609 xfs_mount_t *mp, 3569 xfs_mount_t *mp)
3610 int flag)
3611{ 3570{
3612 int busy;
3613 int done;
3614 int purged;
3615 xfs_inode_t *ip; 3571 xfs_inode_t *ip;
3616 vmap_t vmap;
3617 vnode_t *vp; 3572 vnode_t *vp;
3618 3573
3619 busy = done = 0; 3574 again:
3620 while (!done) { 3575 XFS_MOUNT_ILOCK(mp);
3621 purged = 0; 3576 ip = mp->m_inodes;
3622 XFS_MOUNT_ILOCK(mp); 3577 if (ip == NULL)
3623 ip = mp->m_inodes; 3578 goto out;
3624 if (ip == NULL) {
3625 break;
3626 }
3627 do {
3628 /* Make sure we skip markers inserted by sync */
3629 if (ip->i_mount == NULL) {
3630 ip = ip->i_mnext;
3631 continue;
3632 }
3633
3634 /*
3635 * It's up to our caller to purge the root
3636 * and quota vnodes later.
3637 */
3638 vp = XFS_ITOV_NULL(ip);
3639
3640 if (!vp) {
3641 XFS_MOUNT_IUNLOCK(mp);
3642 xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
3643 purged = 1;
3644 break;
3645 }
3646 3579
3647 if (vn_count(vp) != 0) { 3580 do {
3648 if (vn_count(vp) == 1 && 3581 /* Make sure we skip markers inserted by sync */
3649 (ip == mp->m_rootip || 3582 if (ip->i_mount == NULL) {
3650 (mp->m_quotainfo && 3583 ip = ip->i_mnext;
3651 (ip->i_ino == mp->m_sb.sb_uquotino || 3584 continue;
3652 ip->i_ino == mp->m_sb.sb_gquotino)))) { 3585 }
3653 3586
3654 ip = ip->i_mnext; 3587 vp = XFS_ITOV_NULL(ip);
3655 continue; 3588 if (!vp) {
3656 }
3657 if (!(flag & XFS_FLUSH_ALL)) {
3658 busy = 1;
3659 done = 1;
3660 break;
3661 }
3662 /*
3663 * Ignore busy inodes but continue flushing
3664 * others.
3665 */
3666 ip = ip->i_mnext;
3667 continue;
3668 }
3669 /*
3670 * Sample vp mapping while holding mp locked on MP
3671 * systems, so we don't purge a reclaimed or
3672 * nonexistent vnode. We break from the loop
3673 * since we know that we modify
3674 * it by pulling ourselves from it in xfs_reclaim()
3675 * called via vn_purge() below. Set ip to the next
3676 * entry in the list anyway so we'll know below
3677 * whether we reached the end or not.
3678 */
3679 VMAP(vp, vmap);
3680 XFS_MOUNT_IUNLOCK(mp); 3589 XFS_MOUNT_IUNLOCK(mp);
3590 xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
3591 goto again;
3592 }
3681 3593
3682 vn_purge(vp, &vmap); 3594 ASSERT(vn_count(vp) == 0);
3683 3595
3684 purged = 1; 3596 ip = ip->i_mnext;
3685 break; 3597 } while (ip != mp->m_inodes);
3686 } while (ip != mp->m_inodes); 3598 out:
3687 /*
3688 * We need to distinguish between when we exit the loop
3689 * after a purge and when we simply hit the end of the
3690 * list. We can't use the (ip == mp->m_inodes) test,
3691 * because when we purge an inode at the start of the list
3692 * the next inode on the list becomes mp->m_inodes. That
3693 * would cause such a test to bail out early. The purged
3694 * variable tells us how we got out of the loop.
3695 */
3696 if (!purged) {
3697 done = 1;
3698 }
3699 }
3700 XFS_MOUNT_IUNLOCK(mp); 3599 XFS_MOUNT_IUNLOCK(mp);
3701 return !busy;
3702} 3600}
3703 3601
3704
3705/* 3602/*
3706 * xfs_iaccess: check accessibility of inode for mode. 3603 * xfs_iaccess: check accessibility of inode for mode.
3707 */ 3604 */
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 37e1c316f3b6..54d9e54c7c95 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -412,11 +412,6 @@ void xfs_ifork_next_set(xfs_inode_t *ip, int w, int n);
412#define XFS_IFLUSH_DELWRI 5 412#define XFS_IFLUSH_DELWRI 5
413 413
414/* 414/*
415 * Flags for xfs_iflush_all.
416 */
417#define XFS_FLUSH_ALL 0x1
418
419/*
420 * Flags for xfs_itruncate_start(). 415 * Flags for xfs_itruncate_start().
421 */ 416 */
422#define XFS_ITRUNC_DEFINITE 0x1 417#define XFS_ITRUNC_DEFINITE 0x1
@@ -487,8 +482,6 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
487/* 482/*
488 * xfs_inode.c prototypes. 483 * xfs_inode.c prototypes.
489 */ 484 */
490int xfs_inotobp(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
491 xfs_dinode_t **, struct xfs_buf **, int *);
492int xfs_itobp(struct xfs_mount *, struct xfs_trans *, 485int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
493 xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **, 486 xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
494 xfs_daddr_t); 487 xfs_daddr_t);
@@ -522,7 +515,7 @@ void xfs_ipin(xfs_inode_t *);
522void xfs_iunpin(xfs_inode_t *); 515void xfs_iunpin(xfs_inode_t *);
523int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int); 516int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
524int xfs_iflush(xfs_inode_t *, uint); 517int xfs_iflush(xfs_inode_t *, uint);
525int xfs_iflush_all(struct xfs_mount *, int); 518void xfs_iflush_all(struct xfs_mount *);
526int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *); 519int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
527uint xfs_iroundup(uint); 520uint xfs_iroundup(uint);
528void xfs_ichgtime(xfs_inode_t *, int); 521void xfs_ichgtime(xfs_inode_t *, int);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 768cb1816b8e..0eed30f5cb19 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -910,7 +910,7 @@ xfs_inode_item_committing(
910/* 910/*
911 * This is the ops vector shared by all buf log items. 911 * This is the ops vector shared by all buf log items.
912 */ 912 */
913struct xfs_item_ops xfs_inode_item_ops = { 913STATIC struct xfs_item_ops xfs_inode_item_ops = {
914 .iop_size = (uint(*)(xfs_log_item_t*))xfs_inode_item_size, 914 .iop_size = (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
915 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 915 .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
916 xfs_inode_item_format, 916 xfs_inode_item_format,
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 991f8a61f7c4..2edd6769e5d3 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -278,7 +278,9 @@ phase2:
278 switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { 278 switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
279 case BMAPI_WRITE: 279 case BMAPI_WRITE:
280 /* If we found an extent, return it */ 280 /* If we found an extent, return it */
281 if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) { 281 if (nimaps &&
282 (imap.br_startblock != HOLESTARTBLOCK) &&
283 (imap.br_startblock != DELAYSTARTBLOCK)) {
282 xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, 284 xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
283 offset, count, iomapp, &imap, flags); 285 offset, count, iomapp, &imap, flags);
284 break; 286 break;
@@ -383,15 +385,15 @@ xfs_iomap_write_direct(
383 int nimaps, maps; 385 int nimaps, maps;
384 int error; 386 int error;
385 int bmapi_flag; 387 int bmapi_flag;
388 int quota_flag;
386 int rt; 389 int rt;
387 xfs_trans_t *tp; 390 xfs_trans_t *tp;
388 xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; 391 xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
389 xfs_bmap_free_t free_list; 392 xfs_bmap_free_t free_list;
390 int aeof; 393 int aeof;
391 xfs_filblks_t datablocks; 394 xfs_filblks_t datablocks, qblocks, resblks;
392 int committed; 395 int committed;
393 int numrtextents; 396 int numrtextents;
394 uint resblks;
395 397
396 /* 398 /*
397 * Make sure that the dquots are there. This doesn't hold 399 * Make sure that the dquots are there. This doesn't hold
@@ -417,7 +419,6 @@ xfs_iomap_write_direct(
417 xfs_fileoff_t map_last_fsb; 419 xfs_fileoff_t map_last_fsb;
418 420
419 map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; 421 map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
420
421 if (map_last_fsb < last_fsb) { 422 if (map_last_fsb < last_fsb) {
422 last_fsb = map_last_fsb; 423 last_fsb = map_last_fsb;
423 count_fsb = last_fsb - offset_fsb; 424 count_fsb = last_fsb - offset_fsb;
@@ -426,56 +427,47 @@ xfs_iomap_write_direct(
426 } 427 }
427 428
428 /* 429 /*
429 * determine if reserving space on 430 * Determine if reserving space on the data or realtime partition.
430 * the data or realtime partition.
431 */ 431 */
432 if ((rt = XFS_IS_REALTIME_INODE(ip))) { 432 if ((rt = XFS_IS_REALTIME_INODE(ip))) {
433 int sbrtextsize, iprtextsize; 433 xfs_extlen_t extsz;
434 434
435 sbrtextsize = mp->m_sb.sb_rextsize; 435 if (!(extsz = ip->i_d.di_extsize))
436 iprtextsize = 436 extsz = mp->m_sb.sb_rextsize;
437 ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; 437 numrtextents = qblocks = (count_fsb + extsz - 1);
438 numrtextents = (count_fsb + iprtextsize - 1); 438 do_div(numrtextents, mp->m_sb.sb_rextsize);
439 do_div(numrtextents, sbrtextsize); 439 quota_flag = XFS_QMOPT_RES_RTBLKS;
440 datablocks = 0; 440 datablocks = 0;
441 } else { 441 } else {
442 datablocks = count_fsb; 442 datablocks = qblocks = count_fsb;
443 quota_flag = XFS_QMOPT_RES_REGBLKS;
443 numrtextents = 0; 444 numrtextents = 0;
444 } 445 }
445 446
446 /* 447 /*
447 * allocate and setup the transaction 448 * Allocate and setup the transaction
448 */ 449 */
449 xfs_iunlock(ip, XFS_ILOCK_EXCL); 450 xfs_iunlock(ip, XFS_ILOCK_EXCL);
450 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); 451 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
451
452 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); 452 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
453
454 error = xfs_trans_reserve(tp, resblks, 453 error = xfs_trans_reserve(tp, resblks,
455 XFS_WRITE_LOG_RES(mp), numrtextents, 454 XFS_WRITE_LOG_RES(mp), numrtextents,
456 XFS_TRANS_PERM_LOG_RES, 455 XFS_TRANS_PERM_LOG_RES,
457 XFS_WRITE_LOG_COUNT); 456 XFS_WRITE_LOG_COUNT);
458 457
459 /* 458 /*
460 * check for running out of space 459 * Check for running out of space, note: need lock to return
461 */ 460 */
462 if (error) 461 if (error)
463 /*
464 * Free the transaction structure.
465 */
466 xfs_trans_cancel(tp, 0); 462 xfs_trans_cancel(tp, 0);
467
468 xfs_ilock(ip, XFS_ILOCK_EXCL); 463 xfs_ilock(ip, XFS_ILOCK_EXCL);
469
470 if (error) 464 if (error)
471 goto error_out; /* Don't return in above if .. trans .., 465 goto error_out;
472 need lock to return */
473 466
474 if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { 467 if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
475 error = (EDQUOT); 468 error = (EDQUOT);
476 goto error1; 469 goto error1;
477 } 470 }
478 nimaps = 1;
479 471
480 bmapi_flag = XFS_BMAPI_WRITE; 472 bmapi_flag = XFS_BMAPI_WRITE;
481 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 473 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -485,31 +477,29 @@ xfs_iomap_write_direct(
485 bmapi_flag |= XFS_BMAPI_PREALLOC; 477 bmapi_flag |= XFS_BMAPI_PREALLOC;
486 478
487 /* 479 /*
488 * issue the bmapi() call to allocate the blocks 480 * Issue the bmapi() call to allocate the blocks
489 */ 481 */
490 XFS_BMAP_INIT(&free_list, &firstfsb); 482 XFS_BMAP_INIT(&free_list, &firstfsb);
483 nimaps = 1;
491 imapp = &imap[0]; 484 imapp = &imap[0];
492 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, 485 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
493 bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); 486 bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
494 if (error) { 487 if (error)
495 goto error0; 488 goto error0;
496 }
497 489
498 /* 490 /*
499 * complete the transaction 491 * Complete the transaction
500 */ 492 */
501
502 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); 493 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
503 if (error) { 494 if (error)
504 goto error0; 495 goto error0;
505 }
506
507 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); 496 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
508 if (error) { 497 if (error)
509 goto error_out; 498 goto error_out;
510 }
511 499
512 /* copy any maps to caller's array and return any error. */ 500 /*
501 * Copy any maps to caller's array and return any error.
502 */
513 if (nimaps == 0) { 503 if (nimaps == 0) {
514 error = (ENOSPC); 504 error = (ENOSPC);
515 goto error_out; 505 goto error_out;
@@ -528,10 +518,11 @@ xfs_iomap_write_direct(
528 } 518 }
529 return 0; 519 return 0;
530 520
531 error0: /* Cancel bmap, unlock inode, and cancel trans */ 521error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
532 xfs_bmap_cancel(&free_list); 522 xfs_bmap_cancel(&free_list);
523 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
533 524
534 error1: /* Just cancel transaction */ 525error1: /* Just cancel transaction */
535 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 526 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
536 *nmaps = 0; /* nothing set-up here */ 527 *nmaps = 0; /* nothing set-up here */
537 528
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 092d5fb096b1..1cd2ac163877 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -134,7 +134,7 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
134#define xlog_verify_tail_lsn(a,b,c) 134#define xlog_verify_tail_lsn(a,b,c)
135#endif 135#endif
136 136
137int xlog_iclogs_empty(xlog_t *log); 137STATIC int xlog_iclogs_empty(xlog_t *log);
138 138
139#ifdef DEBUG 139#ifdef DEBUG
140int xlog_do_error = 0; 140int xlog_do_error = 0;
@@ -1857,7 +1857,7 @@ xlog_write(xfs_mount_t * mp,
1857 * 1857 *
1858 * State Change: DIRTY -> ACTIVE 1858 * State Change: DIRTY -> ACTIVE
1859 */ 1859 */
1860void 1860STATIC void
1861xlog_state_clean_log(xlog_t *log) 1861xlog_state_clean_log(xlog_t *log)
1862{ 1862{
1863 xlog_in_core_t *iclog; 1863 xlog_in_core_t *iclog;
@@ -3542,7 +3542,7 @@ xfs_log_force_umount(
3542 return (retval); 3542 return (retval);
3543} 3543}
3544 3544
3545int 3545STATIC int
3546xlog_iclogs_empty(xlog_t *log) 3546xlog_iclogs_empty(xlog_t *log)
3547{ 3547{
3548 xlog_in_core_t *iclog; 3548 xlog_in_core_t *iclog;
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index c31e3ce3be66..1a1d452f15f9 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -535,7 +535,6 @@ typedef struct log {
535 535
536/* common routines */ 536/* common routines */
537extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); 537extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
538extern int xlog_find_head(xlog_t *log, xfs_daddr_t *head_blk);
539extern int xlog_find_tail(xlog_t *log, 538extern int xlog_find_tail(xlog_t *log,
540 xfs_daddr_t *head_blk, 539 xfs_daddr_t *head_blk,
541 xfs_daddr_t *tail_blk, 540 xfs_daddr_t *tail_blk,
@@ -548,7 +547,6 @@ extern void xlog_recover_process_iunlinks(xlog_t *log);
548extern struct xfs_buf *xlog_get_bp(xlog_t *, int); 547extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
549extern void xlog_put_bp(struct xfs_buf *); 548extern void xlog_put_bp(struct xfs_buf *);
550extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *); 549extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
551extern xfs_caddr_t xlog_align(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
552 550
553/* iclog tracing */ 551/* iclog tracing */
554#define XLOG_TRACE_GRAB_FLUSH 1 552#define XLOG_TRACE_GRAB_FLUSH 1
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 9824b5bf0ec0..0aac28ddb81c 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -148,7 +148,7 @@ xlog_bread(
148 * The buffer is kept locked across the write and is returned locked. 148 * The buffer is kept locked across the write and is returned locked.
149 * This can only be used for synchronous log writes. 149 * This can only be used for synchronous log writes.
150 */ 150 */
151int 151STATIC int
152xlog_bwrite( 152xlog_bwrite(
153 xlog_t *log, 153 xlog_t *log,
154 xfs_daddr_t blk_no, 154 xfs_daddr_t blk_no,
@@ -179,7 +179,7 @@ xlog_bwrite(
179 return error; 179 return error;
180} 180}
181 181
182xfs_caddr_t 182STATIC xfs_caddr_t
183xlog_align( 183xlog_align(
184 xlog_t *log, 184 xlog_t *log,
185 xfs_daddr_t blk_no, 185 xfs_daddr_t blk_no,
@@ -528,7 +528,7 @@ out:
528 * 528 *
529 * Return: zero if normal, non-zero if error. 529 * Return: zero if normal, non-zero if error.
530 */ 530 */
531int 531STATIC int
532xlog_find_head( 532xlog_find_head(
533 xlog_t *log, 533 xlog_t *log,
534 xfs_daddr_t *return_head_blk) 534 xfs_daddr_t *return_head_blk)
@@ -1964,7 +1964,8 @@ xlog_recover_do_reg_buffer(
1964 * probably a good thing to do for other buf types also. 1964 * probably a good thing to do for other buf types also.
1965 */ 1965 */
1966 error = 0; 1966 error = 0;
1967 if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { 1967 if (buf_f->blf_flags &
1968 (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
1968 error = xfs_qm_dqcheck((xfs_disk_dquot_t *) 1969 error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
1969 item->ri_buf[i].i_addr, 1970 item->ri_buf[i].i_addr,
1970 -1, 0, XFS_QMOPT_DOWARN, 1971 -1, 0, XFS_QMOPT_DOWARN,
@@ -2030,6 +2031,7 @@ xfs_qm_dqcheck(
2030 } 2031 }
2031 2032
2032 if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER && 2033 if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER &&
2034 INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_PROJ &&
2033 INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) { 2035 INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) {
2034 if (flags & XFS_QMOPT_DOWARN) 2036 if (flags & XFS_QMOPT_DOWARN)
2035 cmn_err(CE_ALERT, 2037 cmn_err(CE_ALERT,
@@ -2135,6 +2137,8 @@ xlog_recover_do_dquot_buffer(
2135 type = 0; 2137 type = 0;
2136 if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF) 2138 if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF)
2137 type |= XFS_DQ_USER; 2139 type |= XFS_DQ_USER;
2140 if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF)
2141 type |= XFS_DQ_PROJ;
2138 if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF) 2142 if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF)
2139 type |= XFS_DQ_GROUP; 2143 type |= XFS_DQ_GROUP;
2140 /* 2144 /*
@@ -2247,7 +2251,8 @@ xlog_recover_do_buffer_trans(
2247 error = 0; 2251 error = 0;
2248 if (flags & XFS_BLI_INODE_BUF) { 2252 if (flags & XFS_BLI_INODE_BUF) {
2249 error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); 2253 error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
2250 } else if (flags & (XFS_BLI_UDQUOT_BUF | XFS_BLI_GDQUOT_BUF)) { 2254 } else if (flags &
2255 (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
2251 xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); 2256 xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
2252 } else { 2257 } else {
2253 xlog_recover_do_reg_buffer(mp, item, bp, buf_f); 2258 xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
@@ -2619,7 +2624,7 @@ xlog_recover_do_dquot_trans(
2619 * This type of quotas was turned off, so ignore this record. 2624 * This type of quotas was turned off, so ignore this record.
2620 */ 2625 */
2621 type = INT_GET(recddq->d_flags, ARCH_CONVERT) & 2626 type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
2622 (XFS_DQ_USER | XFS_DQ_GROUP); 2627 (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
2623 ASSERT(type); 2628 ASSERT(type);
2624 if (log->l_quotaoffs_flag & type) 2629 if (log->l_quotaoffs_flag & type)
2625 return (0); 2630 return (0);
@@ -2742,7 +2747,6 @@ xlog_recover_do_efd_trans(
2742 xfs_efi_log_item_t *efip = NULL; 2747 xfs_efi_log_item_t *efip = NULL;
2743 xfs_log_item_t *lip; 2748 xfs_log_item_t *lip;
2744 int gen; 2749 int gen;
2745 int nexts;
2746 __uint64_t efi_id; 2750 __uint64_t efi_id;
2747 SPLDECL(s); 2751 SPLDECL(s);
2748 2752
@@ -2777,22 +2781,15 @@ xlog_recover_do_efd_trans(
2777 } 2781 }
2778 lip = xfs_trans_next_ail(mp, lip, &gen, NULL); 2782 lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
2779 } 2783 }
2780 if (lip == NULL) {
2781 AIL_UNLOCK(mp, s);
2782 }
2783 2784
2784 /* 2785 /*
2785 * If we found it, then free it up. If it wasn't there, it 2786 * If we found it, then free it up. If it wasn't there, it
2786 * must have been overwritten in the log. Oh well. 2787 * must have been overwritten in the log. Oh well.
2787 */ 2788 */
2788 if (lip != NULL) { 2789 if (lip != NULL) {
2789 nexts = efip->efi_format.efi_nextents; 2790 xfs_efi_item_free(efip);
2790 if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { 2791 } else {
2791 kmem_free(lip, sizeof(xfs_efi_log_item_t) + 2792 AIL_UNLOCK(mp, s);
2792 ((nexts - 1) * sizeof(xfs_extent_t)));
2793 } else {
2794 kmem_zone_free(xfs_efi_zone, efip);
2795 }
2796 } 2793 }
2797} 2794}
2798 2795
diff --git a/fs/xfs/xfs_macros.c b/fs/xfs/xfs_macros.c
index ce4f46c6b3ab..698c2cd62858 100644
--- a/fs/xfs/xfs_macros.c
+++ b/fs/xfs/xfs_macros.c
@@ -1658,6 +1658,11 @@ xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i)
1658{ 1658{
1659 return XFS_INOBT_IS_FREE(rp, i); 1659 return XFS_INOBT_IS_FREE(rp, i);
1660} 1660}
1661int
1662xfs_inobt_is_free_disk(xfs_inobt_rec_t *rp, int i)
1663{
1664 return XFS_INOBT_IS_FREE_DISK(rp, i);
1665}
1661#endif 1666#endif
1662 1667
1663#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_IS_LAST_REC) 1668#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_IS_LAST_REC)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 2ec967d93e5a..82e1646e6243 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -64,6 +64,7 @@
64STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t); 64STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
65STATIC int xfs_uuid_mount(xfs_mount_t *); 65STATIC int xfs_uuid_mount(xfs_mount_t *);
66STATIC void xfs_uuid_unmount(xfs_mount_t *mp); 66STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
67STATIC void xfs_unmountfs_wait(xfs_mount_t *);
67 68
68static struct { 69static struct {
69 short offset; 70 short offset;
@@ -555,7 +556,7 @@ xfs_readsb(xfs_mount_t *mp)
555 * fields from the superblock associated with the given 556 * fields from the superblock associated with the given
556 * mount structure 557 * mount structure
557 */ 558 */
558void 559STATIC void
559xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) 560xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
560{ 561{
561 int i; 562 int i;
@@ -1081,7 +1082,7 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1081 int64_t fsid; 1082 int64_t fsid;
1082#endif 1083#endif
1083 1084
1084 xfs_iflush_all(mp, XFS_FLUSH_ALL); 1085 xfs_iflush_all(mp);
1085 1086
1086 XFS_QM_DQPURGEALL(mp, 1087 XFS_QM_DQPURGEALL(mp,
1087 XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING); 1088 XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING);
@@ -1111,15 +1112,6 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1111 */ 1112 */
1112 ASSERT(mp->m_inodes == NULL); 1113 ASSERT(mp->m_inodes == NULL);
1113 1114
1114 /*
1115 * We may have bufs that are in the process of getting written still.
1116 * We must wait for the I/O completion of those. The sync flag here
1117 * does a two pass iteration thru the bufcache.
1118 */
1119 if (XFS_FORCED_SHUTDOWN(mp)) {
1120 xfs_incore_relse(mp->m_ddev_targp, 0, 1); /* synchronous */
1121 }
1122
1123 xfs_unmountfs_close(mp, cr); 1115 xfs_unmountfs_close(mp, cr);
1124 if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) 1116 if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
1125 xfs_uuid_unmount(mp); 1117 xfs_uuid_unmount(mp);
@@ -1146,7 +1138,7 @@ xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
1146 xfs_free_buftarg(mp->m_ddev_targp, 0); 1138 xfs_free_buftarg(mp->m_ddev_targp, 0);
1147} 1139}
1148 1140
1149void 1141STATIC void
1150xfs_unmountfs_wait(xfs_mount_t *mp) 1142xfs_unmountfs_wait(xfs_mount_t *mp)
1151{ 1143{
1152 if (mp->m_logdev_targp != mp->m_ddev_targp) 1144 if (mp->m_logdev_targp != mp->m_ddev_targp)
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 30dd08fb9f57..5affba38a577 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -141,7 +141,7 @@ typedef int (*xfs_dqattach_t)(struct xfs_inode *, uint);
141typedef void (*xfs_dqdetach_t)(struct xfs_inode *); 141typedef void (*xfs_dqdetach_t)(struct xfs_inode *);
142typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint); 142typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint);
143typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *, 143typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *,
144 struct xfs_inode *, uid_t, gid_t, uint, 144 struct xfs_inode *, uid_t, gid_t, prid_t, uint,
145 struct xfs_dquot **, struct xfs_dquot **); 145 struct xfs_dquot **, struct xfs_dquot **);
146typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *, 146typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *,
147 struct xfs_dquot *, struct xfs_dquot *); 147 struct xfs_dquot *, struct xfs_dquot *);
@@ -185,8 +185,8 @@ typedef struct xfs_qmops {
185 (*(mp)->m_qm_ops.xfs_dqdetach)(ip) 185 (*(mp)->m_qm_ops.xfs_dqdetach)(ip)
186#define XFS_QM_DQPURGEALL(mp, fl) \ 186#define XFS_QM_DQPURGEALL(mp, fl) \
187 (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl) 187 (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
188#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, fl, dq1, dq2) \ 188#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
189 (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, fl, dq1, dq2) 189 (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
190#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \ 190#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
191 (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2) 191 (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
192#define XFS_QM_DQVOPRENAME(mp, ip) \ 192#define XFS_QM_DQVOPRENAME(mp, ip) \
@@ -544,7 +544,6 @@ extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
544extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int); 544extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int);
545 545
546extern int xfs_unmountfs(xfs_mount_t *, struct cred *); 546extern int xfs_unmountfs(xfs_mount_t *, struct cred *);
547extern void xfs_unmountfs_wait(xfs_mount_t *);
548extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *); 547extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *);
549extern int xfs_unmountfs_writesb(xfs_mount_t *); 548extern int xfs_unmountfs_writesb(xfs_mount_t *);
550extern int xfs_unmount_flush(xfs_mount_t *, int); 549extern int xfs_unmount_flush(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 703ec4efcb41..7134576ae7fa 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -96,7 +96,7 @@ typedef struct xfs_dqblk {
96 * flags for q_flags field in the dquot. 96 * flags for q_flags field in the dquot.
97 */ 97 */
98#define XFS_DQ_USER 0x0001 /* a user quota */ 98#define XFS_DQ_USER 0x0001 /* a user quota */
99/* #define XFS_DQ_PROJ 0x0002 -- project quota (IRIX) */ 99#define XFS_DQ_PROJ 0x0002 /* project quota */
100#define XFS_DQ_GROUP 0x0004 /* a group quota */ 100#define XFS_DQ_GROUP 0x0004 /* a group quota */
101#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */ 101#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */
102#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */ 102#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */
@@ -104,6 +104,8 @@ typedef struct xfs_dqblk {
104#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */ 104#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */
105#define XFS_DQ_MARKER 0x0080 /* sentinel */ 105#define XFS_DQ_MARKER 0x0080 /* sentinel */
106 106
107#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
108
107/* 109/*
108 * In the worst case, when both user and group quotas are on, 110 * In the worst case, when both user and group quotas are on,
109 * we can have a max of three dquots changing in a single transaction. 111 * we can have a max of three dquots changing in a single transaction.
@@ -124,7 +126,7 @@ typedef struct xfs_dqblk {
124typedef struct xfs_dq_logformat { 126typedef struct xfs_dq_logformat {
125 __uint16_t qlf_type; /* dquot log item type */ 127 __uint16_t qlf_type; /* dquot log item type */
126 __uint16_t qlf_size; /* size of this item */ 128 __uint16_t qlf_size; /* size of this item */
127 xfs_dqid_t qlf_id; /* usr/grp id number : 32 bits */ 129 xfs_dqid_t qlf_id; /* usr/grp/proj id : 32 bits */
128 __int64_t qlf_blkno; /* blkno of dquot buffer */ 130 __int64_t qlf_blkno; /* blkno of dquot buffer */
129 __int32_t qlf_len; /* len of dquot buffer */ 131 __int32_t qlf_len; /* len of dquot buffer */
130 __uint32_t qlf_boffset; /* off of dquot in buffer */ 132 __uint32_t qlf_boffset; /* off of dquot in buffer */
@@ -152,9 +154,9 @@ typedef struct xfs_qoff_logformat {
152#define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */ 154#define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */
153#define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */ 155#define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */
154#define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */ 156#define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */
155#define XFS_PQUOTA_ACCT 0x0008 /* (IRIX) project quota accounting ON */ 157#define XFS_PQUOTA_ACCT 0x0008 /* project quota accounting ON */
156#define XFS_GQUOTA_ENFD 0x0010 /* group quota limits enforced */ 158#define XFS_OQUOTA_ENFD 0x0010 /* other (grp/prj) quota limits enforced */
157#define XFS_GQUOTA_CHKD 0x0020 /* quotacheck run on grp quotas */ 159#define XFS_OQUOTA_CHKD 0x0020 /* quotacheck run on other (grp/prj) quotas */
158#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */ 160#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
159 161
160/* 162/*
@@ -162,17 +164,22 @@ typedef struct xfs_qoff_logformat {
162 * are in the process of getting turned off. These flags are in m_qflags but 164 * are in the process of getting turned off. These flags are in m_qflags but
163 * never in sb_qflags. 165 * never in sb_qflags.
164 */ 166 */
165#define XFS_UQUOTA_ACTIVE 0x0080 /* uquotas are being turned off */ 167#define XFS_UQUOTA_ACTIVE 0x0100 /* uquotas are being turned off */
166#define XFS_GQUOTA_ACTIVE 0x0100 /* gquotas are being turned off */ 168#define XFS_PQUOTA_ACTIVE 0x0200 /* pquotas are being turned off */
169#define XFS_GQUOTA_ACTIVE 0x0400 /* gquotas are being turned off */
167 170
168/* 171/*
169 * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees 172 * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
170 * quota will be not be switched off as long as that inode lock is held. 173 * quota will be not be switched off as long as that inode lock is held.
171 */ 174 */
172#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \ 175#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
173 XFS_GQUOTA_ACTIVE)) 176 XFS_GQUOTA_ACTIVE | \
177 XFS_PQUOTA_ACTIVE))
178#define XFS_IS_OQUOTA_ON(mp) ((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
179 XFS_PQUOTA_ACTIVE))
174#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE) 180#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
175#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE) 181#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
182#define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
176 183
177/* 184/*
178 * Flags to tell various functions what to do. Not all of these are meaningful 185 * Flags to tell various functions what to do. Not all of these are meaningful
@@ -182,7 +189,7 @@ typedef struct xfs_qoff_logformat {
182#define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */ 189#define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */
183#define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ 190#define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */
184#define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ 191#define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */
185#define XFS_QMOPT_GQUOTA 0x0000008 /* group dquot requested */ 192#define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */
186#define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */ 193#define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */
187#define XFS_QMOPT_DQSUSER 0x0000020 /* don't cache super users dquot */ 194#define XFS_QMOPT_DQSUSER 0x0000020 /* don't cache super users dquot */
188#define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */ 195#define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */
@@ -192,6 +199,7 @@ typedef struct xfs_qoff_logformat {
192#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */ 199#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */
193#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */ 200#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */
194#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */ 201#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */
202#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */
195 203
196/* 204/*
197 * flags to xfs_trans_mod_dquot to indicate which field needs to be 205 * flags to xfs_trans_mod_dquot to indicate which field needs to be
@@ -231,7 +239,8 @@ typedef struct xfs_qoff_logformat {
231#define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT 239#define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT
232 240
233 241
234#define XFS_QMOPT_QUOTALL (XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA) 242#define XFS_QMOPT_QUOTALL \
243 (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
235#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) 244#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
236 245
237#ifdef __KERNEL__ 246#ifdef __KERNEL__
@@ -246,21 +255,33 @@ typedef struct xfs_qoff_logformat {
246 */ 255 */
247#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ 256#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
248 (ip)->i_udquot == NULL) || \ 257 (ip)->i_udquot == NULL) || \
249 (XFS_IS_GQUOTA_ON(mp) && \ 258 (XFS_IS_OQUOTA_ON(mp) && \
250 (ip)->i_gdquot == NULL)) 259 (ip)->i_gdquot == NULL))
251 260
252#define XFS_QM_NEED_QUOTACHECK(mp) ((XFS_IS_UQUOTA_ON(mp) && \ 261#define XFS_QM_NEED_QUOTACHECK(mp) \
253 (mp->m_sb.sb_qflags & \ 262 ((XFS_IS_UQUOTA_ON(mp) && \
254 XFS_UQUOTA_CHKD) == 0) || \ 263 (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
255 (XFS_IS_GQUOTA_ON(mp) && \ 264 (XFS_IS_GQUOTA_ON(mp) && \
256 (mp->m_sb.sb_qflags & \ 265 ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
257 XFS_GQUOTA_CHKD) == 0)) 266 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
267 (XFS_IS_PQUOTA_ON(mp) && \
268 ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
269 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
270
271#define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
272 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
273 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
274
275#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
276 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
277 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
258 278
259#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ 279#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
260 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ 280 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
261 XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD) 281 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
282 XFS_GQUOTA_ACCT)
262#define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \ 283#define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
263 XFS_GQUOTA_ACTIVE) 284 XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
264 285
265 286
266/* 287/*
@@ -331,15 +352,8 @@ typedef struct xfs_dqtrxops {
331#define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \ 352#define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
332 XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots) 353 XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
333 354
334#define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \ 355#define XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, flags) \
335 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \ 356 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), -(ninos), flags)
336 XFS_QMOPT_RES_REGBLKS)
337#define XFS_TRANS_RESERVE_BLKQUOTA_FORCE(mp, tp, ip, nblks) \
338 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
339 XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES)
340#define XFS_TRANS_UNRESERVE_BLKQUOTA(mp, tp, ip, nblks) \
341 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), 0, \
342 XFS_QMOPT_RES_REGBLKS)
343#define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \ 357#define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \
344 XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \ 358 XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \
345 f | XFS_QMOPT_RES_REGBLKS) 359 f | XFS_QMOPT_RES_REGBLKS)
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index cb13f9a1d45b..23b48ac1cb7e 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -234,9 +234,6 @@ xfs_lock_for_rename(
234 return 0; 234 return 0;
235} 235}
236 236
237
238int rename_which_error_return = 0;
239
240/* 237/*
241 * xfs_rename 238 * xfs_rename
242 */ 239 */
@@ -316,7 +313,6 @@ xfs_rename(
316 &num_inodes); 313 &num_inodes);
317 314
318 if (error) { 315 if (error) {
319 rename_which_error_return = __LINE__;
320 /* 316 /*
321 * We have nothing locked, no inode references, and 317 * We have nothing locked, no inode references, and
322 * no transaction, so just get out. 318 * no transaction, so just get out.
@@ -332,7 +328,6 @@ xfs_rename(
332 */ 328 */
333 if (target_ip == NULL && (src_dp != target_dp) && 329 if (target_ip == NULL && (src_dp != target_dp) &&
334 target_dp->i_d.di_nlink >= XFS_MAXLINK) { 330 target_dp->i_d.di_nlink >= XFS_MAXLINK) {
335 rename_which_error_return = __LINE__;
336 error = XFS_ERROR(EMLINK); 331 error = XFS_ERROR(EMLINK);
337 xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED); 332 xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
338 goto rele_return; 333 goto rele_return;
@@ -359,7 +354,6 @@ xfs_rename(
359 XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT); 354 XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
360 } 355 }
361 if (error) { 356 if (error) {
362 rename_which_error_return = __LINE__;
363 xfs_trans_cancel(tp, 0); 357 xfs_trans_cancel(tp, 0);
364 goto rele_return; 358 goto rele_return;
365 } 359 }
@@ -369,7 +363,6 @@ xfs_rename(
369 */ 363 */
370 if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) { 364 if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) {
371 xfs_trans_cancel(tp, cancel_flags); 365 xfs_trans_cancel(tp, cancel_flags);
372 rename_which_error_return = __LINE__;
373 goto rele_return; 366 goto rele_return;
374 } 367 }
375 368
@@ -413,7 +406,6 @@ xfs_rename(
413 if (spaceres == 0 && 406 if (spaceres == 0 &&
414 (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name, 407 (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name,
415 target_namelen))) { 408 target_namelen))) {
416 rename_which_error_return = __LINE__;
417 goto error_return; 409 goto error_return;
418 } 410 }
419 /* 411 /*
@@ -425,11 +417,9 @@ xfs_rename(
425 target_namelen, src_ip->i_ino, 417 target_namelen, src_ip->i_ino,
426 &first_block, &free_list, spaceres); 418 &first_block, &free_list, spaceres);
427 if (error == ENOSPC) { 419 if (error == ENOSPC) {
428 rename_which_error_return = __LINE__;
429 goto error_return; 420 goto error_return;
430 } 421 }
431 if (error) { 422 if (error) {
432 rename_which_error_return = __LINE__;
433 goto abort_return; 423 goto abort_return;
434 } 424 }
435 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 425 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -437,7 +427,6 @@ xfs_rename(
437 if (new_parent && src_is_directory) { 427 if (new_parent && src_is_directory) {
438 error = xfs_bumplink(tp, target_dp); 428 error = xfs_bumplink(tp, target_dp);
439 if (error) { 429 if (error) {
440 rename_which_error_return = __LINE__;
441 goto abort_return; 430 goto abort_return;
442 } 431 }
443 } 432 }
@@ -455,7 +444,6 @@ xfs_rename(
455 if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) || 444 if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) ||
456 (target_ip->i_d.di_nlink > 2)) { 445 (target_ip->i_d.di_nlink > 2)) {
457 error = XFS_ERROR(EEXIST); 446 error = XFS_ERROR(EEXIST);
458 rename_which_error_return = __LINE__;
459 goto error_return; 447 goto error_return;
460 } 448 }
461 } 449 }
@@ -473,7 +461,6 @@ xfs_rename(
473 target_namelen, src_ip->i_ino, &first_block, 461 target_namelen, src_ip->i_ino, &first_block,
474 &free_list, spaceres); 462 &free_list, spaceres);
475 if (error) { 463 if (error) {
476 rename_which_error_return = __LINE__;
477 goto abort_return; 464 goto abort_return;
478 } 465 }
479 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 466 xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -484,7 +471,6 @@ xfs_rename(
484 */ 471 */
485 error = xfs_droplink(tp, target_ip); 472 error = xfs_droplink(tp, target_ip);
486 if (error) { 473 if (error) {
487 rename_which_error_return = __LINE__;
488 goto abort_return; 474 goto abort_return;
489 } 475 }
490 target_ip_dropped = 1; 476 target_ip_dropped = 1;
@@ -495,7 +481,6 @@ xfs_rename(
495 */ 481 */
496 error = xfs_droplink(tp, target_ip); 482 error = xfs_droplink(tp, target_ip);
497 if (error) { 483 if (error) {
498 rename_which_error_return = __LINE__;
499 goto abort_return; 484 goto abort_return;
500 } 485 }
501 } 486 }
@@ -519,7 +504,6 @@ xfs_rename(
519 &free_list, spaceres); 504 &free_list, spaceres);
520 ASSERT(error != EEXIST); 505 ASSERT(error != EEXIST);
521 if (error) { 506 if (error) {
522 rename_which_error_return = __LINE__;
523 goto abort_return; 507 goto abort_return;
524 } 508 }
525 xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 509 xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -550,7 +534,6 @@ xfs_rename(
550 */ 534 */
551 error = xfs_droplink(tp, src_dp); 535 error = xfs_droplink(tp, src_dp);
552 if (error) { 536 if (error) {
553 rename_which_error_return = __LINE__;
554 goto abort_return; 537 goto abort_return;
555 } 538 }
556 } 539 }
@@ -558,7 +541,6 @@ xfs_rename(
558 error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen, 541 error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen,
559 src_ip->i_ino, &first_block, &free_list, spaceres); 542 src_ip->i_ino, &first_block, &free_list, spaceres);
560 if (error) { 543 if (error) {
561 rename_which_error_return = __LINE__;
562 goto abort_return; 544 goto abort_return;
563 } 545 }
564 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 546 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 3db0e2200775..06dfca531f79 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -332,25 +332,6 @@ undo_blocks:
332 332
333 333
334/* 334/*
335 * This is called to set the a callback to be called when the given
336 * transaction is committed to disk. The transaction pointer and the
337 * argument pointer will be passed to the callback routine.
338 *
339 * Only one callback can be associated with any single transaction.
340 */
341void
342xfs_trans_callback(
343 xfs_trans_t *tp,
344 xfs_trans_callback_t callback,
345 void *arg)
346{
347 ASSERT(tp->t_callback == NULL);
348 tp->t_callback = callback;
349 tp->t_callarg = arg;
350}
351
352
353/*
354 * Record the indicated change to the given field for application 335 * Record the indicated change to the given field for application
355 * to the file system's superblock when the transaction commits. 336 * to the file system's superblock when the transaction commits.
356 * For now, just store the change in the transaction structure. 337 * For now, just store the change in the transaction structure.
@@ -551,7 +532,7 @@ xfs_trans_apply_sb_deltas(
551 * 532 *
552 * This is done efficiently with a single call to xfs_mod_incore_sb_batch(). 533 * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
553 */ 534 */
554void 535STATIC void
555xfs_trans_unreserve_and_mod_sb( 536xfs_trans_unreserve_and_mod_sb(
556 xfs_trans_t *tp) 537 xfs_trans_t *tp)
557{ 538{
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index bd37ccb85e76..ec541d66fa2a 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -987,8 +987,6 @@ xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint);
987xfs_trans_t *xfs_trans_dup(xfs_trans_t *); 987xfs_trans_t *xfs_trans_dup(xfs_trans_t *);
988int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, 988int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
989 uint, uint); 989 uint, uint);
990void xfs_trans_callback(xfs_trans_t *,
991 void (*)(xfs_trans_t *, void *), void *);
992void xfs_trans_mod_sb(xfs_trans_t *, uint, long); 990void xfs_trans_mod_sb(xfs_trans_t *, uint, long);
993struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t, 991struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
994 int, uint); 992 int, uint);
@@ -1010,7 +1008,6 @@ int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
1010 xfs_ino_t , uint, uint, struct xfs_inode **); 1008 xfs_ino_t , uint, uint, struct xfs_inode **);
1011void xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint); 1009void xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint);
1012void xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *); 1010void xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *);
1013void xfs_trans_ihold_release(xfs_trans_t *, struct xfs_inode *);
1014void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); 1011void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
1015void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); 1012void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
1016struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); 1013struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index a9682b9510c1..144da7a85466 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -976,6 +976,7 @@ xfs_trans_dquot_buf(
976 ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 976 ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
977 ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 977 ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
978 ASSERT(type == XFS_BLI_UDQUOT_BUF || 978 ASSERT(type == XFS_BLI_UDQUOT_BUF ||
979 type == XFS_BLI_PDQUOT_BUF ||
979 type == XFS_BLI_GDQUOT_BUF); 980 type == XFS_BLI_GDQUOT_BUF);
980 981
981 bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 982 bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index e2c3706f453d..7e7631ca4979 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -253,24 +253,6 @@ xfs_trans_ihold(
253 ip->i_itemp->ili_flags |= XFS_ILI_HOLD; 253 ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
254} 254}
255 255
256/*
257 * Cancel the previous inode hold request made on this inode
258 * for this transaction.
259 */
260/*ARGSUSED*/
261void
262xfs_trans_ihold_release(
263 xfs_trans_t *tp,
264 xfs_inode_t *ip)
265{
266 ASSERT(ip->i_transp == tp);
267 ASSERT(ip->i_itemp != NULL);
268 ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
269 ASSERT(ip->i_itemp->ili_flags & XFS_ILI_HOLD);
270
271 ip->i_itemp->ili_flags &= ~XFS_ILI_HOLD;
272}
273
274 256
275/* 257/*
276 * This is called to mark the fields indicated in fieldmask as needing 258 * This is called to mark the fields indicated in fieldmask as needing
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index e4bf711e48ff..16f5371ce102 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -55,7 +55,7 @@ typedef signed long long int __int64_t;
55typedef unsigned long long int __uint64_t; 55typedef unsigned long long int __uint64_t;
56 56
57typedef enum { B_FALSE,B_TRUE } boolean_t; 57typedef enum { B_FALSE,B_TRUE } boolean_t;
58typedef __int64_t prid_t; /* project ID */ 58typedef __uint32_t prid_t; /* project ID */
59typedef __uint32_t inst_t; /* an instruction */ 59typedef __uint32_t inst_t; /* an instruction */
60 60
61typedef __s64 xfs_off_t; /* <file offset> type */ 61typedef __s64 xfs_off_t; /* <file offset> type */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index d1f8146a06ea..11351f08d438 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -428,7 +428,7 @@ xfs_truncate_file(
428 if (ip->i_ino != mp->m_sb.sb_uquotino) 428 if (ip->i_ino != mp->m_sb.sb_uquotino)
429 ASSERT(ip->i_udquot); 429 ASSERT(ip->i_udquot);
430 } 430 }
431 if (XFS_IS_GQUOTA_ON(mp)) { 431 if (XFS_IS_OQUOTA_ON(mp)) {
432 if (ip->i_ino != mp->m_sb.sb_gquotino) 432 if (ip->i_ino != mp->m_sb.sb_gquotino)
433 ASSERT(ip->i_gdquot); 433 ASSERT(ip->i_gdquot);
434 } 434 }
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index b53736650100..42bcc0215203 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -368,16 +368,6 @@ xfs_finish_flags(
368 } 368 }
369 369
370 /* 370 /*
371 * disallow mount attempts with (IRIX) project quota enabled
372 */
373 if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
374 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT)) {
375 cmn_err(CE_WARN,
376 "XFS: cannot mount a filesystem with IRIX project quota enabled");
377 return XFS_ERROR(ENOSYS);
378 }
379
380 /*
381 * check for shared mount. 371 * check for shared mount.
382 */ 372 */
383 if (ap->flags & XFSMNT_SHARED) { 373 if (ap->flags & XFSMNT_SHARED) {
@@ -622,7 +612,34 @@ out:
622 return XFS_ERROR(error); 612 return XFS_ERROR(error);
623} 613}
624 614
625#define REMOUNT_READONLY_FLAGS (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT) 615STATIC int
616xfs_quiesce_fs(
617 xfs_mount_t *mp)
618{
619 int count = 0, pincount;
620
621 xfs_refcache_purge_mp(mp);
622 xfs_flush_buftarg(mp->m_ddev_targp, 0);
623 xfs_finish_reclaim_all(mp, 0);
624
625 /* This loop must run at least twice.
626 * The first instance of the loop will flush
627 * most meta data but that will generate more
628 * meta data (typically directory updates).
629 * Which then must be flushed and logged before
630 * we can write the unmount record.
631 */
632 do {
633 xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
634 pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
635 if (!pincount) {
636 delay(50);
637 count++;
638 }
639 } while (count < 2);
640
641 return 0;
642}
626 643
627STATIC int 644STATIC int
628xfs_mntupdate( 645xfs_mntupdate(
@@ -632,8 +649,7 @@ xfs_mntupdate(
632{ 649{
633 struct vfs *vfsp = bhvtovfs(bdp); 650 struct vfs *vfsp = bhvtovfs(bdp);
634 xfs_mount_t *mp = XFS_BHVTOM(bdp); 651 xfs_mount_t *mp = XFS_BHVTOM(bdp);
635 int pincount, error; 652 int error;
636 int count = 0;
637 653
638 if (args->flags & XFSMNT_NOATIME) 654 if (args->flags & XFSMNT_NOATIME)
639 mp->m_flags |= XFS_MOUNT_NOATIME; 655 mp->m_flags |= XFS_MOUNT_NOATIME;
@@ -645,25 +661,7 @@ xfs_mntupdate(
645 } 661 }
646 662
647 if (*flags & MS_RDONLY) { 663 if (*flags & MS_RDONLY) {
648 xfs_refcache_purge_mp(mp); 664 xfs_quiesce_fs(mp);
649 xfs_flush_buftarg(mp->m_ddev_targp, 0);
650 xfs_finish_reclaim_all(mp, 0);
651
652 /* This loop must run at least twice.
653 * The first instance of the loop will flush
654 * most meta data but that will generate more
655 * meta data (typically directory updates).
656 * Which then must be flushed and logged before
657 * we can write the unmount record.
658 */
659 do {
660 VFS_SYNC(vfsp, REMOUNT_READONLY_FLAGS, NULL, error);
661 pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
662 if (!pincount) {
663 delay(50);
664 count++;
665 }
666 } while (count < 2);
667 665
668 /* Ok now write out an unmount record */ 666 /* Ok now write out an unmount record */
669 xfs_log_unmount_write(mp); 667 xfs_log_unmount_write(mp);
@@ -879,10 +877,12 @@ xfs_sync(
879 int flags, 877 int flags,
880 cred_t *credp) 878 cred_t *credp)
881{ 879{
882 xfs_mount_t *mp; 880 xfs_mount_t *mp = XFS_BHVTOM(bdp);
883 881
884 mp = XFS_BHVTOM(bdp); 882 if (unlikely(flags == SYNC_QUIESCE))
885 return (xfs_syncsub(mp, flags, 0, NULL)); 883 return xfs_quiesce_fs(mp);
884 else
885 return xfs_syncsub(mp, flags, 0, NULL);
886} 886}
887 887
888/* 888/*
@@ -1681,7 +1681,7 @@ suffix_strtoul(const char *cp, char **endp, unsigned int base)
1681 return simple_strtoul(cp, endp, base) << shift_left_factor; 1681 return simple_strtoul(cp, endp, base) << shift_left_factor;
1682} 1682}
1683 1683
1684int 1684STATIC int
1685xfs_parseargs( 1685xfs_parseargs(
1686 struct bhv_desc *bhv, 1686 struct bhv_desc *bhv,
1687 char *options, 1687 char *options,
@@ -1867,7 +1867,7 @@ printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
1867 return 0; 1867 return 0;
1868} 1868}
1869 1869
1870int 1870STATIC int
1871xfs_showargs( 1871xfs_showargs(
1872 struct bhv_desc *bhv, 1872 struct bhv_desc *bhv,
1873 struct seq_file *m) 1873 struct seq_file *m)
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 25a526629b12..1377c868f3f4 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * under the terms of version 2 of the GNU General Public License as
@@ -351,21 +351,28 @@ xfs_setattr(
351 * If the IDs do change before we take the ilock, we're covered 351 * If the IDs do change before we take the ilock, we're covered
352 * because the i_*dquot fields will get updated anyway. 352 * because the i_*dquot fields will get updated anyway.
353 */ 353 */
354 if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) { 354 if (XFS_IS_QUOTA_ON(mp) &&
355 (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
355 uint qflags = 0; 356 uint qflags = 0;
356 357
357 if (mask & XFS_AT_UID) { 358 if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
358 uid = vap->va_uid; 359 uid = vap->va_uid;
359 qflags |= XFS_QMOPT_UQUOTA; 360 qflags |= XFS_QMOPT_UQUOTA;
360 } else { 361 } else {
361 uid = ip->i_d.di_uid; 362 uid = ip->i_d.di_uid;
362 } 363 }
363 if (mask & XFS_AT_GID) { 364 if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
364 gid = vap->va_gid; 365 gid = vap->va_gid;
365 qflags |= XFS_QMOPT_GQUOTA; 366 qflags |= XFS_QMOPT_GQUOTA;
366 } else { 367 } else {
367 gid = ip->i_d.di_gid; 368 gid = ip->i_d.di_gid;
368 } 369 }
370 if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
371 projid = vap->va_projid;
372 qflags |= XFS_QMOPT_PQUOTA;
373 } else {
374 projid = ip->i_d.di_projid;
375 }
369 /* 376 /*
370 * We take a reference when we initialize udqp and gdqp, 377 * We take a reference when we initialize udqp and gdqp,
371 * so it is important that we never blindly double trip on 378 * so it is important that we never blindly double trip on
@@ -373,7 +380,8 @@ xfs_setattr(
373 */ 380 */
374 ASSERT(udqp == NULL); 381 ASSERT(udqp == NULL);
375 ASSERT(gdqp == NULL); 382 ASSERT(gdqp == NULL);
376 code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp); 383 code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
384 &udqp, &gdqp);
377 if (code) 385 if (code)
378 return (code); 386 return (code);
379 } 387 }
@@ -499,8 +507,6 @@ xfs_setattr(
499 * that the group ID supplied to the chown() function 507 * that the group ID supplied to the chown() function
500 * shall be equal to either the group ID or one of the 508 * shall be equal to either the group ID or one of the
501 * supplementary group IDs of the calling process. 509 * supplementary group IDs of the calling process.
502 *
503 * XXX: How does restricted_chown affect projid?
504 */ 510 */
505 if (restricted_chown && 511 if (restricted_chown &&
506 (iuid != uid || (igid != gid && 512 (iuid != uid || (igid != gid &&
@@ -510,10 +516,11 @@ xfs_setattr(
510 goto error_return; 516 goto error_return;
511 } 517 }
512 /* 518 /*
513 * Do a quota reservation only if uid or gid is actually 519 * Do a quota reservation only if uid/projid/gid is actually
514 * going to change. 520 * going to change.
515 */ 521 */
516 if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || 522 if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
523 (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
517 (XFS_IS_GQUOTA_ON(mp) && igid != gid)) { 524 (XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
518 ASSERT(tp); 525 ASSERT(tp);
519 code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp, 526 code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
@@ -774,6 +781,7 @@ xfs_setattr(
774 } 781 }
775 if (igid != gid) { 782 if (igid != gid) {
776 if (XFS_IS_GQUOTA_ON(mp)) { 783 if (XFS_IS_GQUOTA_ON(mp)) {
784 ASSERT(!XFS_IS_PQUOTA_ON(mp));
777 ASSERT(mask & XFS_AT_GID); 785 ASSERT(mask & XFS_AT_GID);
778 ASSERT(gdqp); 786 ASSERT(gdqp);
779 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, 787 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
@@ -782,6 +790,13 @@ xfs_setattr(
782 ip->i_d.di_gid = gid; 790 ip->i_d.di_gid = gid;
783 } 791 }
784 if (iprojid != projid) { 792 if (iprojid != projid) {
793 if (XFS_IS_PQUOTA_ON(mp)) {
794 ASSERT(!XFS_IS_GQUOTA_ON(mp));
795 ASSERT(mask & XFS_AT_PROJID);
796 ASSERT(gdqp);
797 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
798 &ip->i_gdquot, gdqp);
799 }
785 ip->i_d.di_projid = projid; 800 ip->i_d.di_projid = projid;
786 /* 801 /*
787 * We may have to rev the inode as well as 802 * We may have to rev the inode as well as
@@ -843,6 +858,8 @@ xfs_setattr(
843 di_flags |= XFS_DIFLAG_NOATIME; 858 di_flags |= XFS_DIFLAG_NOATIME;
844 if (vap->va_xflags & XFS_XFLAG_NODUMP) 859 if (vap->va_xflags & XFS_XFLAG_NODUMP)
845 di_flags |= XFS_DIFLAG_NODUMP; 860 di_flags |= XFS_DIFLAG_NODUMP;
861 if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
862 di_flags |= XFS_DIFLAG_PROJINHERIT;
846 if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { 863 if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
847 if (vap->va_xflags & XFS_XFLAG_RTINHERIT) 864 if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
848 di_flags |= XFS_DIFLAG_RTINHERIT; 865 di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -1898,7 +1915,9 @@ xfs_create(
1898 /* Return through std_return after this point. */ 1915 /* Return through std_return after this point. */
1899 1916
1900 udqp = gdqp = NULL; 1917 udqp = gdqp = NULL;
1901 if (vap->va_mask & XFS_AT_PROJID) 1918 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
1919 prid = dp->i_d.di_projid;
1920 else if (vap->va_mask & XFS_AT_PROJID)
1902 prid = (xfs_prid_t)vap->va_projid; 1921 prid = (xfs_prid_t)vap->va_projid;
1903 else 1922 else
1904 prid = (xfs_prid_t)dfltprid; 1923 prid = (xfs_prid_t)dfltprid;
@@ -1907,7 +1926,7 @@ xfs_create(
1907 * Make sure that we have allocated dquot(s) on disk. 1926 * Make sure that we have allocated dquot(s) on disk.
1908 */ 1927 */
1909 error = XFS_QM_DQVOPALLOC(mp, dp, 1928 error = XFS_QM_DQVOPALLOC(mp, dp,
1910 current_fsuid(credp), current_fsgid(credp), 1929 current_fsuid(credp), current_fsgid(credp), prid,
1911 XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); 1930 XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
1912 if (error) 1931 if (error)
1913 goto std_return; 1932 goto std_return;
@@ -2604,17 +2623,7 @@ xfs_link(
2604 if (src_vp->v_type == VDIR) 2623 if (src_vp->v_type == VDIR)
2605 return XFS_ERROR(EPERM); 2624 return XFS_ERROR(EPERM);
2606 2625
2607 /*
2608 * For now, manually find the XFS behavior descriptor for
2609 * the source vnode. If it doesn't exist then something
2610 * is wrong and we should just return an error.
2611 * Eventually we need to figure out how link is going to
2612 * work in the face of stacked vnodes.
2613 */
2614 src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops); 2626 src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops);
2615 if (src_bdp == NULL) {
2616 return XFS_ERROR(EXDEV);
2617 }
2618 sip = XFS_BHVTOI(src_bdp); 2627 sip = XFS_BHVTOI(src_bdp);
2619 tdp = XFS_BHVTOI(target_dir_bdp); 2628 tdp = XFS_BHVTOI(target_dir_bdp);
2620 mp = tdp->i_mount; 2629 mp = tdp->i_mount;
@@ -2681,6 +2690,17 @@ xfs_link(
2681 goto error_return; 2690 goto error_return;
2682 } 2691 }
2683 2692
2693 /*
2694 * If we are using project inheritance, we only allow hard link
2695 * creation in our tree when the project IDs are the same; else
2696 * the tree quota mechanism could be circumvented.
2697 */
2698 if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
2699 (tdp->i_d.di_projid != sip->i_d.di_projid))) {
2700 error = XFS_ERROR(EPERM);
2701 goto error_return;
2702 }
2703
2684 if (resblks == 0 && 2704 if (resblks == 0 &&
2685 (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name, 2705 (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name,
2686 target_namelen))) 2706 target_namelen)))
@@ -2803,7 +2823,9 @@ xfs_mkdir(
2803 2823
2804 mp = dp->i_mount; 2824 mp = dp->i_mount;
2805 udqp = gdqp = NULL; 2825 udqp = gdqp = NULL;
2806 if (vap->va_mask & XFS_AT_PROJID) 2826 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
2827 prid = dp->i_d.di_projid;
2828 else if (vap->va_mask & XFS_AT_PROJID)
2807 prid = (xfs_prid_t)vap->va_projid; 2829 prid = (xfs_prid_t)vap->va_projid;
2808 else 2830 else
2809 prid = (xfs_prid_t)dfltprid; 2831 prid = (xfs_prid_t)dfltprid;
@@ -2812,7 +2834,7 @@ xfs_mkdir(
2812 * Make sure that we have allocated dquot(s) on disk. 2834 * Make sure that we have allocated dquot(s) on disk.
2813 */ 2835 */
2814 error = XFS_QM_DQVOPALLOC(mp, dp, 2836 error = XFS_QM_DQVOPALLOC(mp, dp,
2815 current_fsuid(credp), current_fsgid(credp), 2837 current_fsuid(credp), current_fsgid(credp), prid,
2816 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 2838 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
2817 if (error) 2839 if (error)
2818 goto std_return; 2840 goto std_return;
@@ -3357,7 +3379,9 @@ xfs_symlink(
3357 /* Return through std_return after this point. */ 3379 /* Return through std_return after this point. */
3358 3380
3359 udqp = gdqp = NULL; 3381 udqp = gdqp = NULL;
3360 if (vap->va_mask & XFS_AT_PROJID) 3382 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
3383 prid = dp->i_d.di_projid;
3384 else if (vap->va_mask & XFS_AT_PROJID)
3361 prid = (xfs_prid_t)vap->va_projid; 3385 prid = (xfs_prid_t)vap->va_projid;
3362 else 3386 else
3363 prid = (xfs_prid_t)dfltprid; 3387 prid = (xfs_prid_t)dfltprid;
@@ -3366,7 +3390,7 @@ xfs_symlink(
3366 * Make sure that we have allocated dquot(s) on disk. 3390 * Make sure that we have allocated dquot(s) on disk.
3367 */ 3391 */
3368 error = XFS_QM_DQVOPALLOC(mp, dp, 3392 error = XFS_QM_DQVOPALLOC(mp, dp,
3369 current_fsuid(credp), current_fsgid(credp), 3393 current_fsuid(credp), current_fsgid(credp), prid,
3370 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 3394 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
3371 if (error) 3395 if (error)
3372 goto std_return; 3396 goto std_return;
@@ -4028,7 +4052,7 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
4028 * errno on error 4052 * errno on error
4029 * 4053 *
4030 */ 4054 */
4031int 4055STATIC int
4032xfs_alloc_file_space( 4056xfs_alloc_file_space(
4033 xfs_inode_t *ip, 4057 xfs_inode_t *ip,
4034 xfs_off_t offset, 4058 xfs_off_t offset,
@@ -4151,9 +4175,8 @@ retry:
4151 break; 4175 break;
4152 } 4176 }
4153 xfs_ilock(ip, XFS_ILOCK_EXCL); 4177 xfs_ilock(ip, XFS_ILOCK_EXCL);
4154 error = XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, 4178 error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
4155 ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? 4179 ip->i_udquot, ip->i_gdquot, resblks, 0, 0);
4156 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
4157 if (error) 4180 if (error)
4158 goto error1; 4181 goto error1;
4159 4182
@@ -4305,6 +4328,7 @@ xfs_free_file_space(
4305 xfs_off_t len, 4328 xfs_off_t len,
4306 int attr_flags) 4329 int attr_flags)
4307{ 4330{
4331 vnode_t *vp;
4308 int committed; 4332 int committed;
4309 int done; 4333 int done;
4310 xfs_off_t end_dmi_offset; 4334 xfs_off_t end_dmi_offset;
@@ -4325,9 +4349,11 @@ xfs_free_file_space(
4325 xfs_trans_t *tp; 4349 xfs_trans_t *tp;
4326 int need_iolock = 1; 4350 int need_iolock = 1;
4327 4351
4328 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); 4352 vp = XFS_ITOV(ip);
4329 mp = ip->i_mount; 4353 mp = ip->i_mount;
4330 4354
4355 vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
4356
4331 if ((error = XFS_QM_DQATTACH(mp, ip, 0))) 4357 if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
4332 return error; 4358 return error;
4333 4359
@@ -4344,7 +4370,7 @@ xfs_free_file_space(
4344 DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) { 4370 DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
4345 if (end_dmi_offset > ip->i_d.di_size) 4371 if (end_dmi_offset > ip->i_d.di_size)
4346 end_dmi_offset = ip->i_d.di_size; 4372 end_dmi_offset = ip->i_d.di_size;
4347 error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip), 4373 error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
4348 offset, end_dmi_offset - offset, 4374 offset, end_dmi_offset - offset,
4349 AT_DELAY_FLAG(attr_flags), NULL); 4375 AT_DELAY_FLAG(attr_flags), NULL);
4350 if (error) 4376 if (error)
@@ -4363,7 +4389,14 @@ xfs_free_file_space(
4363 ioffset = offset & ~(rounding - 1); 4389 ioffset = offset & ~(rounding - 1);
4364 if (ilen & (rounding - 1)) 4390 if (ilen & (rounding - 1))
4365 ilen = (ilen + rounding) & ~(rounding - 1); 4391 ilen = (ilen + rounding) & ~(rounding - 1);
4366 xfs_inval_cached_pages(XFS_ITOV(ip), &(ip->i_iocore), ioffset, 0, 0); 4392
4393 if (VN_CACHED(vp) != 0) {
4394 xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
4395 ctooff(offtoct(ioffset)), -1);
4396 VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)),
4397 -1, FI_REMAPF_LOCKED);
4398 }
4399
4367 /* 4400 /*
4368 * Need to zero the stuff we're not freeing, on disk. 4401 * Need to zero the stuff we're not freeing, on disk.
4369 * If its a realtime file & can't use unwritten extents then we 4402 * If its a realtime file & can't use unwritten extents then we